Update patch to teach printPretty making the decision of print an attribute
or not based on an enum value that identifies where the attribute appears
around declaration and statement. For C++11 attributes, we always print them at
the start of declarations or immediately after declarator-id to make sure they
appertain to declarator rather than a type (since we don't support any such
attribute yet.).
Hi rsmith,
http://llvm-reviews.chandlerc.com/D395
CHANGE SINCE LAST DIFF
http://llvm-reviews.chandlerc.com/D395?vs=1159&id=1315#toc
Files:
utils/TableGen/ClangAttrEmitter.cpp
lib/AST/DeclPrinter.cpp
lib/AST/StmtPrinter.cpp
test/SemaCXX/cxx11-attr-print.cpp
include/clang/AST/Attr.h
Index: utils/TableGen/ClangAttrEmitter.cpp
===================================================================
--- utils/TableGen/ClangAttrEmitter.cpp
+++ utils/TableGen/ClangAttrEmitter.cpp
@@ -755,7 +755,8 @@
std::vector<Record*> Spellings = R.getValueAsListOfDefs("Spellings");
OS << "void " << R.getName() << "Attr::printPretty("
- << "raw_ostream &OS, const PrintingPolicy &Policy) const {\n";
+ << "raw_ostream &OS, const PrintingPolicy &Policy, "
+ << "LocationKind LK) const {\n";
if (Spellings.size() == 0) {
OS << "}\n\n";
@@ -800,10 +801,22 @@
Spelling += Name;
- OS <<
- " case " << I << " : {\n"
- " OS << \"" + Prefix.str() + Spelling.str();
+ OS << " case " << I << " : {\n";
+ // C++11 attributes should be printed only at the start of a declaration,
+ // or immediately after declarator-id to make sure they appertain to
+ // a declaration rather than a type.
+ // We also print C++11 attributes at the start of a statement.
+ if (Variety == "CXX11")
+ OS << " if (LK == 0 || LK == 1 || LK == 3) {\n";
+
+ // C11 _Noreturn attribute should be printed only at the start of
+ // a declaration.
+ if (Variety == "Keyword" && Name == "_Noreturn")
+ OS << " if (LK == 0) {\n";
+
+ OS << " OS << \"" + Prefix.str() + Spelling.str();
+
if (Args.size()) OS << "(";
if (Spelling == "availability") {
writeAvailabilityValue(OS);
@@ -817,7 +830,13 @@
if (Args.size()) OS << ")";
OS << Suffix.str() + "\";\n";
+ // Emit a space after printing the attribute before a declaration.
+ OS << " if (LK == 0) OS << \" \";\n";
+ if (Variety == "CXX11" ||
+ (Variety == "Keyword" && Name == "_Noreturn"))
+ OS << " }\n";
+
OS <<
" break;\n"
" }\n";
@@ -946,7 +965,8 @@
OS << " virtual " << R.getName() << "Attr *clone (ASTContext &C) const;\n";
OS << " virtual void printPretty(raw_ostream &OS,\n"
- << " const PrintingPolicy &Policy) const;\n";
+ << " const PrintingPolicy &Policy,\n"
+ << " LocationKind LC) const;\n";
writeAttrAccessorDefinition(R, OS);
Index: lib/AST/DeclPrinter.cpp
===================================================================
--- lib/AST/DeclPrinter.cpp
+++ lib/AST/DeclPrinter.cpp
@@ -85,7 +85,7 @@
void PrintTemplateParameters(const TemplateParameterList *Params,
const TemplateArgumentList *Args = 0);
- void prettyPrintAttributes(Decl *D);
+ void prettyPrintAttributes(Decl *D, Attr::LocationKind LC);
};
}
@@ -183,7 +183,7 @@
return Out;
}
-void DeclPrinter::prettyPrintAttributes(Decl *D) {
+void DeclPrinter::prettyPrintAttributes(Decl *D, Attr::LocationKind LK) {
if (Policy.PolishForDeclaration)
return;
@@ -191,7 +191,7 @@
AttrVec &Attrs = D->getAttrs();
for (AttrVec::const_iterator i=Attrs.begin(), e=Attrs.end(); i!=e; ++i) {
Attr *A = *i;
- A->printPretty(Out, Policy);
+ A->printPretty(Out, Policy, LK);
}
}
}
@@ -335,7 +335,7 @@
Out << "__module_private__ ";
}
D->getUnderlyingType().print(Out, Policy, D->getName());
- prettyPrintAttributes(D);
+ prettyPrintAttributes(D, Attr::LK_AfterDeclaratorID);
}
void DeclPrinter::VisitTypeAliasDecl(TypeAliasDecl *D) {
@@ -362,7 +362,7 @@
VisitDeclContext(D);
Indent() << "}";
}
- prettyPrintAttributes(D);
+ prettyPrintAttributes(D, Attr::LK_AfterDeclaratorID);
}
void DeclPrinter::VisitRecordDecl(RecordDecl *D) {
@@ -388,6 +388,7 @@
}
void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
+ prettyPrintAttributes(D, Attr::LK_StartOfDecl);
CXXConstructorDecl *CDecl = dyn_cast<CXXConstructorDecl>(D);
if (!Policy.SuppressSpecifiers) {
switch (D->getStorageClassAsWritten()) {
@@ -554,7 +555,7 @@
Ty.print(Out, Policy, Proto);
}
- prettyPrintAttributes(D);
+ prettyPrintAttributes(D, Attr::LK_EndOfDecl);
if (D->isPure())
Out << " = 0";
@@ -629,7 +630,7 @@
Out << " = ";
Init->printPretty(Out, 0, Policy, Indentation);
}
- prettyPrintAttributes(D);
+ prettyPrintAttributes(D, Attr::LK_AfterDeclaratorID);
}
void DeclPrinter::VisitLabelDecl(LabelDecl *D) {
@@ -673,7 +674,7 @@
Out << ")";
}
}
- prettyPrintAttributes(D);
+ prettyPrintAttributes(D, Attr::LK_AfterDeclaratorID);
}
void DeclPrinter::VisitParmVarDecl(ParmVarDecl *D) {
@@ -725,7 +726,7 @@
}
void DeclPrinter::VisitEmptyDecl(EmptyDecl *D) {
- prettyPrintAttributes(D);
+ prettyPrintAttributes(D, Attr::LK_AfterDeclaratorID);
}
void DeclPrinter::VisitCXXRecordDecl(CXXRecordDecl *D) {
Index: lib/AST/StmtPrinter.cpp
===================================================================
--- lib/AST/StmtPrinter.cpp
+++ lib/AST/StmtPrinter.cpp
@@ -182,7 +182,7 @@
first = false;
}
// TODO: check this
- (*it)->printPretty(OS, Policy);
+ (*it)->printPretty(OS, Policy, Attr::LK_StartOfStmt);
}
OS << "]] ";
PrintStmt(Node->getSubStmt(), 0);
Index: test/SemaCXX/cxx11-attr-print.cpp
===================================================================
--- test/SemaCXX/cxx11-attr-print.cpp
+++ test/SemaCXX/cxx11-attr-print.cpp
@@ -31,34 +31,35 @@
// CHECK: int f1() __attribute__((warn_unused_result));
int f1() __attribute__((warn_unused_result));
-// CHECK: {{\[}}[clang::warn_unused_result]];
+// CHECK: {{\[}}[clang::warn_unused_result]] int f2();
int f2 [[clang::warn_unused_result]] ();
-// CHECK: {{\[}}[gnu::warn_unused_result]];
+// CHECK: {{\[}}[gnu::warn_unused_result]] int f3();
int f3 [[gnu::warn_unused_result]] ();
-// FIXME: ast-print need to print C++11
-// attribute after function declare-id.
-// CHECK: {{\[}}[noreturn]];
+// CHECK: {{\[}}[noreturn]] void f4();
void f4 [[noreturn]] ();
-// CHECK: {{\[}}[std::noreturn]];
+// CHECK: {{\[}}[std::noreturn]] void f5();
void f5 [[std::noreturn]] ();
// CHECK: __attribute__((gnu_inline));
inline void f6() __attribute__((gnu_inline));
-// CHECK: {{\[}}[gnu::gnu_inline]];
+// CHECK: {{\[}}[gnu::gnu_inline]] inline void f7();
inline void f7 [[gnu::gnu_inline]] ();
// arguments printing
// CHECK: __attribute__((format("printf", 2, 3)));
void f8 (void *, const char *, ...) __attribute__ ((format (printf, 2, 3)));
+// CHECK: _Noreturn void f9();
+_Noreturn void f9();
+
// CHECK: int m __attribute__((aligned(4
// CHECK: int n alignas(4
// CHECK: static int f() __attribute__((pure))
-// 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;
@@ -73,5 +74,9 @@
// CHECK: int m __attribute__((aligned(4
// CHECK: int n alignas(4
// CHECK: static int f() __attribute__((pure))
-// CHECK: static int g() {{\[}}[gnu::pure]]
+// CHECK: {{\[}}[gnu::pure]] static int g()
template struct S<int>;
+
+// CHECK: {{\[}}[gnu::deprecated("")]] {{\[}}[gnu::pure]] void combo() __attribute__((always_inline));
+void combo [[gnu::pure]] [[gnu::deprecated("")]] () __attribute__((always_inline));
+
Index: include/clang/AST/Attr.h
===================================================================
--- include/clang/AST/Attr.h
+++ include/clang/AST/Attr.h
@@ -62,6 +62,20 @@
}
public:
+ /// \brief Describes the kind of a syntax location where the attribute
+ /// could appear. It is used to print out the attribute at right location.
+ enum LocationKind {
+ /// \brief Attribute appears at the start of a declaration.
+ LK_StartOfDecl,
+ /// \brief Attribute appears after the declarator-id.
+ LK_AfterDeclaratorID,
+ /// \brief Attribute appears at the end of a declaration.
+ LK_EndOfDecl,
+ /// \brief Attribute appears at the start of a statement.
+ LK_StartOfStmt
+ };
+
+public:
// Forward so that the regular new and delete do not hide global ones.
void* operator new(size_t Bytes, ASTContext &C,
size_t Alignment = 16) throw() {
@@ -101,7 +115,8 @@
// Pretty print this attribute.
virtual void printPretty(raw_ostream &OS,
- const PrintingPolicy &Policy) const = 0;
+ const PrintingPolicy &Policy,
+ LocationKind LK) const = 0;
};
class InheritableAttr : public Attr {
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits