[AST] Add TableGen for StmtDataCollectors
Summary: This adds an option "-gen-clang-data-collectors" to the Clang TableGen that is used to generate StmtDataCollectors.inc. Reviewers: arphaman, teemperor! Subscribers: mgorny, cfe-commits Differential Revision: https://reviews.llvm.org/D37383 llvm-svn: 312634
This commit is contained in:
parent
d614a1c15a
commit
1509da083a
|
@ -50,3 +50,6 @@ clang_tablegen(CommentCommandList.inc -gen-clang-comment-command-list
|
|||
SOURCE CommentCommands.td
|
||||
TARGET ClangCommentCommandList)
|
||||
|
||||
clang_tablegen(StmtDataCollectors.inc -gen-clang-data-collectors
|
||||
SOURCE StmtDataCollectors.td
|
||||
TARGET StmtDataCollectors)
|
||||
|
|
|
@ -0,0 +1,242 @@
|
|||
class Stmt {
|
||||
code Code = [{
|
||||
addData(S->getStmtClass());
|
||||
// This ensures that non-macro-generated code isn't identical to
|
||||
// macro-generated code.
|
||||
addData(data_collection::getMacroStack(S->getLocStart(), Context));
|
||||
addData(data_collection::getMacroStack(S->getLocEnd(), Context));
|
||||
}];
|
||||
}
|
||||
|
||||
class Expr {
|
||||
code Code = [{
|
||||
addData(S->getType());
|
||||
}];
|
||||
}
|
||||
|
||||
//--- Builtin functionality ----------------------------------------------//
|
||||
class ArrayTypeTraitExpr {
|
||||
code Code = [{
|
||||
addData(S->getTrait());
|
||||
}];
|
||||
}
|
||||
class ExpressionTraitExpr {
|
||||
code Code = [{
|
||||
addData(S->getTrait());
|
||||
}];
|
||||
}
|
||||
class PredefinedExpr {
|
||||
code Code = [{
|
||||
addData(S->getIdentType());
|
||||
}];
|
||||
}
|
||||
class TypeTraitExpr {
|
||||
code Code = [{
|
||||
addData(S->getTrait());
|
||||
for (unsigned i = 0; i < S->getNumArgs(); ++i)
|
||||
addData(S->getArg(i)->getType());
|
||||
}];
|
||||
}
|
||||
|
||||
//--- Calls --------------------------------------------------------------//
|
||||
class CallExpr {
|
||||
code Code = [{
|
||||
// Function pointers don't have a callee and we just skip hashing it.
|
||||
if (const FunctionDecl *D = S->getDirectCallee()) {
|
||||
// If the function is a template specialization, we also need to handle
|
||||
// the template arguments as they are not included in the qualified name.
|
||||
if (auto Args = D->getTemplateSpecializationArgs()) {
|
||||
std::string ArgString;
|
||||
|
||||
// Print all template arguments into ArgString
|
||||
llvm::raw_string_ostream OS(ArgString);
|
||||
for (unsigned i = 0; i < Args->size(); ++i) {
|
||||
Args->get(i).print(Context.getLangOpts(), OS);
|
||||
// Add a padding character so that 'foo<X, XX>()' != 'foo<XX, X>()'.
|
||||
OS << '\n';
|
||||
}
|
||||
OS.flush();
|
||||
|
||||
addData(ArgString);
|
||||
}
|
||||
addData(D->getQualifiedNameAsString());
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
//--- Value references ---------------------------------------------------//
|
||||
class DeclRefExpr {
|
||||
code Code = [{
|
||||
addData(S->getDecl()->getQualifiedNameAsString());
|
||||
}];
|
||||
}
|
||||
class MemberExpr {
|
||||
code Code = [{
|
||||
addData(S->getMemberDecl()->getName());
|
||||
}];
|
||||
}
|
||||
|
||||
//--- Literals -----------------------------------------------------------//
|
||||
class IntegerLiteral {
|
||||
code Code = [{
|
||||
addData(llvm::hash_value(S->getValue()));
|
||||
}];
|
||||
}
|
||||
class FloatingLiteral {
|
||||
code Code = [{
|
||||
addData(llvm::hash_value(S->getValue()));
|
||||
}];
|
||||
}
|
||||
class StringLiteral {
|
||||
code Code = [{
|
||||
addData(S->getString());
|
||||
}];
|
||||
}
|
||||
class CXXBoolLiteralExpr {
|
||||
code Code = [{
|
||||
addData(S->getValue());
|
||||
}];
|
||||
}
|
||||
class CharacterLiteral {
|
||||
code Code = [{
|
||||
addData(S->getValue());
|
||||
}];
|
||||
}
|
||||
|
||||
//--- Exceptions ---------------------------------------------------------//
|
||||
class CXXCatchStmt {
|
||||
code Code = [{
|
||||
addData(S->getCaughtType());
|
||||
}];
|
||||
}
|
||||
|
||||
//--- C++ OOP Stmts ------------------------------------------------------//
|
||||
class CXXDeleteExpr {
|
||||
code Code = [{
|
||||
addData(S->isArrayFormAsWritten()); addData(S->isGlobalDelete());
|
||||
}];
|
||||
}
|
||||
|
||||
//--- Casts --------------------------------------------------------------//
|
||||
class ObjCBridgedCastExpr {
|
||||
code Code = [{
|
||||
addData(S->getBridgeKind());
|
||||
}];
|
||||
}
|
||||
|
||||
//--- Miscellaneous Exprs ------------------------------------------------//
|
||||
class BinaryOperator {
|
||||
code Code = [{
|
||||
addData(S->getOpcode());
|
||||
}];
|
||||
}
|
||||
class UnaryOperator {
|
||||
code Code = [{
|
||||
addData(S->getOpcode());
|
||||
}];
|
||||
}
|
||||
|
||||
//--- Control flow -------------------------------------------------------//
|
||||
class GotoStmt {
|
||||
code Code = [{
|
||||
addData(S->getLabel()->getName());
|
||||
}];
|
||||
}
|
||||
class IndirectGotoStmt {
|
||||
code Code = [{
|
||||
if (S->getConstantTarget())
|
||||
addData(S->getConstantTarget()->getName());
|
||||
}];
|
||||
}
|
||||
class LabelStmt {
|
||||
code Code = [{
|
||||
addData(S->getDecl()->getName());
|
||||
}];
|
||||
}
|
||||
class MSDependentExistsStmt {
|
||||
code Code = [{
|
||||
addData(S->isIfExists());
|
||||
}];
|
||||
}
|
||||
class AddrLabelExpr {
|
||||
code Code = [{
|
||||
addData(S->getLabel()->getName());
|
||||
}];
|
||||
}
|
||||
|
||||
//--- Objective-C --------------------------------------------------------//
|
||||
class ObjCIndirectCopyRestoreExpr {
|
||||
code Code = [{
|
||||
addData(S->shouldCopy());
|
||||
}];
|
||||
}
|
||||
class ObjCPropertyRefExpr {
|
||||
code Code = [{
|
||||
addData(S->isSuperReceiver()); addData(S->isImplicitProperty());
|
||||
}];
|
||||
}
|
||||
class ObjCAtCatchStmt {
|
||||
code Code = [{
|
||||
addData(S->hasEllipsis());
|
||||
}];
|
||||
}
|
||||
|
||||
//--- Miscellaneous Stmts ------------------------------------------------//
|
||||
class CXXFoldExpr {
|
||||
code Code = [{
|
||||
addData(S->isRightFold()); addData(S->getOperator());
|
||||
}];
|
||||
}
|
||||
class GenericSelectionExpr {
|
||||
code Code = [{
|
||||
for (unsigned i = 0; i < S->getNumAssocs(); ++i) {
|
||||
addData(S->getAssocType(i));
|
||||
}
|
||||
}];
|
||||
}
|
||||
class LambdaExpr {
|
||||
code Code = [{
|
||||
for (const LambdaCapture &C : S->captures()) {
|
||||
addData(C.isPackExpansion());
|
||||
addData(C.getCaptureKind());
|
||||
if (C.capturesVariable())
|
||||
addData(C.getCapturedVar()->getType());
|
||||
}
|
||||
addData(S->isGenericLambda());
|
||||
addData(S->isMutable());
|
||||
}];
|
||||
}
|
||||
class DeclStmt {
|
||||
code Code = [{
|
||||
auto numDecls = std::distance(S->decl_begin(), S->decl_end());
|
||||
addData(static_cast<unsigned>(numDecls));
|
||||
for (const Decl *D : S->decls()) {
|
||||
if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
|
||||
addData(VD->getType());
|
||||
}
|
||||
}
|
||||
}];
|
||||
}
|
||||
class AsmStmt {
|
||||
code Code = [{
|
||||
addData(S->isSimple());
|
||||
addData(S->isVolatile());
|
||||
addData(S->generateAsmString(Context));
|
||||
for (unsigned i = 0; i < S->getNumInputs(); ++i) {
|
||||
addData(S->getInputConstraint(i));
|
||||
}
|
||||
for (unsigned i = 0; i < S->getNumOutputs(); ++i) {
|
||||
addData(S->getOutputConstraint(i));
|
||||
}
|
||||
for (unsigned i = 0; i < S->getNumClobbers(); ++i) {
|
||||
addData(S->getClobber(i));
|
||||
}
|
||||
}];
|
||||
}
|
||||
class AttributedStmt {
|
||||
code Code = [{
|
||||
for (const Attr *A : S->getAttrs()) {
|
||||
addData(std::string(A->getSpelling()));
|
||||
}
|
||||
}];
|
||||
}
|
|
@ -1,141 +0,0 @@
|
|||
// The functions below collect the class specific data of each Stmt subclass.
|
||||
|
||||
DEF_ADD_DATA(Stmt, {
|
||||
addData(S->getStmtClass());
|
||||
// This ensures that non-macro-generated code isn't identical to
|
||||
// macro-generated code.
|
||||
addData(data_collection::getMacroStack(S->getLocStart(), Context));
|
||||
addData(data_collection::getMacroStack(S->getLocEnd(), Context));
|
||||
})
|
||||
DEF_ADD_DATA(Expr, { addData(S->getType()); })
|
||||
|
||||
//--- Builtin functionality ----------------------------------------------//
|
||||
DEF_ADD_DATA(ArrayTypeTraitExpr, { addData(S->getTrait()); })
|
||||
DEF_ADD_DATA(ExpressionTraitExpr, { addData(S->getTrait()); })
|
||||
DEF_ADD_DATA(PredefinedExpr, { addData(S->getIdentType()); })
|
||||
DEF_ADD_DATA(TypeTraitExpr, {
|
||||
addData(S->getTrait());
|
||||
for (unsigned i = 0; i < S->getNumArgs(); ++i)
|
||||
addData(S->getArg(i)->getType());
|
||||
})
|
||||
|
||||
//--- Calls --------------------------------------------------------------//
|
||||
DEF_ADD_DATA(CallExpr, {
|
||||
// Function pointers don't have a callee and we just skip hashing it.
|
||||
if (const FunctionDecl *D = S->getDirectCallee()) {
|
||||
// If the function is a template specialization, we also need to handle
|
||||
// the template arguments as they are not included in the qualified name.
|
||||
if (auto Args = D->getTemplateSpecializationArgs()) {
|
||||
std::string ArgString;
|
||||
|
||||
// Print all template arguments into ArgString
|
||||
llvm::raw_string_ostream OS(ArgString);
|
||||
for (unsigned i = 0; i < Args->size(); ++i) {
|
||||
Args->get(i).print(Context.getLangOpts(), OS);
|
||||
// Add a padding character so that 'foo<X, XX>()' != 'foo<XX, X>()'.
|
||||
OS << '\n';
|
||||
}
|
||||
OS.flush();
|
||||
|
||||
addData(ArgString);
|
||||
}
|
||||
addData(D->getQualifiedNameAsString());
|
||||
}
|
||||
})
|
||||
|
||||
//--- Value references ---------------------------------------------------//
|
||||
DEF_ADD_DATA(DeclRefExpr,
|
||||
{ addData(S->getDecl()->getQualifiedNameAsString()); })
|
||||
DEF_ADD_DATA(MemberExpr,
|
||||
{ addData(S->getMemberDecl()->getName()); })
|
||||
|
||||
//--- Literals -----------------------------------------------------------//
|
||||
DEF_ADD_DATA(IntegerLiteral, { addData(llvm::hash_value(S->getValue())); })
|
||||
DEF_ADD_DATA(FloatingLiteral, { addData(llvm::hash_value(S->getValue())); })
|
||||
DEF_ADD_DATA(StringLiteral, { addData(S->getString()); })
|
||||
DEF_ADD_DATA(CXXBoolLiteralExpr, { addData(S->getValue()); })
|
||||
DEF_ADD_DATA(CharacterLiteral, { addData(S->getValue()); })
|
||||
|
||||
//--- Exceptions ---------------------------------------------------------//
|
||||
DEF_ADD_DATA(CXXCatchStmt, { addData(S->getCaughtType()); })
|
||||
|
||||
//--- C++ OOP Stmts ------------------------------------------------------//
|
||||
DEF_ADD_DATA(CXXDeleteExpr, {
|
||||
addData(S->isArrayFormAsWritten());
|
||||
addData(S->isGlobalDelete());
|
||||
})
|
||||
|
||||
//--- Casts --------------------------------------------------------------//
|
||||
DEF_ADD_DATA(ObjCBridgedCastExpr, { addData(S->getBridgeKind()); })
|
||||
|
||||
//--- Miscellaneous Exprs ------------------------------------------------//
|
||||
DEF_ADD_DATA(BinaryOperator, { addData(S->getOpcode()); })
|
||||
DEF_ADD_DATA(UnaryOperator, { addData(S->getOpcode()); })
|
||||
|
||||
//--- Control flow -------------------------------------------------------//
|
||||
DEF_ADD_DATA(GotoStmt, { addData(S->getLabel()->getName()); })
|
||||
DEF_ADD_DATA(IndirectGotoStmt, {
|
||||
if (S->getConstantTarget())
|
||||
addData(S->getConstantTarget()->getName());
|
||||
})
|
||||
DEF_ADD_DATA(LabelStmt, { addData(S->getDecl()->getName()); })
|
||||
DEF_ADD_DATA(MSDependentExistsStmt, { addData(S->isIfExists()); })
|
||||
DEF_ADD_DATA(AddrLabelExpr, { addData(S->getLabel()->getName()); })
|
||||
|
||||
//--- Objective-C --------------------------------------------------------//
|
||||
DEF_ADD_DATA(ObjCIndirectCopyRestoreExpr, { addData(S->shouldCopy()); })
|
||||
DEF_ADD_DATA(ObjCPropertyRefExpr, {
|
||||
addData(S->isSuperReceiver());
|
||||
addData(S->isImplicitProperty());
|
||||
})
|
||||
DEF_ADD_DATA(ObjCAtCatchStmt, { addData(S->hasEllipsis()); })
|
||||
|
||||
//--- Miscellaneous Stmts ------------------------------------------------//
|
||||
DEF_ADD_DATA(CXXFoldExpr, {
|
||||
addData(S->isRightFold());
|
||||
addData(S->getOperator());
|
||||
})
|
||||
DEF_ADD_DATA(GenericSelectionExpr, {
|
||||
for (unsigned i = 0; i < S->getNumAssocs(); ++i) {
|
||||
addData(S->getAssocType(i));
|
||||
}
|
||||
})
|
||||
DEF_ADD_DATA(LambdaExpr, {
|
||||
for (const LambdaCapture &C : S->captures()) {
|
||||
addData(C.isPackExpansion());
|
||||
addData(C.getCaptureKind());
|
||||
if (C.capturesVariable())
|
||||
addData(C.getCapturedVar()->getType());
|
||||
}
|
||||
addData(S->isGenericLambda());
|
||||
addData(S->isMutable());
|
||||
})
|
||||
DEF_ADD_DATA(DeclStmt, {
|
||||
auto numDecls = std::distance(S->decl_begin(), S->decl_end());
|
||||
addData(static_cast<unsigned>(numDecls));
|
||||
for (const Decl *D : S->decls()) {
|
||||
if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
|
||||
addData(VD->getType());
|
||||
}
|
||||
}
|
||||
})
|
||||
DEF_ADD_DATA(AsmStmt, {
|
||||
addData(S->isSimple());
|
||||
addData(S->isVolatile());
|
||||
addData(S->generateAsmString(Context));
|
||||
for (unsigned i = 0; i < S->getNumInputs(); ++i) {
|
||||
addData(S->getInputConstraint(i));
|
||||
}
|
||||
for (unsigned i = 0; i < S->getNumOutputs(); ++i) {
|
||||
addData(S->getOutputConstraint(i));
|
||||
}
|
||||
for (unsigned i = 0; i < S->getNumClobbers(); ++i) {
|
||||
addData(S->getClobber(i));
|
||||
}
|
||||
})
|
||||
DEF_ADD_DATA(AttributedStmt, {
|
||||
for (const Attr *A : S->getAttrs()) {
|
||||
addData(std::string(A->getSpelling()));
|
||||
}
|
||||
})
|
||||
#undef DEF_ADD_DATA
|
|
@ -205,7 +205,7 @@ public:
|
|||
ConstStmtVisitor<CloneTypeIIStmtDataCollector<T>>::Visit##CLASS(S); \
|
||||
}
|
||||
|
||||
#include "../AST/StmtDataCollectors.inc"
|
||||
#include "clang/AST/StmtDataCollectors.inc"
|
||||
|
||||
// Type II clones ignore variable names and literals, so let's skip them.
|
||||
#define SKIP(CLASS) \
|
||||
|
|
|
@ -46,7 +46,7 @@ public:
|
|||
ConstStmtVisitor<StmtDataCollector>::Visit##CLASS(S); \
|
||||
}
|
||||
|
||||
#include "../../lib/AST/StmtDataCollectors.inc"
|
||||
#include "clang/AST/StmtDataCollectors.inc"
|
||||
};
|
||||
} // end anonymous namespace
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ add_tablegen(clang-tblgen CLANG
|
|||
ClangCommentCommandInfoEmitter.cpp
|
||||
ClangCommentHTMLNamedCharacterReferenceEmitter.cpp
|
||||
ClangCommentHTMLTagsEmitter.cpp
|
||||
ClangDataCollectorsEmitter.cpp
|
||||
ClangDiagnosticsEmitter.cpp
|
||||
ClangOptionDocEmitter.cpp
|
||||
ClangSACheckersEmitter.cpp
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
#include "llvm/TableGen/Record.h"
|
||||
#include "llvm/TableGen/TableGenBackend.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
namespace clang {
|
||||
void EmitClangDataCollectors(RecordKeeper &RK, raw_ostream &OS) {
|
||||
const auto &Defs = RK.getClasses();
|
||||
for (const auto &Entry : Defs) {
|
||||
Record &R = *Entry.second;
|
||||
OS << "DEF_ADD_DATA(" << R.getName() << ", {";
|
||||
auto Code = R.getValue("Code")->getValue();
|
||||
OS << Code->getAsUnquotedString() << "}\n)";
|
||||
OS << "\n";
|
||||
}
|
||||
OS << "#undef DEF_ADD_DATA\n";
|
||||
}
|
||||
} // end namespace clang
|
|
@ -57,6 +57,7 @@ enum ActionType {
|
|||
GenAttrDocs,
|
||||
GenDiagDocs,
|
||||
GenOptDocs,
|
||||
GenDataCollectors,
|
||||
GenTestPragmaAttributeSupportedAttributes
|
||||
};
|
||||
|
||||
|
@ -147,6 +148,8 @@ cl::opt<ActionType> Action(
|
|||
clEnumValN(GenDiagDocs, "gen-diag-docs",
|
||||
"Generate diagnostic documentation"),
|
||||
clEnumValN(GenOptDocs, "gen-opt-docs", "Generate option documentation"),
|
||||
clEnumValN(GenDataCollectors, "gen-clang-data-collectors",
|
||||
"Generate data collectors for AST nodes"),
|
||||
clEnumValN(GenTestPragmaAttributeSupportedAttributes,
|
||||
"gen-clang-test-pragma-attribute-supported-attributes",
|
||||
"Generate a list of attributes supported by #pragma clang "
|
||||
|
@ -262,6 +265,9 @@ bool ClangTableGenMain(raw_ostream &OS, RecordKeeper &Records) {
|
|||
case GenOptDocs:
|
||||
EmitClangOptDocs(Records, OS);
|
||||
break;
|
||||
case GenDataCollectors:
|
||||
EmitClangDataCollectors(Records, OS);
|
||||
break;
|
||||
case GenTestPragmaAttributeSupportedAttributes:
|
||||
EmitTestPragmaAttributeSupportedAttributes(Records, OS);
|
||||
break;
|
||||
|
|
|
@ -75,6 +75,8 @@ void EmitClangAttrDocs(RecordKeeper &Records, raw_ostream &OS);
|
|||
void EmitClangDiagDocs(RecordKeeper &Records, raw_ostream &OS);
|
||||
void EmitClangOptDocs(RecordKeeper &Records, raw_ostream &OS);
|
||||
|
||||
void EmitClangDataCollectors(RecordKeeper &Records, raw_ostream &OS);
|
||||
|
||||
void EmitTestPragmaAttributeSupportedAttributes(RecordKeeper &Records,
|
||||
raw_ostream &OS);
|
||||
|
||||
|
|
Loading…
Reference in New Issue