diff options
Diffstat (limited to 'include/clang/StaticAnalyzer')
67 files changed, 1694 insertions, 2076 deletions
diff --git a/include/clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h b/include/clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h index 192ac1261c76..c7732333d9ba 100644 --- a/include/clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h +++ b/include/clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h @@ -1,9 +1,8 @@ //===--- ClangSACheckers.h - Registration functions for Checkers *- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -19,13 +18,17 @@ namespace clang { +class LangOptions; + namespace ento { + class CheckerManager; class CheckerRegistry; #define GET_CHECKERS -#define CHECKER(FULLNAME, CLASS, HELPTEXT, DOC_URI) \ - void register##CLASS(CheckerManager &mgr); +#define CHECKER(FULLNAME, CLASS, HELPTEXT, DOC_URI, IS_HIDDEN) \ + void register##CLASS(CheckerManager &mgr); \ + bool shouldRegister##CLASS(const LangOptions &LO); #include "clang/StaticAnalyzer/Checkers/Checkers.inc" #undef CHECKER #undef GET_CHECKERS diff --git a/include/clang/StaticAnalyzer/Checkers/CheckerBase.td b/include/clang/StaticAnalyzer/Checkers/CheckerBase.td index 453e189fccb0..6625d79559f5 100644 --- a/include/clang/StaticAnalyzer/Checkers/CheckerBase.td +++ b/include/clang/StaticAnalyzer/Checkers/CheckerBase.td @@ -1,9 +1,8 @@ //===--- CheckerBase.td - Checker TableGen classes ------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -11,14 +10,68 @@ // //===----------------------------------------------------------------------===// +/// Describes a checker or package option type. This is important for validating +/// user supplied inputs. +/// New option types can be added by modifying this enum. Note that this +/// requires changes in the TableGen emitter file ClangSACheckersEmitter.cpp. +class CmdLineOptionTypeEnum<bits<2> val> { + bits<2> Type = val; +} +def Integer : CmdLineOptionTypeEnum<0>; +def String : CmdLineOptionTypeEnum<1>; +def Boolean : CmdLineOptionTypeEnum<2>; + +/// Describes the state of the entry. We wouldn't like to display, for example, +/// developer only entries for a list meant for end users. +class DevelopmentStageEnum<bits<1> val> { + bits<1> Val = val; +} + +/// Alpha entries are under development, might be incomplet, inkorrekt and +/// unstable. +def InAlpha : DevelopmentStageEnum<0>; + +/// Released entries are stable, produce minimal, if any false positives, +/// and emits reports that explain the occurance of the bug understandably and +/// thoroughly. +def Released : DevelopmentStageEnum<1>; + +/// Marks the entry hidden. Hidden entries won't be displayed in +/// -analyzer-checker-option-help. +class HiddenEnum<bit val> { + bit Val = val; +} +def DontHide : HiddenEnum<0>; +def Hide : HiddenEnum<1>; + +/// Describes an option for a checker or a package. +class CmdLineOption<CmdLineOptionTypeEnum type, string cmdFlag, string desc, + string defaultVal, DevelopmentStageEnum stage, + HiddenEnum isHidden = DontHide> { + bits<2> Type = type.Type; + string CmdFlag = cmdFlag; + string Desc = desc; + string DefaultVal = defaultVal; + bits<1> DevelopmentStage = stage.Val; + bit Hidden = isHidden.Val; +} + +/// Describes a list of package options. +class PackageOptions<list<CmdLineOption> opts> { + list<CmdLineOption> PackageOptions = opts; +} + /// 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; - Package ParentPackage; + string PackageName = name; + // This field is optional. + list<CmdLineOption> PackageOptions; + Package ParentPackage; + bit Hidden = 0; } /// Describes a 'super' package that holds another package inside it. This is @@ -49,9 +102,37 @@ class Documentation<DocumentationEnum val> { /// 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'). +/// Example: +/// def DereferenceChecker : Checker<"NullDereference">, +/// HelpText<"Check for dereferences of null pointers">; class Checker<string name = ""> { - string CheckerName = name; - string HelpText; - bits<2> Documentation; - Package ParentPackage; + string CheckerName = name; + string HelpText; + // This field is optional. + list<CmdLineOption> CheckerOptions; + // This field is optional. + list<Checker> Dependencies; + bits<2> Documentation; + Package ParentPackage; + bit Hidden = 0; +} + +/// Describes a list of checker options. +class CheckerOptions<list<CmdLineOption> opts> { + list<CmdLineOption> CheckerOptions = opts; } + +/// Describes dependencies in between checkers. For example, InnerPointerChecker +/// relies on information MallocBase gathers. +/// Example: +/// def InnerPointerChecker : Checker<"InnerPointer">, +/// HelpText<"Check for inner pointers of C++ containers used after " +/// "re/deallocation">, +/// Dependencies<[MallocBase]>; +class Dependencies<list<Checker> Deps = []> { + list<Checker> Dependencies = Deps; +} + +/// Marks a checker or a package hidden. Hidden entries are meant for developers +/// only, and aren't exposed to end users. +class Hidden { bit Hidden = 1; } diff --git a/include/clang/StaticAnalyzer/Checkers/Checkers.td b/include/clang/StaticAnalyzer/Checkers/Checkers.td index 1bb3da7a2458..2b29efba66a4 100644 --- a/include/clang/StaticAnalyzer/Checkers/Checkers.td +++ b/include/clang/StaticAnalyzer/Checkers/Checkers.td @@ -1,9 +1,8 @@ //===--- Checkers.td - Static Analyzer Checkers -===-----------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// @@ -21,7 +20,7 @@ include "CheckerBase.td" def Alpha : Package<"alpha">; def Core : Package<"core">; -def CoreBuiltin : Package<"builtin">, ParentPackage<Core>; +def CoreBuiltin : Package<"builtin">, ParentPackage<Core>, Hidden; def CoreUninitialized : Package<"uninitialized">, ParentPackage<Core>; def CoreAlpha : Package<"core">, ParentPackage<Alpha>; @@ -43,7 +42,18 @@ def OptIn : Package<"optin">; // development, but unwanted for developers who target only a single platform. def PortabilityOptIn : Package<"portability">, ParentPackage<OptIn>; -def Nullability : Package<"nullability">; +def Nullability : Package<"nullability">, + PackageOptions<[ + CmdLineOption<Boolean, + "NoDiagnoseCallsToSystemHeaders", + "Suppresses warnings for violating nullability annotations " + "of system header functions. This is useful if you are " + "concerned with your custom nullability annotations more " + "than with following nullability specifications of system " + "header functions.", + "false", + Released> + ]>; def Cplusplus : Package<"cplusplus">; def CplusplusAlpha : Package<"cplusplus">, ParentPackage<Alpha>; @@ -88,13 +98,16 @@ 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">; -def GoogleAPIModeling : Package<"google">, ParentPackage<APIModeling>; +def APIModeling : Package<"apiModeling">, Hidden; +def GoogleAPIModeling : Package<"google">, ParentPackage<APIModeling>, Hidden; +def LLVMAPIModeling : Package<"llvm">, ParentPackage<APIModeling>, Hidden; -def Debug : Package<"debug">; +def Debug : Package<"debug">, Hidden; def CloneDetectionAlpha : Package<"clone">, ParentPackage<Alpha>; +def NonDeterminismAlpha : Package<"nondeterminism">, ParentPackage<Alpha>; + //===----------------------------------------------------------------------===// // Core Checkers. //===----------------------------------------------------------------------===// @@ -128,8 +141,14 @@ def UndefResultChecker : Checker<"UndefinedBinaryOperatorResult">, HelpText<"Check for undefined results of binary operators">, Documentation<HasDocumentation>; +def StackAddrEscapeBase : Checker<"StackAddrEscapeBase">, + HelpText<"Generate information about stack address escapes.">, + Documentation<NotDocumented>, + Hidden; + def StackAddrEscapeChecker : Checker<"StackAddressEscape">, HelpText<"Check that addresses to stack memory do not escape the function">, + Dependencies<[StackAddrEscapeBase]>, Documentation<HasDocumentation>; def DynamicTypePropagation : Checker<"DynamicTypePropagation">, @@ -138,7 +157,8 @@ def DynamicTypePropagation : Checker<"DynamicTypePropagation">, def NonnullGlobalConstantsChecker: Checker<"NonnilStringConstants">, HelpText<"Assume that const string-like globals are non-null">, - Documentation<NotDocumented>; + Documentation<NotDocumented>, + Hidden; } // end "core" @@ -187,6 +207,7 @@ 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)">, + Dependencies<[CallAndMessageChecker]>, Documentation<HasAlphaDocumentation>; def TestAfterDivZeroChecker : Checker<"TestAfterDivZero">, @@ -201,38 +222,57 @@ def DynamicTypeChecker : Checker<"DynamicTypeChecker">, def StackAddrAsyncEscapeChecker : Checker<"StackAddressAsyncEscape">, HelpText<"Check that addresses to stack memory do not escape the function">, + Dependencies<[StackAddrEscapeBase]>, Documentation<HasAlphaDocumentation>; } // end "alpha.core" +//===----------------------------------------------------------------------===// +// Nullability checkers. +//===----------------------------------------------------------------------===// + let ParentPackage = Nullability in { +def NullabilityBase : Checker<"NullabilityBase">, + HelpText<"Stores information during the analysis about nullability.">, + Documentation<NotDocumented>, + Hidden; + def NullPassedToNonnullChecker : Checker<"NullPassedToNonnull">, HelpText<"Warns when a null pointer is passed to a pointer which has a " "_Nonnull type.">, + Dependencies<[NullabilityBase]>, Documentation<HasDocumentation>; def NullReturnedFromNonnullChecker : Checker<"NullReturnedFromNonnull">, HelpText<"Warns when a null pointer is returned from a function that has " "_Nonnull return type.">, + Dependencies<[NullabilityBase]>, Documentation<HasDocumentation>; def NullableDereferencedChecker : Checker<"NullableDereferenced">, HelpText<"Warns when a nullable pointer is dereferenced.">, + Dependencies<[NullabilityBase]>, Documentation<HasDocumentation>; def NullablePassedToNonnullChecker : Checker<"NullablePassedToNonnull">, HelpText<"Warns when a nullable pointer is passed to a pointer which has a " "_Nonnull type.">, + Dependencies<[NullabilityBase]>, Documentation<HasDocumentation>; def NullableReturnedFromNonnullChecker : Checker<"NullableReturnedFromNonnull">, HelpText<"Warns when a nullable pointer is returned from a function that has " "_Nonnull return type.">, + Dependencies<[NullabilityBase]>, Documentation<NotDocumented>; } // end "nullability" +//===----------------------------------------------------------------------===// +// APIModeling. +//===----------------------------------------------------------------------===// + let ParentPackage = APIModeling in { def StdCLibraryFunctionsChecker : Checker<"StdCLibraryFunctions">, @@ -292,6 +332,120 @@ def ReturnUndefChecker : Checker<"UndefReturn">, } // end "core.uninitialized" //===----------------------------------------------------------------------===// +// Unix API checkers. +//===----------------------------------------------------------------------===// + +let ParentPackage = CString in { + +def CStringModeling : Checker<"CStringModeling">, + HelpText<"The base of several CString related checkers. On it's own it emits " + "no reports, but adds valuable information to the analysis when " + "enabled.">, + Documentation<NotDocumented>, + Hidden; + +def CStringNullArg : Checker<"NullArg">, + HelpText<"Check for null pointers being passed as arguments to C string " + "functions">, + Dependencies<[CStringModeling]>, + Documentation<HasDocumentation>; + +def CStringSyntaxChecker : Checker<"BadSizeArg">, + HelpText<"Check the size argument passed into C string functions for common " + "erroneous patterns">, + Dependencies<[CStringModeling]>, + Documentation<HasDocumentation>; + +} // end "unix.cstring" + +let ParentPackage = CStringAlpha in { + +def CStringOutOfBounds : Checker<"OutOfBounds">, + HelpText<"Check for out-of-bounds access in string functions">, + Dependencies<[CStringModeling]>, + Documentation<HasAlphaDocumentation>; + +def CStringBufferOverlap : Checker<"BufferOverlap">, + HelpText<"Checks for overlap in two buffer arguments">, + Dependencies<[CStringModeling]>, + Documentation<HasAlphaDocumentation>; + +def CStringNotNullTerm : Checker<"NotNullTerminated">, + HelpText<"Check for arguments which are not null-terminating strings">, + Dependencies<[CStringModeling]>, + Documentation<HasAlphaDocumentation>; + +} // end "alpha.unix.cstring" + +let ParentPackage = Unix in { + +def UnixAPIMisuseChecker : Checker<"API">, + HelpText<"Check calls to various UNIX/Posix functions">, + Documentation<HasDocumentation>; + +def DynamicMemoryModeling: Checker<"DynamicMemoryModeling">, + HelpText<"The base of several malloc() related checkers. On it's own it " + "emits no reports, but adds valuable information to the analysis " + "when enabled.">, + CheckerOptions<[ + CmdLineOption<Boolean, + "Optimistic", + "If set to true, the checker assumes that all the " + "allocating and deallocating functions are annotated with " + "ownership_holds, ownership_takes and ownership_returns.", + "false", + InAlpha> + ]>, + Dependencies<[CStringModeling]>, + Documentation<NotDocumented>, + Hidden; + +def MallocChecker: Checker<"Malloc">, + HelpText<"Check for memory leaks, double free, and use-after-free problems. " + "Traces memory managed by malloc()/free().">, + Dependencies<[DynamicMemoryModeling]>, + Documentation<HasDocumentation>; + +def MallocSizeofChecker : Checker<"MallocSizeof">, + HelpText<"Check for dubious malloc arguments involving sizeof">, + Documentation<HasDocumentation>; + +def MismatchedDeallocatorChecker : Checker<"MismatchedDeallocator">, + HelpText<"Check for mismatched deallocators.">, + Dependencies<[DynamicMemoryModeling]>, + Documentation<HasDocumentation>; + +def VforkChecker : Checker<"Vfork">, + HelpText<"Check for proper usage of vfork">, + Documentation<HasDocumentation>; + +} // end "unix" + +let ParentPackage = UnixAlpha in { + +def ChrootChecker : Checker<"Chroot">, + HelpText<"Check improper use of chroot">, + Documentation<HasAlphaDocumentation>; + +def PthreadLockChecker : Checker<"PthreadLock">, + HelpText<"Simple lock -> unlock checker">, + Documentation<HasAlphaDocumentation>; + +def StreamChecker : Checker<"Stream">, + HelpText<"Check stream handling functions">, + Documentation<HasAlphaDocumentation>; + +def SimpleStreamChecker : Checker<"SimpleStream">, + HelpText<"Check for misuses of stream APIs">, + Documentation<HasAlphaDocumentation>; + +def BlockInCriticalSectionChecker : Checker<"BlockInCriticalSection">, + HelpText<"Check for calls to blocking functions inside a critical section">, + Documentation<HasAlphaDocumentation>; + +} // end "alpha.unix" + +//===----------------------------------------------------------------------===// // C++ checkers. //===----------------------------------------------------------------------===// @@ -300,31 +454,112 @@ let ParentPackage = Cplusplus in { def InnerPointerChecker : Checker<"InnerPointer">, HelpText<"Check for inner pointers of C++ containers used after " "re/deallocation">, + Dependencies<[DynamicMemoryModeling]>, Documentation<NotDocumented>; def NewDeleteChecker : Checker<"NewDelete">, HelpText<"Check for double-free and use-after-free problems. Traces memory " "managed by new/delete.">, + Dependencies<[DynamicMemoryModeling]>, Documentation<HasDocumentation>; def NewDeleteLeaksChecker : Checker<"NewDeleteLeaks">, HelpText<"Check for memory leaks. Traces memory managed by new/delete.">, + Dependencies<[NewDeleteChecker]>, Documentation<HasDocumentation>; def CXXSelfAssignmentChecker : Checker<"SelfAssignment">, HelpText<"Checks C++ copy and move assignment operators for self assignment">, - Documentation<NotDocumented>; + Documentation<NotDocumented>, + Hidden; + +def SmartPtrModeling: Checker<"SmartPtr">, + HelpText<"Model behavior of C++ smart pointers">, + Documentation<NotDocumented>, + Hidden; def MoveChecker: Checker<"Move">, - HelpText<"Find use-after-move bugs in C++">, + HelpText<"Find use-after-move bugs in C++">, + CheckerOptions<[ + CmdLineOption<String, + "WarnOn", + "In non-aggressive mode, only warn on use-after-move of " + "local variables (or local rvalue references) and of STL " + "objects. The former is possible because local variables (or " + "local rvalue references) are not tempting their user to " + "re-use the storage. The latter is possible because STL " + "objects are known to end up in a valid but unspecified " + "state after the move and their state-reset methods are also " + "known, which allows us to predict precisely when " + "use-after-move is invalid. Some STL objects are known to " + "conform to additional contracts after move, so they are not " + "tracked. However, smart pointers specifically are tracked " + "because we can perform extra checking over them. In " + "aggressive mode, warn on any use-after-move because the " + "user has intentionally asked us to completely eliminate " + "use-after-move in his code. Values: \"KnownsOnly\", " + "\"KnownsAndLocals\", \"All\".", + "KnownsAndLocals", + Released> + ]>, Documentation<HasDocumentation>; } // end: "cplusplus" let ParentPackage = CplusplusOptIn in { +def UninitializedObjectChecker: Checker<"UninitializedObject">, + HelpText<"Reports uninitialized fields after object construction">, + CheckerOptions<[ + CmdLineOption<Boolean, + "Pedantic", + "If set to false, the checker won't emit warnings " + "for objects that don't have at least one initialized " + "field.", + "false", + Released>, + CmdLineOption<Boolean, + "NotesAsWarnings", + "If set to true, the checker will emit a warning " + "for each uninitalized field, as opposed to emitting one " + "warning per constructor call, and listing the uninitialized " + "fields that belongs to it in notes.", + "false", + Released, + Hide>, + CmdLineOption<Boolean, + "CheckPointeeInitialization", + "If set to false, the checker will not analyze " + "the pointee of pointer/reference fields, and will only " + "check whether the object itself is initialized.", + "false", + InAlpha>, + CmdLineOption<String, + "IgnoreRecordsWithField", + "If supplied, the checker will not analyze " + "structures that have a field with a name or type name that " + "matches the given pattern.", + "\"\"", + Released>, + CmdLineOption<Boolean, + "IgnoreGuardedFields", + "If set to true, the checker will analyze _syntactically_ " + "whether the found uninitialized object is used without a " + "preceding assert call. Defaults to false.", + "false", + InAlpha> + ]>, + Documentation<HasAlphaDocumentation>; + def VirtualCallChecker : Checker<"VirtualCall">, HelpText<"Check virtual function calls during construction or destruction">, + CheckerOptions<[ + CmdLineOption<Boolean, + "PureOnly", + "Whether to only report calls to pure virtual methods.", + "false", + Released> + ]>, Documentation<HasDocumentation>; } // end: "optin.cplusplus" @@ -340,21 +575,25 @@ def EnumCastOutOfRangeChecker : Checker<"EnumCastOutOfRange">, HelpText<"Check integer to enumeration casts for out of range values">, Documentation<HasAlphaDocumentation>; +def IteratorModeling : Checker<"IteratorModeling">, + HelpText<"Models iterators of C++ containers">, + Documentation<NotDocumented>, + Hidden; + def InvalidatedIteratorChecker : Checker<"InvalidatedIterator">, HelpText<"Check for use of invalidated iterators">, + Dependencies<[IteratorModeling]>, Documentation<HasAlphaDocumentation>; def IteratorRangeChecker : Checker<"IteratorRange">, HelpText<"Check for iterators used outside their valid ranges">, + Dependencies<[IteratorModeling]>, Documentation<HasAlphaDocumentation>; def MismatchedIteratorChecker : Checker<"MismatchedIterator">, HelpText<"Check for use of iterators of different containers where iterators " "of the same container are expected">, - Documentation<HasAlphaDocumentation>; - -def UninitializedObjectChecker: Checker<"UninitializedObject">, - HelpText<"Reports uninitialized fields after object construction">, + Dependencies<[IteratorModeling]>, Documentation<HasAlphaDocumentation>; } // end: "alpha.cplusplus" @@ -366,16 +605,24 @@ def UninitializedObjectChecker: Checker<"UninitializedObject">, let ParentPackage = Valist in { +def ValistBase : Checker<"ValistBase">, + HelpText<"Gathers information about va_lists.">, + Documentation<NotDocumented>, + Hidden; + def UninitializedChecker : Checker<"Uninitialized">, HelpText<"Check for usages of uninitialized (or already released) va_lists.">, + Dependencies<[ValistBase]>, Documentation<NotDocumented>; def UnterminatedChecker : Checker<"Unterminated">, HelpText<"Check for va_lists which are not released by a va_end call.">, + Dependencies<[ValistBase]>, Documentation<NotDocumented>; def CopyToSelfChecker : Checker<"CopyToSelf">, HelpText<"Check for va_lists which are copied onto itself.">, + Dependencies<[ValistBase]>, Documentation<NotDocumented>; } // end : "valist" @@ -409,6 +656,14 @@ let ParentPackage = Performance in { def PaddingChecker : Checker<"Padding">, HelpText<"Check for excessively padded structs.">, + CheckerOptions<[ + CmdLineOption<Integer, + "AllowedPad", + "Reports are only generated if the excessive padding exceeds " + "'AllowedPad' in bytes.", + "24", + Released> + ]>, Documentation<NotDocumented>; } // end: "padding" @@ -419,40 +674,73 @@ def PaddingChecker : Checker<"Padding">, let ParentPackage = InsecureAPI in { +def SecuritySyntaxChecker : Checker<"SecuritySyntaxChecker">, + HelpText<"Base of various security function related checkers">, + Documentation<NotDocumented>, + Hidden; + def bcmp : Checker<"bcmp">, HelpText<"Warn on uses of the 'bcmp' function">, + Dependencies<[SecuritySyntaxChecker]>, Documentation<HasDocumentation>; + def bcopy : Checker<"bcopy">, HelpText<"Warn on uses of the 'bcopy' function">, + Dependencies<[SecuritySyntaxChecker]>, Documentation<HasDocumentation>; + def bzero : Checker<"bzero">, HelpText<"Warn on uses of the 'bzero' function">, + Dependencies<[SecuritySyntaxChecker]>, Documentation<HasDocumentation>; + def gets : Checker<"gets">, HelpText<"Warn on uses of the 'gets' function">, + Dependencies<[SecuritySyntaxChecker]>, Documentation<HasDocumentation>; + def getpw : Checker<"getpw">, HelpText<"Warn on uses of the 'getpw' function">, + Dependencies<[SecuritySyntaxChecker]>, Documentation<HasDocumentation>; + def mktemp : Checker<"mktemp">, HelpText<"Warn on uses of the 'mktemp' function">, + Dependencies<[SecuritySyntaxChecker]>, Documentation<HasDocumentation>; + def mkstemp : Checker<"mkstemp">, HelpText<"Warn when 'mkstemp' is passed fewer than 6 X's in the format " "string">, + Dependencies<[SecuritySyntaxChecker]>, Documentation<HasDocumentation>; + def rand : Checker<"rand">, HelpText<"Warn on uses of the 'rand', 'random', and related functions">, + Dependencies<[SecuritySyntaxChecker]>, Documentation<HasDocumentation>; + def strcpy : Checker<"strcpy">, HelpText<"Warn on uses of the 'strcpy' and 'strcat' functions">, + Dependencies<[SecuritySyntaxChecker]>, Documentation<HasDocumentation>; + def vfork : Checker<"vfork">, HelpText<"Warn on uses of the 'vfork' function">, + Dependencies<[SecuritySyntaxChecker]>, Documentation<HasDocumentation>; + def UncheckedReturn : Checker<"UncheckedReturn">, HelpText<"Warn on uses of functions whose return values must be always " "checked">, + Dependencies<[SecuritySyntaxChecker]>, + Documentation<HasDocumentation>; + +def DeprecatedOrUnsafeBufferHandling : + Checker<"DeprecatedOrUnsafeBufferHandling">, + HelpText<"Warn on uses of unsecure or deprecated buffer manipulating " + "functions">, + Dependencies<[SecuritySyntaxChecker]>, Documentation<HasDocumentation>; } // end "security.insecureAPI" @@ -462,6 +750,7 @@ 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)">, + Dependencies<[SecuritySyntaxChecker]>, Documentation<HasDocumentation>; } // end "security" @@ -484,11 +773,20 @@ def MallocOverflowSecurityChecker : Checker<"MallocOverflow">, HelpText<"Check for overflows in the arguments to malloc()">, Documentation<HasAlphaDocumentation>; -// 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">, + CheckerOptions<[ + CmdLineOption<Integer, + "MmapProtExec", + "Specifies the value of PROT_EXEC", + "0x04", + Released>, + CmdLineOption<Integer, + "MmapProtRead", + "Specifies the value of PROT_READ", + "0x01", + Released> + ]>, Documentation<HasAlphaDocumentation>; } // end "alpha.security" @@ -506,97 +804,37 @@ def GenericTaintChecker : Checker<"TaintPropagation">, } // end "alpha.security.taint" //===----------------------------------------------------------------------===// -// Unix API checkers. +// Mac OS X, Cocoa, and Core Foundation checkers. //===----------------------------------------------------------------------===// -let ParentPackage = Unix in { - -def UnixAPIMisuseChecker : Checker<"API">, - HelpText<"Check calls to various UNIX/Posix functions">, - Documentation<HasDocumentation>; - -def MallocChecker: Checker<"Malloc">, - HelpText<"Check for memory leaks, double free, and use-after-free problems. " - "Traces memory managed by malloc()/free().">, - Documentation<HasDocumentation>; - -def MallocSizeofChecker : Checker<"MallocSizeof">, - HelpText<"Check for dubious malloc arguments involving sizeof">, - Documentation<HasDocumentation>; - -def MismatchedDeallocatorChecker : Checker<"MismatchedDeallocator">, - HelpText<"Check for mismatched deallocators.">, - Documentation<HasDocumentation>; - -def VforkChecker : Checker<"Vfork">, - HelpText<"Check for proper usage of vfork">, - Documentation<HasDocumentation>; - -} // end "unix" - -let ParentPackage = UnixAlpha in { - -def ChrootChecker : Checker<"Chroot">, - HelpText<"Check improper use of chroot">, - Documentation<HasAlphaDocumentation>; - -def PthreadLockChecker : Checker<"PthreadLock">, - HelpText<"Simple lock -> unlock checker">, - Documentation<HasAlphaDocumentation>; - -def StreamChecker : Checker<"Stream">, - HelpText<"Check stream handling functions">, - Documentation<HasAlphaDocumentation>; - -def SimpleStreamChecker : Checker<"SimpleStream">, - HelpText<"Check for misuses of stream APIs">, - Documentation<HasAlphaDocumentation>; - -def BlockInCriticalSectionChecker : Checker<"BlockInCriticalSection">, - HelpText<"Check for calls to blocking functions inside a critical section">, - Documentation<HasAlphaDocumentation>; - -} // end "alpha.unix" - -let ParentPackage = CString in { - -def CStringNullArg : Checker<"NullArg">, - HelpText<"Check for null pointers being passed as arguments to C string " - "functions">, - Documentation<HasDocumentation>; - -def CStringSyntaxChecker : Checker<"BadSizeArg">, - HelpText<"Check the size argument passed into C string functions for common " - "erroneous patterns">, - Documentation<HasDocumentation>; - -} // end "unix.cstring" - -let ParentPackage = CStringAlpha in { - -def CStringOutOfBounds : Checker<"OutOfBounds">, - HelpText<"Check for out-of-bounds access in string functions">, - Documentation<HasAlphaDocumentation>; - -def CStringBufferOverlap : Checker<"BufferOverlap">, - HelpText<"Checks for overlap in two buffer arguments">, - Documentation<HasAlphaDocumentation>; - -def CStringNotNullTerm : Checker<"NotNullTerminated">, - HelpText<"Check for arguments which are not null-terminating strings">, - Documentation<HasAlphaDocumentation>; +let ParentPackage = Cocoa in { -} // end "alpha.unix.cstring" +def RetainCountBase : Checker<"RetainCountBase">, + HelpText<"Common base of various retain count related checkers">, + Documentation<NotDocumented>, + Hidden; -//===----------------------------------------------------------------------===// -// Mac OS X, Cocoa, and Core Foundation checkers. -//===----------------------------------------------------------------------===// +} // end "osx.cocoa" let ParentPackage = OSX in { +def NSOrCFErrorDerefChecker : Checker<"NSOrCFErrorDerefChecker">, + HelpText<"Implementation checker for NSErrorChecker and CFErrorChecker">, + Documentation<NotDocumented>, + Hidden; + def NumberObjectConversionChecker : Checker<"NumberObjectConversion">, HelpText<"Check for erroneous conversions of objects representing numbers " "into numbers">, + CheckerOptions<[ + CmdLineOption<Boolean, + "Pedantic", + "Enables detection of more conversion patterns (which are " + "most likely more harmless, and therefore are more likely to " + "produce false positives).", + "false", + Released> + ]>, Documentation<NotDocumented>; def MacOSXAPIChecker : Checker<"API">, @@ -607,12 +845,19 @@ def MacOSKeychainAPIChecker : Checker<"SecKeychainAPI">, HelpText<"Check for proper uses of Secure Keychain APIs">, Documentation<HasDocumentation>; +def MIGChecker : Checker<"MIG">, + HelpText<"Find violations of the Mach Interface Generator " + "calling convention">, + Documentation<NotDocumented>; + def ObjCPropertyChecker : Checker<"ObjCProperty">, HelpText<"Check for proper uses of Objective-C properties">, Documentation<NotDocumented>; def OSObjectRetainCountChecker : Checker<"OSObjectRetainCount">, - HelpText<"Check for leaks and improper reference count management for OSObject">, + HelpText<"Check for leaks and improper reference count management for " + "OSObject">, + Dependencies<[RetainCountBase]>, Documentation<NotDocumented>; } // end "osx" @@ -676,14 +921,37 @@ def ObjCSuperCallChecker : Checker<"MissingSuperCall">, def NSErrorChecker : Checker<"NSError">, HelpText<"Check usage of NSError** parameters">, + Dependencies<[NSOrCFErrorDerefChecker]>, Documentation<HasDocumentation>; def RetainCountChecker : Checker<"RetainCount">, HelpText<"Check for leaks and improper reference count management">, + CheckerOptions<[ + CmdLineOption<Boolean, + "CheckOSObject", + "Find violations of retain-release rules applied to XNU " + "OSObject instances. By default, the checker only checks " + "retain-release rules for Objective-C NSObject instances " + "and CoreFoundation objects.", + "true", + InAlpha, + Hide>, + CmdLineOption<Boolean, + "TrackNSCFStartParam", + "Check not only that the code follows retain-release rules " + "with respect to objects it allocates or borrows from " + "elsewhere, but also that it fulfills its own retain count " + "specification with respect to objects that it receives as " + "arguments.", + "false", + Released> + ]>, + Dependencies<[RetainCountBase]>, Documentation<HasDocumentation>; def ObjCGenericsChecker : Checker<"ObjCGenerics">, HelpText<"Check for type errors when using Objective-C generics">, + Dependencies<[DynamicTypePropagation]>, Documentation<HasDocumentation>; def ObjCDeallocChecker : Checker<"Dealloc">, @@ -710,16 +978,33 @@ def GCDAntipattern : Checker<"GCDAntipattern">, Documentation<NotDocumented>; } // end "optin.performance" +let ParentPackage = OSXOptIn in { + +def OSObjectCStyleCast : Checker<"OSObjectCStyleCast">, + HelpText<"Checker for C-style casts of OSObjects">, + Documentation<NotDocumented>; + +} // end "optin.osx" + let ParentPackage = CocoaAlpha in { +def IvarInvalidationModeling : Checker<"IvarInvalidationModeling">, + HelpText<"Gathers information for annotation driven invalidation checking " + "for classes that contains a method annotated with " + "'objc_instance_variable_invalidator'">, + Documentation<NotDocumented>, + Hidden; + def InstanceVariableInvalidation : Checker<"InstanceVariableInvalidation">, HelpText<"Check that the invalidatable instance variables are invalidated in " "the methods annotated with objc_instance_variable_invalidator">, + Dependencies<[IvarInvalidationModeling]>, Documentation<HasAlphaDocumentation>; def MissingInvalidationMethod : Checker<"MissingInvalidationMethod">, HelpText<"Check that the invalidation methods are present in classes that " "contain invalidatable instance variables">, + Dependencies<[IvarInvalidationModeling]>, Documentation<HasAlphaDocumentation>; def DirectIvarAssignment : Checker<"DirectIvarAssignment">, @@ -730,6 +1015,7 @@ def DirectIvarAssignmentForAnnotatedFunctions : Checker<"DirectIvarAssignmentForAnnotatedFunctions">, HelpText<"Check for direct assignments to instance variables in the methods " "annotated with objc_no_direct_instance_variable_assignment">, + Dependencies<[DirectIvarAssignment]>, Documentation<HasAlphaDocumentation>; } // end "alpha.osx.cocoa" @@ -746,6 +1032,7 @@ def CFRetainReleaseChecker : Checker<"CFRetainRelease">, def CFErrorChecker : Checker<"CFError">, HelpText<"Check usage of CFErrorRef* parameters">, + Dependencies<[NSOrCFErrorDerefChecker]>, Documentation<HasDocumentation>; } // end "osx.coreFoundation" @@ -768,6 +1055,19 @@ let ParentPackage = LocalizabilityOptIn in { def NonLocalizedStringChecker : Checker<"NonLocalizedStringChecker">, HelpText<"Warns about uses of non-localized NSStrings passed to UI methods " "expecting localized NSStrings">, + CheckerOptions<[ + CmdLineOption<Boolean, + "AggressiveReport", + "Marks a string being returned by any call as localized if " + "it is in LocStringFunctions (LSF) or the function is " + "annotated. Otherwise, we mark it as NonLocalized " + "(Aggressive) or NonLocalized only if it is not backed by a " + "SymRegion (Non-Aggressive), basically leaving only string " + "literals as NonLocalized.", + "false", + InAlpha, + Hide> + ]>, Documentation<HasDocumentation>; def EmptyLocalizationContextChecker : @@ -806,6 +1106,18 @@ def LLVMConventionsChecker : Checker<"Conventions">, } // end "llvm" +let ParentPackage = LLVMAPIModeling in { + +def CastValueChecker : Checker<"CastValue">, + HelpText<"Model implementation of custom RTTIs">, + Documentation<NotDocumented>; + +def ReturnValueChecker : Checker<"ReturnValue">, + HelpText<"Model the guaranteed boolean return value of function calls">, + Documentation<NotDocumented>; + +} // end "apiModeling.llvm" + //===----------------------------------------------------------------------===// // Checkers modeling Google APIs. //===----------------------------------------------------------------------===// @@ -826,12 +1138,118 @@ let ParentPackage = Debug in { def AnalysisOrderChecker : Checker<"AnalysisOrder">, HelpText<"Print callbacks that are called during analysis in order">, + CheckerOptions<[ + CmdLineOption<Boolean, + "PreStmtCastExpr", + "", + "false", + Released, + Hide>, + CmdLineOption<Boolean, + "PostStmtCastExpr", + "", + "false", + Released, + Hide>, + CmdLineOption<Boolean, + "PreStmtArraySubscriptExpr", + "", + "false", + Released, + Hide>, + CmdLineOption<Boolean, + "PostStmtArraySubscriptExpr", + "", + "false", + Released, + Hide>, + CmdLineOption<Boolean, + "PreStmtCXXNewExpr", + "", + "false", + Released, + Hide>, + CmdLineOption<Boolean, + "PostStmtCXXNewExpr", + "", + "false", + Released, + Hide>, + CmdLineOption<Boolean, + "PreStmtOffsetOfExpr", + "", + "false", + Released, + Hide>, + CmdLineOption<Boolean, + "PostStmtOffsetOfExpr", + "", + "false", + Released, + Hide>, + CmdLineOption<Boolean, + "PreCall", + "", + "false", + Released, + Hide>, + CmdLineOption<Boolean, + "PostCall", + "", + "false", + Released, + Hide>, + CmdLineOption<Boolean, + "EndFunction", + "", + "false", + Released, + Hide>, + CmdLineOption<Boolean, + "NewAllocator", + "", + "false", + Released, + Hide>, + CmdLineOption<Boolean, + "Bind", + "", + "false", + Released, + Hide>, + CmdLineOption<Boolean, + "LiveSymbols", + "", + "false", + Released, + Hide>, + CmdLineOption<Boolean, + "RegionChanges", + "", + "false", + Released, + Hide>, + CmdLineOption<Boolean, + "*", + "Enables all callbacks.", + "false", + Released, + Hide> + ]>, Documentation<NotDocumented>; def DominatorsTreeDumper : Checker<"DumpDominators">, HelpText<"Print the dominance tree for a given CFG">, Documentation<NotDocumented>; +def PostDominatorsTreeDumper : Checker<"DumpPostDominators">, + HelpText<"Print the post dominance tree for a given CFG">, + Documentation<NotDocumented>; + +def ControlDependencyTreeDumper : Checker<"DumpControlDependencies">, + HelpText<"Print the post control dependency tree for a given CFG">, + Documentation<NotDocumented>; + def LiveVariablesDumper : Checker<"DumpLiveVars">, HelpText<"Print results of live variable analysis">, Documentation<NotDocumented>; @@ -884,6 +1302,10 @@ def ExplodedGraphViewer : Checker<"ViewExplodedGraph">, HelpText<"View Exploded Graphs using GraphViz">, Documentation<NotDocumented>; +def ReportStmts : Checker<"ReportStmts">, + HelpText<"Emits a warning for every statement.">, + Documentation<NotDocumented>; + } // end "debug" @@ -895,6 +1317,28 @@ let ParentPackage = CloneDetectionAlpha in { def CloneChecker : Checker<"CloneChecker">, HelpText<"Reports similar pieces of code.">, + CheckerOptions<[ + CmdLineOption<Integer, + "MinimumCloneComplexity", + "Ensures that every clone has at least the given complexity. " + "Complexity is here defined as the total amount of children " + "of a statement. This constraint assumes the first statement " + "in the group is representative for all other statements in " + "the group in terms of complexity.", + "50", + Released>, + CmdLineOption<Boolean, + "ReportNormalClones", + "Report all clones, even less suspicious ones.", + "true", + Released>, + CmdLineOption<String, + "IgnoredFilesPattern", + "If supplied, the checker wont analyze files with a filename " + "that matches the given pattern.", + "\"\"", + Released> + ]>, Documentation<HasAlphaDocumentation>; } // end "clone" @@ -910,3 +1354,19 @@ def UnixAPIPortabilityChecker : Checker<"UnixAPI">, Documentation<NotDocumented>; } // end optin.portability + +//===----------------------------------------------------------------------===// +// NonDeterminism checkers. +//===----------------------------------------------------------------------===// + +let ParentPackage = NonDeterminismAlpha in { + +def PointerIterationChecker : Checker<"PointerIteration">, + HelpText<"Checks for non-determinism caused by iteration of unordered containers of pointers">, + Documentation<HasDocumentation>; + +def PointerSortingChecker : Checker<"PointerSorting">, + HelpText<"Check for non-determinism caused by sorting of pointers">, + Documentation<HasDocumentation>; + +} // end alpha.nondeterminism diff --git a/include/clang/StaticAnalyzer/Checkers/LocalCheckers.h b/include/clang/StaticAnalyzer/Checkers/LocalCheckers.h index 463f04a65ac3..8f7148fde19a 100644 --- a/include/clang/StaticAnalyzer/Checkers/LocalCheckers.h +++ b/include/clang/StaticAnalyzer/Checkers/LocalCheckers.h @@ -1,9 +1,8 @@ //==- LocalCheckers.h - Intra-Procedural+Flow-Sensitive Checkers -*- C++ -*-==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/include/clang/StaticAnalyzer/Checkers/MPIFunctionClassifier.h b/include/clang/StaticAnalyzer/Checkers/MPIFunctionClassifier.h index 65e908912c54..bbc5111ccacc 100644 --- a/include/clang/StaticAnalyzer/Checkers/MPIFunctionClassifier.h +++ b/include/clang/StaticAnalyzer/Checkers/MPIFunctionClassifier.h @@ -1,9 +1,8 @@ //===-- MPIFunctionClassifier.h - classifies MPI functions ----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// /// diff --git a/include/clang/StaticAnalyzer/Checkers/SValExplainer.h b/include/clang/StaticAnalyzer/Checkers/SValExplainer.h index 62bb0f666d44..10c890246521 100644 --- a/include/clang/StaticAnalyzer/Checkers/SValExplainer.h +++ b/include/clang/StaticAnalyzer/Checkers/SValExplainer.h @@ -1,9 +1,8 @@ //== SValExplainer.h - Symbolic value explainer -----------------*- C++ -*--==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/include/clang/StaticAnalyzer/Core/Analyses.def b/include/clang/StaticAnalyzer/Core/Analyses.def index 99e26c75e1c2..377451576148 100644 --- a/include/clang/StaticAnalyzer/Core/Analyses.def +++ b/include/clang/StaticAnalyzer/Core/Analyses.def @@ -1,9 +1,8 @@ //===-- Analyses.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. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def b/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def index 3cd54df7b179..70bd476b6c43 100644 --- a/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def +++ b/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def @@ -1,9 +1,8 @@ //===-- 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. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -205,6 +204,10 @@ ANALYZER_OPTION(bool, ShouldPrunePaths, "prune-paths", "be pruned out of the final output.", true) +ANALYZER_OPTION(bool, ShouldAddPopUpNotes, "add-pop-up-notes", + "Whether pop-up notes should be added to the final output.", + true) + ANALYZER_OPTION( bool, ShouldConditionalizeStaticInitializers, "cfg-conditional-static-initializers", @@ -288,6 +291,23 @@ ANALYZER_OPTION(bool, DisplayCTUProgress, "display-ctu-progress", "the analyzer's progress related to ctu.", false) +ANALYZER_OPTION(bool, ShouldTrackConditions, "track-conditions", + "Whether to track conditions that are a control dependency of " + "an already tracked variable.", + false) + +ANALYZER_OPTION(bool, ShouldTrackConditionsDebug, "track-conditions-debug", + "Whether to place an event at each tracked condition.", + false) + +ANALYZER_OPTION(unsigned, CTUImportThreshold, "ctu-import-threshold", + "The maximal amount of translation units that is considered " + "for import when inlining functions during CTU analysis. " + "Lowering this threshold can alleviate the memory burder of " + "analysis with many interdependent definitions located in " + "various translation units.", + 100u) + //===----------------------------------------------------------------------===// // Unsinged analyzer options. //===----------------------------------------------------------------------===// diff --git a/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h b/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h index 7745e459e19b..9630a229bd3b 100644 --- a/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h +++ b/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h @@ -1,9 +1,8 @@ //===- AnalyzerOptions.h - Analysis Engine Options --------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -167,6 +166,29 @@ public: static std::vector<StringRef> getRegisteredCheckers(bool IncludeExperimental = false); + /// Convenience function for printing options or checkers and their + /// description in a formatted manner. If \p MinLineWidth is set to 0, no line + /// breaks are introduced for the description. + /// + /// Format, depending whether the option name's length is less then + /// \p OptionWidth: + /// + /// <padding>EntryName<padding>Description + /// <---------padding--------->Description + /// <---------padding--------->Description + /// + /// <padding>VeryVeryLongOptionName + /// <---------padding--------->Description + /// <---------padding--------->Description + /// ^~~~~~~~ InitialPad + /// ^~~~~~~~~~~~~~~~~~~~~~~~~~ EntryWidth + /// ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~MinLineWidth + static void printFormattedEntry( + llvm::raw_ostream &Out, + std::pair<StringRef, StringRef> EntryDescPair, + size_t EntryWidth, size_t InitialPad, size_t MinLineWidth = 0); + + /// Pair of checker name and enable/disable. std::vector<std::pair<std::string, bool>> CheckersControlList; @@ -198,6 +220,13 @@ public: unsigned DisableAllChecks : 1; unsigned ShowCheckerHelp : 1; + unsigned ShowCheckerHelpAlpha : 1; + unsigned ShowCheckerHelpDeveloper : 1; + + unsigned ShowCheckerOptionList : 1; + unsigned ShowCheckerOptionAlphaList : 1; + unsigned ShowCheckerOptionDeveloperList : 1; + unsigned ShowEnabledCheckerList : 1; unsigned ShowConfigOptionsList : 1; unsigned ShouldEmitErrorsOnInvalidConfigValue : 1; @@ -216,6 +245,9 @@ public: /// strategy. We get better code coverage when retry is enabled. unsigned NoRetryExhausted : 1; + /// Emit analyzer warnings as errors. + unsigned AnalyzerWerror : 1; + /// The inlining stack depth limit. // Cap the stack depth at 4 calls (5 stack frames, base + 4 calls). unsigned InlineMaxStackDepth = 5; @@ -261,11 +293,14 @@ public: AnalyzerOptions() : DisableAllChecks(false), ShowCheckerHelp(false), - ShowEnabledCheckerList(false), ShowConfigOptionsList(false), - AnalyzeAll(false), AnalyzerDisplayProgress(false), - AnalyzeNestedBlocks(false), eagerlyAssumeBinOpBifurcation(false), - TrimGraph(false), visualizeExplodedGraphWithGraphViz(false), - UnoptimizedCFG(false), PrintStats(false), NoRetryExhausted(false) { + ShowCheckerHelpAlpha(false), ShowCheckerHelpDeveloper(false), + ShowCheckerOptionList(false), ShowCheckerOptionAlphaList(false), + ShowCheckerOptionDeveloperList(false), ShowEnabledCheckerList(false), + ShowConfigOptionsList(false), AnalyzeAll(false), + AnalyzerDisplayProgress(false), AnalyzeNestedBlocks(false), + eagerlyAssumeBinOpBifurcation(false), TrimGraph(false), + visualizeExplodedGraphWithGraphViz(false), UnoptimizedCFG(false), + PrintStats(false), NoRetryExhausted(false), AnalyzerWerror(false) { llvm::sort(AnalyzerConfigCmdFlags); } @@ -273,54 +308,63 @@ public: /// interpreted as true and the "false" string is interpreted as false. /// /// If an option value is not provided, returns the given \p DefaultVal. - /// @param [in] Name Name for option to retrieve. - /// @param [in] DefaultVal Default value returned if no such option was - /// specified. - /// @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] CheckerName The *full name* of the checker. One may retrieve + /// this from the checker object's field \c Name, or through \c + /// CheckerManager::getCurrentCheckName within the checker's registry + /// function. + /// Checker options are retrieved in the following format: + /// `-analyzer-config CheckerName:OptionName=Value. + /// @param [in] OptionName Name for option to retrieve. /// @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 getCheckerBooleanOption(StringRef Name, bool DefaultVal, - const ento::CheckerBase *C, - bool SearchInParents = false) const; + bool getCheckerBooleanOption(StringRef CheckerName, StringRef OptionName, + bool SearchInParents = false) const; + bool getCheckerBooleanOption(const ento::CheckerBase *C, StringRef OptionName, + bool SearchInParents = false) const; /// Interprets an option's string value as an integer value. /// /// If an option value is not provided, returns the given \p DefaultVal. - /// @param [in] Name Name for option to retrieve. - /// @param [in] DefaultVal Default value returned if no such option was - /// specified. - /// @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] CheckerName The *full name* of the checker. One may retrieve + /// this from the checker object's field \c Name, or through \c + /// CheckerManager::getCurrentCheckName within the checker's registry + /// function. + /// Checker options are retrieved in the following format: + /// `-analyzer-config CheckerName:OptionName=Value. + /// @param [in] OptionName Name for option to retrieve. /// @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 getCheckerIntegerOption(StringRef Name, int DefaultVal, - const ento::CheckerBase *C, - bool SearchInParents = false) const; + int getCheckerIntegerOption(StringRef CheckerName, StringRef OptionName, + bool SearchInParents = false) const; + + int getCheckerIntegerOption(const ento::CheckerBase *C, StringRef OptionName, + bool SearchInParents = false) const; /// Query an option's string value. /// /// If an option value is not provided, returns the given \p DefaultVal. - /// @param [in] Name Name for option to retrieve. - /// @param [in] DefaultVal Default value returned if no such option was - /// specified. - /// @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] CheckerName The *full name* of the checker. One may retrieve + /// this from the checker object's field \c Name, or through \c + /// CheckerManager::getCurrentCheckName within the checker's registry + /// function. + /// Checker options are retrieved in the following format: + /// `-analyzer-config CheckerName:OptionName=Value. + /// @param [in] OptionName Name for option to retrieve. /// @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 getCheckerStringOption(StringRef Name, StringRef DefaultVal, - const ento::CheckerBase *C, - bool SearchInParents = false) const; + StringRef getCheckerStringOption(StringRef CheckerName, StringRef OptionName, + bool SearchInParents = false) const; + + StringRef getCheckerStringOption(const ento::CheckerBase *C, + StringRef OptionName, + 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 diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h index 9041f4c1afbd..d30ad19b20f8 100644 --- a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h +++ b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h @@ -1,9 +1,8 @@ //===- BugReporter.h - Generate PathDiagnostics -----------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -95,7 +94,7 @@ protected: friend class BugReportEquivClass; friend class BugReporter; - BugType& BT; + const BugType& BT; const Decl *DeclWithIssue = nullptr; std::string ShortDescription; std::string Description; @@ -154,6 +153,9 @@ protected: /// \sa removeInvalidation llvm::SmallSet<InvalidationRecord, 4> Invalidations; + /// Conditions we're already tracking. + llvm::SmallSet<const ExplodedNode *, 4> TrackedConditions; + private: // Used internally by BugReporter. Symbols &getInterestingSymbols(); @@ -164,15 +166,15 @@ private: void popInterestingSymbolsAndRegions(); public: - BugReport(BugType& bt, StringRef desc, const ExplodedNode *errornode) + BugReport(const BugType& bt, StringRef desc, const ExplodedNode *errornode) : BT(bt), Description(desc), ErrorNode(errornode) {} - BugReport(BugType& bt, StringRef shortDesc, StringRef desc, + BugReport(const BugType& bt, StringRef shortDesc, StringRef desc, const ExplodedNode *errornode) : BT(bt), ShortDescription(shortDesc), Description(desc), ErrorNode(errornode) {} - BugReport(BugType &bt, StringRef desc, PathDiagnosticLocation l) + BugReport(const BugType &bt, StringRef desc, PathDiagnosticLocation l) : BT(bt), Description(desc), Location(l) {} /// Create a BugReport with a custom uniqueing location. @@ -190,7 +192,7 @@ public: virtual ~BugReport(); const BugType& getBugType() const { return BT; } - BugType& getBugType() { return BT; } + //BugType& getBugType() { return BT; } /// True when the report has an execution path associated with it. /// @@ -350,6 +352,13 @@ public: visitor_iterator visitor_begin() { return Callbacks.begin(); } visitor_iterator visitor_end() { return Callbacks.end(); } + /// Notes that the condition of the CFGBlock associated with \p Cond is + /// being tracked. + /// \returns false if the condition is already being tracked. + bool addTrackedCondition(const ExplodedNode *Cond) { + return TrackedConditions.insert(Cond).second; + } + /// Profile to identify equivalent bug reports for error report coalescing. /// Reports are uniqued to ensure that we do not emit multiple diagnostics /// for each bug. @@ -481,7 +490,7 @@ public: return {}; } - void Register(BugType *BT); + void Register(const BugType *BT); /// Add the given report to the set of reports tracked by BugReporter. /// @@ -593,6 +602,63 @@ public: NodeMapClosure& getNodeResolver() { return NMC; } }; + +/// The tag upon which the TagVisitor reacts. Add these in order to display +/// additional PathDiagnosticEventPieces along the path. +class NoteTag : public ProgramPointTag { +public: + using Callback = + std::function<std::string(BugReporterContext &, BugReport &)>; + +private: + static int Kind; + + const Callback Cb; + const bool IsPrunable; + + NoteTag(Callback &&Cb, bool IsPrunable) + : ProgramPointTag(&Kind), Cb(std::move(Cb)), IsPrunable(IsPrunable) {} + +public: + static bool classof(const ProgramPointTag *T) { + return T->getTagKind() == &Kind; + } + + Optional<std::string> generateMessage(BugReporterContext &BRC, + BugReport &R) const { + std::string Msg = Cb(BRC, R); + if (Msg.empty()) + return None; + + return std::move(Msg); + } + + StringRef getTagDescription() const override { + // TODO: Remember a few examples of generated messages + // and display them in the ExplodedGraph dump by + // returning them from this function. + return "Note Tag"; + } + + bool isPrunable() const { return IsPrunable; } + + // Manage memory for NoteTag objects. + class Factory { + std::vector<std::unique_ptr<NoteTag>> Tags; + + public: + const NoteTag *makeNoteTag(Callback &&Cb, bool IsPrunable = false) { + // We cannot use make_unique because we cannot access the private + // constructor from inside it. + std::unique_ptr<NoteTag> T(new NoteTag(std::move(Cb), IsPrunable)); + Tags.push_back(std::move(T)); + return Tags.back().get(); + } + }; + + friend class TagVisitor; +}; + } // namespace ento } // namespace clang diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h index c023ed5641a3..ef5d327d39da 100644 --- a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h +++ b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h @@ -1,9 +1,8 @@ //===- BugReporterVisitors.h - Generate PathDiagnostics ---------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -15,6 +14,7 @@ #ifndef LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_BUGREPORTERVISITORS_H #define LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_BUGREPORTERVISITORS_H +#include "clang/Analysis/ProgramPoint.h" #include "clang/Basic/LLVM.h" #include "clang/StaticAnalyzer/Core/PathSensitive/RangedConstraintManager.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" @@ -189,22 +189,40 @@ public: BugReporterContext &BRC); std::shared_ptr<PathDiagnosticPiece> - VisitTrueTest(const Expr *Cond, bool tookTrue, BugReporterContext &BRC, - BugReport &R, const ExplodedNode *N); + VisitTrueTest(const Expr *Cond, BugReporterContext &BRC, BugReport &R, + const ExplodedNode *N, bool TookTrue); std::shared_ptr<PathDiagnosticPiece> - VisitTrueTest(const Expr *Cond, const DeclRefExpr *DR, const bool tookTrue, - BugReporterContext &BRC, BugReport &R, const ExplodedNode *N); + VisitTrueTest(const Expr *Cond, const DeclRefExpr *DR, + BugReporterContext &BRC, BugReport &R, const ExplodedNode *N, + bool TookTrue, bool IsAssuming); std::shared_ptr<PathDiagnosticPiece> VisitTrueTest(const Expr *Cond, const BinaryOperator *BExpr, - const bool tookTrue, BugReporterContext &BRC, BugReport &R, - const ExplodedNode *N); + BugReporterContext &BRC, BugReport &R, const ExplodedNode *N, + bool TookTrue, bool IsAssuming); + + std::shared_ptr<PathDiagnosticPiece> + VisitTrueTest(const Expr *Cond, const MemberExpr *ME, BugReporterContext &BRC, + BugReport &R, const ExplodedNode *N, bool TookTrue, + bool IsAssuming); std::shared_ptr<PathDiagnosticPiece> VisitConditionVariable(StringRef LhsString, const Expr *CondVarExpr, - const bool tookTrue, BugReporterContext &BRC, - BugReport &R, const ExplodedNode *N); + BugReporterContext &BRC, BugReport &R, + const ExplodedNode *N, bool TookTrue); + + /// Tries to print the value of the given expression. + /// + /// \param CondVarExpr The expression to print its value. + /// \param Out The stream to print. + /// \param N The node where we encountered the condition. + /// \param TookTrue Whether we took the \c true branch of the condition. + /// + /// \return Whether the print was successful. (The printing is successful if + /// we model the value and we could obtain it.) + bool printValue(const Expr *CondVarExpr, raw_ostream &Out, + const ExplodedNode *N, bool TookTrue, bool IsAssuming); bool patternMatch(const Expr *Ex, const Expr *ParentEx, @@ -212,7 +230,8 @@ public: BugReporterContext &BRC, BugReport &R, const ExplodedNode *N, - Optional<bool> &prunable); + Optional<bool> &prunable, + bool IsSameFieldName); static bool isPieceMessageGeneric(const PathDiagnosticPiece *Piece); }; @@ -294,34 +313,6 @@ public: BugReport &BR) override; }; -class CXXSelfAssignmentBRVisitor final : public BugReporterVisitor { - bool Satisfied = false; - -public: - CXXSelfAssignmentBRVisitor() = default; - - void Profile(llvm::FoldingSetNodeID &ID) const override {} - - std::shared_ptr<PathDiagnosticPiece> VisitNode(const ExplodedNode *Succ, - BugReporterContext &BRC, - BugReport &BR) override; -}; - -/// The bug visitor prints a diagnostic message at the location where a given -/// variable was tainted. -class TaintBugVisitor final : public BugReporterVisitor { -private: - const SVal V; - -public: - TaintBugVisitor(const SVal V) : V(V) {} - void Profile(llvm::FoldingSetNodeID &ID) const override { ID.Add(V); } - - std::shared_ptr<PathDiagnosticPiece> VisitNode(const ExplodedNode *N, - BugReporterContext &BRC, - BugReport &BR) override; -}; - /// The bug visitor will walk all the nodes in a path and collect all the /// constraints. When it reaches the root node, will create a refutation /// manager and check if the constraints are satisfiable @@ -343,6 +334,17 @@ public: BugReport &BR) override; }; + +/// The visitor detects NoteTags and displays the event notes they contain. +class TagVisitor : public BugReporterVisitor { +public: + void Profile(llvm::FoldingSetNodeID &ID) const override; + + std::shared_ptr<PathDiagnosticPiece> VisitNode(const ExplodedNode *N, + BugReporterContext &BRC, + BugReport &R) override; +}; + namespace bugreporter { /// Attempts to add visitors to track expression value back to its point of diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h b/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h index 727ec7c66a89..324b5312e790 100644 --- a/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h +++ b/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h @@ -1,9 +1,8 @@ //===--- BugType.h - Bug Information Description ---------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -38,12 +37,14 @@ private: virtual void anchor(); public: - BugType(CheckName Check, StringRef Name, StringRef Cat) + BugType(CheckName Check, StringRef Name, StringRef Cat, + bool SuppressOnSink=false) : Check(Check), Name(Name), Category(Cat), Checker(nullptr), - SuppressOnSink(false) {} - BugType(const CheckerBase *Checker, StringRef Name, StringRef Cat) + SuppressOnSink(SuppressOnSink) {} + BugType(const CheckerBase *Checker, StringRef Name, StringRef Cat, + bool SuppressOnSink=false) : Check(Checker->getCheckName()), Name(Name), Category(Cat), - Checker(Checker), SuppressOnSink(false) {} + Checker(Checker), SuppressOnSink(SuppressOnSink) {} virtual ~BugType() = default; StringRef getName() const { return Name; } @@ -64,7 +65,6 @@ public: /// type should be suppressed if the end node of the report is post-dominated /// by a sink node. bool isSuppressOnSink() const { return SuppressOnSink; } - void setSuppressOnSink(bool x) { SuppressOnSink = x; } }; class BuiltinBug : public BugType { diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/CommonBugCategories.h b/include/clang/StaticAnalyzer/Core/BugReporter/CommonBugCategories.h index d07525661a6c..85526eb49f0c 100644 --- a/include/clang/StaticAnalyzer/Core/BugReporter/CommonBugCategories.h +++ b/include/clang/StaticAnalyzer/Core/BugReporter/CommonBugCategories.h @@ -1,9 +1,8 @@ //=--- CommonBugCategories.h - Provides common issue categories -*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h b/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h index e9c682d7986c..5230742a4aa4 100644 --- a/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h +++ b/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h @@ -1,9 +1,8 @@ //===- PathDiagnostic.h - Path-Specific Diagnostic Handling -----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -314,6 +313,8 @@ public: bool hasRange() const { return K == StmtK || K == RangeK || K == DeclK; } + bool hasValidLocation() const { return asLocation().isValid(); } + void invalidate() { *this = PathDiagnosticLocation(); } @@ -366,7 +367,7 @@ public: class PathDiagnosticPiece: public llvm::FoldingSetNode { public: - enum Kind { ControlFlow, Event, Macro, Call, Note }; + enum Kind { ControlFlow, Event, Macro, Call, Note, PopUp }; enum DisplayHint { Above, Below }; private: @@ -469,7 +470,7 @@ public: PathDiagnosticPiece::Kind k, bool addPosRange = true) : PathDiagnosticPiece(s, k), Pos(pos) { - assert(Pos.isValid() && Pos.asLocation().isValid() && + assert(Pos.isValid() && Pos.hasValidLocation() && "PathDiagnosticSpotPiece's must have a valid location."); if (addPosRange && Pos.hasRange()) addRange(Pos.asRange()); } @@ -481,7 +482,7 @@ public: static bool classof(const PathDiagnosticPiece *P) { return P->getKind() == Event || P->getKind() == Macro || - P->getKind() == Note; + P->getKind() == Note || P->getKind() == PopUp; } }; @@ -745,7 +746,7 @@ public: class PathDiagnosticNotePiece: public PathDiagnosticSpotPiece { public: PathDiagnosticNotePiece(const PathDiagnosticLocation &Pos, StringRef S, - bool AddPosRange = true) + bool AddPosRange = true) : PathDiagnosticSpotPiece(Pos, S, Note, AddPosRange) {} ~PathDiagnosticNotePiece() override; @@ -758,6 +759,22 @@ public: void Profile(llvm::FoldingSetNodeID &ID) const override; }; +class PathDiagnosticPopUpPiece: public PathDiagnosticSpotPiece { +public: + PathDiagnosticPopUpPiece(const PathDiagnosticLocation &Pos, StringRef S, + bool AddPosRange = true) + : PathDiagnosticSpotPiece(Pos, S, PopUp, AddPosRange) {} + ~PathDiagnosticPopUpPiece() override; + + static bool classof(const PathDiagnosticPiece *P) { + return P->getKind() == PopUp; + } + + void dump() const override; + + void Profile(llvm::FoldingSetNodeID &ID) const override; +}; + /// File IDs mapped to sets of line numbers. using FilesToLineNumsMap = std::map<FileID, std::set<unsigned>>; diff --git a/include/clang/StaticAnalyzer/Core/Checker.h b/include/clang/StaticAnalyzer/Core/Checker.h index 786465cee855..d0fe15f8b896 100644 --- a/include/clang/StaticAnalyzer/Core/Checker.h +++ b/include/clang/StaticAnalyzer/Core/Checker.h @@ -1,9 +1,8 @@ //== Checker.h - Registration mechanism for checkers -------------*- C++ -*--=// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -15,6 +14,7 @@ #define LLVM_CLANG_STATICANALYZER_CORE_CHECKER_H #include "clang/Analysis/ProgramPoint.h" +#include "clang/Basic/LangOptions.h" #include "clang/StaticAnalyzer/Core/CheckerManager.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" #include "llvm/Support/Casting.h" @@ -474,8 +474,9 @@ public: class Call { template <typename CHECKER> - static bool _evalCall(void *checker, const CallExpr *CE, CheckerContext &C) { - return ((const CHECKER *)checker)->evalCall(CE, C); + static bool _evalCall(void *checker, const CallEvent &Call, + CheckerContext &C) { + return ((const CHECKER *)checker)->evalCall(Call, C); } public: diff --git a/include/clang/StaticAnalyzer/Core/CheckerManager.h b/include/clang/StaticAnalyzer/Core/CheckerManager.h index 538ed19f7eef..6cc4baa1687f 100644 --- a/include/clang/StaticAnalyzer/Core/CheckerManager.h +++ b/include/clang/StaticAnalyzer/Core/CheckerManager.h @@ -1,9 +1,8 @@ //===- CheckerManager.h - Static Analyzer Checker Manager -------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -137,12 +136,18 @@ public: AnalyzerOptions &getAnalyzerOptions() { return AOptions; } ASTContext &getASTContext() { return Context; } + /// Emits an error through a DiagnosticsEngine about an invalid user supplied + /// checker option value. + void reportInvalidCheckerOptionValue(const CheckerBase *C, + StringRef OptionName, + StringRef ExpectedValueDesc); + using CheckerRef = CheckerBase *; using CheckerTag = const void *; using CheckerDtor = CheckerFn<void ()>; //===----------------------------------------------------------------------===// -// registerChecker +// Checker registration. //===----------------------------------------------------------------------===// /// Used to register checkers. @@ -154,8 +159,7 @@ public: CHECKER *registerChecker(AT &&... Args) { CheckerTag tag = getTag<CHECKER>(); CheckerRef &ref = CheckerTags[tag]; - if (ref) - return static_cast<CHECKER *>(ref); // already registered. + assert(!ref && "Checker already registered, use getChecker!"); CHECKER *checker = new CHECKER(std::forward<AT>(Args)...); checker->Name = CurrentCheckName; @@ -165,8 +169,17 @@ public: return checker; } + template <typename CHECKER> + CHECKER *getChecker() { + CheckerTag tag = getTag<CHECKER>(); + assert(CheckerTags.count(tag) != 0 && + "Requested checker is not registered! Maybe you should add it as a " + "dependency in Checkers.td?"); + return static_cast<CHECKER *>(CheckerTags[tag]); + } + //===----------------------------------------------------------------------===// -// Functions for running checkers for AST traversing.. +// Functions for running checkers for AST traversing. //===----------------------------------------------------------------------===// /// Run checkers handling Decls. @@ -393,16 +406,20 @@ public: /// /// Unlike most other callbacks, any checker can simply implement the virtual /// method CheckerBase::printState if it has custom data to print. - /// \param Out The output stream + /// + /// \param Out The output stream /// \param State The state being printed - /// \param NL The preferred representation of a newline. - /// \param Sep The preferred separator between different kinds of data. - void runCheckersForPrintState(raw_ostream &Out, ProgramStateRef State, - const char *NL, const char *Sep); - -//===----------------------------------------------------------------------===// -// Internal registration functions for AST traversing. -//===----------------------------------------------------------------------===// + /// \param NL The preferred representation of a newline. + /// \param Space The preferred space between the left side and the message. + /// \param IsDot Whether the message will be printed in 'dot' format. + void runCheckersForPrintStateJson(raw_ostream &Out, ProgramStateRef State, + const char *NL = "\n", + unsigned int Space = 0, + bool IsDot = false) const; + + //===----------------------------------------------------------------------===// + // Internal registration functions for AST traversing. + //===----------------------------------------------------------------------===// // Functions used by the registration mechanism, checkers should not touch // these directly. @@ -473,7 +490,7 @@ public: CheckerFn<ProgramStateRef (ProgramStateRef, const SVal &cond, bool assumption)>; - using EvalCallFunc = CheckerFn<bool (const CallExpr *, CheckerContext &)>; + using EvalCallFunc = CheckerFn<bool (const CallEvent &, CheckerContext &)>; using CheckEndOfTranslationUnit = CheckerFn<void (const TranslationUnitDecl *, AnalysisManager &, diff --git a/include/clang/StaticAnalyzer/Core/IssueHash.h b/include/clang/StaticAnalyzer/Core/IssueHash.h index 03997aae79ae..38d5f847fc29 100644 --- a/include/clang/StaticAnalyzer/Core/IssueHash.h +++ b/include/clang/StaticAnalyzer/Core/IssueHash.h @@ -1,9 +1,8 @@ //===---------- IssueHash.h - Generate identification hashes ----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_STATICANALYZER_CORE_ISSUE_HASH_H diff --git a/include/clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h b/include/clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h index 2e81aa38c8de..ef6e7e0f45d5 100644 --- a/include/clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h +++ b/include/clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h @@ -1,9 +1,8 @@ //===--- PathDiagnosticConsumers.h - Path Diagnostic Clients ------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h b/include/clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h index 243795e720f6..4b7d6054cd87 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h @@ -1,9 +1,8 @@ //== APSIntType.h - Simple record of the type of APSInts --------*- C++ -*--==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h index 50b9b566edc3..b0dda78a00a9 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h @@ -1,9 +1,8 @@ //== AnalysisManager.h - Path sensitive analysis data manager ------*- C++ -*-// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h b/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h index 1c5d4eb2de32..ac218bc070e9 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h @@ -1,9 +1,8 @@ //==- BasicValueFactory.h - Basic values for Path Sens analysis --*- C++ -*-==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/BlockCounter.h b/include/clang/StaticAnalyzer/Core/PathSensitive/BlockCounter.h index 5e831095abc7..46ff69e0c396 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/BlockCounter.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/BlockCounter.h @@ -1,9 +1,8 @@ //==- BlockCounter.h - ADT for counting block visits ---------------*- C++ -*-// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h b/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h index 81dd83fc1071..db84102983af 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h @@ -1,9 +1,8 @@ //===- CallEvent.h - Wrapper for all function and method calls --*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -72,39 +71,7 @@ enum CallEventKind { }; class CallEvent; - -/// This class represents a description of a function call using the number of -/// arguments and the name of the function. -class CallDescription { - friend CallEvent; - - mutable IdentifierInfo *II = nullptr; - mutable bool IsLookupDone = false; - // The list of the qualified names used to identify the specified CallEvent, - // e.g. "{a, b}" represent the qualified names, like "a::b". - std::vector<const char *> QualifiedName; - unsigned RequiredArgs; - -public: - const static unsigned NoArgRequirement = std::numeric_limits<unsigned>::max(); - - /// Constructs a CallDescription object. - /// - /// @param QualifiedName The list of the name qualifiers of the function that - /// will be matched. The user is allowed to skip any of the qualifiers. - /// For example, {"std", "basic_string", "c_str"} would match both - /// std::basic_string<...>::c_str() and std::__1::basic_string<...>::c_str(). - /// - /// @param RequiredArgs The number of arguments that is expected to match a - /// call. Omit this parameter to match every occurrence of call with a given - /// name regardless the number of arguments. - CallDescription(ArrayRef<const char *> QualifiedName, - unsigned RequiredArgs = NoArgRequirement) - : QualifiedName(QualifiedName), RequiredArgs(RequiredArgs) {} - - /// Get the name of the function that this object matches. - StringRef getFunctionName() const { return QualifiedName.back(); } -}; +class CallDescription; template<typename T = CallEvent> class CallEventRef : public IntrusiveRefCntPtr<const T> { @@ -1077,6 +1044,85 @@ public: } }; +enum CallDescriptionFlags : int { + /// Describes a C standard function that is sometimes implemented as a macro + /// that expands to a compiler builtin with some __builtin prefix. + /// The builtin may as well have a few extra arguments on top of the requested + /// number of arguments. + CDF_MaybeBuiltin = 1 << 0, +}; + +/// This class represents a description of a function call using the number of +/// arguments and the name of the function. +class CallDescription { + friend CallEvent; + + mutable IdentifierInfo *II = nullptr; + mutable bool IsLookupDone = false; + // The list of the qualified names used to identify the specified CallEvent, + // e.g. "{a, b}" represent the qualified names, like "a::b". + std::vector<const char *> QualifiedName; + Optional<unsigned> RequiredArgs; + int Flags; + +public: + /// Constructs a CallDescription object. + /// + /// @param QualifiedName The list of the name qualifiers of the function that + /// will be matched. The user is allowed to skip any of the qualifiers. + /// For example, {"std", "basic_string", "c_str"} would match both + /// std::basic_string<...>::c_str() and std::__1::basic_string<...>::c_str(). + /// + /// @param RequiredArgs The number of arguments that is expected to match a + /// call. Omit this parameter to match every occurrence of call with a given + /// name regardless the number of arguments. + CallDescription(int Flags, ArrayRef<const char *> QualifiedName, + Optional<unsigned> RequiredArgs = None) + : QualifiedName(QualifiedName), RequiredArgs(RequiredArgs), + Flags(Flags) {} + + /// Construct a CallDescription with default flags. + CallDescription(ArrayRef<const char *> QualifiedName, + Optional<unsigned> RequiredArgs = None) + : CallDescription(0, QualifiedName, RequiredArgs) {} + + /// Get the name of the function that this object matches. + StringRef getFunctionName() const { return QualifiedName.back(); } +}; + +/// An immutable map from CallDescriptions to arbitrary data. Provides a unified +/// way for checkers to react on function calls. +template <typename T> class CallDescriptionMap { + // Some call descriptions aren't easily hashable (eg., the ones with qualified + // names in which some sections are omitted), so let's put them + // in a simple vector and use linear lookup. + // TODO: Implement an actual map for fast lookup for "hashable" call + // descriptions (eg., the ones for C functions that just match the name). + std::vector<std::pair<CallDescription, T>> LinearMap; + +public: + CallDescriptionMap( + std::initializer_list<std::pair<CallDescription, T>> &&List) + : LinearMap(List) {} + + ~CallDescriptionMap() = default; + + // These maps are usually stored once per checker, so let's make sure + // we don't do redundant copies. + CallDescriptionMap(const CallDescriptionMap &) = delete; + CallDescriptionMap &operator=(const CallDescription &) = delete; + + const T *lookup(const CallEvent &Call) const { + // Slow path: linear lookup. + // TODO: Implement some sort of fast path. + for (const std::pair<CallDescription, T> &I : LinearMap) + if (Call.isCalled(I.first)) + return &I.second; + + return nullptr; + } +}; + /// Manages the lifetime of CallEvent objects. /// /// CallEventManager provides a way to create arbitrary CallEvents "on the diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h b/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h index 6ee75b738465..981133e66977 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h @@ -1,9 +1,8 @@ //== CheckerContext.h - Context info for path-sensitive checkers--*- C++ -*--=// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -220,6 +219,45 @@ public: Eng.getBugReporter().emitReport(std::move(R)); } + /// Produce a program point tag that displays an additional path note + /// to the user. This is a lightweight alternative to the + /// BugReporterVisitor mechanism: instead of visiting the bug report + /// node-by-node to restore the sequence of events that led to discovering + /// a bug, you can add notes as you add your transitions. + /// + /// @param Cb Callback with 'BugReporterContext &, BugReport &' parameters. + /// @param IsPrunable Whether the note is prunable. It allows BugReporter + /// to omit the note from the report if it would make the displayed + /// bug path significantly shorter. + const NoteTag *getNoteTag(NoteTag::Callback &&Cb, bool IsPrunable = false) { + return Eng.getNoteTags().makeNoteTag(std::move(Cb), IsPrunable); + } + + /// A shorthand version of getNoteTag that doesn't require you to accept + /// the BugReporterContext arguments when you don't need it. + /// + /// @param Cb Callback only with 'BugReport &' parameter. + /// @param IsPrunable Whether the note is prunable. It allows BugReporter + /// to omit the note from the report if it would make the displayed + /// bug path significantly shorter. + const NoteTag *getNoteTag(std::function<std::string(BugReport &)> &&Cb, + bool IsPrunable = false) { + return getNoteTag( + [Cb](BugReporterContext &, BugReport &BR) { return Cb(BR); }, + IsPrunable); + } + + /// A shorthand version of getNoteTag that accepts a plain note. + /// + /// @param Note The note. + /// @param IsPrunable Whether the note is prunable. It allows BugReporter + /// to omit the note from the report if it would make the displayed + /// bug path significantly shorter. + const NoteTag *getNoteTag(StringRef Note, bool IsPrunable = false) { + return getNoteTag( + [Note](BugReporterContext &, BugReport &) { return Note; }, IsPrunable); + } + /// Returns the word that should be used to refer to the declaration /// in the report. StringRef getDeclDescription(const Decl *D); diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h b/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h index 7f34a7a5b19d..b53c042a1ca1 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h @@ -1,9 +1,8 @@ //== CheckerHelpers.h - Helper functions for checkers ------------*- C++ -*--=// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h index d4f8fbaa43df..f85c37379158 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h @@ -1,9 +1,8 @@ //===- ConstraintManager.h - Constraints on symbolic values. ----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -80,6 +79,9 @@ public: ConstraintManager() = default; virtual ~ConstraintManager(); + virtual bool haveEqualConstraints(ProgramStateRef S1, + ProgramStateRef S2) const = 0; + virtual ProgramStateRef assume(ProgramStateRef state, DefinedSVal Cond, bool Assumption) = 0; @@ -160,12 +162,9 @@ public: virtual ProgramStateRef removeDeadBindings(ProgramStateRef state, SymbolReaper& SymReaper) = 0; - virtual void print(ProgramStateRef state, - raw_ostream &Out, - const char* nl, - const char *sep) = 0; - - virtual void EndPath(ProgramStateRef state) {} + virtual void printJson(raw_ostream &Out, ProgramStateRef State, + const char *NL, unsigned int Space, + bool IsDot) const = 0; /// Convenience method to query the state to see if a symbol is null or /// not null, or if neither assumption can be made. diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h index 17369a85bfa3..278193ef99ed 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h @@ -1,9 +1,8 @@ //===- CoreEngine.h - Path-Sensitive Dataflow Engine ------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -20,6 +19,7 @@ #include "clang/Analysis/CFG.h" #include "clang/Analysis/ProgramPoint.h" #include "clang/Basic/LLVM.h" +#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" #include "clang/StaticAnalyzer/Core/PathSensitive/BlockCounter.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h" @@ -96,6 +96,10 @@ private: /// (This data is owned by AnalysisConsumer.) FunctionSummariesTy *FunctionSummaries; + /// Add path note tags along the path when we see that something interesting + /// is happening. This field is the allocator for such tags. + NoteTag::Factory NoteTags; + void generateNode(const ProgramPoint &Loc, ProgramStateRef State, ExplodedNode *Pred); @@ -117,6 +121,8 @@ private: void HandleStaticInit(const DeclStmt *DS, const CFGBlock *B, ExplodedNode *Pred); + void HandleVirtualBaseBranch(const CFGBlock *B, ExplodedNode *Pred); + private: ExplodedNode *generateCallExitBeginNode(ExplodedNode *N, const ReturnStmt *RS); @@ -193,9 +199,11 @@ public: /// Enqueue a single node created as a result of statement processing. void enqueueStmtNode(ExplodedNode *N, const CFGBlock *Block, unsigned Idx); + + NoteTag::Factory &getNoteTags() { return NoteTags; } }; -// TODO: Turn into a calss. +// TODO: Turn into a class. struct NodeBuilderContext { const CoreEngine &Eng; const CFGBlock *Block; diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeInfo.h b/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeInfo.h index 092e23ce73c8..9bb1e2137566 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeInfo.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeInfo.h @@ -1,9 +1,8 @@ //== DynamicTypeInfo.h - Runtime type information ----------------*- C++ -*--=// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_DYNAMICTYPEINFO_H diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeMap.h b/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeMap.h index b0d514dc2863..a84b24872061 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeMap.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeMap.h @@ -1,9 +1,8 @@ //===- DynamicTypeMap.h - Dynamic type map ----------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -30,12 +29,11 @@ class MemRegion; /// symbol to its most likely type. struct DynamicTypeMap {}; -using DynamicTypeMapImpl = - llvm::ImmutableMap<const MemRegion *, DynamicTypeInfo>; +using DynamicTypeMapTy = llvm::ImmutableMap<const MemRegion *, DynamicTypeInfo>; template <> struct ProgramStateTrait<DynamicTypeMap> - : public ProgramStatePartialTrait<DynamicTypeMapImpl> { + : public ProgramStatePartialTrait<DynamicTypeMapTy> { static void *GDMIndex(); }; @@ -55,8 +53,9 @@ inline ProgramStateRef setDynamicTypeInfo(ProgramStateRef State, DynamicTypeInfo(NewTy, CanBeSubClassed)); } -void printDynamicTypeInfo(ProgramStateRef State, raw_ostream &Out, - const char *NL, const char *Sep); +void printDynamicTypeInfoJson(raw_ostream &Out, ProgramStateRef State, + const char *NL = "\n", unsigned int Space = 0, + bool IsDot = false); } // namespace ento } // namespace clang diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h b/include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h index 6d498031bea0..498e36e1431f 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h @@ -1,9 +1,8 @@ //===- Environment.h - Map from Stmt* to Locations/Values -------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -92,9 +91,9 @@ public: return ExprBindings == RHS.ExprBindings; } - void print(raw_ostream &Out, const char *NL, const char *Sep, - const ASTContext &Context, - const LocationContext *WithLC = nullptr) const; + void printJson(raw_ostream &Out, const ASTContext &Ctx, + const LocationContext *LCtx = nullptr, const char *NL = "\n", + unsigned int Space = 0, bool IsDot = false) const; }; class EnvironmentManager { diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h index bf460df278aa..727d04cba278 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h @@ -1,9 +1,8 @@ //===- ExplodedGraph.h - Local, Path-Sens. "Exploded Graph" -----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h index 86b776afb822..2629d7121de4 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h @@ -1,9 +1,8 @@ //===- ExprEngine.h - Path-Sensitive Expression-Level Dataflow --*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -23,6 +22,7 @@ #include "clang/Analysis/ProgramPoint.h" #include "clang/Basic/LLVM.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" +#include "clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h" #include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h" #include "clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h" #include "clang/StaticAnalyzer/Core/PathSensitive/FunctionSummary.h" @@ -131,6 +131,9 @@ private: /// SymMgr - Object that manages the symbol information. SymbolManager &SymMgr; + /// MRMgr - MemRegionManager object that creates memory regions. + MemRegionManager &MRMgr; + /// svalBuilder - SValBuilder object that creates SVals from expressions. SValBuilder &svalBuilder; @@ -158,7 +161,7 @@ public: SetOfConstDecls *VisitedCalleesIn, FunctionSummariesTy *FS, InliningModes HowToInlineIn); - ~ExprEngine() override; + ~ExprEngine() override = default; /// Returns true if there is still simulation state on the worklist. bool ExecuteWorkList(const LocationContext *L, unsigned Steps = 150000) { @@ -180,6 +183,10 @@ public: AnalysisManager &getAnalysisManager() override { return AMgr; } + AnalysisDeclContextManager &getAnalysisDeclContextManager() { + return AMgr.getAnalysisDeclContextManager(); + } + CheckerManager &getCheckerManager() const { return *AMgr.getCheckerManager(); } @@ -369,10 +376,10 @@ public: const LocationContext *LCtx, const CallEvent *Call) override; - /// printState - Called by ProgramStateManager to print checker-specific data. - void printState(raw_ostream &Out, ProgramStateRef State, const char *NL, - const char *Sep, - const LocationContext *LCtx = nullptr) override; + /// printJson - Called by ProgramStateManager to print checker-specific data. + void printJson(raw_ostream &Out, ProgramStateRef State, + const LocationContext *LCtx, const char *NL, + unsigned int Space, bool IsDot) const override; ProgramStateManager &getStateManager() override { return StateMgr; } @@ -387,9 +394,11 @@ public: return StateMgr.getBasicVals(); } - // FIXME: Remove when we migrate over to just using ValueManager. SymbolManager &getSymbolManager() { return SymMgr; } - const SymbolManager &getSymbolManager() const { return SymMgr; } + MemRegionManager &getRegionManager() { return MRMgr; } + + NoteTag::Factory &getNoteTags() { return Engine.getNoteTags(); } + // Functions for external checking of whether we have unfinished work bool wasBlocksExhausted() const { return Engine.wasBlocksExhausted(); } @@ -707,6 +716,25 @@ private: AnalyzerOptions &Opts, const EvalCallOptions &CallOpts); + /// See if the given AnalysisDeclContext is built for a function that we + /// should always inline simply because it's small enough. + /// Apart from "small" functions, we also have "large" functions + /// (cf. isLarge()), some of which are huge (cf. isHuge()), and we classify + /// the remaining functions as "medium". + bool isSmall(AnalysisDeclContext *ADC) const; + + /// See if the given AnalysisDeclContext is built for a function that we + /// should inline carefully because it looks pretty large. + bool isLarge(AnalysisDeclContext *ADC) const; + + /// See if the given AnalysisDeclContext is built for a function that we + /// should never inline because it's legit gigantic. + bool isHuge(AnalysisDeclContext *ADC) const; + + /// See if the given AnalysisDeclContext is built for a function that we + /// should inline, just by looking at the declaration of the function. + bool mayInlineDecl(AnalysisDeclContext *ADC) const; + /// Checks our policies and decides weither the given call should be inlined. bool shouldInlineCall(const CallEvent &Call, const Decl *D, const ExplodedNode *Pred, diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/FunctionSummary.h b/include/clang/StaticAnalyzer/Core/PathSensitive/FunctionSummary.h index b70faa10f0b2..53b4bf605871 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/FunctionSummary.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/FunctionSummary.h @@ -1,9 +1,8 @@ //===- FunctionSummary.h - Stores summaries of functions. -------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/LoopUnrolling.h b/include/clang/StaticAnalyzer/Core/PathSensitive/LoopUnrolling.h index a4c505ce5f23..d25d26435454 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/LoopUnrolling.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/LoopUnrolling.h @@ -1,9 +1,8 @@ //===--- LoopUnrolling.h - Unroll loops -------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// /// diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/LoopWidening.h b/include/clang/StaticAnalyzer/Core/PathSensitive/LoopWidening.h index f494c5d6dab8..7484a51b1eda 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/LoopWidening.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/LoopWidening.h @@ -1,9 +1,8 @@ //===--- LoopWidening.h - Widen loops ---------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// /// diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h b/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h index 3d0ff4efa1d7..071e35085a5f 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h @@ -1,9 +1,8 @@ //==- MemRegion.h - Abstract memory regions for static analysis -*- C++ -*--==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -774,9 +773,6 @@ class SymbolicRegion : public SubRegion { assert(s->getType()->isAnyPointerType() || s->getType()->isReferenceType() || s->getType()->isBlockPointerType()); - - // populateWorklistFromSymbol() relies on this assertion, and needs to be - // updated if more cases are introduced. assert(isa<UnknownSpaceRegion>(sreg) || isa<HeapSpaceRegion>(sreg)); } @@ -912,7 +908,7 @@ protected: DeclRegion(const ValueDecl *d, const MemRegion *sReg, Kind k) : TypedValueRegion(sReg, k), D(d) { assert(classof(this)); - assert(d); + assert(d && d->isCanonicalDecl()); } static void ProfileRegion(llvm::FoldingSetNodeID& ID, const Decl *D, diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h index c3a7028d8755..d38058f9af56 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h @@ -1,9 +1,8 @@ //== ProgramState.h - Path-sensitive "State" for tracking values -*- C++ -*--=// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -21,7 +20,6 @@ #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h" #include "clang/StaticAnalyzer/Core/PathSensitive/Store.h" -#include "clang/StaticAnalyzer/Core/PathSensitive/TaintTag.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/ImmutableMap.h" #include "llvm/Support/Allocator.h" @@ -44,7 +42,6 @@ typedef std::unique_ptr<ConstraintManager>(*ConstraintManagerCreator)( ProgramStateManager &, SubEngine *); typedef std::unique_ptr<StoreManager>(*StoreManagerCreator)( ProgramStateManager &); -typedef llvm::ImmutableMap<const SubRegion*, TaintTagType> TaintedSubRegions; //===----------------------------------------------------------------------===// // ProgramStateTrait - Traits used by the Generic Data Map of a ProgramState. @@ -368,38 +365,6 @@ public: template <typename CB> CB scanReachableSymbols(llvm::iterator_range<region_iterator> Reachable) const; - /// Create a new state in which the statement is marked as tainted. - LLVM_NODISCARD ProgramStateRef - addTaint(const Stmt *S, const LocationContext *LCtx, - TaintTagType Kind = TaintTagGeneric) const; - - /// Create a new state in which the value is marked as tainted. - LLVM_NODISCARD ProgramStateRef - addTaint(SVal V, TaintTagType Kind = TaintTagGeneric) const; - - /// Create a new state in which the symbol is marked as tainted. - LLVM_NODISCARD ProgramStateRef addTaint(SymbolRef S, - TaintTagType Kind = TaintTagGeneric) const; - - /// Create a new state in which the region symbol is marked as tainted. - LLVM_NODISCARD ProgramStateRef - addTaint(const MemRegion *R, TaintTagType Kind = TaintTagGeneric) const; - - /// Create a new state in a which a sub-region of a given symbol is tainted. - /// This might be necessary when referring to regions that can not have an - /// individual symbol, e.g. if they are represented by the default binding of - /// a LazyCompoundVal. - LLVM_NODISCARD ProgramStateRef - addPartialTaint(SymbolRef ParentSym, const SubRegion *SubRegion, - TaintTagType Kind = TaintTagGeneric) const; - - /// Check if the statement is tainted in the current state. - bool isTainted(const Stmt *S, const LocationContext *LCtx, - TaintTagType Kind = TaintTagGeneric) const; - bool isTainted(SVal V, TaintTagType Kind = TaintTagGeneric) const; - bool isTainted(SymbolRef Sym, TaintTagType Kind = TaintTagGeneric) const; - bool isTainted(const MemRegion *Reg, TaintTagType Kind=TaintTagGeneric) const; - //==---------------------------------------------------------------------==// // Accessing the Generic Data Map (GDM). //==---------------------------------------------------------------------==// @@ -459,14 +424,14 @@ public: } // Pretty-printing. - void print(raw_ostream &Out, const char *nl = "\n", const char *sep = "", - const LocationContext *CurrentLC = nullptr) const; - void printDOT(raw_ostream &Out, - const LocationContext *CurrentLC = nullptr) const; - void printTaint(raw_ostream &Out, const char *nl = "\n") const; + void printJson(raw_ostream &Out, const LocationContext *LCtx = nullptr, + const char *NL = "\n", unsigned int Space = 0, + bool IsDot = false) const; + + void printDOT(raw_ostream &Out, const LocationContext *LCtx = nullptr, + unsigned int Space = 0) const; void dump() const; - void dumpTaint() const; private: friend void ProgramStateRetain(const ProgramState *state); @@ -500,7 +465,6 @@ private: std::unique_ptr<ConstraintManager> ConstraintMgr; ProgramState::GenericDataMap::Factory GDMFactory; - TaintedSubRegions::Factory TSRFactory; typedef llvm::DenseMap<void*,std::pair<void*,void (*)(void*)> > GDMContextsTy; GDMContextsTy GDMContexts; @@ -589,11 +553,15 @@ public: ProgramStateRef getPersistentStateWithGDM(ProgramStateRef FromState, ProgramStateRef GDMState); - bool haveEqualEnvironments(ProgramStateRef S1, ProgramStateRef S2) { + bool haveEqualConstraints(ProgramStateRef S1, ProgramStateRef S2) const { + return ConstraintMgr->haveEqualConstraints(S1, S2); + } + + bool haveEqualEnvironments(ProgramStateRef S1, ProgramStateRef S2) const { return S1->Env == S2->Env; } - bool haveEqualStores(ProgramStateRef S1, ProgramStateRef S2) { + bool haveEqualStores(ProgramStateRef S1, ProgramStateRef S2) const { return S1->store == S2->store; } @@ -666,10 +634,6 @@ public: return ProgramStateTrait<T>::MakeContext(p); } - - void EndPath(ProgramStateRef St) { - ConstraintMgr->EndPath(St); - } }; diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h index 64de736c7e9f..da82a55e3625 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h @@ -1,9 +1,8 @@ //ProgramStateTrait.h - Partial implementations of ProgramStateTrait -*- C++ -*- // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h index 415bb7713d4b..0ea26bf2e509 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h @@ -1,9 +1,8 @@ //== ProgramState_Fwd.h - Incomplete declarations of ProgramState -*- C++ -*--=/ // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/RangedConstraintManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/RangedConstraintManager.h index 1b12a4edc205..a9ca3451d8f3 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/RangedConstraintManager.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/RangedConstraintManager.h @@ -1,9 +1,8 @@ //== RangedConstraintManager.h ----------------------------------*- C++ -*--==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -114,7 +113,8 @@ private: public: RangeSet Intersect(BasicValueFactory &BV, Factory &F, llvm::APSInt Lower, llvm::APSInt Upper) const; - + RangeSet Intersect(BasicValueFactory &BV, Factory &F, + const RangeSet &Other) const; RangeSet Negate(BasicValueFactory &BV, Factory &F) const; void print(raw_ostream &os) const; diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/Regions.def b/include/clang/StaticAnalyzer/Core/PathSensitive/Regions.def index 10f89ecc55a5..3c52c2bc7142 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/Regions.def +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/Regions.def @@ -1,9 +1,8 @@ //===-- Regions.def - Metadata about MemRegion kinds ------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SMTConstraintManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SMTConstraintManager.h index 8eaa9365be1d..1712501b13bd 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SMTConstraintManager.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SMTConstraintManager.h @@ -1,9 +1,8 @@ //== SMTConstraintManager.h -------------------------------------*- C++ -*--==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -15,20 +14,24 @@ #ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SMTCONSTRAINTMANAGER_H #define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SMTCONSTRAINTMANAGER_H +#include "clang/Basic/JsonSupport.h" #include "clang/StaticAnalyzer/Core/PathSensitive/RangedConstraintManager.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SMTConv.h" +typedef llvm::ImmutableSet< + std::pair<clang::ento::SymbolRef, const llvm::SMTExpr *>> + ConstraintSMTType; +REGISTER_TRAIT_WITH_PROGRAMSTATE(ConstraintSMT, ConstraintSMTType) + namespace clang { namespace ento { -template <typename ConstraintSMT, typename SMTExprTy> class SMTConstraintManager : public clang::ento::SimpleConstraintManager { - SMTSolverRef &Solver; + mutable llvm::SMTSolverRef Solver = llvm::CreateZ3Solver(); public: - SMTConstraintManager(clang::ento::SubEngine *SE, clang::ento::SValBuilder &SB, - SMTSolverRef &S) - : SimpleConstraintManager(SE, SB), Solver(S) {} + SMTConstraintManager(clang::ento::SubEngine *SE, clang::ento::SValBuilder &SB) + : SimpleConstraintManager(SE, SB) {} virtual ~SMTConstraintManager() = default; //===------------------------------------------------------------------===// @@ -42,7 +45,8 @@ public: QualType RetTy; bool hasComparison; - SMTExprRef Exp = SMTConv::getExpr(Solver, Ctx, Sym, &RetTy, &hasComparison); + llvm::SMTExprRef Exp = + SMTConv::getExpr(Solver, Ctx, Sym, &RetTy, &hasComparison); // Create zero comparison for implicit boolean cast, with reversed // assumption @@ -78,12 +82,12 @@ public: QualType RetTy; // The expression may be casted, so we cannot call getZ3DataExpr() directly - SMTExprRef VarExp = SMTConv::getExpr(Solver, Ctx, Sym, &RetTy); - SMTExprRef Exp = + llvm::SMTExprRef VarExp = SMTConv::getExpr(Solver, Ctx, Sym, &RetTy); + llvm::SMTExprRef Exp = SMTConv::getZeroExpr(Solver, Ctx, VarExp, RetTy, /*Assumption=*/true); // Negate the constraint - SMTExprRef NotExp = + llvm::SMTExprRef NotExp = SMTConv::getZeroExpr(Solver, Ctx, VarExp, RetTy, /*Assumption=*/false); ConditionTruthVal isSat = checkModel(State, Sym, Exp); @@ -116,7 +120,7 @@ public: // this method tries to get the interpretation (the actual value) from // the solver, which is currently not cached. - SMTExprRef Exp = + llvm::SMTExprRef Exp = SMTConv::fromData(Solver, SD->getSymbolID(), Ty, Ctx.getTypeSize(Ty)); Solver->reset(); @@ -132,7 +136,7 @@ public: return nullptr; // A value has been obtained, check if it is the only value - SMTExprRef NotExp = SMTConv::fromBinOp( + llvm::SMTExprRef NotExp = SMTConv::fromBinOp( Solver, Exp, BO_NE, Ty->isBooleanType() ? Solver->mkBoolean(Value.getBoolValue()) : Solver->mkBitvector(Value, Value.getBitWidth()), @@ -205,17 +209,37 @@ public: return State->set<ConstraintSMT>(CZ); } - void print(ProgramStateRef St, raw_ostream &OS, const char *nl, - const char *sep) override { + void printJson(raw_ostream &Out, ProgramStateRef State, const char *NL = "\n", + unsigned int Space = 0, bool IsDot = false) const override { + ConstraintSMTType Constraints = State->get<ConstraintSMT>(); - auto CZ = St->get<ConstraintSMT>(); + Indent(Out, Space, IsDot) << "\"constraints\": "; + if (Constraints.isEmpty()) { + Out << "null," << NL; + return; + } - OS << nl << sep << "Constraints:"; - for (auto I = CZ.begin(), E = CZ.end(); I != E; ++I) { - OS << nl << ' ' << I->first << " : "; - I->second.print(OS); + ++Space; + Out << '[' << NL; + for (ConstraintSMTType::iterator I = Constraints.begin(); + I != Constraints.end(); ++I) { + Indent(Out, Space, IsDot) + << "{ \"symbol\": \"" << I->first << "\", \"range\": \""; + I->second->print(Out); + Out << "\" }"; + + if (std::next(I) != Constraints.end()) + Out << ','; + Out << NL; } - OS << nl; + + --Space; + Indent(Out, Space, IsDot) << "],"; + } + + bool haveEqualConstraints(ProgramStateRef S1, + ProgramStateRef S2) const override { + return S1->get<ConstraintSMT>() == S2->get<ConstraintSMT>(); } bool canReasonAbout(SVal X) const override { @@ -270,11 +294,10 @@ public: protected: // Check whether a new model is satisfiable, and update the program state. virtual ProgramStateRef assumeExpr(ProgramStateRef State, SymbolRef Sym, - const SMTExprRef &Exp) { + const llvm::SMTExprRef &Exp) { // Check the model, avoid simplifying AST to save time if (checkModel(State, Sym, Exp).isConstrainedTrue()) - return State->add<ConstraintSMT>( - std::make_pair(Sym, static_cast<const SMTExprTy &>(*Exp))); + return State->add<ConstraintSMT>(std::make_pair(Sym, Exp)); return nullptr; } @@ -288,11 +311,11 @@ protected: // Construct the logical AND of all the constraints if (I != IE) { - std::vector<SMTExprRef> ASTs; + std::vector<llvm::SMTExprRef> ASTs; - SMTExprRef Constraint = Solver->newExprRef(I++->second); + llvm::SMTExprRef Constraint = I++->second; while (I != IE) { - Constraint = Solver->mkAnd(Constraint, Solver->newExprRef(I++->second)); + Constraint = Solver->mkAnd(Constraint, I++->second); } Solver->addConstraint(Constraint); @@ -301,9 +324,9 @@ protected: // Generate and check a Z3 model, using the given constraint. ConditionTruthVal checkModel(ProgramStateRef State, SymbolRef Sym, - const SMTExprRef &Exp) const { - ProgramStateRef NewState = State->add<ConstraintSMT>( - std::make_pair(Sym, static_cast<const SMTExprTy &>(*Exp))); + const llvm::SMTExprRef &Exp) const { + ProgramStateRef NewState = + State->add<ConstraintSMT>(std::make_pair(Sym, Exp)); llvm::FoldingSetNodeID ID; NewState->get<ConstraintSMT>().Profile(ID); diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SMTConv.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SMTConv.h index cdca2a09700d..bdebe238829e 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SMTConv.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SMTConv.h @@ -1,9 +1,8 @@ //== SMTConv.h --------------------------------------------------*- C++ -*--==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -16,8 +15,8 @@ #include "clang/AST/Expr.h" #include "clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h" -#include "clang/StaticAnalyzer/Core/PathSensitive/SMTSolver.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h" +#include "llvm/Support/SMTAPI.h" namespace clang { namespace ento { @@ -25,8 +24,8 @@ namespace ento { class SMTConv { public: // Returns an appropriate sort, given a QualType and it's bit width. - static inline SMTSortRef mkSort(SMTSolverRef &Solver, const QualType &Ty, - unsigned BitWidth) { + static inline llvm::SMTSortRef mkSort(llvm::SMTSolverRef &Solver, + const QualType &Ty, unsigned BitWidth) { if (Ty->isBooleanType()) return Solver->getBoolSort(); @@ -36,10 +35,10 @@ public: return Solver->getBitvectorSort(BitWidth); } - /// Constructs an SMTExprRef from an unary operator. - static inline SMTExprRef fromUnOp(SMTSolverRef &Solver, - const UnaryOperator::Opcode Op, - const SMTExprRef &Exp) { + /// Constructs an SMTSolverRef from an unary operator. + static inline llvm::SMTExprRef fromUnOp(llvm::SMTSolverRef &Solver, + const UnaryOperator::Opcode Op, + const llvm::SMTExprRef &Exp) { switch (Op) { case UO_Minus: return Solver->mkBVNeg(Exp); @@ -55,10 +54,10 @@ public: llvm_unreachable("Unimplemented opcode"); } - /// Constructs an SMTExprRef from a floating-point unary operator. - static inline SMTExprRef fromFloatUnOp(SMTSolverRef &Solver, - const UnaryOperator::Opcode Op, - const SMTExprRef &Exp) { + /// Constructs an SMTSolverRef from a floating-point unary operator. + static inline llvm::SMTExprRef fromFloatUnOp(llvm::SMTSolverRef &Solver, + const UnaryOperator::Opcode Op, + const llvm::SMTExprRef &Exp) { switch (Op) { case UO_Minus: return Solver->mkFPNeg(Exp); @@ -71,27 +70,28 @@ public: llvm_unreachable("Unimplemented opcode"); } - /// Construct an SMTExprRef from a n-ary binary operator. - static inline SMTExprRef fromNBinOp(SMTSolverRef &Solver, - const BinaryOperator::Opcode Op, - const std::vector<SMTExprRef> &ASTs) { + /// Construct an SMTSolverRef from a n-ary binary operator. + static inline llvm::SMTExprRef + fromNBinOp(llvm::SMTSolverRef &Solver, const BinaryOperator::Opcode Op, + const std::vector<llvm::SMTExprRef> &ASTs) { assert(!ASTs.empty()); if (Op != BO_LAnd && Op != BO_LOr) llvm_unreachable("Unimplemented opcode"); - SMTExprRef res = ASTs.front(); + llvm::SMTExprRef res = ASTs.front(); for (std::size_t i = 1; i < ASTs.size(); ++i) res = (Op == BO_LAnd) ? Solver->mkAnd(res, ASTs[i]) : Solver->mkOr(res, ASTs[i]); return res; } - /// Construct an SMTExprRef from a binary operator. - static inline SMTExprRef fromBinOp(SMTSolverRef &Solver, - const SMTExprRef &LHS, - const BinaryOperator::Opcode Op, - const SMTExprRef &RHS, bool isSigned) { + /// Construct an SMTSolverRef from a binary operator. + static inline llvm::SMTExprRef fromBinOp(llvm::SMTSolverRef &Solver, + const llvm::SMTExprRef &LHS, + const BinaryOperator::Opcode Op, + const llvm::SMTExprRef &RHS, + bool isSigned) { assert(*Solver->getSort(LHS) == *Solver->getSort(RHS) && "AST's must have the same sort!"); @@ -163,9 +163,10 @@ public: llvm_unreachable("Unimplemented opcode"); } - /// Construct an SMTExprRef from a special floating-point binary operator. - static inline SMTExprRef - fromFloatSpecialBinOp(SMTSolverRef &Solver, const SMTExprRef &LHS, + /// Construct an SMTSolverRef from a special floating-point binary + /// operator. + static inline llvm::SMTExprRef + fromFloatSpecialBinOp(llvm::SMTSolverRef &Solver, const llvm::SMTExprRef &LHS, const BinaryOperator::Opcode Op, const llvm::APFloat::fltCategory &RHS) { switch (Op) { @@ -196,11 +197,11 @@ public: llvm_unreachable("Unimplemented opcode"); } - /// Construct an SMTExprRef from a floating-point binary operator. - static inline SMTExprRef fromFloatBinOp(SMTSolverRef &Solver, - const SMTExprRef &LHS, - const BinaryOperator::Opcode Op, - const SMTExprRef &RHS) { + /// Construct an SMTSolverRef from a floating-point binary operator. + static inline llvm::SMTExprRef fromFloatBinOp(llvm::SMTSolverRef &Solver, + const llvm::SMTExprRef &LHS, + const BinaryOperator::Opcode Op, + const llvm::SMTExprRef &RHS) { assert(*Solver->getSort(LHS) == *Solver->getSort(RHS) && "AST's must have the same sort!"); @@ -254,11 +255,13 @@ public: llvm_unreachable("Unimplemented opcode"); } - /// Construct an SMTExprRef from a QualType FromTy to a QualType ToTy, and - /// their bit widths. - static inline SMTExprRef fromCast(SMTSolverRef &Solver, const SMTExprRef &Exp, - QualType ToTy, uint64_t ToBitWidth, - QualType FromTy, uint64_t FromBitWidth) { + /// Construct an SMTSolverRef from a QualType FromTy to a QualType ToTy, + /// and their bit widths. + static inline llvm::SMTExprRef fromCast(llvm::SMTSolverRef &Solver, + const llvm::SMTExprRef &Exp, + QualType ToTy, uint64_t ToBitWidth, + QualType FromTy, + uint64_t FromBitWidth) { if ((FromTy->isIntegralOrEnumerationType() && ToTy->isIntegralOrEnumerationType()) || (FromTy->isAnyPointerType() ^ ToTy->isAnyPointerType()) || @@ -292,7 +295,7 @@ public: } if (FromTy->isIntegralOrEnumerationType() && ToTy->isRealFloatingType()) { - SMTSortRef Sort = Solver->getFloatSort(ToBitWidth); + llvm::SMTSortRef Sort = Solver->getFloatSort(ToBitWidth); return FromTy->isSignedIntegerOrEnumerationType() ? Solver->mkSBVtoFP(Exp, Sort) : Solver->mkUBVtoFP(Exp, Sort); @@ -307,7 +310,7 @@ public: } // Callback function for doCast parameter on APSInt type. - static inline llvm::APSInt castAPSInt(SMTSolverRef &Solver, + static inline llvm::APSInt castAPSInt(llvm::SMTSolverRef &Solver, const llvm::APSInt &V, QualType ToTy, uint64_t ToWidth, QualType FromTy, uint64_t FromWidth) { @@ -315,30 +318,32 @@ public: return TargetType.convert(V); } - /// Construct an SMTExprRef from a SymbolData. - static inline SMTExprRef fromData(SMTSolverRef &Solver, const SymbolID ID, - const QualType &Ty, uint64_t BitWidth) { + /// Construct an SMTSolverRef from a SymbolData. + static inline llvm::SMTExprRef fromData(llvm::SMTSolverRef &Solver, + const SymbolID ID, const QualType &Ty, + uint64_t BitWidth) { llvm::Twine Name = "$" + llvm::Twine(ID); return Solver->mkSymbol(Name.str().c_str(), mkSort(Solver, Ty, BitWidth)); } - // Wrapper to generate SMTExprRef from SymbolCast data. - static inline SMTExprRef getCastExpr(SMTSolverRef &Solver, ASTContext &Ctx, - const SMTExprRef &Exp, QualType FromTy, - QualType ToTy) { + // Wrapper to generate SMTSolverRef from SymbolCast data. + static inline llvm::SMTExprRef getCastExpr(llvm::SMTSolverRef &Solver, + ASTContext &Ctx, + const llvm::SMTExprRef &Exp, + QualType FromTy, QualType ToTy) { return fromCast(Solver, Exp, ToTy, Ctx.getTypeSize(ToTy), FromTy, Ctx.getTypeSize(FromTy)); } - // Wrapper to generate SMTExprRef from unpacked binary symbolic expression. - // Sets the RetTy parameter. See getSMTExprRef(). - static inline SMTExprRef getBinExpr(SMTSolverRef &Solver, ASTContext &Ctx, - const SMTExprRef &LHS, QualType LTy, - BinaryOperator::Opcode Op, - const SMTExprRef &RHS, QualType RTy, - QualType *RetTy) { - SMTExprRef NewLHS = LHS; - SMTExprRef NewRHS = RHS; + // Wrapper to generate SMTSolverRef from unpacked binary symbolic + // expression. Sets the RetTy parameter. See getSMTSolverRef(). + static inline llvm::SMTExprRef + getBinExpr(llvm::SMTSolverRef &Solver, ASTContext &Ctx, + const llvm::SMTExprRef &LHS, QualType LTy, + BinaryOperator::Opcode Op, const llvm::SMTExprRef &RHS, + QualType RTy, QualType *RetTy) { + llvm::SMTExprRef NewLHS = LHS; + llvm::SMTExprRef NewRHS = RHS; doTypeConversion(Solver, Ctx, NewLHS, NewRHS, LTy, RTy); // Update the return type parameter if the output type has changed. @@ -366,36 +371,40 @@ public: LTy->isSignedIntegerOrEnumerationType()); } - // Wrapper to generate SMTExprRef from BinarySymExpr. - // Sets the hasComparison and RetTy parameters. See getSMTExprRef(). - static inline SMTExprRef getSymBinExpr(SMTSolverRef &Solver, ASTContext &Ctx, - const BinarySymExpr *BSE, - bool *hasComparison, QualType *RetTy) { + // Wrapper to generate SMTSolverRef from BinarySymExpr. + // Sets the hasComparison and RetTy parameters. See getSMTSolverRef(). + static inline llvm::SMTExprRef getSymBinExpr(llvm::SMTSolverRef &Solver, + ASTContext &Ctx, + const BinarySymExpr *BSE, + bool *hasComparison, + QualType *RetTy) { QualType LTy, RTy; BinaryOperator::Opcode Op = BSE->getOpcode(); if (const SymIntExpr *SIE = dyn_cast<SymIntExpr>(BSE)) { - SMTExprRef LHS = + llvm::SMTExprRef LHS = getSymExpr(Solver, Ctx, SIE->getLHS(), <y, hasComparison); llvm::APSInt NewRInt; std::tie(NewRInt, RTy) = fixAPSInt(Ctx, SIE->getRHS()); - SMTExprRef RHS = Solver->mkBitvector(NewRInt, NewRInt.getBitWidth()); + llvm::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->mkBitvector(NewLInt, NewLInt.getBitWidth()); - SMTExprRef RHS = + llvm::SMTExprRef LHS = + Solver->mkBitvector(NewLInt, NewLInt.getBitWidth()); + llvm::SMTExprRef RHS = getSymExpr(Solver, Ctx, ISE->getRHS(), &RTy, hasComparison); return getBinExpr(Solver, Ctx, LHS, LTy, Op, RHS, RTy, RetTy); } if (const SymSymExpr *SSM = dyn_cast<SymSymExpr>(BSE)) { - SMTExprRef LHS = + llvm::SMTExprRef LHS = getSymExpr(Solver, Ctx, SSM->getLHS(), <y, hasComparison); - SMTExprRef RHS = + llvm::SMTExprRef RHS = getSymExpr(Solver, Ctx, SSM->getRHS(), &RTy, hasComparison); return getBinExpr(Solver, Ctx, LHS, LTy, Op, RHS, RTy, RetTy); } @@ -405,9 +414,10 @@ public: // Recursive implementation to unpack and generate symbolic expression. // Sets the hasComparison and RetTy parameters. See getExpr(). - static inline SMTExprRef getSymExpr(SMTSolverRef &Solver, ASTContext &Ctx, - SymbolRef Sym, QualType *RetTy, - bool *hasComparison) { + static inline llvm::SMTExprRef getSymExpr(llvm::SMTSolverRef &Solver, + ASTContext &Ctx, SymbolRef Sym, + QualType *RetTy, + bool *hasComparison) { if (const SymbolData *SD = dyn_cast<SymbolData>(Sym)) { if (RetTy) *RetTy = Sym->getType(); @@ -421,7 +431,7 @@ public: *RetTy = Sym->getType(); QualType FromTy; - SMTExprRef Exp = + llvm::SMTExprRef Exp = getSymExpr(Solver, Ctx, SC->getOperand(), &FromTy, hasComparison); // Casting an expression with a comparison invalidates it. Note that this @@ -433,7 +443,8 @@ public: } if (const BinarySymExpr *BSE = dyn_cast<BinarySymExpr>(Sym)) { - SMTExprRef Exp = getSymBinExpr(Solver, Ctx, BSE, hasComparison, RetTy); + llvm::SMTExprRef Exp = + getSymBinExpr(Solver, Ctx, BSE, hasComparison, RetTy); // Set the hasComparison parameter, in post-order traversal order. if (hasComparison) *hasComparison = BinaryOperator::isComparisonOp(BSE->getOpcode()); @@ -443,13 +454,14 @@ public: llvm_unreachable("Unsupported SymbolRef type!"); } - // Generate an SMTExprRef that represents the given symbolic expression. + // Generate an SMTSolverRef that represents the given symbolic expression. // Sets the hasComparison parameter if the expression has a comparison // operator. Sets the RetTy parameter to the final return type after // promotions and casts. - static inline SMTExprRef getExpr(SMTSolverRef &Solver, ASTContext &Ctx, - SymbolRef Sym, QualType *RetTy = nullptr, - bool *hasComparison = nullptr) { + static inline llvm::SMTExprRef getExpr(llvm::SMTSolverRef &Solver, + ASTContext &Ctx, SymbolRef Sym, + QualType *RetTy = nullptr, + bool *hasComparison = nullptr) { if (hasComparison) { *hasComparison = false; } @@ -457,11 +469,11 @@ public: return getSymExpr(Solver, Ctx, Sym, RetTy, hasComparison); } - // Generate an SMTExprRef that compares the expression to zero. - static inline SMTExprRef getZeroExpr(SMTSolverRef &Solver, ASTContext &Ctx, - const SMTExprRef &Exp, QualType Ty, - bool Assumption) { - + // Generate an SMTSolverRef that compares the expression to zero. + static inline llvm::SMTExprRef getZeroExpr(llvm::SMTSolverRef &Solver, + ASTContext &Ctx, + const llvm::SMTExprRef &Exp, + QualType Ty, bool Assumption) { if (Ty->isRealFloatingType()) { llvm::APFloat Zero = llvm::APFloat::getZero(Ctx.getFloatTypeSemantics(Ty)); @@ -486,21 +498,21 @@ public: llvm_unreachable("Unsupported type for zero value!"); } - // Wrapper to generate SMTExprRef from a range. If From == To, an equality - // will be created instead. - static inline SMTExprRef getRangeExpr(SMTSolverRef &Solver, ASTContext &Ctx, - SymbolRef Sym, const llvm::APSInt &From, - const llvm::APSInt &To, bool InRange) { + // Wrapper to generate SMTSolverRef from a range. If From == To, an + // equality will be created instead. + static inline llvm::SMTExprRef + getRangeExpr(llvm::SMTSolverRef &Solver, ASTContext &Ctx, SymbolRef Sym, + const llvm::APSInt &From, const llvm::APSInt &To, bool InRange) { // Convert lower bound QualType FromTy; llvm::APSInt NewFromInt; std::tie(NewFromInt, FromTy) = fixAPSInt(Ctx, From); - SMTExprRef FromExp = + llvm::SMTExprRef FromExp = Solver->mkBitvector(NewFromInt, NewFromInt.getBitWidth()); // Convert symbol QualType SymTy; - SMTExprRef Exp = getExpr(Solver, Ctx, Sym, &SymTy); + llvm::SMTExprRef Exp = getExpr(Solver, Ctx, Sym, &SymTy); // Construct single (in)equality if (From == To) @@ -510,16 +522,17 @@ public: QualType ToTy; llvm::APSInt NewToInt; std::tie(NewToInt, ToTy) = fixAPSInt(Ctx, To); - SMTExprRef ToExp = Solver->mkBitvector(NewToInt, NewToInt.getBitWidth()); + llvm::SMTExprRef ToExp = + Solver->mkBitvector(NewToInt, NewToInt.getBitWidth()); assert(FromTy == ToTy && "Range values have different types!"); // Construct two (in)equalities, and a logical and/or - SMTExprRef LHS = + llvm::SMTExprRef LHS = getBinExpr(Solver, Ctx, Exp, SymTy, InRange ? BO_GE : BO_LT, FromExp, FromTy, /*RetTy=*/nullptr); - SMTExprRef RHS = getBinExpr(Solver, Ctx, Exp, SymTy, - InRange ? BO_LE : BO_GT, ToExp, ToTy, - /*RetTy=*/nullptr); + llvm::SMTExprRef RHS = getBinExpr(Solver, Ctx, Exp, SymTy, + InRange ? BO_LE : BO_GT, ToExp, ToTy, + /*RetTy=*/nullptr); return fromBinOp(Solver, LHS, InRange ? BO_LAnd : BO_LOr, RHS, SymTy->isSignedIntegerOrEnumerationType()); @@ -551,23 +564,24 @@ public: // Perform implicit type conversion on binary symbolic expressions. // May modify all input parameters. // TODO: Refactor to use built-in conversion functions - static inline void doTypeConversion(SMTSolverRef &Solver, ASTContext &Ctx, - SMTExprRef &LHS, SMTExprRef &RHS, - QualType <y, QualType &RTy) { + static inline void doTypeConversion(llvm::SMTSolverRef &Solver, + ASTContext &Ctx, llvm::SMTExprRef &LHS, + llvm::SMTExprRef &RHS, QualType <y, + QualType &RTy) { assert(!LTy.isNull() && !RTy.isNull() && "Input type is null!"); // Perform type conversion if ((LTy->isIntegralOrEnumerationType() && RTy->isIntegralOrEnumerationType()) && (LTy->isArithmeticType() && RTy->isArithmeticType())) { - SMTConv::doIntTypeConversion<SMTExprRef, &fromCast>(Solver, Ctx, LHS, LTy, - RHS, RTy); + SMTConv::doIntTypeConversion<llvm::SMTExprRef, &fromCast>( + Solver, Ctx, LHS, LTy, RHS, RTy); return; } if (LTy->isRealFloatingType() || RTy->isRealFloatingType()) { - SMTConv::doFloatTypeConversion<SMTExprRef, &fromCast>(Solver, Ctx, LHS, - LTy, RHS, RTy); + SMTConv::doFloatTypeConversion<llvm::SMTExprRef, &fromCast>( + Solver, Ctx, LHS, LTy, RHS, RTy); return; } @@ -625,12 +639,11 @@ public: // Perform implicit integer type conversion. // May modify all input parameters. // TODO: Refactor to use Sema::handleIntegerConversion() - template <typename T, T (*doCast)(SMTSolverRef &Solver, const T &, QualType, - uint64_t, QualType, uint64_t)> - static inline void doIntTypeConversion(SMTSolverRef &Solver, ASTContext &Ctx, - T &LHS, QualType <y, T &RHS, - QualType &RTy) { - + template <typename T, T (*doCast)(llvm::SMTSolverRef &Solver, const T &, + QualType, uint64_t, QualType, uint64_t)> + static inline void doIntTypeConversion(llvm::SMTSolverRef &Solver, + ASTContext &Ctx, T &LHS, QualType <y, + T &RHS, QualType &RTy) { uint64_t LBitWidth = Ctx.getTypeSize(LTy); uint64_t RBitWidth = Ctx.getTypeSize(RTy); @@ -708,12 +721,11 @@ public: // Perform implicit floating-point type conversion. // May modify all input parameters. // TODO: Refactor to use Sema::handleFloatConversion() - template <typename T, T (*doCast)(SMTSolverRef &Solver, const T &, QualType, - uint64_t, QualType, uint64_t)> + template <typename T, T (*doCast)(llvm::SMTSolverRef &Solver, const T &, + QualType, uint64_t, QualType, uint64_t)> static inline void - doFloatTypeConversion(SMTSolverRef &Solver, ASTContext &Ctx, T &LHS, + doFloatTypeConversion(llvm::SMTSolverRef &Solver, ASTContext &Ctx, T &LHS, QualType <y, T &RHS, QualType &RTy) { - uint64_t LBitWidth = Ctx.getTypeSize(LTy); uint64_t RBitWidth = Ctx.getTypeSize(RTy); @@ -750,4 +762,4 @@ public: } // namespace ento } // namespace clang -#endif
\ No newline at end of file +#endif diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SMTExpr.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SMTExpr.h deleted file mode 100644 index 9dedf96cfaf8..000000000000 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SMTExpr.h +++ /dev/null @@ -1,62 +0,0 @@ -//== SMTExpr.h --------------------------------------------------*- 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 a SMT generic Expr API, which will be the base class -// for every SMT solver expr specific class. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SMTEXPR_H -#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SMTEXPR_H - -#include "clang/Basic/TargetInfo.h" -#include "llvm/ADT/FoldingSet.h" - -namespace clang { -namespace ento { - -/// Generic base class for SMT exprs -class SMTExpr { -public: - SMTExpr() = default; - virtual ~SMTExpr() = default; - - bool operator<(const SMTExpr &Other) const { - llvm::FoldingSetNodeID ID1, ID2; - Profile(ID1); - Other.Profile(ID2); - return ID1 < ID2; - } - - virtual void Profile(llvm::FoldingSetNodeID &ID) const { - static int Tag = 0; - ID.AddPointer(&Tag); - } - - friend bool operator==(SMTExpr const &LHS, SMTExpr const &RHS) { - return LHS.equal_to(RHS); - } - - virtual void print(raw_ostream &OS) const = 0; - - LLVM_DUMP_METHOD void dump() const { print(llvm::errs()); } - -protected: - /// Query the SMT solver and returns true if two sorts are equal (same kind - /// and bit width). This does not check if the two sorts are the same objects. - virtual bool equal_to(SMTExpr const &other) const = 0; -}; - -/// Shared pointer for SMTExprs, used by SMTSolver API. -using SMTExprRef = std::shared_ptr<SMTExpr>; - -} // namespace ento -} // namespace clang - -#endif diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SMTSolver.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SMTSolver.h deleted file mode 100644 index 2abe5fc98744..000000000000 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SMTSolver.h +++ /dev/null @@ -1,303 +0,0 @@ -//== SMTSolver.h ------------------------------------------------*- 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 a SMT generic Solver API, which will be the base class -// for every SMT solver specific class. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SMTSOLVER_H -#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SMTSOLVER_H - -#include "clang/StaticAnalyzer/Core/PathSensitive/SMTExpr.h" -#include "clang/StaticAnalyzer/Core/PathSensitive/SMTSort.h" -#include "llvm/ADT/APSInt.h" - -namespace clang { -namespace ento { - -/// Generic base class for SMT Solvers -/// -/// This class is responsible for wrapping all sorts and expression generation, -/// through the mk* methods. It also provides methods to create SMT expressions -/// straight from clang's AST, through the from* methods. -class SMTSolver { -public: - SMTSolver() = default; - virtual ~SMTSolver() = default; - - LLVM_DUMP_METHOD void dump() const { print(llvm::errs()); } - - // Returns an appropriate floating-point sort for the given bitwidth. - SMTSortRef getFloatSort(unsigned BitWidth) { - switch (BitWidth) { - case 16: - return getFloat16Sort(); - case 32: - return getFloat32Sort(); - case 64: - return getFloat64Sort(); - case 128: - return getFloat128Sort(); - default:; - } - llvm_unreachable("Unsupported floating-point bitwidth!"); - } - - // Returns a boolean sort. - virtual SMTSortRef getBoolSort() = 0; - - // Returns an appropriate bitvector sort for the given bitwidth. - virtual SMTSortRef getBitvectorSort(const unsigned BitWidth) = 0; - - // Returns a floating-point sort of width 16 - virtual SMTSortRef getFloat16Sort() = 0; - - // Returns a floating-point sort of width 32 - virtual SMTSortRef getFloat32Sort() = 0; - - // Returns a floating-point sort of width 64 - virtual SMTSortRef getFloat64Sort() = 0; - - // Returns a floating-point sort of width 128 - virtual SMTSortRef getFloat128Sort() = 0; - - // Returns an appropriate sort for the given AST. - virtual SMTSortRef getSort(const SMTExprRef &AST) = 0; - - // Returns a new SMTExprRef from an SMTExpr - virtual SMTExprRef newExprRef(const SMTExpr &E) const = 0; - - /// Given a constraint, adds it to the solver - virtual void addConstraint(const SMTExprRef &Exp) const = 0; - - /// Creates a bitvector addition operation - virtual SMTExprRef mkBVAdd(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; - - /// Creates a bitvector subtraction operation - virtual SMTExprRef mkBVSub(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; - - /// Creates a bitvector multiplication operation - virtual SMTExprRef mkBVMul(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; - - /// Creates a bitvector signed modulus operation - virtual SMTExprRef mkBVSRem(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; - - /// Creates a bitvector unsigned modulus operation - virtual SMTExprRef mkBVURem(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; - - /// Creates a bitvector signed division operation - virtual SMTExprRef mkBVSDiv(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; - - /// Creates a bitvector unsigned division operation - virtual SMTExprRef mkBVUDiv(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; - - /// Creates a bitvector logical shift left operation - virtual SMTExprRef mkBVShl(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; - - /// Creates a bitvector arithmetic shift right operation - virtual SMTExprRef mkBVAshr(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; - - /// Creates a bitvector logical shift right operation - virtual SMTExprRef mkBVLshr(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; - - /// Creates a bitvector negation operation - virtual SMTExprRef mkBVNeg(const SMTExprRef &Exp) = 0; - - /// Creates a bitvector not operation - virtual SMTExprRef mkBVNot(const SMTExprRef &Exp) = 0; - - /// Creates a bitvector xor operation - virtual SMTExprRef mkBVXor(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; - - /// Creates a bitvector or operation - virtual SMTExprRef mkBVOr(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; - - /// Creates a bitvector and operation - virtual SMTExprRef mkBVAnd(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; - - /// Creates a bitvector unsigned less-than operation - virtual SMTExprRef mkBVUlt(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; - - /// Creates a bitvector signed less-than operation - virtual SMTExprRef mkBVSlt(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; - - /// Creates a bitvector unsigned greater-than operation - virtual SMTExprRef mkBVUgt(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; - - /// Creates a bitvector signed greater-than operation - virtual SMTExprRef mkBVSgt(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; - - /// Creates a bitvector unsigned less-equal-than operation - virtual SMTExprRef mkBVUle(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; - - /// Creates a bitvector signed less-equal-than operation - virtual SMTExprRef mkBVSle(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; - - /// Creates a bitvector unsigned greater-equal-than operation - virtual SMTExprRef mkBVUge(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; - - /// Creates a bitvector signed greater-equal-than operation - virtual SMTExprRef mkBVSge(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; - - /// Creates a boolean not operation - virtual SMTExprRef mkNot(const SMTExprRef &Exp) = 0; - - /// Creates a boolean equality operation - virtual SMTExprRef mkEqual(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; - - /// Creates a boolean and operation - virtual SMTExprRef mkAnd(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; - - /// Creates a boolean or operation - virtual SMTExprRef mkOr(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; - - /// Creates a boolean ite operation - virtual SMTExprRef mkIte(const SMTExprRef &Cond, const SMTExprRef &T, - const SMTExprRef &F) = 0; - - /// Creates a bitvector sign extension operation - virtual SMTExprRef mkBVSignExt(unsigned i, const SMTExprRef &Exp) = 0; - - /// Creates a bitvector zero extension operation - virtual SMTExprRef mkBVZeroExt(unsigned i, const SMTExprRef &Exp) = 0; - - /// Creates a bitvector extract operation - virtual SMTExprRef mkBVExtract(unsigned High, unsigned Low, - const SMTExprRef &Exp) = 0; - - /// Creates a bitvector concat operation - virtual SMTExprRef mkBVConcat(const SMTExprRef &LHS, - const SMTExprRef &RHS) = 0; - - /// Creates a floating-point negation operation - virtual SMTExprRef mkFPNeg(const SMTExprRef &Exp) = 0; - - /// Creates a floating-point isInfinite operation - virtual SMTExprRef mkFPIsInfinite(const SMTExprRef &Exp) = 0; - - /// Creates a floating-point isNaN operation - virtual SMTExprRef mkFPIsNaN(const SMTExprRef &Exp) = 0; - - /// Creates a floating-point isNormal operation - virtual SMTExprRef mkFPIsNormal(const SMTExprRef &Exp) = 0; - - /// Creates a floating-point isZero operation - virtual SMTExprRef mkFPIsZero(const SMTExprRef &Exp) = 0; - - /// Creates a floating-point multiplication operation - virtual SMTExprRef mkFPMul(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; - - /// Creates a floating-point division operation - virtual SMTExprRef mkFPDiv(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; - - /// Creates a floating-point remainder operation - virtual SMTExprRef mkFPRem(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; - - /// Creates a floating-point addition operation - virtual SMTExprRef mkFPAdd(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; - - /// Creates a floating-point subtraction operation - virtual SMTExprRef mkFPSub(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; - - /// Creates a floating-point less-than operation - virtual SMTExprRef mkFPLt(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; - - /// Creates a floating-point greater-than operation - virtual SMTExprRef mkFPGt(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; - - /// Creates a floating-point less-than-or-equal operation - virtual SMTExprRef mkFPLe(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; - - /// Creates a floating-point greater-than-or-equal operation - virtual SMTExprRef mkFPGe(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; - - /// Creates a floating-point equality operation - virtual SMTExprRef mkFPEqual(const SMTExprRef &LHS, - const SMTExprRef &RHS) = 0; - - /// Creates a floating-point conversion from floatint-point to floating-point - /// operation - virtual SMTExprRef mkFPtoFP(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, - const SMTSortRef &To) = 0; - - /// Creates a floating-point conversion from unsigned bitvector to - /// floatint-point operation - 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; - - // Returns an appropriate floating-point rounding mode. - virtual SMTExprRef getFloatRoundingMode() = 0; - - // If the a model is available, returns the value of a given bitvector symbol - virtual llvm::APSInt getBitvector(const SMTExprRef &Exp, unsigned BitWidth, - bool isUnsigned) = 0; - - // If the a model is available, returns the value of a given boolean symbol - virtual bool getBoolean(const SMTExprRef &Exp) = 0; - - /// Constructs an SMTExprRef from a boolean. - virtual SMTExprRef mkBoolean(const bool b) = 0; - - /// Constructs an SMTExprRef from a finite APFloat. - virtual SMTExprRef mkFloat(const llvm::APFloat Float) = 0; - - /// Constructs an SMTExprRef from an APSInt and its bit width - virtual SMTExprRef mkBitvector(const llvm::APSInt Int, unsigned BitWidth) = 0; - - /// Given an expression, extract the value of this operand in the model. - virtual bool getInterpretation(const SMTExprRef &Exp, llvm::APSInt &Int) = 0; - - /// Given an expression extract the value of this operand in the model. - virtual bool getInterpretation(const SMTExprRef &Exp, - llvm::APFloat &Float) = 0; - - /// Check if the constraints are satisfiable - virtual Optional<bool> check() const = 0; - - /// Push the current solver state - virtual void push() = 0; - - /// Pop the previous solver state - virtual void pop(unsigned NumStates = 1) = 0; - - /// Reset the solver and remove all constraints. - virtual void reset() = 0; - - /// Checks if the solver supports floating-points. - virtual bool isFPSupported() = 0; - - virtual void print(raw_ostream &OS) const = 0; -}; - -/// Shared pointer for SMTSolvers. -using SMTSolverRef = std::shared_ptr<SMTSolver>; - -/// Convenience method to create and Z3Solver object -SMTSolverRef CreateZ3Solver(); - -} // namespace ento -} // namespace clang - -#endif diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SMTSort.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SMTSort.h deleted file mode 100644 index 41ef573f0c71..000000000000 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SMTSort.h +++ /dev/null @@ -1,91 +0,0 @@ -//== SMTSort.h --------------------------------------------------*- 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 a SMT generic Sort API, which will be the base class -// for every SMT solver sort specific class. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SMTSORT_H -#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SMTSORT_H - -#include "clang/Basic/TargetInfo.h" - -namespace clang { -namespace ento { - -/// Generic base class for SMT sorts -class SMTSort { -public: - SMTSort() = default; - virtual ~SMTSort() = default; - - /// Returns true if the sort is a bitvector, calls isBitvectorSortImpl(). - virtual bool isBitvectorSort() const { return isBitvectorSortImpl(); } - - /// Returns true if the sort is a floating-point, calls isFloatSortImpl(). - virtual bool isFloatSort() const { return isFloatSortImpl(); } - - /// Returns true if the sort is a boolean, calls isBooleanSortImpl(). - virtual bool isBooleanSort() const { return isBooleanSortImpl(); } - - /// Returns the bitvector size, fails if the sort is not a bitvector - /// Calls getBitvectorSortSizeImpl(). - virtual unsigned getBitvectorSortSize() const { - assert(isBitvectorSort() && "Not a bitvector sort!"); - unsigned Size = getBitvectorSortSizeImpl(); - assert(Size && "Size is zero!"); - return Size; - }; - - /// Returns the floating-point size, fails if the sort is not a floating-point - /// Calls getFloatSortSizeImpl(). - virtual unsigned getFloatSortSize() const { - assert(isFloatSort() && "Not a floating-point sort!"); - unsigned Size = getFloatSortSizeImpl(); - assert(Size && "Size is zero!"); - return Size; - }; - - friend bool operator==(SMTSort const &LHS, SMTSort const &RHS) { - return LHS.equal_to(RHS); - } - - virtual void print(raw_ostream &OS) const = 0; - - LLVM_DUMP_METHOD void dump() const { print(llvm::errs()); } - -protected: - /// Query the SMT solver and returns true if two sorts are equal (same kind - /// and bit width). This does not check if the two sorts are the same objects. - virtual bool equal_to(SMTSort const &other) const = 0; - - /// Query the SMT solver and checks if a sort is bitvector. - virtual bool isBitvectorSortImpl() const = 0; - - /// Query the SMT solver and checks if a sort is floating-point. - virtual bool isFloatSortImpl() const = 0; - - /// Query the SMT solver and checks if a sort is boolean. - virtual bool isBooleanSortImpl() const = 0; - - /// Query the SMT solver and returns the sort bit width. - virtual unsigned getBitvectorSortSizeImpl() const = 0; - - /// Query the SMT solver and returns the sort bit width. - virtual unsigned getFloatSortSizeImpl() const = 0; -}; - -/// Shared pointer for SMTSorts, used by SMTSolver API. -using SMTSortRef = std::shared_ptr<SMTSort>; - -} // namespace ento -} // namespace clang - -#endif diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h index c9e284a1a3e8..35ebefdc00d6 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h @@ -1,9 +1,8 @@ // SValBuilder.h - Construction of SVals from evaluating expressions -*- C++ -*- // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SValVisitor.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SValVisitor.h index f87fdce1561b..fc83e26183b3 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SValVisitor.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SValVisitor.h @@ -1,9 +1,8 @@ //===--- SValVisitor.h - Visitor for SVal subclasses ------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.def b/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.def index a0e309937892..eb05de6d9933 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.def +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.def @@ -1,9 +1,8 @@ //===-- SVals.def - Metadata about SVal kinds -------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h index 0efe96f67f8e..1abe29782088 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h @@ -1,9 +1,8 @@ //===- SVals.h - Abstract Values for Static Analysis ------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -191,6 +190,9 @@ public: const MemRegion *getAsRegion() const; + /// printJson - Pretty-prints in JSON format. + void printJson(raw_ostream &Out, bool AddQuotes) const; + void dumpToStream(raw_ostream &OS) const; void dump() const; @@ -304,7 +306,7 @@ public: static bool isCompoundType(QualType T) { return T->isArrayType() || T->isRecordType() || - T->isComplexType() || T->isVectorType(); + T->isAnyComplexType() || T->isVectorType(); } private: @@ -668,13 +670,4 @@ private: } // namespace clang -namespace llvm { - -template <typename T> struct isPodLike; -template <> struct isPodLike<clang::ento::SVal> { - static const bool value = true; -}; - -} // namespace llvm - #endif // LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SVALS_H diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SimpleConstraintManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SimpleConstraintManager.h index d64b90e2d380..6bf5e94afdbb 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SimpleConstraintManager.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SimpleConstraintManager.h @@ -1,9 +1,8 @@ //== SimpleConstraintManager.h ----------------------------------*- C++ -*--==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h b/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h index f49f761c77eb..cbff29953944 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h @@ -1,9 +1,8 @@ //===- Store.h - Interface for maps from Locations to Values ----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -254,7 +253,8 @@ public: virtual bool scanReachableSymbols(Store S, const MemRegion *R, ScanReachableSymbols &Visitor) = 0; - virtual void print(Store store, raw_ostream &Out, const char* nl) = 0; + virtual void printJson(raw_ostream &Out, Store S, const char *NL, + unsigned int Space, bool IsDot) const = 0; class BindingsHandler { public: diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h b/include/clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h index 22259a239cf6..a2dd05cfdf4c 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h @@ -1,9 +1,8 @@ //===- StoreRef.h - Smart pointer for store objects -------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h index d745b0f51ab0..7789b431c0a6 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h @@ -1,9 +1,8 @@ //== SubEngine.h - Interface of the subengine of CoreEngine --------*- C++ -*-// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -159,10 +158,10 @@ public: const CallEvent *Call, RegionAndSymbolInvalidationTraits &HTraits) = 0; - /// printState - Called by ProgramStateManager to print checker-specific data. - virtual void printState(raw_ostream &Out, ProgramStateRef State, - const char *NL, const char *Sep, - const LocationContext *LCtx = nullptr) = 0; + /// printJson - Called by ProgramStateManager to print checker-specific data. + virtual void printJson(raw_ostream &Out, ProgramStateRef State, + const LocationContext *LCtx, const char *NL, + unsigned int Space, bool IsDot) const = 0; /// Called by CoreEngine when the analysis worklist is either empty or the // maximum number of analysis steps have been reached. diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SummaryManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SummaryManager.h index 0a75eeb3ea53..1a56153da11e 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SummaryManager.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SummaryManager.h @@ -1,9 +1,8 @@ //== SummaryManager.h - Generic handling of function summaries --*- C++ -*--==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h index 69b9858d3feb..abfcd1d80faa 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h @@ -1,9 +1,8 @@ //===- SymExpr.h - Management of Symbolic Values ----------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h index d02a8abd1148..d212e23da6fc 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h @@ -1,9 +1,8 @@ //===- SymbolManager.h - Management of Symbolic Values ----------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/Symbols.def b/include/clang/StaticAnalyzer/Core/PathSensitive/Symbols.def index 7d4d8fe0a55a..7163a16263ab 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/Symbols.def +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/Symbols.def @@ -1,9 +1,8 @@ //===-- Symbols.def - Metadata about SymExpr kinds --------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/TaintManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/TaintManager.h deleted file mode 100644 index 8218fb1eeafe..000000000000 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/TaintManager.h +++ /dev/null @@ -1,59 +0,0 @@ -//===- TaintManager.h - Managing taint --------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file provides APIs for adding, removing, querying symbol taint. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_TAINTMANAGER_H -#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_TAINTMANAGER_H - -#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" -#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h" -#include "clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h" -#include "clang/StaticAnalyzer/Core/PathSensitive/TaintTag.h" -#include "llvm/ADT/ImmutableMap.h" - -namespace clang { -namespace ento { - -/// The GDM component containing the tainted root symbols. We lazily infer the -/// taint of the dependent symbols. Currently, this is a map from a symbol to -/// tag kind. TODO: Should support multiple tag kinds. -// FIXME: This does not use the nice trait macros because it must be accessible -// from multiple translation units. -struct TaintMap {}; - -using TaintMapImpl = llvm::ImmutableMap<SymbolRef, TaintTagType>; - -template<> struct ProgramStateTrait<TaintMap> - : public ProgramStatePartialTrait<TaintMapImpl> { - static void *GDMIndex(); -}; - -/// The GDM component mapping derived symbols' parent symbols to their -/// underlying regions. This is used to efficiently check whether a symbol is -/// tainted when it represents a sub-region of a tainted symbol. -struct DerivedSymTaint {}; - -using DerivedSymTaintImpl = llvm::ImmutableMap<SymbolRef, TaintedSubRegions>; - -template<> struct ProgramStateTrait<DerivedSymTaint> - : public ProgramStatePartialTrait<DerivedSymTaintImpl> { - static void *GDMIndex(); -}; - -class TaintManager { - TaintManager() = default; -}; - -} // namespace ento -} // namespace clang - -#endif // LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_TAINTMANAGER_H diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/TaintTag.h b/include/clang/StaticAnalyzer/Core/PathSensitive/TaintTag.h deleted file mode 100644 index 50c4b8194cff..000000000000 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/TaintTag.h +++ /dev/null @@ -1,30 +0,0 @@ -//===- TaintTag.h - Path-sensitive "State" for tracking values --*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Defines a set of taint tags. Several tags are used to differentiate kinds -// of taint. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_TAINTTAG_H -#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_TAINTTAG_H - -namespace clang { -namespace ento { - -/// The type of taint, which helps to differentiate between different types of -/// taint. -using TaintTagType = unsigned; - -static const TaintTagType TaintTagGeneric = 0; - -} // namespace ento -} // namespace clang - -#endif // LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_TAINTTAG_H diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/WorkList.h b/include/clang/StaticAnalyzer/Core/PathSensitive/WorkList.h index ef3c2694b283..7beb7ddf5bce 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/WorkList.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/WorkList.h @@ -1,9 +1,8 @@ //==- WorkList.h - Worklist class used by CoreEngine ---------------*- C++ -*-// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/include/clang/StaticAnalyzer/Core/RetainSummaryManager.h b/include/clang/StaticAnalyzer/Core/RetainSummaryManager.h deleted file mode 100644 index 4fcaa794c17b..000000000000 --- a/include/clang/StaticAnalyzer/Core/RetainSummaryManager.h +++ /dev/null @@ -1,798 +0,0 @@ -//=== RetainSummaryManager.h - Summaries for reference counting ---*- 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 summaries implementation for retain counting, which -// implements a reference count checker for Core Foundation and Cocoa -// on (Mac OS X). -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_ANALYZER_CORE_RETAINSUMMARYMANAGER -#define LLVM_CLANG_ANALYZER_CORE_RETAINSUMMARYMANAGER - -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/FoldingSet.h" -#include "clang/AST/Attr.h" -#include "clang/AST/DeclCXX.h" -#include "clang/AST/DeclObjC.h" -#include "clang/AST/ParentMap.h" -#include "clang/Analysis/SelectorExtras.h" -#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h" -#include "llvm/ADT/STLExtras.h" - -//===----------------------------------------------------------------------===// -// Adapters for FoldingSet. -//===----------------------------------------------------------------------===// - -using namespace clang; -using namespace ento; - -namespace clang { -namespace ento { - -/// Determines the object kind of a tracked object. -enum class ObjKind { - /// Indicates that the tracked object is a CF object. - CF, - - /// Indicates that the tracked object is an Objective-C object. - ObjC, - - /// Indicates that the tracked object could be a CF or Objective-C object. - AnyObj, - - /// Indicates that the tracked object is a generalized object. - Generalized, - - /// Indicates that the tracking object is a descendant of a - /// referenced-counted OSObject, used in the Darwin kernel. - OS -}; - -enum ArgEffectKind { - /// There is no effect. - DoNothing, - - /// The argument is treated as if an -autorelease message had been sent to - /// the referenced object. - Autorelease, - - /// The argument is treated as if the referenced object was deallocated. - Dealloc, - - /// The argument has its reference count decreased by 1. - DecRef, - - /// The argument has its reference count decreased by 1 to model - /// a transferred bridge cast under ARC. - DecRefBridgedTransferred, - - /// The argument has its reference count increased by 1. - IncRef, - - /// The argument is a pointer to a retain-counted object; on exit, the new - /// value of the pointer is a +0 value. - UnretainedOutParameter, - - /// The argument is a pointer to a retain-counted object; on exit, the new - /// value of the pointer is a +1 value. - RetainedOutParameter, - - /// The argument is a pointer to a retain-counted object; on exit, the new - /// value of the pointer is a +1 value iff the return code is zero. - RetainedOutParameterOnZero, - - /// The argument is a pointer to a retain-counted object; on exit, the new - /// value of the pointer is a +1 value iff the return code is non-zero. - RetainedOutParameterOnNonZero, - - /// The argument is treated as potentially escaping, meaning that - /// even when its reference count hits 0 it should be treated as still - /// possibly being alive as someone else *may* be holding onto the object. - MayEscape, - - /// All typestate tracking of the object ceases. This is usually employed - /// when the effect of the call is completely unknown. - StopTracking, - - /// All typestate tracking of the object ceases. Unlike StopTracking, - /// this is also enforced when the method body is inlined. - /// - /// In some cases, we obtain a better summary for this checker - /// by looking at the call site than by inlining the function. - /// Signifies that we should stop tracking the symbol even if - /// the function is inlined. - StopTrackingHard, - - /// Performs the combined functionality of DecRef and StopTrackingHard. - /// - /// The models the effect that the called function decrements the reference - /// count of the argument and all typestate tracking on that argument - /// should cease. - DecRefAndStopTrackingHard, -}; - -/// An ArgEffect summarizes the retain count behavior on an argument or receiver -/// to a function or method. -class ArgEffect { - ArgEffectKind K; - ObjKind O; -public: - explicit ArgEffect(ArgEffectKind K = DoNothing, ObjKind O = ObjKind::AnyObj) - : K(K), O(O) {} - - ArgEffectKind getKind() const { return K; } - ObjKind getObjKind() const { return O; } - - ArgEffect withKind(ArgEffectKind NewK) { - return ArgEffect(NewK, O); - } - - bool operator==(const ArgEffect &Other) const { - return K == Other.K && O == Other.O; - } -}; - -/// RetEffect summarizes a call's retain/release behavior with respect -/// to its return value. -class RetEffect { -public: - enum Kind { - /// Indicates that no retain count information is tracked for - /// the return value. - NoRet, - - /// Indicates that the returned value is an owned (+1) symbol. - OwnedSymbol, - - /// Indicates that the returned value is an object with retain count - /// semantics but that it is not owned (+0). This is the default - /// for getters, etc. - NotOwnedSymbol, - - /// Indicates that the return value is an owned object when the - /// receiver is also a tracked object. - 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 precise than the summary indirectly produced - // by inlining the function - NoRetHard - }; - -private: - Kind K; - ObjKind O; - - RetEffect(Kind k, ObjKind o = ObjKind::AnyObj) : K(k), O(o) {} - -public: - Kind getKind() const { return K; } - - ObjKind getObjKind() const { return O; } - - bool isOwned() const { - return K == OwnedSymbol || K == OwnedWhenTrackedReceiver; - } - - bool notOwned() const { - return K == NotOwnedSymbol; - } - - bool operator==(const RetEffect &Other) const { - return K == Other.K && O == Other.O; - } - - static RetEffect MakeOwnedWhenTrackedReceiver() { - return RetEffect(OwnedWhenTrackedReceiver, ObjKind::ObjC); - } - - static RetEffect MakeOwned(ObjKind o) { - return RetEffect(OwnedSymbol, o); - } - static RetEffect MakeNotOwned(ObjKind o) { - return RetEffect(NotOwnedSymbol, o); - } - static RetEffect MakeNoRet() { - return RetEffect(NoRet); - } - static RetEffect MakeNoRetHard() { - return RetEffect(NoRetHard); - } -}; - -/// Encapsulates the retain count semantics on the arguments, return value, -/// and receiver (if any) of a function/method call. -/// -/// Note that construction of these objects is not highly efficient. That -/// is okay for clients where creating these objects isn't really a bottleneck. -/// The purpose of the API is to provide something simple. The actual -/// static analyzer checker that implements retain/release typestate -/// tracking uses something more efficient. -class CallEffects { - llvm::SmallVector<ArgEffect, 10> Args; - RetEffect Ret; - ArgEffect Receiver; - - CallEffects(const RetEffect &R, - ArgEffect Receiver = ArgEffect(DoNothing, ObjKind::AnyObj)) - : Ret(R), Receiver(Receiver) {} - -public: - /// Returns the argument effects for a call. - ArrayRef<ArgEffect> getArgs() const { return Args; } - - /// Returns the effects on the receiver. - ArgEffect getReceiver() const { return Receiver; } - - /// Returns the effect on the return value. - RetEffect getReturnValue() const { return Ret; } - - /// Return the CallEfect for a given Objective-C method. - static CallEffects getEffect(const ObjCMethodDecl *MD); - - /// Return the CallEfect for a given C/C++ function. - static CallEffects getEffect(const FunctionDecl *FD); -}; - -/// A key identifying a summary. -class ObjCSummaryKey { - IdentifierInfo* II; - Selector S; -public: - ObjCSummaryKey(IdentifierInfo* ii, Selector s) - : II(ii), S(s) {} - - ObjCSummaryKey(const ObjCInterfaceDecl *d, Selector s) - : II(d ? d->getIdentifier() : nullptr), S(s) {} - - ObjCSummaryKey(Selector s) - : II(nullptr), S(s) {} - - IdentifierInfo *getIdentifier() const { return II; } - Selector getSelector() const { return S; } -}; - -} // end namespace ento -} // end namespace clang - - -namespace llvm { - -template <> struct FoldingSetTrait<ArgEffect> { -static inline void Profile(const ArgEffect X, FoldingSetNodeID &ID) { - ID.AddInteger((unsigned) X.getKind()); - ID.AddInteger((unsigned) X.getObjKind()); -} -}; -template <> struct FoldingSetTrait<RetEffect> { - static inline void Profile(const RetEffect &X, FoldingSetNodeID &ID) { - ID.AddInteger((unsigned) X.getKind()); - ID.AddInteger((unsigned) X.getObjKind()); -} -}; - -template <> struct DenseMapInfo<ObjCSummaryKey> { - static inline ObjCSummaryKey getEmptyKey() { - return ObjCSummaryKey(DenseMapInfo<IdentifierInfo*>::getEmptyKey(), - DenseMapInfo<Selector>::getEmptyKey()); - } - - static inline ObjCSummaryKey getTombstoneKey() { - return ObjCSummaryKey(DenseMapInfo<IdentifierInfo*>::getTombstoneKey(), - DenseMapInfo<Selector>::getTombstoneKey()); - } - - static unsigned getHashValue(const ObjCSummaryKey &V) { - typedef std::pair<IdentifierInfo*, Selector> PairTy; - return DenseMapInfo<PairTy>::getHashValue(PairTy(V.getIdentifier(), - V.getSelector())); - } - - static bool isEqual(const ObjCSummaryKey& LHS, const ObjCSummaryKey& RHS) { - return LHS.getIdentifier() == RHS.getIdentifier() && - LHS.getSelector() == RHS.getSelector(); - } - -}; - -} // end llvm namespace - - -namespace clang { -namespace ento { - -/// ArgEffects summarizes the effects of a function/method call on all of -/// its arguments. -typedef llvm::ImmutableMap<unsigned, ArgEffect> ArgEffects; - -/// Summary for a function with respect to ownership changes. -class RetainSummary { - /// Args - a map of (index, ArgEffect) pairs, where index - /// specifies the argument (starting from 0). This can be sparsely - /// populated; arguments with no entry in Args use 'DefaultArgEffect'. - ArgEffects Args; - - /// DefaultArgEffect - The default ArgEffect to apply to arguments that - /// do not have an entry in Args. - ArgEffect DefaultArgEffect; - - /// Receiver - If this summary applies to an Objective-C message expression, - /// this is the effect applied to the state of the receiver. - ArgEffect Receiver; - - /// Effect on "this" pointer - applicable only to C++ method calls. - ArgEffect This; - - /// Ret - The effect on the return value. Used to indicate if the - /// function/method call returns a new tracked symbol. - RetEffect Ret; - -public: - RetainSummary(ArgEffects A, - RetEffect R, - ArgEffect defaultEff, - ArgEffect ReceiverEff, - ArgEffect ThisEff) - : Args(A), DefaultArgEffect(defaultEff), Receiver(ReceiverEff), - This(ThisEff), Ret(R) {} - - /// getArg - Return the argument effect on the argument specified by - /// idx (starting from 0). - ArgEffect getArg(unsigned idx) const { - if (const ArgEffect *AE = Args.lookup(idx)) - return *AE; - - return DefaultArgEffect; - } - - void addArg(ArgEffects::Factory &af, unsigned idx, ArgEffect e) { - Args = af.add(Args, idx, e); - } - - /// setDefaultArgEffect - Set the default argument effect. - void setDefaultArgEffect(ArgEffect E) { - DefaultArgEffect = E; - } - - /// getRetEffect - Returns the effect on the return value of the call. - RetEffect getRetEffect() const { return Ret; } - - /// setRetEffect - Set the effect of the return value of the call. - void setRetEffect(RetEffect E) { Ret = E; } - - - /// Sets the effect on the receiver of the message. - void setReceiverEffect(ArgEffect e) { Receiver = e; } - - /// getReceiverEffect - Returns the effect on the receiver of the call. - /// 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. - /// This is only meaningful if the summary applies to CXXMethodDecl*. - 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.getKind() == DoNothing - && DefaultArgEffect.getKind() == MayEscape && This.getKind() == DoNothing - && Args.isEmpty(); - } - - /// Test if two retain summaries are identical. Note that merely equivalent - /// summaries are not necessarily identical (for example, if an explicit - /// argument effect matches the default effect). - bool operator==(const RetainSummary &Other) const { - return Args == Other.Args && DefaultArgEffect == Other.DefaultArgEffect && - Receiver == Other.Receiver && This == Other.This && Ret == Other.Ret; - } - - /// Profile this summary for inclusion in a FoldingSet. - void Profile(llvm::FoldingSetNodeID& ID) const { - ID.Add(Args); - ID.Add(DefaultArgEffect); - ID.Add(Receiver); - ID.Add(This); - ID.Add(Ret); - } - - /// A retain summary is simple if it has no ArgEffects other than the default. - bool isSimple() const { - return Args.isEmpty(); - } - - ArgEffects getArgEffects() const { return Args; } - -private: - ArgEffect getDefaultArgEffect() const { return DefaultArgEffect; } - - friend class RetainSummaryManager; -}; - -class ObjCSummaryCache { - typedef llvm::DenseMap<ObjCSummaryKey, const RetainSummary *> MapTy; - MapTy M; -public: - ObjCSummaryCache() {} - - const RetainSummary * find(const ObjCInterfaceDecl *D, Selector S) { - // Do a lookup with the (D,S) pair. If we find a match return - // the iterator. - ObjCSummaryKey K(D, S); - MapTy::iterator I = M.find(K); - - if (I != M.end()) - return I->second; - if (!D) - return nullptr; - - // Walk the super chain. If we find a hit with a parent, we'll end - // up returning that summary. We actually allow that key (null,S), as - // we cache summaries for the null ObjCInterfaceDecl* to allow us to - // generate initial summaries without having to worry about NSObject - // being declared. - // FIXME: We may change this at some point. - for (ObjCInterfaceDecl *C=D->getSuperClass() ;; C=C->getSuperClass()) { - if ((I = M.find(ObjCSummaryKey(C, S))) != M.end()) - break; - - if (!C) - return nullptr; - } - - // Cache the summary with original key to make the next lookup faster - // and return the iterator. - const RetainSummary *Summ = I->second; - M[K] = Summ; - return Summ; - } - - const RetainSummary *find(IdentifierInfo* II, Selector S) { - // FIXME: Class method lookup. Right now we don't have a good way - // of going between IdentifierInfo* and the class hierarchy. - MapTy::iterator I = M.find(ObjCSummaryKey(II, S)); - - if (I == M.end()) - I = M.find(ObjCSummaryKey(S)); - - return I == M.end() ? nullptr : I->second; - } - - const RetainSummary *& operator[](ObjCSummaryKey K) { - return M[K]; - } - - const RetainSummary *& operator[](Selector S) { - return M[ ObjCSummaryKey(S) ]; - } -}; - -class RetainSummaryTemplate; - -class RetainSummaryManager { - typedef llvm::DenseMap<const FunctionDecl*, const RetainSummary *> - FuncSummariesTy; - - typedef ObjCSummaryCache ObjCMethodSummariesTy; - - typedef llvm::FoldingSetNodeWrapper<RetainSummary> CachedSummaryNode; - - /// Ctx - The ASTContext object for the analyzed ASTs. - ASTContext &Ctx; - - /// Records whether or not the analyzed code runs in ARC mode. - const bool ARCEnabled; - - /// Track Objective-C and CoreFoundation objects. - const bool TrackObjCAndCFObjects; - - /// Track sublcasses of OSObject. - const bool TrackOSObjects; - - /// FuncSummaries - A map from FunctionDecls to summaries. - FuncSummariesTy FuncSummaries; - - /// ObjCClassMethodSummaries - A map from selectors (for instance methods) - /// to summaries. - ObjCMethodSummariesTy ObjCClassMethodSummaries; - - /// ObjCMethodSummaries - A map from selectors to summaries. - ObjCMethodSummariesTy ObjCMethodSummaries; - - /// BPAlloc - A BumpPtrAllocator used for allocating summaries, ArgEffects, - /// and all other data used by the checker. - llvm::BumpPtrAllocator BPAlloc; - - /// AF - A factory for ArgEffects objects. - ArgEffects::Factory AF; - - /// ObjCAllocRetE - Default return effect for methods returning Objective-C - /// objects. - RetEffect ObjCAllocRetE; - - /// ObjCInitRetE - Default return effect for init methods returning - /// Objective-C objects. - RetEffect ObjCInitRetE; - - /// SimpleSummaries - Used for uniquing summaries that don't have special - /// effects. - llvm::FoldingSet<CachedSummaryNode> SimpleSummaries; - - /// Create an OS object at +1. - const RetainSummary *getOSSummaryCreateRule(const FunctionDecl *FD); - - /// Get an OS object at +0. - const RetainSummary *getOSSummaryGetRule(const FunctionDecl *FD); - - /// Increment the reference count on OS object. - const RetainSummary *getOSSummaryRetainRule(const FunctionDecl *FD); - - /// Decrement the reference count on OS object. - const RetainSummary *getOSSummaryReleaseRule(const FunctionDecl *FD); - - /// Free the OS object. - const RetainSummary *getOSSummaryFreeRule(const FunctionDecl *FD); - - const RetainSummary *getUnarySummary(const FunctionType* FT, - ArgEffectKind AE); - - const RetainSummary *getCFSummaryCreateRule(const FunctionDecl *FD); - const RetainSummary *getCFSummaryGetRule(const FunctionDecl *FD); - const RetainSummary *getCFCreateGetRuleSummary(const FunctionDecl *FD); - - const RetainSummary *getPersistentSummary(const RetainSummary &OldSumm); - - const RetainSummary * - getPersistentSummary(RetEffect RetEff, ArgEffects ScratchArgs, - ArgEffect ReceiverEff = ArgEffect(DoNothing), - ArgEffect DefaultEff = ArgEffect(MayEscape), - ArgEffect ThisEff = ArgEffect(DoNothing)) { - RetainSummary Summ(ScratchArgs, RetEff, DefaultEff, ReceiverEff, ThisEff); - return getPersistentSummary(Summ); - } - - const RetainSummary *getDoNothingSummary() { - return getPersistentSummary(RetEffect::MakeNoRet(), - ArgEffects(AF.getEmptyMap()), - ArgEffect(DoNothing), ArgEffect(DoNothing)); - } - - const RetainSummary *getDefaultSummary() { - return getPersistentSummary(RetEffect::MakeNoRet(), - ArgEffects(AF.getEmptyMap()), - ArgEffect(DoNothing), ArgEffect(MayEscape)); - } - - const RetainSummary *getPersistentStopSummary() { - return getPersistentSummary( - RetEffect::MakeNoRet(), ArgEffects(AF.getEmptyMap()), - ArgEffect(StopTracking), ArgEffect(StopTracking)); - } - - void InitializeClassMethodSummaries(); - void InitializeMethodSummaries(); - - void addNSObjectClsMethSummary(Selector S, const RetainSummary *Summ) { - ObjCClassMethodSummaries[S] = Summ; - } - - void addNSObjectMethSummary(Selector S, const RetainSummary *Summ) { - ObjCMethodSummaries[S] = Summ; - } - - void addClassMethSummary(const char* Cls, const char* name, - const RetainSummary *Summ, bool isNullary = true) { - IdentifierInfo* ClsII = &Ctx.Idents.get(Cls); - Selector S = isNullary ? GetNullarySelector(name, Ctx) - : GetUnarySelector(name, Ctx); - ObjCClassMethodSummaries[ObjCSummaryKey(ClsII, S)] = Summ; - } - - void addInstMethSummary(const char* Cls, const char* nullaryName, - const RetainSummary *Summ) { - IdentifierInfo* ClsII = &Ctx.Idents.get(Cls); - Selector S = GetNullarySelector(nullaryName, Ctx); - ObjCMethodSummaries[ObjCSummaryKey(ClsII, S)] = Summ; - } - - template <typename... Keywords> - void addMethodSummary(IdentifierInfo *ClsII, ObjCMethodSummariesTy &Summaries, - const RetainSummary *Summ, Keywords *... Kws) { - Selector S = getKeywordSelector(Ctx, Kws...); - Summaries[ObjCSummaryKey(ClsII, S)] = Summ; - } - - template <typename... Keywords> - void addInstMethSummary(const char *Cls, const RetainSummary *Summ, - Keywords *... Kws) { - addMethodSummary(&Ctx.Idents.get(Cls), ObjCMethodSummaries, Summ, Kws...); - } - - template <typename... Keywords> - void addClsMethSummary(const char *Cls, const RetainSummary *Summ, - Keywords *... Kws) { - addMethodSummary(&Ctx.Idents.get(Cls), ObjCClassMethodSummaries, Summ, - Kws...); - } - - template <typename... Keywords> - void addClsMethSummary(IdentifierInfo *II, const RetainSummary *Summ, - Keywords *... Kws) { - addMethodSummary(II, ObjCClassMethodSummaries, Summ, Kws...); - } - - 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 applyParamAnnotationEffect(const ParmVarDecl *pd, unsigned parm_idx, - const NamedDecl *FD, - RetainSummaryTemplate &Template); - -public: - RetainSummaryManager(ASTContext &ctx, - bool usesARC, - bool trackObjCAndCFObjects, - bool trackOSObjects) - : Ctx(ctx), - ARCEnabled(usesARC), - TrackObjCAndCFObjects(trackObjCAndCFObjects), - TrackOSObjects(trackOSObjects), - AF(BPAlloc), - ObjCAllocRetE(usesARC ? RetEffect::MakeNotOwned(ObjKind::ObjC) - : RetEffect::MakeOwned(ObjKind::ObjC)), - ObjCInitRetE(usesARC ? RetEffect::MakeNotOwned(ObjKind::ObjC) - : RetEffect::MakeOwnedWhenTrackedReceiver()) { - InitializeClassMethodSummaries(); - InitializeMethodSummaries(); - } - - 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); - - const RetainSummary *getSummary(const CallEvent &Call, - QualType ReceiverType=QualType()); - - const RetainSummary *getFunctionSummary(const FunctionDecl *FD); - - const RetainSummary *getMethodSummary(Selector S, const ObjCInterfaceDecl *ID, - const ObjCMethodDecl *MD, - QualType RetTy, - ObjCMethodSummariesTy &CachedSummaries); - - const RetainSummary * - getInstanceMethodSummary(const ObjCMethodCall &M, - QualType ReceiverType); - - const RetainSummary *getClassMethodSummary(const ObjCMethodCall &M) { - assert(!M.isInstanceMessage()); - const ObjCInterfaceDecl *Class = M.getReceiverInterface(); - - return getMethodSummary(M.getSelector(), Class, M.getDecl(), - M.getResultType(), ObjCClassMethodSummaries); - } - - /// getMethodSummary - This version of getMethodSummary is used to query - /// the summary for the current method being analyzed. - const RetainSummary *getMethodSummary(const ObjCMethodDecl *MD) { - const ObjCInterfaceDecl *ID = MD->getClassInterface(); - Selector S = MD->getSelector(); - QualType ResultTy = MD->getReturnType(); - - ObjCMethodSummariesTy *CachedSummaries; - if (MD->isInstanceMethod()) - CachedSummaries = &ObjCMethodSummaries; - else - CachedSummaries = &ObjCClassMethodSummaries; - - return getMethodSummary(S, ID, MD, ResultTy, *CachedSummaries); - } - - const RetainSummary *getStandardMethodSummary(const ObjCMethodDecl *MD, - Selector S, QualType RetTy); - - /// Determine if there is a special return effect for this function or method. - Optional<RetEffect> getRetEffectFromAnnotations(QualType RetTy, - const Decl *D); - - void updateSummaryFromAnnotations(const RetainSummary *&Summ, - const ObjCMethodDecl *MD); - - void updateSummaryFromAnnotations(const RetainSummary *&Summ, - const FunctionDecl *FD); - - - void updateSummaryForCall(const RetainSummary *&Summ, - const CallEvent &Call); - - bool isARCEnabled() const { return ARCEnabled; } - - RetEffect getObjAllocRetEffect() const { return ObjCAllocRetE; } - - /// Determine whether a declaration {@code D} of correspondent type (return - /// type for functions/methods) {@code QT} has any of the given attributes, - /// provided they pass necessary validation checks AND tracking the given - /// attribute is enabled. - /// Returns the object kind corresponding to the present attribute, or None, - /// if none of the specified attributes are present. - /// Crashes if passed an attribute which is not explicitly handled. - template <class T> - Optional<ObjKind> hasAnyEnabledAttrOf(const Decl *D, QualType QT); - - template <class T1, class T2, class... Others> - Optional<ObjKind> hasAnyEnabledAttrOf(const Decl *D, QualType QT); - - 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 -// and then copied into managed memory. -class RetainSummaryTemplate { - RetainSummaryManager &Manager; - const RetainSummary *&RealSummary; - RetainSummary ScratchSummary; - bool Accessed; -public: - RetainSummaryTemplate(const RetainSummary *&real, RetainSummaryManager &mgr) - : Manager(mgr), RealSummary(real), ScratchSummary(*real), Accessed(false) {} - - ~RetainSummaryTemplate() { - if (Accessed) - RealSummary = Manager.getPersistentSummary(ScratchSummary); - } - - RetainSummary &operator*() { - Accessed = true; - return ScratchSummary; - } - - RetainSummary *operator->() { - Accessed = true; - return &ScratchSummary; - } -}; - -} // end namespace ento -} // end namespace clang - -#endif diff --git a/include/clang/StaticAnalyzer/Frontend/AnalysisConsumer.h b/include/clang/StaticAnalyzer/Frontend/AnalysisConsumer.h index 59fbbc3ca80f..2d24e6a9586b 100644 --- a/include/clang/StaticAnalyzer/Frontend/AnalysisConsumer.h +++ b/include/clang/StaticAnalyzer/Frontend/AnalysisConsumer.h @@ -1,9 +1,8 @@ //===--- AnalysisConsumer.h - Front-end Analysis Engine Hooks ---*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/include/clang/StaticAnalyzer/Frontend/CheckerRegistration.h b/include/clang/StaticAnalyzer/Frontend/CheckerRegistration.h index 61709548aed1..52a534499002 100644 --- a/include/clang/StaticAnalyzer/Frontend/CheckerRegistration.h +++ b/include/clang/StaticAnalyzer/Frontend/CheckerRegistration.h @@ -1,9 +1,8 @@ //===-- CheckerRegistration.h - Checker Registration Function ---*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// diff --git a/include/clang/StaticAnalyzer/Frontend/CheckerRegistry.h b/include/clang/StaticAnalyzer/Frontend/CheckerRegistry.h index 966234492fe0..bc258160ada4 100644 --- a/include/clang/StaticAnalyzer/Frontend/CheckerRegistry.h +++ b/include/clang/StaticAnalyzer/Frontend/CheckerRegistry.h @@ -1,9 +1,8 @@ //===- CheckerRegistry.h - Maintains all available checkers -----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// @@ -70,6 +69,7 @@ namespace clang { class AnalyzerOptions; class DiagnosticsEngine; +class LangOptions; namespace ento { @@ -81,73 +81,245 @@ namespace ento { /// "core.builtin", or the full name "core.builtin.NoReturnFunctionChecker". class CheckerRegistry { public: - CheckerRegistry(ArrayRef<std::string> plugins, DiagnosticsEngine &diags); + CheckerRegistry(ArrayRef<std::string> plugins, DiagnosticsEngine &diags, + AnalyzerOptions &AnOpts, const LangOptions &LangOpts, + ArrayRef<std::function<void(CheckerRegistry &)>> + checkerRegistrationFns = {}); /// Initialization functions perform any necessary setup for a checker. /// They should include a call to CheckerManager::registerChecker. using InitializationFunction = void (*)(CheckerManager &); + using ShouldRegisterFunction = bool (*)(const LangOptions &); + + /// Specifies a command line option. It may either belong to a checker or a + /// package. + struct CmdLineOption { + StringRef OptionType; + StringRef OptionName; + StringRef DefaultValStr; + StringRef Description; + StringRef DevelopmentStatus; + bool IsHidden; + + CmdLineOption(StringRef OptionType, StringRef OptionName, + StringRef DefaultValStr, StringRef Description, + StringRef DevelopmentStatus, bool IsHidden) + : OptionType(OptionType), OptionName(OptionName), + DefaultValStr(DefaultValStr), Description(Description), + DevelopmentStatus(DevelopmentStatus), IsHidden(IsHidden) { + + assert((OptionType == "bool" || OptionType == "string" || + OptionType == "int") && + "Unknown command line option type!"); + + assert((OptionType != "bool" || + (DefaultValStr == "true" || DefaultValStr == "false")) && + "Invalid value for boolean command line option! Maybe incorrect " + "parameters to the addCheckerOption or addPackageOption method?"); + + int Tmp; + assert((OptionType != "int" || !DefaultValStr.getAsInteger(0, Tmp)) && + "Invalid value for integer command line option! Maybe incorrect " + "parameters to the addCheckerOption or addPackageOption method?"); + (void)Tmp; + + assert((DevelopmentStatus == "alpha" || DevelopmentStatus == "beta" || + DevelopmentStatus == "released") && + "Invalid development status!"); + } + }; + + using CmdLineOptionList = llvm::SmallVector<CmdLineOption, 0>; + + struct CheckerInfo; + using CheckerInfoList = std::vector<CheckerInfo>; + using CheckerInfoListRange = llvm::iterator_range<CheckerInfoList::iterator>; + using ConstCheckerInfoList = llvm::SmallVector<const CheckerInfo *, 0>; + using CheckerInfoSet = llvm::SetVector<const CheckerInfo *>; + + /// Specifies a checker. Note that this isn't what we call a checker object, + /// it merely contains everything required to create one. struct CheckerInfo { - InitializationFunction Initialize; + enum class StateFromCmdLine { + // This checker wasn't explicitly enabled or disabled. + State_Unspecified, + // This checker was explicitly disabled. + State_Disabled, + // This checker was explicitly enabled. + State_Enabled + }; + + InitializationFunction Initialize = nullptr; + ShouldRegisterFunction ShouldRegister = nullptr; StringRef FullName; StringRef Desc; StringRef DocumentationUri; + CmdLineOptionList CmdLineOptions; + bool IsHidden = false; + StateFromCmdLine State = StateFromCmdLine::State_Unspecified; + + ConstCheckerInfoList Dependencies; + + bool isEnabled(const LangOptions &LO) const { + return State == StateFromCmdLine::State_Enabled && ShouldRegister(LO); + } - CheckerInfo(InitializationFunction Fn, StringRef Name, StringRef Desc, - StringRef DocsUri) - : Initialize(Fn), FullName(Name), Desc(Desc), - DocumentationUri(DocsUri) {} + bool isDisabled(const LangOptions &LO) const { + return State == StateFromCmdLine::State_Disabled && ShouldRegister(LO); + } + + // Since each checker must have a different full name, we can identify + // CheckerInfo objects by them. + bool operator==(const CheckerInfo &Rhs) const { + return FullName == Rhs.FullName; + } + + CheckerInfo(InitializationFunction Fn, ShouldRegisterFunction sfn, + StringRef Name, StringRef Desc, StringRef DocsUri, + bool IsHidden) + : Initialize(Fn), ShouldRegister(sfn), FullName(Name), Desc(Desc), + DocumentationUri(DocsUri), IsHidden(IsHidden) {} + + // Used for lower_bound. + explicit CheckerInfo(StringRef FullName) : FullName(FullName) {} }; - using CheckerInfoList = std::vector<CheckerInfo>; - using CheckerInfoSet = llvm::SetVector<const CheckerRegistry::CheckerInfo *>; + using StateFromCmdLine = CheckerInfo::StateFromCmdLine; + + /// Specifies a package. Each package option is implicitly an option for all + /// checkers within the package. + struct PackageInfo { + StringRef FullName; + CmdLineOptionList CmdLineOptions; + + // Since each package must have a different full name, we can identify + // CheckerInfo objects by them. + bool operator==(const PackageInfo &Rhs) const { + return FullName == Rhs.FullName; + } + + explicit PackageInfo(StringRef FullName) : FullName(FullName) {} + }; + + using PackageInfoList = llvm::SmallVector<PackageInfo, 0>; private: - template <typename T> - static void initializeManager(CheckerManager &mgr) { + template <typename T> static void initializeManager(CheckerManager &mgr) { mgr.registerChecker<T>(); } + template <typename T> static bool returnTrue(const LangOptions &LO) { + return true; + } + public: /// Adds a checker to the registry. Use this non-templated overload when your /// checker requires custom initialization. - void addChecker(InitializationFunction Fn, StringRef FullName, StringRef Desc, - StringRef DocsUri); + void addChecker(InitializationFunction Fn, ShouldRegisterFunction sfn, + StringRef FullName, StringRef Desc, StringRef DocsUri, + bool IsHidden); /// Adds a checker to the registry. Use this templated overload when your /// checker does not require any custom initialization. template <class T> - void addChecker(StringRef FullName, StringRef Desc, StringRef DocsUri) { + void addChecker(StringRef FullName, StringRef Desc, StringRef DocsUri, + bool IsHidden = false) { // Avoid MSVC's Compiler Error C2276: // http://msdn.microsoft.com/en-us/library/850cstw1(v=VS.80).aspx - addChecker(&CheckerRegistry::initializeManager<T>, FullName, Desc, DocsUri); + addChecker(&CheckerRegistry::initializeManager<T>, + &CheckerRegistry::returnTrue<T>, FullName, Desc, DocsUri, + IsHidden); } + /// Makes the checker with the full name \p fullName depends on the checker + /// called \p dependency. + void addDependency(StringRef FullName, StringRef Dependency); + + /// Registers an option to a given checker. A checker option will always have + /// the following format: + /// CheckerFullName:OptionName=Value + /// And can be specified from the command line like this: + /// -analyzer-config CheckerFullName:OptionName=Value + /// + /// Options for unknown checkers, or unknown options for a given checker, or + /// invalid value types for that given option are reported as an error in + /// non-compatibility mode. + void addCheckerOption(StringRef OptionType, StringRef CheckerFullName, + StringRef OptionName, StringRef DefaultValStr, + StringRef Description, StringRef DevelopmentStatus, + bool IsHidden = false); + + /// Adds a package to the registry. + void addPackage(StringRef FullName); + + /// Registers an option to a given package. A package option will always have + /// the following format: + /// PackageFullName:OptionName=Value + /// And can be specified from the command line like this: + /// -analyzer-config PackageFullName:OptionName=Value + /// + /// Options for unknown packages, or unknown options for a given package, or + /// invalid value types for that given option are reported as an error in + /// non-compatibility mode. + void addPackageOption(StringRef OptionType, StringRef PackageFullName, + StringRef OptionName, StringRef DefaultValStr, + StringRef Description, StringRef DevelopmentStatus, + bool IsHidden = false); + + // FIXME: This *really* should be added to the frontend flag descriptions. /// Initializes a CheckerManager by calling the initialization functions for /// 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, - const AnalyzerOptions &Opts) const; + void initializeManager(CheckerManager &CheckerMgr) const; /// Check if every option corresponds to a specific checker or package. - void validateCheckerOptions(const AnalyzerOptions &opts) const; + void validateCheckerOptions() const; /// 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, const AnalyzerOptions &opts) const; + void printCheckerWithDescList(raw_ostream &Out, + size_t MaxNameChars = 30) const; + void printEnabledCheckerList(raw_ostream &Out) const; + void printCheckerOptionList(raw_ostream &Out) const; private: - CheckerInfoSet getEnabledCheckers(const AnalyzerOptions &Opts) const; + /// Collect all enabled checkers. The returned container preserves the order + /// of insertion, as dependencies have to be enabled before the checkers that + /// depend on them. + CheckerInfoSet getEnabledCheckers() const; + + /// Return an iterator range of mutable CheckerInfos \p CmdLineArg applies to. + /// For example, it'll return the checkers for the core package, if + /// \p CmdLineArg is "core". + CheckerInfoListRange getMutableCheckersForCmdLineArg(StringRef CmdLineArg); + + CheckerInfoList Checkers; + PackageInfoList Packages; + /// Used for couting how many checkers belong to a certain package in the + /// \c Checkers field. For convenience purposes. + llvm::StringMap<size_t> PackageSizes; + + /// Contains all (Dependendent checker, Dependency) pairs. We need this, as + /// we'll resolve dependencies after all checkers were added first. + llvm::SmallVector<std::pair<StringRef, StringRef>, 0> Dependencies; + void resolveDependencies(); + + /// Contains all (FullName, CmdLineOption) pairs. Similarly to dependencies, + /// we only modify the actual CheckerInfo and PackageInfo objects once all + /// of them have been added. + llvm::SmallVector<std::pair<StringRef, CmdLineOption>, 0> PackageOptions; + llvm::SmallVector<std::pair<StringRef, CmdLineOption>, 0> CheckerOptions; + + void resolveCheckerAndPackageOptions(); - mutable CheckerInfoList Checkers; - mutable llvm::StringMap<size_t> Packages; DiagnosticsEngine &Diags; + AnalyzerOptions &AnOpts; + const LangOptions &LangOpts; }; } // namespace ento - } // namespace clang #endif // LLVM_CLANG_STATICANALYZER_CORE_CHECKERREGISTRY_H diff --git a/include/clang/StaticAnalyzer/Frontend/FrontendActions.h b/include/clang/StaticAnalyzer/Frontend/FrontendActions.h index 2e9d0502e6f3..878b65a1b143 100644 --- a/include/clang/StaticAnalyzer/Frontend/FrontendActions.h +++ b/include/clang/StaticAnalyzer/Frontend/FrontendActions.h @@ -1,9 +1,8 @@ //===-- FrontendActions.h - Useful Frontend Actions -------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// @@ -52,12 +51,20 @@ private: llvm::StringMap<Stmt *> &Bodies; }; -void printCheckerHelp(raw_ostream &OS, ArrayRef<std::string> plugins, - DiagnosticsEngine &diags); +void printCheckerHelp(raw_ostream &OS, + ArrayRef<std::string> plugins, + AnalyzerOptions &opts, + DiagnosticsEngine &diags, + const LangOptions &LangOpts); void printEnabledCheckerList(raw_ostream &OS, ArrayRef<std::string> plugins, - const AnalyzerOptions &opts, - DiagnosticsEngine &diags); + AnalyzerOptions &opts, + DiagnosticsEngine &diags, + const LangOptions &LangOpts); void printAnalyzerConfigList(raw_ostream &OS); +void printCheckerConfigList(raw_ostream &OS, ArrayRef<std::string> plugins, + AnalyzerOptions &opts, + DiagnosticsEngine &diags, + const LangOptions &LangOpts); } // end GR namespace diff --git a/include/clang/StaticAnalyzer/Frontend/ModelConsumer.h b/include/clang/StaticAnalyzer/Frontend/ModelConsumer.h index fa00ffd16553..5f9ae78dac63 100644 --- a/include/clang/StaticAnalyzer/Frontend/ModelConsumer.h +++ b/include/clang/StaticAnalyzer/Frontend/ModelConsumer.h @@ -1,9 +1,8 @@ //===-- ModelConsumer.h -----------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// /// |