steveire updated this revision to Diff 181182. steveire marked an inline comment as done. steveire added a comment.
Nits Repository: rC Clang CHANGES SINCE LAST ACTION https://reviews.llvm.org/D55492/new/ https://reviews.llvm.org/D55492 Files: include/clang/AST/AttrVisitor.h include/clang/AST/CMakeLists.txt include/clang/AST/TextNodeDumper.h lib/AST/ASTDumper.cpp lib/AST/TextNodeDumper.cpp utils/TableGen/ClangAttrEmitter.cpp utils/TableGen/TableGen.cpp utils/TableGen/TableGenBackends.h
Index: utils/TableGen/TableGenBackends.h =================================================================== --- utils/TableGen/TableGenBackends.h +++ utils/TableGen/TableGenBackends.h @@ -45,7 +45,10 @@ void EmitClangAttrParsedAttrList(llvm::RecordKeeper &Records, llvm::raw_ostream &OS); void EmitClangAttrParsedAttrImpl(llvm::RecordKeeper &Records, llvm::raw_ostream &OS); void EmitClangAttrParsedAttrKinds(llvm::RecordKeeper &Records, llvm::raw_ostream &OS); -void EmitClangAttrDump(llvm::RecordKeeper &Records, llvm::raw_ostream &OS); +void EmitClangAttrTextNodeDump(llvm::RecordKeeper &Records, + llvm::raw_ostream &OS); +void EmitClangAttrNodeTraverse(llvm::RecordKeeper &Records, + llvm::raw_ostream &OS); void EmitClangDiagsDefs(llvm::RecordKeeper &Records, llvm::raw_ostream &OS, const std::string &Component); Index: utils/TableGen/TableGen.cpp =================================================================== --- utils/TableGen/TableGen.cpp +++ utils/TableGen/TableGen.cpp @@ -40,7 +40,8 @@ GenClangAttrParsedAttrList, GenClangAttrParsedAttrImpl, GenClangAttrParsedAttrKinds, - GenClangAttrDump, + GenClangAttrTextNodeDump, + GenClangAttrNodeTraverse, GenClangDiagsDefs, GenClangDiagGroups, GenClangDiagsIndexName, @@ -112,8 +113,10 @@ clEnumValN(GenClangAttrParsedAttrKinds, "gen-clang-attr-parsed-attr-kinds", "Generate a clang parsed attribute kinds"), - clEnumValN(GenClangAttrDump, "gen-clang-attr-dump", - "Generate clang attribute dumper"), + clEnumValN(GenClangAttrTextNodeDump, "gen-clang-attr-text-node-dump", + "Generate clang attribute text node dumper"), + clEnumValN(GenClangAttrNodeTraverse, "gen-clang-attr-node-traverse", + "Generate clang attribute traverser"), clEnumValN(GenClangDiagsDefs, "gen-clang-diags-defs", "Generate Clang diagnostics definitions"), clEnumValN(GenClangDiagGroups, "gen-clang-diag-groups", @@ -221,8 +224,11 @@ case GenClangAttrParsedAttrKinds: EmitClangAttrParsedAttrKinds(Records, OS); break; - case GenClangAttrDump: - EmitClangAttrDump(Records, OS); + case GenClangAttrTextNodeDump: + EmitClangAttrTextNodeDump(Records, OS); + break; + case GenClangAttrNodeTraverse: + EmitClangAttrNodeTraverse(Records, OS); break; case GenClangDiagsDefs: EmitClangDiagsDefs(Records, OS, ClangComponent); Index: utils/TableGen/ClangAttrEmitter.cpp =================================================================== --- utils/TableGen/ClangAttrEmitter.cpp +++ utils/TableGen/ClangAttrEmitter.cpp @@ -603,14 +603,15 @@ OS << " OS << \""; } - void writeDump(raw_ostream &OS) const override {} + void writeDump(raw_ostream &OS) const override { + OS << " if (!SA->is" << getUpperName() << "Expr())\n"; + OS << " dumpType(SA->get" << getUpperName() + << "Type()->getType());\n"; + } void writeDumpChildren(raw_ostream &OS) const override { OS << " if (SA->is" << getUpperName() << "Expr())\n"; OS << " dumpStmt(SA->get" << getUpperName() << "Expr());\n"; - OS << " else\n"; - OS << " dumpType(SA->get" << getUpperName() - << "Type()->getType());\n"; } void writeHasChildren(raw_ostream &OS) const override { @@ -2932,15 +2933,15 @@ OS << "case AttrSyntax::" << Variety << ": {\n"; // C++11-style attributes are further split out based on the Scope. for (auto I = List.cbegin(), E = List.cend(); I != E; ++I) { - if (I != List.cbegin()) - OS << " else "; - if (I->first.empty()) - OS << "if (ScopeName == \"\") {\n"; - else - OS << "if (ScopeName == \"" << I->first << "\") {\n"; - OS << " return llvm::StringSwitch<int>(Name)\n"; - GenerateHasAttrSpellingStringSwitch(I->second, OS, Spelling, I->first); - OS << "}"; + if (I != List.cbegin()) + OS << " else "; + if (I->first.empty()) + OS << "if (ScopeName == \"\") {\n"; + else + OS << "if (ScopeName == \"" << I->first << "\") {\n"; + OS << " return llvm::StringSwitch<int>(Name)\n"; + GenerateHasAttrSpellingStringSwitch(I->second, OS, Spelling, I->first); + OS << "}"; } OS << "\n} break;\n"; }; @@ -3697,39 +3698,67 @@ } // Emits the code to dump an attribute. -void EmitClangAttrDump(RecordKeeper &Records, raw_ostream &OS) { - emitSourceFileHeader("Attribute dumper", OS); +void EmitClangAttrTextNodeDump(RecordKeeper &Records, raw_ostream &OS) { + emitSourceFileHeader("Attribute text node dumper", OS); - OS << " switch (A->getKind()) {\n"; std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"), Args; for (const auto *Attr : Attrs) { const Record &R = *Attr; if (!R.getValueAsBit("ASTNode")) continue; - OS << " case attr::" << R.getName() << ": {\n"; // If the attribute has a semantically-meaningful name (which is determined // by whether there is a Spelling enumeration for it), then write out the // spelling used for the attribute. + + std::string FunctionContent; + llvm::raw_string_ostream SS(FunctionContent); + std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(R); if (Spellings.size() > 1 && !SpellingNamesAreCommon(Spellings)) - OS << " OS << \" \" << A->getSpelling();\n"; + SS << " OS << \" \" << A->getSpelling();\n"; Args = R.getValueAsListOfDefs("Args"); - if (!Args.empty()) { - OS << " const auto *SA = cast<" << R.getName() - << "Attr>(A);\n"; - for (const auto *Arg : Args) - createArgument(*Arg, R.getName())->writeDump(OS); + for (const auto *Arg : Args) + createArgument(*Arg, R.getName())->writeDump(SS); + + if (SS.tell()) { + OS << " void Visit" << R.getName() << "Attr(const " << R.getName() + << "Attr *A) {\n"; + if (!Args.empty()) + OS << " const auto *SA = cast<" << R.getName() + << "Attr>(A); (void)SA;\n"; + OS << SS.str(); + OS << " }\n"; + } + } +} + +void EmitClangAttrNodeTraverse(RecordKeeper &Records, raw_ostream &OS) { + emitSourceFileHeader("Attribute text node traverser", OS); + + std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr"), Args; + for (const auto *Attr : Attrs) { + const Record &R = *Attr; + if (!R.getValueAsBit("ASTNode")) + continue; - for (const auto *AI : Args) - createArgument(*AI, R.getName())->writeDumpChildren(OS); + std::string FunctionContent; + llvm::raw_string_ostream SS(FunctionContent); + + Args = R.getValueAsListOfDefs("Args"); + for (const auto *Arg : Args) + createArgument(*Arg, R.getName())->writeDumpChildren(SS); + if (SS.tell()) { + OS << " void Visit" << R.getName() << "Attr(const " << R.getName() + << "Attr *A) {\n"; + if (!Args.empty()) + OS << " const auto *SA = cast<" << R.getName() + << "Attr>(A); (void)SA;\n"; + OS << SS.str(); + OS << " }\n"; } - OS << - " break;\n" - " }\n"; } - OS << " }\n"; } void EmitClangAttrParserStringSwitches(RecordKeeper &Records, Index: lib/AST/TextNodeDumper.cpp =================================================================== --- lib/AST/TextNodeDumper.cpp +++ lib/AST/TextNodeDumper.cpp @@ -41,6 +41,29 @@ const comments::FullComment *>::visit(C, FC); } +void TextNodeDumper::Visit(const Attr *A) { + { + ColorScope Color(OS, ShowColors, AttrColor); + + switch (A->getKind()) { +#define ATTR(X) \ + case attr::X: \ + OS << #X; \ + break; +#include "clang/Basic/AttrList.inc" + } + OS << "Attr"; + } + dumpPointer(A); + dumpSourceRange(A->getRange()); + if (A->isInherited()) + OS << " Inherited"; + if (A->isImplicit()) + OS << " Implicit"; + + ConstAttrVisitor<TextNodeDumper>::Visit(A); +} + void TextNodeDumper::dumpPointer(const void *Ptr) { ColorScope Color(OS, ShowColors, AddressColor); OS << ' ' << Ptr; Index: lib/AST/ASTDumper.cpp =================================================================== --- lib/AST/ASTDumper.cpp +++ lib/AST/ASTDumper.cpp @@ -15,6 +15,7 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/ASTDumperUtils.h" #include "clang/AST/Attr.h" +#include "clang/AST/AttrVisitor.h" #include "clang/AST/CommentVisitor.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclLookups.h" @@ -42,7 +43,8 @@ : public ConstDeclVisitor<ASTDumper>, public ConstStmtVisitor<ASTDumper>, public ConstCommentVisitor<ASTDumper, void, const FullComment *>, - public TypeVisitor<ASTDumper> { + public TypeVisitor<ASTDumper>, + public ConstAttrVisitor<ASTDumper> { TextNodeDumper NodeDumper; @@ -86,10 +88,8 @@ void dumpStmt(const Stmt *S, StringRef Label = {}); // Utilities - void dumpType(QualType T) { NodeDumper.dumpType(T); } void dumpTypeAsChild(QualType T); void dumpTypeAsChild(const Type *T); - void dumpBareDeclRef(const Decl *Node) { NodeDumper.dumpBareDeclRef(Node); } void dumpDeclContext(const DeclContext *DC); void dumpLookups(const DeclContext *DC, bool DumpDecls); void dumpAttr(const Attr *A); @@ -439,6 +439,9 @@ // Comments. void dumpComment(const Comment *C, const FullComment *FC); + +// Implements Visit methods for Attrs. +#include "clang/AST/AttrNodeTraverse.inc" }; } @@ -584,22 +587,8 @@ void ASTDumper::dumpAttr(const Attr *A) { dumpChild([=] { - { - ColorScope Color(OS, ShowColors, AttrColor); - - switch (A->getKind()) { -#define ATTR(X) case attr::X: OS << #X; break; -#include "clang/Basic/AttrList.inc" - } - OS << "Attr"; - } - NodeDumper.dumpPointer(A); - NodeDumper.dumpSourceRange(A->getRange()); - if (A->isInherited()) - OS << " Inherited"; - if (A->isImplicit()) - OS << " Implicit"; -#include "clang/AST/AttrDump.inc" + NodeDumper.Visit(A); + ConstAttrVisitor<ASTDumper>::Visit(A); }); } Index: include/clang/AST/TextNodeDumper.h =================================================================== --- include/clang/AST/TextNodeDumper.h +++ include/clang/AST/TextNodeDumper.h @@ -16,6 +16,7 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/ASTDumperUtils.h" +#include "clang/AST/AttrVisitor.h" #include "clang/AST/CommentCommandTraits.h" #include "clang/AST/CommentVisitor.h" #include "clang/AST/ExprCXX.h" @@ -121,7 +122,8 @@ class TextNodeDumper : public TextTreeStructure, public comments::ConstCommentVisitor<TextNodeDumper, void, - const comments::FullComment *> { + const comments::FullComment *>, + public ConstAttrVisitor<TextNodeDumper> { raw_ostream &OS; const bool ShowColors; @@ -146,6 +148,8 @@ void Visit(const comments::Comment *C, const comments::FullComment *FC); + void Visit(const Attr *A); + void dumpPointer(const void *Ptr); void dumpLocation(SourceLocation Loc); void dumpSourceRange(SourceRange R); @@ -179,6 +183,9 @@ const comments::FullComment *); void visitVerbatimLineComment(const comments::VerbatimLineComment *C, const comments::FullComment *); + +// Implements Visit methods for Attrs. +#include "clang/AST/AttrTextNodeDump.inc" }; } // namespace clang Index: include/clang/AST/CMakeLists.txt =================================================================== --- include/clang/AST/CMakeLists.txt +++ include/clang/AST/CMakeLists.txt @@ -8,10 +8,15 @@ SOURCE ../Basic/Attr.td TARGET ClangAttrImpl) -clang_tablegen(AttrDump.inc -gen-clang-attr-dump +clang_tablegen(AttrTextNodeDump.inc -gen-clang-attr-text-node-dump -I ${CMAKE_CURRENT_SOURCE_DIR}/../../ SOURCE ../Basic/Attr.td - TARGET ClangAttrDump) + TARGET ClangAttrTextDump) + +clang_tablegen(AttrNodeTraverse.inc -gen-clang-attr-node-traverse + -I ${CMAKE_CURRENT_SOURCE_DIR}/../../ + SOURCE ../Basic/Attr.td + TARGET ClangAttrTraverse) clang_tablegen(AttrVisitor.inc -gen-clang-attr-ast-visitor -I ${CMAKE_CURRENT_SOURCE_DIR}/../../ Index: include/clang/AST/AttrVisitor.h =================================================================== --- /dev/null +++ include/clang/AST/AttrVisitor.h @@ -0,0 +1,76 @@ +//===- AttrVisitor.h - Visitor for Attr subclasses --------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the AttrVisitor interface. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_ATTRVISITOR_H +#define LLVM_CLANG_AST_ATTRVISITOR_H + +#include "clang/AST/Attr.h" + +namespace clang { + +namespace attrvisitor { + +/// A simple visitor class that helps create attribute visitors. +template <template <typename> class Ptr, typename ImplClass, + typename RetTy = void, class... ParamTys> +class Base { +public: +#define PTR(CLASS) typename Ptr<CLASS>::type +#define DISPATCH(NAME) \ + return static_cast<ImplClass *>(this)->Visit##NAME(static_cast<PTR(NAME)>(A)) + + RetTy Visit(PTR(Attr) A) { + switch (A->getKind()) { + +#define ATTR(NAME) \ + case attr::NAME: \ + DISPATCH(NAME##Attr); +#include "clang/Basic/AttrList.inc" + } + llvm_unreachable("Attr that isn't part of AttrList.inc!"); + } + + // If the implementation chooses not to implement a certain visit + // method, fall back to the parent. +#define ATTR(NAME) \ + RetTy Visit##NAME##Attr(PTR(NAME##Attr) A) { DISPATCH(Attr); } +#include "clang/Basic/AttrList.inc" + + RetTy VisitAttr(PTR(Attr)) { return RetTy(); } + +#undef PTR +#undef DISPATCH +}; + +} // namespace attrvisitor + +/// A simple visitor class that helps create attribute visitors. +/// +/// This class does not preserve constness of Attr pointers (see +/// also ConstAttrVisitor). +template <typename ImplClass, typename RetTy = void, typename... ParamTys> +class AttrVisitor : public attrvisitor::Base<std::add_pointer, ImplClass, RetTy, + ParamTys...> {}; + +/// A simple visitor class that helps create attribute visitors. +/// +/// This class preserves constness of Attr pointers (see also +/// AttrVisitor). +template <typename ImplClass, typename RetTy = void, typename... ParamTys> +class ConstAttrVisitor + : public attrvisitor::Base<llvm::make_const_ptr, ImplClass, RetTy, + ParamTys...> {}; + +} // namespace clang + +#endif // LLVM_CLANG_AST_ATTRVISITOR_H
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits