[cfe-commits] r145002 - in /cfe/trunk: include/clang/AST/Attr.h lib/AST/DeclPrinter.cpp utils/TableGen/ClangAttrEmitter.cpp

Douglas Gregor dgregor at apple.com
Sat Nov 19 11:22:57 PST 2011


Author: dgregor
Date: Sat Nov 19 13:22:57 2011
New Revision: 145002

URL: http://llvm.org/viewvc/llvm-project?rev=145002&view=rev
Log:
Add support for pretty-printing attributes, from Richard Membarth!

Modified:
    cfe/trunk/include/clang/AST/Attr.h
    cfe/trunk/lib/AST/DeclPrinter.cpp
    cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp

Modified: cfe/trunk/include/clang/AST/Attr.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Attr.h?rev=145002&r1=145001&r2=145002&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Attr.h (original)
+++ cfe/trunk/include/clang/AST/Attr.h Sat Nov 19 13:22:57 2011
@@ -23,6 +23,7 @@
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/StringSwitch.h"
 #include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/raw_ostream.h"
 #include <cassert>
 #include <cstring>
 #include <algorithm>
@@ -103,6 +104,9 @@
   // Clone this attribute.
   virtual Attr* clone(ASTContext &C) const = 0;
 
+  // Pretty print this attribute.
+  virtual void printPretty(llvm::raw_ostream &OS, ASTContext &C) const = 0;
+
   // Implement isa/cast/dyncast/etc.
   static bool classof(const Attr *) { return true; }
 };

Modified: cfe/trunk/lib/AST/DeclPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclPrinter.cpp?rev=145002&r1=145001&r2=145002&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclPrinter.cpp (original)
+++ cfe/trunk/lib/AST/DeclPrinter.cpp Sat Nov 19 13:22:57 2011
@@ -85,6 +85,7 @@
 
     void PrintTemplateParameters(const TemplateParameterList *Params,
                                  const TemplateArgumentList *Args);
+    void prettyPrintAttributes(Decl *D);
   };
 }
 
@@ -182,6 +183,16 @@
   return Out;
 }
 
+void DeclPrinter::prettyPrintAttributes(Decl *D) {
+  if (D->hasAttrs()) {
+    AttrVec &Attrs = D->getAttrs();
+    for (AttrVec::const_iterator i=Attrs.begin(), e=Attrs.end(); i!=e; ++i) {
+        Attr *A = *i;
+        A->printPretty(Out, Context);
+    }
+  }
+}
+
 void DeclPrinter::ProcessDeclGroup(SmallVectorImpl<Decl*>& Decls) {
   this->Indent();
   Decl::printGroup(Decls.data(), Decls.size(), Out, Policy, Indentation);
@@ -320,6 +331,7 @@
       Out << "__module_private__ ";
   }
   Out << S;
+  prettyPrintAttributes(D);
 }
 
 void DeclPrinter::VisitTypeAliasDecl(TypeAliasDecl *D) {
@@ -350,6 +362,7 @@
     VisitDeclContext(D);
     Indent() << "}";
   }
+  prettyPrintAttributes(D);
 }
 
 void DeclPrinter::VisitRecordDecl(RecordDecl *D) {
@@ -466,12 +479,6 @@
       }
     }
 
-    if (D->hasAttr<NoReturnAttr>())
-      Proto += " __attribute((noreturn))";
-
-    if (D->hasAttr<ReturnsTwiceAttr>())
-      Proto += " __attribute((returns_twice))";
-
     if (CXXConstructorDecl *CDecl = dyn_cast<CXXConstructorDecl>(D)) {
       bool HasInitializerList = false;
       for (CXXConstructorDecl::init_const_iterator B = CDecl->init_begin(),
@@ -542,6 +549,7 @@
   }
 
   Out << Proto;
+  prettyPrintAttributes(D);
 
   if (D->isPure())
     Out << " = 0";
@@ -588,6 +596,7 @@
     Out << " = ";
     Init->printPretty(Out, Context, 0, Policy, Indentation);
   }
+  prettyPrintAttributes(D);
 }
 
 void DeclPrinter::VisitLabelDecl(LabelDecl *D) {
@@ -624,6 +633,7 @@
     if (D->hasCXXDirectInitializer())
       Out << ")";
   }
+  prettyPrintAttributes(D);
 }
 
 void DeclPrinter::VisitParmVarDecl(ParmVarDecl *D) {

Modified: cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp?rev=145002&r1=145001&r2=145002&view=diff
==============================================================================
--- cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp (original)
+++ cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp Sat Nov 19 13:22:57 2011
@@ -98,6 +98,7 @@
     virtual void writePCHReadArgs(raw_ostream &OS) const = 0;
     virtual void writePCHReadDecls(raw_ostream &OS) const = 0;
     virtual void writePCHWrite(raw_ostream &OS) const = 0;
+    virtual void writeValue(raw_ostream &OS) const = 0;
   };
 
   class SimpleArgument : public Argument {
@@ -136,6 +137,19 @@
       OS << "    " << WritePCHRecord(type, "SA->get" +
                                            std::string(getUpperName()) + "()");
     }
+    void writeValue(raw_ostream &OS) const {
+      if (type == "FunctionDecl *") {
+        OS << "\" << get" << getUpperName() << "()->getNameInfo().getAsString() << \"";
+      } else if (type == "IdentifierInfo *") {
+        OS << "\" << get" << getUpperName() << "()->getName() << \"";
+      } else if (type == "QualType") {
+        OS << "\" << get" << getUpperName() << "().getAsString() << \"";
+      } else if (type == "SourceLocation") {
+        OS << "\" << get" << getUpperName() << "().getRawEncoding() << \"";
+      } else {
+        OS << "\" << get" << getUpperName() << "() << \"";
+      }
+    }
   };
 
   class StringArgument : public Argument {
@@ -190,6 +204,9 @@
     void writePCHWrite(raw_ostream &OS) const {
       OS << "    AddString(SA->get" << getUpperName() << "(), Record);\n";
     }
+    void writeValue(raw_ostream &OS) const {
+      OS << "\\\"\" << get" << getUpperName() << "() << \"\\\"";
+    }
   };
 
   class AlignedArgument : public Argument {
@@ -293,6 +310,9 @@
       OS << "      AddTypeSourceInfo(SA->get" << getUpperName()
          << "Type(), Record);\n";
     }
+    void writeValue(raw_ostream &OS) const {
+      OS << "\" << get" << getUpperName() << "(Ctx) << \"";
+    }
   };
 
   class VariadicArgument : public Argument {
@@ -362,6 +382,18 @@
          << getLowerName() << "_end(); i != e; ++i)\n";
       OS << "      " << WritePCHRecord(type, "(*i)");
     }
+    void writeValue(raw_ostream &OS) const {
+      OS << "\";\n";
+      OS << "  bool isFirst = true;\n"
+         << "  for (" << getAttrName() << "Attr::" << getLowerName()
+         << "_iterator i = " << getLowerName() << "_begin(), e = "
+         << getLowerName() << "_end(); i != e; ++i) {\n"
+         << "    if (isFirst) isFirst = false;\n"
+         << "    else OS << \", \";\n"
+         << "    OS << *i;\n"
+         << "  }\n";
+      OS << "  OS << \"";
+    }
   };
 
   class EnumArgument : public Argument {
@@ -422,6 +454,9 @@
     void writePCHWrite(raw_ostream &OS) const {
       OS << "Record.push_back(SA->get" << getUpperName() << "());\n";
     }
+    void writeValue(raw_ostream &OS) const {
+      OS << "\" << get" << getUpperName() << "() << \"";
+    }
   };
 
   class VersionArgument : public Argument {
@@ -463,6 +498,9 @@
     void writePCHWrite(raw_ostream &OS) const {
       OS << "    AddVersionTuple(SA->get" << getUpperName() << "(), Record);\n";
     }
+    void writeValue(raw_ostream &OS) const {
+      OS << getLowerName() << "=\" << get" << getUpperName() << "() << \"";
+    }
   };
 }
 
@@ -511,6 +549,15 @@
   return Ptr;
 }
 
+static void writeAvailabilityValue(raw_ostream &OS) {
+  OS << "\" << getPlatform()->getName();\n"
+     << "  if (!getIntroduced().empty()) OS << \", introduced=\" << getIntroduced();\n"
+     << "  if (!getDeprecated().empty()) OS << \", deprecated=\" << getDeprecated();\n"
+     << "  if (!getObsoleted().empty()) OS << \", obsoleted=\" << getObsoleted();\n"
+     << "  if (getUnavailable()) OS << \", unavailable\";\n"
+     << "  OS << \"";
+}
+
 void ClangAttrClassEmitter::run(raw_ostream &OS) {
   OS << "// This file is generated by TableGen. Do not edit.\n\n";
   OS << "#ifndef LLVM_CLANG_ATTR_CLASSES_INC\n";
@@ -571,6 +618,7 @@
     OS << "  }\n\n";
 
     OS << "  virtual " << R.getName() << "Attr *clone (ASTContext &C) const;\n";
+    OS << "  virtual void printPretty(llvm::raw_ostream &OS, ASTContext &Ctx) const;\n";
 
     for (ai = Args.begin(); ai != ae; ++ai) {
       (*ai)->writeAccessors(OS);
@@ -600,6 +648,7 @@
   for (; i != e; ++i) {
     Record &R = **i;
     std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args");
+    std::vector<StringRef> Spellings = getValueAsListOfStrings(R, "Spellings");
     std::vector<Argument*> Args;
     for (ri = ArgRecords.begin(), re = ArgRecords.end(); ri != re; ++ri)
       Args.push_back(createArgument(**ri, R.getName()));
@@ -615,6 +664,24 @@
       (*ai)->writeCloneArgs(OS);
     }
     OS << ");\n}\n\n";
+
+    OS << "void " << R.getName() << "Attr::printPretty("
+       << "llvm::raw_ostream &OS, ASTContext &Ctx) const {\n";
+    if (Spellings.begin() != Spellings.end()) {
+      OS << "  OS << \" __attribute__((" << *Spellings.begin();
+      if (Args.size()) OS << "(";
+      if (*Spellings.begin()=="availability") {
+        writeAvailabilityValue(OS);
+      } else {
+        for (ai = Args.begin(); ai != ae; ++ai) {
+          if (ai!=Args.begin()) OS <<", ";
+          (*ai)->writeValue(OS);
+        }
+      }
+      if (Args.size()) OS << ")";
+      OS << "))\";\n";
+    }
+    OS << "}\n\n";
   }
 }
 





More information about the cfe-commits mailing list