summaryrefslogtreecommitdiffstats
path: root/include/clang/StaticAnalyzer
diff options
context:
space:
mode:
Diffstat (limited to 'include/clang/StaticAnalyzer')
-rw-r--r--include/clang/StaticAnalyzer/Checkers/CheckerBase.td37
-rw-r--r--include/clang/StaticAnalyzer/Checkers/Checkers.td609
-rw-r--r--include/clang/StaticAnalyzer/Core/Analyses.def1
-rw-r--r--include/clang/StaticAnalyzer/Core/AnalyzerOptions.def377
-rw-r--r--include/clang/StaticAnalyzer/Core/AnalyzerOptions.h608
-rw-r--r--include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h14
-rw-r--r--include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h2
-rw-r--r--include/clang/StaticAnalyzer/Core/Checker.h2
-rw-r--r--include/clang/StaticAnalyzer/Core/CheckerManager.h6
-rw-r--r--include/clang/StaticAnalyzer/Core/CheckerOptInfo.h44
-rw-r--r--include/clang/StaticAnalyzer/Core/CheckerRegistry.h9
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h21
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeMap.h5
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h21
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h2
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h6
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h29
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/RangedConstraintManager.h2
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/SMTConstraintManager.h54
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/SMTConv.h27
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/SMTSolver.h41
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/Store.h4
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h22
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/TaintManager.h10
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/WorkList.h1
-rw-r--r--include/clang/StaticAnalyzer/Core/RetainSummaryManager.h75
-rw-r--r--include/clang/StaticAnalyzer/Frontend/FrontendActions.h1
27 files changed, 1004 insertions, 1026 deletions
diff --git a/include/clang/StaticAnalyzer/Checkers/CheckerBase.td b/include/clang/StaticAnalyzer/Checkers/CheckerBase.td
index 11f1e5d4bd..15034fc689 100644
--- a/include/clang/StaticAnalyzer/Checkers/CheckerBase.td
+++ b/include/clang/StaticAnalyzer/Checkers/CheckerBase.td
@@ -11,29 +11,34 @@
//
//===----------------------------------------------------------------------===//
-class CheckerGroup<string name> {
- string GroupName = name;
-}
-class InGroup<CheckerGroup G> { CheckerGroup Group = G; }
-
+/// Describes a package. Every checker is a part of a package, for example,
+/// 'NullDereference' is part of the 'core' package, hence it's full name is
+/// 'core.NullDereference'.
+/// Example:
+/// def Core : Package<"core">;
class Package<string name> {
string PackageName = name;
- bit Hidden = 0;
Package ParentPackage;
- CheckerGroup Group;
}
-class InPackage<Package P> { Package ParentPackage = P; }
-// All checkers are an indirect subclass of this.
+/// Describes a 'super' package that holds another package inside it. This is
+/// used to nest packages in one another. One may, for example, create the
+/// 'builtin' package inside 'core', thus creating the package 'core.builtin'.
+/// Example:
+/// def CoreBuiltin : Package<"builtin">, ParentPackage<Core>;
+class ParentPackage<Package P> { Package ParentPackage = P; }
+
+/// A description. May be displayed to the user when clang is invoked with
+/// a '-help'-like command line option.
+class HelpText<string text> { string HelpText = text; }
+
+/// Describes a checker. Every builtin checker has to be registered with the use
+/// of this class (out-of-trunk checkers loaded from plugins obviously don't).
+/// Note that a checker has a name (e.g.: 'NullDereference'), and a fullname,
+/// that is autogenerated with the help of the ParentPackage field, that also
+/// includes package names (e.g.: 'core.NullDereference').
class Checker<string name = ""> {
string CheckerName = name;
- string DescFile;
string HelpText;
- bit Hidden = 0;
Package ParentPackage;
- CheckerGroup Group;
}
-
-class DescFile<string filename> { string DescFile = filename; }
-class HelpText<string text> { string HelpText = text; }
-class Hidden { bit Hidden = 1; }
diff --git a/include/clang/StaticAnalyzer/Checkers/Checkers.td b/include/clang/StaticAnalyzer/Checkers/Checkers.td
index 435bf6023a..9feb5a8766 100644
--- a/include/clang/StaticAnalyzer/Checkers/Checkers.td
+++ b/include/clang/StaticAnalyzer/Checkers/Checkers.td
@@ -21,9 +21,9 @@ include "CheckerBase.td"
def Alpha : Package<"alpha">;
def Core : Package<"core">;
-def CoreBuiltin : Package<"builtin">, InPackage<Core>;
-def CoreUninitialized : Package<"uninitialized">, InPackage<Core>;
-def CoreAlpha : Package<"core">, InPackage<Alpha>, Hidden;
+def CoreBuiltin : Package<"builtin">, ParentPackage<Core>;
+def CoreUninitialized : Package<"uninitialized">, ParentPackage<Core>;
+def CoreAlpha : Package<"core">, ParentPackage<Alpha>;
// The OptIn package is for checkers that are not alpha and that would normally
// be on by default but where the driver does not have enough information to
@@ -41,58 +41,59 @@ def OptIn : Package<"optin">;
// In the Portability package reside checkers for finding code that relies on
// implementation-defined behavior. Such checks are wanted for cross-platform
// development, but unwanted for developers who target only a single platform.
-def PortabilityOptIn : Package<"portability">, InPackage<OptIn>;
+def PortabilityOptIn : Package<"portability">, ParentPackage<OptIn>;
def Nullability : Package<"nullability">;
def Cplusplus : Package<"cplusplus">;
-def CplusplusAlpha : Package<"cplusplus">, InPackage<Alpha>, Hidden;
-def CplusplusOptIn : Package<"cplusplus">, InPackage<OptIn>;
+def CplusplusAlpha : Package<"cplusplus">, ParentPackage<Alpha>;
+def CplusplusOptIn : Package<"cplusplus">, ParentPackage<OptIn>;
def Valist : Package<"valist">;
def DeadCode : Package<"deadcode">;
-def DeadCodeAlpha : Package<"deadcode">, InPackage<Alpha>, Hidden;
+def DeadCodeAlpha : Package<"deadcode">, ParentPackage<Alpha>;
-def Performance : Package<"performance">, InPackage<OptIn>;
+def Performance : Package<"performance">, ParentPackage<OptIn>;
def Security : Package <"security">;
-def InsecureAPI : Package<"insecureAPI">, InPackage<Security>;
-def SecurityAlpha : Package<"security">, InPackage<Alpha>, Hidden;
-def Taint : Package<"taint">, InPackage<SecurityAlpha>, Hidden;
+def InsecureAPI : Package<"insecureAPI">, ParentPackage<Security>;
+def SecurityAlpha : Package<"security">, ParentPackage<Alpha>;
+def Taint : Package<"taint">, ParentPackage<SecurityAlpha>;
def Unix : Package<"unix">;
-def UnixAlpha : Package<"unix">, InPackage<Alpha>, Hidden;
-def CString : Package<"cstring">, InPackage<Unix>, Hidden;
-def CStringAlpha : Package<"cstring">, InPackage<UnixAlpha>, Hidden;
+def UnixAlpha : Package<"unix">, ParentPackage<Alpha>;
+def CString : Package<"cstring">, ParentPackage<Unix>;
+def CStringAlpha : Package<"cstring">, ParentPackage<UnixAlpha>;
def OSX : Package<"osx">;
-def OSXAlpha : Package<"osx">, InPackage<Alpha>, Hidden;
-def OSXOptIn : Package<"osx">, InPackage<OptIn>;
+def OSXAlpha : Package<"osx">, ParentPackage<Alpha>;
+def OSXOptIn : Package<"osx">, ParentPackage<OptIn>;
-def Cocoa : Package<"cocoa">, InPackage<OSX>;
-def CocoaAlpha : Package<"cocoa">, InPackage<OSXAlpha>, Hidden;
-def CocoaOptIn : Package<"cocoa">, InPackage<OSXOptIn>;
+def Cocoa : Package<"cocoa">, ParentPackage<OSX>;
+def CocoaAlpha : Package<"cocoa">, ParentPackage<OSXAlpha>;
+def CocoaOptIn : Package<"cocoa">, ParentPackage<OSXOptIn>;
-def CoreFoundation : Package<"coreFoundation">, InPackage<OSX>;
-def Containers : Package<"containers">, InPackage<CoreFoundation>;
+def CoreFoundation : Package<"coreFoundation">, ParentPackage<OSX>;
+def Containers : Package<"containers">, ParentPackage<CoreFoundation>;
-def LocalizabilityAlpha : Package<"localizability">, InPackage<CocoaAlpha>;
-def LocalizabilityOptIn : Package<"localizability">, InPackage<CocoaOptIn>;
+def LocalizabilityAlpha : Package<"localizability">, ParentPackage<CocoaAlpha>;
+def LocalizabilityOptIn : Package<"localizability">, ParentPackage<CocoaOptIn>;
-def MPI : Package<"mpi">, InPackage<OptIn>;
+def MPI : Package<"mpi">, ParentPackage<OptIn>;
def LLVM : Package<"llvm">;
+def LLVMAlpha : Package<"llvm">, ParentPackage<Alpha>;
// The APIModeling package is for checkers that model APIs and don't perform
// any diagnostics. These checkers are always turned on; this package is
// intended for API modeling that is not controlled by the target triple.
-def APIModeling : Package<"apiModeling">, Hidden;
-def GoogleAPIModeling : Package<"google">, InPackage<APIModeling>;
+def APIModeling : Package<"apiModeling">;
+def GoogleAPIModeling : Package<"google">, ParentPackage<APIModeling>;
def Debug : Package<"debug">;
-def CloneDetectionAlpha : Package<"clone">, InPackage<Alpha>, Hidden;
+def CloneDetectionAlpha : Package<"clone">, ParentPackage<Alpha>;
//===----------------------------------------------------------------------===//
// Core Checkers.
@@ -101,130 +102,120 @@ def CloneDetectionAlpha : Package<"clone">, InPackage<Alpha>, Hidden;
let ParentPackage = Core in {
def DereferenceChecker : Checker<"NullDereference">,
- HelpText<"Check for dereferences of null pointers">,
- DescFile<"DereferenceChecker.cpp">;
+ HelpText<"Check for dereferences of null pointers">;
def CallAndMessageChecker : Checker<"CallAndMessage">,
- HelpText<"Check for logical errors for function calls and Objective-C message expressions (e.g., uninitialized arguments, null function pointers)">,
- DescFile<"CallAndMessageChecker.cpp">;
+ HelpText<"Check for logical errors for function calls and Objective-C "
+ "message expressions (e.g., uninitialized arguments, null function "
+ "pointers)">;
def NonNullParamChecker : Checker<"NonNullParamChecker">,
- HelpText<"Check for null pointers passed as arguments to a function whose arguments are references or marked with the 'nonnull' attribute">,
- DescFile<"NonNullParamChecker.cpp">;
+ HelpText<"Check for null pointers passed as arguments to a function whose "
+ "arguments are references or marked with the 'nonnull' attribute">;
def VLASizeChecker : Checker<"VLASize">,
- HelpText<"Check for declarations of VLA of undefined or zero size">,
- DescFile<"VLASizeChecker.cpp">;
+ HelpText<"Check for declarations of VLA of undefined or zero size">;
def DivZeroChecker : Checker<"DivideZero">,
- HelpText<"Check for division by zero">,
- DescFile<"DivZeroChecker.cpp">;
+ HelpText<"Check for division by zero">;
def UndefResultChecker : Checker<"UndefinedBinaryOperatorResult">,
- HelpText<"Check for undefined results of binary operators">,
- DescFile<"UndefResultChecker.cpp">;
+ HelpText<"Check for undefined results of binary operators">;
def StackAddrEscapeChecker : Checker<"StackAddressEscape">,
- HelpText<"Check that addresses to stack memory do not escape the function">,
- DescFile<"StackAddrEscapeChecker.cpp">;
+ HelpText<"Check that addresses to stack memory do not escape the function">;
def DynamicTypePropagation : Checker<"DynamicTypePropagation">,
- HelpText<"Generate dynamic type information">,
- DescFile<"DynamicTypePropagation.cpp">;
+ HelpText<"Generate dynamic type information">;
def NonnullGlobalConstantsChecker: Checker<"NonnilStringConstants">,
- HelpText<"Assume that const string-like globals are non-null">,
- DescFile<"NonilStringConstantsChecker.cpp">;
+ HelpText<"Assume that const string-like globals are non-null">;
} // end "core"
let ParentPackage = CoreAlpha in {
def BoolAssignmentChecker : Checker<"BoolAssignment">,
- HelpText<"Warn about assigning non-{0,1} values to Boolean variables">,
- DescFile<"BoolAssignmentChecker.cpp">;
+ HelpText<"Warn about assigning non-{0,1} values to Boolean variables">;
def CastSizeChecker : Checker<"CastSize">,
- HelpText<"Check when casting a malloc'ed type T, whether the size is a multiple of the size of T">,
- DescFile<"CastSizeChecker.cpp">;
+ HelpText<"Check when casting a malloc'ed type T, whether the size is a "
+ "multiple of the size of T">;
def CastToStructChecker : Checker<"CastToStruct">,
- HelpText<"Check for cast from non-struct pointer to struct pointer">,
- DescFile<"CastToStructChecker.cpp">;
+ HelpText<"Check for cast from non-struct pointer to struct pointer">;
def ConversionChecker : Checker<"Conversion">,
- HelpText<"Loss of sign/precision in implicit conversions">,
- DescFile<"ConversionChecker.cpp">;
+ HelpText<"Loss of sign/precision in implicit conversions">;
def IdenticalExprChecker : Checker<"IdenticalExpr">,
- HelpText<"Warn about unintended use of identical expressions in operators">,
- DescFile<"IdenticalExprChecker.cpp">;
+ HelpText<"Warn about unintended use of identical expressions in operators">;
def FixedAddressChecker : Checker<"FixedAddr">,
- HelpText<"Check for assignment of a fixed address to a pointer">,
- DescFile<"FixedAddressChecker.cpp">;
+ HelpText<"Check for assignment of a fixed address to a pointer">;
def PointerArithChecker : Checker<"PointerArithm">,
- HelpText<"Check for pointer arithmetic on locations other than array elements">,
- DescFile<"PointerArithChecker">;
+ HelpText<"Check for pointer arithmetic on locations other than array "
+ "elements">;
def PointerSubChecker : Checker<"PointerSub">,
- HelpText<"Check for pointer subtractions on two pointers pointing to different memory chunks">,
- DescFile<"PointerSubChecker">;
+ HelpText<"Check for pointer subtractions on two pointers pointing to "
+ "different memory chunks">;
def SizeofPointerChecker : Checker<"SizeofPtr">,
- HelpText<"Warn about unintended use of sizeof() on pointer expressions">,
- DescFile<"CheckSizeofPointer.cpp">;
+ HelpText<"Warn about unintended use of sizeof() on pointer expressions">;
def CallAndMessageUnInitRefArg : Checker<"CallAndMessageUnInitRefArg">,
- HelpText<"Check for logical errors for function calls and Objective-C message expressions (e.g., uninitialized arguments, null function pointers, and pointer to undefined variables)">,
- DescFile<"CallAndMessageChecker.cpp">;
+ HelpText<"Check for logical errors for function calls and Objective-C "
+ "message expressions (e.g., uninitialized arguments, null function "
+ "pointers, and pointer to undefined variables)">;
def TestAfterDivZeroChecker : Checker<"TestAfterDivZero">,
- HelpText<"Check for division by variable that is later compared against 0. Either the comparison is useless or there is division by zero.">,
- DescFile<"TestAfterDivZeroChecker.cpp">;
+ HelpText<"Check for division by variable that is later compared against 0. "
+ "Either the comparison is useless or there is division by zero.">;
def DynamicTypeChecker : Checker<"DynamicTypeChecker">,
- HelpText<"Check for cases where the dynamic and the static type of an object are unrelated.">,
- DescFile<"DynamicTypeChecker.cpp">;
+ HelpText<"Check for cases where the dynamic and the static type of an object "
+ "are unrelated.">;
def StackAddrAsyncEscapeChecker : Checker<"StackAddressAsyncEscape">,
- HelpText<"Check that addresses to stack memory do not escape the function">,
- DescFile<"StackAddrEscapeChecker.cpp">;
+ HelpText<"Check that addresses to stack memory do not escape the function">;
} // end "alpha.core"
let ParentPackage = Nullability in {
def NullPassedToNonnullChecker : Checker<"NullPassedToNonnull">,
- HelpText<"Warns when a null pointer is passed to a pointer which has a _Nonnull type.">,
- DescFile<"NullabilityChecker.cpp">;
+ HelpText<"Warns when a null pointer is passed to a pointer which has a "
+ "_Nonnull type.">;
def NullReturnedFromNonnullChecker : Checker<"NullReturnedFromNonnull">,
- HelpText<"Warns when a null pointer is returned from a function that has _Nonnull return type.">,
- DescFile<"NullabilityChecker.cpp">;
+ HelpText<"Warns when a null pointer is returned from a function that has "
+ "_Nonnull return type.">;
def NullableDereferencedChecker : Checker<"NullableDereferenced">,
- HelpText<"Warns when a nullable pointer is dereferenced.">,
- DescFile<"NullabilityChecker.cpp">;
+ HelpText<"Warns when a nullable pointer is dereferenced.">;
def NullablePassedToNonnullChecker : Checker<"NullablePassedToNonnull">,
- HelpText<"Warns when a nullable pointer is passed to a pointer which has a _Nonnull type.">,
- DescFile<"NullabilityChecker.cpp">;
+ HelpText<"Warns when a nullable pointer is passed to a pointer which has a "
+ "_Nonnull type.">;
def NullableReturnedFromNonnullChecker : Checker<"NullableReturnedFromNonnull">,
- HelpText<"Warns when a nullable pointer is returned from a function that has _Nonnull return type.">,
- DescFile<"NullabilityChecker.cpp">;
+ HelpText<"Warns when a nullable pointer is returned from a function that has "
+ "_Nonnull return type.">;
} // end "nullability"
let ParentPackage = APIModeling in {
+def StdCLibraryFunctionsChecker : Checker<"StdCLibraryFunctions">,
+ HelpText<"Improve modeling of the C standard library functions">;
+
def TrustNonnullChecker : Checker<"TrustNonnull">,
- HelpText<"Trust that returns from framework methods annotated with _Nonnull are not null">,
- DescFile<"TrustNonnullChecker.cpp">;
+ HelpText<"Trust that returns from framework methods annotated with _Nonnull "
+ "are not null">;
-}
+} // end "apiModeling"
//===----------------------------------------------------------------------===//
// Evaluate "builtin" functions.
@@ -233,12 +224,11 @@ def TrustNonnullChecker : Checker<"TrustNonnull">,
let ParentPackage = CoreBuiltin in {
def NoReturnFunctionChecker : Checker<"NoReturnFunctions">,
- HelpText<"Evaluate \"panic\" functions that are known to not return to the caller">,
- DescFile<"NoReturnFunctionChecker.cpp">;
+ HelpText<"Evaluate \"panic\" functions that are known to not return to the "
+ "caller">;
def BuiltinFunctionChecker : Checker<"BuiltinFunctions">,
- HelpText<"Evaluate compiler builtin functions (e.g., alloca())">,
- DescFile<"BuiltinFunctionChecker.cpp">;
+ HelpText<"Evaluate compiler builtin functions (e.g., alloca())">;
} // end "core.builtin"
@@ -249,24 +239,19 @@ def BuiltinFunctionChecker : Checker<"BuiltinFunctions">,
let ParentPackage = CoreUninitialized in {
def UndefinedArraySubscriptChecker : Checker<"ArraySubscript">,
- HelpText<"Check for uninitialized values used as array subscripts">,
- DescFile<"UndefinedArraySubscriptChecker.cpp">;
+ HelpText<"Check for uninitialized values used as array subscripts">;
def UndefinedAssignmentChecker : Checker<"Assign">,
- HelpText<"Check for assigning uninitialized values">,
- DescFile<"UndefinedAssignmentChecker.cpp">;
+ HelpText<"Check for assigning uninitialized values">;
def UndefBranchChecker : Checker<"Branch">,
- HelpText<"Check for uninitialized values used as branch conditions">,
- DescFile<"UndefBranchChecker.cpp">;
+ HelpText<"Check for uninitialized values used as branch conditions">;
def UndefCapturedBlockVarChecker : Checker<"CapturedBlockVariable">,
- HelpText<"Check for blocks that capture uninitialized values">,
- DescFile<"UndefCapturedBlockVarChecker.cpp">;
+ HelpText<"Check for blocks that capture uninitialized values">;
def ReturnUndefChecker : Checker<"UndefReturn">,
- HelpText<"Check for uninitialized values being returned to the caller">,
- DescFile<"ReturnUndefChecker.cpp">;
+ HelpText<"Check for uninitialized values being returned to the caller">;
} // end "core.uninitialized"
@@ -277,28 +262,25 @@ def ReturnUndefChecker : Checker<"UndefReturn">,
let ParentPackage = Cplusplus in {
def InnerPointerChecker : Checker<"InnerPointer">,
- HelpText<"Check for inner pointers of C++ containers used after re/deallocation">,
- DescFile<"InnerPointerChecker.cpp">;
+ HelpText<"Check for inner pointers of C++ containers used after "
+ "re/deallocation">;
def NewDeleteChecker : Checker<"NewDelete">,
- HelpText<"Check for double-free and use-after-free problems. Traces memory managed by new/delete.">,
- DescFile<"MallocChecker.cpp">;
+ HelpText<"Check for double-free and use-after-free problems. Traces memory "
+ "managed by new/delete.">;
def NewDeleteLeaksChecker : Checker<"NewDeleteLeaks">,
- HelpText<"Check for memory leaks. Traces memory managed by new/delete.">,
- DescFile<"MallocChecker.cpp">;
+ HelpText<"Check for memory leaks. Traces memory managed by new/delete.">;
def CXXSelfAssignmentChecker : Checker<"SelfAssignment">,
- HelpText<"Checks C++ copy and move assignment operators for self assignment">,
- DescFile<"CXXSelfAssignmentChecker.cpp">;
+ HelpText<"Checks C++ copy and move assignment operators for self assignment">;
} // end: "cplusplus"
let ParentPackage = CplusplusOptIn in {
def VirtualCallChecker : Checker<"VirtualCall">,
- HelpText<"Check virtual function calls during construction or destruction">,
- DescFile<"VirtualCallChecker.cpp">;
+ HelpText<"Check virtual function calls during construction or destruction">;
} // end: "optin.cplusplus"
@@ -306,29 +288,26 @@ let ParentPackage = CplusplusAlpha in {
def DeleteWithNonVirtualDtorChecker : Checker<"DeleteWithNonVirtualDtor">,
HelpText<"Reports destructions of polymorphic objects with a non-virtual "
- "destructor in their base class">,
- DescFile<"DeleteWithNonVirtualDtorChecker.cpp">;
+ "destructor in their base class">;
+
+def EnumCastOutOfRangeChecker : Checker<"EnumCastOutOfRange">,
+ HelpText<"Check integer to enumeration casts for out of range values">;
def InvalidatedIteratorChecker : Checker<"InvalidatedIterator">,
- HelpText<"Check for use of invalidated iterators">,
- DescFile<"IteratorChecker.cpp">;
+ HelpText<"Check for use of invalidated iterators">;
def IteratorRangeChecker : Checker<"IteratorRange">,
- HelpText<"Check for iterators used outside their valid ranges">,
- DescFile<"IteratorChecker.cpp">;
+ HelpText<"Check for iterators used outside their valid ranges">;
def MismatchedIteratorChecker : Checker<"MismatchedIterator">,
- HelpText<"Check for use of iterators of different containers where iterators of the same container are expected">,
- DescFile<"IteratorChecker.cpp">;
+ HelpText<"Check for use of iterators of different containers where iterators "
+ "of the same container are expected">;
-def MisusedMovedObjectChecker: Checker<"MisusedMovedObject">,
- HelpText<"Method calls on a moved-from object and copying a moved-from "
- "object will be reported">,
- DescFile<"MisusedMovedObjectChecker.cpp">;
+def MoveChecker: Checker<"Move">,
+ HelpText<"Find use-after-move bugs in C++">;
def UninitializedObjectChecker: Checker<"UninitializedObject">,
- HelpText<"Reports uninitialized fields after object construction">,
- DescFile<"UninitializedObjectChecker.cpp">;
+ HelpText<"Reports uninitialized fields after object construction">;
} // end: "alpha.cplusplus"
@@ -340,16 +319,13 @@ def UninitializedObjectChecker: Checker<"UninitializedObject">,
let ParentPackage = Valist in {
def UninitializedChecker : Checker<"Uninitialized">,
- HelpText<"Check for usages of uninitialized (or already released) va_lists.">,
- DescFile<"ValistChecker.cpp">;
+ HelpText<"Check for usages of uninitialized (or already released) va_lists.">;
def UnterminatedChecker : Checker<"Unterminated">,
- HelpText<"Check for va_lists which are not released by a va_end call.">,
- DescFile<"ValistChecker.cpp">;
+ HelpText<"Check for va_lists which are not released by a va_end call.">;
def CopyToSelfChecker : Checker<"CopyToSelf">,
- HelpText<"Check for va_lists which are copied onto itself.">,
- DescFile<"ValistChecker.cpp">;
+ HelpText<"Check for va_lists which are copied onto itself.">;
} // end : "valist"
@@ -360,15 +336,15 @@ def CopyToSelfChecker : Checker<"CopyToSelf">,
let ParentPackage = DeadCode in {
def DeadStoresChecker : Checker<"DeadStores">,
- HelpText<"Check for values stored to variables that are never read afterwards">,
- DescFile<"DeadStoresChecker.cpp">;
+ HelpText<"Check for values stored to variables that are never read "
+ "afterwards">;
+
} // end DeadCode
let ParentPackage = DeadCodeAlpha in {
def UnreachableCodeChecker : Checker<"UnreachableCode">,
- HelpText<"Check unreachable code">,
- DescFile<"UnreachableCodeChecker.cpp">;
+ HelpText<"Check unreachable code">;
} // end "alpha.deadcode"
@@ -379,8 +355,7 @@ def UnreachableCodeChecker : Checker<"UnreachableCode">,
let ParentPackage = Performance in {
def PaddingChecker : Checker<"Padding">,
- HelpText<"Check for excessively padded structs.">,
- DescFile<"PaddingChecker.cpp">;
+ HelpText<"Check for excessively padded structs.">;
} // end: "padding"
@@ -389,70 +364,61 @@ def PaddingChecker : Checker<"Padding">,
//===----------------------------------------------------------------------===//
let ParentPackage = InsecureAPI in {
- def bcmp : Checker<"bcmp">,
- HelpText<"Warn on uses of the 'bcmp' function">,
- DescFile<"CheckSecuritySyntaxOnly.cpp">;
- def bcopy : Checker<"bcopy">,
- HelpText<"Warn on uses of the 'bcopy' function">,
- DescFile<"CheckSecuritySyntaxOnly.cpp">;
- def bzero : Checker<"bzero">,
- HelpText<"Warn on uses of the 'bzero' function">,
- DescFile<"CheckSecuritySyntaxOnly.cpp">;
- def gets : Checker<"gets">,
- HelpText<"Warn on uses of the 'gets' function">,
- DescFile<"CheckSecuritySyntaxOnly.cpp">;
- def getpw : Checker<"getpw">,
- HelpText<"Warn on uses of the 'getpw' function">,
- DescFile<"CheckSecuritySyntaxOnly.cpp">;
- def mktemp : Checker<"mktemp">,
- HelpText<"Warn on uses of the 'mktemp' function">,
- DescFile<"CheckSecuritySyntaxOnly.cpp">;
- def mkstemp : Checker<"mkstemp">,
- HelpText<"Warn when 'mkstemp' is passed fewer than 6 X's in the format string">,
- DescFile<"CheckSecuritySyntaxOnly.cpp">;
- def rand : Checker<"rand">,
- HelpText<"Warn on uses of the 'rand', 'random', and related functions">,
- DescFile<"CheckSecuritySyntaxOnly.cpp">;
- def strcpy : Checker<"strcpy">,
- HelpText<"Warn on uses of the 'strcpy' and 'strcat' functions">,
- DescFile<"CheckSecuritySyntaxOnly.cpp">;
- def vfork : Checker<"vfork">,
- HelpText<"Warn on uses of the 'vfork' function">,
- DescFile<"CheckSecuritySyntaxOnly.cpp">;
- def UncheckedReturn : Checker<"UncheckedReturn">,
- HelpText<"Warn on uses of functions whose return values must be always checked">,
- DescFile<"CheckSecuritySyntaxOnly.cpp">;
-}
+
+def bcmp : Checker<"bcmp">,
+ HelpText<"Warn on uses of the 'bcmp' function">;
+def bcopy : Checker<"bcopy">,
+ HelpText<"Warn on uses of the 'bcopy' function">;
+def bzero : Checker<"bzero">,
+ HelpText<"Warn on uses of the 'bzero' function">;
+def gets : Checker<"gets">,
+ HelpText<"Warn on uses of the 'gets' function">;
+def getpw : Checker<"getpw">,
+ HelpText<"Warn on uses of the 'getpw' function">;
+def mktemp : Checker<"mktemp">,
+ HelpText<"Warn on uses of the 'mktemp' function">;
+def mkstemp : Checker<"mkstemp">,
+ HelpText<"Warn when 'mkstemp' is passed fewer than 6 X's in the format "
+ "string">;
+def rand : Checker<"rand">,
+ HelpText<"Warn on uses of the 'rand', 'random', and related functions">;
+def strcpy : Checker<"strcpy">,
+ HelpText<"Warn on uses of the 'strcpy' and 'strcat' functions">;
+def vfork : Checker<"vfork">,
+ HelpText<"Warn on uses of the 'vfork' function">;
+def UncheckedReturn : Checker<"UncheckedReturn">,
+ HelpText<"Warn on uses of functions whose return values must be always "
+ "checked">;
+
+} // end "security.insecureAPI"
+
let ParentPackage = Security in {
- def FloatLoopCounter : Checker<"FloatLoopCounter">,
- HelpText<"Warn on using a floating point value as a loop counter (CERT: FLP30-C, FLP30-CPP)">,
- DescFile<"CheckSecuritySyntaxOnly.cpp">;
-}
+
+def FloatLoopCounter : Checker<"FloatLoopCounter">,
+ HelpText<"Warn on using a floating point value as a loop counter (CERT: "
+ "FLP30-C, FLP30-CPP)">;
+
+} // end "security"
let ParentPackage = SecurityAlpha in {
def ArrayBoundChecker : Checker<"ArrayBound">,
- HelpText<"Warn about buffer overflows (older checker)">,
- DescFile<"ArrayBoundChecker.cpp">;
+ HelpText<"Warn about buffer overflows (older checker)">;
def ArrayBoundCheckerV2 : Checker<"ArrayBoundV2">,
- HelpText<"Warn about buffer overflows (newer checker)">,
- DescFile<"ArrayBoundCheckerV2.cpp">;
+ HelpText<"Warn about buffer overflows (newer checker)">;
def ReturnPointerRangeChecker : Checker<"ReturnPtrRange">,
- HelpText<"Check for an out-of-bound pointer being returned to callers">,
- DescFile<"ReturnPointerRangeChecker.cpp">;
+ HelpText<"Check for an out-of-bound pointer being returned to callers">;
def MallocOverflowSecurityChecker : Checker<"MallocOverflow">,
- HelpText<"Check for overflows in the arguments to malloc()">,
- DescFile<"MallocOverflowSecurityChecker.cpp">;
+ HelpText<"Check for overflows in the arguments to malloc()">;
// Operating systems specific PROT_READ/PROT_WRITE values is not implemented,
// the defaults are correct for several common operating systems though,
// but may need to be overridden via the related analyzer-config flags.
def MmapWriteExecChecker : Checker<"MmapWriteExec">,
- HelpText<"Warn on mmap() calls that are both writable and executable">,
- DescFile<"MmapWriteExecChecker.cpp">;
+ HelpText<"Warn on mmap() calls that are both writable and executable">;
} // end "alpha.security"
@@ -463,8 +429,7 @@ def MmapWriteExecChecker : Checker<"MmapWriteExec">,
let ParentPackage = Taint in {
def GenericTaintChecker : Checker<"TaintPropagation">,
- HelpText<"Generate taint information used by other checkers">,
- DescFile<"GenericTaintChecker.cpp">;
+ HelpText<"Generate taint information used by other checkers">;
} // end "alpha.security.taint"
@@ -475,80 +440,66 @@ def GenericTaintChecker : Checker<"TaintPropagation">,
let ParentPackage = Unix in {
def UnixAPIMisuseChecker : Checker<"API">,
- HelpText<"Check calls to various UNIX/Posix functions">,
- DescFile<"UnixAPIChecker.cpp">;
+ HelpText<"Check calls to various UNIX/Posix functions">;
def MallocChecker: Checker<"Malloc">,
- HelpText<"Check for memory leaks, double free, and use-after-free problems. Traces memory managed by malloc()/free().">,
- DescFile<"MallocChecker.cpp">;
+ HelpText<"Check for memory leaks, double free, and use-after-free problems. "
+ "Traces memory managed by malloc()/free().">;
def MallocSizeofChecker : Checker<"MallocSizeof">,
- HelpText<"Check for dubious malloc arguments involving sizeof">,
- DescFile<"MallocSizeofChecker.cpp">;
+ HelpText<"Check for dubious malloc arguments involving sizeof">;
def MismatchedDeallocatorChecker : Checker<"MismatchedDeallocator">,
- HelpText<"Check for mismatched deallocators.">,
- DescFile<"MallocChecker.cpp">;
+ HelpText<"Check for mismatched deallocators.">;
def VforkChecker : Checker<"Vfork">,
- HelpText<"Check for proper usage of vfork">,
- DescFile<"VforkChecker.cpp">;
-
-def StdCLibraryFunctionsChecker : Checker<"StdCLibraryFunctions">,
- HelpText<"Improve modeling of the C standard library functions">,
- DescFile<"StdLibraryFunctionsChecker.cpp">;
+ HelpText<"Check for proper usage of vfork">;
} // end "unix"
let ParentPackage = UnixAlpha in {
def ChrootChecker : Checker<"Chroot">,
- HelpText<"Check improper use of chroot">,
- DescFile<"ChrootChecker.cpp">;
+ HelpText<"Check improper use of chroot">;
def PthreadLockChecker : Checker<"PthreadLock">,
- HelpText<"Simple lock -> unlock checker">,
- DescFile<"PthreadLockChecker.cpp">;
+ HelpText<"Simple lock -> unlock checker">;
def StreamChecker : Checker<"Stream">,
- HelpText<"Check stream handling functions">,
- DescFile<"StreamChecker.cpp">;
+ HelpText<"Check stream handling functions">;
def SimpleStreamChecker : Checker<"SimpleStream">,
- HelpText<"Check for misuses of stream APIs">,
- DescFile<"SimpleStreamChecker.cpp">;
+ HelpText<"Check for misuses of stream APIs">;
def BlockInCriticalSectionChecker : Checker<"BlockInCriticalSection">,
- HelpText<"Check for calls to blocking functions inside a critical section">,
- DescFile<"BlockInCriticalSectionChecker.cpp">;
+ HelpText<"Check for calls to blocking functions inside a critical section">;
} // end "alpha.unix"
let ParentPackage = CString in {
def CStringNullArg : Checker<"NullArg">,
- HelpText<"Check for null pointers being passed as arguments to C string functions">,
- DescFile<"CStringChecker.cpp">;
+ HelpText<"Check for null pointers being passed as arguments to C string "
+ "functions">;
def CStringSyntaxChecker : Checker<"BadSizeArg">,
- HelpText<"Check the size argument passed into C string functions for common erroneous patterns">,
- DescFile<"CStringSyntaxChecker.cpp">;
-}
+ HelpText<"Check the size argument passed into C string functions for common "
+ "erroneous patterns">;
+
+} // end "unix.cstring"
let ParentPackage = CStringAlpha in {
def CStringOutOfBounds : Checker<"OutOfBounds">,
- HelpText<"Check for out-of-bounds access in string functions">,
- DescFile<"CStringChecker.cpp">;
+ HelpText<"Check for out-of-bounds access in string functions">;
def CStringBufferOverlap : Checker<"BufferOverlap">,
- HelpText<"Checks for overlap in two buffer arguments">,
- DescFile<"CStringChecker.cpp">;
+ HelpText<"Checks for overlap in two buffer arguments">;
def CStringNotNullTerm : Checker<"NotNullTerminated">,
- HelpText<"Check for arguments which are not null-terminating strings">,
- DescFile<"CStringChecker.cpp">;
-}
+ HelpText<"Check for arguments which are not null-terminating strings">;
+
+} // end "alpha.unix.cstring"
//===----------------------------------------------------------------------===//
// Mac OS X, Cocoa, and Core Foundation checkers.
@@ -557,193 +508,189 @@ def CStringNotNullTerm : Checker<"NotNullTerminated">,
let ParentPackage = OSX in {
def NumberObjectConversionChecker : Checker<"NumberObjectConversion">,
- HelpText<"Check for erroneous conversions of objects representing numbers into numbers">,
- DescFile<"NumberObjectConversionChecker.cpp">;
+ HelpText<"Check for erroneous conversions of objects representing numbers "
+ "into numbers">;
def MacOSXAPIChecker : Checker<"API">,
- HelpText<"Check for proper uses of various Apple APIs">,
- DescFile<"MacOSXAPIChecker.cpp">;
+ HelpText<"Check for proper uses of various Apple APIs">;
def MacOSKeychainAPIChecker : Checker<"SecKeychainAPI">,
- HelpText<"Check for proper uses of Secure Keychain APIs">,
- DescFile<"MacOSKeychainAPIChecker.cpp">;
+ HelpText<"Check for proper uses of Secure Keychain APIs">;
def ObjCPropertyChecker : Checker<"ObjCProperty">,
- HelpText<"Check for proper uses of Objective-C properties">,
- DescFile<"ObjCPropertyChecker.cpp">;
+ HelpText<"Check for proper uses of Objective-C properties">;
+
+def OSObjectRetainCountChecker : Checker<"OSObjectRetainCount">,
+ HelpText<"Check for leaks and improper reference count management for OSObject">;
} // end "osx"
let ParentPackage = Cocoa in {
def RunLoopAutoreleaseLeakChecker : Checker<"RunLoopAutoreleaseLeak">,
- HelpText<"Check for leaked memory in autorelease pools that will never be drained">,
- DescFile<"RunLoopAutoreleaseLeakChecker.cpp">;
+ HelpText<"Check for leaked memory in autorelease pools that will never be "
+ "drained">;
def ObjCAtSyncChecker : Checker<"AtSync">,
- HelpText<"Check for nil pointers used as mutexes for @synchronized">,
- DescFile<"ObjCAtSyncChecker.cpp">;
+ HelpText<"Check for nil pointers used as mutexes for @synchronized">;
def NilArgChecker : Checker<"NilArg">,
- HelpText<"Check for prohibited nil arguments to ObjC method calls">,
- DescFile<"BasicObjCFoundationChecks.cpp">;
+ HelpText<"Check for prohibited nil arguments to ObjC method calls">;
def ClassReleaseChecker : Checker<"ClassRelease">,
- HelpText<"Check for sending 'retain', 'release', or 'autorelease' directly to a Class">,
- DescFile<"BasicObjCFoundationChecks.cpp">;
+ HelpText<"Check for sending 'retain', 'release', or 'autorelease' directly "
+ "to a Class">;
def VariadicMethodTypeChecker : Checker<"VariadicMethodTypes">,
HelpText<"Check for passing non-Objective-C types to variadic collection "
- "initialization methods that expect only Objective-C types">,
- DescFile<"BasicObjCFoundationChecks.cpp">;
+ "initialization methods that expect only Objective-C types">;
def NSAutoreleasePoolChecker : Checker<"NSAutoreleasePool">,
- HelpText<"Warn for suboptimal uses of NSAutoreleasePool in Objective-C GC mode">,
- DescFile<"NSAutoreleasePoolChecker.cpp">;
+ HelpText<"Warn for suboptimal uses of NSAutoreleasePool in Objective-C GC "
+ "mode">;
def ObjCMethSigsChecker : Checker<"IncompatibleMethodTypes">,
- HelpText<"Warn about Objective-C method signatures with type incompatibilities">,
- DescFile<"CheckObjCInstMethSignature.cpp">;
+ HelpText<"Warn about Objective-C method signatures with type "
+ "incompatibilities">;
def ObjCUnusedIvarsChecker : Checker<"UnusedIvars">,
- HelpText<"Warn about private ivars that are never used">,
- DescFile<"ObjCUnusedIVarsChecker.cpp">;
+ HelpText<"Warn about private ivars that are never used">;
def ObjCSelfInitChecker : Checker<"SelfInit">,
- HelpText<"Check that 'self' is properly initialized inside an initializer method">,
- DescFile<"ObjCSelfInitChecker.cpp">;
+ HelpText<"Check that 'self' is properly initialized inside an initializer "
+ "method">;
def ObjCLoopChecker : Checker<"Loops">,
- HelpText<"Improved modeling of loops using Cocoa collection types">,
- DescFile<"BasicObjCFoundationChecks.cpp">;
+ HelpText<"Improved modeling of loops using Cocoa collection types">;
def ObjCNonNilReturnValueChecker : Checker<"NonNilReturnValue">,
- HelpText<"Model the APIs that are guaranteed to return a non-nil value">,
- DescFile<"BasicObjCFoundationChecks.cpp">;
+ HelpText<"Model the APIs that are guaranteed to return a non-nil value">;
def ObjCSuperCallChecker : Checker<"MissingSuperCall">,
- HelpText<"Warn about Objective-C methods that lack a necessary call to super">,
- DescFile<"ObjCMissingSuperCallChecker.cpp">;
+ HelpText<"Warn about Objective-C methods that lack a necessary call to "
+ "super">;
def NSErrorChecker : Checker<"NSError">,
- HelpText<"Check usage of NSError** parameters">,
- DescFile<"NSErrorChecker.cpp">;
+ HelpText<"Check usage of NSError** parameters">;
def RetainCountChecker : Checker<"RetainCount">,
- HelpText<"Check for leaks and improper reference count management">,
- DescFile<"RetainCountChecker.cpp">;
+ HelpText<"Check for leaks and improper reference count management">;
def ObjCGenericsChecker : Checker<"ObjCGenerics">,
- HelpText<"Check for type errors when using Objective-C generics">,
- DescFile<"DynamicTypePropagation.cpp">;
+ HelpText<"Check for type errors when using Objective-C generics">;
def ObjCDeallocChecker : Checker<"Dealloc">,
- HelpText<"Warn about Objective-C classes that lack a correct implementation of -dealloc">,
- DescFile<"CheckObjCDealloc.cpp">;
+ HelpText<"Warn about Objective-C classes that lack a correct implementation "
+ "of -dealloc">;
def ObjCSuperDeallocChecker : Checker<"SuperDealloc">,
- HelpText<"Warn about improper use of '[super dealloc]' in Objective-C">,
- DescFile<"ObjCSuperDeallocChecker.cpp">;
+ HelpText<"Warn about improper use of '[super dealloc]' in Objective-C">;
def AutoreleaseWriteChecker : Checker<"AutoreleaseWrite">,
- HelpText<"Warn about potentially crashing writes to autoreleasing objects from different autoreleasing pools in Objective-C">,
- DescFile<"ObjCAutoreleaseWriteChecker.cpp">;
+ HelpText<"Warn about potentially crashing writes to autoreleasing objects "
+ "from different autoreleasing pools in Objective-C">;
+
} // end "osx.cocoa"
let ParentPackage = Performance in {
def GCDAntipattern : Checker<"GCDAntipattern">,
- HelpText<"Check for performance anti-patterns when using Grand Central Dispatch">,
- DescFile<"GCDAntipatternChecker.cpp">;
+ HelpText<"Check for performance anti-patterns when using Grand Central "
+ "Dispatch">;
} // end "optin.performance"
let ParentPackage = CocoaAlpha in {
def InstanceVariableInvalidation : Checker<"InstanceVariableInvalidation">,
- HelpText<"Check that the invalidatable instance variables are invalidated in the methods annotated with objc_instance_variable_invalidator">,
- DescFile<"IvarInvalidationChecker.cpp">;
+ HelpText<"Check that the invalidatable instance variables are invalidated in "
+ "the methods annotated with objc_instance_variable_invalidator">;
def MissingInvalidationMethod : Checker<"MissingInvalidationMethod">,
- HelpText<"Check that the invalidation methods are present in classes that contain invalidatable instance variables">,
- DescFile<"IvarInvalidationChecker.cpp">;
+ HelpText<"Check that the invalidation methods are present in classes that "
+ "contain invalidatable instance variables">;
def DirectIvarAssignment : Checker<"DirectIvarAssignment">,
- HelpText<"Check for direct assignments to instance variables">,
- DescFile<"DirectIvarAssignment.cpp">;
+ HelpText<"Check for direct assignments to instance variables">;
-def DirectIvarAssignmentForAnnotatedFunctions : Checker<"DirectIvarAssignmentForAnnotatedFunctions">,
- HelpText<"Check for direct assignments to instance variables in the methods annotated with objc_no_direct_instance_variable_assignment">,
- DescFile<"DirectIvarAssignment.cpp">;
+def DirectIvarAssignmentForAnnotatedFunctions :
+ Checker<"DirectIvarAssignmentForAnnotatedFunctions">,
+ HelpText<"Check for direct assignments to instance variables in the methods "
+ "annotated with objc_no_direct_instance_variable_assignment">;
} // end "alpha.osx.cocoa"
let ParentPackage = CoreFoundation in {
def CFNumberChecker : Checker<"CFNumber">,
- HelpText<"Check for proper uses of CFNumber APIs">,
- DescFile<"BasicObjCFoundationChecks.cpp">;
+ HelpText<"Check for proper uses of CFNumber APIs">;
def CFRetainReleaseChecker : Checker<"CFRetainRelease">,
- HelpText<"Check for null arguments to CFRetain/CFRelease/CFMakeCollectable">,
- DescFile<"BasicObjCFoundationChecks.cpp">;
+ HelpText<"Check for null arguments to CFRetain/CFRelease/CFMakeCollectable">;
def CFErrorChecker : Checker<"CFError">,
- HelpText<"Check usage of CFErrorRef* parameters">,
- DescFile<"NSErrorChecker.cpp">;
-}
+ HelpText<"Check usage of CFErrorRef* parameters">;
+
+} // end "osx.coreFoundation"
let ParentPackage = Containers in {
+
def ObjCContainersASTChecker : Checker<"PointerSizedValues">,
- HelpText<"Warns if 'CFArray', 'CFDictionary', 'CFSet' are created with non-pointer-size values">,
- DescFile<"ObjCContainersASTChecker.cpp">;
+ HelpText<"Warns if 'CFArray', 'CFDictionary', 'CFSet' are created with "
+ "non-pointer-size values">;
def ObjCContainersChecker : Checker<"OutOfBounds">,
- HelpText<"Checks for index out-of-bounds when using 'CFArray' API">,
- DescFile<"ObjCContainersChecker.cpp">;
+ HelpText<"Checks for index out-of-bounds when using 'CFArray' API">;
-}
+} // end "osx.coreFoundation.containers"
let ParentPackage = LocalizabilityOptIn in {
+
def NonLocalizedStringChecker : Checker<"NonLocalizedStringChecker">,
- HelpText<"Warns about uses of non-localized NSStrings passed to UI methods expecting localized NSStrings">,
- DescFile<"LocalizationChecker.cpp">;
+ HelpText<"Warns about uses of non-localized NSStrings passed to UI methods "
+ "expecting localized NSStrings">;
-def EmptyLocalizationContextChecker : Checker<"EmptyLocalizationContextChecker">,
- HelpText<"Check that NSLocalizedString macros include a comment for context">,
- DescFile<"LocalizationChecker.cpp">;
-}
+def EmptyLocalizationContextChecker :
+ Checker<"EmptyLocalizationContextChecker">,
+ HelpText<"Check that NSLocalizedString macros include a comment for context">;
+
+} // end "optin.osx.cocoa.localizability"
let ParentPackage = LocalizabilityAlpha in {
+
def PluralMisuseChecker : Checker<"PluralMisuseChecker">,
- HelpText<"Warns against using one vs. many plural pattern in code when generating localized strings.">,
- DescFile<"LocalizationChecker.cpp">;
-}
+ HelpText<"Warns against using one vs. many plural pattern in code when "
+ "generating localized strings.">;
+
+} // end "alpha.osx.cocoa.localizability"
let ParentPackage = MPI in {
- def MPIChecker : Checker<"MPI-Checker">,
- HelpText<"Checks MPI code">,
- DescFile<"MPIChecker.cpp">;
-}
+
+def MPIChecker : Checker<"MPI-Checker">,
+ HelpText<"Checks MPI code">;
+
+} // end "optin.mpi"
//===----------------------------------------------------------------------===//
// Checkers for LLVM development.
//===----------------------------------------------------------------------===//
-def LLVMConventionsChecker : Checker<"Conventions">,
- InPackage<LLVM>,
- HelpText<"Check code for LLVM codebase conventions">,
- DescFile<"LLVMConventionsChecker.cpp">;
+let ParentPackage = LLVMAlpha in {
+def LLVMConventionsChecker : Checker<"Conventions">,
+ HelpText<"Check code for LLVM codebase conventions">;
+} // end "llvm"
//===----------------------------------------------------------------------===//
// Checkers modeling Google APIs.
//===----------------------------------------------------------------------===//
+let ParentPackage = GoogleAPIModeling in {
+
def GTestChecker : Checker<"GTest">,
- InPackage<GoogleAPIModeling>,
- HelpText<"Model gtest assertion APIs">,
- DescFile<"GTestChecker.cpp">;
+ HelpText<"Model gtest assertion APIs">;
+
+} // end "apiModeling.google"
//===----------------------------------------------------------------------===//
// Debugging checkers (for analyzer development).
@@ -752,60 +699,46 @@ def GTestChecker : Checker<"GTest">,
let ParentPackage = Debug in {
def AnalysisOrderChecker : Checker<"AnalysisOrder">,
- HelpText<"Print callbacks that are called during analysis in order">,
- DescFile<"AnalysisOrder.cpp">;
+ HelpText<"Print callbacks that are called during analysis in order">;
def DominatorsTreeDumper : Checker<"DumpDominators">,
- HelpText<"Print the dominance tree for a given CFG">,
- DescFile<"DebugCheckers.cpp">;
+ HelpText<"Print the dominance tree for a given CFG">;
def LiveVariablesDumper : Checker<"DumpLiveVars">,
- HelpText<"Print results of live variable analysis">,
- DescFile<"DebugCheckers.cpp">;
+ HelpText<"Print results of live variable analysis">;
def CFGViewer : Checker<"ViewCFG">,
- HelpText<"View Control-Flow Graphs using GraphViz">,
- DescFile<"DebugCheckers.cpp">;
+ HelpText<"View Control-Flow Graphs using GraphViz">;
def CFGDumper : Checker<"DumpCFG">,
- HelpText<"Display Control-Flow Graphs">,
- DescFile<"DebugCheckers.cpp">;
+ HelpText<"Display Control-Flow Graphs">;
def CallGraphViewer : Checker<"ViewCallGraph">,
- HelpText<"View Call Graph using GraphViz">,
- DescFile<"DebugCheckers.cpp">;
+ HelpText<"View Call Graph using GraphViz">;
def CallGraphDumper : Checker<"DumpCallGraph">,
- HelpText<"Display Call Graph">,
- DescFile<"DebugCheckers.cpp">;
+ HelpText<"Display Call Graph">;
def ConfigDumper : Checker<"ConfigDumper">,
- HelpText<"Dump config table">,
- DescFile<"DebugCheckers.cpp">;
+ HelpText<"Dump config table">;
def TraversalDumper : Checker<"DumpTraversal">,
- HelpText<"Print branch conditions as they are traversed by the engine">,
- DescFile<"TraversalChecker.cpp">;
+ HelpText<"Print branch conditions as they are traversed by the engine">;
def CallDumper : Checker<"DumpCalls">,
- HelpText<"Print calls as they are traversed by the engine">,
- DescFile<"TraversalChecker.cpp">;
+ HelpText<"Print calls as they are traversed by the engine">;
def AnalyzerStatsChecker : Checker<"Stats">,
- HelpText<"Emit warnings with analyzer statistics">,
- DescFile<"AnalyzerStatsChecker.cpp">;
+ HelpText<"Emit warnings with analyzer statistics">;
def TaintTesterChecker : Checker<"TaintTest">,
- HelpText<"Mark tainted symbols as such.">,
- DescFile<"TaintTesterChecker.cpp">;
+ HelpText<"Mark tainted symbols as such.">;
def ExprInspectionChecker : Checker<"ExprInspection">,
- HelpText<"Check the analyzer's understanding of expressions">,
- DescFile<"ExprInspectionChecker.cpp">;
+ HelpText<"Check the analyzer's understanding of expressions">;
def ExplodedGraphViewer : Checker<"ViewExplodedGraph">,
- HelpText<"View Exploded Graphs using GraphViz">,
- DescFile<"DebugCheckers.cpp">;
+ HelpText<"View Exploded Graphs using GraphViz">;
} // end "debug"
@@ -817,8 +750,7 @@ def ExplodedGraphViewer : Checker<"ViewExplodedGraph">,
let ParentPackage = CloneDetectionAlpha in {
def CloneChecker : Checker<"CloneChecker">,
- HelpText<"Reports similar pieces of code.">,
- DescFile<"CloneChecker.cpp">;
+ HelpText<"Reports similar pieces of code.">;
} // end "clone"
@@ -829,7 +761,6 @@ def CloneChecker : Checker<"CloneChecker">,
let ParentPackage = PortabilityOptIn in {
def UnixAPIPortabilityChecker : Checker<"UnixAPI">,
- HelpText<"Finds implementation-defined behavior in UNIX/Posix functions">,
- DescFile<"UnixAPIChecker.cpp">;
+ HelpText<"Finds implementation-defined behavior in UNIX/Posix functions">;
} // end optin.portability
diff --git a/include/clang/StaticAnalyzer/Core/Analyses.def b/include/clang/StaticAnalyzer/Core/Analyses.def
index 281a2ac3a6..99e26c75e1 100644
--- a/include/clang/StaticAnalyzer/Core/Analyses.def
+++ b/include/clang/StaticAnalyzer/Core/Analyses.def
@@ -33,6 +33,7 @@ ANALYSIS_DIAGNOSTICS(HTML_SINGLE_FILE, "html-single-file", "Output analysis resu
ANALYSIS_DIAGNOSTICS(PLIST, "plist", "Output analysis results using Plists", createPlistDiagnosticConsumer)
ANALYSIS_DIAGNOSTICS(PLIST_MULTI_FILE, "plist-multi-file", "Output analysis results using Plists (allowing for multi-file bugs)", createPlistMultiFileDiagnosticConsumer)
ANALYSIS_DIAGNOSTICS(PLIST_HTML, "plist-html", "Output analysis results using HTML wrapped with Plists", createPlistHTMLDiagnosticConsumer)
+ANALYSIS_DIAGNOSTICS(SARIF, "sarif", "Output analysis results in a SARIF file", createSarifDiagnosticConsumer)
ANALYSIS_DIAGNOSTICS(TEXT, "text", "Text output of analysis results", createTextPathDiagnosticConsumer)
#ifndef ANALYSIS_PURGE
diff --git a/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def b/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def
new file mode 100644
index 0000000000..8e5d8d3ad3
--- /dev/null
+++ b/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def
@@ -0,0 +1,377 @@
+//===-- AnalyzerOptions.def - Metadata about Static Analyses ----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the analyzer options avaible with -analyzer-config.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ADT_STRINGREF_H
+#error This .def file is expected to be included in translation units where \
+"llvm/ADT/StringRef.h" is already included!
+#endif
+
+#ifdef ANALYZER_OPTION
+#ifndef ANALYZER_OPTION_DEPENDS_ON_USER_MODE
+#error If you didnt include this file with the intent of generating methods, \
+define both 'ANALYZER_OPTION' and 'ANALYZER_OPTION_DEPENDS_ON_USER_MODE' macros!
+#endif
+#endif
+
+#ifndef ANALYZER_OPTION_DEPENDS_ON_USER_MODE
+#ifdef ANALYZER_OPTION
+#error If you didnt include this file with the intent of generating methods, \
+define both 'ANALYZER_OPTION' and 'ANALYZER_OPTION_DEPENDS_ON_USER_MODE' macros!
+#endif
+#endif
+
+#ifndef ANALYZER_OPTION
+/// Create a new analyzer option, but dont generate a method for it in
+/// AnalyzerOptions.
+///
+/// TYPE - The type of the option object that will be stored in
+/// AnalyzerOptions. This file is expected to be icluded in translation
+/// units where AnalyzerOptions.h is included, so types from that
+/// header should be used.
+/// NAME - The name of the option object.
+/// CMDFLAG - The command line flag for the option.
+/// (-analyzer-config CMDFLAG=VALUE)
+/// DESC - Description of the flag.
+/// DEFAULT_VAL - The default value for CMDFLAG.
+#define ANALYZER_OPTION(TYPE, NAME, CMDFLAG, DESC, DEFAULT_VAL)
+#endif
+
+#ifndef ANALYZER_OPTION_DEPENDS_ON_USER_MODE
+/// Create a new analyzer option, but dont generate a method for it in
+/// AnalyzerOptions. It's value depends on the option "user-mode".
+///
+/// TYPE - The type of the option object that will be stored in
+/// AnalyzerOptions. This file is expected to be icluded in translation
+/// units where AnalyzerOptions.h is included, so types from that
+/// header should be used.
+/// NAME - The name of the option object.
+/// CMDFLAG - The command line flag for the option.
+/// (-analyzer-config CMDFLAG=VALUE)
+/// DESC - Description of the flag.
+/// SHALLOW_VAL - The default value for CMDFLAG, when "user-mode" was set to
+/// "shallow".
+/// DEEP_VAL - The default value for CMDFLAG, when "user-mode" was set to
+/// "deep".
+#define ANALYZER_OPTION_DEPENDS_ON_USER_MODE(TYPE, NAME, CMDFLAG, DESC, \
+ SHALLOW_VAL, DEEP_VAL)
+#endif
+
+//===----------------------------------------------------------------------===//
+// The "mode" option. Since some options depend on this, we list it on top of
+// this file in order to make sure that the generated field for it is
+// initialized before the rest.
+//===----------------------------------------------------------------------===//
+
+ANALYZER_OPTION(
+ StringRef, UserMode, "mode",
+ "(string) Controls the high-level analyzer mode, which influences the "
+ "default settings for some of the lower-level config options (such as "
+ "IPAMode). Value: \"deep\", \"shallow\".",
+ "deep")
+
+//===----------------------------------------------------------------------===//
+// Boolean analyzer options.
+//===----------------------------------------------------------------------===//
+
+ANALYZER_OPTION(bool, ShouldIncludeImplicitDtorsInCFG, "cfg-implicit-dtors",
+ "Whether or not implicit destructors for C++ objects "
+ "should be included in the CFG.",
+ true)
+
+ANALYZER_OPTION(bool, ShouldIncludeTemporaryDtorsInCFG, "cfg-temporary-dtors",
+ "Whether or not the destructors for C++ temporary "
+ "objects should be included in the CFG.",
+ true)
+
+ANALYZER_OPTION(
+ bool, ShouldIncludeLifetimeInCFG, "cfg-lifetime",
+ "Whether or not end-of-lifetime information should be included in the CFG.",
+ false)
+
+ANALYZER_OPTION(bool, ShouldIncludeLoopExitInCFG, "cfg-loopexit",
+ "Whether or not the end of the loop information should "
+ "be included in the CFG.",
+ false)
+
+ANALYZER_OPTION(bool, ShouldIncludeRichConstructorsInCFG,
+ "cfg-rich-constructors",
+ "Whether or not construction site information should be "
+ "included in the CFG C++ constructor elements.",
+ true)
+
+ANALYZER_OPTION(
+ bool, ShouldIncludeScopesInCFG, "cfg-scopes",
+ "Whether or not scope information should be included in the CFG.", false)
+
+ANALYZER_OPTION(
+ bool, MayInlineTemplateFunctions, "c++-template-inlining",
+ "Whether or not templated functions may be considered for inlining.", true)
+
+ANALYZER_OPTION(bool, MayInlineCXXStandardLibrary, "c++-stdlib-inlining",
+ "Whether or not C++ standard library functions may be "
+ "considered for inlining.",
+ true)
+
+ANALYZER_OPTION(bool, MayInlineCXXAllocator, "c++-allocator-inlining",
+ "Whether or not allocator call may be considered for inlining.",
+ true)
+
+ANALYZER_OPTION(
+ bool, MayInlineCXXSharedPtrDtor, "c++-shared_ptr-inlining",
+ "Whether or not the destructor of C++ 'shared_ptr' may be considered for "
+ "inlining. This covers std::shared_ptr, std::tr1::shared_ptr, and "
+ "boost::shared_ptr, and indeed any destructor named '~shared_ptr'.",
+ false)
+
+ANALYZER_OPTION(bool, MayInlineCXXTemporaryDtors, "c++-temp-dtor-inlining",
+ "Whether C++ temporary destructors should be inlined "
+ "during analysis. If temporary destructors are disabled "
+ "in the CFG via the 'cfg-temporary-dtors' option, "
+ "temporary destructors would not be inlined anyway.",
+ true)
+
+ANALYZER_OPTION(
+ bool, ShouldSuppressNullReturnPaths, "suppress-null-return-paths",
+ "Whether or not paths that go through null returns should be suppressed. "
+ "This is a heuristic for avoiding bug reports with paths that go through "
+ "inlined functions that are more defensive than their callers.",
+ true)
+
+ANALYZER_OPTION(
+ bool, ShouldAvoidSuppressingNullArgumentPaths,
+ "avoid-suppressing-null-argument-paths",
+ "Whether a bug report should not be suppressed if its path includes a call "
+ "with a null argument, even if that call has a null return. This option "
+ "has no effect when ShouldSuppressNullReturnPaths is false. This is a "
+ "counter-heuristic to avoid false negatives.",
+ false)
+
+ANALYZER_OPTION(bool, ShouldSuppressInlinedDefensiveChecks,
+ "suppress-inlined-defensive-checks",
+ "Whether or not diagnostics containing inlined "
+ "defensive NULL checks should be suppressed.",
+ true)
+
+ANALYZER_OPTION(bool, MayInlineCXXContainerMethods, "c++-container-inlining",
+ "Whether or not methods of C++ container objects may be "
+ "considered for inlining.",
+ false)
+
+ANALYZER_OPTION(bool, ShouldSuppressFromCXXStandardLibrary,
+ "suppress-c++-stdlib",
+ "Whether or not diagnostics reported within the C++ "
+ "standard library should be suppressed.",
+ true)
+
+ANALYZER_OPTION(bool, ShouldCrosscheckWithZ3, "crosscheck-with-z3",
+ "Whether bug reports should be crosschecked with the Z3 "
+ "constraint manager backend.",
+ false)
+
+ANALYZER_OPTION(bool, ShouldReportIssuesInMainSourceFile,
+ "report-in-main-source-file",
+ "Whether or not the diagnostic report should be always "
+ "reported in the main source file and not the headers.",
+ false)
+
+ANALYZER_OPTION(bool, ShouldWriteStableReportFilename, "stable-report-filename",
+ "Whether or not the report filename should be random or not.",
+ false)
+
+ANALYZER_OPTION(
+ bool, ShouldSerializeStats, "serialize-stats",
+ "Whether the analyzer should serialize statistics to plist output. "
+ "Statistics would be serialized in JSON format inside the main dictionary "
+ "under the statistics key. Available only if compiled in assert mode or "
+ "with LLVM statistics explicitly enabled.",
+ false)
+
+ANALYZER_OPTION(bool, MayInlineObjCMethod, "objc-inlining",
+ "Whether ObjectiveC inlining is enabled, false otherwise.",
+ true)
+
+ANALYZER_OPTION(bool, ShouldPrunePaths, "prune-paths",
+ "Whether irrelevant parts of a bug report path should "
+ "be pruned out of the final output.",
+ true)
+
+ANALYZER_OPTION(
+ bool, ShouldConditionalizeStaticInitializers,
+ "cfg-conditional-static-initializers",
+ "Whether 'static' initializers should be in conditional logic in the CFG.",
+ true)
+
+ANALYZER_OPTION(bool, ShouldSynthesizeBodies, "faux-bodies",
+ "Whether the analyzer engine should synthesize fake "
+ "bodies for well-known functions.",
+ true)
+
+ANALYZER_OPTION(
+ bool, ShouldElideConstructors, "elide-constructors",
+ "Whether elidable C++ copy-constructors and move-constructors should be "
+ "actually elided during analysis. Both behaviors are allowed by the C++ "
+ "standard, and the analyzer, like CodeGen, defaults to eliding. Starting "
+ "with C++17 some elisions become mandatory, and in these cases the option "
+ "will be ignored.",
+ true)
+
+ANALYZER_OPTION(
+ bool, ShouldInlineLambdas, "inline-lambdas",
+ "Whether lambdas should be inlined. Otherwise a sink node will be "
+ "generated each time a LambdaExpr is visited.",
+ true)
+
+ANALYZER_OPTION(bool, ShouldWidenLoops, "widen-loops",
+ "Whether the analysis should try to widen loops.", false)
+
+ANALYZER_OPTION(
+ bool, ShouldUnrollLoops, "unroll-loops",
+ "Whether the analysis should try to unroll loops with known bounds.", false)
+
+ANALYZER_OPTION(
+ bool, ShouldDisplayNotesAsEvents, "notes-as-events",
+ "Whether the bug reporter should transparently treat extra note diagnostic "
+ "pieces as event diagnostic pieces. Useful when the diagnostic consumer "
+ "doesn't support the extra note pieces.",
+ false)
+
+ANALYZER_OPTION(
+ bool, ShouldAggressivelySimplifyBinaryOperation,
+ "aggressive-binary-operation-simplification",
+ "Whether SValBuilder should rearrange comparisons and additive operations "
+ "of symbolic expressions which consist of a sum of a symbol and a concrete "
+ "integer into the format where symbols are on the left-hand side and the "
+ "integer is on the right. This is only done if both symbols and both "
+ "concrete integers are signed, greater than or equal to the quarter of the "
+ "minimum value of the type and less than or equal to the quarter of the "
+ "maximum value of that type. A + n <OP> B + m becomes A - B <OP> m - n, "
+ "where A and B symbolic, n and m are integers. <OP> is any of '==', '!=', "
+ "'<', '<=', '>', '>=', '+' or '-'. The rearrangement also happens with '-' "
+ "instead of '+' on either or both side and also if any or both integers "
+ "are missing.",
+ false)
+
+ANALYZER_OPTION(
+ bool, ShouldEagerlyAssume, "eagerly-assume",
+ "Whether we should eagerly assume evaluations of conditionals, thus, "
+ "bifurcating the path. This indicates how the engine should handle "
+ "expressions such as: 'x = (y != 0)'. When this is true then the "
+ "subexpression 'y != 0' will be eagerly assumed to be true or false, thus "
+ "evaluating it to the integers 0 or 1 respectively. The upside is that "
+ "this can increase analysis precision until we have a better way to lazily "
+ "evaluate such logic. The downside is that it eagerly bifurcates paths.",
+ true)
+
+ANALYZER_OPTION(
+ bool, IsNaiveCTUEnabled, "experimental-enable-naive-ctu-analysis",
+ "Whether naive cross translation unit analysis is enabled. This is an "
+ "experimental feature to inline functions from another translation units.",
+ false)
+
+ANALYZER_OPTION(bool, ShouldDisplayMacroExpansions, "expand-macros",
+ "Whether macros related to the bugpath should be "
+ "expanded and included in the plist output.",
+ false)
+
+ANALYZER_OPTION(bool, DisplayCTUProgress, "display-ctu-progress",
+ "Whether to emit verbose output about "
+ "the analyzer's progress related to ctu.",
+ false)
+
+//===----------------------------------------------------------------------===//
+// Unsinged analyzer options.
+//===----------------------------------------------------------------------===//
+
+ANALYZER_OPTION(
+ unsigned, AlwaysInlineSize, "ipa-always-inline-size",
+ "The size of the functions (in basic blocks), which should be considered "
+ "to be small enough to always inline.",
+ 3)
+
+ANALYZER_OPTION(
+ unsigned, GraphTrimInterval, "graph-trim-interval",
+ "How often nodes in the ExplodedGraph should be recycled to save memory. "
+ "To disable node reclamation, set the option to 0.",
+ 1000)
+
+ANALYZER_OPTION(
+ unsigned, MinCFGSizeTreatFunctionsAsLarge,
+ "min-cfg-size-treat-functions-as-large",
+ "The number of basic blocks a function needs to have to be considered "
+ "large for the 'max-times-inline-large' config option.",
+ 14)
+
+ANALYZER_OPTION(unsigned, MaxSymbolComplexity, "max-symbol-complexity",
+ "The maximum complexity of symbolic constraint.", 35)
+
+ANALYZER_OPTION(unsigned, MaxTimesInlineLarge, "max-times-inline-large",
+ "The maximum times a large function could be inlined.", 32)
+
+ANALYZER_OPTION_DEPENDS_ON_USER_MODE(
+ unsigned, MaxInlinableSize, "max-inlinable-size",
+ "The bound on the number of basic blocks in an inlined function.",
+ /* SHALLOW_VAL */ 4, /* DEEP_VAL */ 100)
+
+ANALYZER_OPTION_DEPENDS_ON_USER_MODE(
+ unsigned, MaxNodesPerTopLevelFunction, "max-nodes",
+ "The maximum number of nodes the analyzer can generate while exploring a "
+ "top level function (for each exploded graph). 0 means no limit.",
+ /* SHALLOW_VAL */ 75000, /* DEEP_VAL */ 225000)
+
+ANALYZER_OPTION(
+ unsigned, RegionStoreSmallStructLimit, "region-store-small-struct-limit",
+ "The largest number of fields a struct can have and still be considered "
+ "small This is currently used to decide whether or not it is worth forcing "
+ "a LazyCompoundVal on bind. To disable all small-struct-dependent "
+ "behavior, set the option to 0.",
+ 2)
+
+//===----------------------------------------------------------------------===//
+// String analyzer options.
+//===----------------------------------------------------------------------===//
+
+ANALYZER_OPTION(StringRef, CTUDir, "ctu-dir",
+ "The directory containing the CTU related files.", "")
+
+ANALYZER_OPTION(StringRef, CTUIndexName, "ctu-index-name",
+ "the name of the file containing the CTU index of functions.",
+ "externalFnMap.txt")
+
+ANALYZER_OPTION(
+ StringRef, ModelPath, "model-path",
+ "The analyzer can inline an alternative implementation written in C at the "
+ "call site if the called function's body is not available. This is a path "
+ "where to look for those alternative implementations (called models).",
+ "")
+
+ANALYZER_OPTION(
+ StringRef, CXXMemberInliningMode, "c++-inlining",
+ "Controls which C++ member functions will be considered for inlining. "
+ "Value: \"constructors\", \"destructors\", \"methods\".",
+ "destructors")
+
+ANALYZER_OPTION_DEPENDS_ON_USER_MODE(
+ StringRef, IPAMode, "ipa",
+ "Controls the mode of inter-procedural analysis. Value: \"none\", "
+ "\"basic-inlining\", \"inlining\", \"dynamic\", \"dynamic-bifurcate\".",
+ /* SHALLOW_VAL */ "inlining", /* DEEP_VAL */ "dynamic-bifurcate")
+
+ANALYZER_OPTION(
+ StringRef, ExplorationStrategy, "exploration_strategy",
+ "Value: \"dfs\", \"bfs\", \"unexplored_first\", "
+ "\"unexplored_first_queue\", \"unexplored_first_location_queue\", "
+ "\"bfs_block_dfs_contents\".",
+ "unexplored_first_queue")
+
+#undef ANALYZER_OPTION_DEPENDS_ON_USER_MODE
+#undef ANALYZER_OPTION
diff --git a/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h b/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h
index 715cc2bf23..7745e459e1 100644
--- a/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h
+++ b/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h
@@ -20,6 +20,7 @@
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSwitch.h"
#include <string>
#include <utility>
#include <vector>
@@ -85,7 +86,7 @@ enum CXXInlineableMemberKind {
// Uninitialized = 0,
/// A dummy mode in which no C++ inlining is enabled.
- CIMK_None = 1,
+ CIMK_None,
/// Refers to regular member function and operator calls.
CIMK_MemberFunctions,
@@ -102,8 +103,6 @@ enum CXXInlineableMemberKind {
/// Describes the different modes of inter-procedural analysis.
enum IPAKind {
- IPAK_NotSet = 0,
-
/// Perform only intra-procedural analysis.
IPAK_None = 1,
@@ -121,6 +120,46 @@ enum IPAKind {
IPAK_DynamicDispatchBifurcate = 5
};
+enum class ExplorationStrategyKind {
+ DFS,
+ BFS,
+ UnexploredFirst,
+ UnexploredFirstQueue,
+ UnexploredFirstLocationQueue,
+ BFSBlockDFSContents,
+};
+
+/// Describes the kinds for high-level analyzer mode.
+enum UserModeKind {
+ /// Perform shallow but fast analyzes.
+ UMK_Shallow = 1,
+
+ /// Perform deep analyzes.
+ UMK_Deep = 2
+};
+
+/// Stores options for the analyzer from the command line.
+///
+/// Some options are frontend flags (e.g.: -analyzer-output), but some are
+/// analyzer configuration options, which are preceded by -analyzer-config
+/// (e.g.: -analyzer-config notes-as-events=true).
+///
+/// If you'd like to add a new frontend flag, add it to
+/// include/clang/Driver/CC1Options.td, add a new field to store the value of
+/// that flag in this class, and initialize it in
+/// lib/Frontend/CompilerInvocation.cpp.
+///
+/// If you'd like to add a new non-checker configuration, register it in
+/// include/clang/StaticAnalyzer/Core/AnalyzerOptions.def, and refer to the
+/// top of the file for documentation.
+///
+/// If you'd like to add a new checker option, call getChecker*Option()
+/// whenever.
+///
+/// Some of the options are controlled by raw frontend flags for no good reason,
+/// and should be eventually converted into -analyzer-config flags. New analyzer
+/// options should not be implemented as frontend flags. Frontend flags still
+/// make sense for things that do not affect the actual analysis.
class AnalyzerOptions : public RefCountedBase<AnalyzerOptions> {
public:
using ConfigTable = llvm::StringMap<std::string>;
@@ -132,6 +171,7 @@ public:
std::vector<std::pair<std::string, bool>> CheckersControlList;
/// A key-value table of use-specified configuration values.
+ // TODO: This shouldn't be public.
ConfigTable Config;
AnalysisStores AnalysisStoreOpt = RegionStoreModel;
AnalysisConstraints AnalysisConstraintsOpt = RangeConstraintsModel;
@@ -159,6 +199,8 @@ public:
unsigned ShowCheckerHelp : 1;
unsigned ShowEnabledCheckerList : 1;
+ unsigned ShowConfigOptionsList : 1;
+ unsigned ShouldEmitErrorsOnInvalidConfigValue : 1;
unsigned AnalyzeAll : 1;
unsigned AnalyzerDisplayProgress : 1;
unsigned AnalyzeNestedBlocks : 1;
@@ -181,190 +223,51 @@ public:
/// The mode of function selection used during inlining.
AnalysisInliningMode InliningMode = NoRedundancy;
- enum class ExplorationStrategyKind {
- DFS,
- BFS,
- UnexploredFirst,
- UnexploredFirstQueue,
- BFSBlockDFSContents,
- NotSet
- };
-
-private:
- ExplorationStrategyKind ExplorationStrategy = ExplorationStrategyKind::NotSet;
-
- /// Describes the kinds for high-level analyzer mode.
- enum UserModeKind {
- UMK_NotSet = 0,
-
- /// Perform shallow but fast analyzes.
- UMK_Shallow = 1,
-
- /// Perform deep analyzes.
- UMK_Deep = 2
- };
-
- /// Controls the high-level analyzer mode, which influences the default
- /// settings for some of the lower-level config options (such as IPAMode).
- /// \sa getUserMode
- UserModeKind UserMode = UMK_NotSet;
-
- /// Controls the mode of inter-procedural analysis.
- IPAKind IPAMode = IPAK_NotSet;
-
- /// Controls which C++ member functions will be considered for inlining.
- CXXInlineableMemberKind CXXMemberInliningMode;
-
- /// \sa includeImplicitDtorsInCFG
- Optional<bool> IncludeImplicitDtorsInCFG;
-
- /// \sa includeTemporaryDtorsInCFG
- Optional<bool> IncludeTemporaryDtorsInCFG;
-
- /// \sa IncludeLifetimeInCFG
- Optional<bool> IncludeLifetimeInCFG;
-
- /// \sa IncludeLoopExitInCFG
- Optional<bool> IncludeLoopExitInCFG;
-
- /// \sa IncludeRichConstructorsInCFG
- Optional<bool> IncludeRichConstructorsInCFG;
-
- /// \sa mayInlineCXXStandardLibrary
- Optional<bool> InlineCXXStandardLibrary;
-
- /// \sa includeScopesInCFG
- Optional<bool> IncludeScopesInCFG;
-
- /// \sa mayInlineTemplateFunctions
- Optional<bool> InlineTemplateFunctions;
-
- /// \sa mayInlineCXXAllocator
- Optional<bool> InlineCXXAllocator;
-
- /// \sa mayInlineCXXContainerMethods
- Optional<bool> InlineCXXContainerMethods;
-
- /// \sa mayInlineCXXSharedPtrDtor
- Optional<bool> InlineCXXSharedPtrDtor;
-
- /// \sa mayInlineCXXTemporaryDtors
- Optional<bool> InlineCXXTemporaryDtors;
-
- /// \sa mayInlineObjCMethod
- Optional<bool> ObjCInliningMode;
-
- // Cache of the "ipa-always-inline-size" setting.
- // \sa getAlwaysInlineSize
- Optional<unsigned> AlwaysInlineSize;
+ // Create a field for each -analyzer-config option.
+#define ANALYZER_OPTION_DEPENDS_ON_USER_MODE(TYPE, NAME, CMDFLAG, DESC, \
+ SHALLOW_VAL, DEEP_VAL) \
+ ANALYZER_OPTION(TYPE, NAME, CMDFLAG, DESC, SHALLOW_VAL)
- /// \sa shouldSuppressNullReturnPaths
- Optional<bool> SuppressNullReturnPaths;
+#define ANALYZER_OPTION(TYPE, NAME, CMDFLAG, DESC, DEFAULT_VAL) \
+ TYPE NAME;
- // \sa getMaxInlinableSize
- Optional<unsigned> MaxInlinableSize;
+#include "clang/StaticAnalyzer/Core/AnalyzerOptions.def"
+#undef ANALYZER_OPTION
+#undef ANALYZER_OPTION_DEPENDS_ON_USER_MODE
- /// \sa shouldAvoidSuppressingNullArgumentPaths
- Optional<bool> AvoidSuppressingNullArgumentPaths;
+ // Create an array of all -analyzer-config command line options. Sort it in
+ // the constructor.
+ std::vector<StringRef> AnalyzerConfigCmdFlags = {
+#define ANALYZER_OPTION_DEPENDS_ON_USER_MODE(TYPE, NAME, CMDFLAG, DESC, \
+ SHALLOW_VAL, DEEP_VAL) \
+ ANALYZER_OPTION(TYPE, NAME, CMDFLAG, DESC, SHALLOW_VAL)
- /// \sa shouldSuppressInlinedDefensiveChecks
- Optional<bool> SuppressInlinedDefensiveChecks;
+#define ANALYZER_OPTION(TYPE, NAME, CMDFLAG, DESC, DEFAULT_VAL) \
+ CMDFLAG,
- /// \sa shouldSuppressFromCXXStandardLibrary
- Optional<bool> SuppressFromCXXStandardLibrary;
-
- /// \sa shouldCrosscheckWithZ3
- Optional<bool> CrosscheckWithZ3;
-
- /// \sa reportIssuesInMainSourceFile
- Optional<bool> ReportIssuesInMainSourceFile;
-
- /// \sa StableReportFilename
- Optional<bool> StableReportFilename;
-
- Optional<bool> SerializeStats;
-
- /// \sa getGraphTrimInterval
- Optional<unsigned> GraphTrimInterval;
-
- /// \sa getMaxSymbolComplexity
- Optional<unsigned> MaxSymbolComplexity;
-
- /// \sa getMaxTimesInlineLarge
- Optional<unsigned> MaxTimesInlineLarge;
-
- /// \sa getMinCFGSizeTreatFunctionsAsLarge
- Optional<unsigned> MinCFGSizeTreatFunctionsAsLarge;
-
- /// \sa getMaxNodesPerTopLevelFunction
- Optional<unsigned> MaxNodesPerTopLevelFunction;
-
- /// \sa shouldInlineLambdas
- Optional<bool> InlineLambdas;
-
- /// \sa shouldWidenLoops
- Optional<bool> WidenLoops;
-
- /// \sa shouldUnrollLoops
- Optional<bool> UnrollLoops;
-
- /// \sa shouldDisplayNotesAsEvents
- Optional<bool> DisplayNotesAsEvents;
-
- /// \sa shouldAggressivelySimplifyBinaryOperation
- Optional<bool> AggressiveBinaryOperationSimplification;
-
- /// \sa shouldEagerlyAssume
- Optional<bool> EagerlyAssumeBinOpBifurcation;
-
- /// \sa getCTUDir
- Optional<StringRef> CTUDir;
-
- /// \sa getCTUIndexName
- Optional<StringRef> CTUIndexName;
-
- /// \sa naiveCTUEnabled
- Optional<bool> NaiveCTU;
+#include "clang/StaticAnalyzer/Core/AnalyzerOptions.def"
+#undef ANALYZER_OPTION
+#undef ANALYZER_OPTION_DEPENDS_ON_USER_MODE
+ };
- /// \sa shouldElideConstructors
- Optional<bool> ElideConstructors;
+ bool isUnknownAnalyzerConfig(StringRef Name) const {
+ assert(std::is_sorted(AnalyzerConfigCmdFlags.begin(),
+ AnalyzerConfigCmdFlags.end()));
- /// A helper function that retrieves option for a given full-qualified
- /// checker name.
- /// Options for checkers can be specified via 'analyzer-config' command-line
- /// option.
- /// Example:
- /// @code-analyzer-config unix.Malloc:OptionName=CheckerOptionValue @endcode
- /// or @code-analyzer-config unix:OptionName=GroupOptionValue @endcode
- /// for groups of checkers.
- /// @param [in] CheckerName Full-qualified checker name, like
- /// alpha.unix.StreamChecker.
- /// @param [in] OptionName Name of the option to get.
- /// @param [in] Default Default value if no option is specified.
- /// @param [in] SearchInParents If set to true and the searched option was not
- /// specified for the given checker the options for the parent packages will
- /// be searched as well. The inner packages take precedence over the outer
- /// ones.
- /// @retval CheckerOptionValue An option for a checker if it was specified.
- /// @retval GroupOptionValue An option for group if it was specified and no
- /// checker-specific options were found. The closer group to checker,
- /// the more priority it has. For example, @c coregroup.subgroup has more
- /// priority than @c coregroup for @c coregroup.subgroup.CheckerName checker.
- /// @retval Default If nor checker option, nor group option was found.
- StringRef getCheckerOption(StringRef CheckerName, StringRef OptionName,
- StringRef Default,
- bool SearchInParents = false);
+ return !std::binary_search(AnalyzerConfigCmdFlags.begin(),
+ AnalyzerConfigCmdFlags.end(), Name);
+ }
-public:
AnalyzerOptions()
: DisableAllChecks(false), ShowCheckerHelp(false),
- ShowEnabledCheckerList(false), AnalyzeAll(false),
- AnalyzerDisplayProgress(false), AnalyzeNestedBlocks(false),
- eagerlyAssumeBinOpBifurcation(false), TrimGraph(false),
- visualizeExplodedGraphWithGraphViz(false),
- UnoptimizedCFG(false),
- PrintStats(false), NoRetryExhausted(false), CXXMemberInliningMode() {}
+ ShowEnabledCheckerList(false), ShowConfigOptionsList(false),
+ AnalyzeAll(false), AnalyzerDisplayProgress(false),
+ AnalyzeNestedBlocks(false), eagerlyAssumeBinOpBifurcation(false),
+ TrimGraph(false), visualizeExplodedGraphWithGraphViz(false),
+ UnoptimizedCFG(false), PrintStats(false), NoRetryExhausted(false) {
+ llvm::sort(AnalyzerConfigCmdFlags);
+ }
/// Interprets an option's string value as a boolean. The "true" string is
/// interpreted as true and the "false" string is interpreted as false.
@@ -373,34 +276,17 @@ public:
/// @param [in] Name Name for option to retrieve.
/// @param [in] DefaultVal Default value returned if no such option was
/// specified.
- /// @param [in] C The optional checker parameter that can be used to restrict
- /// the search to the options of this particular checker (and its parents
- /// depending on search mode).
+ /// @param [in] C The checker object the option belongs to. Checker options
+ /// are retrieved in the following format:
+ /// `-analyzer-config <package and checker name>:OptionName=Value.
/// @param [in] SearchInParents If set to true and the searched option was not
/// specified for the given checker the options for the parent packages will
/// be searched as well. The inner packages take precedence over the outer
/// ones.
- bool getBooleanOption(StringRef Name, bool DefaultVal,
- const ento::CheckerBase *C = nullptr,
- bool SearchInParents = false);
+ bool getCheckerBooleanOption(StringRef Name, bool DefaultVal,
+ const ento::CheckerBase *C,
+ bool SearchInParents = false) const;
- /// Variant that accepts a Optional value to cache the result.
- ///
- /// @param [in,out] V Return value storage, returned if parameter contains
- /// an existing valid option, else it is used to store a return value
- /// @param [in] Name Name for option to retrieve.
- /// @param [in] DefaultVal Default value returned if no such option was
- /// specified.
- /// @param [in] C The optional checker parameter that can be used to restrict
- /// the search to the options of this particular checker (and its parents
- /// depending on search mode).
- /// @param [in] SearchInParents If set to true and the searched option was not
- /// specified for the given checker the options for the parent packages will
- /// be searched as well. The inner packages take precedence over the outer
- /// ones.
- bool getBooleanOption(Optional<bool> &V, StringRef Name, bool DefaultVal,
- const ento::CheckerBase *C = nullptr,
- bool SearchInParents = false);
/// Interprets an option's string value as an integer value.
///
@@ -408,16 +294,16 @@ public:
/// @param [in] Name Name for option to retrieve.
/// @param [in] DefaultVal Default value returned if no such option was
/// specified.
- /// @param [in] C The optional checker parameter that can be used to restrict
- /// the search to the options of this particular checker (and its parents
- /// depending on search mode).
+ /// @param [in] C The checker object the option belongs to. Checker options
+ /// are retrieved in the following format:
+ /// `-analyzer-config <package and checker name>:OptionName=Value.
/// @param [in] SearchInParents If set to true and the searched option was not
/// specified for the given checker the options for the parent packages will
/// be searched as well. The inner packages take precedence over the outer
/// ones.
- int getOptionAsInteger(StringRef Name, int DefaultVal,
- const ento::CheckerBase *C = nullptr,
- bool SearchInParents = false);
+ int getCheckerIntegerOption(StringRef Name, int DefaultVal,
+ const ento::CheckerBase *C,
+ bool SearchInParents = false) const;
/// Query an option's string value.
///
@@ -425,26 +311,26 @@ public:
/// @param [in] Name Name for option to retrieve.
/// @param [in] DefaultVal Default value returned if no such option was
/// specified.
- /// @param [in] C The optional checker parameter that can be used to restrict
- /// the search to the options of this particular checker (and its parents
- /// depending on search mode).
+ /// @param [in] C The checker object the option belongs to. Checker options
+ /// are retrieved in the following format:
+ /// `-analyzer-config <package and checker name>:OptionName=Value.
/// @param [in] SearchInParents If set to true and the searched option was not
/// specified for the given checker the options for the parent packages will
/// be searched as well. The inner packages take precedence over the outer
/// ones.
- StringRef getOptionAsString(StringRef Name, StringRef DefaultVal,
- const ento::CheckerBase *C = nullptr,
- bool SearchInParents = false);
+ StringRef getCheckerStringOption(StringRef Name, StringRef DefaultVal,
+ const ento::CheckerBase *C,
+ bool SearchInParents = false) const;
/// Retrieves and sets the UserMode. This is a high-level option,
/// which is used to set other low-level options. It is not accessible
/// outside of AnalyzerOptions.
- UserModeKind getUserMode();
+ UserModeKind getUserMode() const;
- ExplorationStrategyKind getExplorationStrategy();
+ ExplorationStrategyKind getExplorationStrategy() const;
/// Returns the inter-procedural analysis mode.
- IPAKind getIPAMode();
+ IPAKind getIPAMode() const;
/// Returns the option controlling which C++ member functions will be
/// considered for inlining.
@@ -452,286 +338,28 @@ public:
/// This is controlled by the 'c++-inlining' config option.
///
/// \sa CXXMemberInliningMode
- bool mayInlineCXXMemberFunction(CXXInlineableMemberKind K);
-
- /// Returns true if ObjectiveC inlining is enabled, false otherwise.
- bool mayInlineObjCMethod();
-
- /// Returns whether or not the destructors for C++ temporary objects should
- /// be included in the CFG.
- ///
- /// This is controlled by the 'cfg-temporary-dtors' config option, which
- /// accepts the values "true" and "false".
- bool includeTemporaryDtorsInCFG();
-
- /// Returns whether or not implicit destructors for C++ objects should
- /// be included in the CFG.
- ///
- /// This is controlled by the 'cfg-implicit-dtors' config option, which
- /// accepts the values "true" and "false".
- bool includeImplicitDtorsInCFG();
-
- /// Returns whether or not end-of-lifetime information should be included in
- /// the CFG.
- ///
- /// This is controlled by the 'cfg-lifetime' config option, which accepts
- /// the values "true" and "false".
- bool includeLifetimeInCFG();
-
- /// Returns whether or not the end of the loop information should be included
- /// in the CFG.
- ///
- /// This is controlled by the 'cfg-loopexit' config option, which accepts
- /// the values "true" and "false".
- bool includeLoopExitInCFG();
-
- /// Returns whether or not construction site information should be included
- /// in the CFG C++ constructor elements.
- ///
- /// This is controlled by the 'cfg-rich-constructors' config options,
- /// which accepts the values "true" and "false".
- bool includeRichConstructorsInCFG();
-
- /// Returns whether or not scope information should be included in the CFG.
- ///
- /// This is controlled by the 'cfg-scope-info' config option, which accepts
- /// the values "true" and "false".
- bool includeScopesInCFG();
-
- /// Returns whether or not C++ standard library functions may be considered
- /// for inlining.
- ///
- /// This is controlled by the 'c++-stdlib-inlining' config option, which
- /// accepts the values "true" and "false".
- bool mayInlineCXXStandardLibrary();
-
- /// Returns whether or not templated functions may be considered for inlining.
- ///
- /// This is controlled by the 'c++-template-inlining' config option, which
- /// accepts the values "true" and "false".
- bool mayInlineTemplateFunctions();
-
- /// Returns whether or not allocator call may be considered for inlining.
- ///
- /// This is controlled by the 'c++-allocator-inlining' config option, which
- /// accepts the values "true" and "false".
- bool mayInlineCXXAllocator();
-
- /// Returns whether or not methods of C++ container objects may be considered
- /// for inlining.
- ///
- /// This is controlled by the 'c++-container-inlining' config option, which
- /// accepts the values "true" and "false".
- bool mayInlineCXXContainerMethods();
-
- /// Returns whether or not the destructor of C++ 'shared_ptr' may be
- /// considered for inlining.
- ///
- /// This covers std::shared_ptr, std::tr1::shared_ptr, and boost::shared_ptr,
- /// and indeed any destructor named "~shared_ptr".
- ///
- /// This is controlled by the 'c++-shared_ptr-inlining' config option, which
- /// accepts the values "true" and "false".
- bool mayInlineCXXSharedPtrDtor();
-
- /// Returns true if C++ temporary destructors should be inlined during
- /// analysis.
- ///
- /// If temporary destructors are disabled in the CFG via the
- /// 'cfg-temporary-dtors' option, temporary destructors would not be
- /// inlined anyway.
- ///
- /// This is controlled by the 'c++-temp-dtor-inlining' config option, which
- /// accepts the values "true" and "false".
- bool mayInlineCXXTemporaryDtors();
-
- /// Returns whether or not paths that go through null returns should be
- /// suppressed.
- ///
- /// This is a heuristic for avoiding bug reports with paths that go through
- /// inlined functions that are more defensive than their callers.
- ///
- /// This is controlled by the 'suppress-null-return-paths' config option,
- /// which accepts the values "true" and "false".
- bool shouldSuppressNullReturnPaths();
-
- /// Returns whether a bug report should \em not be suppressed if its path
- /// includes a call with a null argument, even if that call has a null return.
- ///
- /// This option has no effect when #shouldSuppressNullReturnPaths() is false.
- ///
- /// This is a counter-heuristic to avoid false negatives.
- ///
- /// This is controlled by the 'avoid-suppressing-null-argument-paths' config
- /// option, which accepts the values "true" and "false".
- bool shouldAvoidSuppressingNullArgumentPaths();
-
- /// Returns whether or not diagnostics containing inlined defensive NULL
- /// checks should be suppressed.
- ///
- /// This is controlled by the 'suppress-inlined-defensive-checks' config
- /// option, which accepts the values "true" and "false".
- bool shouldSuppressInlinedDefensiveChecks();
-
- /// Returns whether or not diagnostics reported within the C++ standard
- /// library should be suppressed.
- ///
- /// This is controlled by the 'suppress-c++-stdlib' config option,
- /// which accepts the values "true" and "false".
- bool shouldSuppressFromCXXStandardLibrary();
-
- /// Returns whether bug reports should be crosschecked with the Z3
- /// constraint manager backend.
- ///
- /// This is controlled by the 'crosscheck-with-z3' config option,
- /// which accepts the values "true" and "false".
- bool shouldCrosscheckWithZ3();
-
- /// Returns whether or not the diagnostic report should be always reported
- /// in the main source file and not the headers.
- ///
- /// This is controlled by the 'report-in-main-source-file' config option,
- /// which accepts the values "true" and "false".
- bool shouldReportIssuesInMainSourceFile();
-
- /// Returns whether or not the report filename should be random or not.
- ///
- /// This is controlled by the 'stable-report-filename' config option,
- /// which accepts the values "true" and "false". Default = false
- bool shouldWriteStableReportFilename();
-
- /// \return Whether the analyzer should
- /// serialize statistics to plist output.
- /// Statistics would be serialized in JSON format inside the main dictionary
- /// under the \c statistics key.
- /// Available only if compiled in assert mode or with LLVM statistics
- /// explicitly enabled.
- bool shouldSerializeStats();
-
- /// Returns whether irrelevant parts of a bug report path should be pruned
- /// out of the final output.
- ///
- /// This is controlled by the 'prune-paths' config option, which accepts the
- /// values "true" and "false".
- bool shouldPrunePaths();
-
- /// Returns true if 'static' initializers should be in conditional logic
- /// in the CFG.
- bool shouldConditionalizeStaticInitializers();
-
- // Returns the size of the functions (in basic blocks), which should be
- // considered to be small enough to always inline.
- //
- // This is controlled by "ipa-always-inline-size" analyzer-config option.
- unsigned getAlwaysInlineSize();
-
- // Returns the bound on the number of basic blocks in an inlined function
- // (50 by default).
- //
- // This is controlled by "-analyzer-config max-inlinable-size" option.
- unsigned getMaxInlinableSize();
-
- /// Returns true if the analyzer engine should synthesize fake bodies
- /// for well-known functions.
- bool shouldSynthesizeBodies();
-
- /// Returns how often nodes in the ExplodedGraph should be recycled to save
- /// memory.
- ///
- /// This is controlled by the 'graph-trim-interval' config option. To disable
- /// node reclamation, set the option to "0".
- unsigned getGraphTrimInterval();
-
- /// Returns the maximum complexity of symbolic constraint (50 by default).
- ///
- /// This is controlled by "-analyzer-config max-symbol-complexity" option.
- unsigned getMaxSymbolComplexity();
-
- /// Returns the maximum times a large function could be inlined.
- ///
- /// This is controlled by the 'max-times-inline-large' config option.
- unsigned getMaxTimesInlineLarge();
-
- /// Returns the number of basic blocks a function needs to have to be
- /// considered large for the 'max-times-inline-large' config option.
- ///
- /// This is controlled by the 'min-cfg-size-treat-functions-as-large' config
- /// option.
- unsigned getMinCFGSizeTreatFunctionsAsLarge();
-
- /// Returns the maximum number of nodes the analyzer can generate while
- /// exploring a top level function (for each exploded graph).
- /// 150000 is default; 0 means no limit.
- ///
- /// This is controlled by the 'max-nodes' config option.
- unsigned getMaxNodesPerTopLevelFunction();
-
- /// Returns true if lambdas should be inlined. Otherwise a sink node will be
- /// generated each time a LambdaExpr is visited.
- bool shouldInlineLambdas();
-
- /// Returns true if the analysis should try to widen loops.
- /// This is controlled by the 'widen-loops' config option.
- bool shouldWidenLoops();
-
- /// Returns true if the analysis should try to unroll loops with known bounds.
- /// This is controlled by the 'unroll-loops' config option.
- bool shouldUnrollLoops();
-
- /// Returns true if the bug reporter should transparently treat extra note
- /// diagnostic pieces as event diagnostic pieces. Useful when the diagnostic
- /// consumer doesn't support the extra note pieces.
- ///
- /// This is controlled by the 'extra-notes-as-events' option, which defaults
- /// to false when unset.
- bool shouldDisplayNotesAsEvents();
-
- /// Returns true if SValBuilder should rearrange comparisons and additive
- /// operations of symbolic expressions which consist of a sum of a symbol and
- /// a concrete integer into the format where symbols are on the left-hand
- /// side and the integer is on the right. This is only done if both symbols
- /// and both concrete integers are signed, greater than or equal to the
- /// quarter of the minimum value of the type and less than or equal to the
- /// quarter of the maximum value of that type.
- ///
- /// A + n <OP> B + m becomes A - B <OP> m - n, where A and B symbolic,
- /// n and m are integers. <OP> is any of '==', '!=', '<', '<=', '>', '>=',
- /// '+' or '-'. The rearrangement also happens with '-' instead of '+' on
- // either or both side and also if any or both integers are missing.
- bool shouldAggressivelySimplifyBinaryOperation();
-
- /// Returns true if we should eagerly assume evaluations of
- /// conditionals, thus, bifurcating the path.
- ///
- /// This indicates how the engine should handle expressions such as: 'x =
- /// (y != 0)'. When this is true then the subexpression 'y != 0' will be
- /// eagerly assumed to be true or false, thus evaluating it to the integers 0
- /// or 1 respectively. The upside is that this can increase analysis
- /// precision until we have a better way to lazily evaluate such logic. The
- /// downside is that it eagerly bifurcates paths.
- bool shouldEagerlyAssume();
-
- /// Returns the directory containing the CTU related files.
- StringRef getCTUDir();
-
- /// Returns the name of the file containing the CTU index of functions.
- StringRef getCTUIndexName();
-
- /// Returns true when naive cross translation unit analysis is enabled.
- /// This is an experimental feature to inline functions from another
- /// translation units.
- bool naiveCTUEnabled();
-
- /// Returns true if elidable C++ copy-constructors and move-constructors
- /// should be actually elided during analysis. Both behaviors are allowed
- /// by the C++ standard, and the analyzer, like CodeGen, defaults to eliding.
- /// Starting with C++17 some elisions become mandatory, and in these cases
- /// the option will be ignored.
- bool shouldElideConstructors();
+ bool mayInlineCXXMemberFunction(CXXInlineableMemberKind K) const;
};
using AnalyzerOptionsRef = IntrusiveRefCntPtr<AnalyzerOptions>;
+//===----------------------------------------------------------------------===//
+// We'll use AnalyzerOptions in the frontend, but we can't link the frontend
+// with clangStaticAnalyzerCore, because clangStaticAnalyzerCore depends on
+// clangFrontend.
+//
+// For this reason, implement some methods in this header file.
+//===----------------------------------------------------------------------===//
+
+inline UserModeKind AnalyzerOptions::getUserMode() const {
+ auto K = llvm::StringSwitch<llvm::Optional<UserModeKind>>(UserMode)
+ .Case("shallow", UMK_Shallow)
+ .Case("deep", UMK_Deep)
+ .Default(None);
+ assert(K.hasValue() && "User mode is invalid.");
+ return K.getValue();
+}
+
} // namespace clang
#endif // LLVM_CLANG_STATICANALYZER_CORE_ANALYZEROPTIONS_H
diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h
index ee16522c0b..c023ed5641 100644
--- a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h
+++ b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h
@@ -345,12 +345,11 @@ public:
namespace bugreporter {
-/// Attempts to add visitors to trace a null or undefined value back to its
-/// point of origin, whether it is a symbol constrained to null or an explicit
-/// assignment.
+/// Attempts to add visitors to track expression value back to its point of
+/// origin.
///
/// \param N A node "downstream" from the evaluation of the statement.
-/// \param S The statement whose value is null or undefined.
+/// \param E The expression value which we are tracking
/// \param R The bug report to which visitors should be attached.
/// \param EnableNullFPSuppression Whether we should employ false positive
/// suppression (inlined defensive checks, returned null).
@@ -358,13 +357,10 @@ namespace bugreporter {
/// \return Whether or not the function was able to add visitors for this
/// statement. Note that returning \c true does not actually imply
/// that any visitors were added.
-bool trackNullOrUndefValue(const ExplodedNode *N, const Stmt *S, BugReport &R,
- bool EnableNullFPSuppression = true);
+bool trackExpressionValue(const ExplodedNode *N, const Expr *E, BugReport &R,
+ bool EnableNullFPSuppression = true);
const Expr *getDerefExpr(const Stmt *S);
-const Stmt *GetDenomExpr(const ExplodedNode *N);
-const Stmt *GetRetValExpr(const ExplodedNode *N);
-bool isDeclRefExprToReference(const Expr *E);
} // namespace bugreporter
diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h b/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h
index 7fff42903b..e9c682d798 100644
--- a/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h
+++ b/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h
@@ -118,7 +118,7 @@ public:
/// Only runs visitors, no output generated.
None,
- /// Used for HTML and text output.
+ /// Used for HTML, SARIF, and text output.
Minimal,
/// Used for plist output, used for "arrows" generation.
diff --git a/include/clang/StaticAnalyzer/Core/Checker.h b/include/clang/StaticAnalyzer/Core/Checker.h
index 8484cfe4c9..786465cee8 100644
--- a/include/clang/StaticAnalyzer/Core/Checker.h
+++ b/include/clang/StaticAnalyzer/Core/Checker.h
@@ -558,6 +558,8 @@ struct ImplicitNullDerefEvent {
// dereference might happen later (for example pointer passed to a parameter
// that is marked with nonnull attribute.)
bool IsDirectDereference;
+
+ static int Tag;
};
/// A helper class which wraps a boolean value set to false by default.
diff --git a/include/clang/StaticAnalyzer/Core/CheckerManager.h b/include/clang/StaticAnalyzer/Core/CheckerManager.h
index 463c842ec5..538ed19f7e 100644
--- a/include/clang/StaticAnalyzer/Core/CheckerManager.h
+++ b/include/clang/StaticAnalyzer/Core/CheckerManager.h
@@ -532,19 +532,19 @@ public:
template <typename EVENT>
void _registerListenerForEvent(CheckEventFunc checkfn) {
- EventInfo &info = Events[getTag<EVENT>()];
+ EventInfo &info = Events[&EVENT::Tag];
info.Checkers.push_back(checkfn);
}
template <typename EVENT>
void _registerDispatcherForEvent() {
- EventInfo &info = Events[getTag<EVENT>()];
+ EventInfo &info = Events[&EVENT::Tag];
info.HasDispatcher = true;
}
template <typename EVENT>
void _dispatchEvent(const EVENT &event) const {
- EventsTy::const_iterator I = Events.find(getTag<EVENT>());
+ EventsTy::const_iterator I = Events.find(&EVENT::Tag);
if (I == Events.end())
return;
const EventInfo &info = I->second;
diff --git a/include/clang/StaticAnalyzer/Core/CheckerOptInfo.h b/include/clang/StaticAnalyzer/Core/CheckerOptInfo.h
deleted file mode 100644
index 2d13bf34cd..0000000000
--- a/include/clang/StaticAnalyzer/Core/CheckerOptInfo.h
+++ /dev/null
@@ -1,44 +0,0 @@
-//===--- CheckerOptInfo.h - Specifies which checkers to use -----*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_STATICANALYZER_CORE_CHECKEROPTINFO_H
-#define LLVM_CLANG_STATICANALYZER_CORE_CHECKEROPTINFO_H
-
-#include "clang/Basic/LLVM.h"
-#include "llvm/ADT/StringRef.h"
-
-namespace clang {
-namespace ento {
-
-/// Represents a request to include or exclude a checker or package from a
-/// specific analysis run.
-///
-/// \sa CheckerRegistry::initializeManager
-class CheckerOptInfo {
- StringRef Name;
- bool Enable;
- bool Claimed;
-
-public:
- CheckerOptInfo(StringRef name, bool enable)
- : Name(name), Enable(enable), Claimed(false) { }
-
- StringRef getName() const { return Name; }
- bool isEnabled() const { return Enable; }
- bool isDisabled() const { return !isEnabled(); }
-
- bool isClaimed() const { return Claimed; }
- bool isUnclaimed() const { return !isClaimed(); }
- void claim() { Claimed = true; }
-};
-
-} // end namespace ento
-} // end namespace clang
-
-#endif
diff --git a/include/clang/StaticAnalyzer/Core/CheckerRegistry.h b/include/clang/StaticAnalyzer/Core/CheckerRegistry.h
index d580dda734..740754090d 100644
--- a/include/clang/StaticAnalyzer/Core/CheckerRegistry.h
+++ b/include/clang/StaticAnalyzer/Core/CheckerRegistry.h
@@ -73,8 +73,6 @@ class DiagnosticsEngine;
namespace ento {
-class CheckerOptInfo;
-
/// Manages a set of available checkers for running a static analysis.
/// The checkers are organized into packages by full name, where including
/// a package will recursively include all subpackages and checkers within it.
@@ -123,8 +121,8 @@ public:
/// all checkers specified by the given CheckerOptInfo list. The order of this
/// list is significant; later options can be used to reverse earlier ones.
/// This can be used to exclude certain checkers in an included package.
- void initializeManager(CheckerManager &mgr,
- SmallVectorImpl<CheckerOptInfo> &opts) const;
+ void initializeManager(CheckerManager &mgr, const AnalyzerOptions &Opts,
+ DiagnosticsEngine &diags) const;
/// Check if every option corresponds to a specific checker or package.
void validateCheckerOptions(const AnalyzerOptions &opts,
@@ -133,8 +131,7 @@ public:
/// Prints the name and description of all checkers in this registry.
/// This output is not intended to be machine-parseable.
void printHelp(raw_ostream &out, size_t maxNameChars = 30) const;
- void printList(raw_ostream &out,
- SmallVectorImpl<CheckerOptInfo> &opts) const;
+ void printList(raw_ostream &out, const AnalyzerOptions &opts) const;
private:
mutable CheckerInfoList Checkers;
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h b/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
index 4c50eafbde..a53e8ee693 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
@@ -921,15 +921,30 @@ public:
return getOriginExpr()->getOperatorNew();
}
+ /// Number of non-placement arguments to the call. It is equal to 2 for
+ /// C++17 aligned operator new() calls that have alignment implicitly
+ /// passed as the second argument, and to 1 for other operator new() calls.
+ unsigned getNumImplicitArgs() const {
+ return getOriginExpr()->passAlignment() ? 2 : 1;
+ }
+
unsigned getNumArgs() const override {
- return getOriginExpr()->getNumPlacementArgs() + 1;
+ return getOriginExpr()->getNumPlacementArgs() + getNumImplicitArgs();
}
const Expr *getArgExpr(unsigned Index) const override {
// The first argument of an allocator call is the size of the allocation.
- if (Index == 0)
+ if (Index < getNumImplicitArgs())
return nullptr;
- return getOriginExpr()->getPlacementArg(Index - 1);
+ return getOriginExpr()->getPlacementArg(Index - getNumImplicitArgs());
+ }
+
+ /// Number of placement arguments to the operator new() call. For example,
+ /// standard std::nothrow operator new and standard placement new both have
+ /// 1 implicit argument (size) and 1 placement argument, while regular
+ /// operator new() has 1 implicit argument and 0 placement arguments.
+ const Expr *getPlacementArgExpr(unsigned Index) const {
+ return getOriginExpr()->getPlacementArg(Index);
}
Kind getKind() const override { return CE_CXXAllocator; }
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeMap.h b/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeMap.h
index 2f8ead0746..b0d514dc28 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeMap.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeMap.h
@@ -36,10 +36,7 @@ using DynamicTypeMapImpl =
template <>
struct ProgramStateTrait<DynamicTypeMap>
: public ProgramStatePartialTrait<DynamicTypeMapImpl> {
- static void *GDMIndex() {
- static int index = 0;
- return &index;
- }
+ static void *GDMIndex();
};
/// Get dynamic type information for a region.
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h
index cf4164dcd2..bf460df278 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h
@@ -210,10 +210,14 @@ public:
return const_cast<ExplodedNode*>(this)->getFirstPred();
}
- const ExplodedNode *getFirstSucc() const {
+ ExplodedNode *getFirstSucc() {
return succ_empty() ? nullptr : *(succ_begin());
}
+ const ExplodedNode *getFirstSucc() const {
+ return const_cast<ExplodedNode*>(this)->getFirstSucc();
+ }
+
// Iterators over successor and predecessor vertices.
using succ_iterator = ExplodedNode * const *;
using const_succ_iterator = const ExplodedNode * const *;
@@ -243,8 +247,10 @@ public:
int64_t getID(ExplodedGraph *G) const;
/// The node is trivial if it has only one successor, only one predecessor,
+ /// it's predecessor has only one successor,
/// and its program state is the same as the program state of the previous
/// node.
+ /// Trivial nodes may be skipped while printing exploded graph.
bool isTrivial() const;
private:
@@ -460,7 +466,6 @@ public:
// GraphTraits
namespace llvm {
-
template <> struct GraphTraits<clang::ento::ExplodedGraph *> {
using GraphTy = clang::ento::ExplodedGraph *;
using NodeRef = clang::ento::ExplodedNode *;
@@ -471,17 +476,19 @@ namespace llvm {
return *G->roots_begin();
}
+ static bool predecessorOfTrivial(NodeRef N) {
+ return N->succ_size() == 1 && N->getFirstSucc()->isTrivial();
+ }
+
static ChildIteratorType child_begin(NodeRef N) {
- if (N->succ_size() == 1 && (*N->succ_begin())->isTrivial()) {
+ if (predecessorOfTrivial(N))
return child_begin(*N->succ_begin());
- }
return N->succ_begin();
}
static ChildIteratorType child_end(NodeRef N) {
- if (N->succ_size() == 1 && (*N->succ_begin())->isTrivial()) {
- return child_end(*N->succ_begin());
- }
+ if (predecessorOfTrivial(N))
+ return child_end(N->getFirstSucc());
return N->succ_end();
}
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
index 91e47b37b7..86b776afb8 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
@@ -832,7 +832,7 @@ struct ReplayWithoutInlining{};
template <>
struct ProgramStateTrait<ReplayWithoutInlining> :
public ProgramStatePartialTrait<const void*> {
- static void *GDMIndex() { static int index = 0; return &index; }
+ static void *GDMIndex();
};
} // namespace ento
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h b/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
index 0b0e32b8e3..bf01289a40 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
@@ -118,6 +118,10 @@ public:
const MemRegion *getBaseRegion() const;
+ /// Recursively retrieve the region of the most derived class instance of
+ /// regions of C++ base class instances.
+ const MemRegion *getMostDerivedObjectRegion() const;
+
/// Check if the region is a subregion of the given region.
/// Each region is a subregion of itself.
virtual bool isSubRegionOf(const MemRegion *R) const;
@@ -1077,7 +1081,7 @@ public:
void dump() const;
};
-/// ElementRegin is used to represent both array elements and casts.
+/// ElementRegion is used to represent both array elements and casts.
class ElementRegion : public TypedValueRegion {
friend class MemRegionManager;
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
index 13f5b14378..f544204497 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
@@ -348,6 +348,8 @@ public:
/// a value of such type.
SVal getSValAsScalarOrLoc(const MemRegion *R) const;
+ using region_iterator = const MemRegion **;
+
/// Visits the symbols reachable from the given SVal using the provided
/// SymbolVisitor.
///
@@ -357,24 +359,14 @@ public:
/// \sa ScanReachableSymbols
bool scanReachableSymbols(SVal val, SymbolVisitor& visitor) const;
- /// Visits the symbols reachable from the SVals in the given range
- /// using the provided SymbolVisitor.
- bool scanReachableSymbols(const SVal *I, const SVal *E,
- SymbolVisitor &visitor) const;
-
/// Visits the symbols reachable from the regions in the given
/// MemRegions range using the provided SymbolVisitor.
- bool scanReachableSymbols(const MemRegion * const *I,
- const MemRegion * const *E,
+ bool scanReachableSymbols(llvm::iterator_range<region_iterator> Reachable,
SymbolVisitor &visitor) const;
template <typename CB> CB scanReachableSymbols(SVal val) const;
- template <typename CB> CB scanReachableSymbols(const SVal *beg,
- const SVal *end) const;
-
template <typename CB> CB
- scanReachableSymbols(const MemRegion * const *beg,
- const MemRegion * const *end) const;
+ scanReachableSymbols(llvm::iterator_range<region_iterator> Reachable) const;
/// Create a new state in which the statement is marked as tainted.
LLVM_NODISCARD ProgramStateRef
@@ -883,17 +875,10 @@ CB ProgramState::scanReachableSymbols(SVal val) const {
}
template <typename CB>
-CB ProgramState::scanReachableSymbols(const SVal *beg, const SVal *end) const {
- CB cb(this);
- scanReachableSymbols(beg, end, cb);
- return cb;
-}
-
-template <typename CB>
-CB ProgramState::scanReachableSymbols(const MemRegion * const *beg,
- const MemRegion * const *end) const {
+CB ProgramState::scanReachableSymbols(
+ llvm::iterator_range<region_iterator> Reachable) const {
CB cb(this);
- scanReachableSymbols(beg, end, cb);
+ scanReachableSymbols(Reachable, cb);
return cb;
}
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/RangedConstraintManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/RangedConstraintManager.h
index d2ba1f7c95..1b12a4edc2 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/RangedConstraintManager.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/RangedConstraintManager.h
@@ -131,7 +131,7 @@ using ConstraintRangeTy = llvm::ImmutableMap<SymbolRef, RangeSet>;
template <>
struct ProgramStateTrait<ConstraintRange>
: public ProgramStatePartialTrait<ConstraintRangeTy> {
- static void *GDMIndex() { static int Index; return &Index; }
+ static void *GDMIndex();
};
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SMTConstraintManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SMTConstraintManager.h
index 1a645cb870..8eaa9365be 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/SMTConstraintManager.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SMTConstraintManager.h
@@ -134,9 +134,9 @@ public:
// A value has been obtained, check if it is the only value
SMTExprRef NotExp = SMTConv::fromBinOp(
Solver, Exp, BO_NE,
- Ty->isBooleanType() ? Solver->fromBoolean(Value.getBoolValue())
- : Solver->fromAPSInt(Value),
- false);
+ Ty->isBooleanType() ? Solver->mkBoolean(Value.getBoolValue())
+ : Solver->mkBitvector(Value, Value.getBitWidth()),
+ /*isSigned=*/false);
Solver->addConstraint(NotExp);
@@ -198,7 +198,7 @@ public:
auto &CZFactory = State->get_context<ConstraintSMT>();
for (auto I = CZ.begin(), E = CZ.end(); I != E; ++I) {
- if (SymReaper.maybeDead(I->first))
+ if (SymReaper.isDead(I->first))
CZ = CZFactory.remove(CZ, *I);
}
@@ -218,6 +218,52 @@ public:
OS << nl;
}
+ bool canReasonAbout(SVal X) const override {
+ const TargetInfo &TI = getBasicVals().getContext().getTargetInfo();
+
+ Optional<nonloc::SymbolVal> SymVal = X.getAs<nonloc::SymbolVal>();
+ if (!SymVal)
+ return true;
+
+ const SymExpr *Sym = SymVal->getSymbol();
+ QualType Ty = Sym->getType();
+
+ // Complex types are not modeled
+ if (Ty->isComplexType() || Ty->isComplexIntegerType())
+ return false;
+
+ // Non-IEEE 754 floating-point types are not modeled
+ if ((Ty->isSpecificBuiltinType(BuiltinType::LongDouble) &&
+ (&TI.getLongDoubleFormat() == &llvm::APFloat::x87DoubleExtended() ||
+ &TI.getLongDoubleFormat() == &llvm::APFloat::PPCDoubleDouble())))
+ return false;
+
+ if (Ty->isRealFloatingType())
+ return Solver->isFPSupported();
+
+ if (isa<SymbolData>(Sym))
+ return true;
+
+ SValBuilder &SVB = getSValBuilder();
+
+ if (const SymbolCast *SC = dyn_cast<SymbolCast>(Sym))
+ return canReasonAbout(SVB.makeSymbolVal(SC->getOperand()));
+
+ if (const BinarySymExpr *BSE = dyn_cast<BinarySymExpr>(Sym)) {
+ if (const SymIntExpr *SIE = dyn_cast<SymIntExpr>(BSE))
+ return canReasonAbout(SVB.makeSymbolVal(SIE->getLHS()));
+
+ if (const IntSymExpr *ISE = dyn_cast<IntSymExpr>(BSE))
+ return canReasonAbout(SVB.makeSymbolVal(ISE->getRHS()));
+
+ if (const SymSymExpr *SSE = dyn_cast<SymSymExpr>(BSE))
+ return canReasonAbout(SVB.makeSymbolVal(SSE->getLHS())) &&
+ canReasonAbout(SVB.makeSymbolVal(SSE->getRHS()));
+ }
+
+ llvm_unreachable("Unsupported expression to reason about!");
+ }
+
/// Dumps SMT formula
LLVM_DUMP_METHOD void dump() const { Solver->dump(); }
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SMTConv.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SMTConv.h
index 8be7d4c467..cdca2a0970 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/SMTConv.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SMTConv.h
@@ -246,7 +246,7 @@ public:
// Logical operators
case BO_LAnd:
case BO_LOr:
- return fromBinOp(Solver, LHS, Op, RHS, false);
+ return fromBinOp(Solver, LHS, Op, RHS, /*isSigned=*/false);
default:;
}
@@ -294,14 +294,14 @@ public:
if (FromTy->isIntegralOrEnumerationType() && ToTy->isRealFloatingType()) {
SMTSortRef Sort = Solver->getFloatSort(ToBitWidth);
return FromTy->isSignedIntegerOrEnumerationType()
- ? Solver->mkFPtoSBV(Exp, Sort)
- : Solver->mkFPtoUBV(Exp, Sort);
+ ? Solver->mkSBVtoFP(Exp, Sort)
+ : Solver->mkUBVtoFP(Exp, Sort);
}
if (FromTy->isRealFloatingType() && ToTy->isIntegralOrEnumerationType())
return ToTy->isSignedIntegerOrEnumerationType()
- ? Solver->mkSBVtoFP(Exp, ToBitWidth)
- : Solver->mkUBVtoFP(Exp, ToBitWidth);
+ ? Solver->mkFPtoSBV(Exp, ToBitWidth)
+ : Solver->mkFPtoUBV(Exp, ToBitWidth);
llvm_unreachable("Unsupported explicit type cast!");
}
@@ -379,14 +379,14 @@ public:
getSymExpr(Solver, Ctx, SIE->getLHS(), &LTy, hasComparison);
llvm::APSInt NewRInt;
std::tie(NewRInt, RTy) = fixAPSInt(Ctx, SIE->getRHS());
- SMTExprRef RHS = Solver->fromAPSInt(NewRInt);
+ SMTExprRef RHS = Solver->mkBitvector(NewRInt, NewRInt.getBitWidth());
return getBinExpr(Solver, Ctx, LHS, LTy, Op, RHS, RTy, RetTy);
}
if (const IntSymExpr *ISE = dyn_cast<IntSymExpr>(BSE)) {
llvm::APSInt NewLInt;
std::tie(NewLInt, LTy) = fixAPSInt(Ctx, ISE->getLHS());
- SMTExprRef LHS = Solver->fromAPSInt(NewLInt);
+ SMTExprRef LHS = Solver->mkBitvector(NewLInt, NewLInt.getBitWidth());
SMTExprRef RHS =
getSymExpr(Solver, Ctx, ISE->getRHS(), &RTy, hasComparison);
return getBinExpr(Solver, Ctx, LHS, LTy, Op, RHS, RTy, RetTy);
@@ -466,7 +466,7 @@ public:
llvm::APFloat Zero =
llvm::APFloat::getZero(Ctx.getFloatTypeSemantics(Ty));
return fromFloatBinOp(Solver, Exp, Assumption ? BO_EQ : BO_NE,
- Solver->fromAPFloat(Zero));
+ Solver->mkFloat(Zero));
}
if (Ty->isIntegralOrEnumerationType() || Ty->isAnyPointerType() ||
@@ -477,8 +477,10 @@ public:
if (Ty->isBooleanType())
return Assumption ? fromUnOp(Solver, UO_LNot, Exp) : Exp;
- return fromBinOp(Solver, Exp, Assumption ? BO_EQ : BO_NE,
- Solver->fromInt("0", Ctx.getTypeSize(Ty)), isSigned);
+ return fromBinOp(
+ Solver, Exp, Assumption ? BO_EQ : BO_NE,
+ Solver->mkBitvector(llvm::APSInt("0"), Ctx.getTypeSize(Ty)),
+ isSigned);
}
llvm_unreachable("Unsupported type for zero value!");
@@ -493,7 +495,8 @@ public:
QualType FromTy;
llvm::APSInt NewFromInt;
std::tie(NewFromInt, FromTy) = fixAPSInt(Ctx, From);
- SMTExprRef FromExp = Solver->fromAPSInt(NewFromInt);
+ SMTExprRef FromExp =
+ Solver->mkBitvector(NewFromInt, NewFromInt.getBitWidth());
// Convert symbol
QualType SymTy;
@@ -507,7 +510,7 @@ public:
QualType ToTy;
llvm::APSInt NewToInt;
std::tie(NewToInt, ToTy) = fixAPSInt(Ctx, To);
- SMTExprRef ToExp = Solver->fromAPSInt(NewToInt);
+ SMTExprRef ToExp = Solver->mkBitvector(NewToInt, NewToInt.getBitWidth());
assert(FromTy == ToTy && "Range values have different types!");
// Construct two (in)equalities, and a logical and/or
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SMTSolver.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SMTSolver.h
index 71bfb400fc..2abe5fc987 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/SMTSolver.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SMTSolver.h
@@ -226,23 +226,23 @@ public:
/// operation
virtual SMTExprRef mkFPtoFP(const SMTExprRef &From, const SMTSortRef &To) = 0;
- /// Creates a floating-point conversion from floatint-point to signed
- /// bitvector operation
- virtual SMTExprRef mkFPtoSBV(const SMTExprRef &From,
- const SMTSortRef &To) = 0;
-
- /// Creates a floating-point conversion from floatint-point to unsigned
- /// bitvector operation
- virtual SMTExprRef mkFPtoUBV(const SMTExprRef &From,
- const SMTSortRef &To) = 0;
-
/// Creates a floating-point conversion from signed bitvector to
/// floatint-point operation
- virtual SMTExprRef mkSBVtoFP(const SMTExprRef &From, unsigned ToWidth) = 0;
+ virtual SMTExprRef mkSBVtoFP(const SMTExprRef &From,
+ const SMTSortRef &To) = 0;
/// Creates a floating-point conversion from unsigned bitvector to
/// floatint-point operation
- virtual SMTExprRef mkUBVtoFP(const SMTExprRef &From, unsigned ToWidth) = 0;
+ virtual SMTExprRef mkUBVtoFP(const SMTExprRef &From,
+ const SMTSortRef &To) = 0;
+
+ /// Creates a floating-point conversion from floatint-point to signed
+ /// bitvector operation
+ virtual SMTExprRef mkFPtoSBV(const SMTExprRef &From, unsigned ToWidth) = 0;
+
+ /// Creates a floating-point conversion from floatint-point to unsigned
+ /// bitvector operation
+ virtual SMTExprRef mkFPtoUBV(const SMTExprRef &From, unsigned ToWidth) = 0;
/// Creates a new symbol, given a name and a sort
virtual SMTExprRef mkSymbol(const char *Name, SMTSortRef Sort) = 0;
@@ -273,18 +273,6 @@ public:
virtual bool getInterpretation(const SMTExprRef &Exp,
llvm::APFloat &Float) = 0;
- /// Construct an SMTExprRef value from a boolean.
- virtual SMTExprRef fromBoolean(const bool Bool) = 0;
-
- /// Construct an SMTExprRef value from a finite APFloat.
- virtual SMTExprRef fromAPFloat(const llvm::APFloat &Float) = 0;
-
- /// Construct an SMTExprRef value from an APSInt.
- virtual SMTExprRef fromAPSInt(const llvm::APSInt &Int) = 0;
-
- /// Construct an SMTExprRef value from an integer.
- virtual SMTExprRef fromInt(const char *Int, uint64_t BitWidth) = 0;
-
/// Check if the constraints are satisfiable
virtual Optional<bool> check() const = 0;
@@ -295,7 +283,10 @@ public:
virtual void pop(unsigned NumStates = 1) = 0;
/// Reset the solver and remove all constraints.
- virtual void reset() const = 0;
+ virtual void reset() = 0;
+
+ /// Checks if the solver supports floating-points.
+ virtual bool isFPSupported() = 0;
virtual void print(raw_ostream &OS) const = 0;
};
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h b/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h
index 4ab7161459..f49f761c77 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h
@@ -260,12 +260,12 @@ public:
public:
virtual ~BindingsHandler();
+ /// \return whether the iteration should continue.
virtual bool HandleBinding(StoreManager& SMgr, Store store,
const MemRegion *region, SVal val) = 0;
};
- class FindUniqueBinding :
- public BindingsHandler {
+ class FindUniqueBinding : public BindingsHandler {
SymbolRef Sym;
const MemRegion* Binding = nullptr;
bool First = true;
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h
index b014c63709..d02a8abd11 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h
@@ -558,7 +558,6 @@ class SymbolReaper {
SymbolMapTy TheLiving;
SymbolSetTy MetadataInUse;
- SymbolSetTy TheDead;
RegionSetTy RegionRoots;
@@ -603,21 +602,6 @@ public:
/// symbol marking has occurred, i.e. in the MarkLiveSymbols callback.
void markInUse(SymbolRef sym);
- /// If a symbol is known to be live, marks the symbol as live.
- ///
- /// Otherwise, if the symbol cannot be proven live, it is marked as dead.
- /// Returns true if the symbol is dead, false if live.
- bool maybeDead(SymbolRef sym);
-
- using dead_iterator = SymbolSetTy::const_iterator;
-
- dead_iterator dead_begin() const { return TheDead.begin(); }
- dead_iterator dead_end() const { return TheDead.end(); }
-
- bool hasDeadSymbols() const {
- return !TheDead.empty();
- }
-
using region_iterator = RegionSetTy::const_iterator;
region_iterator region_begin() const { return RegionRoots.begin(); }
@@ -626,9 +610,9 @@ public:
/// Returns whether or not a symbol has been confirmed dead.
///
/// This should only be called once all marking of dead symbols has completed.
- /// (For checkers, this means only in the evalDeadSymbols callback.)
- bool isDead(SymbolRef sym) const {
- return TheDead.count(sym);
+ /// (For checkers, this means only in the checkDeadSymbols callback.)
+ bool isDead(SymbolRef sym) {
+ return !isLive(sym);
}
void markLive(const MemRegion *region);
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/TaintManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/TaintManager.h
index ce19b7131d..8218fb1eea 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/TaintManager.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/TaintManager.h
@@ -34,10 +34,7 @@ using TaintMapImpl = llvm::ImmutableMap<SymbolRef, TaintTagType>;
template<> struct ProgramStateTrait<TaintMap>
: public ProgramStatePartialTrait<TaintMapImpl> {
- static void *GDMIndex() {
- static int index = 0;
- return &index;
- }
+ static void *GDMIndex();
};
/// The GDM component mapping derived symbols' parent symbols to their
@@ -49,10 +46,7 @@ using DerivedSymTaintImpl = llvm::ImmutableMap<SymbolRef, TaintedSubRegions>;
template<> struct ProgramStateTrait<DerivedSymTaint>
: public ProgramStatePartialTrait<DerivedSymTaintImpl> {
- static void *GDMIndex() {
- static int index;
- return &index;
- }
+ static void *GDMIndex();
};
class TaintManager {
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/WorkList.h b/include/clang/StaticAnalyzer/Core/PathSensitive/WorkList.h
index 07edd35ff9..ef3c2694b2 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/WorkList.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/WorkList.h
@@ -85,6 +85,7 @@ public:
static std::unique_ptr<WorkList> makeBFSBlockDFSContents();
static std::unique_ptr<WorkList> makeUnexploredFirst();
static std::unique_ptr<WorkList> makeUnexploredFirstPriorityQueue();
+ static std::unique_ptr<WorkList> makeUnexploredFirstPriorityLocationQueue();
};
} // end ento namespace
diff --git a/include/clang/StaticAnalyzer/Core/RetainSummaryManager.h b/include/clang/StaticAnalyzer/Core/RetainSummaryManager.h
index fc506ae52e..de16a1781a 100644
--- a/include/clang/StaticAnalyzer/Core/RetainSummaryManager.h
+++ b/include/clang/StaticAnalyzer/Core/RetainSummaryManager.h
@@ -56,7 +56,7 @@ enum ArgEffect {
/// The argument has its reference count decreased by 1. This is as
/// if a -release message has been sent to the argument. This differs
- /// in behavior from DecRef when GC is enabled.
+ /// in behavior from DecRef when ARC is enabled.
DecRefMsg,
/// The argument has its reference count decreased by 1 to model
@@ -65,7 +65,7 @@ enum ArgEffect {
/// The argument has its reference count increased by 1. This is as
/// if a -retain message has been sent to the argument. This differs
- /// in behavior from IncRef when GC is enabled.
+ /// in behavior from IncRef when ARC is enabled.
IncRefMsg,
/// The argument has its reference count increased by 1. This is as
@@ -139,7 +139,7 @@ public:
OwnedWhenTrackedReceiver,
// Treat this function as returning a non-tracked symbol even if
// the function has been inlined. This is used where the call
- // site summary is more presise than the summary indirectly produced
+ // site summary is more precise than the summary indirectly produced
// by inlining the function
NoRetHard
};
@@ -369,8 +369,12 @@ public:
/// This is only meaningful if the summary applies to an ObjCMessageExpr*.
ArgEffect getReceiverEffect() const { return Receiver; }
+ /// \return the effect on the "this" receiver of the method call.
ArgEffect getThisEffect() const { return This; }
+ /// Set the effect of the method on "this".
+ void setThisEffect(ArgEffect e) { This = e; }
+
bool isNoop() const {
return Ret == RetEffect::MakeNoRet() && Receiver == DoNothing
&& DefaultArgEffect == MayEscape && This == DoNothing
@@ -465,6 +469,8 @@ public:
}
};
+class RetainSummaryTemplate;
+
class RetainSummaryManager {
typedef llvm::DenseMap<const FunctionDecl*, const RetainSummary *>
FuncSummariesTy;
@@ -479,7 +485,10 @@ class RetainSummaryManager {
/// Records whether or not the analyzed code runs in ARC mode.
const bool ARCEnabled;
- /// Track sublcasses of OSObject
+ /// Track Objective-C and CoreFoundation objects.
+ const bool TrackObjCAndCFObjects;
+
+ /// Track sublcasses of OSObject.
const bool TrackOSObjects;
/// FuncSummaries - A map from FunctionDecls to summaries.
@@ -530,6 +539,8 @@ class RetainSummaryManager {
/// Decrement the reference count on OS object.
const RetainSummary *getOSSummaryReleaseRule(const FunctionDecl *FD);
+ /// Free the OS object.
+ const RetainSummary *getOSSummaryFreeRule(const FunctionDecl *FD);
enum UnaryFuncKind { cfretain, cfrelease, cfautorelease, cfmakecollectable };
@@ -620,13 +631,36 @@ class RetainSummaryManager {
const RetainSummary * generateSummary(const FunctionDecl *FD,
bool &AllowAnnotations);
+ /// Return a summary for OSObject, or nullptr if not found.
+ const RetainSummary *getSummaryForOSObject(const FunctionDecl *FD,
+ StringRef FName, QualType RetTy);
+
+ /// Return a summary for Objective-C or CF object, or nullptr if not found.
+ const RetainSummary *getSummaryForObjCOrCFObject(
+ const FunctionDecl *FD,
+ StringRef FName,
+ QualType RetTy,
+ const FunctionType *FT,
+ bool &AllowAnnotations);
+
+ /// Apply the annotation of {@code pd} in function {@code FD}
+ /// to the resulting summary stored in out-parameter {@code Template}.
+ /// \return whether an annotation was applied.
+ bool applyFunctionParamAnnotationEffect(const ParmVarDecl *pd,
+ unsigned parm_idx,
+ const FunctionDecl *FD,
+ ArgEffects::Factory &AF,
+ RetainSummaryTemplate &Template);
+
public:
RetainSummaryManager(ASTContext &ctx,
bool usesARC,
- bool trackOSObject)
+ bool trackObjCAndCFObjects,
+ bool trackOSObjects)
: Ctx(ctx),
ARCEnabled(usesARC),
- TrackOSObjects(trackOSObject),
+ TrackObjCAndCFObjects(trackObjCAndCFObjects),
+ TrackOSObjects(trackOSObjects),
AF(BPAlloc), ScratchArgs(AF.getEmptyMap()),
ObjCAllocRetE(usesARC ? RetEffect::MakeNotOwned(RetEffect::ObjC)
: RetEffect::MakeOwned(RetEffect::ObjC)),
@@ -636,9 +670,19 @@ public:
InitializeMethodSummaries();
}
- bool canEval(const CallExpr *CE,
- const FunctionDecl *FD,
- bool &hasTrustedImplementationAnnotation);
+ enum class BehaviorSummary {
+ // Function does not return.
+ NoOp,
+
+ // Function returns the first argument.
+ Identity,
+
+ // Function either returns zero, or the input parameter.
+ IdentityOrZero
+ };
+
+ Optional<BehaviorSummary> canEval(const CallExpr *CE, const FunctionDecl *FD,
+ bool &hasTrustedImplementationAnnotation);
bool isTrustedReferenceCountImplementation(const FunctionDecl *FD);
@@ -693,6 +737,7 @@ public:
void updateSummaryFromAnnotations(const RetainSummary *&Summ,
const FunctionDecl *FD);
+
void updateSummaryForCall(const RetainSummary *&Summ,
const CallEvent &Call);
@@ -700,9 +745,21 @@ public:
RetEffect getObjAllocRetEffect() const { return ObjCAllocRetE; }
+ /// \return True if the declaration has an attribute {@code T},
+ /// AND we are tracking that attribute. False otherwise.
+ template <class T>
+ bool hasEnabledAttr(const Decl *D) {
+ return isAttrEnabled<T>() && D->hasAttr<T>();
+ }
+
+ /// Check whether we are tracking properties specified by the attributes.
+ template <class T>
+ bool isAttrEnabled();
+
friend class RetainSummaryTemplate;
};
+
// Used to avoid allocating long-term (BPAlloc'd) memory for default retain
// summaries. If a function or method looks like it has a default summary, but
// it has annotations, the annotations are added to the stack-based template
diff --git a/include/clang/StaticAnalyzer/Frontend/FrontendActions.h b/include/clang/StaticAnalyzer/Frontend/FrontendActions.h
index ba37b7f59a..8fd45bf102 100644
--- a/include/clang/StaticAnalyzer/Frontend/FrontendActions.h
+++ b/include/clang/StaticAnalyzer/Frontend/FrontendActions.h
@@ -55,6 +55,7 @@ private:
void printCheckerHelp(raw_ostream &OS, ArrayRef<std::string> plugins);
void printEnabledCheckerList(raw_ostream &OS, ArrayRef<std::string> plugins,
const AnalyzerOptions &opts);
+void printAnalyzerConfigList(raw_ostream &OS);
} // end GR namespace