Patch updated. Summary of change:
  - Introduce a new table-gen generated function isCXX11Syntax to Attr.
  - Always print out C++11 attributes of a function declaration after function 
declarator-id to make sure they appertain to function itself.

Hi rsmith,

http://llvm-reviews.chandlerc.com/D395

CHANGE SINCE LAST DIFF
  http://llvm-reviews.chandlerc.com/D395?vs=1120&id=1159#toc

Files:
  include/clang/AST/Attr.h
  utils/TableGen/ClangAttrEmitter.cpp
  lib/AST/DeclPrinter.cpp
  test/SemaCXX/cxx11-attr-print.cpp
Index: include/clang/AST/Attr.h
===================================================================
--- include/clang/AST/Attr.h
+++ include/clang/AST/Attr.h
@@ -102,6 +102,9 @@
   // Pretty print this attribute.
   virtual void printPretty(raw_ostream &OS,
                            const PrintingPolicy &Policy) const = 0;
+
+  /// \brief Return true if the attribute is using C++11 syntax.
+  virtual bool isCXX11Syntax() const = 0;
 };
 
 class InheritableAttr : public Attr {
Index: utils/TableGen/ClangAttrEmitter.cpp
===================================================================
--- utils/TableGen/ClangAttrEmitter.cpp
+++ utils/TableGen/ClangAttrEmitter.cpp
@@ -829,6 +829,48 @@
   OS << "}\n\n";
 }
 
+/// \brief Emit function implementation that tells if the attribute
+/// is using C++11 syntax.
+static void writeIsCXX11SyntaxFunction(Record &R,
+                                       std::vector<Argument*> &Args,
+                                       raw_ostream &OS) {
+  std::vector<Record*> Spellings = R.getValueAsListOfDefs("Spellings");
+
+  OS << "bool " << R.getName() << "Attr::isCXX11Syntax() const {\n";
+
+  // Each attribute defined in Attr.td that has a C++11 syntax also
+  // has a spelling.
+  if (Spellings.size() == 0) {
+    OS << "  return false;\n}\n\n";
+    return;
+  }
+
+  OS << "  switch (SpellingListIndex) {\n";
+
+  for (unsigned I = 0; I < Spellings.size(); ++ I) {
+    std::string Name = Spellings[I]->getValueAsString("Name");
+    std::string Variety = Spellings[I]->getValueAsString("Variety");
+
+    bool Result;
+    if (Variety == "CXX11") {
+      Result = true;
+    } else if (Variety == "Keyword" && (Name == "alignas" ||
+                                        Name == "_Alignas")) {
+      Result = true;
+    } else {
+      Result = false;
+    }
+
+    OS << "  case " << I << " : return " << Result << ";\n";
+  }
+
+  // End of the switch statement.
+  OS << "  }\n";
+  OS << "  llvm_unreachable(\"Unknown attribute spelling!\");\n";
+  // End of the function.
+  OS << "}\n\n";
+}
+
 /// \brief Return the index of a spelling in a spelling list.
 static unsigned getSpellingListIndex(const std::vector<Record*> &SpellingList,
                                      const Record &Spelling) {
@@ -948,6 +990,8 @@
     OS << "  virtual void printPretty(raw_ostream &OS,\n"
        << "                           const PrintingPolicy &Policy) const;\n";
 
+    OS << "  virtual bool isCXX11Syntax() const;\n";
+
     writeAttrAccessorDefinition(R, OS);
 
     for (ai = Args.begin(); ai != ae; ++ai) {
@@ -1003,6 +1047,7 @@
     OS << ", getSpellingListIndex());\n}\n\n";
 
     writePrettyPrintFunction(R, Args, OS);
+    writeIsCXX11SyntaxFunction(R, Args, OS);
   }
 }
 
Index: lib/AST/DeclPrinter.cpp
===================================================================
--- lib/AST/DeclPrinter.cpp
+++ lib/AST/DeclPrinter.cpp
@@ -86,6 +86,8 @@
     void PrintTemplateParameters(const TemplateParameterList *Params,
                                  const TemplateArgumentList *Args = 0);
     void prettyPrintAttributes(Decl *D);
+    /// \brief Pretty print a list of attributes to an output stream.
+    void prettyPrintAttributes(AttrVec &Attrs, llvm::raw_ostream &OS);
   };
 }
 
@@ -186,7 +188,7 @@
 void DeclPrinter::prettyPrintAttributes(Decl *D) {
   if (Policy.PolishForDeclaration)
     return;
-  
+
   if (D->hasAttrs()) {
     AttrVec &Attrs = D->getAttrs();
     for (AttrVec::const_iterator i=Attrs.begin(), e=Attrs.end(); i!=e; ++i) {
@@ -196,6 +198,16 @@
   }
 }
 
+void DeclPrinter::prettyPrintAttributes(AttrVec &Attrs, llvm::raw_ostream &OS) {
+  if (Policy.PolishForDeclaration)
+    return;
+
+  for (AttrVec::const_iterator I = Attrs.begin(),
+                               E = Attrs.end(); I != E; ++I) {
+    (*I)->printPretty(OS, Policy);
+  }
+}
+
 void DeclPrinter::ProcessDeclGroup(SmallVectorImpl<Decl*>& Decls) {
   this->Indent();
   Decl::printGroup(Decls.data(), Decls.size(), Out, Policy, Indentation);
@@ -388,6 +400,21 @@
 }
 
 void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
+  // Classify attributes of D into two groups: C++11 attributes
+  // and none C++11 attributes so we can print them seperately.
+  AttrVec CXX11Attrs, OtherAttrs;
+  if (D->hasAttrs()) {
+    AttrVec Attrs = D->getAttrs();
+    for (AttrVec::const_iterator I = Attrs.begin(),
+                                 E = Attrs.end(); I != E; ++I) {
+      Attr *Attribute = *I;
+      if (Attribute->isCXX11Syntax())
+        CXX11Attrs.push_back(Attribute);
+      else
+        OtherAttrs.push_back(Attribute);
+    }
+  }
+
   CXXConstructorDecl *CDecl = dyn_cast<CXXConstructorDecl>(D);
   if (!Policy.SuppressSpecifiers) {
     switch (D->getStorageClassAsWritten()) {
@@ -417,6 +444,16 @@
   }
 
   if (isa<FunctionType>(Ty)) {
+    // Print C++11 attributes between function declarator-id and
+    // parameter-type-list so these attributes appertain to function
+    // itself.
+    std::string AttrStr;
+    llvm::raw_string_ostream OS(AttrStr);
+    prettyPrintAttributes(CXX11Attrs, OS);
+    Proto += OS.str();
+    if (CXX11Attrs.size())
+      Proto += " ";
+
     const FunctionType *AFT = Ty->getAs<FunctionType>();
     const FunctionProtoType *FT = 0;
     if (D->hasWrittenPrototype())
@@ -554,7 +591,7 @@
     Ty.print(Out, Policy, Proto);
   }
 
-  prettyPrintAttributes(D);
+  prettyPrintAttributes(OtherAttrs, Out);
 
   if (D->isPure())
     Out << " = 0";
Index: test/SemaCXX/cxx11-attr-print.cpp
===================================================================
--- test/SemaCXX/cxx11-attr-print.cpp
+++ test/SemaCXX/cxx11-attr-print.cpp
@@ -31,24 +31,22 @@
 // CHECK: int f1() __attribute__((warn_unused_result));
 int f1() __attribute__((warn_unused_result));
 
-// CHECK: {{\[}}[clang::warn_unused_result]];
+// CHECK: int f2 {{\[}}[clang::warn_unused_result]] ();
 int f2 [[clang::warn_unused_result]] ();
 
-// CHECK: {{\[}}[gnu::warn_unused_result]];
+// CHECK: int f3 {{\[}}[gnu::warn_unused_result]] ();
 int f3 [[gnu::warn_unused_result]] ();
 
-// FIXME: ast-print need to print C++11
-// attribute after function declare-id.
-// CHECK: {{\[}}[noreturn]];
+// CHECK: void f4 {{\[}}[noreturn]] ();
 void f4 [[noreturn]] ();
 
-// CHECK: {{\[}}[std::noreturn]];
+// CHECK: void f5 {{\[}}[std::noreturn]] ();
 void f5 [[std::noreturn]] ();
 
 // CHECK: __attribute__((gnu_inline));
 inline void f6() __attribute__((gnu_inline));
 
-// CHECK: {{\[}}[gnu::gnu_inline]];
+// CHECK: inline void f7 {{\[}}[gnu::gnu_inline]] ();
 inline void f7 [[gnu::gnu_inline]] ();
 
 // arguments printing
@@ -58,7 +56,7 @@
 // CHECK: int m __attribute__((aligned(4
 // CHECK: int n alignas(4
 // CHECK: static int f() __attribute__((pure))
-// CHECK: static int g() {{\[}}[gnu::pure]]
+// CHECK: static int g {{\[}}[gnu::pure]] ()
 template <typename T> struct S {
   __attribute__((aligned(4))) int m;
   alignas(4) int n;
@@ -73,5 +71,8 @@
 // CHECK: int m __attribute__((aligned(4
 // CHECK: int n alignas(4
 // CHECK: static int f() __attribute__((pure))
-// CHECK: static int g() {{\[}}[gnu::pure]]
+// CHECK: static int g {{\[}}[gnu::pure]] ()
 template struct S<int>;
+
+// CHECK: void combo {{\[}}[gnu::deprecated("")]] {{\[}}[gnu::pure]] () __attribute__((always_inline));
+void combo [[gnu::pure]] [[gnu::deprecated("")]] () __attribute__((always_inline));
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to