diff options
author | Kristof Umann <dkszelethus@gmail.com> | 2018-09-14 10:10:09 +0000 |
---|---|---|
committer | Kristof Umann <dkszelethus@gmail.com> | 2018-09-14 10:10:09 +0000 |
commit | 43cdc8690f87bf974c1f6d2642da75ca6306fbfd (patch) | |
tree | be844e04fb7fb778a19b13aea39aaad35ec99cfa /lib/StaticAnalyzer/Checkers/UninitializedObject | |
parent | 91ef6e511f5a746095dffca144cbe57dc665d04a (diff) | |
download | clang-43cdc8690f87bf974c1f6d2642da75ca6306fbfd.tar.gz |
[analyzer][UninitializedObjectChecker] New flag to ignore records based on it's fields
Based on a suggestion from @george.karpenkov.
In some cases, structs are used as unions with a help of a tag/kind field.
This patch adds a new string flag (a pattern), that is matched against the
fields of a record, and should a match be found, the entire record is ignored.
For more info refer to http://lists.llvm.org/pipermail/cfe-dev/2018-August/058906.html
and to the responses to that, especially http://lists.llvm.org/pipermail/cfe-dev/2018-August/059215.html.
Differential Revision: https://reviews.llvm.org/D51680
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@342220 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/StaticAnalyzer/Checkers/UninitializedObject')
-rw-r--r-- | lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h | 10 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp | 34 |
2 files changed, 39 insertions, 5 deletions
diff --git a/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h b/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h index fbc241a283..e1e8cfa582 100644 --- a/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h +++ b/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h @@ -35,6 +35,13 @@ // `-analyzer-config \ // alpha.cplusplus.UninitializedObject:CheckPointeeInitialization=true`. // +// - "IgnoreRecordsWithField" (string). If supplied, the checker will not +// analyze structures that have a field with a name or type name that +// matches the given pattern. Defaults to "". +// +// `-analyzer-config \ +// alpha.cplusplus.UninitializedObject:IgnoreRecordsWithField="[Tt]ag|[Kk]ind"`. +// // TODO: With some clever heuristics, some pointers should be dereferenced // by default. For example, if the pointee is constructed within the // constructor call, it's reasonable to say that no external object @@ -60,7 +67,8 @@ namespace ento { struct UninitObjCheckerOptions { bool IsPedantic = false; bool ShouldConvertNotesToWarnings = false; - bool CheckPointeeInitialization = false; + bool CheckPointeeInitialization = false; + std::string IgnoredRecordsWithFieldPattern; }; /// A lightweight polymorphic wrapper around FieldRegion *. We'll use this diff --git a/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp b/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp index 92e21f9cce..b632229321 100644 --- a/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp @@ -109,6 +109,10 @@ getObjectVal(const CXXConstructorDecl *CtorDecl, CheckerContext &Context); static bool willObjectBeAnalyzedLater(const CXXConstructorDecl *Ctor, CheckerContext &Context); +/// Checks whether RD contains a field with a name or type name that matches +/// \p Pattern. +static bool shouldIgnoreRecord(const RecordDecl *RD, StringRef Pattern); + //===----------------------------------------------------------------------===// // Methods for UninitializedObjectChecker. //===----------------------------------------------------------------------===// @@ -228,6 +232,12 @@ bool FindUninitializedFields::isNonUnionUninit(const TypedValueRegion *R, return true; } + if (!Opts.IgnoredRecordsWithFieldPattern.empty() && + shouldIgnoreRecord(RD, Opts.IgnoredRecordsWithFieldPattern)) { + IsAnyFieldInitialized = true; + return false; + } + bool ContainsUninitField = false; // Are all of this non-union's fields initialized? @@ -442,6 +452,19 @@ static bool willObjectBeAnalyzedLater(const CXXConstructorDecl *Ctor, return false; } +static bool shouldIgnoreRecord(const RecordDecl *RD, StringRef Pattern) { + llvm::Regex R(Pattern); + + for (const FieldDecl *FD : RD->fields()) { + if (R.match(FD->getType().getAsString())) + return true; + if (R.match(FD->getName())) + return true; + } + + return false; +} + std::string clang::ento::getVariableName(const FieldDecl *Field) { // If Field is a captured lambda variable, Field->getName() will return with // an empty string. We can however acquire it's name from the lambda's @@ -472,10 +495,13 @@ void ento::registerUninitializedObjectChecker(CheckerManager &Mgr) { AnalyzerOptions &AnOpts = Mgr.getAnalyzerOptions(); UninitObjCheckerOptions &ChOpts = Chk->Opts; - ChOpts.IsPedantic = AnOpts.getBooleanOption( - "Pedantic", /*DefaultVal*/ false, Chk); - ChOpts.ShouldConvertNotesToWarnings = AnOpts.getBooleanOption( - "NotesAsWarnings", /*DefaultVal*/ false, Chk); + ChOpts.IsPedantic = + AnOpts.getBooleanOption("Pedantic", /*DefaultVal*/ false, Chk); + ChOpts.ShouldConvertNotesToWarnings = + AnOpts.getBooleanOption("NotesAsWarnings", /*DefaultVal*/ false, Chk); ChOpts.CheckPointeeInitialization = AnOpts.getBooleanOption( "CheckPointeeInitialization", /*DefaultVal*/ false, Chk); + ChOpts.IgnoredRecordsWithFieldPattern = + AnOpts.getOptionAsString("IgnoreRecordsWithField", + /*DefaultVal*/ "", Chk); } |