mirror of https://github.com/microsoft/clang.git
[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
This commit is contained in:
parent
1061365516
commit
ac61b333fd
|
@ -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();
|
||||
|
||||
{
|
||||
if (TUTotalTimer) TUTotalTimer->startTimer();
|
||||
if (isBisonFile(C)) {
|
||||
reportAnalyzerProgress("Skipping bison-generated file\n");
|
||||
} else if (Opts->DisableAllChecks) {
|
||||
|
||||
// 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);
|
||||
|
||||
// After all decls handled, run checkers on the entire TranslationUnit.
|
||||
checkerMgr->runCheckersOnEndOfTranslationUnit(TU, *Mgr, BR);
|
||||
|
||||
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();
|
||||
|
|
|
@ -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: <key>diagnostics</key>
|
Loading…
Reference in New Issue