Index: cfe/trunk/include/clang/AST/CMakeLists.txt =================================================================== --- cfe/trunk/include/clang/AST/CMakeLists.txt +++ cfe/trunk/include/clang/AST/CMakeLists.txt @@ -50,3 +50,6 @@ SOURCE CommentCommands.td TARGET ClangCommentCommandList) +clang_tablegen(StmtDataCollectors.inc -gen-clang-data-collectors + SOURCE StmtDataCollectors.td + TARGET StmtDataCollectors) Index: cfe/trunk/include/clang/AST/StmtDataCollectors.td =================================================================== --- cfe/trunk/include/clang/AST/StmtDataCollectors.td +++ cfe/trunk/include/clang/AST/StmtDataCollectors.td @@ -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()' != 'foo()'. + 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(numDecls)); + for (const Decl *D : S->decls()) { + if (const VarDecl *VD = dyn_cast(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())); + } + }]; +} Index: cfe/trunk/lib/AST/StmtDataCollectors.inc =================================================================== --- cfe/trunk/lib/AST/StmtDataCollectors.inc +++ cfe/trunk/lib/AST/StmtDataCollectors.inc @@ -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()' != 'foo()'. - 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(numDecls)); - for (const Decl *D : S->decls()) { - if (const VarDecl *VD = dyn_cast(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 Index: cfe/trunk/lib/Analysis/CloneDetection.cpp =================================================================== --- cfe/trunk/lib/Analysis/CloneDetection.cpp +++ cfe/trunk/lib/Analysis/CloneDetection.cpp @@ -205,7 +205,7 @@ ConstStmtVisitor>::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) \ Index: cfe/trunk/unittests/AST/DataCollectionTest.cpp =================================================================== --- cfe/trunk/unittests/AST/DataCollectionTest.cpp +++ cfe/trunk/unittests/AST/DataCollectionTest.cpp @@ -46,7 +46,7 @@ ConstStmtVisitor::Visit##CLASS(S); \ } -#include "../../lib/AST/StmtDataCollectors.inc" +#include "clang/AST/StmtDataCollectors.inc" }; } // end anonymous namespace Index: cfe/trunk/utils/TableGen/CMakeLists.txt =================================================================== --- cfe/trunk/utils/TableGen/CMakeLists.txt +++ cfe/trunk/utils/TableGen/CMakeLists.txt @@ -6,6 +6,7 @@ ClangCommentCommandInfoEmitter.cpp ClangCommentHTMLNamedCharacterReferenceEmitter.cpp ClangCommentHTMLTagsEmitter.cpp + ClangDataCollectorsEmitter.cpp ClangDiagnosticsEmitter.cpp ClangOptionDocEmitter.cpp ClangSACheckersEmitter.cpp Index: cfe/trunk/utils/TableGen/ClangDataCollectorsEmitter.cpp =================================================================== --- cfe/trunk/utils/TableGen/ClangDataCollectorsEmitter.cpp +++ cfe/trunk/utils/TableGen/ClangDataCollectorsEmitter.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 Index: cfe/trunk/utils/TableGen/TableGen.cpp =================================================================== --- cfe/trunk/utils/TableGen/TableGen.cpp +++ cfe/trunk/utils/TableGen/TableGen.cpp @@ -57,6 +57,7 @@ GenAttrDocs, GenDiagDocs, GenOptDocs, + GenDataCollectors, GenTestPragmaAttributeSupportedAttributes }; @@ -147,6 +148,8 @@ 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 @@ case GenOptDocs: EmitClangOptDocs(Records, OS); break; + case GenDataCollectors: + EmitClangDataCollectors(Records, OS); + break; case GenTestPragmaAttributeSupportedAttributes: EmitTestPragmaAttributeSupportedAttributes(Records, OS); break; Index: cfe/trunk/utils/TableGen/TableGenBackends.h =================================================================== --- cfe/trunk/utils/TableGen/TableGenBackends.h +++ cfe/trunk/utils/TableGen/TableGenBackends.h @@ -75,6 +75,8 @@ 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);