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

Reply via email to