summaryrefslogtreecommitdiffstats
path: root/clang/lib/StaticAnalyzer/Checkers/UninitializedObject
diff options
context:
space:
mode:
authorKristof Umann <dkszelethus@gmail.com>2018-09-14 10:10:09 +0000
committerKristof Umann <dkszelethus@gmail.com>2018-09-14 10:10:09 +0000
commitd6145d9849f48229980c9243c36cb08c2e45c869 (patch)
treee6b9431b2dc1e4eb85f23eb2570ac5c944b3bde3 /clang/lib/StaticAnalyzer/Checkers/UninitializedObject
parent6cec6c467ce93fafcf002a781326bfeaa57c6f49 (diff)
downloadbcm5719-llvm-d6145d9849f48229980c9243c36cb08c2e45c869.tar.gz
bcm5719-llvm-d6145d9849f48229980c9243c36cb08c2e45c869.zip
[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 llvm-svn: 342220
Diffstat (limited to 'clang/lib/StaticAnalyzer/Checkers/UninitializedObject')
-rw-r--r--clang/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h10
-rw-r--r--clang/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp34
2 files changed, 39 insertions, 5 deletions
diff --git a/clang/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h b/clang/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h
index fbc241a2831..e1e8cfa5826 100644
--- a/clang/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h
+++ b/clang/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/clang/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp
index 92e21f9cce9..b6322293212 100644
--- a/clang/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp
+++ b/clang/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);
}
OpenPOWER on IntegriCloud