@@ -49,6 +49,18 @@ namespace {
49
49
50
50
void PrintObjCTypeParams (ObjCTypeParamList *Params);
51
51
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
+
52
64
public:
53
65
DeclPrinter (raw_ostream &Out, const PrintingPolicy &Policy,
54
66
const ASTContext &Context, unsigned Indentation = 0 ,
@@ -117,7 +129,11 @@ namespace {
117
129
const TemplateParameterList *Params);
118
130
void printTemplateArguments (llvm::ArrayRef<TemplateArgumentLoc> Args,
119
131
const TemplateParameterList *Params);
120
- void prettyPrintAttributes (Decl *D);
132
+
133
+ inline void prettyPrintAttributes (Decl *D) {
134
+ prettyPrintAttributes (D, Out);
135
+ }
136
+
121
137
void prettyPrintPragmas (Decl *D);
122
138
void printDeclType (QualType T, StringRef DeclName, bool Pack = false );
123
139
};
@@ -234,7 +250,40 @@ raw_ostream& DeclPrinter::Indent(unsigned Indentation) {
234
250
return Out;
235
251
}
236
252
237
- void DeclPrinter::prettyPrintAttributes (Decl *D) {
253
+ static bool canPrintOnLeftSide (attr::Kind kind) {
254
+ switch (kind) {
255
+ #include " clang/Basic/AttrLeftSideCanPrintList.inc"
256
+ return true ;
257
+ default :
258
+ return false ;
259
+ }
260
+ }
261
+
262
+ static bool canPrintOnLeftSide (const Attr *A) {
263
+ if (A->isStandardAttributeSyntax ())
264
+ return false ;
265
+
266
+ return canPrintOnLeftSide (A->getKind ());
267
+ }
268
+
269
+ static bool mustPrintOnLeftSide (attr::Kind kind) {
270
+ switch (kind) {
271
+ #include " clang/Basic/AttrLeftSideMustPrintList.inc"
272
+ return true ;
273
+ default :
274
+ return false ;
275
+ }
276
+ }
277
+
278
+ static bool mustPrintOnLeftSide (const Attr *A) {
279
+ if (A->isDeclspecAttribute ())
280
+ return true ;
281
+
282
+ return mustPrintOnLeftSide (A->getKind ());
283
+ }
284
+
285
+ void DeclPrinter::prettyPrintAttributes (Decl *D, llvm::raw_ostream &Out,
286
+ AttrPrintLoc Loc) {
238
287
if (Policy.PolishForDeclaration )
239
288
return ;
240
289
@@ -243,15 +292,32 @@ void DeclPrinter::prettyPrintAttributes(Decl *D) {
243
292
for (auto *A : Attrs) {
244
293
if (A->isInherited () || A->isImplicit ())
245
294
continue ;
246
- switch (A->getKind ()) {
247
- #define ATTR (X )
248
- #define PRAGMA_SPELLING_ATTR (X ) case attr::X:
249
- #include " clang/Basic/AttrList.inc"
250
- break ;
251
- default :
252
- A->printPretty (Out, Policy);
253
- break ;
295
+
296
+ AttrPrintLoc AttrLoc = AttrPrintLoc::Right;
297
+ if (mustPrintOnLeftSide (A)) {
298
+ // If we must always print on left side (e.g. declspec), then mark as
299
+ // so.
300
+ AttrLoc = AttrPrintLoc::Left;
301
+ } else if (canPrintOnLeftSide (A)) {
302
+ // For functions with body defined we print the attributes on the left
303
+ // side so that GCC accept our dumps as well.
304
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
305
+ FD && FD->isThisDeclarationADefinition ())
306
+ // In case Decl is a function with a body, then attrs should be print
307
+ // on the left side.
308
+ AttrLoc = AttrPrintLoc::Left;
309
+
310
+ // In case it is a variable declaration with a ctor, then allow
311
+ // printing on the left side for readbility.
312
+ else if (const VarDecl *VD = dyn_cast<VarDecl>(D);
313
+ VD && VD->getInit () &&
314
+ VD->getInitStyle () == VarDecl::CallInit)
315
+ AttrLoc = AttrPrintLoc::Left;
254
316
}
317
+
318
+ // Only print the side matches the user requested.
319
+ if ((Loc & AttrLoc) != AttrPrintLoc::None)
320
+ A->printPretty (Out, Policy);
255
321
}
256
322
}
257
323
}
@@ -613,6 +679,22 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
613
679
printTemplateParameters (D->getTemplateParameterList (I));
614
680
}
615
681
682
+ std::string LeftsideAttrs;
683
+ llvm::raw_string_ostream LSAS (LeftsideAttrs);
684
+
685
+ prettyPrintAttributes (D, LSAS, AttrPrintLoc::Left);
686
+
687
+ // prettyPrintAttributes print a space on left side of the attribute.
688
+ if (LeftsideAttrs[0 ] == ' ' ) {
689
+ // Skip the space prettyPrintAttributes generated.
690
+ LeftsideAttrs.erase (0 , LeftsideAttrs.find_first_not_of (' ' ));
691
+
692
+ // Add a single space between the attribute and the Decl name.
693
+ LSAS << ' ' ;
694
+ }
695
+
696
+ Out << LeftsideAttrs;
697
+
616
698
CXXConstructorDecl *CDecl = dyn_cast<CXXConstructorDecl>(D);
617
699
CXXConversionDecl *ConversionDecl = dyn_cast<CXXConversionDecl>(D);
618
700
CXXDeductionGuideDecl *GuideDecl = dyn_cast<CXXDeductionGuideDecl>(D);
@@ -774,7 +856,7 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
774
856
Ty.print (Out, Policy, Proto);
775
857
}
776
858
777
- prettyPrintAttributes (D);
859
+ prettyPrintAttributes (D, Out, AttrPrintLoc::Right );
778
860
779
861
if (D->isPure ())
780
862
Out << " = 0" ;
@@ -867,6 +949,23 @@ void DeclPrinter::VisitLabelDecl(LabelDecl *D) {
867
949
void DeclPrinter::VisitVarDecl (VarDecl *D) {
868
950
prettyPrintPragmas (D);
869
951
952
+ std::string LeftSide;
953
+ llvm::raw_string_ostream LeftSideStream (LeftSide);
954
+
955
+ // Print attributes that should be placed on the left, such as __declspec.
956
+ prettyPrintAttributes (D, LeftSideStream, AttrPrintLoc::Left);
957
+
958
+ // prettyPrintAttributes print a space on left side of the attribute.
959
+ if (LeftSide[0 ] == ' ' ) {
960
+ // Skip the space prettyPrintAttributes generated.
961
+ LeftSide.erase (0 , LeftSide.find_first_not_of (' ' ));
962
+
963
+ // Add a single space between the attribute and the Decl name.
964
+ LeftSideStream << ' ' ;
965
+ }
966
+
967
+ Out << LeftSide;
968
+
870
969
QualType T = D->getTypeSourceInfo ()
871
970
? D->getTypeSourceInfo ()->getType ()
872
971
: D->getASTContext ().getUnqualifiedObjCPointerType (D->getType ());
@@ -899,10 +998,19 @@ void DeclPrinter::VisitVarDecl(VarDecl *D) {
899
998
}
900
999
}
901
1000
902
- printDeclType (T, (isa<ParmVarDecl>(D) && Policy.CleanUglifiedParameters &&
903
- D->getIdentifier ())
904
- ? D->getIdentifier ()->deuglifiedName ()
905
- : D->getName ());
1001
+ StringRef Name;
1002
+
1003
+ Name = (isa<ParmVarDecl>(D) && Policy.CleanUglifiedParameters &&
1004
+ D->getIdentifier ())
1005
+ ? D->getIdentifier ()->deuglifiedName ()
1006
+ : D->getName ();
1007
+
1008
+ printDeclType (T, Name);
1009
+
1010
+ // Print the attributes that should be placed right before the end of the
1011
+ // decl.
1012
+ prettyPrintAttributes (D, Out, AttrPrintLoc::Right);
1013
+
906
1014
Expr *Init = D->getInit ();
907
1015
if (!Policy.SuppressInitializers && Init) {
908
1016
bool ImplicitInit = false ;
@@ -931,7 +1039,6 @@ void DeclPrinter::VisitVarDecl(VarDecl *D) {
931
1039
Out << " )" ;
932
1040
}
933
1041
}
934
- prettyPrintAttributes (D);
935
1042
}
936
1043
937
1044
void DeclPrinter::VisitParmVarDecl (ParmVarDecl *D) {
0 commit comments