21
21
#include " clang/AST/ExprCXX.h"
22
22
#include " clang/AST/PrettyPrinter.h"
23
23
#include " clang/Basic/Module.h"
24
- #include " clang/Basic/SourceManager.h"
25
24
#include " llvm/Support/raw_ostream.h"
26
25
using namespace clang ;
27
26
@@ -50,6 +49,18 @@ namespace {
50
49
51
50
void PrintObjCTypeParams (ObjCTypeParamList *Params);
52
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
+
53
64
public:
54
65
DeclPrinter (raw_ostream &Out, const PrintingPolicy &Policy,
55
66
const ASTContext &Context, unsigned Indentation = 0 ,
@@ -118,10 +129,11 @@ namespace {
118
129
const TemplateParameterList *Params);
119
130
void printTemplateArguments (llvm::ArrayRef<TemplateArgumentLoc> Args,
120
131
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
+
125
137
void prettyPrintPragmas (Decl *D);
126
138
void printDeclType (QualType T, StringRef DeclName, bool Pack = false );
127
139
};
@@ -238,53 +250,87 @@ raw_ostream& DeclPrinter::Indent(unsigned Indentation) {
238
250
return Out;
239
251
}
240
252
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"
248
255
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 "
251
258
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 ());
253
277
}
254
278
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) {
257
301
if (Policy.PolishForDeclaration )
258
302
return ;
259
303
260
304
if (D->hasAttrs ()) {
261
- assert (Pos != AttrPosAsWritten::Unknown && " Use Default" );
262
- const AttrVec &Attrs = D->getAttrs ();
305
+ AttrVec &Attrs = D->getAttrs ();
263
306
for (auto *A : Attrs) {
264
307
if (A->isInherited () || A->isImplicit ())
265
308
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 ;
287
330
}
331
+ // Only print the side matches the user requested.
332
+ if ((Loc & AttrLoc) != AttrPrintLoc::None)
333
+ A->printPretty (Out, Policy);
288
334
}
289
335
}
290
336
}
@@ -645,10 +691,8 @@ static void MaybePrintTagKeywordIfSupressingScopes(PrintingPolicy &Policy,
645
691
646
692
void DeclPrinter::VisitFunctionDecl (FunctionDecl *D) {
647
693
if (!D->getDescribedFunctionTemplate () &&
648
- !D->isFunctionTemplateSpecialization ()) {
694
+ !D->isFunctionTemplateSpecialization ())
649
695
prettyPrintPragmas (D);
650
- prettyPrintAttributes (D, AttrPosAsWritten::Left);
651
- }
652
696
653
697
if (D->isFunctionTemplateSpecialization ())
654
698
Out << " template<> " ;
@@ -658,6 +702,22 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
658
702
printTemplateParameters (D->getTemplateParameterList (I));
659
703
}
660
704
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
+
661
721
CXXConstructorDecl *CDecl = dyn_cast<CXXConstructorDecl>(D);
662
722
CXXConversionDecl *ConversionDecl = dyn_cast<CXXConversionDecl>(D);
663
723
CXXDeductionGuideDecl *GuideDecl = dyn_cast<CXXDeductionGuideDecl>(D);
@@ -823,7 +883,7 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
823
883
Ty.print (Out, Policy, Proto);
824
884
}
825
885
826
- prettyPrintAttributes (D, AttrPosAsWritten ::Right);
886
+ prettyPrintAttributes (D, Out, AttrPrintLoc ::Right);
827
887
828
888
if (D->isPureVirtual ())
829
889
Out << " = 0" ;
@@ -916,12 +976,27 @@ void DeclPrinter::VisitLabelDecl(LabelDecl *D) {
916
976
void DeclPrinter::VisitVarDecl (VarDecl *D) {
917
977
prettyPrintPragmas (D);
918
978
919
- prettyPrintAttributes (D, AttrPosAsWritten::Left);
920
-
921
979
if (const auto *Param = dyn_cast<ParmVarDecl>(D);
922
980
Param && Param->isExplicitObjectParameter ())
923
981
Out << " this " ;
924
982
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
+
925
1000
QualType T = D->getTypeSourceInfo ()
926
1001
? D->getTypeSourceInfo ()->getType ()
927
1002
: D->getASTContext ().getUnqualifiedObjCPointerType (D->getType ());
@@ -954,16 +1029,21 @@ void DeclPrinter::VisitVarDecl(VarDecl *D) {
954
1029
}
955
1030
}
956
1031
1032
+ StringRef Name;
1033
+
1034
+ Name = (isa<ParmVarDecl>(D) && Policy.CleanUglifiedParameters &&
1035
+ D->getIdentifier ())
1036
+ ? D->getIdentifier ()->deuglifiedName ()
1037
+ : D->getName ();
1038
+
957
1039
if (!Policy.SuppressTagKeyword && Policy.SuppressScope &&
958
1040
!Policy.SuppressUnwrittenScope )
959
1041
MaybePrintTagKeywordIfSupressingScopes (Policy, T, Out);
1042
+ printDeclType (T, Name);
960
1043
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);
967
1047
968
1048
Expr *Init = D->getInit ();
969
1049
if (!Policy.SuppressInitializers && Init) {
0 commit comments