Index: include/clang/Tooling/ASTDiff/ASTDiff.h =================================================================== --- include/clang/Tooling/ASTDiff/ASTDiff.h +++ include/clang/Tooling/ASTDiff/ASTDiff.h @@ -125,6 +125,8 @@ /// (see NodeComparison) will be allowed to be matched. bool EnableMatchingWithUnmatchableParents = false; + bool StopAfterTopDown = false; + /// Returns false if the nodes should never be matched. bool isMatchingAllowed(const DynTypedNode &N1, const DynTypedNode &N2) const { return N1.getNodeKind().isSame(N2.getNodeKind()); Index: lib/Tooling/ASTDiff/ASTDiff.cpp =================================================================== --- lib/Tooling/ASTDiff/ASTDiff.cpp +++ lib/Tooling/ASTDiff/ASTDiff.cpp @@ -878,6 +878,8 @@ if (IsMappingDone) return; TheMapping = matchTopDown(); + if (Options.StopAfterTopDown) + return; matchBottomUp(TheMapping); IsMappingDone = true; } Index: test/Tooling/clang-diff-args.sh =================================================================== --- /dev/null +++ test/Tooling/clang-diff-args.sh @@ -0,0 +1,8 @@ +RUN: echo a > %t.cpp + +RUN: echo "CHECK: unknown type name 'X'" > %t1 + +check adding command-line arguments +RUN: clang-diff -ast-dump -extra-arg=-Da=X %t.cpp -- 2>&1 | FileCheck %t1 +RUN: clang-diff -ast-dump -extra-arg-before=-Da=X %t.cpp -- 2>&1 | FileCheck %t1 +RUN: clang-diff -ast-dump %t.cpp -- 2>&1 -Da=X | FileCheck %t1 Index: test/Tooling/clang-diff-basic.cpp =================================================================== --- test/Tooling/clang-diff-basic.cpp +++ test/Tooling/clang-diff-basic.cpp @@ -1,6 +1,6 @@ // RUN: %clang_cc1 -E %s > %T/src.cpp // RUN: %clang_cc1 -E %s > %T/dst.cpp -DDEST -// RUN: clang-diff -no-compilation-database %T/src.cpp %T/dst.cpp | FileCheck %s +// RUN: clang-diff %T/src.cpp %T/dst.cpp -- | FileCheck %s #ifndef DEST namespace src { Index: tools/clang-diff/ClangDiff.cpp =================================================================== --- tools/clang-diff/ClangDiff.cpp +++ tools/clang-diff/ClangDiff.cpp @@ -28,12 +28,6 @@ cl::desc("Print the internal representation of the AST as JSON."), cl::init(false), cl::cat(ClangDiffCategory)); -static cl::opt NoCompilationDatabase( - "no-compilation-database", - cl::desc( - "Do not attempt to load build settings from a compilation database"), - cl::init(false), cl::cat(ClangDiffCategory)); - static cl::opt SourcePath(cl::Positional, cl::desc(""), cl::Required, cl::cat(ClangDiffCategory)); @@ -43,23 +37,61 @@ cl::Optional, cl::cat(ClangDiffCategory)); -static std::unique_ptr getAST(const StringRef Filename) { +static cl::opt StopAfter("stop-after", + cl::desc(""), + cl::Optional, cl::init(""), + cl::cat(ClangDiffCategory)); + +static cl::opt MaxSize("s", cl::desc(""), cl::Optional, + cl::init(-1), cl::cat(ClangDiffCategory)); + +static cl::opt BuildPath("p", cl::desc("Build path"), cl::init(""), + cl::Optional, cl::cat(ClangDiffCategory)); + +static cl::list ArgsAfter( + "extra-arg", + cl::desc("Additional argument to append to the compiler command line"), + cl::cat(ClangDiffCategory)); + +static cl::list ArgsBefore( + "extra-arg-before", + cl::desc("Additional argument to prepend to the compiler command line"), + cl::cat(ClangDiffCategory)); + +static void addExtraArgs(std::unique_ptr &Compilations) { + if (!Compilations) + return; + auto AdjustingCompilations = + llvm::make_unique( + std::move(Compilations)); + AdjustingCompilations->appendArgumentsAdjuster( + getInsertArgumentAdjuster(ArgsBefore, ArgumentInsertPosition::BEGIN)); + AdjustingCompilations->appendArgumentsAdjuster( + getInsertArgumentAdjuster(ArgsAfter, ArgumentInsertPosition::END)); + Compilations = std::move(AdjustingCompilations); +} + +static std::unique_ptr +getAST(const std::unique_ptr &CommonCompilations, + const StringRef Filename) { std::string ErrorMessage; std::unique_ptr Compilations; - if (!NoCompilationDatabase) - Compilations = - CompilationDatabase::autoDetectFromSource(Filename, ErrorMessage); - if (!Compilations) { - if (!NoCompilationDatabase) + if (!CommonCompilations) { + Compilations = CompilationDatabase::autoDetectFromSource( + BuildPath.empty() ? Filename : BuildPath, ErrorMessage); + if (!Compilations) { llvm::errs() << "Error while trying to load a compilation database, running " "without flags.\n" << ErrorMessage; - Compilations = llvm::make_unique( - ".", std::vector()); + Compilations = + llvm::make_unique( + ".", std::vector()); + } } + addExtraArgs(Compilations); std::array Files = {{Filename}}; - ClangTool Tool(*Compilations, Files); + ClangTool Tool(Compilations ? *Compilations : *CommonCompilations, Files); std::vector> ASTs; Tool.buildASTs(ASTs); if (ASTs.size() != Files.size()) @@ -68,18 +100,25 @@ } int main(int argc, const char **argv) { + std::string ErrorMessage; + std::unique_ptr CommonCompilations = + FixedCompilationDatabase::loadFromCommandLine(argc, argv, ErrorMessage); + if (!CommonCompilations && !ErrorMessage.empty()) + llvm::errs() << ErrorMessage; cl::HideUnrelatedOptions(ClangDiffCategory); if (!cl::ParseCommandLineOptions(argc, argv)) { cl::PrintOptionValues(); return 1; } + addExtraArgs(CommonCompilations); + if (ASTDump) { if (!DestinationPath.empty()) { llvm::errs() << "Error: Please specify exactly one filename.\n"; return 1; } - std::unique_ptr AST = getAST(SourcePath); + std::unique_ptr AST = getAST(CommonCompilations, SourcePath); if (!AST) return 1; diff::SyntaxTree Tree(AST->getASTContext()); @@ -92,12 +131,22 @@ return 1; } - std::unique_ptr Src = getAST(SourcePath); - std::unique_ptr Dst = getAST(DestinationPath); + std::unique_ptr Src = getAST(CommonCompilations, SourcePath); + std::unique_ptr Dst = getAST(CommonCompilations, DestinationPath); if (!Src || !Dst) return 1; diff::ComparisonOptions Options; + if (MaxSize != -1) + Options.MaxSize = MaxSize; + if (!StopAfter.empty()) { + if (StopAfter == "topdown") + Options.StopAfterTopDown = true; + else if (StopAfter != "bottomup") { + llvm::errs() << "Error: Invalid argument for -stop-after"; + return 1; + } + } diff::SyntaxTree SrcTree(Src->getASTContext()); diff::SyntaxTree DstTree(Dst->getASTContext()); diff::ASTDiff DiffTool(SrcTree, DstTree, Options);