mirror of
https://github.com/intel/llvm.git
synced 2026-01-19 01:15:50 +08:00
Implement Attr dumping in terms of visitors
Remove now-vestigial dumpType and dumpBareDeclRef methods. The old tablegen generated code used to expect them to be present, but the new generated code has no such requirement. Reviewers: aaron.ballman Subscribers: mgorny, cfe-commits Differential Revision: https://reviews.llvm.org/D55492 llvm-svn: 350958
This commit is contained in:
76
clang/include/clang/AST/AttrVisitor.h
Normal file
76
clang/include/clang/AST/AttrVisitor.h
Normal file
@@ -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
|
||||
@@ -8,10 +8,15 @@ clang_tablegen(AttrImpl.inc -gen-clang-attr-impl
|
||||
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}/../../
|
||||
|
||||
@@ -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 @@ public:
|
||||
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 @@ public:
|
||||
|
||||
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 @@ public:
|
||||
const comments::FullComment *);
|
||||
void visitVerbatimLineComment(const comments::VerbatimLineComment *C,
|
||||
const comments::FullComment *);
|
||||
|
||||
// Implements Visit methods for Attrs.
|
||||
#include "clang/AST/AttrTextNodeDump.inc"
|
||||
};
|
||||
|
||||
} // namespace clang
|
||||
|
||||
@@ -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 @@ namespace {
|
||||
: 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 @@ namespace {
|
||||
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 @@ namespace {
|
||||
|
||||
// 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::dumpLookups(const DeclContext *DC, bool DumpDecls) {
|
||||
|
||||
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);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -41,6 +41,29 @@ void TextNodeDumper::Visit(const comments::Comment *C,
|
||||
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;
|
||||
|
||||
@@ -603,14 +603,15 @@ namespace {
|
||||
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 @@ void EmitClangAttrHasAttrImpl(RecordKeeper &Records, raw_ostream &OS) {
|
||||
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 @@ void EmitClangAttrParsedAttrKinds(RecordKeeper &Records, raw_ostream &OS) {
|
||||
}
|
||||
|
||||
// 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);
|
||||
|
||||
for (const auto *AI : Args)
|
||||
createArgument(*AI, R.getName())->writeDumpChildren(OS);
|
||||
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;
|
||||
|
||||
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,
|
||||
|
||||
@@ -40,7 +40,8 @@ enum ActionType {
|
||||
GenClangAttrParsedAttrList,
|
||||
GenClangAttrParsedAttrImpl,
|
||||
GenClangAttrParsedAttrKinds,
|
||||
GenClangAttrDump,
|
||||
GenClangAttrTextNodeDump,
|
||||
GenClangAttrNodeTraverse,
|
||||
GenClangDiagsDefs,
|
||||
GenClangDiagGroups,
|
||||
GenClangDiagsIndexName,
|
||||
@@ -112,8 +113,10 @@ cl::opt<ActionType> Action(
|
||||
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 @@ bool ClangTableGenMain(raw_ostream &OS, RecordKeeper &Records) {
|
||||
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);
|
||||
|
||||
@@ -45,7 +45,10 @@ void EmitClangAttrTemplateInstantiate(llvm::RecordKeeper &Records, llvm::raw_ost
|
||||
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);
|
||||
|
||||
Reference in New Issue
Block a user