Skip to content

Commit 62e9257

Browse files
committed
Revert "Rework the printing of attributes (#87281)"
This reverts commit a30662f due to bot failures.
1 parent d10983b commit 62e9257

17 files changed

+230
-97
lines changed

clang/include/clang/Basic/Attr.td

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -324,10 +324,13 @@ class Spelling<string name, string variety, int version = 1> {
324324
}
325325

326326
class GNU<string name> : Spelling<name, "GNU">;
327-
class Declspec<string name> : Spelling<name, "Declspec">;
327+
class Declspec<string name> : Spelling<name, "Declspec"> {
328+
bit PrintOnLeft = 1;
329+
}
328330
class Microsoft<string name> : Spelling<name, "Microsoft">;
329331
class CXX11<string namespace, string name, int version = 1>
330332
: Spelling<name, "CXX11", version> {
333+
bit CanPrintOnLeft = 0;
331334
string Namespace = namespace;
332335
}
333336
class C23<string namespace, string name, int version = 1>
@@ -593,6 +596,12 @@ class AttrSubjectMatcherAggregateRule<AttrSubject subject> {
593596
def SubjectMatcherForNamed : AttrSubjectMatcherAggregateRule<Named>;
594597

595598
class Attr {
599+
// Specifies that when printed, this attribute is meaningful on the
600+
// 'left side' of the declaration.
601+
bit CanPrintOnLeft = 1;
602+
// Specifies that when printed, this attribute is required to be printed on
603+
// the 'left side' of the declaration.
604+
bit PrintOnLeft = 0;
596605
// The various ways in which an attribute can be spelled in source
597606
list<Spelling> Spellings;
598607
// The things to which an attribute can appertain
@@ -928,6 +937,7 @@ def AVRSignal : InheritableAttr, TargetSpecificAttr<TargetAVR> {
928937
}
929938

930939
def AsmLabel : InheritableAttr {
940+
let CanPrintOnLeft = 0;
931941
let Spellings = [CustomKeyword<"asm">, CustomKeyword<"__asm__">];
932942
let Args = [
933943
// Label specifies the mangled name for the decl.
@@ -1524,6 +1534,7 @@ def AllocSize : InheritableAttr {
15241534
}
15251535

15261536
def EnableIf : InheritableAttr {
1537+
let CanPrintOnLeft = 0;
15271538
// Does not have a [[]] spelling because this attribute requires the ability
15281539
// to parse function arguments but the attribute is not written in the type
15291540
// position.
@@ -3160,6 +3171,7 @@ def Unavailable : InheritableAttr {
31603171
}
31613172

31623173
def DiagnoseIf : InheritableAttr {
3174+
let CanPrintOnLeft = 0;
31633175
// Does not have a [[]] spelling because this attribute requires the ability
31643176
// to parse function arguments but the attribute is not written in the type
31653177
// position.

clang/include/clang/Basic/CMakeLists.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,16 @@ clang_tablegen(AttrList.inc -gen-clang-attr-list
3131
SOURCE Attr.td
3232
TARGET ClangAttrList)
3333

34+
clang_tablegen(AttrLeftSideCanPrintList.inc -gen-clang-attr-can-print-left-list
35+
-I ${CMAKE_CURRENT_SOURCE_DIR}/../../
36+
SOURCE Attr.td
37+
TARGET ClangAttrCanPrintLeftList)
38+
39+
clang_tablegen(AttrLeftSideMustPrintList.inc -gen-clang-attr-must-print-left-list
40+
-I ${CMAKE_CURRENT_SOURCE_DIR}/../../
41+
SOURCE Attr.td
42+
TARGET ClangAttrMustPrintLeftList)
43+
3444
clang_tablegen(AttrSubMatchRulesList.inc -gen-clang-attr-subject-match-rule-list
3545
-I ${CMAKE_CURRENT_SOURCE_DIR}/../../
3646
SOURCE Attr.td

clang/lib/AST/DeclPrinter.cpp

Lines changed: 132 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
#include "clang/AST/ExprCXX.h"
2222
#include "clang/AST/PrettyPrinter.h"
2323
#include "clang/Basic/Module.h"
24-
#include "clang/Basic/SourceManager.h"
2524
#include "llvm/Support/raw_ostream.h"
2625
using namespace clang;
2726

@@ -50,6 +49,18 @@ namespace {
5049

5150
void PrintObjCTypeParams(ObjCTypeParamList *Params);
5251

52+
enum class AttrPrintLoc {
53+
None = 0,
54+
Left = 1,
55+
Right = 2,
56+
Any = Left | Right,
57+
58+
LLVM_MARK_AS_BITMASK_ENUM(/*DefaultValue=*/Any)
59+
};
60+
61+
void prettyPrintAttributes(Decl *D, raw_ostream &out,
62+
AttrPrintLoc loc = AttrPrintLoc::Any);
63+
5364
public:
5465
DeclPrinter(raw_ostream &Out, const PrintingPolicy &Policy,
5566
const ASTContext &Context, unsigned Indentation = 0,
@@ -118,10 +129,11 @@ namespace {
118129
const TemplateParameterList *Params);
119130
void printTemplateArguments(llvm::ArrayRef<TemplateArgumentLoc> Args,
120131
const TemplateParameterList *Params);
121-
enum class AttrPosAsWritten { Unknown = 0, Default, Left, Right };
122-
void
123-
prettyPrintAttributes(const Decl *D,
124-
AttrPosAsWritten Pos = AttrPosAsWritten::Default);
132+
133+
inline void prettyPrintAttributes(Decl *D) {
134+
prettyPrintAttributes(D, Out);
135+
}
136+
125137
void prettyPrintPragmas(Decl *D);
126138
void printDeclType(QualType T, StringRef DeclName, bool Pack = false);
127139
};
@@ -238,53 +250,87 @@ raw_ostream& DeclPrinter::Indent(unsigned Indentation) {
238250
return Out;
239251
}
240252

241-
static DeclPrinter::AttrPosAsWritten getPosAsWritten(const Attr *A,
242-
const Decl *D) {
243-
SourceLocation ALoc = A->getLoc();
244-
SourceLocation DLoc = D->getLocation();
245-
const ASTContext &C = D->getASTContext();
246-
if (ALoc.isInvalid() || DLoc.isInvalid())
247-
return DeclPrinter::AttrPosAsWritten::Unknown;
253+
// For CLANG_ATTR_LIST_CanPrintOnLeft macro.
254+
#include "clang/Basic/AttrLeftSideCanPrintList.inc"
248255

249-
if (C.getSourceManager().isBeforeInTranslationUnit(ALoc, DLoc))
250-
return DeclPrinter::AttrPosAsWritten::Left;
256+
// For CLANG_ATTR_LIST_PrintOnLeft macro.
257+
#include "clang/Basic/AttrLeftSideMustPrintList.inc"
251258

252-
return DeclPrinter::AttrPosAsWritten::Right;
259+
static bool canPrintOnLeftSide(attr::Kind kind) {
260+
#ifdef CLANG_ATTR_LIST_CanPrintOnLeft
261+
switch (kind) {
262+
CLANG_ATTR_LIST_CanPrintOnLeft
263+
return true;
264+
default:
265+
return false;
266+
}
267+
#else
268+
return false;
269+
#endif
270+
}
271+
272+
static bool canPrintOnLeftSide(const Attr *A) {
273+
if (A->isStandardAttributeSyntax())
274+
return false;
275+
276+
return canPrintOnLeftSide(A->getKind());
253277
}
254278

255-
void DeclPrinter::prettyPrintAttributes(const Decl *D,
256-
AttrPosAsWritten Pos /*=Default*/) {
279+
static bool mustPrintOnLeftSide(attr::Kind kind) {
280+
#ifdef CLANG_ATTR_LIST_PrintOnLeft
281+
switch (kind) {
282+
CLANG_ATTR_LIST_PrintOnLeft
283+
return true;
284+
default:
285+
return false;
286+
}
287+
#else
288+
return false;
289+
#endif
290+
}
291+
292+
static bool mustPrintOnLeftSide(const Attr *A) {
293+
if (A->isDeclspecAttribute())
294+
return true;
295+
296+
return mustPrintOnLeftSide(A->getKind());
297+
}
298+
299+
void DeclPrinter::prettyPrintAttributes(Decl *D, llvm::raw_ostream &Out,
300+
AttrPrintLoc Loc) {
257301
if (Policy.PolishForDeclaration)
258302
return;
259303

260304
if (D->hasAttrs()) {
261-
assert(Pos != AttrPosAsWritten::Unknown && "Use Default");
262-
const AttrVec &Attrs = D->getAttrs();
305+
AttrVec &Attrs = D->getAttrs();
263306
for (auto *A : Attrs) {
264307
if (A->isInherited() || A->isImplicit())
265308
continue;
266-
switch (A->getKind()) {
267-
#define ATTR(X)
268-
#define PRAGMA_SPELLING_ATTR(X) case attr::X:
269-
#include "clang/Basic/AttrList.inc"
270-
break;
271-
default:
272-
AttrPosAsWritten APos = getPosAsWritten(A, D);
273-
// Might trigger on programatically created attributes or declarations
274-
// with no source locations.
275-
assert(APos != AttrPosAsWritten::Unknown &&
276-
"Invalid source location for attribute or decl.");
277-
assert(APos != AttrPosAsWritten::Default &&
278-
"Default not a valid for an attribute location");
279-
if (Pos == AttrPosAsWritten::Default || Pos == APos) {
280-
if (Pos != AttrPosAsWritten::Left)
281-
Out << ' ';
282-
A->printPretty(Out, Policy);
283-
if (Pos == AttrPosAsWritten::Left)
284-
Out << ' ';
285-
}
286-
break;
309+
310+
AttrPrintLoc AttrLoc = AttrPrintLoc::Right;
311+
if (mustPrintOnLeftSide(A)) {
312+
// If we must always print on left side (e.g. declspec), then mark as
313+
// so.
314+
AttrLoc = AttrPrintLoc::Left;
315+
} else if (canPrintOnLeftSide(A)) {
316+
// For functions with body defined we print the attributes on the left
317+
// side so that GCC accept our dumps as well.
318+
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
319+
FD && FD->isThisDeclarationADefinition())
320+
// In case Decl is a function with a body, then attrs should be print
321+
// on the left side.
322+
AttrLoc = AttrPrintLoc::Left;
323+
324+
// In case it is a variable declaration with a ctor, then allow
325+
// printing on the left side for readbility.
326+
else if (const VarDecl *VD = dyn_cast<VarDecl>(D);
327+
VD && VD->getInit() &&
328+
VD->getInitStyle() == VarDecl::CallInit)
329+
AttrLoc = AttrPrintLoc::Left;
287330
}
331+
// Only print the side matches the user requested.
332+
if ((Loc & AttrLoc) != AttrPrintLoc::None)
333+
A->printPretty(Out, Policy);
288334
}
289335
}
290336
}
@@ -645,10 +691,8 @@ static void MaybePrintTagKeywordIfSupressingScopes(PrintingPolicy &Policy,
645691

646692
void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
647693
if (!D->getDescribedFunctionTemplate() &&
648-
!D->isFunctionTemplateSpecialization()) {
694+
!D->isFunctionTemplateSpecialization())
649695
prettyPrintPragmas(D);
650-
prettyPrintAttributes(D, AttrPosAsWritten::Left);
651-
}
652696

653697
if (D->isFunctionTemplateSpecialization())
654698
Out << "template<> ";
@@ -658,6 +702,22 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
658702
printTemplateParameters(D->getTemplateParameterList(I));
659703
}
660704

705+
std::string LeftsideAttrs;
706+
llvm::raw_string_ostream LSAS(LeftsideAttrs);
707+
708+
prettyPrintAttributes(D, LSAS, AttrPrintLoc::Left);
709+
710+
// prettyPrintAttributes print a space on left side of the attribute.
711+
if (LeftsideAttrs[0] == ' ') {
712+
// Skip the space prettyPrintAttributes generated.
713+
LeftsideAttrs.erase(0, LeftsideAttrs.find_first_not_of(' '));
714+
715+
// Add a single space between the attribute and the Decl name.
716+
LSAS << ' ';
717+
}
718+
719+
Out << LeftsideAttrs;
720+
661721
CXXConstructorDecl *CDecl = dyn_cast<CXXConstructorDecl>(D);
662722
CXXConversionDecl *ConversionDecl = dyn_cast<CXXConversionDecl>(D);
663723
CXXDeductionGuideDecl *GuideDecl = dyn_cast<CXXDeductionGuideDecl>(D);
@@ -823,7 +883,7 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
823883
Ty.print(Out, Policy, Proto);
824884
}
825885

826-
prettyPrintAttributes(D, AttrPosAsWritten::Right);
886+
prettyPrintAttributes(D, Out, AttrPrintLoc::Right);
827887

828888
if (D->isPureVirtual())
829889
Out << " = 0";
@@ -916,12 +976,27 @@ void DeclPrinter::VisitLabelDecl(LabelDecl *D) {
916976
void DeclPrinter::VisitVarDecl(VarDecl *D) {
917977
prettyPrintPragmas(D);
918978

919-
prettyPrintAttributes(D, AttrPosAsWritten::Left);
920-
921979
if (const auto *Param = dyn_cast<ParmVarDecl>(D);
922980
Param && Param->isExplicitObjectParameter())
923981
Out << "this ";
924982

983+
std::string LeftSide;
984+
llvm::raw_string_ostream LeftSideStream(LeftSide);
985+
986+
// Print attributes that should be placed on the left, such as __declspec.
987+
prettyPrintAttributes(D, LeftSideStream, AttrPrintLoc::Left);
988+
989+
// prettyPrintAttributes print a space on left side of the attribute.
990+
if (LeftSide[0] == ' ') {
991+
// Skip the space prettyPrintAttributes generated.
992+
LeftSide.erase(0, LeftSide.find_first_not_of(' '));
993+
994+
// Add a single space between the attribute and the Decl name.
995+
LeftSideStream << ' ';
996+
}
997+
998+
Out << LeftSide;
999+
9251000
QualType T = D->getTypeSourceInfo()
9261001
? D->getTypeSourceInfo()->getType()
9271002
: D->getASTContext().getUnqualifiedObjCPointerType(D->getType());
@@ -954,16 +1029,21 @@ void DeclPrinter::VisitVarDecl(VarDecl *D) {
9541029
}
9551030
}
9561031

1032+
StringRef Name;
1033+
1034+
Name = (isa<ParmVarDecl>(D) && Policy.CleanUglifiedParameters &&
1035+
D->getIdentifier())
1036+
? D->getIdentifier()->deuglifiedName()
1037+
: D->getName();
1038+
9571039
if (!Policy.SuppressTagKeyword && Policy.SuppressScope &&
9581040
!Policy.SuppressUnwrittenScope)
9591041
MaybePrintTagKeywordIfSupressingScopes(Policy, T, Out);
1042+
printDeclType(T, Name);
9601043

961-
printDeclType(T, (isa<ParmVarDecl>(D) && Policy.CleanUglifiedParameters &&
962-
D->getIdentifier())
963-
? D->getIdentifier()->deuglifiedName()
964-
: D->getName());
965-
966-
prettyPrintAttributes(D, AttrPosAsWritten::Right);
1044+
// Print the attributes that should be placed right before the end of the
1045+
// decl.
1046+
prettyPrintAttributes(D, Out, AttrPrintLoc::Right);
9671047

9681048
Expr *Init = D->getInit();
9691049
if (!Policy.SuppressInitializers && Init) {

clang/lib/AST/StmtPrinter.cpp

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -292,11 +292,8 @@ void StmtPrinter::VisitLabelStmt(LabelStmt *Node) {
292292
}
293293

294294
void StmtPrinter::VisitAttributedStmt(AttributedStmt *Node) {
295-
llvm::ArrayRef<const Attr *> Attrs = Node->getAttrs();
296-
for (const auto *Attr : Attrs) {
295+
for (const auto *Attr : Node->getAttrs()) {
297296
Attr->printPretty(OS, Policy);
298-
if (Attr != Attrs.back())
299-
OS << ' ';
300297
}
301298

302299
PrintStmt(Node->getSubStmt(), 0);

clang/test/AST/ast-print-method-decl.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ struct DefMethodsWithoutBody {
9494
// CHECK-NEXT: DefMethodsWithoutBody() = default;
9595
~DefMethodsWithoutBody() = default;
9696

97-
// CHECK-NEXT: void m1() __attribute__((alias("X")));
97+
// CHECK-NEXT: __attribute__((alias("X"))) void m1();
9898
void m1() __attribute__((alias("X")));
9999

100100
// CHECK-NEXT: };

clang/test/AST/ast-print-no-sanitize.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,4 @@ void should_not_crash_1() __attribute__((no_sanitize_memory));
44
[[clang::no_sanitize_memory]] void should_not_crash_2();
55

66
// CHECK: void should_not_crash_1() __attribute__((no_sanitize("memory")));
7-
// CHECK: {{\[\[}}clang::no_sanitize("memory"){{\]\]}} void should_not_crash_2();
7+
// CHECK: void should_not_crash_2() {{\[\[}}clang::no_sanitize("memory"){{\]\]}};

clang/test/AST/attr-print-emit.cpp

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -73,18 +73,3 @@ class C {
7373
// CHECK: void pwtt(void *, int) __attribute__((pointer_with_type_tag(foo, 2, 3)));
7474
void pwtt(void *, int) __attribute__((pointer_with_type_tag(foo, 2, 3)));
7575
};
76-
77-
#define ANNOTATE_ATTR __attribute__((annotate("Annotated")))
78-
ANNOTATE_ATTR int annotated_attr ANNOTATE_ATTR = 0;
79-
// CHECK: __attribute__((annotate("Annotated"))) int annotated_attr __attribute__((annotate("Annotated"))) = 0;
80-
81-
// FIXME: We do not print the attribute as written after the type specifier.
82-
int ANNOTATE_ATTR annotated_attr_fixme = 0;
83-
// CHECK: __attribute__((annotate("Annotated"))) int annotated_attr_fixme = 0;
84-
85-
#define NONNULL_ATTR __attribute__((nonnull(1)))
86-
ANNOTATE_ATTR NONNULL_ATTR void fn_non_null_annotated_attr(int *) __attribute__((annotate("AnnotatedRHS")));
87-
// CHECK:__attribute__((annotate("Annotated"))) __attribute__((nonnull(1))) void fn_non_null_annotated_attr(int *) __attribute__((annotate("AnnotatedRHS")));
88-
89-
[[gnu::nonnull(1)]] [[gnu::always_inline]] void cxx11_attr(int*) ANNOTATE_ATTR;
90-
// CHECK: {{\[\[}}gnu::nonnull(1)]] {{\[\[}}gnu::always_inline]] void cxx11_attr(int *) __attribute__((annotate("Annotated")));

clang/test/Analysis/scopes-cfg-output.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1469,7 +1469,7 @@ void test_cleanup_functions2(int m) {
14691469
// CHECK: [B1]
14701470
// CHECK-NEXT: 1: CFGScopeBegin(f)
14711471
// CHECK-NEXT: 2: (CXXConstructExpr, [B1.3], F)
1472-
// CHECK-NEXT: 3: F f __attribute__((cleanup(cleanup_F)));
1472+
// CHECK-NEXT: 3: __attribute__((cleanup(cleanup_F))) F f;
14731473
// CHECK-NEXT: 4: CleanupFunction (cleanup_F)
14741474
// CHECK-NEXT: 5: [B1.3].~F() (Implicit destructor)
14751475
// CHECK-NEXT: 6: CFGScopeEnd(f)

0 commit comments

Comments
 (0)