Author: Vassil Vassilev Date: 2024-04-09T07:26:48Z New Revision: 9391ff8c86007562d40c240ea082b7c0cbf35947
URL: https://github.com/llvm/llvm-project/commit/9391ff8c86007562d40c240ea082b7c0cbf35947 DIFF: https://github.com/llvm/llvm-project/commit/9391ff8c86007562d40c240ea082b7c0cbf35947.diff LOG: Reland "Rework the printing of attributes (#87281)" Original commit message: " Commit https://github.com/llvm/llvm-project/commit/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 https://github.com/llvm/llvm-project/issues/87151 " The reason for the bot breakage is that attributes coming from ApiNotes are not marked implicit even though they do not have source locations. This caused an assert to trigger. This patch forces attributes with no source location information to be printed on the left. That change is consistent to the overall intent of the change to increase the chances for attributes to compile across toolchains and at the same time the produced code to be as close as possible to the one written by the user. 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/APINotes/retain-count-convention.m clang/test/APINotes/versioned.m 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 6584460cf5685e..dc87a8c6f022dc 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. @@ -3171,7 +3160,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 edbcdfe4d55bc9..6afdb6cfccb142 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; @@ -49,18 +50,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 +118,10 @@ namespace { const TemplateParameterList *Params); void printTemplateArguments(llvm::ArrayRef<TemplateArgumentLoc> Args, const TemplateParameterList *Params); - - inline void prettyPrintAttributes(Decl *D) { - prettyPrintAttributes(D, Out); - } - + 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); }; @@ -250,87 +238,48 @@ raw_ostream& DeclPrinter::Indent(unsigned Indentation) { return Out; } -// For CLANG_ATTR_LIST_CanPrintOnLeft macro. -#include "clang/Basic/AttrLeftSideCanPrintList.inc" +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::Left; -// For CLANG_ATTR_LIST_PrintOnLeft macro. -#include "clang/Basic/AttrLeftSideMustPrintList.inc" + if (C.getSourceManager().isBeforeInTranslationUnit(ALoc, DLoc)) + return DeclPrinter::AttrPosAsWritten::Left; -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()); + return DeclPrinter::AttrPosAsWritten::Right; } -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) { +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; - - 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; + 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); + 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; } - // Only print the side matches the user requested. - if ((Loc & AttrLoc) != AttrPrintLoc::None) - A->printPretty(Out, Policy); } } } @@ -691,8 +640,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<> "; @@ -702,22 +653,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); @@ -883,7 +818,7 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) { Ty.print(Out, Policy, Proto); } - prettyPrintAttributes(D, Out, AttrPrintLoc::Right); + prettyPrintAttributes(D, AttrPosAsWritten::Right); if (D->isPureVirtual()) Out << " = 0"; @@ -976,27 +911,12 @@ 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()); @@ -1029,21 +949,16 @@ 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()); + + prettyPrintAttributes(D, AttrPosAsWritten::Right); Expr *Init = D->getInit(); if (!Policy.SuppressInitializers && Init) { diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp index 74b18e50bf1f40..2ba93d17f2675d 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/APINotes/retain-count-convention.m b/clang/test/APINotes/retain-count-convention.m index 4bf9610a352a75..35cfe0581daf59 100644 --- a/clang/test/APINotes/retain-count-convention.m +++ b/clang/test/APINotes/retain-count-convention.m @@ -5,15 +5,15 @@ #import <SimpleKit/SimpleKit.h> -// CHECK: void *getCFOwnedToUnowned(void) __attribute__((cf_returns_not_retained)); -// CHECK: void *getCFUnownedToOwned(void) __attribute__((cf_returns_retained)); -// CHECK: void *getCFOwnedToNone(void) __attribute__((cf_unknown_transfer)); -// CHECK: id getObjCOwnedToUnowned(void) __attribute__((ns_returns_not_retained)); -// CHECK: id getObjCUnownedToOwned(void) __attribute__((ns_returns_retained)); -// CHECK: int indirectGetCFOwnedToUnowned(void * _Nullable *out __attribute__((cf_returns_not_retained))); -// CHECK: int indirectGetCFUnownedToOwned(void * _Nullable *out __attribute__((cf_returns_retained))); +// CHECK: __attribute__((cf_returns_not_retained)) void *getCFOwnedToUnowned(void); +// CHECK: __attribute__((cf_returns_retained)) void *getCFUnownedToOwned(void); +// CHECK: __attribute__((cf_unknown_transfer)) void *getCFOwnedToNone(void); +// CHECK: __attribute__((ns_returns_not_retained)) id getObjCOwnedToUnowned(void); +// CHECK: __attribute__((ns_returns_retained)) id getObjCUnownedToOwned(void); +// CHECK: int indirectGetCFOwnedToUnowned(__attribute__((cf_returns_not_retained)) void * _Nullable *out); +// CHECK: int indirectGetCFUnownedToOwned(__attribute__((cf_returns_retained)) void * _Nullable *out); // CHECK: int indirectGetCFOwnedToNone(void * _Nullable *out); -// CHECK: int indirectGetCFNoneToOwned(void **out __attribute__((cf_returns_not_retained))); +// CHECK: int indirectGetCFNoneToOwned(__attribute__((cf_returns_not_retained)) void **out); // CHECK-LABEL: @interface MethodTest // CHECK: - (id)getOwnedToUnowned __attribute__((ns_returns_not_retained)); diff --git a/clang/test/APINotes/versioned.m b/clang/test/APINotes/versioned.m index 61cc8c3f7c4d1e..4a8da1556f874a 100644 --- a/clang/test/APINotes/versioned.m +++ b/clang/test/APINotes/versioned.m @@ -13,7 +13,7 @@ #import <VersionedKit/VersionedKit.h> // CHECK-UNVERSIONED: void moveToPointDUMP(double x, double y) __attribute__((swift_name("moveTo(x:y:)"))); -// CHECK-VERSIONED: void moveToPointDUMP(double x, double y) __attribute__((swift_name("moveTo(a:b:)"))); +// CHECK-VERSIONED:__attribute__((swift_name("moveTo(a:b:)"))) void moveToPointDUMP(double x, double y); // CHECK-DUMP-LABEL: Dumping moveToPointDUMP // CHECK-VERSIONED-DUMP: SwiftVersionedAdditionAttr {{.+}} Implicit 3.0 IsReplacedByActive{{$}} @@ -65,7 +65,7 @@ // CHECK-DUMP-NOT: Dumping -// CHECK-UNVERSIONED: void acceptClosure(void (^block)(void) __attribute__((noescape))); +// CHECK-UNVERSIONED: void acceptClosure(__attribute__((noescape)) void (^block)(void)); // CHECK-VERSIONED: void acceptClosure(void (^block)(void)); // CHECK-UNVERSIONED: void privateFunc(void) __attribute__((swift_private)); 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-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/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"))); 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/OpenMP/assumes_codegen.cpp b/clang/test/OpenMP/assumes_codegen.cpp index 6a5871c303aade..4a2518a51ec34f 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: __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: @@ -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: 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: __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: 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: __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 a7f04edb3b1af4..da3629f70408dc 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: __attribute__((assume("omp_no_openmp_routines"))) __attribute__((assume("omp_no_openmp"))) void foo() +// CHECK: void foo() __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() diff --git a/clang/test/OpenMP/assumes_template_print.cpp b/clang/test/OpenMP/assumes_template_print.cpp index bd1100fbefffc6..e0bc3e9884ca59 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: __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: __attribute__((assume("omp_no_openmp"))) __attribute__((assume("ompx_global_assumption"))) void S_with_assumes_call() { +// 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; @@ -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(); 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/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/cxx11-attr-print.cpp b/clang/test/SemaCXX/cxx11-attr-print.cpp index c988972aeb1a5a..a169d1b4409b4d 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: 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,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: static int g() {{\[}}[gnu::pure]] +// CHECK: {{\[}}[gnu::pure]] static int g() 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: static int g() {{\[}}[gnu::pure]] +// 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 eb5c34d15693d7..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 = "["; @@ -3316,37 +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; - 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 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); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits