[Lldb-commits] [clang] [lldb] [clang][AST] fix ast-print of extern with >=2 declarators, fixed (PR #93913)

2024-06-20 Thread Artem Yurchenko via lldb-commits

temyurchenko wrote:

> Do you need someone to land these changes on your behalf?

Yeah, I don't have the rights :(

https://github.com/llvm/llvm-project/pull/93913
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [clang] [lldb] [clang][AST] fix ast-print of extern with >=2 declarators, fixed (PR #93913)

2024-06-18 Thread Artem Yurchenko via lldb-commits


@@ -576,13 +576,18 @@ template  static bool 
isFirstInExternCContext(T *D) {
   return First->isInExternCContext();
 }
 
-static bool isSingleLineLanguageLinkage(const Decl ) {
-  if (const auto *SD = dyn_cast(D.getDeclContext()))
-if (!SD->hasBraces())
-  return true;
+static bool isUnbracedLanguageLinkage(const DeclContext *DC) {
+  if (!DC)
+return false;
+  if (const auto *SD = dyn_cast(DC))
+return !SD->hasBraces();
   return false;
 }

temyurchenko wrote:

Done!

https://github.com/llvm/llvm-project/pull/93913
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [clang] [lldb] [clang][AST] fix ast-print of extern with >=2 declarators, fixed (PR #93913)

2024-06-18 Thread Artem Yurchenko via lldb-commits

https://github.com/temyurchenko updated 
https://github.com/llvm/llvm-project/pull/93913

>From 410c7ba9fb7667dabdfbc48fdbda427401ca8df0 Mon Sep 17 00:00:00 2001
From: Artem Yurchenko <44875844+temyurche...@users.noreply.github.com>
Date: Thu, 30 May 2024 16:18:47 -0400
Subject: [PATCH 1/2] [clang][AST] fix ast-print of `extern ` with >=2
 declarators (#93131)

Problem: the printer used to ignore all but the first declarator for
unbraced language linkage declarators. Furthemore, that one would
be printed without the final semicolon.

Solution: for unbraced case we traverse all declarators via
`VisitDeclContext`. Furthermore, in appropriate visitors we query
for whether they are a part of the unbraced extern language linkage
spec, and if so, print appropriately.
---
 clang/lib/AST/DeclPrinter.cpp | 55 ++-
 clang/test/AST/ast-print-language-linkage.cpp | 31 +++
 2 files changed, 72 insertions(+), 14 deletions(-)
 create mode 100644 clang/test/AST/ast-print-language-linkage.cpp

diff --git a/clang/lib/AST/DeclPrinter.cpp b/clang/lib/AST/DeclPrinter.cpp
index 0cf4e64f83b8d..9250a7f6eceb2 100644
--- a/clang/lib/AST/DeclPrinter.cpp
+++ b/clang/lib/AST/DeclPrinter.cpp
@@ -633,7 +633,7 @@ static void printExplicitSpecifier(ExplicitSpecifier ES, 
llvm::raw_ostream ,
   Out << Proto;
 }
 
-static void MaybePrintTagKeywordIfSupressingScopes(PrintingPolicy ,
+static void maybePrintTagKeywordIfSupressingScopes(PrintingPolicy ,
QualType T,
llvm::raw_ostream ) {
   StringRef prefix = T->isClassType()   ? "class "
@@ -643,6 +643,22 @@ static void 
MaybePrintTagKeywordIfSupressingScopes(PrintingPolicy ,
   Out << prefix;
 }
 
+/// Return the language of the linkage spec of `D`, if applicable.
+///
+/// \Return - "C" if `D` has been declared with unbraced `extern "C"`
+/// - "C++" if `D` has been declared with unbraced `extern "C++"`
+/// - nullptr in any other case
+static const char *tryGetUnbracedLinkageLanguage(const Decl *D) {
+  const auto *SD = dyn_cast(D->getDeclContext());
+  if (!SD || SD->hasBraces())
+return nullptr;
+  if (SD->getLanguage() == LinkageSpecLanguageIDs::C)
+return "C";
+  assert(SD->getLanguage() == LinkageSpecLanguageIDs::CXX &&
+ "unknown language in linkage specification");
+  return "C++";
+}
+
 void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
   if (!D->getDescribedFunctionTemplate() &&
   !D->isFunctionTemplateSpecialization()) {
@@ -662,6 +678,11 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
   CXXConversionDecl *ConversionDecl = dyn_cast(D);
   CXXDeductionGuideDecl *GuideDecl = dyn_cast(D);
   if (!Policy.SuppressSpecifiers) {
+if (const char *Lang = tryGetUnbracedLinkageLanguage(D)) {
+  // the "extern" specifier is implicit
+  assert(D->getStorageClass() == SC_None);
+  Out << "extern \"" << Lang << "\" ";
+}
 switch (D->getStorageClass()) {
 case SC_None: break;
 case SC_Extern: Out << "extern "; break;
@@ -807,7 +828,7 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
   }
   if (!Policy.SuppressTagKeyword && Policy.SuppressScope &&
   !Policy.SuppressUnwrittenScope)
-MaybePrintTagKeywordIfSupressingScopes(Policy, AFT->getReturnType(),
+maybePrintTagKeywordIfSupressingScopes(Policy, AFT->getReturnType(),
Out);
   AFT->getReturnType().print(Out, Policy, Proto);
   Proto.clear();
@@ -932,6 +953,11 @@ void DeclPrinter::VisitVarDecl(VarDecl *D) {
 : D->getASTContext().getUnqualifiedObjCPointerType(D->getType());
 
   if (!Policy.SuppressSpecifiers) {
+if (const char *Lang = tryGetUnbracedLinkageLanguage(D)) {
+  // the "extern" specifier is implicit
+  assert(D->getStorageClass() == SC_None);
+  Out << "extern \"" << Lang << "\" ";
+}
 StorageClass SC = D->getStorageClass();
 if (SC != SC_None)
   Out << VarDecl::getStorageClassSpecifierString(SC) << " ";
@@ -961,7 +987,7 @@ void DeclPrinter::VisitVarDecl(VarDecl *D) {
 
   if (!Policy.SuppressTagKeyword && Policy.SuppressScope &&
   !Policy.SuppressUnwrittenScope)
-MaybePrintTagKeywordIfSupressingScopes(Policy, T, Out);
+maybePrintTagKeywordIfSupressingScopes(Policy, T, Out);
 
   printDeclType(T, (isa(D) && Policy.CleanUglifiedParameters &&
 D->getIdentifier())
@@ -1064,6 +1090,8 @@ void 
DeclPrinter::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) {
 
 void DeclPrinter::VisitEmptyDecl(EmptyDecl *D) {
   prettyPrintAttributes(D);
+  if (const char *Lang = tryGetUnbracedLinkageLanguage(D))
+Out << "extern \"" << Lang << "\";";
 }
 
 void DeclPrinter::VisitCXXRecordDecl(CXXRecordDecl *D) {
@@ -1136,22 +1164,21 @@ void DeclPrinter::VisitCXXRecordDecl(CXXRecordDecl *D) {
 }
 
 void DeclPrinter::VisitLinkageSpecDecl(LinkageSpecDecl *D) {
-  const 

[Lldb-commits] [clang] [lldb] [clang][AST] fix ast-print of extern with >=2 declarators, fixed (PR #93913)

2024-06-18 Thread Artem Yurchenko via lldb-commits

https://github.com/temyurchenko updated 
https://github.com/llvm/llvm-project/pull/93913

>From 410c7ba9fb7667dabdfbc48fdbda427401ca8df0 Mon Sep 17 00:00:00 2001
From: Artem Yurchenko <44875844+temyurche...@users.noreply.github.com>
Date: Thu, 30 May 2024 16:18:47 -0400
Subject: [PATCH 1/3] [clang][AST] fix ast-print of `extern ` with >=2
 declarators (#93131)

Problem: the printer used to ignore all but the first declarator for
unbraced language linkage declarators. Furthemore, that one would
be printed without the final semicolon.

Solution: for unbraced case we traverse all declarators via
`VisitDeclContext`. Furthermore, in appropriate visitors we query
for whether they are a part of the unbraced extern language linkage
spec, and if so, print appropriately.
---
 clang/lib/AST/DeclPrinter.cpp | 55 ++-
 clang/test/AST/ast-print-language-linkage.cpp | 31 +++
 2 files changed, 72 insertions(+), 14 deletions(-)
 create mode 100644 clang/test/AST/ast-print-language-linkage.cpp

diff --git a/clang/lib/AST/DeclPrinter.cpp b/clang/lib/AST/DeclPrinter.cpp
index 0cf4e64f83b8d..9250a7f6eceb2 100644
--- a/clang/lib/AST/DeclPrinter.cpp
+++ b/clang/lib/AST/DeclPrinter.cpp
@@ -633,7 +633,7 @@ static void printExplicitSpecifier(ExplicitSpecifier ES, 
llvm::raw_ostream ,
   Out << Proto;
 }
 
-static void MaybePrintTagKeywordIfSupressingScopes(PrintingPolicy ,
+static void maybePrintTagKeywordIfSupressingScopes(PrintingPolicy ,
QualType T,
llvm::raw_ostream ) {
   StringRef prefix = T->isClassType()   ? "class "
@@ -643,6 +643,22 @@ static void 
MaybePrintTagKeywordIfSupressingScopes(PrintingPolicy ,
   Out << prefix;
 }
 
+/// Return the language of the linkage spec of `D`, if applicable.
+///
+/// \Return - "C" if `D` has been declared with unbraced `extern "C"`
+/// - "C++" if `D` has been declared with unbraced `extern "C++"`
+/// - nullptr in any other case
+static const char *tryGetUnbracedLinkageLanguage(const Decl *D) {
+  const auto *SD = dyn_cast(D->getDeclContext());
+  if (!SD || SD->hasBraces())
+return nullptr;
+  if (SD->getLanguage() == LinkageSpecLanguageIDs::C)
+return "C";
+  assert(SD->getLanguage() == LinkageSpecLanguageIDs::CXX &&
+ "unknown language in linkage specification");
+  return "C++";
+}
+
 void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
   if (!D->getDescribedFunctionTemplate() &&
   !D->isFunctionTemplateSpecialization()) {
@@ -662,6 +678,11 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
   CXXConversionDecl *ConversionDecl = dyn_cast(D);
   CXXDeductionGuideDecl *GuideDecl = dyn_cast(D);
   if (!Policy.SuppressSpecifiers) {
+if (const char *Lang = tryGetUnbracedLinkageLanguage(D)) {
+  // the "extern" specifier is implicit
+  assert(D->getStorageClass() == SC_None);
+  Out << "extern \"" << Lang << "\" ";
+}
 switch (D->getStorageClass()) {
 case SC_None: break;
 case SC_Extern: Out << "extern "; break;
@@ -807,7 +828,7 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
   }
   if (!Policy.SuppressTagKeyword && Policy.SuppressScope &&
   !Policy.SuppressUnwrittenScope)
-MaybePrintTagKeywordIfSupressingScopes(Policy, AFT->getReturnType(),
+maybePrintTagKeywordIfSupressingScopes(Policy, AFT->getReturnType(),
Out);
   AFT->getReturnType().print(Out, Policy, Proto);
   Proto.clear();
@@ -932,6 +953,11 @@ void DeclPrinter::VisitVarDecl(VarDecl *D) {
 : D->getASTContext().getUnqualifiedObjCPointerType(D->getType());
 
   if (!Policy.SuppressSpecifiers) {
+if (const char *Lang = tryGetUnbracedLinkageLanguage(D)) {
+  // the "extern" specifier is implicit
+  assert(D->getStorageClass() == SC_None);
+  Out << "extern \"" << Lang << "\" ";
+}
 StorageClass SC = D->getStorageClass();
 if (SC != SC_None)
   Out << VarDecl::getStorageClassSpecifierString(SC) << " ";
@@ -961,7 +987,7 @@ void DeclPrinter::VisitVarDecl(VarDecl *D) {
 
   if (!Policy.SuppressTagKeyword && Policy.SuppressScope &&
   !Policy.SuppressUnwrittenScope)
-MaybePrintTagKeywordIfSupressingScopes(Policy, T, Out);
+maybePrintTagKeywordIfSupressingScopes(Policy, T, Out);
 
   printDeclType(T, (isa(D) && Policy.CleanUglifiedParameters &&
 D->getIdentifier())
@@ -1064,6 +1090,8 @@ void 
DeclPrinter::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) {
 
 void DeclPrinter::VisitEmptyDecl(EmptyDecl *D) {
   prettyPrintAttributes(D);
+  if (const char *Lang = tryGetUnbracedLinkageLanguage(D))
+Out << "extern \"" << Lang << "\";";
 }
 
 void DeclPrinter::VisitCXXRecordDecl(CXXRecordDecl *D) {
@@ -1136,22 +1164,21 @@ void DeclPrinter::VisitCXXRecordDecl(CXXRecordDecl *D) {
 }
 
 void DeclPrinter::VisitLinkageSpecDecl(LinkageSpecDecl *D) {
-  const 

[Lldb-commits] [clang] [lldb] [clang][AST] fix ast-print of extern with >=2 declarators, fixed (PR #93913)

2024-06-17 Thread Artem Yurchenko via lldb-commits

https://github.com/temyurchenko edited 
https://github.com/llvm/llvm-project/pull/93913
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [clang] [lldb] [clang][AST] fix ast-print of extern with >=2 declarators, fixed (PR #93913)

2024-06-17 Thread Artem Yurchenko via lldb-commits


@@ -2380,7 +2380,7 @@ FunctionDecl *Sema::CreateBuiltin(IdentifierInfo *II, 
QualType Type,
   }
 
   FunctionDecl *New = FunctionDecl::Create(Context, Parent, Loc, Loc, II, Type,
-   /*TInfo=*/nullptr, SC_Extern,
+   /*TInfo=*/nullptr, SC_None,

temyurchenko wrote:

> > That's not actually correct -- the declaration of a function at block scope 
> > should definitely _not_ be extern, it should have no linkage: 
> > https://godbolt.org/z/81fMaPaTq
> 
> I may be wrong to rely on cppreference, but the following page tells that 
> indeed a function at a block scope has implicit `extern`, which could also be 
> made explicit: https://en.cppreference.com/w/c/language/storage_duration.
> 
> I also checked your example locally by compiling (via clang) `main.c` with an 
> additional `defs.c`: main.c:
> 
> ```c
> int main(void) {
>   void f();
>   extern void g();
> 
>   f();
>   g();
> 
>   return 0;
> }
> ```
> 
> defs.c:
> 
> ```c
> #include 
> 
> void f() {
>   printf("f\n");
> }
> 
> void g() {
>   printf("g\n");
> }
> ```
> 
> The executable works as expected.
> 
> I will also take a look at the C99 standard draft.

Paragraph 6.2.2.5 says: 

> If the declaration of an identifier for a function has no storage-class 
> specifier, its linkage
is determined exactly as if it were declared with the storage-class specifier 
extern. If
the declaration of an identifier for an object has file scope and no 
storage-class specifier,
its linkage is external.

Thus, seemingly confirming that a function declared at the block scope is 
declared with an implicit `extern`.

https://github.com/llvm/llvm-project/pull/93913
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [clang] [lldb] [clang][AST] fix ast-print of extern with >=2 declarators, fixed (PR #93913)

2024-06-17 Thread Artem Yurchenko via lldb-commits


@@ -2380,7 +2380,7 @@ FunctionDecl *Sema::CreateBuiltin(IdentifierInfo *II, 
QualType Type,
   }
 
   FunctionDecl *New = FunctionDecl::Create(Context, Parent, Loc, Loc, II, Type,
-   /*TInfo=*/nullptr, SC_Extern,
+   /*TInfo=*/nullptr, SC_None,

temyurchenko wrote:

> That's not actually correct -- the declaration of a function at block scope 
> should definitely _not_ be extern, it should have no linkage: 
> https://godbolt.org/z/81fMaPaTq

I may be wrong to rely on cppreference, but the following page tells that 
indeed a function at a block scope has implicit `extern`, which could also be 
made explicit: https://en.cppreference.com/w/c/language/storage_duration.

I also checked your example locally by compiling (via clang) `main.c` with an 
additional `defs.c`: 
main.c:
```c
int main(void) {
  void f();
  extern void g();

  f();
  g();

  return 0;
}
```

defs.c: 
```c
#include 

void f() {
  printf("f\n");
}

void g() {
  printf("g\n");
}

```

The executable works as expected. 

I will also take a look at the C99 standard draft. 

https://github.com/llvm/llvm-project/pull/93913
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [clang] [lldb] [clang][AST] fix ast-print of extern with >=2 declarators, fixed (PR #93913)

2024-06-17 Thread Artem Yurchenko via lldb-commits

https://github.com/temyurchenko updated 
https://github.com/llvm/llvm-project/pull/93913

>From 410c7ba9fb7667dabdfbc48fdbda427401ca8df0 Mon Sep 17 00:00:00 2001
From: Artem Yurchenko <44875844+temyurche...@users.noreply.github.com>
Date: Thu, 30 May 2024 16:18:47 -0400
Subject: [PATCH 1/3] [clang][AST] fix ast-print of `extern ` with >=2
 declarators (#93131)

Problem: the printer used to ignore all but the first declarator for
unbraced language linkage declarators. Furthemore, that one would
be printed without the final semicolon.

Solution: for unbraced case we traverse all declarators via
`VisitDeclContext`. Furthermore, in appropriate visitors we query
for whether they are a part of the unbraced extern language linkage
spec, and if so, print appropriately.
---
 clang/lib/AST/DeclPrinter.cpp | 55 ++-
 clang/test/AST/ast-print-language-linkage.cpp | 31 +++
 2 files changed, 72 insertions(+), 14 deletions(-)
 create mode 100644 clang/test/AST/ast-print-language-linkage.cpp

diff --git a/clang/lib/AST/DeclPrinter.cpp b/clang/lib/AST/DeclPrinter.cpp
index 0cf4e64f83b8d..9250a7f6eceb2 100644
--- a/clang/lib/AST/DeclPrinter.cpp
+++ b/clang/lib/AST/DeclPrinter.cpp
@@ -633,7 +633,7 @@ static void printExplicitSpecifier(ExplicitSpecifier ES, 
llvm::raw_ostream ,
   Out << Proto;
 }
 
-static void MaybePrintTagKeywordIfSupressingScopes(PrintingPolicy ,
+static void maybePrintTagKeywordIfSupressingScopes(PrintingPolicy ,
QualType T,
llvm::raw_ostream ) {
   StringRef prefix = T->isClassType()   ? "class "
@@ -643,6 +643,22 @@ static void 
MaybePrintTagKeywordIfSupressingScopes(PrintingPolicy ,
   Out << prefix;
 }
 
+/// Return the language of the linkage spec of `D`, if applicable.
+///
+/// \Return - "C" if `D` has been declared with unbraced `extern "C"`
+/// - "C++" if `D` has been declared with unbraced `extern "C++"`
+/// - nullptr in any other case
+static const char *tryGetUnbracedLinkageLanguage(const Decl *D) {
+  const auto *SD = dyn_cast(D->getDeclContext());
+  if (!SD || SD->hasBraces())
+return nullptr;
+  if (SD->getLanguage() == LinkageSpecLanguageIDs::C)
+return "C";
+  assert(SD->getLanguage() == LinkageSpecLanguageIDs::CXX &&
+ "unknown language in linkage specification");
+  return "C++";
+}
+
 void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
   if (!D->getDescribedFunctionTemplate() &&
   !D->isFunctionTemplateSpecialization()) {
@@ -662,6 +678,11 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
   CXXConversionDecl *ConversionDecl = dyn_cast(D);
   CXXDeductionGuideDecl *GuideDecl = dyn_cast(D);
   if (!Policy.SuppressSpecifiers) {
+if (const char *Lang = tryGetUnbracedLinkageLanguage(D)) {
+  // the "extern" specifier is implicit
+  assert(D->getStorageClass() == SC_None);
+  Out << "extern \"" << Lang << "\" ";
+}
 switch (D->getStorageClass()) {
 case SC_None: break;
 case SC_Extern: Out << "extern "; break;
@@ -807,7 +828,7 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
   }
   if (!Policy.SuppressTagKeyword && Policy.SuppressScope &&
   !Policy.SuppressUnwrittenScope)
-MaybePrintTagKeywordIfSupressingScopes(Policy, AFT->getReturnType(),
+maybePrintTagKeywordIfSupressingScopes(Policy, AFT->getReturnType(),
Out);
   AFT->getReturnType().print(Out, Policy, Proto);
   Proto.clear();
@@ -932,6 +953,11 @@ void DeclPrinter::VisitVarDecl(VarDecl *D) {
 : D->getASTContext().getUnqualifiedObjCPointerType(D->getType());
 
   if (!Policy.SuppressSpecifiers) {
+if (const char *Lang = tryGetUnbracedLinkageLanguage(D)) {
+  // the "extern" specifier is implicit
+  assert(D->getStorageClass() == SC_None);
+  Out << "extern \"" << Lang << "\" ";
+}
 StorageClass SC = D->getStorageClass();
 if (SC != SC_None)
   Out << VarDecl::getStorageClassSpecifierString(SC) << " ";
@@ -961,7 +987,7 @@ void DeclPrinter::VisitVarDecl(VarDecl *D) {
 
   if (!Policy.SuppressTagKeyword && Policy.SuppressScope &&
   !Policy.SuppressUnwrittenScope)
-MaybePrintTagKeywordIfSupressingScopes(Policy, T, Out);
+maybePrintTagKeywordIfSupressingScopes(Policy, T, Out);
 
   printDeclType(T, (isa(D) && Policy.CleanUglifiedParameters &&
 D->getIdentifier())
@@ -1064,6 +1090,8 @@ void 
DeclPrinter::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) {
 
 void DeclPrinter::VisitEmptyDecl(EmptyDecl *D) {
   prettyPrintAttributes(D);
+  if (const char *Lang = tryGetUnbracedLinkageLanguage(D))
+Out << "extern \"" << Lang << "\";";
 }
 
 void DeclPrinter::VisitCXXRecordDecl(CXXRecordDecl *D) {
@@ -1136,22 +1164,21 @@ void DeclPrinter::VisitCXXRecordDecl(CXXRecordDecl *D) {
 }
 
 void DeclPrinter::VisitLinkageSpecDecl(LinkageSpecDecl *D) {
-  const 

[Lldb-commits] [clang] [lldb] [clang][AST] fix ast-print of extern with >=2 declarators, fixed (PR #93913)

2024-06-17 Thread Artem Yurchenko via lldb-commits


@@ -576,13 +576,19 @@ template  static bool 
isFirstInExternCContext(T *D) {
   return First->isInExternCContext();
 }
 
-static bool isSingleLineLanguageLinkage(const Decl ) {
-  if (const auto *SD = dyn_cast(D.getDeclContext()))
+static bool isUnbracedLanguageLinkage(const DeclContext *DC) {
+  if (!DC)
+return false;
+  if (const auto *SD = dyn_cast(DC))
 if (!SD->hasBraces())
   return true;

temyurchenko wrote:

Will do.

https://github.com/llvm/llvm-project/pull/93913
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [clang] [lldb] [clang][AST] fix ast-print of extern with >=2 declarators, fixed (PR #93913)

2024-06-17 Thread Artem Yurchenko via lldb-commits


@@ -2380,7 +2380,7 @@ FunctionDecl *Sema::CreateBuiltin(IdentifierInfo *II, 
QualType Type,
   }
 
   FunctionDecl *New = FunctionDecl::Create(Context, Parent, Loc, Loc, II, Type,
-   /*TInfo=*/nullptr, SC_Extern,
+   /*TInfo=*/nullptr, SC_None,

temyurchenko wrote:

You are right, I also paid attention to that issue. However, when a storage 
class specifier is omitted for a function, it's storage class is implicitly 
supposed to be `extern`. Thus, it's fine.

Furthermore, the meaning of this field according to the documentation comments 
is not for the actual storage duration or linkage, but for the storage-class 
specifier _as present in the source code_. Since builtins aren't really present 
in the source code, it seems further reasonable to omit a specifier.



https://github.com/llvm/llvm-project/pull/93913
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [clang] [lldb] [clang][AST] fix ast-print of extern with >=2 declarators, fixed (PR #93913)

2024-06-07 Thread Artem Yurchenko via lldb-commits

https://github.com/temyurchenko updated 
https://github.com/llvm/llvm-project/pull/93913

>From 410c7ba9fb7667dabdfbc48fdbda427401ca8df0 Mon Sep 17 00:00:00 2001
From: Artem Yurchenko <44875844+temyurche...@users.noreply.github.com>
Date: Thu, 30 May 2024 16:18:47 -0400
Subject: [PATCH 1/2] [clang][AST] fix ast-print of `extern ` with >=2
 declarators (#93131)

Problem: the printer used to ignore all but the first declarator for
unbraced language linkage declarators. Furthemore, that one would
be printed without the final semicolon.

Solution: for unbraced case we traverse all declarators via
`VisitDeclContext`. Furthermore, in appropriate visitors we query
for whether they are a part of the unbraced extern language linkage
spec, and if so, print appropriately.
---
 clang/lib/AST/DeclPrinter.cpp | 55 ++-
 clang/test/AST/ast-print-language-linkage.cpp | 31 +++
 2 files changed, 72 insertions(+), 14 deletions(-)
 create mode 100644 clang/test/AST/ast-print-language-linkage.cpp

diff --git a/clang/lib/AST/DeclPrinter.cpp b/clang/lib/AST/DeclPrinter.cpp
index 0cf4e64f83b8d..9250a7f6eceb2 100644
--- a/clang/lib/AST/DeclPrinter.cpp
+++ b/clang/lib/AST/DeclPrinter.cpp
@@ -633,7 +633,7 @@ static void printExplicitSpecifier(ExplicitSpecifier ES, 
llvm::raw_ostream ,
   Out << Proto;
 }
 
-static void MaybePrintTagKeywordIfSupressingScopes(PrintingPolicy ,
+static void maybePrintTagKeywordIfSupressingScopes(PrintingPolicy ,
QualType T,
llvm::raw_ostream ) {
   StringRef prefix = T->isClassType()   ? "class "
@@ -643,6 +643,22 @@ static void 
MaybePrintTagKeywordIfSupressingScopes(PrintingPolicy ,
   Out << prefix;
 }
 
+/// Return the language of the linkage spec of `D`, if applicable.
+///
+/// \Return - "C" if `D` has been declared with unbraced `extern "C"`
+/// - "C++" if `D` has been declared with unbraced `extern "C++"`
+/// - nullptr in any other case
+static const char *tryGetUnbracedLinkageLanguage(const Decl *D) {
+  const auto *SD = dyn_cast(D->getDeclContext());
+  if (!SD || SD->hasBraces())
+return nullptr;
+  if (SD->getLanguage() == LinkageSpecLanguageIDs::C)
+return "C";
+  assert(SD->getLanguage() == LinkageSpecLanguageIDs::CXX &&
+ "unknown language in linkage specification");
+  return "C++";
+}
+
 void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
   if (!D->getDescribedFunctionTemplate() &&
   !D->isFunctionTemplateSpecialization()) {
@@ -662,6 +678,11 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
   CXXConversionDecl *ConversionDecl = dyn_cast(D);
   CXXDeductionGuideDecl *GuideDecl = dyn_cast(D);
   if (!Policy.SuppressSpecifiers) {
+if (const char *Lang = tryGetUnbracedLinkageLanguage(D)) {
+  // the "extern" specifier is implicit
+  assert(D->getStorageClass() == SC_None);
+  Out << "extern \"" << Lang << "\" ";
+}
 switch (D->getStorageClass()) {
 case SC_None: break;
 case SC_Extern: Out << "extern "; break;
@@ -807,7 +828,7 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
   }
   if (!Policy.SuppressTagKeyword && Policy.SuppressScope &&
   !Policy.SuppressUnwrittenScope)
-MaybePrintTagKeywordIfSupressingScopes(Policy, AFT->getReturnType(),
+maybePrintTagKeywordIfSupressingScopes(Policy, AFT->getReturnType(),
Out);
   AFT->getReturnType().print(Out, Policy, Proto);
   Proto.clear();
@@ -932,6 +953,11 @@ void DeclPrinter::VisitVarDecl(VarDecl *D) {
 : D->getASTContext().getUnqualifiedObjCPointerType(D->getType());
 
   if (!Policy.SuppressSpecifiers) {
+if (const char *Lang = tryGetUnbracedLinkageLanguage(D)) {
+  // the "extern" specifier is implicit
+  assert(D->getStorageClass() == SC_None);
+  Out << "extern \"" << Lang << "\" ";
+}
 StorageClass SC = D->getStorageClass();
 if (SC != SC_None)
   Out << VarDecl::getStorageClassSpecifierString(SC) << " ";
@@ -961,7 +987,7 @@ void DeclPrinter::VisitVarDecl(VarDecl *D) {
 
   if (!Policy.SuppressTagKeyword && Policy.SuppressScope &&
   !Policy.SuppressUnwrittenScope)
-MaybePrintTagKeywordIfSupressingScopes(Policy, T, Out);
+maybePrintTagKeywordIfSupressingScopes(Policy, T, Out);
 
   printDeclType(T, (isa(D) && Policy.CleanUglifiedParameters &&
 D->getIdentifier())
@@ -1064,6 +1090,8 @@ void 
DeclPrinter::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) {
 
 void DeclPrinter::VisitEmptyDecl(EmptyDecl *D) {
   prettyPrintAttributes(D);
+  if (const char *Lang = tryGetUnbracedLinkageLanguage(D))
+Out << "extern \"" << Lang << "\";";
 }
 
 void DeclPrinter::VisitCXXRecordDecl(CXXRecordDecl *D) {
@@ -1136,22 +1164,21 @@ void DeclPrinter::VisitCXXRecordDecl(CXXRecordDecl *D) {
 }
 
 void DeclPrinter::VisitLinkageSpecDecl(LinkageSpecDecl *D) {
-  const 

[Lldb-commits] [clang] [lldb] [clang][AST] fix ast-print of extern with >=2 declarators, fixed (PR #93913)

2024-06-07 Thread Artem Yurchenko via lldb-commits

https://github.com/temyurchenko updated 
https://github.com/llvm/llvm-project/pull/93913

>From f1951f3f2dd322123a1c49221c4252f4ea932242 Mon Sep 17 00:00:00 2001
From: Artem Yurchenko <44875844+temyurche...@users.noreply.github.com>
Date: Thu, 30 May 2024 16:18:47 -0400
Subject: [PATCH 1/2] [clang][AST] fix ast-print of `extern ` with >=2
 declarators (#93131)

Problem: the printer used to ignore all but the first declarator for
unbraced language linkage declarators. Furthemore, that one would be
printed without the final semicolon.

Solution: when there is more than one declarator, we print them in a
braced `extern ` block. If the original declaration was unbraced
and there is one or less declarator, we omit the braces, but add the
semicolon.

**N.B.** We are printing braces which were, in some cases, absent from
the original CST. If that's an issue, I'll work on it. See the tests for
the examples.
---
 clang/lib/AST/DeclPrinter.cpp | 55 ++-
 clang/test/AST/ast-print-language-linkage.cpp | 31 +++
 2 files changed, 72 insertions(+), 14 deletions(-)
 create mode 100644 clang/test/AST/ast-print-language-linkage.cpp

diff --git a/clang/lib/AST/DeclPrinter.cpp b/clang/lib/AST/DeclPrinter.cpp
index 0cf4e64f83b8d..9250a7f6eceb2 100644
--- a/clang/lib/AST/DeclPrinter.cpp
+++ b/clang/lib/AST/DeclPrinter.cpp
@@ -633,7 +633,7 @@ static void printExplicitSpecifier(ExplicitSpecifier ES, 
llvm::raw_ostream ,
   Out << Proto;
 }
 
-static void MaybePrintTagKeywordIfSupressingScopes(PrintingPolicy ,
+static void maybePrintTagKeywordIfSupressingScopes(PrintingPolicy ,
QualType T,
llvm::raw_ostream ) {
   StringRef prefix = T->isClassType()   ? "class "
@@ -643,6 +643,22 @@ static void 
MaybePrintTagKeywordIfSupressingScopes(PrintingPolicy ,
   Out << prefix;
 }
 
+/// Return the language of the linkage spec of `D`, if applicable.
+///
+/// \Return - "C" if `D` has been declared with unbraced `extern "C"`
+/// - "C++" if `D` has been declared with unbraced `extern "C++"`
+/// - nullptr in any other case
+static const char *tryGetUnbracedLinkageLanguage(const Decl *D) {
+  const auto *SD = dyn_cast(D->getDeclContext());
+  if (!SD || SD->hasBraces())
+return nullptr;
+  if (SD->getLanguage() == LinkageSpecLanguageIDs::C)
+return "C";
+  assert(SD->getLanguage() == LinkageSpecLanguageIDs::CXX &&
+ "unknown language in linkage specification");
+  return "C++";
+}
+
 void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
   if (!D->getDescribedFunctionTemplate() &&
   !D->isFunctionTemplateSpecialization()) {
@@ -662,6 +678,11 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
   CXXConversionDecl *ConversionDecl = dyn_cast(D);
   CXXDeductionGuideDecl *GuideDecl = dyn_cast(D);
   if (!Policy.SuppressSpecifiers) {
+if (const char *Lang = tryGetUnbracedLinkageLanguage(D)) {
+  // the "extern" specifier is implicit
+  assert(D->getStorageClass() == SC_None);
+  Out << "extern \"" << Lang << "\" ";
+}
 switch (D->getStorageClass()) {
 case SC_None: break;
 case SC_Extern: Out << "extern "; break;
@@ -807,7 +828,7 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
   }
   if (!Policy.SuppressTagKeyword && Policy.SuppressScope &&
   !Policy.SuppressUnwrittenScope)
-MaybePrintTagKeywordIfSupressingScopes(Policy, AFT->getReturnType(),
+maybePrintTagKeywordIfSupressingScopes(Policy, AFT->getReturnType(),
Out);
   AFT->getReturnType().print(Out, Policy, Proto);
   Proto.clear();
@@ -932,6 +953,11 @@ void DeclPrinter::VisitVarDecl(VarDecl *D) {
 : D->getASTContext().getUnqualifiedObjCPointerType(D->getType());
 
   if (!Policy.SuppressSpecifiers) {
+if (const char *Lang = tryGetUnbracedLinkageLanguage(D)) {
+  // the "extern" specifier is implicit
+  assert(D->getStorageClass() == SC_None);
+  Out << "extern \"" << Lang << "\" ";
+}
 StorageClass SC = D->getStorageClass();
 if (SC != SC_None)
   Out << VarDecl::getStorageClassSpecifierString(SC) << " ";
@@ -961,7 +987,7 @@ void DeclPrinter::VisitVarDecl(VarDecl *D) {
 
   if (!Policy.SuppressTagKeyword && Policy.SuppressScope &&
   !Policy.SuppressUnwrittenScope)
-MaybePrintTagKeywordIfSupressingScopes(Policy, T, Out);
+maybePrintTagKeywordIfSupressingScopes(Policy, T, Out);
 
   printDeclType(T, (isa(D) && Policy.CleanUglifiedParameters &&
 D->getIdentifier())
@@ -1064,6 +1090,8 @@ void 
DeclPrinter::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) {
 
 void DeclPrinter::VisitEmptyDecl(EmptyDecl *D) {
   prettyPrintAttributes(D);
+  if (const char *Lang = tryGetUnbracedLinkageLanguage(D))
+Out << "extern \"" << Lang << "\";";
 }
 
 void DeclPrinter::VisitCXXRecordDecl(CXXRecordDecl *D) {
@@ -1136,22 

[Lldb-commits] [clang] [lldb] [clang][AST] fix ast-print of extern with >=2 declarators, fixed (PR #93913)

2024-06-07 Thread Artem Yurchenko via lldb-commits

https://github.com/temyurchenko updated 
https://github.com/llvm/llvm-project/pull/93913

>From 9b18a5c4132cf093fc9b32f6b4dcfe406d485e3d Mon Sep 17 00:00:00 2001
From: Artem Yurchenko 
Date: Thu, 6 Jun 2024 20:20:19 -0400
Subject: [PATCH] enforce the unbraced `extern ` invariant

Quoting 9.11.8:
> A declaration directly contained in a linkage-specification is
> treated as if it contains the extern specifier (9.2.2) for the
> purpose of determining the linkage of the declared name and whether
> it is a definition. Such a declaration shall not specify a storage
> class.

So, the invariant is that function and variable declarations within an
unbraced language linkage specification have `StorageClass` set to
`SC_None`.

Problem: in several places the invariant was broken.

Solution: remove the explicit `SC_Extern` specification. Note, that my
changes result in the `extern` being implicit in some functions
that are not contained in a language linkage specification.
---
 clang/lib/AST/Decl.cpp| 26 ---
 clang/lib/Sema/SemaDecl.cpp   |  2 +-
 clang/lib/Sema/SemaExpr.cpp   |  2 +-
 .../Clang/ClangExpressionParser.cpp   |  2 +-
 .../Clang/NameSearchContext.cpp   |  3 ++-
 5 files changed, 27 insertions(+), 8 deletions(-)

diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index 1f19dadafa44e..ebaeed0e818e1 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -576,13 +576,19 @@ template  static bool 
isFirstInExternCContext(T *D) {
   return First->isInExternCContext();
 }
 
-static bool isSingleLineLanguageLinkage(const Decl ) {
-  if (const auto *SD = dyn_cast(D.getDeclContext()))
+static bool isUnbracedLanguageLinkage(const DeclContext *DC) {
+  if (!DC)
+return false;
+  if (const auto *SD = dyn_cast(DC))
 if (!SD->hasBraces())
   return true;
   return false;
 }
 
+static bool hasUnbracedLanguageLinkage(const Decl ) {
+  return isUnbracedLanguageLinkage(D.getDeclContext());
+}
+
 static bool isDeclaredInModuleInterfaceOrPartition(const NamedDecl *D) {
   if (auto *M = D->getOwningModule())
 return M->isInterfaceOrPartition();
@@ -644,7 +650,7 @@ LinkageComputer::getLVForNamespaceScopeDecl(const NamedDecl 
*D,
 
   if (Var->getStorageClass() != SC_Extern &&
   Var->getStorageClass() != SC_PrivateExtern &&
-  !isSingleLineLanguageLinkage(*Var))
+  !hasUnbracedLanguageLinkage(*Var))
 return LinkageInfo::internal();
 }
 
@@ -2133,6 +2139,12 @@ VarDecl::VarDecl(Kind DK, ASTContext , DeclContext *DC,
 "ParmVarDeclBitfields too large!");
   static_assert(sizeof(NonParmVarDeclBitfields) <= sizeof(unsigned),
 "NonParmVarDeclBitfields too large!");
+
+  // The unbraced `extern "C"` invariant is that the storage class
+  // specifier is omitted in the source code, i.e. SC_None (but is,
+  // implicitly, `extern`).
+  assert(!isUnbracedLanguageLinkage(DC) || SC == SC_None);
+
   AllBits = 0;
   VarDeclBits.SClass = SC;
   // Everything else is implicitly initialized to false.
@@ -2316,7 +2328,7 @@ VarDecl::isThisDeclarationADefinition(ASTContext ) 
const {
   //   A declaration directly contained in a linkage-specification is treated
   //   as if it contains the extern specifier for the purpose of determining
   //   the linkage of the declared name and whether it is a definition.
-  if (isSingleLineLanguageLinkage(*this))
+  if (hasUnbracedLanguageLinkage(*this))
 return DeclarationOnly;
 
   // C99 6.9.2p2:
@@ -3041,6 +3053,12 @@ FunctionDecl::FunctionDecl(Kind DK, ASTContext , 
DeclContext *DC,
   DeclContext(DK), redeclarable_base(C), Body(), ODRHash(0),
   EndRangeLoc(NameInfo.getEndLoc()), DNLoc(NameInfo.getInfo()) {
   assert(T.isNull() || T->isFunctionType());
+
+  // The unbraced `extern "C"` invariant is that the storage class
+  // specifier is omitted in the source code, i.e. SC_None (but is,
+  // implicitly, `extern`).
+  assert(!isUnbracedLanguageLinkage(DC) || S == SC_None);
+
   FunctionDeclBits.SClass = S;
   FunctionDeclBits.IsInline = isInlineSpecified;
   FunctionDeclBits.IsInlineSpecified = isInlineSpecified;
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 4b9b735f1cfb4..4e2f02ba7007a 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -2380,7 +2380,7 @@ FunctionDecl *Sema::CreateBuiltin(IdentifierInfo *II, 
QualType Type,
   }
 
   FunctionDecl *New = FunctionDecl::Create(Context, Parent, Loc, Loc, II, Type,
-   /*TInfo=*/nullptr, SC_Extern,
+   /*TInfo=*/nullptr, SC_None,

getCurFPFeatures().isFPConstrained(),
false, Type->isFunctionProtoType());
   New->setImplicit();
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 

[Lldb-commits] [clang] [lldb] [clang][AST] fix ast-print of extern with >=2 declarators, fixed (PR #93913)

2024-06-07 Thread Artem Yurchenko via lldb-commits

temyurchenko wrote:

> Hmm... I don't have a great idea. Is using it not enough to get it to be 
> emitted? I see here we don't seem to cause them to be emitted: 
> https://godbolt.org/z/nYzMca7Te

Yes, I get the same result. I also tried adding a test in `DeclPrinterTest`, 
but it doesn't lookup builtins.

https://github.com/llvm/llvm-project/pull/93913
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [clang] [lldb] [clang][AST] fix ast-print of extern with >=2 declarators, fixed (PR #93913)

2024-06-07 Thread Artem Yurchenko via lldb-commits

https://github.com/temyurchenko updated 
https://github.com/llvm/llvm-project/pull/93913

>From a54036c0fdc1a875f40a274d502dd96651a35ae3 Mon Sep 17 00:00:00 2001
From: Artem Yurchenko 
Date: Thu, 6 Jun 2024 20:20:19 -0400
Subject: [PATCH] enforce the unbraced `extern ` invariant

Quoting 9.11.8:
> A declaration directly contained in a linkage-specification is
> treated as if it contains the extern specifier (9.2.2) for the
> purpose of determining the linkage of the declared name and whether
> it is a definition. Such a declaration shall not specify a storage
> class.

So, the invariant is that function and variable declarations within an
unbraced language linkage specification have `StorageClass` set to
`SC_None`.

Problem: in several places the invariant was broken.

Solution: remove the explicit `SC_Extern` specification. Note, that my
changes result in the `extern` being implicit in some functions
that are not contained in a language linkage specification.
---
 clang/lib/AST/Decl.cpp| 26 ---
 clang/lib/Sema/SemaDecl.cpp   |  2 +-
 .../Clang/ClangExpressionParser.cpp   |  2 +-
 .../Clang/NameSearchContext.cpp   |  3 ++-
 4 files changed, 26 insertions(+), 7 deletions(-)

diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index 1f19dadafa44e..ebaeed0e818e1 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -576,13 +576,19 @@ template  static bool 
isFirstInExternCContext(T *D) {
   return First->isInExternCContext();
 }
 
-static bool isSingleLineLanguageLinkage(const Decl ) {
-  if (const auto *SD = dyn_cast(D.getDeclContext()))
+static bool isUnbracedLanguageLinkage(const DeclContext *DC) {
+  if (!DC)
+return false;
+  if (const auto *SD = dyn_cast(DC))
 if (!SD->hasBraces())
   return true;
   return false;
 }
 
+static bool hasUnbracedLanguageLinkage(const Decl ) {
+  return isUnbracedLanguageLinkage(D.getDeclContext());
+}
+
 static bool isDeclaredInModuleInterfaceOrPartition(const NamedDecl *D) {
   if (auto *M = D->getOwningModule())
 return M->isInterfaceOrPartition();
@@ -644,7 +650,7 @@ LinkageComputer::getLVForNamespaceScopeDecl(const NamedDecl 
*D,
 
   if (Var->getStorageClass() != SC_Extern &&
   Var->getStorageClass() != SC_PrivateExtern &&
-  !isSingleLineLanguageLinkage(*Var))
+  !hasUnbracedLanguageLinkage(*Var))
 return LinkageInfo::internal();
 }
 
@@ -2133,6 +2139,12 @@ VarDecl::VarDecl(Kind DK, ASTContext , DeclContext *DC,
 "ParmVarDeclBitfields too large!");
   static_assert(sizeof(NonParmVarDeclBitfields) <= sizeof(unsigned),
 "NonParmVarDeclBitfields too large!");
+
+  // The unbraced `extern "C"` invariant is that the storage class
+  // specifier is omitted in the source code, i.e. SC_None (but is,
+  // implicitly, `extern`).
+  assert(!isUnbracedLanguageLinkage(DC) || SC == SC_None);
+
   AllBits = 0;
   VarDeclBits.SClass = SC;
   // Everything else is implicitly initialized to false.
@@ -2316,7 +2328,7 @@ VarDecl::isThisDeclarationADefinition(ASTContext ) 
const {
   //   A declaration directly contained in a linkage-specification is treated
   //   as if it contains the extern specifier for the purpose of determining
   //   the linkage of the declared name and whether it is a definition.
-  if (isSingleLineLanguageLinkage(*this))
+  if (hasUnbracedLanguageLinkage(*this))
 return DeclarationOnly;
 
   // C99 6.9.2p2:
@@ -3041,6 +3053,12 @@ FunctionDecl::FunctionDecl(Kind DK, ASTContext , 
DeclContext *DC,
   DeclContext(DK), redeclarable_base(C), Body(), ODRHash(0),
   EndRangeLoc(NameInfo.getEndLoc()), DNLoc(NameInfo.getInfo()) {
   assert(T.isNull() || T->isFunctionType());
+
+  // The unbraced `extern "C"` invariant is that the storage class
+  // specifier is omitted in the source code, i.e. SC_None (but is,
+  // implicitly, `extern`).
+  assert(!isUnbracedLanguageLinkage(DC) || S == SC_None);
+
   FunctionDeclBits.SClass = S;
   FunctionDeclBits.IsInline = isInlineSpecified;
   FunctionDeclBits.IsInlineSpecified = isInlineSpecified;
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 4b9b735f1cfb4..4e2f02ba7007a 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -2380,7 +2380,7 @@ FunctionDecl *Sema::CreateBuiltin(IdentifierInfo *II, 
QualType Type,
   }
 
   FunctionDecl *New = FunctionDecl::Create(Context, Parent, Loc, Loc, II, Type,
-   /*TInfo=*/nullptr, SC_Extern,
+   /*TInfo=*/nullptr, SC_None,

getCurFPFeatures().isFPConstrained(),
false, Type->isFunctionProtoType());
   New->setImplicit();
diff --git 
a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp 

[Lldb-commits] [clang] [lldb] [clang][AST] fix ast-print of extern with >=2 declarators, fixed (PR #93913)

2024-06-07 Thread Artem Yurchenko via lldb-commits

temyurchenko wrote:

> I see the 2nds commit doesn't add any tests! Please make it do so

I've tried and I'm not quite sure how to do it. The issue is we need to test 
AST printing of «implicitly declared» functions, such as builtins and functions 
instrumented by lldb, such as `log` for logging; which seems contradictory. Do 
you have any suggestions?

Furthermore, the second commit adds an assertion of an invariant and then fixes 
the places in the code where the invariant breaks. Is it fair to say that the 
codebase itself is the test for the invariant? If any codepath would break the 
invariant, the assertion would be triggered. Not on a release build though, I 
imagine.

https://github.com/llvm/llvm-project/pull/93913
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [clang] [lldb] [clang][AST] fix ast-print of extern with >=2 declarators, fixed (PR #93913)

2024-06-06 Thread Artem Yurchenko via lldb-commits

temyurchenko wrote:

This is a relanding of #93131. 

The first commit is the same, the second commit presents and fixes the issue 
from the linked discussion.

cc @erichkeane, @AaronBallman, @gulfemsavrun.
(I can't set the reviewers myself)

https://github.com/llvm/llvm-project/pull/93913
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [clang] [lldb] [clang][AST] fix ast-print of extern with >=2 declarators, fixed (PR #93913)

2024-06-06 Thread Artem Yurchenko via lldb-commits

https://github.com/temyurchenko updated 
https://github.com/llvm/llvm-project/pull/93913

>From fac45476736cd04f044f046fd0df9e59450a926b Mon Sep 17 00:00:00 2001
From: Artem Yurchenko 
Date: Wed, 22 May 2024 23:41:35 -0400
Subject: [PATCH 1/2] [clang][AST] fix ast-print of `extern ` with >=2
 declarators

Problem: the printer used to ignore all but the first declarator for
unbraced language linkage declarators. Furthemore, that one would
be printed without the final semicolon.

Solution: for unbraced case we traverse all declarators via
`VisitDeclContext`. Furthermore, in appropriate visitors we query
for whether they are a part of the unbraced extern language linkage
spec, and if so, print appropriately.
---
 clang/lib/AST/DeclPrinter.cpp | 55 ++-
 clang/test/AST/ast-print-language-linkage.cpp | 31 +++
 2 files changed, 72 insertions(+), 14 deletions(-)
 create mode 100644 clang/test/AST/ast-print-language-linkage.cpp

diff --git a/clang/lib/AST/DeclPrinter.cpp b/clang/lib/AST/DeclPrinter.cpp
index 0cf4e64f83b8d..9250a7f6eceb2 100644
--- a/clang/lib/AST/DeclPrinter.cpp
+++ b/clang/lib/AST/DeclPrinter.cpp
@@ -633,7 +633,7 @@ static void printExplicitSpecifier(ExplicitSpecifier ES, 
llvm::raw_ostream ,
   Out << Proto;
 }
 
-static void MaybePrintTagKeywordIfSupressingScopes(PrintingPolicy ,
+static void maybePrintTagKeywordIfSupressingScopes(PrintingPolicy ,
QualType T,
llvm::raw_ostream ) {
   StringRef prefix = T->isClassType()   ? "class "
@@ -643,6 +643,22 @@ static void 
MaybePrintTagKeywordIfSupressingScopes(PrintingPolicy ,
   Out << prefix;
 }
 
+/// Return the language of the linkage spec of `D`, if applicable.
+///
+/// \Return - "C" if `D` has been declared with unbraced `extern "C"`
+/// - "C++" if `D` has been declared with unbraced `extern "C++"`
+/// - nullptr in any other case
+static const char *tryGetUnbracedLinkageLanguage(const Decl *D) {
+  const auto *SD = dyn_cast(D->getDeclContext());
+  if (!SD || SD->hasBraces())
+return nullptr;
+  if (SD->getLanguage() == LinkageSpecLanguageIDs::C)
+return "C";
+  assert(SD->getLanguage() == LinkageSpecLanguageIDs::CXX &&
+ "unknown language in linkage specification");
+  return "C++";
+}
+
 void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
   if (!D->getDescribedFunctionTemplate() &&
   !D->isFunctionTemplateSpecialization()) {
@@ -662,6 +678,11 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
   CXXConversionDecl *ConversionDecl = dyn_cast(D);
   CXXDeductionGuideDecl *GuideDecl = dyn_cast(D);
   if (!Policy.SuppressSpecifiers) {
+if (const char *Lang = tryGetUnbracedLinkageLanguage(D)) {
+  // the "extern" specifier is implicit
+  assert(D->getStorageClass() == SC_None);
+  Out << "extern \"" << Lang << "\" ";
+}
 switch (D->getStorageClass()) {
 case SC_None: break;
 case SC_Extern: Out << "extern "; break;
@@ -807,7 +828,7 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
   }
   if (!Policy.SuppressTagKeyword && Policy.SuppressScope &&
   !Policy.SuppressUnwrittenScope)
-MaybePrintTagKeywordIfSupressingScopes(Policy, AFT->getReturnType(),
+maybePrintTagKeywordIfSupressingScopes(Policy, AFT->getReturnType(),
Out);
   AFT->getReturnType().print(Out, Policy, Proto);
   Proto.clear();
@@ -932,6 +953,11 @@ void DeclPrinter::VisitVarDecl(VarDecl *D) {
 : D->getASTContext().getUnqualifiedObjCPointerType(D->getType());
 
   if (!Policy.SuppressSpecifiers) {
+if (const char *Lang = tryGetUnbracedLinkageLanguage(D)) {
+  // the "extern" specifier is implicit
+  assert(D->getStorageClass() == SC_None);
+  Out << "extern \"" << Lang << "\" ";
+}
 StorageClass SC = D->getStorageClass();
 if (SC != SC_None)
   Out << VarDecl::getStorageClassSpecifierString(SC) << " ";
@@ -961,7 +987,7 @@ void DeclPrinter::VisitVarDecl(VarDecl *D) {
 
   if (!Policy.SuppressTagKeyword && Policy.SuppressScope &&
   !Policy.SuppressUnwrittenScope)
-MaybePrintTagKeywordIfSupressingScopes(Policy, T, Out);
+maybePrintTagKeywordIfSupressingScopes(Policy, T, Out);
 
   printDeclType(T, (isa(D) && Policy.CleanUglifiedParameters &&
 D->getIdentifier())
@@ -1064,6 +1090,8 @@ void 
DeclPrinter::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) {
 
 void DeclPrinter::VisitEmptyDecl(EmptyDecl *D) {
   prettyPrintAttributes(D);
+  if (const char *Lang = tryGetUnbracedLinkageLanguage(D))
+Out << "extern \"" << Lang << "\";";
 }
 
 void DeclPrinter::VisitCXXRecordDecl(CXXRecordDecl *D) {
@@ -1136,22 +1164,21 @@ void DeclPrinter::VisitCXXRecordDecl(CXXRecordDecl *D) {
 }
 
 void DeclPrinter::VisitLinkageSpecDecl(LinkageSpecDecl *D) {
-  const char *l;
+  if (!D->hasBraces()) {
+

[Lldb-commits] [clang] [lldb] [clang][AST] fix ast-print of extern with >=2 declarators, fixed (PR #93913)

2024-06-06 Thread Artem Yurchenko via lldb-commits

https://github.com/temyurchenko updated 
https://github.com/llvm/llvm-project/pull/93913

>From fac45476736cd04f044f046fd0df9e59450a926b Mon Sep 17 00:00:00 2001
From: Artem Yurchenko 
Date: Wed, 22 May 2024 23:41:35 -0400
Subject: [PATCH 1/2] [clang][AST] fix ast-print of `extern ` with >=2
 declarators

Problem: the printer used to ignore all but the first declarator for
unbraced language linkage declarators. Furthemore, that one would
be printed without the final semicolon.

Solution: for unbraced case we traverse all declarators via
`VisitDeclContext`. Furthermore, in appropriate visitors we query
for whether they are a part of the unbraced extern language linkage
spec, and if so, print appropriately.
---
 clang/lib/AST/DeclPrinter.cpp | 55 ++-
 clang/test/AST/ast-print-language-linkage.cpp | 31 +++
 2 files changed, 72 insertions(+), 14 deletions(-)
 create mode 100644 clang/test/AST/ast-print-language-linkage.cpp

diff --git a/clang/lib/AST/DeclPrinter.cpp b/clang/lib/AST/DeclPrinter.cpp
index 0cf4e64f83b8d..9250a7f6eceb2 100644
--- a/clang/lib/AST/DeclPrinter.cpp
+++ b/clang/lib/AST/DeclPrinter.cpp
@@ -633,7 +633,7 @@ static void printExplicitSpecifier(ExplicitSpecifier ES, 
llvm::raw_ostream ,
   Out << Proto;
 }
 
-static void MaybePrintTagKeywordIfSupressingScopes(PrintingPolicy ,
+static void maybePrintTagKeywordIfSupressingScopes(PrintingPolicy ,
QualType T,
llvm::raw_ostream ) {
   StringRef prefix = T->isClassType()   ? "class "
@@ -643,6 +643,22 @@ static void 
MaybePrintTagKeywordIfSupressingScopes(PrintingPolicy ,
   Out << prefix;
 }
 
+/// Return the language of the linkage spec of `D`, if applicable.
+///
+/// \Return - "C" if `D` has been declared with unbraced `extern "C"`
+/// - "C++" if `D` has been declared with unbraced `extern "C++"`
+/// - nullptr in any other case
+static const char *tryGetUnbracedLinkageLanguage(const Decl *D) {
+  const auto *SD = dyn_cast(D->getDeclContext());
+  if (!SD || SD->hasBraces())
+return nullptr;
+  if (SD->getLanguage() == LinkageSpecLanguageIDs::C)
+return "C";
+  assert(SD->getLanguage() == LinkageSpecLanguageIDs::CXX &&
+ "unknown language in linkage specification");
+  return "C++";
+}
+
 void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
   if (!D->getDescribedFunctionTemplate() &&
   !D->isFunctionTemplateSpecialization()) {
@@ -662,6 +678,11 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
   CXXConversionDecl *ConversionDecl = dyn_cast(D);
   CXXDeductionGuideDecl *GuideDecl = dyn_cast(D);
   if (!Policy.SuppressSpecifiers) {
+if (const char *Lang = tryGetUnbracedLinkageLanguage(D)) {
+  // the "extern" specifier is implicit
+  assert(D->getStorageClass() == SC_None);
+  Out << "extern \"" << Lang << "\" ";
+}
 switch (D->getStorageClass()) {
 case SC_None: break;
 case SC_Extern: Out << "extern "; break;
@@ -807,7 +828,7 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
   }
   if (!Policy.SuppressTagKeyword && Policy.SuppressScope &&
   !Policy.SuppressUnwrittenScope)
-MaybePrintTagKeywordIfSupressingScopes(Policy, AFT->getReturnType(),
+maybePrintTagKeywordIfSupressingScopes(Policy, AFT->getReturnType(),
Out);
   AFT->getReturnType().print(Out, Policy, Proto);
   Proto.clear();
@@ -932,6 +953,11 @@ void DeclPrinter::VisitVarDecl(VarDecl *D) {
 : D->getASTContext().getUnqualifiedObjCPointerType(D->getType());
 
   if (!Policy.SuppressSpecifiers) {
+if (const char *Lang = tryGetUnbracedLinkageLanguage(D)) {
+  // the "extern" specifier is implicit
+  assert(D->getStorageClass() == SC_None);
+  Out << "extern \"" << Lang << "\" ";
+}
 StorageClass SC = D->getStorageClass();
 if (SC != SC_None)
   Out << VarDecl::getStorageClassSpecifierString(SC) << " ";
@@ -961,7 +987,7 @@ void DeclPrinter::VisitVarDecl(VarDecl *D) {
 
   if (!Policy.SuppressTagKeyword && Policy.SuppressScope &&
   !Policy.SuppressUnwrittenScope)
-MaybePrintTagKeywordIfSupressingScopes(Policy, T, Out);
+maybePrintTagKeywordIfSupressingScopes(Policy, T, Out);
 
   printDeclType(T, (isa(D) && Policy.CleanUglifiedParameters &&
 D->getIdentifier())
@@ -1064,6 +1090,8 @@ void 
DeclPrinter::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) {
 
 void DeclPrinter::VisitEmptyDecl(EmptyDecl *D) {
   prettyPrintAttributes(D);
+  if (const char *Lang = tryGetUnbracedLinkageLanguage(D))
+Out << "extern \"" << Lang << "\";";
 }
 
 void DeclPrinter::VisitCXXRecordDecl(CXXRecordDecl *D) {
@@ -1136,22 +1164,21 @@ void DeclPrinter::VisitCXXRecordDecl(CXXRecordDecl *D) {
 }
 
 void DeclPrinter::VisitLinkageSpecDecl(LinkageSpecDecl *D) {
-  const char *l;
+  if (!D->hasBraces()) {
+