diff --git a/test/Tooling/clang-check-analyzer.cpp b/test/Tooling/clang-check-analyzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..16cf7ce603baddf2412e908dc9d4ffc03304c426 --- /dev/null +++ b/test/Tooling/clang-check-analyzer.cpp @@ -0,0 +1,4 @@ +// RUN: clang-check -analyze "%s" -- -c 2>&1 | FileCheck %s + +// CHECK: Dereference of null pointer +int a(int *x) { if(x){} *x = 47; } diff --git a/tools/clang-check/CMakeLists.txt b/tools/clang-check/CMakeLists.txt index e8d0d0a18abd4f17ca00e3e1433944d336e9913a..2070de37fcf528dac255b51767919e05fb2ed713 100644 --- a/tools/clang-check/CMakeLists.txt +++ b/tools/clang-check/CMakeLists.txt @@ -14,6 +14,7 @@ target_link_libraries(clang-check clangTooling clangBasic clangRewriteFrontend + clangStaticAnalyzerFrontend ) install(TARGETS clang-check diff --git a/tools/clang-check/ClangCheck.cpp b/tools/clang-check/ClangCheck.cpp index 05783620ca3eb74e6994f756a53d394a74aadf50..bc01874bcf6efbbd649328923be6b622fe63e64c 100644 --- a/tools/clang-check/ClangCheck.cpp +++ b/tools/clang-check/ClangCheck.cpp @@ -21,6 +21,7 @@ #include "clang/Driver/Options.h" #include "clang/Frontend/ASTConsumers.h" #include "clang/Frontend/CompilerInstance.h" +#include "clang/StaticAnalyzer/Frontend/FrontendActions.h" #include "clang/Rewrite/Frontend/FixItRewriter.h" #include "clang/Rewrite/Frontend/FrontendActions.h" #include "clang/Tooling/CommonOptionsParser.h" @@ -62,6 +63,9 @@ static cl::opt<bool> ASTPrint( static cl::opt<std::string> ASTDumpFilter( "ast-dump-filter", cl::desc(Options->getOptionHelpText(options::OPT_ast_dump_filter))); +static cl::opt<bool> Analyze( + "analyze", + cl::desc(Options->getOptionHelpText(options::OPT_analyze))); static cl::opt<bool> Fixit( "fixit", @@ -136,6 +140,10 @@ public: : Extra(Extra), Pos(Pos) { } + InsertAdjuster(const char *Extra, Position Pos) + : Extra(1, std::string(Extra)), Pos(Pos) { + } + virtual CommandLineArguments Adjust(const CommandLineArguments &Args) LLVM_OVERRIDE { CommandLineArguments Return(Args); @@ -182,13 +190,33 @@ int main(int argc, const char **argv) { ClangTool Tool(OptionsParser.getCompilations(), OptionsParser.getSourcePathList()); - if (ArgsAfter.size() > 0) - Tool.appendArgumentsAdjuster(new InsertAdjuster(ArgsAfter, InsertAdjuster::END)); - if (ArgsBefore.size() > 0) - Tool.appendArgumentsAdjuster(new InsertAdjuster(ArgsBefore, InsertAdjuster::BEGIN)); + // Clear adjusters because -fsyntax-only is inserted by the default chain. + Tool.clearArgumentsAdjusters(); + Tool.appendArgumentsAdjuster(new ClangStripOutputAdjuster()); + if (ArgsAfter.size() > 0) { + Tool.appendArgumentsAdjuster(new InsertAdjuster(ArgsAfter, + InsertAdjuster::END)); + } + if (ArgsBefore.size() > 0) { + Tool.appendArgumentsAdjuster(new InsertAdjuster(ArgsBefore, + InsertAdjuster::BEGIN)); + } + + // Running the analyzer requires --analyze. Other modes can work with the + // -fsyntax-only option. + Tool.appendArgumentsAdjuster(new InsertAdjuster( + Analyze ? "--analyze" : "-fsyntax-only", InsertAdjuster::BEGIN)); + + clang_check::ClangCheckActionFactory CheckFactory; + FrontendActionFactory *FrontendFactory; + + // Choose the correct factory based on the selected mode. + if (Analyze) + FrontendFactory = newFrontendActionFactory<clang::ento::AnalysisAction>(); + else if (Fixit) + FrontendFactory = newFrontendActionFactory<FixItAction>(); + else + FrontendFactory = newFrontendActionFactory(&CheckFactory); - if (Fixit) - return Tool.run(newFrontendActionFactory<FixItAction>()); - clang_check::ClangCheckActionFactory Factory; - return Tool.run(newFrontendActionFactory(&Factory)); + return Tool.run(FrontendFactory); }