[clang] 62e9257 - Revert "Rework the printing of attributes (#87281)"
Vassil Vassilev via cfe-commits
cfe-commits at lists.llvm.org
Mon Apr 8 22:03:52 PDT 2024
Author: Vassil Vassilev
Date: 2024-04-09T05:03:34Z
New Revision: 62e92573d28d62ab7e6438ac34d513b07c51ce09
URL: https://github.com/llvm/llvm-project/commit/62e92573d28d62ab7e6438ac34d513b07c51ce09
DIFF: https://github.com/llvm/llvm-project/commit/62e92573d28d62ab7e6438ac34d513b07c51ce09.diff
LOG: Revert "Rework the printing of attributes (#87281)"
This reverts commit a30662fc2acdd73ca1a9217716299a4676999fb4 due to bot failures.
Added:
Modified:
clang/include/clang/Basic/Attr.td
clang/include/clang/Basic/CMakeLists.txt
clang/lib/AST/DeclPrinter.cpp
clang/lib/AST/StmtPrinter.cpp
clang/test/AST/ast-print-method-decl.cpp
clang/test/AST/ast-print-no-sanitize.cpp
clang/test/AST/attr-print-emit.cpp
clang/test/Analysis/scopes-cfg-output.cpp
clang/test/OpenMP/assumes_codegen.cpp
clang/test/OpenMP/assumes_print.cpp
clang/test/OpenMP/assumes_template_print.cpp
clang/test/OpenMP/declare_simd_ast_print.cpp
clang/test/SemaCXX/attr-no-sanitize.cpp
clang/test/SemaCXX/cxx11-attr-print.cpp
clang/utils/TableGen/ClangAttrEmitter.cpp
clang/utils/TableGen/TableGen.cpp
clang/utils/TableGen/TableGenBackends.h
Removed:
################################################################################
diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td
index dc87a8c6f022dc..6584460cf5685e 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -324,10 +324,13 @@ class Spelling<string name, string variety, int version = 1> {
}
class GNU<string name> : Spelling<name, "GNU">;
-class Declspec<string name> : Spelling<name, "Declspec">;
+class Declspec<string name> : Spelling<name, "Declspec"> {
+ bit PrintOnLeft = 1;
+}
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>
@@ -593,6 +596,12 @@ 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
@@ -928,6 +937,7 @@ 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.
@@ -1524,6 +1534,7 @@ 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.
@@ -3160,6 +3171,7 @@ 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 2ef6ddc68f4bf3..7d53c751c13ac4 100644
--- a/clang/include/clang/Basic/CMakeLists.txt
+++ b/clang/include/clang/Basic/CMakeLists.txt
@@ -31,6 +31,16 @@ 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 0d03288a491ab5..edbcdfe4d55bc9 100644
--- a/clang/lib/AST/DeclPrinter.cpp
+++ b/clang/lib/AST/DeclPrinter.cpp
@@ -21,7 +21,6 @@
#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;
@@ -50,6 +49,18 @@ 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,
@@ -118,10 +129,11 @@ namespace {
const TemplateParameterList *Params);
void printTemplateArguments(llvm::ArrayRef<TemplateArgumentLoc> Args,
const TemplateParameterList *Params);
- enum class AttrPosAsWritten { Unknown = 0, Default, Left, Right };
- void
- prettyPrintAttributes(const Decl *D,
- AttrPosAsWritten Pos = AttrPosAsWritten::Default);
+
+ inline void prettyPrintAttributes(Decl *D) {
+ prettyPrintAttributes(D, Out);
+ }
+
void prettyPrintPragmas(Decl *D);
void printDeclType(QualType T, StringRef DeclName, bool Pack = false);
};
@@ -238,53 +250,87 @@ raw_ostream& DeclPrinter::Indent(unsigned Indentation) {
return Out;
}
-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::Unknown;
+// For CLANG_ATTR_LIST_CanPrintOnLeft macro.
+#include "clang/Basic/AttrLeftSideCanPrintList.inc"
- if (C.getSourceManager().isBeforeInTranslationUnit(ALoc, DLoc))
- return DeclPrinter::AttrPosAsWritten::Left;
+// For CLANG_ATTR_LIST_PrintOnLeft macro.
+#include "clang/Basic/AttrLeftSideMustPrintList.inc"
- return DeclPrinter::AttrPosAsWritten::Right;
+static bool canPrintOnLeftSide(attr::Kind kind) {
+#ifdef CLANG_ATTR_LIST_CanPrintOnLeft
+ switch (kind) {
+ CLANG_ATTR_LIST_CanPrintOnLeft
+ return true;
+ default:
+ return false;
+ }
+#else
+ return false;
+#endif
+}
+
+static bool canPrintOnLeftSide(const Attr *A) {
+ if (A->isStandardAttributeSyntax())
+ return false;
+
+ return canPrintOnLeftSide(A->getKind());
}
-void DeclPrinter::prettyPrintAttributes(const Decl *D,
- AttrPosAsWritten Pos /*=Default*/) {
+static bool mustPrintOnLeftSide(attr::Kind kind) {
+#ifdef CLANG_ATTR_LIST_PrintOnLeft
+ switch (kind) {
+ CLANG_ATTR_LIST_PrintOnLeft
+ return true;
+ default:
+ return false;
+ }
+#else
+ return false;
+#endif
+}
+
+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) {
if (Policy.PolishForDeclaration)
return;
if (D->hasAttrs()) {
- assert(Pos != AttrPosAsWritten::Unknown && "Use Default");
- const AttrVec &Attrs = D->getAttrs();
+ AttrVec &Attrs = D->getAttrs();
for (auto *A : Attrs) {
if (A->isInherited() || A->isImplicit())
continue;
- switch (A->getKind()) {
-#define ATTR(X)
-#define PRAGMA_SPELLING_ATTR(X) case attr::X:
-#include "clang/Basic/AttrList.inc"
- break;
- default:
- AttrPosAsWritten APos = getPosAsWritten(A, D);
- // Might trigger on programatically created attributes or declarations
- // with no source locations.
- 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 << ' ';
- A->printPretty(Out, Policy);
- if (Pos == AttrPosAsWritten::Left)
- Out << ' ';
- }
- break;
+
+ 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)
+ A->printPretty(Out, Policy);
}
}
}
@@ -645,10 +691,8 @@ 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<> ";
@@ -658,6 +702,22 @@ 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);
@@ -823,7 +883,7 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
Ty.print(Out, Policy, Proto);
}
- prettyPrintAttributes(D, AttrPosAsWritten::Right);
+ prettyPrintAttributes(D, Out, AttrPrintLoc::Right);
if (D->isPureVirtual())
Out << " = 0";
@@ -916,12 +976,27 @@ 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 ";
+ 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());
@@ -954,16 +1029,21 @@ 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);
- printDeclType(T, (isa<ParmVarDecl>(D) && Policy.CleanUglifiedParameters &&
- D->getIdentifier())
- ? D->getIdentifier()->deuglifiedName()
- : D->getName());
-
- prettyPrintAttributes(D, AttrPosAsWritten::Right);
+ // Print the attributes that should be placed right before the end of the
+ // decl.
+ prettyPrintAttributes(D, Out, AttrPrintLoc::Right);
Expr *Init = D->getInit();
if (!Policy.SuppressInitializers && Init) {
diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp
index 2ba93d17f2675d..74b18e50bf1f40 100644
--- a/clang/lib/AST/StmtPrinter.cpp
+++ b/clang/lib/AST/StmtPrinter.cpp
@@ -292,11 +292,8 @@ void StmtPrinter::VisitLabelStmt(LabelStmt *Node) {
}
void StmtPrinter::VisitAttributedStmt(AttributedStmt *Node) {
- llvm::ArrayRef<const Attr *> Attrs = Node->getAttrs();
- for (const auto *Attr : Attrs) {
+ for (const auto *Attr : Node->getAttrs()) {
Attr->printPretty(OS, Policy);
- if (Attr != Attrs.back())
- OS << ' ';
}
PrintStmt(Node->getSubStmt(), 0);
diff --git a/clang/test/AST/ast-print-method-decl.cpp b/clang/test/AST/ast-print-method-decl.cpp
index cb5d10096381a9..75dea0cac16be1 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: void m1() __attribute__((alias("X")));
+ // CHECK-NEXT: __attribute__((alias("X"))) void m1();
void m1() __attribute__((alias("X")));
// CHECK-NEXT: };
diff --git a/clang/test/AST/ast-print-no-sanitize.cpp b/clang/test/AST/ast-print-no-sanitize.cpp
index a5ada8246f0c0b..4ff97190955add 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: {{\[\[}}clang::no_sanitize("memory"){{\]\]}} void should_not_crash_2();
+// CHECK: void should_not_crash_2() {{\[\[}}clang::no_sanitize("memory"){{\]\]}};
diff --git a/clang/test/AST/attr-print-emit.cpp b/clang/test/AST/attr-print-emit.cpp
index 8c8a2b20805993..8c48eb92daba5e 100644
--- a/clang/test/AST/attr-print-emit.cpp
+++ b/clang/test/AST/attr-print-emit.cpp
@@ -73,18 +73,3 @@ 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")));
diff --git a/clang/test/Analysis/scopes-cfg-output.cpp b/clang/test/Analysis/scopes-cfg-output.cpp
index 5e6706602d4564..4eb8967e373516 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: F f __attribute__((cleanup(cleanup_F)));
+// CHECK-NEXT: 3: __attribute__((cleanup(cleanup_F))) F 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/OpenMP/assumes_codegen.cpp b/clang/test/OpenMP/assumes_codegen.cpp
index 4a2518a51ec34f..6a5871c303aade 100644
--- a/clang/test/OpenMP/assumes_codegen.cpp
+++ b/clang/test/OpenMP/assumes_codegen.cpp
@@ -67,7 +67,7 @@ int lambda_outer() {
}
#pragma omp end assumes
-// AST: void foo() __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) {
+// AST: __attribute__((assume("omp_no_openmp_routines,ompx_another_warning,ompx_after_invalid_clauses"))) __attribute__((assume("omp_no_openmp"))) void foo() {
// AST-NEXT: }
// AST-NEXT: class BAR {
// AST-NEXT: public:
@@ -81,7 +81,7 @@ int lambda_outer() {
// 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: __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: 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>() {
@@ -95,8 +95,8 @@ int lambda_outer() {
// 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: }
-// 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: 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: BAZ<float> b;
diff --git a/clang/test/OpenMP/assumes_print.cpp b/clang/test/OpenMP/assumes_print.cpp
index da3629f70408dc..a7f04edb3b1af4 100644
--- a/clang/test/OpenMP/assumes_print.cpp
+++ b/clang/test/OpenMP/assumes_print.cpp
@@ -37,7 +37,7 @@ void baz() {
}
#pragma omp end assumes
-// CHECK: void foo() __attribute__((assume("omp_no_openmp_routines"))) __attribute__((assume("omp_no_openmp")))
+// 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()
diff --git a/clang/test/OpenMP/assumes_template_print.cpp b/clang/test/OpenMP/assumes_template_print.cpp
index e0bc3e9884ca59..bd1100fbefffc6 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: void foo() __attribute__((assume("ompx_global_assumption"))) {
+// CHECK: __attribute__((assume("ompx_global_assumption"))) void foo() {
void foo() {
#pragma omp parallel
{}
@@ -25,15 +25,15 @@ struct S {
};
// CHECK: template<> struct S<int> {
-// CHECK: void foo() __attribute__((assume("ompx_global_assumption"))) {
+// CHECK: __attribute__((assume("ompx_global_assumption"))) void foo() {
#pragma omp begin assumes no_openmp
-// CHECK: __attribute__((assume("omp_no_openmp"))) void S_with_assumes_no_call() __attribute__((assume("ompx_global_assumption"))) {
+// CHECK: __attribute__((assume("omp_no_openmp"))) __attribute__((assume("ompx_global_assumption"))) void S_with_assumes_no_call() {
void S_with_assumes_no_call() {
S<int> s;
s.a = 0;
}
-// CHECK: __attribute__((assume("omp_no_openmp"))) void S_with_assumes_call() __attribute__((assume("ompx_global_assumption"))) {
+// CHECK: __attribute__((assume("omp_no_openmp"))) __attribute__((assume("ompx_global_assumption"))) void S_with_assumes_call() {
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: void S_without_assumes() __attribute__((assume("ompx_global_assumption"))) {
+// CHECK: __attribute__((assume("ompx_global_assumption"))) void S_without_assumes() {
void S_without_assumes() {
S<int> s;
s.foo();
diff --git a/clang/test/OpenMP/declare_simd_ast_print.cpp b/clang/test/OpenMP/declare_simd_ast_print.cpp
index 565dc2dfc04d11..1adf95226c8beb 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: int add(int a, int b) __attribute__((cold)) {
+ // CHECK-NEXT: __attribute__((cold)) int add(int a, int b) {
// CHECK-NEXT: return a + b;
// CHECK-NEXT: }
#pragma omp declare simd uniform(this, a) linear(val(b): a)
- int add(int a, int b) __attribute__((cold)) { return a + b; }
+ __attribute__((cold)) int add(int a, int b) { 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/SemaCXX/attr-no-sanitize.cpp b/clang/test/SemaCXX/attr-no-sanitize.cpp
index 8951f616ce0f05..a464947fe5a346 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: {{\[\[}}clang::no_sanitize("thread")]] int f4()
+// PRINT: int f4() {{\[\[}}clang::no_sanitize("thread")]]
[[clang::no_sanitize("thread")]] int f4();
// DUMP-LABEL: FunctionDecl {{.*}} f4
// DUMP: NoSanitizeAttr {{.*}} hwaddress
-// PRINT: {{\[\[}}clang::no_sanitize("hwaddress")]] int f4()
+// PRINT: int f4() {{\[\[}}clang::no_sanitize("hwaddress")]]
[[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: {{\[\[}}clang::no_sanitize("memtag")]] int f7()
+// PRINT: int f7() {{\[\[}}clang::no_sanitize("memtag")]]
[[clang::no_sanitize("memtag")]] int f7();
diff --git a/clang/test/SemaCXX/cxx11-attr-print.cpp b/clang/test/SemaCXX/cxx11-attr-print.cpp
index a169d1b4409b4d..c988972aeb1a5a 100644
--- a/clang/test/SemaCXX/cxx11-attr-print.cpp
+++ b/clang/test/SemaCXX/cxx11-attr-print.cpp
@@ -24,10 +24,10 @@ int d [[deprecated("warning")]];
// CHECK: __attribute__((deprecated("warning", "fixit")));
int e __attribute__((deprecated("warning", "fixit")));
-// CHECK: alignas(4) int cxx11_alignas;
+// CHECK: int cxx11_alignas alignas(4);
alignas(4) int cxx11_alignas;
-// CHECK: _Alignas(int) int c11_alignas;
+// CHECK: int c11_alignas _Alignas(int);
_Alignas(int) int c11_alignas;
// CHECK: int foo() __attribute__((const));
@@ -66,7 +66,7 @@ void f8 (void *, const char *, ...) __attribute__ ((format (printf, 2, 3)));
// CHECK: int n alignas(4
// CHECK: int p alignas(int
// CHECK: __attribute__((pure)) static int f()
-// CHECK: {{\[}}[gnu::pure]] static int g()
+// CHECK: static int g() {{\[}}[gnu::pure]]
template <typename T> struct S {
__attribute__((aligned(4))) int m;
alignas(4) int n;
@@ -82,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: {{\[}}[gnu::pure]] static int g()
+// CHECK: static int g() {{\[}}[gnu::pure]]
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 6c56f99f503df4..eb5c34d15693d7 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 = "[";
@@ -3316,6 +3316,37 @@ 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;
+ bool first = false;
+
+ for (auto *Attr : Attrs) {
+ if (!Attr->getValueAsBit("ASTNode"))
+ continue;
+
+ if (!Attr->getValueAsBit(FieldName))
+ continue;
+
+ if (!first) {
+ first = true;
+ OS << "#define CLANG_ATTR_LIST_" << FieldName;
+ }
+
+ OS << " \\\n case attr::" << Attr->getName() << ":";
+ }
+
+ OS << '\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 42cc704543f18e..3f22e43b97ecd2 100644
--- a/clang/utils/TableGen/TableGen.cpp
+++ b/clang/utils/TableGen/TableGen.cpp
@@ -31,6 +31,8 @@ enum ActionType {
GenClangAttrSubjectMatchRulesParserStringSwitches,
GenClangAttrImpl,
GenClangAttrList,
+ GenClangAttrCanPrintLeftList,
+ GenClangAttrMustPrintLeftList,
GenClangAttrDocTable,
GenClangAttrSubjectMatchRuleList,
GenClangAttrPCHRead,
@@ -132,6 +134,14 @@ 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,
@@ -335,6 +345,12 @@ 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 5f2dd257cb90a9..ecd506b7b6b50a 100644
--- a/clang/utils/TableGen/TableGenBackends.h
+++ b/clang/utils/TableGen/TableGenBackends.h
@@ -47,6 +47,8 @@ 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);
More information about the cfe-commits
mailing list