<div dir="ltr"><div class="gmail_default" style>Does r171808 fix the issue?</div><div class="gmail_extra"><br><br><div class="gmail_quote">On Mon, Jan 7, 2013 at 11:38 PM, David Dean <span dir="ltr"><<a href="mailto:david_dean@apple.com" target="_blank">david_dean@apple.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">I'm seeing the following test failure on darwin:<br>
<br>
******************** TEST 'Clang :: Misc/ast-dump-attr.cpp' FAILED ********************Script:<br>
--<br>
/Users/buildslave/zorg/buildbot/smooshlab/slave-0.8/build.clang-x86_64-darwin10-nobootstrap-RA/clang-build/Release+Asserts/bin/clang -cc1 -internal-isystem /Users/buildslave/zorg/buildbot/smooshlab/slave-0.8/build.clang-x86_64-darwin10-nobootstrap-RA/clang-build/Release+Asserts/bin/../lib/clang/3.3/include -std=c++11 -ast-dump -ast-dump-filter Test /Users/buildslave/zorg/buildbot/smooshlab/slave-0.8/build.clang-x86_64-darwin10-nobootstrap-RA/clang.src/test/Misc/ast-dump-attr.cpp | FileCheck --strict-whitespace /Users/buildslave/zorg/buildbot/smooshlab/slave-0.8/build.clang-x86_64-darwin10-nobootstrap-RA/clang.src/test/Misc/ast-dump-attr.cpp<br>

--<br>
Exit Code: 1<br>
Command Output (stderr):<br>
--<br>
/Users/buildslave/zorg/buildbot/smooshlab/slave-0.8/build.clang-x86_64-darwin10-nobootstrap-RA/clang.src/test/Misc/ast-dump-attr.cpp:82:31: error: only weak aliases are supported on darwin<br>
<div class="im">int TestString __attribute__((alias("alias1")));<br>
                              ^<br>
1 error generated.<br>
</div>/Users/buildslave/zorg/buildbot/smooshlab/slave-0.8/build.clang-x86_64-darwin10-nobootstrap-RA/clang.src/test/Misc/ast-dump-attr.cpp:84:18: error: expected string not found in input<br>
<div class="im">// CHECK-NEXT:   AliasAttr{{.*}} "alias1"<br>
                 ^<br>
</div><stdin>:84:180: note: scanning from here<br>
(VarDecl 0x10285abf0 </Users/buildslave/zorg/buildbot/smooshlab/slave-0.8/build.clang-x86_64-darwin10-nobootstrap-RA/clang.src/test/Misc/ast-dump-attr.cpp:82:1, col:5> TestString 'int')<br>
                                                                                                                                                                                   ^<br>
<stdin>:93:7: note: possible intended match here<br>
  (AllocSizeAttr 0x10285afd0 <col:49, col:61> 0))<br>
      ^<br>
--<br>
<br>
********************<br>
<div class="HOEnZb"><div class="h5">On 7 Jan 2013, at 9:53 AM, Alexander Kornienko <<a href="mailto:alexfh@google.com">alexfh@google.com</a>> wrote:<br>
<br>
> Author: alexfh<br>
> Date: Mon Jan  7 11:53:08 2013<br>
> New Revision: 171760<br>
><br>
> URL: <a href="http://llvm.org/viewvc/llvm-project?rev=171760&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=171760&view=rev</a><br>
> Log:<br>
> Implement Attr dumping for -ast-dump.<br>
> <a href="http://llvm-reviews.chandlerc.com/D234" target="_blank">http://llvm-reviews.chandlerc.com/D234</a><br>
><br>
> Patch by Philip Craig!<br>
><br>
> Added:<br>
>    cfe/trunk/test/Misc/ast-dump-attr.cpp<br>
> Modified:<br>
>    cfe/trunk/include/clang/AST/CMakeLists.txt<br>
>    cfe/trunk/include/clang/AST/Makefile<br>
>    cfe/trunk/lib/AST/ASTDumper.cpp<br>
>    cfe/trunk/lib/AST/CMakeLists.txt<br>
>    cfe/trunk/test/Tooling/clang-check-ast-dump.cpp<br>
>    cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp<br>
>    cfe/trunk/utils/TableGen/TableGen.cpp<br>
>    cfe/trunk/utils/TableGen/TableGenBackends.h<br>
><br>
> Modified: cfe/trunk/include/clang/AST/CMakeLists.txt<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/CMakeLists.txt?rev=171760&r1=171759&r2=171760&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/CMakeLists.txt?rev=171760&r1=171759&r2=171760&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/include/clang/AST/CMakeLists.txt (original)<br>
> +++ cfe/trunk/include/clang/AST/CMakeLists.txt Mon Jan  7 11:53:08 2013<br>
> @@ -8,6 +8,11 @@<br>
>   SOURCE ../Basic/Attr.td<br>
>   TARGET ClangAttrImpl)<br>
><br>
> +clang_tablegen(AttrDump.inc -gen-clang-attr-dump<br>
> +  -I ${CMAKE_CURRENT_SOURCE_DIR}/../../<br>
> +  SOURCE ../Basic/Attr.td<br>
> +  TARGET ClangAttrDump)<br>
> +<br>
> clang_tablegen(StmtNodes.inc -gen-clang-stmt-nodes<br>
>   SOURCE ../Basic/StmtNodes.td<br>
>   TARGET ClangStmtNodes)<br>
><br>
> Modified: cfe/trunk/include/clang/AST/Makefile<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Makefile?rev=171760&r1=171759&r2=171760&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Makefile?rev=171760&r1=171759&r2=171760&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/include/clang/AST/Makefile (original)<br>
> +++ cfe/trunk/include/clang/AST/Makefile Mon Jan  7 11:53:08 2013<br>
> @@ -1,6 +1,7 @@<br>
> CLANG_LEVEL := ../../..<br>
> TD_SRC_DIR = $(PROJ_SRC_DIR)/../Basic<br>
> -BUILT_SOURCES = Attrs.inc AttrImpl.inc StmtNodes.inc DeclNodes.inc \<br>
> +BUILT_SOURCES = Attrs.inc AttrImpl.inc AttrDump.inc \<br>
> +                StmtNodes.inc DeclNodes.inc \<br>
>                 CommentNodes.inc CommentHTMLTags.inc \<br>
>                 CommentHTMLTagsProperties.inc CommentCommandInfo.inc<br>
><br>
> @@ -20,6 +21,12 @@<br>
>       $(Verb) $(ClangTableGen) -gen-clang-attr-impl -o $(call SYSPATH, $@) \<br>
>               -I $(PROJ_SRC_DIR)/../../ $<<br>
><br>
> +$(ObjDir)/AttrDump.inc.tmp : $(TD_SRC_DIR)/Attr.td $(CLANG_TBLGEN) \<br>
> +                              $(ObjDir)/.dir<br>
> +     $(Echo) "Building Clang attribute dumper with tblgen"<br>
> +     $(Verb) $(ClangTableGen) -gen-clang-attr-dump -o $(call SYSPATH, $@) \<br>
> +             -I $(PROJ_SRC_DIR)/../../ $<<br>
> +<br>
> $(ObjDir)/StmtNodes.inc.tmp : $(TD_SRC_DIR)/StmtNodes.td $(CLANG_TBLGEN) \<br>
>                               $(ObjDir)/.dir<br>
>       $(Echo) "Building Clang statement node tables with tblgen"<br>
><br>
> Modified: cfe/trunk/lib/AST/ASTDumper.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTDumper.cpp?rev=171760&r1=171759&r2=171760&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTDumper.cpp?rev=171760&r1=171759&r2=171760&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/lib/AST/ASTDumper.cpp (original)<br>
> +++ cfe/trunk/lib/AST/ASTDumper.cpp Mon Jan  7 11:53:08 2013<br>
> @@ -13,6 +13,7 @@<br>
> //===----------------------------------------------------------------------===//<br>
><br>
> #include "clang/AST/ASTContext.h"<br>
> +#include "clang/AST/Attr.h"<br>
> #include "clang/AST/DeclCXX.h"<br>
> #include "clang/AST/DeclObjC.h"<br>
> #include "clang/AST/DeclVisitor.h"<br>
> @@ -74,6 +75,7 @@<br>
>     void dumpDeclRef(const Decl *Node, const char *Label = 0);<br>
>     void dumpName(const NamedDecl *D);<br>
>     void dumpDeclContext(const DeclContext *DC);<br>
> +    void dumpAttr(const Attr *A);<br>
><br>
>     // C++ Utilities<br>
>     void dumpAccessSpecifier(AccessSpecifier AS);<br>
> @@ -141,6 +143,7 @@<br>
>     // Stmts.<br>
>     void VisitStmt(Stmt *Node);<br>
>     void VisitDeclStmt(DeclStmt *Node);<br>
> +    void VisitAttributedStmt(AttributedStmt *Node);<br>
>     void VisitLabelStmt(LabelStmt *Node);<br>
>     void VisitGotoStmt(GotoStmt *Node);<br>
><br>
> @@ -308,6 +311,19 @@<br>
>     dumpDecl(*I);<br>
> }<br>
><br>
> +void ASTDumper::dumpAttr(const Attr *A) {<br>
> +  IndentScope Indent(*this);<br>
> +  switch (A->getKind()) {<br>
> +#define ATTR(X) case attr::X: OS << #X; break;<br>
> +#include "clang/Basic/AttrList.inc"<br>
> +  default: llvm_unreachable("unexpected attribute kind");<br>
> +  }<br>
> +  OS << "Attr";<br>
> +  dumpPointer(A);<br>
> +  dumpSourceRange(A->getRange());<br>
> +#include "clang/AST/AttrDump.inc"<br>
> +}<br>
> +<br>
> //===----------------------------------------------------------------------===//<br>
> //  C++ Utilities<br>
> //===----------------------------------------------------------------------===//<br>
> @@ -425,6 +441,11 @@<br>
>   dumpPointer(D);<br>
>   dumpSourceRange(D->getSourceRange());<br>
>   DeclVisitor<ASTDumper>::Visit(D);<br>
> +  if (D->hasAttrs()) {<br>
> +    for (AttrVec::const_iterator I = D->getAttrs().begin(),<br>
> +         E = D->getAttrs().end(); I != E; ++I)<br>
> +      dumpAttr(*I);<br>
> +  }<br>
>   // Decls within functions are visited by the body<br>
>   if (!isa<FunctionDecl>(*D) && !isa<ObjCMethodDecl>(*D))<br>
>     dumpDeclContext(dyn_cast<DeclContext>(D));<br>
> @@ -959,6 +980,13 @@<br>
>     dumpDecl(*I);<br>
> }<br>
><br>
> +void ASTDumper::VisitAttributedStmt(AttributedStmt *Node) {<br>
> +  VisitStmt(Node);<br>
> +  for (ArrayRef<const Attr*>::iterator I = Node->getAttrs().begin(),<br>
> +       E = Node->getAttrs().end(); I != E; ++I)<br>
> +    dumpAttr(*I);<br>
> +}<br>
> +<br>
> void ASTDumper::VisitLabelStmt(LabelStmt *Node) {<br>
>   VisitStmt(Node);<br>
>   OS << " '" << Node->getName() << "'";<br>
><br>
> Modified: cfe/trunk/lib/AST/CMakeLists.txt<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/CMakeLists.txt?rev=171760&r1=171759&r2=171760&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/CMakeLists.txt?rev=171760&r1=171759&r2=171760&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/lib/AST/CMakeLists.txt (original)<br>
> +++ cfe/trunk/lib/AST/CMakeLists.txt Mon Jan  7 11:53:08 2013<br>
> @@ -64,6 +64,7 @@<br>
>   ClangAttrClasses<br>
>   ClangAttrList<br>
>   ClangAttrImpl<br>
> +  ClangAttrDump<br>
>   ClangCommentCommandInfo<br>
>   ClangCommentNodes<br>
>   ClangCommentHTMLTags<br>
><br>
> Added: cfe/trunk/test/Misc/ast-dump-attr.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Misc/ast-dump-attr.cpp?rev=171760&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Misc/ast-dump-attr.cpp?rev=171760&view=auto</a><br>

> ==============================================================================<br>
> --- cfe/trunk/test/Misc/ast-dump-attr.cpp (added)<br>
> +++ cfe/trunk/test/Misc/ast-dump-attr.cpp Mon Jan  7 11:53:08 2013<br>
> @@ -0,0 +1,97 @@<br>
> +// RUN: %clang_cc1 -std=c++11 -ast-dump -ast-dump-filter Test %s | FileCheck --strict-whitespace %s<br>
> +<br>
> +int TestLocation<br>
> +__attribute__((unused));<br>
> +// CHECK:      VarDecl{{.*}}TestLocation<br>
> +// CHECK-NEXT:   UnusedAttr 0x{{[^ ]*}} <line:[[@LINE-2]]:16><br>
> +<br>
> +int TestIndent<br>
> +__attribute__((unused));<br>
> +// CHECK:      {{^\(VarDecl.*TestIndent[^()]*$}}<br>
> +// CHECK-NEXT: {{^  \(UnusedAttr[^()]*\)\)$}}<br>
> +<br>
> +void TestAttributedStmt() {<br>
> +  switch (1) {<br>
> +  case 1:<br>
> +    [[clang::fallthrough]];<br>
> +  case 2:<br>
> +    ;<br>
> +  }<br>
> +}<br>
> +// CHECK:      FunctionDecl{{.*}}TestAttributedStmt<br>
> +// CHECK:      AttributedStmt<br>
> +// CHECK-NEXT:   FallThroughAttr<br>
> +// CHECK-NEXT:   NullStmt<br>
> +<br>
> +[[clang::warn_unused_result]] int TestCXX11DeclAttr();<br>
> +// CHECK:      FunctionDecl{{.*}}TestCXX11DeclAttr<br>
> +// CHECK-NEXT:   WarnUnusedResultAttr<br>
> +<br>
> +int TestAlignedNull __attribute__((aligned));<br>
> +// CHECK:      VarDecl{{.*}}TestAlignedNull<br>
> +// CHECK-NEXT:   AlignedAttr<br>
> +// CHECK-NEXT:     <<<NULL>>><br>
> +<br>
> +int TestAlignedExpr __attribute__((aligned(4)));<br>
> +// CHECK:      VarDecl{{.*}}TestAlignedExpr<br>
> +// CHECK-NEXT:   AlignedAttr<br>
> +// CHECK-NEXT:     IntegerLiteral<br>
> +<br>
> +int TestEnum __attribute__((visibility("default")));<br>
> +// CHECK:      VarDecl{{.*}}TestEnum<br>
> +// CHECK-NEXT:   VisibilityAttr{{.*}} Default<br>
> +<br>
> +class __attribute__((lockable)) Mutex {<br>
> +} mu1, mu2;<br>
> +int TestExpr __attribute__((guarded_by(mu1)));<br>
> +// CHECK:      VarDecl{{.*}}TestExpr<br>
> +// CHECK-NEXT:   GuardedByAttr<br>
> +// CHECK-NEXT:     DeclRefExpr{{.*}}mu1<br>
> +<br>
> +class Mutex TestVariadicExpr __attribute__((acquired_after(mu1, mu2)));<br>
> +// CHECK:      VarDecl{{.*}}TestVariadicExpr<br>
> +// CHECK:        AcquiredAfterAttr<br>
> +// CHECK-NEXT:     DeclRefExpr{{.*}}mu1<br>
> +// CHECK-NEXT:     DeclRefExpr{{.*}}mu2<br>
> +<br>
> +void function1(void *) {<br>
> +  int TestFunction __attribute__((cleanup(function1)));<br>
> +}<br>
> +// CHECK:      VarDecl{{.*}}TestFunction<br>
> +// CHECK-NEXT:   CleanupAttr{{.*}} Function{{.*}}function1<br>
> +<br>
> +void TestIdentifier(void *, int)<br>
> +__attribute__((pointer_with_type_tag(ident1,1,2)));<br>
> +// CHECK: FunctionDecl{{.*}}TestIdentifier<br>
> +// CHECK:   ArgumentWithTypeTagAttr{{.*}} ident1<br>
> +<br>
> +void TestBool(void *, int)<br>
> +__attribute__((pointer_with_type_tag(bool1,1,2)));<br>
> +// CHECK: FunctionDecl{{.*}}TestBool<br>
> +// CHECK:   ArgumentWithTypeTagAttr{{.*}} IsPointer<br>
> +<br>
> +void TestUnsigned(void *, int)<br>
> +__attribute__((pointer_with_type_tag(unsigned1,1,2)));<br>
> +// CHECK: FunctionDecl{{.*}}TestUnsigned<br>
> +// CHECK:   ArgumentWithTypeTagAttr{{.*}} 0 1<br>
> +<br>
> +void TestInt(void) __attribute__((constructor(123)));<br>
> +// CHECK:      FunctionDecl{{.*}}TestInt<br>
> +// CHECK-NEXT:   ConstructorAttr{{.*}} 123<br>
> +<br>
> +int TestString __attribute__((alias("alias1")));<br>
> +// CHECK:      VarDecl{{.*}}TestString<br>
> +// CHECK-NEXT:   AliasAttr{{.*}} "alias1"<br>
> +<br>
> +extern struct s1 TestType<br>
> +__attribute__((type_tag_for_datatype(ident1,int)));<br>
> +// CHECK:      VarDecl{{.*}}TestType<br>
> +// CHECK-NEXT:   TypeTagForDatatypeAttr{{.*}} int<br>
> +<br>
> +void *TestVariadicUnsigned1(int) __attribute__((alloc_size(1)));<br>
> +// CHECK: FunctionDecl{{.*}}TestVariadicUnsigned1<br>
> +// CHECK:   AllocSizeAttr{{.*}} 0<br>
> +<br>
> +void *TestVariadicUnsigned2(int, int) __attribute__((alloc_size(1,2)));<br>
> +// CHECK: FunctionDecl{{.*}}TestVariadicUnsigned2<br>
> +// CHECK:   AllocSizeAttr{{.*}} 0 1<br>
><br>
> Modified: cfe/trunk/test/Tooling/clang-check-ast-dump.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Tooling/clang-check-ast-dump.cpp?rev=171760&r1=171759&r2=171760&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Tooling/clang-check-ast-dump.cpp?rev=171760&r1=171759&r2=171760&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/test/Tooling/clang-check-ast-dump.cpp (original)<br>
> +++ cfe/trunk/test/Tooling/clang-check-ast-dump.cpp Mon Jan  7 11:53:08 2013<br>
> @@ -31,7 +31,8 @@<br>
> // RUN: clang-check -ast-dump -ast-dump-filter test_namespace::TheClass::n "%s" -- 2>&1 | FileCheck -check-prefix CHECK-ATTR %s<br>
> // CHECK-ATTR: test_namespace<br>
> // CHECK-ATTR-NEXT: (FieldDecl{{.*}}n<br>
> -// FIXME: attribute dumping not implemented yet<br>
> +// CHECK-ATTR-NEXT:   (AlignedAttr<br>
> +// CHECK-ATTR-NEXT:     (BinaryOperator<br>
> //<br>
> // RUN: clang-check -ast-dump -ast-dump-filter test_namespace::AfterNullNode "%s" -- 2>&1 | FileCheck -check-prefix CHECK-AFTER-NULL %s<br>
> // CHECK-AFTER-NULL: class AfterNullNode<br>
><br>
> Modified: cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp?rev=171760&r1=171759&r2=171760&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp?rev=171760&r1=171759&r2=171760&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp (original)<br>
> +++ cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp Mon Jan  7 11:53:08 2013<br>
> @@ -125,6 +125,8 @@<br>
>     virtual void writePCHReadDecls(raw_ostream &OS) const = 0;<br>
>     virtual void writePCHWrite(raw_ostream &OS) const = 0;<br>
>     virtual void writeValue(raw_ostream &OS) const = 0;<br>
> +    virtual void writeDump(raw_ostream &OS) const = 0;<br>
> +    virtual void writeDumpChildren(raw_ostream &OS) const {}<br>
>   };<br>
><br>
>   class SimpleArgument : public Argument {<br>
> @@ -181,6 +183,28 @@<br>
>         OS << "\" << get" << getUpperName() << "() << \"";<br>
>       }<br>
>     }<br>
> +    void writeDump(raw_ostream &OS) const {<br>
> +      if (type == "FunctionDecl *") {<br>
> +        OS << "    OS << \" \";\n";<br>
> +        OS << "    dumpBareDeclRef(SA->get" << getUpperName() << "());\n";<br>
> +      } else if (type == "IdentifierInfo *") {<br>
> +        OS << "    OS << \" \" << SA->get" << getUpperName()<br>
> +           << "()->getName();\n";<br>
> +      } else if (type == "QualType") {<br>
> +        OS << "    OS << \" \" << SA->get" << getUpperName()<br>
> +           << "().getAsString();\n";<br>
> +      } else if (type == "SourceLocation") {<br>
> +        OS << "    OS << \" \";\n";<br>
> +        OS << "    SA->get" << getUpperName() << "().print(OS, *SM);\n";<br>
> +      } else if (type == "bool") {<br>
> +        OS << "    if (SA->get" << getUpperName() << "()) OS << \" "<br>
> +           << getUpperName() << "\";\n";<br>
> +      } else if (type == "int" || type == "unsigned") {<br>
> +        OS << "    OS << \" \" << SA->get" << getUpperName() << "();\n";<br>
> +      } else {<br>
> +        llvm_unreachable("Unknown SimpleArgument type!");<br>
> +      }<br>
> +    }<br>
>   };<br>
><br>
>   class StringArgument : public Argument {<br>
> @@ -241,6 +265,10 @@<br>
>     void writeValue(raw_ostream &OS) const {<br>
>       OS << "\\\"\" << get" << getUpperName() << "() << \"\\\"";<br>
>     }<br>
> +    void writeDump(raw_ostream &OS) const {<br>
> +      OS << "    OS << \" \\\"\" << SA->get" << getUpperName()<br>
> +         << "() << \"\\\"\";\n";<br>
> +    }<br>
>   };<br>
><br>
>   class AlignedArgument : public Argument {<br>
> @@ -353,6 +381,15 @@<br>
>          << "  " << getLowerName() << "Expr->printPretty(OS, 0, Policy);\n"<br>
>          << "  OS << \"";<br>
>     }<br>
> +    void writeDump(raw_ostream &OS) const {<br>
> +    }<br>
> +    void writeDumpChildren(raw_ostream &OS) const {<br>
> +      OS << "    if (SA->is" << getUpperName() << "Expr())\n";<br>
> +      OS << "      dumpStmt(SA->get" << getUpperName() << "Expr());\n";<br>
> +      OS << "    else\n";<br>
> +      OS << "      dumpType(SA->get" << getUpperName()<br>
> +         << "Type()->getType());\n";<br>
> +    }<br>
>   };<br>
><br>
>   class VariadicArgument : public Argument {<br>
> @@ -439,17 +476,30 @@<br>
>          << "  }\n";<br>
>       OS << "  OS << \"";<br>
>     }<br>
> +    void writeDump(raw_ostream &OS) const {<br>
> +      OS << "    for (" << getAttrName() << "Attr::" << getLowerName()<br>
> +         << "_iterator I = SA->" << getLowerName() << "_begin(), E = SA->"<br>
> +         << getLowerName() << "_end(); I != E; ++I)\n";<br>
> +      OS << "      OS << \" \" << *I;\n";<br>
> +    }<br>
>   };<br>
><br>
>   class EnumArgument : public Argument {<br>
>     std::string type;<br>
> -    std::vector<StringRef> values, enums;<br>
> +    std::vector<StringRef> values, enums, uniques;<br>
>   public:<br>
>     EnumArgument(Record &Arg, StringRef Attr)<br>
>       : Argument(Arg, Attr), type(Arg.getValueAsString("Type")),<br>
>         values(getValueAsListOfStrings(Arg, "Values")),<br>
> -        enums(getValueAsListOfStrings(Arg, "Enums"))<br>
> -    {}<br>
> +        enums(getValueAsListOfStrings(Arg, "Enums")),<br>
> +        uniques(enums)<br>
> +    {<br>
> +      // Calculate the various enum values<br>
> +      std::sort(uniques.begin(), uniques.end());<br>
> +      uniques.erase(std::unique(uniques.begin(), uniques.end()), uniques.end());<br>
> +      // FIXME: Emit a proper error<br>
> +      assert(!uniques.empty());<br>
> +    }<br>
><br>
>     void writeAccessors(raw_ostream &OS) const {<br>
>       OS << "  " << type << " get" << getUpperName() << "() const {\n";<br>
> @@ -469,16 +519,8 @@<br>
>       OS << type << " " << getUpperName();<br>
>     }<br>
>     void writeDeclarations(raw_ostream &OS) const {<br>
> -      // Calculate the various enum values<br>
> -      std::vector<StringRef> uniques(enums);<br>
> -      std::sort(uniques.begin(), uniques.end());<br>
> -      uniques.erase(std::unique(uniques.begin(), uniques.end()),<br>
> -                    uniques.end());<br>
> -      // FIXME: Emit a proper error<br>
> -      assert(!uniques.empty());<br>
> -<br>
> -      std::vector<StringRef>::iterator i = uniques.begin(),<br>
> -                                       e = uniques.end();<br>
> +      std::vector<StringRef>::const_iterator i = uniques.begin(),<br>
> +                                             e = uniques.end();<br>
>       // The last one needs to not have a comma.<br>
>       --e;<br>
><br>
> @@ -505,6 +547,21 @@<br>
>     void writeValue(raw_ostream &OS) const {<br>
>       OS << "\" << get" << getUpperName() << "() << \"";<br>
>     }<br>
> +    void writeDump(raw_ostream &OS) const {<br>
> +      OS << "    switch(SA->get" << getUpperName() << "()) {\n";<br>
> +      OS << "    default:\n";<br>
> +      OS << "      llvm_unreachable(\"Unknown " << getAttrName() << "Attr::"<br>
> +         << type << "!\");\n";<br>
> +      OS << "      break;\n";<br>
> +<br>
> +      for (std::vector<StringRef>::const_iterator I = uniques.begin(),<br>
> +           E = uniques.end(); I != E; ++I) {<br>
> +        OS << "    case " << getAttrName() << "Attr::" << *I << ":\n";<br>
> +        OS << "      OS << \" " << *I << "\";\n";<br>
> +        OS << "      break;\n";<br>
> +      }<br>
> +      OS << "    }\n";<br>
> +    }<br>
>   };<br>
><br>
>   class VersionArgument : public Argument {<br>
> @@ -552,6 +609,9 @@<br>
>     void writeValue(raw_ostream &OS) const {<br>
>       OS << getLowerName() << "=\" << get" << getUpperName() << "() << \"";<br>
>     }<br>
> +    void writeDump(raw_ostream &OS) const {<br>
> +      OS << "    OS << \" \" << SA->get" << getUpperName() << "();\n";<br>
> +    }<br>
>   };<br>
><br>
>   class ExprArgument : public SimpleArgument {<br>
> @@ -575,6 +635,13 @@<br>
>          << "Result.takeAs<Expr>();\n";<br>
>       OS << "      }\n";<br>
>     }<br>
> +<br>
> +    void writeDump(raw_ostream &OS) const {<br>
> +    }<br>
> +<br>
> +    void writeDumpChildren(raw_ostream &OS) const {<br>
> +      OS << "    dumpStmt(SA->get" << getUpperName() << "());\n";<br>
> +    }<br>
>   };<br>
><br>
>   class VariadicExprArgument : public VariadicArgument {<br>
> @@ -607,6 +674,16 @@<br>
>       OS << "        }\n";<br>
>       OS << "      }\n";<br>
>     }<br>
> +<br>
> +    void writeDump(raw_ostream &OS) const {<br>
> +    }<br>
> +<br>
> +    void writeDumpChildren(raw_ostream &OS) const {<br>
> +      OS << "    for (" << getAttrName() << "Attr::" << getLowerName()<br>
> +         << "_iterator I = SA->" << getLowerName() << "_begin(), E = SA->"<br>
> +         << getLowerName() << "_end(); I != E; ++I)\n";<br>
> +      OS << "      dumpStmt(*I);\n";<br>
> +    }<br>
>   };<br>
> }<br>
><br>
> @@ -1163,4 +1240,36 @@<br>
>      << "}\n";<br>
> }<br>
><br>
> +// Emits the code to dump an attribute.<br>
> +void EmitClangAttrDump(RecordKeeper &Records, raw_ostream &OS) {<br>
> +  OS <<<br>
> +    "  switch (A->getKind()) {\n"<br>
> +    "  default:\n"<br>
> +    "    llvm_unreachable(\"Unknown attribute kind!\");\n"<br>
> +    "    break;\n";<br>
> +  std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"), Args;<br>
> +  for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end();<br>
> +       I != E; ++I) {<br>
> +    Record &R = **I;<br>
> +    if (!R.getValueAsBit("ASTNode"))<br>
> +      continue;<br>
> +    OS << "  case attr::" << R.getName() << ": {\n";<br>
> +    Args = R.getValueAsListOfDefs("Args");<br>
> +    if (!Args.empty()) {<br>
> +      OS << "    const " << R.getName() << "Attr *SA = cast<" << R.getName()<br>
> +         << "Attr>(A);\n";<br>
> +      for (std::vector<Record*>::iterator I = Args.begin(), E = Args.end();<br>
> +           I != E; ++I)<br>
> +        createArgument(**I, R.getName())->writeDump(OS);<br>
> +      for (std::vector<Record*>::iterator I = Args.begin(), E = Args.end();<br>
> +           I != E; ++I)<br>
> +        createArgument(**I, R.getName())->writeDumpChildren(OS);<br>
> +    }<br>
> +    OS <<<br>
> +      "    break;\n"<br>
> +      "  }\n";<br>
> +  }<br>
> +  OS << "  }\n";<br>
> +}<br>
> +<br>
> } // end namespace clang<br>
><br>
> Modified: cfe/trunk/utils/TableGen/TableGen.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/utils/TableGen/TableGen.cpp?rev=171760&r1=171759&r2=171760&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/utils/TableGen/TableGen.cpp?rev=171760&r1=171759&r2=171760&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/utils/TableGen/TableGen.cpp (original)<br>
> +++ cfe/trunk/utils/TableGen/TableGen.cpp Mon Jan  7 11:53:08 2013<br>
> @@ -33,6 +33,7 @@<br>
>   GenClangAttrTemplateInstantiate,<br>
>   GenClangAttrParsedAttrList,<br>
>   GenClangAttrParsedAttrKinds,<br>
> +  GenClangAttrDump,<br>
>   GenClangDiagsDefs,<br>
>   GenClangDiagGroups,<br>
>   GenClangDiagsIndexName,<br>
> @@ -81,6 +82,8 @@<br>
>                     clEnumValN(GenClangAttrParsedAttrKinds,<br>
>                                "gen-clang-attr-parsed-attr-kinds",<br>
>                                "Generate a clang parsed attribute kinds"),<br>
> +                    clEnumValN(GenClangAttrDump, "gen-clang-attr-dump",<br>
> +                               "Generate clang attribute dumper"),<br>
>                     clEnumValN(GenClangDiagsDefs, "gen-clang-diags-defs",<br>
>                                "Generate Clang diagnostics definitions"),<br>
>                     clEnumValN(GenClangDiagGroups, "gen-clang-diag-groups",<br>
> @@ -153,6 +156,9 @@<br>
>   case GenClangAttrParsedAttrKinds:<br>
>     EmitClangAttrParsedAttrKinds(Records, OS);<br>
>     break;<br>
> +  case GenClangAttrDump:<br>
> +    EmitClangAttrDump(Records, OS);<br>
> +    break;<br>
>   case GenClangDiagsDefs:<br>
>     EmitClangDiagsDefs(Records, OS, ClangComponent);<br>
>     break;<br>
><br>
> Modified: cfe/trunk/utils/TableGen/TableGenBackends.h<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/utils/TableGen/TableGenBackends.h?rev=171760&r1=171759&r2=171760&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/utils/TableGen/TableGenBackends.h?rev=171760&r1=171759&r2=171760&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/utils/TableGen/TableGenBackends.h (original)<br>
> +++ cfe/trunk/utils/TableGen/TableGenBackends.h Mon Jan  7 11:53:08 2013<br>
> @@ -39,6 +39,7 @@<br>
> void EmitClangAttrTemplateInstantiate(RecordKeeper &Records, raw_ostream &OS);<br>
> void EmitClangAttrParsedAttrList(RecordKeeper &Records, raw_ostream &OS);<br>
> void EmitClangAttrParsedAttrKinds(RecordKeeper &Records, raw_ostream &OS);<br>
> +void EmitClangAttrDump(RecordKeeper &Records, raw_ostream &OS);<br>
><br>
> void EmitClangDiagsDefs(RecordKeeper &Records, raw_ostream &OS,<br>
>                         const std::string &Component);<br>
><br>
><br>
> _______________________________________________<br>
> cfe-commits mailing list<br>
> <a href="mailto:cfe-commits@cs.uiuc.edu">cfe-commits@cs.uiuc.edu</a><br>
> <a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits</a><br>
<br>
</div></div><span class="HOEnZb"><font color="#888888">-David<br></font></span></blockquote></div>
</div></div>