From ac61b333fdb5a81d36387934e7e33cf9fecb3dea Mon Sep 17 00:00:00 2001 From: George Karpenkov Date: Mon, 26 Feb 2018 22:14:16 +0000 Subject: [PATCH] [analyzer] Do not analyze bison-generated files Bison/YACC generated files result in a very large number of (presumably) false positives from the analyzer. These false positives are "true" in a sense of the information analyzer sees: assuming that the lexer can return any token at any point a number of uninitialized reads does occur. (naturally, the analyzer can not capture a complex invariant that certain tokens can only occur under certain conditions). Current fix simply stops analysis on those files. I have examined a very large number of such auto-generated files, and they do all start with such a comment. Conversely, user code is very unlikely to contain such a comment. rdar://33608161 Differential Revision: https://reviews.llvm.org/D43421 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@326135 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../Frontend/AnalysisConsumer.cpp | 98 ++++++++++++------- test/Analysis/yaccignore.c | 13 +++ 2 files changed, 74 insertions(+), 37 deletions(-) create mode 100644 test/Analysis/yaccignore.c diff --git a/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp b/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp index a982a4a856..a5cf61e90e 100644 --- a/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp +++ b/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp @@ -389,7 +389,10 @@ private: /// \brief Check if we should skip (not analyze) the given function. AnalysisMode getModeForDecl(Decl *D, AnalysisMode Mode); + void runAnalysisOnTranslationUnit(ASTContext &C); + /// Print \p S to stderr if \c Opts->AnalyzerDisplayProgress is set. + void reportAnalyzerProgress(StringRef S); }; } // end anonymous namespace @@ -511,51 +514,72 @@ void AnalysisConsumer::HandleDeclsCallGraph(const unsigned LocalTUDeclsSize) { } } +static bool isBisonFile(ASTContext &C) { + const SourceManager &SM = C.getSourceManager(); + FileID FID = SM.getMainFileID(); + StringRef Buffer = SM.getBuffer(FID)->getBuffer(); + if (Buffer.startswith("/* A Bison parser, made by")) + return true; + return false; +} + +void AnalysisConsumer::runAnalysisOnTranslationUnit(ASTContext &C) { + BugReporter BR(*Mgr); + TranslationUnitDecl *TU = C.getTranslationUnitDecl(); + checkerMgr->runCheckersOnASTDecl(TU, *Mgr, BR); + + // Run the AST-only checks using the order in which functions are defined. + // If inlining is not turned on, use the simplest function order for path + // sensitive analyzes as well. + RecVisitorMode = AM_Syntax; + if (!Mgr->shouldInlineCall()) + RecVisitorMode |= AM_Path; + RecVisitorBR = &BR; + + // Process all the top level declarations. + // + // Note: TraverseDecl may modify LocalTUDecls, but only by appending more + // entries. Thus we don't use an iterator, but rely on LocalTUDecls + // random access. By doing so, we automatically compensate for iterators + // possibly being invalidated, although this is a bit slower. + const unsigned LocalTUDeclsSize = LocalTUDecls.size(); + for (unsigned i = 0 ; i < LocalTUDeclsSize ; ++i) { + TraverseDecl(LocalTUDecls[i]); + } + + if (Mgr->shouldInlineCall()) + HandleDeclsCallGraph(LocalTUDeclsSize); + + // After all decls handled, run checkers on the entire TranslationUnit. + checkerMgr->runCheckersOnEndOfTranslationUnit(TU, *Mgr, BR); + + RecVisitorBR = nullptr; +} + +void AnalysisConsumer::reportAnalyzerProgress(StringRef S) { + if (Opts->AnalyzerDisplayProgress) + llvm::errs() << S; +} + void AnalysisConsumer::HandleTranslationUnit(ASTContext &C) { + // Don't run the actions if an error has occurred with parsing the file. DiagnosticsEngine &Diags = PP.getDiagnostics(); if (Diags.hasErrorOccurred() || Diags.hasFatalErrorOccurred()) return; - // Don't analyze if the user explicitly asked for no checks to be performed - // on this file. - if (Opts->DisableAllChecks) - return; - - { - if (TUTotalTimer) TUTotalTimer->startTimer(); - - // Introduce a scope to destroy BR before Mgr. - BugReporter BR(*Mgr); - TranslationUnitDecl *TU = C.getTranslationUnitDecl(); - checkerMgr->runCheckersOnASTDecl(TU, *Mgr, BR); - - // Run the AST-only checks using the order in which functions are defined. - // If inlining is not turned on, use the simplest function order for path - // sensitive analyzes as well. - RecVisitorMode = AM_Syntax; - if (!Mgr->shouldInlineCall()) - RecVisitorMode |= AM_Path; - RecVisitorBR = &BR; - - // Process all the top level declarations. - // - // Note: TraverseDecl may modify LocalTUDecls, but only by appending more - // entries. Thus we don't use an iterator, but rely on LocalTUDecls - // random access. By doing so, we automatically compensate for iterators - // possibly being invalidated, although this is a bit slower. - const unsigned LocalTUDeclsSize = LocalTUDecls.size(); - for (unsigned i = 0 ; i < LocalTUDeclsSize ; ++i) { - TraverseDecl(LocalTUDecls[i]); - } - - if (Mgr->shouldInlineCall()) - HandleDeclsCallGraph(LocalTUDeclsSize); + if (TUTotalTimer) TUTotalTimer->startTimer(); - // After all decls handled, run checkers on the entire TranslationUnit. - checkerMgr->runCheckersOnEndOfTranslationUnit(TU, *Mgr, BR); + if (isBisonFile(C)) { + reportAnalyzerProgress("Skipping bison-generated file\n"); + } else if (Opts->DisableAllChecks) { - RecVisitorBR = nullptr; + // Don't analyze if the user explicitly asked for no checks to be performed + // on this file. + reportAnalyzerProgress("All checks are disabled using a supplied option\n"); + } else { + // Otherwise, just run the analysis. + runAnalysisOnTranslationUnit(C); } if (TUTotalTimer) TUTotalTimer->stopTimer(); diff --git a/test/Analysis/yaccignore.c b/test/Analysis/yaccignore.c new file mode 100644 index 0000000000..c9edfadaf2 --- /dev/null +++ b/test/Analysis/yaccignore.c @@ -0,0 +1,13 @@ +/* A Bison parser, made by GNU Bison 1.875. */ + +// RUN: rm -rf %t.plist +// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-output=plist -o %t.plist -verify %s +// RUN: FileCheck --input-file=%t.plist %s + +// expected-no-diagnostics +int foo() { + int *x = 0; + return *x; // no-warning +} + +// CHECK: diagnostics -- 2.40.0