[clang] Rework the printing of attributes (PR #87281)
Vassil Vassilev via cfe-commits
cfe-commits at lists.llvm.org
Mon Apr 8 09:57:42 PDT 2024
https://github.com/vgvassilev updated https://github.com/llvm/llvm-project/pull/87281
>From 94f1c8653903cc3db55abd641c68a9dd11f05df3 Mon Sep 17 00:00:00 2001
From: Vassil Vassilev <v.g.vassilev at gmail.com>
Date: Mon, 1 Apr 2024 15:01:33 +0000
Subject: [PATCH 01/10] Revert "Remove extra switch from 0323938d"
This reverts commit 6c0b9e35761738726aded3b399db89eb0a86f82b.
---
clang/lib/AST/DeclPrinter.cpp | 1 +
1 file changed, 1 insertion(+)
diff --git a/clang/lib/AST/DeclPrinter.cpp b/clang/lib/AST/DeclPrinter.cpp
index edbcdfe4d55bc9..1ab74c71d0fd49 100644
--- a/clang/lib/AST/DeclPrinter.cpp
+++ b/clang/lib/AST/DeclPrinter.cpp
@@ -277,6 +277,7 @@ static bool canPrintOnLeftSide(const Attr *A) {
}
static bool mustPrintOnLeftSide(attr::Kind kind) {
+ switch (kind) {
#ifdef CLANG_ATTR_LIST_PrintOnLeft
switch (kind) {
CLANG_ATTR_LIST_PrintOnLeft
>From 871f5b06e0da167c4cf50d336bdc38f0eb684b6b Mon Sep 17 00:00:00 2001
From: Vassil Vassilev <v.g.vassilev at gmail.com>
Date: Mon, 1 Apr 2024 15:01:44 +0000
Subject: [PATCH 02/10] Revert "Fix warning in MSVC"
This reverts commit 0323938d3c7a1a48b60a7dea8ec7300e98b4a931.
---
clang/lib/AST/DeclPrinter.cpp | 20 +++-----------------
clang/utils/TableGen/ClangAttrEmitter.cpp | 11 +----------
2 files changed, 4 insertions(+), 27 deletions(-)
diff --git a/clang/lib/AST/DeclPrinter.cpp b/clang/lib/AST/DeclPrinter.cpp
index 1ab74c71d0fd49..c2e0edd5f1f12c 100644
--- a/clang/lib/AST/DeclPrinter.cpp
+++ b/clang/lib/AST/DeclPrinter.cpp
@@ -250,23 +250,13 @@ raw_ostream& DeclPrinter::Indent(unsigned Indentation) {
return Out;
}
-// For CLANG_ATTR_LIST_CanPrintOnLeft macro.
-#include "clang/Basic/AttrLeftSideCanPrintList.inc"
-
-// For CLANG_ATTR_LIST_PrintOnLeft macro.
-#include "clang/Basic/AttrLeftSideMustPrintList.inc"
-
static bool canPrintOnLeftSide(attr::Kind kind) {
-#ifdef CLANG_ATTR_LIST_CanPrintOnLeft
switch (kind) {
- CLANG_ATTR_LIST_CanPrintOnLeft
+#include "clang/Basic/AttrLeftSideCanPrintList.inc"
return true;
default:
return false;
}
-#else
- return false;
-#endif
}
static bool canPrintOnLeftSide(const Attr *A) {
@@ -278,16 +268,11 @@ static bool canPrintOnLeftSide(const Attr *A) {
static bool mustPrintOnLeftSide(attr::Kind kind) {
switch (kind) {
-#ifdef CLANG_ATTR_LIST_PrintOnLeft
- switch (kind) {
- CLANG_ATTR_LIST_PrintOnLeft
+#include "clang/Basic/AttrLeftSideMustPrintList.inc"
return true;
default:
return false;
}
-#else
- return false;
-#endif
}
static bool mustPrintOnLeftSide(const Attr *A) {
@@ -329,6 +314,7 @@ void DeclPrinter::prettyPrintAttributes(Decl *D, llvm::raw_ostream &Out,
VD->getInitStyle() == VarDecl::CallInit)
AttrLoc = AttrPrintLoc::Left;
}
+
// Only print the side matches the user requested.
if ((Loc & AttrLoc) != AttrPrintLoc::None)
A->printPretty(Out, Policy);
diff --git a/clang/utils/TableGen/ClangAttrEmitter.cpp b/clang/utils/TableGen/ClangAttrEmitter.cpp
index eb5c34d15693d7..985cc1aee579e9 100644
--- a/clang/utils/TableGen/ClangAttrEmitter.cpp
+++ b/clang/utils/TableGen/ClangAttrEmitter.cpp
@@ -3327,8 +3327,6 @@ void EmitClangAttrPrintList(const std::string &FieldName, RecordKeeper &Records,
std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr");
std::vector<Record *> PragmaAttrs;
- bool first = false;
-
for (auto *Attr : Attrs) {
if (!Attr->getValueAsBit("ASTNode"))
continue;
@@ -3336,15 +3334,8 @@ void EmitClangAttrPrintList(const std::string &FieldName, RecordKeeper &Records,
if (!Attr->getValueAsBit(FieldName))
continue;
- if (!first) {
- first = true;
- OS << "#define CLANG_ATTR_LIST_" << FieldName;
- }
-
- OS << " \\\n case attr::" << Attr->getName() << ":";
+ OS << "case attr::" << Attr->getName() << ":\n";
}
-
- OS << '\n';
}
// Emits the enumeration list for attributes.
>From e7e2e90da2a9644b0ca8a4c5c464c75a35f019a5 Mon Sep 17 00:00:00 2001
From: Vassil Vassilev <v.g.vassilev at gmail.com>
Date: Mon, 1 Apr 2024 15:11:28 +0000
Subject: [PATCH 03/10] Revert "Fix ast print of variables with attributes"
This reverts commit 46f3ade5083b8bfce55c78a21086a487eaac6f99.
---
clang/include/clang/Basic/Attr.td | 14 +-
clang/include/clang/Basic/CMakeLists.txt | 10 --
clang/lib/AST/DeclPrinter.cpp | 137 +++----------------
clang/test/AST/ast-print-attr-knr.c | 17 ---
clang/test/AST/ast-print-attr.c | 6 -
clang/test/AST/ast-print-method-decl.cpp | 2 +-
clang/test/AST/ast-print-pragmas.cpp | 4 +-
clang/test/Analysis/blocks.mm | 2 +-
clang/test/OpenMP/assumes_codegen.cpp | 22 +--
clang/test/OpenMP/assumes_print.cpp | 6 +-
clang/test/OpenMP/assumes_template_print.cpp | 20 +--
clang/test/OpenMP/declare_simd_ast_print.cpp | 4 +-
clang/test/Sema/attr-print.c | 3 +-
clang/test/SemaCXX/attr-print.cpp | 3 +-
clang/test/SemaCXX/cxx11-attr-print.cpp | 7 +-
clang/utils/TableGen/ClangAttrEmitter.cpp | 22 ---
clang/utils/TableGen/TableGen.cpp | 16 ---
clang/utils/TableGen/TableGenBackends.h | 2 -
18 files changed, 55 insertions(+), 242 deletions(-)
delete mode 100644 clang/test/AST/ast-print-attr-knr.c
diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td
index 3e03e55612645b..bb77f62405fbec 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -324,13 +324,10 @@ class Spelling<string name, string variety, int version = 1> {
}
class GNU<string name> : Spelling<name, "GNU">;
-class Declspec<string name> : Spelling<name, "Declspec"> {
- bit PrintOnLeft = 1;
-}
+class Declspec<string name> : Spelling<name, "Declspec">;
class Microsoft<string name> : Spelling<name, "Microsoft">;
class CXX11<string namespace, string name, int version = 1>
: Spelling<name, "CXX11", version> {
- bit CanPrintOnLeft = 0;
string Namespace = namespace;
}
class C23<string namespace, string name, int version = 1>
@@ -596,12 +593,6 @@ class AttrSubjectMatcherAggregateRule<AttrSubject subject> {
def SubjectMatcherForNamed : AttrSubjectMatcherAggregateRule<Named>;
class Attr {
- // Specifies that when printed, this attribute is meaningful on the
- // 'left side' of the declaration.
- bit CanPrintOnLeft = 1;
- // Specifies that when printed, this attribute is required to be printed on
- // the 'left side' of the declaration.
- bit PrintOnLeft = 0;
// The various ways in which an attribute can be spelled in source
list<Spelling> Spellings;
// The things to which an attribute can appertain
@@ -937,7 +928,6 @@ def AVRSignal : InheritableAttr, TargetSpecificAttr<TargetAVR> {
}
def AsmLabel : InheritableAttr {
- let CanPrintOnLeft = 0;
let Spellings = [CustomKeyword<"asm">, CustomKeyword<"__asm__">];
let Args = [
// Label specifies the mangled name for the decl.
@@ -1534,7 +1524,6 @@ def AllocSize : InheritableAttr {
}
def EnableIf : InheritableAttr {
- let CanPrintOnLeft = 0;
// Does not have a [[]] spelling because this attribute requires the ability
// to parse function arguments but the attribute is not written in the type
// position.
@@ -3149,7 +3138,6 @@ def Unavailable : InheritableAttr {
}
def DiagnoseIf : InheritableAttr {
- let CanPrintOnLeft = 0;
// Does not have a [[]] spelling because this attribute requires the ability
// to parse function arguments but the attribute is not written in the type
// position.
diff --git a/clang/include/clang/Basic/CMakeLists.txt b/clang/include/clang/Basic/CMakeLists.txt
index 7d53c751c13ac4..2ef6ddc68f4bf3 100644
--- a/clang/include/clang/Basic/CMakeLists.txt
+++ b/clang/include/clang/Basic/CMakeLists.txt
@@ -31,16 +31,6 @@ clang_tablegen(AttrList.inc -gen-clang-attr-list
SOURCE Attr.td
TARGET ClangAttrList)
-clang_tablegen(AttrLeftSideCanPrintList.inc -gen-clang-attr-can-print-left-list
- -I ${CMAKE_CURRENT_SOURCE_DIR}/../../
- SOURCE Attr.td
- TARGET ClangAttrCanPrintLeftList)
-
-clang_tablegen(AttrLeftSideMustPrintList.inc -gen-clang-attr-must-print-left-list
- -I ${CMAKE_CURRENT_SOURCE_DIR}/../../
- SOURCE Attr.td
- TARGET ClangAttrMustPrintLeftList)
-
clang_tablegen(AttrSubMatchRulesList.inc -gen-clang-attr-subject-match-rule-list
-I ${CMAKE_CURRENT_SOURCE_DIR}/../../
SOURCE Attr.td
diff --git a/clang/lib/AST/DeclPrinter.cpp b/clang/lib/AST/DeclPrinter.cpp
index c2e0edd5f1f12c..9aba0bec0b0cc2 100644
--- a/clang/lib/AST/DeclPrinter.cpp
+++ b/clang/lib/AST/DeclPrinter.cpp
@@ -49,18 +49,6 @@ namespace {
void PrintObjCTypeParams(ObjCTypeParamList *Params);
- enum class AttrPrintLoc {
- None = 0,
- Left = 1,
- Right = 2,
- Any = Left | Right,
-
- LLVM_MARK_AS_BITMASK_ENUM(/*DefaultValue=*/Any)
- };
-
- void prettyPrintAttributes(Decl *D, raw_ostream &out,
- AttrPrintLoc loc = AttrPrintLoc::Any);
-
public:
DeclPrinter(raw_ostream &Out, const PrintingPolicy &Policy,
const ASTContext &Context, unsigned Indentation = 0,
@@ -129,11 +117,7 @@ namespace {
const TemplateParameterList *Params);
void printTemplateArguments(llvm::ArrayRef<TemplateArgumentLoc> Args,
const TemplateParameterList *Params);
-
- inline void prettyPrintAttributes(Decl *D) {
- prettyPrintAttributes(D, Out);
- }
-
+ void prettyPrintAttributes(Decl *D);
void prettyPrintPragmas(Decl *D);
void printDeclType(QualType T, StringRef DeclName, bool Pack = false);
};
@@ -250,40 +234,7 @@ raw_ostream& DeclPrinter::Indent(unsigned Indentation) {
return Out;
}
-static bool canPrintOnLeftSide(attr::Kind kind) {
- switch (kind) {
-#include "clang/Basic/AttrLeftSideCanPrintList.inc"
- return true;
- default:
- return false;
- }
-}
-
-static bool canPrintOnLeftSide(const Attr *A) {
- if (A->isStandardAttributeSyntax())
- return false;
-
- return canPrintOnLeftSide(A->getKind());
-}
-
-static bool mustPrintOnLeftSide(attr::Kind kind) {
- switch (kind) {
-#include "clang/Basic/AttrLeftSideMustPrintList.inc"
- return true;
- default:
- return false;
- }
-}
-
-static bool mustPrintOnLeftSide(const Attr *A) {
- if (A->isDeclspecAttribute())
- return true;
-
- return mustPrintOnLeftSide(A->getKind());
-}
-
-void DeclPrinter::prettyPrintAttributes(Decl *D, llvm::raw_ostream &Out,
- AttrPrintLoc Loc) {
+void DeclPrinter::prettyPrintAttributes(Decl *D) {
if (Policy.PolishForDeclaration)
return;
@@ -292,32 +243,15 @@ void DeclPrinter::prettyPrintAttributes(Decl *D, llvm::raw_ostream &Out,
for (auto *A : Attrs) {
if (A->isInherited() || A->isImplicit())
continue;
-
- AttrPrintLoc AttrLoc = AttrPrintLoc::Right;
- if (mustPrintOnLeftSide(A)) {
- // If we must always print on left side (e.g. declspec), then mark as
- // so.
- AttrLoc = AttrPrintLoc::Left;
- } else if (canPrintOnLeftSide(A)) {
- // For functions with body defined we print the attributes on the left
- // side so that GCC accept our dumps as well.
- if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
- FD && FD->isThisDeclarationADefinition())
- // In case Decl is a function with a body, then attrs should be print
- // on the left side.
- AttrLoc = AttrPrintLoc::Left;
-
- // In case it is a variable declaration with a ctor, then allow
- // printing on the left side for readbility.
- else if (const VarDecl *VD = dyn_cast<VarDecl>(D);
- VD && VD->getInit() &&
- VD->getInitStyle() == VarDecl::CallInit)
- AttrLoc = AttrPrintLoc::Left;
- }
-
- // Only print the side matches the user requested.
- if ((Loc & AttrLoc) != AttrPrintLoc::None)
+ switch (A->getKind()) {
+#define ATTR(X)
+#define PRAGMA_SPELLING_ATTR(X) case attr::X:
+#include "clang/Basic/AttrList.inc"
+ break;
+ default:
A->printPretty(Out, Policy);
+ break;
+ }
}
}
}
@@ -689,22 +623,6 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
printTemplateParameters(D->getTemplateParameterList(I));
}
- std::string LeftsideAttrs;
- llvm::raw_string_ostream LSAS(LeftsideAttrs);
-
- prettyPrintAttributes(D, LSAS, AttrPrintLoc::Left);
-
- // prettyPrintAttributes print a space on left side of the attribute.
- if (LeftsideAttrs[0] == ' ') {
- // Skip the space prettyPrintAttributes generated.
- LeftsideAttrs.erase(0, LeftsideAttrs.find_first_not_of(' '));
-
- // Add a single space between the attribute and the Decl name.
- LSAS << ' ';
- }
-
- Out << LeftsideAttrs;
-
CXXConstructorDecl *CDecl = dyn_cast<CXXConstructorDecl>(D);
CXXConversionDecl *ConversionDecl = dyn_cast<CXXConversionDecl>(D);
CXXDeductionGuideDecl *GuideDecl = dyn_cast<CXXDeductionGuideDecl>(D);
@@ -870,7 +788,7 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
Ty.print(Out, Policy, Proto);
}
- prettyPrintAttributes(D, Out, AttrPrintLoc::Right);
+ prettyPrintAttributes(D);
if (D->isPureVirtual())
Out << " = 0";
@@ -967,23 +885,6 @@ void DeclPrinter::VisitVarDecl(VarDecl *D) {
Param && Param->isExplicitObjectParameter())
Out << "this ";
- std::string LeftSide;
- llvm::raw_string_ostream LeftSideStream(LeftSide);
-
- // Print attributes that should be placed on the left, such as __declspec.
- prettyPrintAttributes(D, LeftSideStream, AttrPrintLoc::Left);
-
- // prettyPrintAttributes print a space on left side of the attribute.
- if (LeftSide[0] == ' ') {
- // Skip the space prettyPrintAttributes generated.
- LeftSide.erase(0, LeftSide.find_first_not_of(' '));
-
- // Add a single space between the attribute and the Decl name.
- LeftSideStream << ' ';
- }
-
- Out << LeftSide;
-
QualType T = D->getTypeSourceInfo()
? D->getTypeSourceInfo()->getType()
: D->getASTContext().getUnqualifiedObjCPointerType(D->getType());
@@ -1016,21 +917,14 @@ void DeclPrinter::VisitVarDecl(VarDecl *D) {
}
}
- StringRef Name;
-
- Name = (isa<ParmVarDecl>(D) && Policy.CleanUglifiedParameters &&
- D->getIdentifier())
- ? D->getIdentifier()->deuglifiedName()
- : D->getName();
-
if (!Policy.SuppressTagKeyword && Policy.SuppressScope &&
!Policy.SuppressUnwrittenScope)
MaybePrintTagKeywordIfSupressingScopes(Policy, T, Out);
- printDeclType(T, Name);
- // Print the attributes that should be placed right before the end of the
- // decl.
- prettyPrintAttributes(D, Out, AttrPrintLoc::Right);
+ printDeclType(T, (isa<ParmVarDecl>(D) && Policy.CleanUglifiedParameters &&
+ D->getIdentifier())
+ ? D->getIdentifier()->deuglifiedName()
+ : D->getName());
Expr *Init = D->getInit();
if (!Policy.SuppressInitializers && Init) {
@@ -1060,6 +954,7 @@ void DeclPrinter::VisitVarDecl(VarDecl *D) {
Out << ")";
}
}
+ prettyPrintAttributes(D);
}
void DeclPrinter::VisitParmVarDecl(ParmVarDecl *D) {
diff --git a/clang/test/AST/ast-print-attr-knr.c b/clang/test/AST/ast-print-attr-knr.c
deleted file mode 100644
index d7a53f958669f3..00000000000000
--- a/clang/test/AST/ast-print-attr-knr.c
+++ /dev/null
@@ -1,17 +0,0 @@
-// This file contain tests for attribute arguments on K&R functions.
-
-// RUN: %clang_cc1 -ast-print -x c -std=c89 -fms-extensions %s -o - | FileCheck %s
-
-// CHECK: int knr(i)
-// CHECK-NEXT: int i __attribute__((unused));
-// CHECK-NEXT: {
-// CHECK-NEXT: return 0;
-// CHECK-NEXT: }
-int knr(i) int i __attribute__((unused)); { return 0; }
-
-// CHECK: __attribute__((unused)) int knr2(i)
-// CHECK-NEXT: int i;
-// CHECK-NEXT: {
-// CHECK-NEXT: return 0;
-// CHECK-NEXT: }
-__attribute__((unused)) int knr2(i) int i; { return 0; }
diff --git a/clang/test/AST/ast-print-attr.c b/clang/test/AST/ast-print-attr.c
index 8e047f16bb16ca..4140ae6ac11fe3 100644
--- a/clang/test/AST/ast-print-attr.c
+++ b/clang/test/AST/ast-print-attr.c
@@ -32,9 +32,3 @@ int *fun_returns() __attribute__((ownership_returns(fun_returns)));
// CHECK: void fun_holds(int *a) __attribute__((ownership_holds(fun_holds, 1)));
void fun_holds(int *a) __attribute__((ownership_holds(fun_holds, 1)));
-
-// CHECK: int fun_var_unused() {
-// CHECK-NEXT: int x __attribute__((unused)) = 0;
-// CHECK-NEXT: return x;
-// CHECK-NEXT: }
-int fun_var_unused() { int x __attribute__((unused)) = 0; return x; }
diff --git a/clang/test/AST/ast-print-method-decl.cpp b/clang/test/AST/ast-print-method-decl.cpp
index 75dea0cac16be1..cb5d10096381a9 100644
--- a/clang/test/AST/ast-print-method-decl.cpp
+++ b/clang/test/AST/ast-print-method-decl.cpp
@@ -94,7 +94,7 @@ struct DefMethodsWithoutBody {
// CHECK-NEXT: DefMethodsWithoutBody() = default;
~DefMethodsWithoutBody() = default;
- // CHECK-NEXT: __attribute__((alias("X"))) void m1();
+ // CHECK-NEXT: void m1() __attribute__((alias("X")));
void m1() __attribute__((alias("X")));
// CHECK-NEXT: };
diff --git a/clang/test/AST/ast-print-pragmas.cpp b/clang/test/AST/ast-print-pragmas.cpp
index 5059c5710189ee..5f27ff71b4ee8b 100644
--- a/clang/test/AST/ast-print-pragmas.cpp
+++ b/clang/test/AST/ast-print-pragmas.cpp
@@ -93,7 +93,7 @@ void test_templates(int *List, int Length) {
#ifdef MS_EXT
#pragma init_seg(compiler)
// MS-EXT: #pragma init_seg (.CRT$XCC){{$}}
-// MS-EXT-NEXT: __declspec(thread) int x = 3;
-__declspec(thread) int x = 3;
+// MS-EXT-NEXT: int x = 3 __declspec(thread);
+int __declspec(thread) x = 3;
#endif //MS_EXT
diff --git a/clang/test/Analysis/blocks.mm b/clang/test/Analysis/blocks.mm
index 3ac11aa5a620ed..81db705b6afbc2 100644
--- a/clang/test/Analysis/blocks.mm
+++ b/clang/test/Analysis/blocks.mm
@@ -78,7 +78,7 @@ void testBlockWithCaptureByReference() {
// CHECK-NEXT: 1: 5
// WARNINGS-NEXT: 2: [B1.1] (CXXConstructExpr, StructWithCopyConstructor)
// ANALYZER-NEXT: 2: [B1.1] (CXXConstructExpr, [B1.3], StructWithCopyConstructor)
-// CHECK-NEXT: 3: __attribute__((blocks("byref"))) StructWithCopyConstructor s(5);
+// CHECK-NEXT: 3: StructWithCopyConstructor s(5) __attribute__((blocks("byref")));
// CHECK-NEXT: 4: ^{ }
// CHECK-NEXT: 5: (void)([B1.4]) (CStyleCastExpr, ToVoid, void)
// CHECK-NEXT: Preds (1): B2
diff --git a/clang/test/OpenMP/assumes_codegen.cpp b/clang/test/OpenMP/assumes_codegen.cpp
index 6a5871c303aade..5d8a2ae909a768 100644
--- a/clang/test/OpenMP/assumes_codegen.cpp
+++ b/clang/test/OpenMP/assumes_codegen.cpp
@@ -67,41 +67,41 @@ int lambda_outer() {
}
#pragma omp end assumes
-// AST: __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) void foo() {
+// AST: void foo() __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) {
// AST-NEXT: }
// AST-NEXT: class BAR {
// AST-NEXT: public:
-// AST-NEXT: __attribute__((assume("ompx_range_bar_only"))) __attribute__((assume("ompx_range_bar_only_2"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) BAR() {
+// AST-NEXT: BAR() __attribute__((assume("ompx_range_bar_only"))) __attribute__((assume("ompx_range_bar_only_2"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) {
// AST-NEXT: }
-// AST-NEXT: __attribute__((assume("ompx_range_bar_only"))) __attribute__((assume("ompx_range_bar_only_2"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) void bar1() {
+// AST-NEXT: void bar1() __attribute__((assume("ompx_range_bar_only"))) __attribute__((assume("ompx_range_bar_only_2"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) {
// AST-NEXT: }
-// AST-NEXT: __attribute__((assume("ompx_range_bar_only"))) __attribute__((assume("ompx_range_bar_only_2"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) static void bar2() {
+// AST-NEXT: static void bar2() __attribute__((assume("ompx_range_bar_only"))) __attribute__((assume("ompx_range_bar_only_2"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) {
// AST-NEXT: }
// AST-NEXT: };
-// AST-NEXT: __attribute__((assume("ompx_range_bar_only"))) __attribute__((assume("ompx_range_bar_only_2"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) void bar() {
+// AST-NEXT: void bar() __attribute__((assume("ompx_range_bar_only"))) __attribute__((assume("ompx_range_bar_only_2"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) {
// AST-NEXT: BAR b;
// AST-NEXT: }
// AST-NEXT: void baz() __attribute__((assume("ompx_1234"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp")));
// AST-NEXT: template <typename T> class BAZ {
// AST-NEXT: public:
-// AST-NEXT: __attribute__((assume("ompx_1234"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) BAZ<T>() {
+// AST-NEXT: BAZ<T>() __attribute__((assume("ompx_1234"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) {
// AST-NEXT: }
-// AST-NEXT: __attribute__((assume("ompx_1234"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) void baz1() {
+// AST-NEXT: void baz1() __attribute__((assume("ompx_1234"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) {
// AST-NEXT: }
-// AST-NEXT: __attribute__((assume("ompx_1234"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) static void baz2() {
+// AST-NEXT: static void baz2() __attribute__((assume("ompx_1234"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) {
// AST-NEXT: }
// AST-NEXT: };
// AST-NEXT: template<> class BAZ<float> {
// AST-NEXT: public:
-// AST-NEXT: __attribute__((assume("ompx_1234"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) BAZ() {
+// AST-NEXT: BAZ() __attribute__((assume("ompx_1234"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) {
// AST-NEXT: }
// AST-NEXT: void baz1() __attribute__((assume("ompx_1234"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp")));
// AST-NEXT: static void baz2() __attribute__((assume("ompx_1234"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp")));
// AST-NEXT: };
-// AST-NEXT: __attribute__((assume("ompx_1234"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) void baz() {
+// AST-NEXT: void baz() __attribute__((assume("ompx_1234"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) {
// AST-NEXT: BAZ<float> b;
// AST-NEXT: }
-// AST-NEXT: __attribute__((assume("ompx_lambda_assumption"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) int lambda_outer() {
+// AST-NEXT: int lambda_outer() __attribute__((assume("ompx_lambda_assumption"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) {
// AST-NEXT: auto lambda_inner = []() {
// AST-NEXT: return 42;
// AST-NEXT: };
diff --git a/clang/test/OpenMP/assumes_print.cpp b/clang/test/OpenMP/assumes_print.cpp
index a7f04edb3b1af4..eaaf55ccfd05de 100644
--- a/clang/test/OpenMP/assumes_print.cpp
+++ b/clang/test/OpenMP/assumes_print.cpp
@@ -37,8 +37,8 @@ void baz() {
}
#pragma omp end assumes
-// CHECK: __attribute__((assume("omp_no_openmp_routines"))) __attribute__((assume("omp_no_openmp"))) void foo()
-// CHECK: __attribute__((assume("ompx_range_bar_only"))) __attribute__((assume("ompx_range_bar_only_2"))) __attribute__((assume("omp_no_openmp_routines"))) __attribute__((assume("omp_no_openmp"))) void bar()
-// CHECK: __attribute__((assume("ompx_1234"))) __attribute__((assume("omp_no_openmp_routines"))) __attribute__((assume("omp_no_openmp"))) void baz()
+// CHECK: void foo() __attribute__((assume("omp_no_openmp_routines"))) __attribute__((assume("omp_no_openmp")))
+// CHECK: void bar() __attribute__((assume("ompx_range_bar_only"))) __attribute__((assume("ompx_range_bar_only_2"))) __attribute__((assume("omp_no_openmp_routines"))) __attribute__((assume("omp_no_openmp")))
+// CHECK: void baz() __attribute__((assume("ompx_1234"))) __attribute__((assume("omp_no_openmp_routines"))) __attribute__((assume("omp_no_openmp")))
#endif
diff --git a/clang/test/OpenMP/assumes_template_print.cpp b/clang/test/OpenMP/assumes_template_print.cpp
index bd1100fbefffc6..c73095e6f771f3 100644
--- a/clang/test/OpenMP/assumes_template_print.cpp
+++ b/clang/test/OpenMP/assumes_template_print.cpp
@@ -17,7 +17,7 @@ template <typename T>
struct S {
int a;
// CHECK: template <typename T> struct S {
-// CHECK: __attribute__((assume("ompx_global_assumption"))) void foo() {
+// CHECK: void foo() __attribute__((assume("ompx_global_assumption"))) {
void foo() {
#pragma omp parallel
{}
@@ -25,15 +25,15 @@ struct S {
};
// CHECK: template<> struct S<int> {
-// CHECK: __attribute__((assume("ompx_global_assumption"))) void foo() {
+// CHECK: void foo() __attribute__((assume("ompx_global_assumption"))) {
#pragma omp begin assumes no_openmp
-// CHECK: __attribute__((assume("omp_no_openmp"))) __attribute__((assume("ompx_global_assumption"))) void S_with_assumes_no_call() {
+// CHECK: void S_with_assumes_no_call() __attribute__((assume("omp_no_openmp"))) __attribute__((assume("ompx_global_assumption"))) {
void S_with_assumes_no_call() {
S<int> s;
s.a = 0;
}
-// CHECK: __attribute__((assume("omp_no_openmp"))) __attribute__((assume("ompx_global_assumption"))) void S_with_assumes_call() {
+// CHECK: void S_with_assumes_call() __attribute__((assume("omp_no_openmp"))) __attribute__((assume("ompx_global_assumption"))) {
void S_with_assumes_call() {
S<int> s;
s.a = 0;
@@ -42,7 +42,7 @@ void S_with_assumes_call() {
}
#pragma omp end assumes
-// CHECK: __attribute__((assume("ompx_global_assumption"))) void S_without_assumes() {
+// CHECK: void S_without_assumes() __attribute__((assume("ompx_global_assumption"))) {
void S_without_assumes() {
S<int> s;
s.foo();
@@ -54,7 +54,7 @@ void S_without_assumes() {
template <typename T>
struct P {
// CHECK: template <typename T> struct P {
-// CHECK: __attribute__((assume("ompx_global_assumption"))) void foo() {
+// CHECK: void foo() __attribute__((assume("ompx_global_assumption"))) {
int a;
void foo() {
#pragma omp parallel
@@ -65,21 +65,21 @@ struct P {
// TODO: Avoid the duplication here:
// CHECK: template<> struct P<int> {
-// CHECK: __attribute__((assume("ompx_global_assumption"))) __attribute__((assume("ompx_global_assumption"))) void foo() {
+// CHECK: void foo() __attribute__((assume("ompx_global_assumption"))) __attribute__((assume("ompx_global_assumption"))) {
-// CHECK: __attribute__((assume("ompx_global_assumption"))) void P_without_assumes() {
+// CHECK: void P_without_assumes() __attribute__((assume("ompx_global_assumption"))) {
void P_without_assumes() {
P<int> p;
p.foo();
}
#pragma omp begin assumes no_openmp
-// CHECK: __attribute__((assume("omp_no_openmp"))) __attribute__((assume("ompx_global_assumption"))) void P_with_assumes_no_call() {
+// CHECK: void P_with_assumes_no_call() __attribute__((assume("omp_no_openmp"))) __attribute__((assume("ompx_global_assumption"))) {
void P_with_assumes_no_call() {
P<int> p;
p.a = 0;
}
-// CHECK: __attribute__((assume("omp_no_openmp"))) __attribute__((assume("ompx_global_assumption"))) void P_with_assumes_call() {
+// CHECK: void P_with_assumes_call() __attribute__((assume("omp_no_openmp"))) __attribute__((assume("ompx_global_assumption"))) {
void P_with_assumes_call() {
P<int> p;
p.a = 0;
diff --git a/clang/test/OpenMP/declare_simd_ast_print.cpp b/clang/test/OpenMP/declare_simd_ast_print.cpp
index 1adf95226c8beb..565dc2dfc04d11 100644
--- a/clang/test/OpenMP/declare_simd_ast_print.cpp
+++ b/clang/test/OpenMP/declare_simd_ast_print.cpp
@@ -60,11 +60,11 @@ void h(int *hp, int *hp2, int *hq, int *lin)
class VV {
// CHECK: #pragma omp declare simd uniform(this, a) linear(val(b): a)
- // CHECK-NEXT: __attribute__((cold)) int add(int a, int b) {
+ // CHECK-NEXT: int add(int a, int b) __attribute__((cold)) {
// CHECK-NEXT: return a + b;
// CHECK-NEXT: }
#pragma omp declare simd uniform(this, a) linear(val(b): a)
- __attribute__((cold)) int add(int a, int b) { return a + b; }
+ int add(int a, int b) __attribute__((cold)) { return a + b; }
// CHECK: #pragma omp declare simd aligned(b: 4) aligned(a) linear(ref(b): 4) linear(val(this)) linear(val(a))
// CHECK-NEXT: float taddpf(float *a, float *&b) {
diff --git a/clang/test/Sema/attr-print.c b/clang/test/Sema/attr-print.c
index 8492356e5d2e57..e12c0109efcd9a 100644
--- a/clang/test/Sema/attr-print.c
+++ b/clang/test/Sema/attr-print.c
@@ -3,7 +3,8 @@
// CHECK: int x __attribute__((aligned(4)));
int x __attribute__((aligned(4)));
-// CHECK: __declspec(align(4)) int y;
+// FIXME: Print this at a valid location for a __declspec attr.
+// CHECK: int y __declspec(align(4));
__declspec(align(4)) int y;
// CHECK: short arr[3] __attribute__((aligned));
diff --git a/clang/test/SemaCXX/attr-print.cpp b/clang/test/SemaCXX/attr-print.cpp
index c7c58a25504eed..fc11365d14a214 100644
--- a/clang/test/SemaCXX/attr-print.cpp
+++ b/clang/test/SemaCXX/attr-print.cpp
@@ -3,7 +3,8 @@
// CHECK: int x __attribute__((aligned(4)));
int x __attribute__((aligned(4)));
-// CHECK: __declspec(align(4)) int y;
+// FIXME: Print this at a valid location for a __declspec attr.
+// CHECK: int y __declspec(align(4));
__declspec(align(4)) int y;
// CHECK: int foo() __attribute__((const));
diff --git a/clang/test/SemaCXX/cxx11-attr-print.cpp b/clang/test/SemaCXX/cxx11-attr-print.cpp
index c988972aeb1a5a..e017c8b08b1ddd 100644
--- a/clang/test/SemaCXX/cxx11-attr-print.cpp
+++ b/clang/test/SemaCXX/cxx11-attr-print.cpp
@@ -3,7 +3,8 @@
// CHECK: int x __attribute__((aligned(4)));
int x __attribute__((aligned(4)));
-// CHECK: __declspec(align(4)) int y;
+// FIXME: Print this at a valid location for a __declspec attr.
+// CHECK: int y __declspec(align(4));
__declspec(align(4)) int y;
// CHECK: int z {{\[}}[gnu::aligned(4)]];
@@ -65,7 +66,7 @@ void f8 (void *, const char *, ...) __attribute__ ((format (printf, 2, 3)));
// CHECK: int m __attribute__((aligned(4
// CHECK: int n alignas(4
// CHECK: int p alignas(int
-// CHECK: __attribute__((pure)) static int f()
+// CHECK: static int f() __attribute__((pure))
// CHECK: static int g() {{\[}}[gnu::pure]]
template <typename T> struct S {
__attribute__((aligned(4))) int m;
@@ -81,7 +82,7 @@ template <typename T> struct S {
// CHECK: int m __attribute__((aligned(4
// CHECK: int n alignas(4
-// CHECK: __attribute__((pure)) static int f()
+// CHECK: static int f() __attribute__((pure))
// CHECK: static int g() {{\[}}[gnu::pure]]
template struct S<int>;
diff --git a/clang/utils/TableGen/ClangAttrEmitter.cpp b/clang/utils/TableGen/ClangAttrEmitter.cpp
index 985cc1aee579e9..9d2e906573443b 100644
--- a/clang/utils/TableGen/ClangAttrEmitter.cpp
+++ b/clang/utils/TableGen/ClangAttrEmitter.cpp
@@ -3316,28 +3316,6 @@ void EmitClangAttrList(RecordKeeper &Records, raw_ostream &OS) {
OS << "#undef PRAGMA_SPELLING_ATTR\n";
}
-// Emits the enumeration list for attributes.
-void EmitClangAttrPrintList(const std::string &FieldName, RecordKeeper &Records,
- raw_ostream &OS) {
- emitSourceFileHeader(
- "List of attributes that can be print on the left side of a decl", OS,
- Records);
-
- AttrClassHierarchy Hierarchy(Records);
-
- std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr");
- std::vector<Record *> PragmaAttrs;
- for (auto *Attr : Attrs) {
- if (!Attr->getValueAsBit("ASTNode"))
- continue;
-
- if (!Attr->getValueAsBit(FieldName))
- continue;
-
- OS << "case attr::" << Attr->getName() << ":\n";
- }
-}
-
// Emits the enumeration list for attributes.
void EmitClangAttrSubjectMatchRuleList(RecordKeeper &Records, raw_ostream &OS) {
emitSourceFileHeader(
diff --git a/clang/utils/TableGen/TableGen.cpp b/clang/utils/TableGen/TableGen.cpp
index 3f22e43b97ecd2..42cc704543f18e 100644
--- a/clang/utils/TableGen/TableGen.cpp
+++ b/clang/utils/TableGen/TableGen.cpp
@@ -31,8 +31,6 @@ enum ActionType {
GenClangAttrSubjectMatchRulesParserStringSwitches,
GenClangAttrImpl,
GenClangAttrList,
- GenClangAttrCanPrintLeftList,
- GenClangAttrMustPrintLeftList,
GenClangAttrDocTable,
GenClangAttrSubjectMatchRuleList,
GenClangAttrPCHRead,
@@ -134,14 +132,6 @@ cl::opt<ActionType> Action(
"Generate clang attribute implementations"),
clEnumValN(GenClangAttrList, "gen-clang-attr-list",
"Generate a clang attribute list"),
- clEnumValN(GenClangAttrCanPrintLeftList,
- "gen-clang-attr-can-print-left-list",
- "Generate list of attributes that can be printed on left "
- "side of a decl"),
- clEnumValN(GenClangAttrMustPrintLeftList,
- "gen-clang-attr-must-print-left-list",
- "Generate list of attributes that must be printed on left "
- "side of a decl"),
clEnumValN(GenClangAttrDocTable, "gen-clang-attr-doc-table",
"Generate a table of attribute documentation"),
clEnumValN(GenClangAttrSubjectMatchRuleList,
@@ -345,12 +335,6 @@ bool ClangTableGenMain(raw_ostream &OS, RecordKeeper &Records) {
case GenClangAttrList:
EmitClangAttrList(Records, OS);
break;
- case GenClangAttrCanPrintLeftList:
- EmitClangAttrPrintList("CanPrintOnLeft", Records, OS);
- break;
- case GenClangAttrMustPrintLeftList:
- EmitClangAttrPrintList("PrintOnLeft", Records, OS);
- break;
case GenClangAttrDocTable:
EmitClangAttrDocTable(Records, OS);
break;
diff --git a/clang/utils/TableGen/TableGenBackends.h b/clang/utils/TableGen/TableGenBackends.h
index ecd506b7b6b50a..5f2dd257cb90a9 100644
--- a/clang/utils/TableGen/TableGenBackends.h
+++ b/clang/utils/TableGen/TableGenBackends.h
@@ -47,8 +47,6 @@ void EmitClangAttrSubjectMatchRulesParserStringSwitches(
void EmitClangAttrClass(llvm::RecordKeeper &Records, llvm::raw_ostream &OS);
void EmitClangAttrImpl(llvm::RecordKeeper &Records, llvm::raw_ostream &OS);
void EmitClangAttrList(llvm::RecordKeeper &Records, llvm::raw_ostream &OS);
-void EmitClangAttrPrintList(const std::string &FieldName,
- llvm::RecordKeeper &Records, llvm::raw_ostream &OS);
void EmitClangAttrSubjectMatchRuleList(llvm::RecordKeeper &Records,
llvm::raw_ostream &OS);
void EmitClangAttrPCHRead(llvm::RecordKeeper &Records, llvm::raw_ostream &OS);
>From 551e75c1513c300c5b99f43cee6b1b87481b90f3 Mon Sep 17 00:00:00 2001
From: Vassil Vassilev <v.g.vassilev at gmail.com>
Date: Mon, 1 Apr 2024 19:27:39 +0000
Subject: [PATCH 04/10] Rework the printing of attributes.
Commit llvm/llvm-project at 46f3ade introduced a notion of printing the attributes
on the left to improve the printing of attributes attached to variable
declarations. The intent was to produce more GCC compatible code because clang
tends to print the attributes on the right hand side which is not accepted by
gcc.
This approach has increased the complexity in tablegen and the attrubutes
themselves as now the are supposed to know where they could appear. That lead to
mishandling of the `override` keyword which is modelled as an attribute in clang.
This patch takes an inspiration from the existing approach and tries to keep
the position of the attributes as they were written. To do so we use simpler
heuristic which checks if the source locations of the attribute precedes the
declaration. If so, it is considered to be printed before the declaration.
Fixes llvm/llvm-project#87151
---
clang/lib/AST/DeclPrinter.cpp | 44 +++++++++++++++++++----
clang/lib/AST/StmtPrinter.cpp | 5 ++-
clang/test/AST/ast-print-attr-knr.c | 17 +++++++++
clang/test/AST/ast-print-attr.c | 6 ++++
clang/test/AST/ast-print-no-sanitize.cpp | 2 +-
clang/test/AST/ast-print-pragmas.cpp | 4 +--
clang/test/Analysis/blocks.mm | 2 +-
clang/test/Analysis/scopes-cfg-output.cpp | 2 +-
clang/test/Sema/attr-print.c | 3 +-
clang/test/SemaCXX/attr-no-sanitize.cpp | 6 ++--
clang/test/SemaCXX/attr-print.cpp | 3 +-
clang/test/SemaCXX/cxx11-attr-print.cpp | 15 ++++----
clang/utils/TableGen/ClangAttrEmitter.cpp | 6 ++--
13 files changed, 84 insertions(+), 31 deletions(-)
create mode 100644 clang/test/AST/ast-print-attr-knr.c
diff --git a/clang/lib/AST/DeclPrinter.cpp b/clang/lib/AST/DeclPrinter.cpp
index 9aba0bec0b0cc2..02cea3c9ae9471 100644
--- a/clang/lib/AST/DeclPrinter.cpp
+++ b/clang/lib/AST/DeclPrinter.cpp
@@ -21,6 +21,7 @@
#include "clang/AST/ExprCXX.h"
#include "clang/AST/PrettyPrinter.h"
#include "clang/Basic/Module.h"
+#include "clang/Basic/SourceManager.h"
#include "llvm/Support/raw_ostream.h"
using namespace clang;
@@ -117,7 +118,10 @@ namespace {
const TemplateParameterList *Params);
void printTemplateArguments(llvm::ArrayRef<TemplateArgumentLoc> Args,
const TemplateParameterList *Params);
- void prettyPrintAttributes(Decl *D);
+ enum class AttrPosAsWritten { Default = 0, Left, Right };
+ void
+ prettyPrintAttributes(const Decl *D,
+ AttrPosAsWritten Pos = AttrPosAsWritten::Default);
void prettyPrintPragmas(Decl *D);
void printDeclType(QualType T, StringRef DeclName, bool Pack = false);
};
@@ -234,12 +238,27 @@ raw_ostream& DeclPrinter::Indent(unsigned Indentation) {
return Out;
}
-void DeclPrinter::prettyPrintAttributes(Decl *D) {
+static DeclPrinter::AttrPosAsWritten getPosAsWritten(const Attr *A,
+ const Decl *D) {
+ SourceLocation ALoc = A->getLoc();
+ SourceLocation DLoc = D->getLocation();
+ const ASTContext &C = D->getASTContext();
+ if (ALoc.isInvalid() || DLoc.isInvalid())
+ return DeclPrinter::AttrPosAsWritten::Default;
+
+ if (C.getSourceManager().isBeforeInTranslationUnit(ALoc, DLoc))
+ return DeclPrinter::AttrPosAsWritten::Left;
+
+ return DeclPrinter::AttrPosAsWritten::Right;
+}
+
+void DeclPrinter::prettyPrintAttributes(const Decl *D,
+ AttrPosAsWritten Pos /*=Default*/) {
if (Policy.PolishForDeclaration)
return;
if (D->hasAttrs()) {
- AttrVec &Attrs = D->getAttrs();
+ const AttrVec &Attrs = D->getAttrs();
for (auto *A : Attrs) {
if (A->isInherited() || A->isImplicit())
continue;
@@ -249,7 +268,13 @@ void DeclPrinter::prettyPrintAttributes(Decl *D) {
#include "clang/Basic/AttrList.inc"
break;
default:
- A->printPretty(Out, Policy);
+ if (Pos == AttrPosAsWritten::Default || Pos == getPosAsWritten(A, D)) {
+ if (Pos != AttrPosAsWritten::Left)
+ Out << " ";
+ A->printPretty(Out, Policy);
+ if (Pos == AttrPosAsWritten::Left)
+ Out << " ";
+ }
break;
}
}
@@ -612,8 +637,10 @@ static void MaybePrintTagKeywordIfSupressingScopes(PrintingPolicy &Policy,
void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
if (!D->getDescribedFunctionTemplate() &&
- !D->isFunctionTemplateSpecialization())
+ !D->isFunctionTemplateSpecialization()) {
prettyPrintPragmas(D);
+ prettyPrintAttributes(D, AttrPosAsWritten::Left);
+ }
if (D->isFunctionTemplateSpecialization())
Out << "template<> ";
@@ -788,7 +815,7 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
Ty.print(Out, Policy, Proto);
}
- prettyPrintAttributes(D);
+ prettyPrintAttributes(D, AttrPosAsWritten::Right);
if (D->isPureVirtual())
Out << " = 0";
@@ -881,6 +908,8 @@ void DeclPrinter::VisitLabelDecl(LabelDecl *D) {
void DeclPrinter::VisitVarDecl(VarDecl *D) {
prettyPrintPragmas(D);
+ prettyPrintAttributes(D, AttrPosAsWritten::Left);
+
if (const auto *Param = dyn_cast<ParmVarDecl>(D);
Param && Param->isExplicitObjectParameter())
Out << "this ";
@@ -926,6 +955,8 @@ void DeclPrinter::VisitVarDecl(VarDecl *D) {
? D->getIdentifier()->deuglifiedName()
: D->getName());
+ prettyPrintAttributes(D, AttrPosAsWritten::Right);
+
Expr *Init = D->getInit();
if (!Policy.SuppressInitializers && Init) {
bool ImplicitInit = false;
@@ -954,7 +985,6 @@ void DeclPrinter::VisitVarDecl(VarDecl *D) {
Out << ")";
}
}
- prettyPrintAttributes(D);
}
void DeclPrinter::VisitParmVarDecl(ParmVarDecl *D) {
diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp
index d66c3ccce2094c..aac926c056bf0d 100644
--- a/clang/lib/AST/StmtPrinter.cpp
+++ b/clang/lib/AST/StmtPrinter.cpp
@@ -292,8 +292,11 @@ void StmtPrinter::VisitLabelStmt(LabelStmt *Node) {
}
void StmtPrinter::VisitAttributedStmt(AttributedStmt *Node) {
- for (const auto *Attr : Node->getAttrs()) {
+ llvm::ArrayRef<const Attr *> Attrs = Node->getAttrs();
+ for (const auto *Attr : Attrs) {
Attr->printPretty(OS, Policy);
+ if (Attr != Attrs.back())
+ OS << " ";
}
PrintStmt(Node->getSubStmt(), 0);
diff --git a/clang/test/AST/ast-print-attr-knr.c b/clang/test/AST/ast-print-attr-knr.c
new file mode 100644
index 00000000000000..d7a53f958669f3
--- /dev/null
+++ b/clang/test/AST/ast-print-attr-knr.c
@@ -0,0 +1,17 @@
+// This file contain tests for attribute arguments on K&R functions.
+
+// RUN: %clang_cc1 -ast-print -x c -std=c89 -fms-extensions %s -o - | FileCheck %s
+
+// CHECK: int knr(i)
+// CHECK-NEXT: int i __attribute__((unused));
+// CHECK-NEXT: {
+// CHECK-NEXT: return 0;
+// CHECK-NEXT: }
+int knr(i) int i __attribute__((unused)); { return 0; }
+
+// CHECK: __attribute__((unused)) int knr2(i)
+// CHECK-NEXT: int i;
+// CHECK-NEXT: {
+// CHECK-NEXT: return 0;
+// CHECK-NEXT: }
+__attribute__((unused)) int knr2(i) int i; { return 0; }
diff --git a/clang/test/AST/ast-print-attr.c b/clang/test/AST/ast-print-attr.c
index 4140ae6ac11fe3..8e047f16bb16ca 100644
--- a/clang/test/AST/ast-print-attr.c
+++ b/clang/test/AST/ast-print-attr.c
@@ -32,3 +32,9 @@ int *fun_returns() __attribute__((ownership_returns(fun_returns)));
// CHECK: void fun_holds(int *a) __attribute__((ownership_holds(fun_holds, 1)));
void fun_holds(int *a) __attribute__((ownership_holds(fun_holds, 1)));
+
+// CHECK: int fun_var_unused() {
+// CHECK-NEXT: int x __attribute__((unused)) = 0;
+// CHECK-NEXT: return x;
+// CHECK-NEXT: }
+int fun_var_unused() { int x __attribute__((unused)) = 0; return x; }
diff --git a/clang/test/AST/ast-print-no-sanitize.cpp b/clang/test/AST/ast-print-no-sanitize.cpp
index 4ff97190955add..a5ada8246f0c0b 100644
--- a/clang/test/AST/ast-print-no-sanitize.cpp
+++ b/clang/test/AST/ast-print-no-sanitize.cpp
@@ -4,4 +4,4 @@ void should_not_crash_1() __attribute__((no_sanitize_memory));
[[clang::no_sanitize_memory]] void should_not_crash_2();
// CHECK: void should_not_crash_1() __attribute__((no_sanitize("memory")));
-// CHECK: void should_not_crash_2() {{\[\[}}clang::no_sanitize("memory"){{\]\]}};
+// CHECK: {{\[\[}}clang::no_sanitize("memory"){{\]\]}} void should_not_crash_2();
diff --git a/clang/test/AST/ast-print-pragmas.cpp b/clang/test/AST/ast-print-pragmas.cpp
index 5f27ff71b4ee8b..5059c5710189ee 100644
--- a/clang/test/AST/ast-print-pragmas.cpp
+++ b/clang/test/AST/ast-print-pragmas.cpp
@@ -93,7 +93,7 @@ void test_templates(int *List, int Length) {
#ifdef MS_EXT
#pragma init_seg(compiler)
// MS-EXT: #pragma init_seg (.CRT$XCC){{$}}
-// MS-EXT-NEXT: int x = 3 __declspec(thread);
-int __declspec(thread) x = 3;
+// MS-EXT-NEXT: __declspec(thread) int x = 3;
+__declspec(thread) int x = 3;
#endif //MS_EXT
diff --git a/clang/test/Analysis/blocks.mm b/clang/test/Analysis/blocks.mm
index 81db705b6afbc2..3ac11aa5a620ed 100644
--- a/clang/test/Analysis/blocks.mm
+++ b/clang/test/Analysis/blocks.mm
@@ -78,7 +78,7 @@ void testBlockWithCaptureByReference() {
// CHECK-NEXT: 1: 5
// WARNINGS-NEXT: 2: [B1.1] (CXXConstructExpr, StructWithCopyConstructor)
// ANALYZER-NEXT: 2: [B1.1] (CXXConstructExpr, [B1.3], StructWithCopyConstructor)
-// CHECK-NEXT: 3: StructWithCopyConstructor s(5) __attribute__((blocks("byref")));
+// CHECK-NEXT: 3: __attribute__((blocks("byref"))) StructWithCopyConstructor s(5);
// CHECK-NEXT: 4: ^{ }
// CHECK-NEXT: 5: (void)([B1.4]) (CStyleCastExpr, ToVoid, void)
// CHECK-NEXT: Preds (1): B2
diff --git a/clang/test/Analysis/scopes-cfg-output.cpp b/clang/test/Analysis/scopes-cfg-output.cpp
index 4eb8967e373516..5e6706602d4564 100644
--- a/clang/test/Analysis/scopes-cfg-output.cpp
+++ b/clang/test/Analysis/scopes-cfg-output.cpp
@@ -1469,7 +1469,7 @@ void test_cleanup_functions2(int m) {
// CHECK: [B1]
// CHECK-NEXT: 1: CFGScopeBegin(f)
// CHECK-NEXT: 2: (CXXConstructExpr, [B1.3], F)
-// CHECK-NEXT: 3: __attribute__((cleanup(cleanup_F))) F f;
+// CHECK-NEXT: 3: F f __attribute__((cleanup(cleanup_F)));
// CHECK-NEXT: 4: CleanupFunction (cleanup_F)
// CHECK-NEXT: 5: [B1.3].~F() (Implicit destructor)
// CHECK-NEXT: 6: CFGScopeEnd(f)
diff --git a/clang/test/Sema/attr-print.c b/clang/test/Sema/attr-print.c
index e12c0109efcd9a..8492356e5d2e57 100644
--- a/clang/test/Sema/attr-print.c
+++ b/clang/test/Sema/attr-print.c
@@ -3,8 +3,7 @@
// CHECK: int x __attribute__((aligned(4)));
int x __attribute__((aligned(4)));
-// FIXME: Print this at a valid location for a __declspec attr.
-// CHECK: int y __declspec(align(4));
+// CHECK: __declspec(align(4)) int y;
__declspec(align(4)) int y;
// CHECK: short arr[3] __attribute__((aligned));
diff --git a/clang/test/SemaCXX/attr-no-sanitize.cpp b/clang/test/SemaCXX/attr-no-sanitize.cpp
index a464947fe5a346..8951f616ce0f05 100644
--- a/clang/test/SemaCXX/attr-no-sanitize.cpp
+++ b/clang/test/SemaCXX/attr-no-sanitize.cpp
@@ -16,12 +16,12 @@ int f3() __attribute__((no_sanitize("address")));
// DUMP-LABEL: FunctionDecl {{.*}} f4
// DUMP: NoSanitizeAttr {{.*}} thread
-// PRINT: int f4() {{\[\[}}clang::no_sanitize("thread")]]
+// PRINT: {{\[\[}}clang::no_sanitize("thread")]] int f4()
[[clang::no_sanitize("thread")]] int f4();
// DUMP-LABEL: FunctionDecl {{.*}} f4
// DUMP: NoSanitizeAttr {{.*}} hwaddress
-// PRINT: int f4() {{\[\[}}clang::no_sanitize("hwaddress")]]
+// PRINT: {{\[\[}}clang::no_sanitize("hwaddress")]] int f4()
[[clang::no_sanitize("hwaddress")]] int f4();
// DUMP-LABEL: FunctionDecl {{.*}} f5
@@ -36,5 +36,5 @@ int f6() __attribute__((no_sanitize("unknown"))); // expected-warning{{unknown s
// DUMP-LABEL: FunctionDecl {{.*}} f7
// DUMP: NoSanitizeAttr {{.*}} memtag
-// PRINT: int f7() {{\[\[}}clang::no_sanitize("memtag")]]
+// PRINT: {{\[\[}}clang::no_sanitize("memtag")]] int f7()
[[clang::no_sanitize("memtag")]] int f7();
diff --git a/clang/test/SemaCXX/attr-print.cpp b/clang/test/SemaCXX/attr-print.cpp
index fc11365d14a214..c7c58a25504eed 100644
--- a/clang/test/SemaCXX/attr-print.cpp
+++ b/clang/test/SemaCXX/attr-print.cpp
@@ -3,8 +3,7 @@
// CHECK: int x __attribute__((aligned(4)));
int x __attribute__((aligned(4)));
-// FIXME: Print this at a valid location for a __declspec attr.
-// CHECK: int y __declspec(align(4));
+// CHECK: __declspec(align(4)) int y;
__declspec(align(4)) int y;
// CHECK: int foo() __attribute__((const));
diff --git a/clang/test/SemaCXX/cxx11-attr-print.cpp b/clang/test/SemaCXX/cxx11-attr-print.cpp
index e017c8b08b1ddd..a169d1b4409b4d 100644
--- a/clang/test/SemaCXX/cxx11-attr-print.cpp
+++ b/clang/test/SemaCXX/cxx11-attr-print.cpp
@@ -3,8 +3,7 @@
// CHECK: int x __attribute__((aligned(4)));
int x __attribute__((aligned(4)));
-// FIXME: Print this at a valid location for a __declspec attr.
-// CHECK: int y __declspec(align(4));
+// CHECK: __declspec(align(4)) int y;
__declspec(align(4)) int y;
// CHECK: int z {{\[}}[gnu::aligned(4)]];
@@ -25,10 +24,10 @@ int d [[deprecated("warning")]];
// CHECK: __attribute__((deprecated("warning", "fixit")));
int e __attribute__((deprecated("warning", "fixit")));
-// CHECK: int cxx11_alignas alignas(4);
+// CHECK: alignas(4) int cxx11_alignas;
alignas(4) int cxx11_alignas;
-// CHECK: int c11_alignas _Alignas(int);
+// CHECK: _Alignas(int) int c11_alignas;
_Alignas(int) int c11_alignas;
// CHECK: int foo() __attribute__((const));
@@ -66,8 +65,8 @@ void f8 (void *, const char *, ...) __attribute__ ((format (printf, 2, 3)));
// CHECK: int m __attribute__((aligned(4
// CHECK: int n alignas(4
// CHECK: int p alignas(int
-// CHECK: static int f() __attribute__((pure))
-// CHECK: static int g() {{\[}}[gnu::pure]]
+// CHECK: __attribute__((pure)) static int f()
+// CHECK: {{\[}}[gnu::pure]] static int g()
template <typename T> struct S {
__attribute__((aligned(4))) int m;
alignas(4) int n;
@@ -82,8 +81,8 @@ template <typename T> struct S {
// CHECK: int m __attribute__((aligned(4
// CHECK: int n alignas(4
-// CHECK: static int f() __attribute__((pure))
-// CHECK: static int g() {{\[}}[gnu::pure]]
+// CHECK: __attribute__((pure)) static int f()
+// CHECK: {{\[}}[gnu::pure]] static int g()
template struct S<int>;
// CHECK: using Small2 {{\[}}[gnu::mode(byte)]] = int;
diff --git a/clang/utils/TableGen/ClangAttrEmitter.cpp b/clang/utils/TableGen/ClangAttrEmitter.cpp
index 9d2e906573443b..6c56f99f503df4 100644
--- a/clang/utils/TableGen/ClangAttrEmitter.cpp
+++ b/clang/utils/TableGen/ClangAttrEmitter.cpp
@@ -1591,10 +1591,10 @@ writePrettyPrintFunction(const Record &R,
std::string Variety = Spellings[I].variety();
if (Variety == "GNU") {
- Prefix = " __attribute__((";
+ Prefix = "__attribute__((";
Suffix = "))";
} else if (Variety == "CXX11" || Variety == "C23") {
- Prefix = " [[";
+ Prefix = "[[";
Suffix = "]]";
std::string Namespace = Spellings[I].nameSpace();
if (!Namespace.empty()) {
@@ -1602,7 +1602,7 @@ writePrettyPrintFunction(const Record &R,
Spelling += "::";
}
} else if (Variety == "Declspec") {
- Prefix = " __declspec(";
+ Prefix = "__declspec(";
Suffix = ")";
} else if (Variety == "Microsoft") {
Prefix = "[";
>From f3aeedb58ec65abf18faf2479213c0796faf193d Mon Sep 17 00:00:00 2001
From: Vassil Vassilev <v.g.vassilev at gmail.com>
Date: Mon, 1 Apr 2024 20:25:21 +0000
Subject: [PATCH 05/10] OpenMP attributes now respect the pragma location
---
clang/test/OpenMP/assumes_codegen.cpp | 26 ++++++++++----------
clang/test/OpenMP/assumes_print.cpp | 4 +--
clang/test/OpenMP/assumes_template_print.cpp | 14 +++++------
3 files changed, 22 insertions(+), 22 deletions(-)
diff --git a/clang/test/OpenMP/assumes_codegen.cpp b/clang/test/OpenMP/assumes_codegen.cpp
index 5d8a2ae909a768..4a2518a51ec34f 100644
--- a/clang/test/OpenMP/assumes_codegen.cpp
+++ b/clang/test/OpenMP/assumes_codegen.cpp
@@ -71,37 +71,37 @@ int lambda_outer() {
// AST-NEXT: }
// AST-NEXT: class BAR {
// AST-NEXT: public:
-// AST-NEXT: BAR() __attribute__((assume("ompx_range_bar_only"))) __attribute__((assume("ompx_range_bar_only_2"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) {
+// AST-NEXT: __attribute__((assume("ompx_range_bar_only"))) __attribute__((assume("ompx_range_bar_only_2"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) BAR() {
// AST-NEXT: }
-// AST-NEXT: void bar1() __attribute__((assume("ompx_range_bar_only"))) __attribute__((assume("ompx_range_bar_only_2"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) {
+// AST-NEXT: __attribute__((assume("ompx_range_bar_only"))) __attribute__((assume("ompx_range_bar_only_2"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) void bar1() {
// AST-NEXT: }
-// AST-NEXT: static void bar2() __attribute__((assume("ompx_range_bar_only"))) __attribute__((assume("ompx_range_bar_only_2"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) {
+// AST-NEXT: __attribute__((assume("ompx_range_bar_only"))) __attribute__((assume("ompx_range_bar_only_2"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) static void bar2() {
// AST-NEXT: }
// AST-NEXT: };
-// AST-NEXT: void bar() __attribute__((assume("ompx_range_bar_only"))) __attribute__((assume("ompx_range_bar_only_2"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) {
+// AST-NEXT: __attribute__((assume("ompx_range_bar_only"))) __attribute__((assume("ompx_range_bar_only_2"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) void bar() {
// AST-NEXT: BAR b;
// AST-NEXT: }
-// AST-NEXT: void baz() __attribute__((assume("ompx_1234"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp")));
+// AST-NEXT: __attribute__((assume("ompx_1234"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) void baz();
// AST-NEXT: template <typename T> class BAZ {
// AST-NEXT: public:
-// AST-NEXT: BAZ<T>() __attribute__((assume("ompx_1234"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) {
+// AST-NEXT: __attribute__((assume("ompx_1234"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) BAZ<T>() {
// AST-NEXT: }
-// AST-NEXT: void baz1() __attribute__((assume("ompx_1234"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) {
+// AST-NEXT: __attribute__((assume("ompx_1234"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) void baz1() {
// AST-NEXT: }
-// AST-NEXT: static void baz2() __attribute__((assume("ompx_1234"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) {
+// AST-NEXT: __attribute__((assume("ompx_1234"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) static void baz2() {
// AST-NEXT: }
// AST-NEXT: };
// AST-NEXT: template<> class BAZ<float> {
// AST-NEXT: public:
-// AST-NEXT: BAZ() __attribute__((assume("ompx_1234"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) {
+// AST-NEXT: __attribute__((assume("ompx_1234"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) BAZ() {
// AST-NEXT: }
-// AST-NEXT: void baz1() __attribute__((assume("ompx_1234"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp")));
-// AST-NEXT: static void baz2() __attribute__((assume("ompx_1234"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp")));
+// AST-NEXT: __attribute__((assume("ompx_1234"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) void baz1();
+// AST-NEXT: __attribute__((assume("ompx_1234"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) static void baz2();
// AST-NEXT: };
-// AST-NEXT: void baz() __attribute__((assume("ompx_1234"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) {
+// AST-NEXT: __attribute__((assume("ompx_1234"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) void baz() {
// AST-NEXT: BAZ<float> b;
// AST-NEXT: }
-// AST-NEXT: int lambda_outer() __attribute__((assume("ompx_lambda_assumption"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) {
+// AST-NEXT: __attribute__((assume("ompx_lambda_assumption"))) __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) int lambda_outer() {
// AST-NEXT: auto lambda_inner = []() {
// AST-NEXT: return 42;
// AST-NEXT: };
diff --git a/clang/test/OpenMP/assumes_print.cpp b/clang/test/OpenMP/assumes_print.cpp
index eaaf55ccfd05de..da3629f70408dc 100644
--- a/clang/test/OpenMP/assumes_print.cpp
+++ b/clang/test/OpenMP/assumes_print.cpp
@@ -38,7 +38,7 @@ void baz() {
#pragma omp end assumes
// CHECK: void foo() __attribute__((assume("omp_no_openmp_routines"))) __attribute__((assume("omp_no_openmp")))
-// CHECK: void bar() __attribute__((assume("ompx_range_bar_only"))) __attribute__((assume("ompx_range_bar_only_2"))) __attribute__((assume("omp_no_openmp_routines"))) __attribute__((assume("omp_no_openmp")))
-// CHECK: void baz() __attribute__((assume("ompx_1234"))) __attribute__((assume("omp_no_openmp_routines"))) __attribute__((assume("omp_no_openmp")))
+// CHECK: __attribute__((assume("ompx_range_bar_only"))) __attribute__((assume("ompx_range_bar_only_2"))) __attribute__((assume("omp_no_openmp_routines"))) __attribute__((assume("omp_no_openmp"))) void bar()
+// CHECK: __attribute__((assume("ompx_1234"))) __attribute__((assume("omp_no_openmp_routines"))) __attribute__((assume("omp_no_openmp"))) void baz()
#endif
diff --git a/clang/test/OpenMP/assumes_template_print.cpp b/clang/test/OpenMP/assumes_template_print.cpp
index c73095e6f771f3..e0bc3e9884ca59 100644
--- a/clang/test/OpenMP/assumes_template_print.cpp
+++ b/clang/test/OpenMP/assumes_template_print.cpp
@@ -28,12 +28,12 @@ struct S {
// CHECK: void foo() __attribute__((assume("ompx_global_assumption"))) {
#pragma omp begin assumes no_openmp
-// CHECK: void S_with_assumes_no_call() __attribute__((assume("omp_no_openmp"))) __attribute__((assume("ompx_global_assumption"))) {
+// CHECK: __attribute__((assume("omp_no_openmp"))) void S_with_assumes_no_call() __attribute__((assume("ompx_global_assumption"))) {
void S_with_assumes_no_call() {
S<int> s;
s.a = 0;
}
-// CHECK: void S_with_assumes_call() __attribute__((assume("omp_no_openmp"))) __attribute__((assume("ompx_global_assumption"))) {
+// CHECK: __attribute__((assume("omp_no_openmp"))) void S_with_assumes_call() __attribute__((assume("ompx_global_assumption"))) {
void S_with_assumes_call() {
S<int> s;
s.a = 0;
@@ -54,7 +54,7 @@ void S_without_assumes() {
template <typename T>
struct P {
// CHECK: template <typename T> struct P {
-// CHECK: void foo() __attribute__((assume("ompx_global_assumption"))) {
+// CHECK: __attribute__((assume("ompx_global_assumption"))) void foo() {
int a;
void foo() {
#pragma omp parallel
@@ -65,21 +65,21 @@ struct P {
// TODO: Avoid the duplication here:
// CHECK: template<> struct P<int> {
-// CHECK: void foo() __attribute__((assume("ompx_global_assumption"))) __attribute__((assume("ompx_global_assumption"))) {
+// CHECK: __attribute__((assume("ompx_global_assumption"))) __attribute__((assume("ompx_global_assumption"))) void foo() {
-// CHECK: void P_without_assumes() __attribute__((assume("ompx_global_assumption"))) {
+// CHECK: __attribute__((assume("ompx_global_assumption"))) void P_without_assumes() {
void P_without_assumes() {
P<int> p;
p.foo();
}
#pragma omp begin assumes no_openmp
-// CHECK: void P_with_assumes_no_call() __attribute__((assume("omp_no_openmp"))) __attribute__((assume("ompx_global_assumption"))) {
+// CHECK: __attribute__((assume("omp_no_openmp"))) __attribute__((assume("ompx_global_assumption"))) void P_with_assumes_no_call() {
void P_with_assumes_no_call() {
P<int> p;
p.a = 0;
}
-// CHECK: void P_with_assumes_call() __attribute__((assume("omp_no_openmp"))) __attribute__((assume("ompx_global_assumption"))) {
+// CHECK: __attribute__((assume("omp_no_openmp"))) __attribute__((assume("ompx_global_assumption"))) void P_with_assumes_call() {
void P_with_assumes_call() {
P<int> p;
p.a = 0;
>From 121f120a466d4b6b4784e21b5648ad55a8248d50 Mon Sep 17 00:00:00 2001
From: Vassil Vassilev <v.g.vassilev at gmail.com>
Date: Tue, 2 Apr 2024 17:59:29 +0000
Subject: [PATCH 06/10] Add attr in preprocessor macro
---
clang/test/AST/attr-print-emit.cpp | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/clang/test/AST/attr-print-emit.cpp b/clang/test/AST/attr-print-emit.cpp
index 8c48eb92daba5e..8c8a2b20805993 100644
--- a/clang/test/AST/attr-print-emit.cpp
+++ b/clang/test/AST/attr-print-emit.cpp
@@ -73,3 +73,18 @@ class C {
// CHECK: void pwtt(void *, int) __attribute__((pointer_with_type_tag(foo, 2, 3)));
void pwtt(void *, int) __attribute__((pointer_with_type_tag(foo, 2, 3)));
};
+
+#define ANNOTATE_ATTR __attribute__((annotate("Annotated")))
+ANNOTATE_ATTR int annotated_attr ANNOTATE_ATTR = 0;
+// CHECK: __attribute__((annotate("Annotated"))) int annotated_attr __attribute__((annotate("Annotated"))) = 0;
+
+// FIXME: We do not print the attribute as written after the type specifier.
+int ANNOTATE_ATTR annotated_attr_fixme = 0;
+// CHECK: __attribute__((annotate("Annotated"))) int annotated_attr_fixme = 0;
+
+#define NONNULL_ATTR __attribute__((nonnull(1)))
+ANNOTATE_ATTR NONNULL_ATTR void fn_non_null_annotated_attr(int *) __attribute__((annotate("AnnotatedRHS")));
+// CHECK:__attribute__((annotate("Annotated"))) __attribute__((nonnull(1))) void fn_non_null_annotated_attr(int *) __attribute__((annotate("AnnotatedRHS")));
+
+[[gnu::nonnull(1)]] [[gnu::always_inline]] void cxx11_attr(int*) ANNOTATE_ATTR;
+// CHECK: {{\[\[}}gnu::nonnull(1)]] {{\[\[}}gnu::always_inline]] void cxx11_attr(int *) __attribute__((annotate("Annotated")));
>From 967248c72432dbf69bbf6d9d49a118c5c4943fdd Mon Sep 17 00:00:00 2001
From: Vassil Vassilev <v.g.vassilev at gmail.com>
Date: Wed, 3 Apr 2024 21:00:39 +0000
Subject: [PATCH 07/10] Address review comments
---
clang/lib/AST/DeclPrinter.cpp | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/clang/lib/AST/DeclPrinter.cpp b/clang/lib/AST/DeclPrinter.cpp
index 02cea3c9ae9471..a67024474436a0 100644
--- a/clang/lib/AST/DeclPrinter.cpp
+++ b/clang/lib/AST/DeclPrinter.cpp
@@ -118,7 +118,7 @@ namespace {
const TemplateParameterList *Params);
void printTemplateArguments(llvm::ArrayRef<TemplateArgumentLoc> Args,
const TemplateParameterList *Params);
- enum class AttrPosAsWritten { Default = 0, Left, Right };
+ enum class AttrPosAsWritten { Unknown = 0, Default, Left, Right };
void
prettyPrintAttributes(const Decl *D,
AttrPosAsWritten Pos = AttrPosAsWritten::Default);
@@ -244,7 +244,7 @@ static DeclPrinter::AttrPosAsWritten getPosAsWritten(const Attr *A,
SourceLocation DLoc = D->getLocation();
const ASTContext &C = D->getASTContext();
if (ALoc.isInvalid() || DLoc.isInvalid())
- return DeclPrinter::AttrPosAsWritten::Default;
+ return DeclPrinter::AttrPosAsWritten::Unknown;
if (C.getSourceManager().isBeforeInTranslationUnit(ALoc, DLoc))
return DeclPrinter::AttrPosAsWritten::Left;
@@ -268,7 +268,9 @@ void DeclPrinter::prettyPrintAttributes(const Decl *D,
#include "clang/Basic/AttrList.inc"
break;
default:
- if (Pos == AttrPosAsWritten::Default || Pos == getPosAsWritten(A, D)) {
+ AttrPosAsWritten APos = getPosAsWritten(A, D);
+ assert(APos != AttrPosAsWritten::Unknown && "Implicit attribute!");
+ if (Pos == AttrPosAsWritten::Default || Pos == APos) {
if (Pos != AttrPosAsWritten::Left)
Out << " ";
A->printPretty(Out, Policy);
>From cb2d7fb50a92e0b51e56ca9c4d40eaa1afef0920 Mon Sep 17 00:00:00 2001
From: Vassil Vassilev <v.g.vassilev at gmail.com>
Date: Thu, 4 Apr 2024 06:06:14 +0000
Subject: [PATCH 08/10] More review comments
---
clang/lib/AST/DeclPrinter.cpp | 5 +++--
clang/lib/AST/StmtPrinter.cpp | 2 +-
2 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/clang/lib/AST/DeclPrinter.cpp b/clang/lib/AST/DeclPrinter.cpp
index a67024474436a0..80cccd5c98ad72 100644
--- a/clang/lib/AST/DeclPrinter.cpp
+++ b/clang/lib/AST/DeclPrinter.cpp
@@ -258,6 +258,7 @@ void DeclPrinter::prettyPrintAttributes(const Decl *D,
return;
if (D->hasAttrs()) {
+ assert(Pos != AttrPosAsWritten::Unknown && "Use Default");
const AttrVec &Attrs = D->getAttrs();
for (auto *A : Attrs) {
if (A->isInherited() || A->isImplicit())
@@ -272,10 +273,10 @@ void DeclPrinter::prettyPrintAttributes(const Decl *D,
assert(APos != AttrPosAsWritten::Unknown && "Implicit attribute!");
if (Pos == AttrPosAsWritten::Default || Pos == APos) {
if (Pos != AttrPosAsWritten::Left)
- Out << " ";
+ Out << ' ';
A->printPretty(Out, Policy);
if (Pos == AttrPosAsWritten::Left)
- Out << " ";
+ Out << ' ';
}
break;
}
diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp
index aac926c056bf0d..cdafcaadeeb3d8 100644
--- a/clang/lib/AST/StmtPrinter.cpp
+++ b/clang/lib/AST/StmtPrinter.cpp
@@ -296,7 +296,7 @@ void StmtPrinter::VisitAttributedStmt(AttributedStmt *Node) {
for (const auto *Attr : Attrs) {
Attr->printPretty(OS, Policy);
if (Attr != Attrs.back())
- OS << " ";
+ OS << ' ';
}
PrintStmt(Node->getSubStmt(), 0);
>From 455a21081e45c27dc79ee5ae5e5e24ef4ceeab30 Mon Sep 17 00:00:00 2001
From: Vassil Vassilev <v.g.vassilev at gmail.com>
Date: Mon, 8 Apr 2024 16:51:18 +0000
Subject: [PATCH 09/10] Address more comments
---
clang/lib/AST/DeclPrinter.cpp | 2 ++
1 file changed, 2 insertions(+)
diff --git a/clang/lib/AST/DeclPrinter.cpp b/clang/lib/AST/DeclPrinter.cpp
index 80cccd5c98ad72..b30c4447a7c743 100644
--- a/clang/lib/AST/DeclPrinter.cpp
+++ b/clang/lib/AST/DeclPrinter.cpp
@@ -270,6 +270,8 @@ void DeclPrinter::prettyPrintAttributes(const Decl *D,
break;
default:
AttrPosAsWritten APos = getPosAsWritten(A, D);
+ // Might trigger on programatically created attributes with no source
+ // locations.
assert(APos != AttrPosAsWritten::Unknown && "Implicit attribute!");
if (Pos == AttrPosAsWritten::Default || Pos == APos) {
if (Pos != AttrPosAsWritten::Left)
>From 9943145b876bcaad97b6908a31ba92ae156d737b Mon Sep 17 00:00:00 2001
From: Vassil Vassilev <v.g.vassilev at gmail.com>
Date: Mon, 8 Apr 2024 19:57:32 +0300
Subject: [PATCH 10/10] Update clang/lib/AST/DeclPrinter.cpp
Co-authored-by: Erich Keane <ekeane at nvidia.com>
---
clang/lib/AST/DeclPrinter.cpp | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/clang/lib/AST/DeclPrinter.cpp b/clang/lib/AST/DeclPrinter.cpp
index b30c4447a7c743..6c4875ecfb4abe 100644
--- a/clang/lib/AST/DeclPrinter.cpp
+++ b/clang/lib/AST/DeclPrinter.cpp
@@ -272,7 +272,8 @@ void DeclPrinter::prettyPrintAttributes(const Decl *D,
AttrPosAsWritten APos = getPosAsWritten(A, D);
// Might trigger on programatically created attributes with no source
// locations.
- assert(APos != AttrPosAsWritten::Unknown && "Implicit attribute!");
+ assert(APos != AttrPosAsWritten::Unknown && "Invalid source location for attribute or decl.");
+ assert(APos !=AttrPosAsWritten::Default && "Default not a valid for an attribute location");
if (Pos == AttrPosAsWritten::Default || Pos == APos) {
if (Pos != AttrPosAsWritten::Left)
Out << ' ';
More information about the cfe-commits
mailing list