r339135 - [analyzer][UninitializedObjectChecker] New flag to turn off dereferencing
Author: szelethus Date: Tue Aug 7 05:55:26 2018 New Revision: 339135 URL: http://llvm.org/viewvc/llvm-project?rev=339135&view=rev Log: [analyzer][UninitializedObjectChecker] New flag to turn off dereferencing Even for a checker being in alpha, some reports about pointees held so little value to the user that it's safer to disable pointer/reference chasing for now. It can be enabled with a new flag, in which case checker should function as it has always been. This can be set with `CheckPointeeInitialization`. Differential Revision: https://reviews.llvm.org/D49438 Added: cfe/trunk/test/Analysis/cxx-uninitialized-object-no-dereference.cpp Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObjectChecker.cpp cfe/trunk/test/Analysis/cxx-uninitialized-object-inheritance.cpp cfe/trunk/test/Analysis/cxx-uninitialized-object-notes-as-warnings.cpp cfe/trunk/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp cfe/trunk/test/Analysis/cxx-uninitialized-object.cpp Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObjectChecker.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObjectChecker.cpp?rev=339135&r1=339134&r2=339135&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObjectChecker.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObjectChecker.cpp Tue Aug 7 05:55:26 2018 @@ -10,19 +10,33 @@ // This file defines a checker that reports uninitialized fields in objects // created after a constructor call. // -// This checker has two options: +// This checker has several options: // - "Pedantic" (boolean). If its not set or is set to false, the checker // won't emit warnings for objects that don't have at least one initialized // field. This may be set with // -// `-analyzer-config alpha.cplusplus.UninitializedObject:Pedantic=true`. +// `-analyzer-config alpha.cplusplus.UninitializedObject:Pedantic=true`. // // - "NotesAsWarnings" (boolean). 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. Defaults to false. // -// `-analyzer-config alpha.cplusplus.UninitializedObject:NotesAsWarnings=true`. +// `-analyzer-config \ +// alpha.cplusplus.UninitializedObject:NotesAsWarnings=true`. +// +// - "CheckPointeeInitialization" (boolean). 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. Defaults to false. +// +// `-analyzer-config \ +// alpha.cplusplus.UninitializedObject:CheckPointeeInitialization=true`. +// +// TODO: With some clever heuristics, some pointers should be dereferenced +// by default. For example, if the pointee is constructed within the +// constructor call, it's reasonable to say that no external object +// references it, and we wouldn't generate multiple report on the same +// pointee. // //===--===// @@ -44,6 +58,7 @@ public: // These fields will be initialized when registering the checker. bool IsPedantic; bool ShouldConvertNotesToWarnings; + bool CheckPointeeInitialization; UninitializedObjectChecker() : BT_uninitField(new BuiltinBug(this, "Uninitialized fields")) {} @@ -109,13 +124,16 @@ class FindUninitializedFields { const TypedValueRegion *const ObjectR; const bool IsPedantic; + const bool CheckPointeeInitialization; + bool IsAnyFieldInitialized = false; UninitFieldSet UninitFields; public: FindUninitializedFields(ProgramStateRef State, - const TypedValueRegion *const R, bool IsPedantic); + const TypedValueRegion *const R, bool IsPedantic, + bool CheckPointeeInitialization); const UninitFieldSet &getUninitFields(); private: @@ -262,8 +280,8 @@ void UninitializedObjectChecker::checkEn if (!Object) return; - FindUninitializedFields F(Context.getState(), Object->getRegion(), -IsPedantic); + FindUninitializedFields F(Context.getState(), Object->getRegion(), IsPedantic, +CheckPointeeInitialization); const UninitFieldSet &UninitFields = F.getUninitFields(); @@ -327,8 +345,10 @@ void UninitializedObjectChecker::checkEn //===--===// FindUninitializedFields::FindUninitializedFields( -ProgramStateRef State, const TypedValueRegion *const R, bool IsPedantic) -: State(State), ObjectR(R), IsPedantic(IsPedantic) {} +ProgramStateRef State, const TypedValueRegion *const R, bool IsPedantic, +bool Ch
r339237 - [analyzer][UninitializedObjectChecker] Fixed a false negative by no longer filtering out certain constructor calls
Author: szelethus Date: Wed Aug 8 05:23:02 2018 New Revision: 339237 URL: http://llvm.org/viewvc/llvm-project?rev=339237&view=rev Log: [analyzer][UninitializedObjectChecker] Fixed a false negative by no longer filtering out certain constructor calls As of now, all constructor calls are ignored that are being called by a constructor. The point of this was not to analyze the fields of an object, so an uninitialized field wouldn't be reported multiple times. This however introduced false negatives when the two constructors were in no relation to one another -- see the test file for a neat example for this with singletons. This patch aims so fix this issue. Differential Revision: https://reviews.llvm.org/D48436 Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObjectChecker.cpp cfe/trunk/test/Analysis/cxx-uninitialized-object.cpp Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObjectChecker.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObjectChecker.cpp?rev=339237&r1=339236&r2=339237&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObjectChecker.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObjectChecker.cpp Wed Aug 8 05:23:02 2018 @@ -225,12 +225,16 @@ static llvm::ImmutableListFactory getObjectVal(const CXXConstructorDecl *CtorDecl, CheckerContext &Context); -/// Checks whether the constructor under checking is called by another -/// constructor. -static bool isCalledByConstructor(const CheckerContext &Context); +/// Checks whether the object constructed by \p Ctor will be analyzed later +/// (e.g. if the object is a field of another object, in which case we'd check +/// it multiple times). +static bool willObjectBeAnalyzedLater(const CXXConstructorDecl *Ctor, + CheckerContext &Context); /// Returns whether FD can be (transitively) dereferenced to a void pointer type /// (void*, void**, ...). The type of the region behind a void pointer isn't @@ -273,7 +277,7 @@ void UninitializedObjectChecker::checkEn return; // This avoids essentially the same error being reported multiple times. - if (isCalledByConstructor(Context)) + if (willObjectBeAnalyzedLater(CtorDecl, Context)) return; Optional Object = getObjectVal(CtorDecl, Context); @@ -433,8 +437,8 @@ bool FindUninitializedFields::isNonUnion } // Checking bases. - // FIXME: As of now, because of `isCalledByConstructor`, objects whose type - // is a descendant of another type will emit warnings for uninitalized + // FIXME: As of now, because of `willObjectBeAnalyzedLater`, objects whose + // type is a descendant of another type will emit warnings for uninitalized // inherited members. // This is not the only way to analyze bases of an object -- if we didn't // filter them out, and didn't analyze the bases, this checker would run for @@ -661,18 +665,32 @@ getObjectVal(const CXXConstructorDecl *C return Object.getAs(); } -// TODO: We should also check that if the constructor was called by another -// constructor, whether those two are in any relation to one another. In it's -// current state, this introduces some false negatives. -static bool isCalledByConstructor(const CheckerContext &Context) { - const LocationContext *LC = Context.getLocationContext()->getParent(); +static bool willObjectBeAnalyzedLater(const CXXConstructorDecl *Ctor, + CheckerContext &Context) { - while (LC) { -if (isa(LC->getDecl())) - return true; + Optional CurrentObject = getObjectVal(Ctor, Context); + if (!CurrentObject) +return false; + + const LocationContext *LC = Context.getLocationContext(); + while ((LC = LC->getParent())) { + +// If \p Ctor was called by another constructor. +const auto *OtherCtor = dyn_cast(LC->getDecl()); +if (!OtherCtor) + continue; -LC = LC->getParent(); +Optional OtherObject = +getObjectVal(OtherCtor, Context); +if (!OtherObject) + continue; + +// If the CurrentObject is a subregion of OtherObject, it will be analyzed +// during the analysis of OtherObject. +if (CurrentObject->getRegion()->isSubRegionOf(OtherObject->getRegion())) + return true; } + return false; } Modified: cfe/trunk/test/Analysis/cxx-uninitialized-object.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/cxx-uninitialized-object.cpp?rev=339237&r1=339236&r2=339237&view=diff == --- cfe/trunk/test/Analysis/cxx-uninitialized-object.cpp (original) +++ cfe/trunk/test/Analysis/cxx-uninitialized-object.cpp Wed Aug 8 05:23:02 2018 @@ -1040,13 +1040,12 @@ void assert(int b) { // While a singleton would make more sense as a static variable, that would zero // initialize all of its fields, he
r339240 - [analyzer][UninitializedObjectChecker] Pointer/reference objects are dereferenced according to dynamic type
Author: szelethus Date: Wed Aug 8 06:18:53 2018 New Revision: 339240 URL: http://llvm.org/viewvc/llvm-project?rev=339240&view=rev Log: [analyzer][UninitializedObjectChecker] Pointer/reference objects are dereferenced according to dynamic type This patch fixed an issue where the dynamic type of pointer/reference object was known by the analyzer, but wasn't obtained in the checker, which resulted in false negatives. This should also increase reliability of the checker, as derefencing is always done now according to the dynamic type (even if that happens to be the same as the static type). Special thanks to Artem Degrachev for setting me on the right track. Differential Revision: https://reviews.llvm.org/D49199 Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObjectChecker.cpp cfe/trunk/test/Analysis/cxx-uninitialized-object-inheritance.cpp cfe/trunk/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObjectChecker.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObjectChecker.cpp?rev=339240&r1=339239&r2=339240&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObjectChecker.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObjectChecker.cpp Wed Aug 8 06:18:53 2018 @@ -44,7 +44,7 @@ #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" #include "clang/StaticAnalyzer/Core/Checker.h" #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" -#include +#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeMap.h" using namespace clang; using namespace clang::ento; @@ -236,10 +236,10 @@ getObjectVal(const CXXConstructorDecl *C static bool willObjectBeAnalyzedLater(const CXXConstructorDecl *Ctor, CheckerContext &Context); -/// Returns whether FD can be (transitively) dereferenced to a void pointer type +/// Returns whether T can be (transitively) dereferenced to a void pointer type /// (void*, void**, ...). The type of the region behind a void pointer isn't /// known, and thus FD can not be analyzed. -static bool isVoidPointer(const FieldDecl *FD); +static bool isVoidPointer(QualType T); /// Returns true if T is a primitive type. We defined this type so that for /// objects that we'd only like analyze as much as checking whether their @@ -483,7 +483,7 @@ bool FindUninitializedFields::isPointerO SVal V = State->getSVal(FR); - if (V.isUnknown() || V.isZeroConstant()) { + if (V.isUnknown() || V.getAs()) { IsAnyFieldInitialized = true; return false; } @@ -497,48 +497,70 @@ bool FindUninitializedFields::isPointerO return false; } - const FieldDecl *FD = FR->getDecl(); + assert(V.getAs() && + "At this point V must be loc::MemRegionVal!"); + auto L = V.castAs(); + + // We can't reason about symbolic regions, assume its initialized. + // Note that this also avoids a potential infinite recursion, because + // constructors for list-like classes are checked without being called, and + // the Static Analyzer will construct a symbolic region for Node *next; or + // similar code snippets. + if (L.getRegion()->getSymbolicBase()) { +IsAnyFieldInitialized = true; +return false; + } - // TODO: The dynamic type of a void pointer may be retrieved with - // `getDynamicTypeInfo`. - if (isVoidPointer(FD)) { + DynamicTypeInfo DynTInfo = getDynamicTypeInfo(State, L.getRegion()); + if (!DynTInfo.isValid()) { IsAnyFieldInitialized = true; return false; } - assert(V.getAs() && "V should be Loc at this point!"); + QualType DynT = DynTInfo.getType(); + + if (isVoidPointer(DynT)) { +IsAnyFieldInitialized = true; +return false; + } // At this point the pointer itself is initialized and points to a valid // location, we'll now check the pointee. - SVal DerefdV = State->getSVal(V.castAs()); - - // TODO: Dereferencing should be done according to the dynamic type. - while (Optional L = DerefdV.getAs()) { -DerefdV = State->getSVal(*L); - } + SVal DerefdV = State->getSVal(V.castAs(), DynT); - // If V is a pointer pointing to a record type. - if (Optional RecordV = - DerefdV.getAs()) { + // If DerefdV is still a pointer value, we'll dereference it again (e.g.: + // int** -> int*). + while (auto Tmp = DerefdV.getAs()) { +if (Tmp->getRegion()->getSymbolicBase()) { + IsAnyFieldInitialized = true; + return false; +} -const TypedValueRegion *R = RecordV->getRegion(); +DynTInfo = getDynamicTypeInfo(State, Tmp->getRegion()); +if (!DynTInfo.isValid()) { + IsAnyFieldInitialized = true; + return false; +} -// We can't reason about symbolic regions, assume its initialized. -// Note that this also avoids a potential infinite recursion, because -// constructors f
r339591 - [analyzer][UninitializedObjectChecker] Refactoring p1.: ImmutableList factory is no longer static
Author: szelethus Date: Mon Aug 13 10:55:52 2018 New Revision: 339591 URL: http://llvm.org/viewvc/llvm-project?rev=339591&view=rev Log: [analyzer][UninitializedObjectChecker] Refactoring p1.: ImmutableList factory is no longer static This patch is the first part of a series of patches to refactor UninitializedObjectChecker. The goal of this effort is to Separate pointer chasing from the rest of the checker, Increase readability and reliability, Don't impact performance (too bad). In this one, ImmutableList's factory is moved to FindUninitializedFields. Differential Revision: https://reviews.llvm.org/D50503 Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObjectChecker.cpp Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObjectChecker.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObjectChecker.cpp?rev=339591&r1=339590&r2=339591&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObjectChecker.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObjectChecker.cpp Mon Aug 13 10:55:52 2018 @@ -73,17 +73,21 @@ public: /// Note that this class is immutable, and new fields may only be added through /// constructor calls. class FieldChainInfo { +public: using FieldChain = llvm::ImmutableList; +private: + FieldChain::Factory &Factory; FieldChain Chain; const bool IsDereferenced = false; public: - FieldChainInfo() = default; + FieldChainInfo() = delete; + FieldChainInfo(FieldChain::Factory &F) : Factory(F) {} FieldChainInfo(const FieldChainInfo &Other, const bool IsDereferenced) - : Chain(Other.Chain), IsDereferenced(IsDereferenced) {} + : Factory(Other.Factory), Chain(Other.Chain), IsDereferenced(IsDereferenced) {} FieldChainInfo(const FieldChainInfo &Other, const FieldRegion *FR, const bool IsDereferenced = false); @@ -128,6 +132,7 @@ class FindUninitializedFields { bool IsAnyFieldInitialized = false; + FieldChainInfo::FieldChain::Factory Factory; UninitFieldSet UninitFields; public: @@ -217,10 +222,6 @@ private: } // end of anonymous namespace -// Static variable instantionations. - -static llvm::ImmutableListFactory Factory; - // Utility function declarations. /// Returns the object that was constructed by CtorDecl, or None if that isn't @@ -355,7 +356,7 @@ FindUninitializedFields::FindUninitializ CheckPointeeInitialization(CheckPointeeInitialization) {} const UninitFieldSet &FindUninitializedFields::getUninitFields() { - isNonUnionUninit(ObjectR, FieldChainInfo()); + isNonUnionUninit(ObjectR, FieldChainInfo(Factory)); if (!IsPedantic && !IsAnyFieldInitialized) UninitFields.clear(); ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r339595 - [analyzer][UninitializedObjectChecker] Refactoring p2.: Moving pointer chasing to a separate file
Author: szelethus Date: Mon Aug 13 11:17:05 2018 New Revision: 339595 URL: http://llvm.org/viewvc/llvm-project?rev=339595&view=rev Log: [analyzer][UninitializedObjectChecker] Refactoring p2.: Moving pointer chasing to a separate file In this patch, the following classes and functions have been moved to a header file: FieldChainInfo FindUninitializedFields isPrimitiveType This also meant that they moved from anonymous namespace to clang::ento. Code related to pointer chasing now relies in its own file. There's absolutely no functional change in this patch -- its literally just copy pasting. Differential Revision: https://reviews.llvm.org/D50504 Added: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/ cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp Removed: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObjectChecker.cpp Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/CMakeLists.txt Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/CMakeLists.txt URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/CMakeLists.txt?rev=339595&r1=339594&r2=339595&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Checkers/CMakeLists.txt (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/CMakeLists.txt Mon Aug 13 11:17:05 2018 @@ -93,7 +93,8 @@ add_clang_library(clangStaticAnalyzerChe UndefResultChecker.cpp UndefinedArraySubscriptChecker.cpp UndefinedAssignmentChecker.cpp - UninitializedObjectChecker.cpp + UninitializedObject/UninitializedObjectChecker.cpp + UninitializedObject/UninitializedPointee.cpp UnixAPIChecker.cpp UnreachableCodeChecker.cpp VforkChecker.cpp Added: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h?rev=339595&view=auto == --- cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h (added) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h Mon Aug 13 11:17:05 2018 @@ -0,0 +1,196 @@ +//===- UninitializedObject.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 helper classes for UninitializedObjectChecker and +// documentation about the logic of it. +// +// To read about command line options and a description what this checker does, +// refer to UninitializedObjectChecker.cpp. +// +// Some methods are implemented in UninitializedPointee.cpp, to reduce the +// complexity of the main checker file. +// +//===--===// + +#ifndef LLVM_CLANG_STATICANALYZER_UNINITIALIZEDOBJECT_H +#define LLVM_CLANG_STATICANALYZER_UNINITIALIZEDOBJECT_H + +#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" + +namespace clang { +namespace ento { + +/// Represents a field chain. A field chain is a vector of fields where the +/// first element of the chain is the object under checking (not stored), and +/// every other element is a field, and the element that precedes it is the +/// object that contains it. +/// +/// Note that this class is immutable, and new fields may only be added through +/// constructor calls. +class FieldChainInfo { +public: + using FieldChain = llvm::ImmutableList; + +private: + FieldChain::Factory &Factory; + FieldChain Chain; + + const bool IsDereferenced = false; + +public: + FieldChainInfo() = delete; + FieldChainInfo(FieldChain::Factory &F) : Factory(F) {} + + FieldChainInfo(const FieldChainInfo &Other, const bool IsDereferenced) + : Factory(Other.Factory), Chain(Other.Chain), IsDereferenced(IsDereferenced) {} + + FieldChainInfo(const FieldChainInfo &Other, const FieldRegion *FR, + const bool IsDereferenced = false); + + bool contains(const FieldRegion *FR) const { return Chain.contains(FR); } + bool isPointer() const; + + /// If this is a fieldchain whose last element is an uninitialized region of a + /// pointer type, `IsDereferenced` will store whether the pointer itself or + /// the pointee is uninitialized. + bool isDereferenced() const; + const FieldDecl *getEndOfChain() const; + void print(llvm::raw_ostream &Out) const; + +private: + /// Prints every element except the last to `Out`. Since ImmutableLists store + /// eleme
r339596 - [analyzer][UninitializedObjectChecker] Refactoring p3.: printTail moved out from FieldChainInfo
Author: szelethus Date: Mon Aug 13 11:22:22 2018 New Revision: 339596 URL: http://llvm.org/viewvc/llvm-project?rev=339596&view=rev Log: [analyzer][UninitializedObjectChecker] Refactoring p3.: printTail moved out from FieldChainInfo This is a standalone part of the effort to reduce FieldChainInfos inteerface. Differential Revision: https://reviews.llvm.org/D50505 Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h?rev=339596&r1=339595&r2=339596&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h Mon Aug 13 11:22:22 2018 @@ -35,6 +35,7 @@ namespace ento { /// constructor calls. class FieldChainInfo { public: + using FieldChainImpl = llvm::ImmutableListImpl; using FieldChain = llvm::ImmutableList; private: @@ -48,7 +49,8 @@ public: FieldChainInfo(FieldChain::Factory &F) : Factory(F) {} FieldChainInfo(const FieldChainInfo &Other, const bool IsDereferenced) - : Factory(Other.Factory), Chain(Other.Chain), IsDereferenced(IsDereferenced) {} + : Factory(Other.Factory), Chain(Other.Chain), +IsDereferenced(IsDereferenced) {} FieldChainInfo(const FieldChainInfo &Other, const FieldRegion *FR, const bool IsDereferenced = false); @@ -64,12 +66,6 @@ public: void print(llvm::raw_ostream &Out) const; private: - /// Prints every element except the last to `Out`. Since ImmutableLists store - /// elements in reverse order, and have no reverse iterators, we use a - /// recursive function to print the fieldchain correctly. The last element in - /// the chain is to be printed by `print`. - static void printTail(llvm::raw_ostream &Out, -const llvm::ImmutableListImpl *L); friend struct FieldChainInfoComparator; }; Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp?rev=339596&r1=339595&r2=339596&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp Mon Aug 13 11:22:22 2018 @@ -46,8 +46,8 @@ // //===--===// -#include "UninitializedObject.h" #include "ClangSACheckers.h" +#include "UninitializedObject.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" #include "clang/StaticAnalyzer/Core/Checker.h" #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" @@ -87,7 +87,7 @@ getObjectVal(const CXXConstructorDecl *C /// (e.g. if the object is a field of another object, in which case we'd check /// it multiple times). static bool willObjectBeAnalyzedLater(const CXXConstructorDecl *Ctor, - CheckerContext &Context); + CheckerContext &Context); /// Constructs a note message for a given FieldChainInfo object. static void printNoteMessage(llvm::raw_ostream &Out, @@ -346,6 +346,13 @@ const FieldDecl *FieldChainInfo::getEndO return (*Chain.begin())->getDecl(); } +/// Prints every element except the last to `Out`. Since ImmutableLists store +/// elements in reverse order, and have no reverse iterators, we use a +/// recursive function to print the fieldchain correctly. The last element in +/// the chain is to be printed by `print`. +static void printTail(llvm::raw_ostream &Out, + const FieldChainInfo::FieldChainImpl *L); + // TODO: This function constructs an incorrect string if a void pointer is a // part of the chain: // @@ -383,15 +390,13 @@ void FieldChainInfo::print(llvm::raw_ost if (Chain.isEmpty()) return; - const llvm::ImmutableListImpl *L = - Chain.getInternalPointer(); + const FieldChainImpl *L = Chain.getInternalPointer(); printTail(Out, L->getTail()); Out << getVariableName(L->getHead()->getDecl()); } -void FieldChainInfo::printTail( -llvm::raw_ostream &Out, -const llvm::ImmutableListImpl *L) { +static void printTail(llvm::raw_ostream &Out, + const FieldChainInfo::FieldChainImpl *L) { if (!L) return; @@ -420,7 +425,
r339599 - [analyzer][UninitializedObjectChecker] Refactoring p4.: Wrap FieldRegions and reduce weight on FieldChainInfo
Author: szelethus Date: Mon Aug 13 11:43:08 2018 New Revision: 339599 URL: http://llvm.org/viewvc/llvm-project?rev=339599&view=rev Log: [analyzer][UninitializedObjectChecker] Refactoring p4.: Wrap FieldRegions and reduce weight on FieldChainInfo Before this patch, FieldChainInfo used a spaghetti: it took care of way too many cases, even though it was always meant as a lightweight wrapper around ImmutableList. This problem is solved by introducing a lightweight polymorphic wrapper around const FieldRegion *, FieldNode. It is an interface that abstracts away special cases like pointers/references, objects that need to be casted to another type for a proper note messages. Changes to FieldChainInfo: * Now wraps ImmutableList. * Any pointer/reference related fields and methods were removed * Got a new add method. This replaces it's former constructors as a way to create a new FieldChainInfo objects with a new element. Changes to FindUninitializedField: * In order not to deal with dynamic memory management, when an uninitialized field is found, the note message for it is constructed and is stored instead of a FieldChainInfo object. (see doc around addFieldToUninits). Some of the test files are changed too, from now on uninitialized pointees of references always print "uninitialized pointee" instead of "uninitialized field" (which should've really been like this from the beginning). I also updated every comment according to these changes. Differential Revision: https://reviews.llvm.org/D50506 Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp cfe/trunk/test/Analysis/cxx-uninitialized-object.cpp cfe/trunk/test/Analysis/objcpp-uninitialized-object.mm Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h?rev=339599&r1=339598&r2=339599&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h Mon Aug 13 11:43:08 2018 @@ -26,58 +26,85 @@ namespace clang { namespace ento { +/// Represent a single field. This is only an interface to abstract away special +/// cases like pointers/references. +class FieldNode { +protected: + const FieldRegion *FR; + +public: + FieldNode(const FieldRegion *FR) : FR(FR) { assert(FR); } + + FieldNode() = delete; + FieldNode(const FieldNode &) = delete; + FieldNode(FieldNode &&) = delete; + FieldNode &operator=(const FieldNode &) = delete; + FieldNode &operator=(const FieldNode &&) = delete; + + /// Profile - Used to profile the contents of this object for inclusion in a + /// FoldingSet. + void Profile(llvm::FoldingSetNodeID &ID) const { ID.AddPointer(this); } + + bool operator<(const FieldNode &Other) const { return FR < Other.FR; } + bool isSameRegion(const FieldRegion *OtherFR) const { return FR == OtherFR; } + + const FieldRegion *getRegion() const { return FR; } + const FieldDecl *getDecl() const { return FR->getDecl(); } + + // When a fieldchain is printed (a list of FieldNode objects), it will have + // the following format: + // 'this->...' + + /// If this is the last element of the fieldchain, this method will be called. + /// The note message should state something like "uninitialized field" or + /// "uninitialized pointee" etc. + virtual void printNoteMsg(llvm::raw_ostream &Out) const = 0; + + /// Print any prefixes before the fieldchain. + virtual void printPrefix(llvm::raw_ostream &Out) const = 0; + + /// Print the node. Should contain the name of the field stored in getRegion. + virtual void printNode(llvm::raw_ostream &Out) const = 0; + + /// Print the separator. For example, fields may be separated with '.' or + /// "->". + virtual void printSeparator(llvm::raw_ostream &Out) const = 0; +}; + +/// Returns with Field's name. This is a helper function to get the correct name +/// even if Field is a captured lambda variable. +StringRef getVariableName(const FieldDecl *Field); + /// Represents a field chain. A field chain is a vector of fields where the /// first element of the chain is the object under checking (not stored), and /// every other element is a field, and the element that precedes it is the /// object that contains it. /// -/// Note that this class is immutable, and new fields may only be added through -/// constructor calls. +/// Note that this class is immutable (essentially a wrapper around an +/// ImmutableList), and new elements can only be added by creating new +/// FieldChainInfo object
r339601 - [analyzer][UninitializedObjectChecker] Refactoring p5.: Handle pedantic mode in the checker class only
Author: szelethus Date: Mon Aug 13 11:48:34 2018 New Revision: 339601 URL: http://llvm.org/viewvc/llvm-project?rev=339601&view=rev Log: [analyzer][UninitializedObjectChecker] Refactoring p5.: Handle pedantic mode in the checker class only Differential Revision: https://reviews.llvm.org/D50508 Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h?rev=339601&r1=339600&r2=339601&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h Mon Aug 13 11:48:34 2018 @@ -111,9 +111,7 @@ class FindUninitializedFields { ProgramStateRef State; const TypedValueRegion *const ObjectR; - const bool IsPedantic; const bool CheckPointeeInitialization; - bool IsAnyFieldInitialized = false; FieldChainInfo::FieldChain::Factory ChainFactory; @@ -131,10 +129,17 @@ class FindUninitializedFields { UninitFieldMap UninitFields; public: + /// Constructs the FindUninitializedField object, searches for and stores + /// uninitialized fields in R. FindUninitializedFields(ProgramStateRef State, - const TypedValueRegion *const R, bool IsPedantic, + const TypedValueRegion *const R, bool CheckPointeeInitialization); - const UninitFieldMap &getUninitFields(); + + const UninitFieldMap &getUninitFields() { return UninitFields; } + + /// Returns whether the analyzed region contains at least one initialized + /// field. + bool isAnyFieldInitialized() { return IsAnyFieldInitialized; } private: // For the purposes of this checker, we'll regard the object under checking as Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp?rev=339601&r1=339600&r2=339601&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp Mon Aug 13 11:48:34 2018 @@ -136,7 +136,7 @@ void UninitializedObjectChecker::checkEn if (!Object) return; - FindUninitializedFields F(Context.getState(), Object->getRegion(), IsPedantic, + FindUninitializedFields F(Context.getState(), Object->getRegion(), CheckPointeeInitialization); const UninitFieldMap &UninitFields = F.getUninitFields(); @@ -144,6 +144,12 @@ void UninitializedObjectChecker::checkEn if (UninitFields.empty()) return; + // In non-pedantic mode, if Object's region doesn't contain a single + // initialized field, we'll assume that Object was intentionally left + // uninitialized. + if (!IsPedantic && !F.isAnyFieldInitialized()) +return; + // There are uninitialized fields in the record. ExplodedNode *Node = Context.generateNonFatalErrorNode(Context.getState()); @@ -192,18 +198,12 @@ void UninitializedObjectChecker::checkEn //===--===// FindUninitializedFields::FindUninitializedFields( -ProgramStateRef State, const TypedValueRegion *const R, bool IsPedantic, +ProgramStateRef State, const TypedValueRegion *const R, bool CheckPointeeInitialization) -: State(State), ObjectR(R), IsPedantic(IsPedantic), - CheckPointeeInitialization(CheckPointeeInitialization) {} +: State(State), ObjectR(R), + CheckPointeeInitialization(CheckPointeeInitialization) { -const UninitFieldMap &FindUninitializedFields::getUninitFields() { isNonUnionUninit(ObjectR, FieldChainInfo(ChainFactory)); - - if (!IsPedantic && !IsAnyFieldInitialized) -UninitFields.clear(); - - return UninitFields; } bool FindUninitializedFields::addFieldToUninits(FieldChainInfo Chain) { ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r339653 - [analyzer][UninitializedObjectChecker] Void pointers are casted back to their dynamic type in note message
Author: szelethus Date: Tue Aug 14 01:20:51 2018 New Revision: 339653 URL: http://llvm.org/viewvc/llvm-project?rev=339653&view=rev Log: [analyzer][UninitializedObjectChecker] Void pointers are casted back to their dynamic type in note message Differential Revision: https://reviews.llvm.org/D49228 Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp cfe/trunk/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp?rev=339653&r1=339652&r2=339653&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp Tue Aug 14 01:20:51 2018 @@ -60,6 +60,32 @@ public: } }; +/// Represents a void* field that needs to be casted back to its dynamic type +/// for a correct note message. +class NeedsCastLocField final : public FieldNode { + QualType CastBackType; + +public: + NeedsCastLocField(const FieldRegion *FR, const QualType &T) + : FieldNode(FR), CastBackType(T) {} + + virtual void printNoteMsg(llvm::raw_ostream &Out) const override { +Out << "uninitialized pointee "; + } + + virtual void printPrefix(llvm::raw_ostream &Out) const override { +Out << "static_cast" << '<' << CastBackType.getAsString() << ">("; + } + + virtual void printNode(llvm::raw_ostream &Out) const override { +Out << getVariableName(getDecl()) << ')'; + } + + virtual void printSeparator(llvm::raw_ostream &Out) const override { +Out << "->"; + } +}; + } // end of anonymous namespace // Utility function declarations. @@ -122,6 +148,10 @@ bool FindUninitializedFields::isPointerO QualType DynT = DynTInfo.getType(); + // If the static type of the field is a void pointer, we need to cast it back + // to the dynamic type before dereferencing. + bool NeedsCastBack = isVoidPointer(FR->getDecl()->getType()); + if (isVoidPointer(DynT)) { IsAnyFieldInitialized = true; return false; @@ -160,11 +190,16 @@ bool FindUninitializedFields::isPointerO const TypedValueRegion *R = RecordV->getRegion(); -if (DynT->getPointeeType()->isStructureOrClassType()) +if (DynT->getPointeeType()->isStructureOrClassType()) { + if (NeedsCastBack) +return isNonUnionUninit(R, LocalChain.add(NeedsCastLocField(FR, DynT))); return isNonUnionUninit(R, LocalChain.add(LocField(FR))); +} if (DynT->getPointeeType()->isUnionType()) { if (isUnionUninit(R)) { +if (NeedsCastBack) + return addFieldToUninits(LocalChain.add(NeedsCastLocField(FR, DynT))); return addFieldToUninits(LocalChain.add(LocField(FR))); } else { IsAnyFieldInitialized = true; @@ -185,8 +220,11 @@ bool FindUninitializedFields::isPointerO "At this point FR must either have a primitive dynamic type, or it " "must be a null, undefined, unknown or concrete pointer!"); - if (isPrimitiveUninit(DerefdV)) + if (isPrimitiveUninit(DerefdV)) { +if (NeedsCastBack) + return addFieldToUninits(LocalChain.add(NeedsCastLocField(FR, DynT))); return addFieldToUninits(LocalChain.add(LocField(FR))); + } IsAnyFieldInitialized = true; return false; Modified: cfe/trunk/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp?rev=339653&r1=339652&r2=339653&view=diff == --- cfe/trunk/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp (original) +++ cfe/trunk/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp Tue Aug 14 01:20:51 2018 @@ -292,7 +292,7 @@ void fCyclicVoidPointerTest() { } struct IntDynTypedVoidPointerTest1 { - void *vptr; // expected-note{{uninitialized pointee 'this->vptr'}} + void *vptr; // expected-note{{uninitialized pointee 'static_cast(this->vptr)'}} int dontGetFilteredByNonPedanticMode = 0; IntDynTypedVoidPointerTest1(void *vptr) : vptr(vptr) {} // expected-warning{{1 uninitialized field}} @@ -305,8 +305,8 @@ void fIntDynTypedVoidPointerTest1() { struct RecordDynTypedVoidPointerTest { struct RecordType { -int x; // expected-note{{uninitialized field 'this->vptr->x'}} -int y; // expected-note{{uninitialized field 'this->vptr->y'}} +int x; // expected-note{{uninitialized field 'static_cast(this->vptr)->x'}} +int y; // expected-note{{uninitialized field 'static_cast(this->vptr)->y'}} }; void *vptr; @@ -322,9 +322,9 @@ void fRecordDynTypedVoidPointerTest() { struct NestedNonVoidDynTypedVoidPointerTest { struct RecordType { -int x;
r339655 - [analyzer] Made a buildbot happy.
Author: szelethus Date: Tue Aug 14 01:38:35 2018 New Revision: 339655 URL: http://llvm.org/viewvc/llvm-project?rev=339655&view=rev Log: [analyzer] Made a buildbot happy. Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp?rev=339655&r1=339654&r2=339655&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp Tue Aug 14 01:38:35 2018 @@ -215,10 +215,12 @@ bool FindUninitializedFields::isPointerO llvm_unreachable("All cases are handled!"); } - assert((isPrimitiveType(DynT->getPointeeType()) || DynT->isPointerType() || - DynT->isReferenceType()) && + // Temporary variable to avoid warning from -Wunused-function. + bool IsPrimitive = isPrimitiveType(DynT->getPointeeType()); + assert((IsPrimitive || DynT->isAnyPointerType() || DynT->isReferenceType()) && "At this point FR must either have a primitive dynamic type, or it " "must be a null, undefined, unknown or concrete pointer!"); + (void)IsPrimitive; if (isPrimitiveUninit(DerefdV)) { if (NeedsCastBack) ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r340265 - [analyzer][UninitializedObjectChecker] Refactoring p6.: Move dereferencing to a function
Author: szelethus Date: Tue Aug 21 03:45:21 2018 New Revision: 340265 URL: http://llvm.org/viewvc/llvm-project?rev=340265&view=rev Log: [analyzer][UninitializedObjectChecker] Refactoring p6.: Move dereferencing to a function Now that it has it's own file, it makes little sense for isPointerOrReferenceUninit to be this large, so I moved dereferencing to a separate function. Differential Revision: https://reviews.llvm.org/D50509 Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp cfe/trunk/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp?rev=340265&r1=340264&r2=340265&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp Tue Aug 21 03:45:21 2018 @@ -265,7 +265,8 @@ bool FindUninitializedFields::isNonUnion continue; } -if (T->isAnyPointerType() || T->isReferenceType() || T->isBlockPointerType()) { +if (T->isAnyPointerType() || T->isReferenceType() || +T->isBlockPointerType()) { if (isPointerOrReferenceUninit(FR, LocalChain)) ContainsUninitField = true; continue; Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp?rev=340265&r1=340264&r2=340265&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp Tue Aug 21 03:45:21 2018 @@ -95,6 +95,12 @@ public: /// known, and thus FD can not be analyzed. static bool isVoidPointer(QualType T); +/// Dereferences \p V and returns the value and dynamic type of the pointee, as +/// well as wether \p FR needs to be casted back to that type. If for whatever +/// reason dereferencing fails, returns with None. +static llvm::Optional> +dereference(ProgramStateRef State, const FieldRegion *FR); + //===--===// // Methods for FindUninitializedFields. //===--===// @@ -126,67 +132,22 @@ bool FindUninitializedFields::isPointerO return false; } - assert(V.getAs() && - "At this point V must be loc::MemRegionVal!"); - auto L = V.castAs(); - - // We can't reason about symbolic regions, assume its initialized. - // Note that this also avoids a potential infinite recursion, because - // constructors for list-like classes are checked without being called, and - // the Static Analyzer will construct a symbolic region for Node *next; or - // similar code snippets. - if (L.getRegion()->getSymbolicBase()) { -IsAnyFieldInitialized = true; -return false; - } - - DynamicTypeInfo DynTInfo = getDynamicTypeInfo(State, L.getRegion()); - if (!DynTInfo.isValid()) { + // At this point the pointer itself is initialized and points to a valid + // location, we'll now check the pointee. + llvm::Optional> DerefInfo = + dereference(State, FR); + if (!DerefInfo) { IsAnyFieldInitialized = true; return false; } - QualType DynT = DynTInfo.getType(); - - // If the static type of the field is a void pointer, we need to cast it back - // to the dynamic type before dereferencing. - bool NeedsCastBack = isVoidPointer(FR->getDecl()->getType()); - - if (isVoidPointer(DynT)) { -IsAnyFieldInitialized = true; -return false; - } - - // At this point the pointer itself is initialized and points to a valid - // location, we'll now check the pointee. - SVal DerefdV = State->getSVal(V.castAs(), DynT); - - // If DerefdV is still a pointer value, we'll dereference it again (e.g.: - // int** -> int*). - while (auto Tmp = DerefdV.getAs()) { -if (Tmp->getRegion()->getSymbolicBase()) { - IsAnyFieldInitialized = true; - return false; -} - -DynTInfo = getDynamicTypeInfo(State, Tmp->getRegion()); -if (!DynTInfo.isValid()) { - IsAnyFieldInitialized = true; - return false; -} - -DynT = DynTInfo.getType(); -if (isVoidPointer(DynT)) { - IsAnyFieldInitialized = true; - return false; -} - -DerefdV = State->getSVal(*Tmp, DynT); - } + V = std::get<0>(*DerefInfo); + QualType DynT = std::get<1>(*Deref
r340266 - [analyzer][UninitializedObjectChecker] Added documentation to the checker list
Author: szelethus Date: Tue Aug 21 03:47:19 2018 New Revision: 340266 URL: http://llvm.org/viewvc/llvm-project?rev=340266&view=rev Log: [analyzer][UninitializedObjectChecker] Added documentation to the checker list Differential Revision: https://reviews.llvm.org/D50904 Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp cfe/trunk/www/analyzer/alpha_checks.html Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp?rev=340266&r1=340265&r2=340266&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp Tue Aug 21 03:47:19 2018 @@ -286,18 +286,6 @@ bool FindUninitializedFields::isNonUnion } // Checking bases. - // FIXME: As of now, because of `willObjectBeAnalyzedLater`, objects whose - // type is a descendant of another type will emit warnings for uninitalized - // inherited members. - // This is not the only way to analyze bases of an object -- if we didn't - // filter them out, and didn't analyze the bases, this checker would run for - // each base of the object in order of base initailization and in theory would - // find every uninitalized field. This approach could also make handling - // diamond inheritances more easily. - // - // This rule (that a descendant type's cunstructor is responsible for - // initializing inherited data members) is not obvious, and should it should - // be. const auto *CXXRD = dyn_cast(RD); if (!CXXRD) return ContainsUninitField; Modified: cfe/trunk/www/analyzer/alpha_checks.html URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/www/analyzer/alpha_checks.html?rev=340266&r1=340265&r2=340266&view=diff == --- cfe/trunk/www/analyzer/alpha_checks.html (original) +++ cfe/trunk/www/analyzer/alpha_checks.html Tue Aug 21 03:47:19 2018 @@ -323,6 +323,118 @@ public: }; + + +alpha.cplusplus.UninitializedObject +(C++) +This checker reports uninitialized fields in objects created +after a constructor call. It doesn't only find direct uninitialized +fields, but rather makes a deep inspection of the object, +analyzing all of it's fields subfields. +The checker regards inherited fields as direct fields, so one +will recieve warnings for uninitialized inherited data members +as well. + +It has several options: + + +"Pedantic" (boolean). If its not set or is set to false, the checker +won't emit warnings for objects that don't have at least one initialized +field. This may be set with +-analyzer-config alpha.cplusplus.UninitializedObject:Pedantic=true. + + +"NotesAsWarnings" (boolean). 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. Defaults to false. +-analyzer-config alpha.cplusplus.UninitializedObject:NotesAsWarnings=true. + + +"CheckPointeeInitialization" (boolean). 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. Defaults to false. +-analyzer-config alpha.cplusplus.UninitializedObject:CheckPointeeInitialization=true. + + + + +// With Pedantic and CheckPointeeInitialization set to true + +struct A { + struct B { +int x; // note: uninitialized field 'this->b.x' + // note: uninitialized field 'this->bptr->x' +int y; // note: uninitialized field 'this->b.y' + // note: uninitialized field 'this->bptr->y' + }; + int *iptr; // note: uninitialized pointer 'this->iptr' + B b; + B *bptr; + char *cptr; // note: uninitialized pointee 'this->cptr' + + A (B *bptr, char *cptr) : bptr(bptr), cptr(cptr) {} +}; + +void f() { + A::B b; + char c; + A a(&b, &c); // warning: 6 uninitialized fields + // after the constructor call +} + + +// With Pedantic set to false and +// CheckPointeeInitialization set to true +// (every field is uninitialized) + +struct A { + struct B { +int x; +int y; + }; + int *iptr; + B b; + B *bptr; + char *cptr; + + A (B *bptr, char *cptr) : bptr(bptr), cptr(cptr) {} +}; + +void f() { + A::B b; + char c; + A a(&b, &c); // no warning +} + + +// With Pedantic and CheckPointeeInitialization set to false +// (pointees are regarded as initialized) + +struct A { + struct B { +int x; // note: uninitialized field 'this->b.x' +int y; // note: uninitialized field 'this->b.y' + }; + int *iptr; // note: uniniti
r340272 - [analyzer][UninitializedObjectChecker] Explicit namespace resolution for inherited data members
Author: szelethus Date: Tue Aug 21 05:16:59 2018 New Revision: 340272 URL: http://llvm.org/viewvc/llvm-project?rev=340272&view=rev Log: [analyzer][UninitializedObjectChecker] Explicit namespace resolution for inherited data members For the following example: struct Base { int x; }; // In a different translation unit struct Derived : public Base { Derived() {} }; For a call to Derived::Derived(), we'll receive a note that this->x is uninitialized. Since x is not a direct field of Derived, it could be a little confusing. This patch aims to fix this, as well as the case when the derived object has a field that has the name as an inherited uninitialized data member: struct Base { int x; // note: uninitialized field 'this->Base::x' }; struct Derived : public Base { int x = 5; Derived() {} }; Differential Revision: https://reviews.llvm.org/D50905 Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp cfe/trunk/test/Analysis/cxx-uninitialized-object-inheritance.cpp Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h?rev=340272&r1=340271&r2=340272&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h Tue Aug 21 05:16:59 2018 @@ -32,10 +32,10 @@ class FieldNode { protected: const FieldRegion *FR; - ~FieldNode() = default; + /* non-virtual */ ~FieldNode() = default; public: - FieldNode(const FieldRegion *FR) : FR(FR) { assert(FR); } + FieldNode(const FieldRegion *FR) : FR(FR) {} FieldNode() = delete; FieldNode(const FieldNode &) = delete; @@ -47,11 +47,21 @@ public: /// FoldingSet. void Profile(llvm::FoldingSetNodeID &ID) const { ID.AddPointer(this); } - bool operator<(const FieldNode &Other) const { return FR < Other.FR; } - bool isSameRegion(const FieldRegion *OtherFR) const { return FR == OtherFR; } + // Helper method for uniqueing. + bool isSameRegion(const FieldRegion *OtherFR) const { +// Special FieldNode descendants may wrap nullpointers -- we wouldn't like +// to unique these objects. +if (FR == nullptr) + return false; + +return FR == OtherFR; + } const FieldRegion *getRegion() const { return FR; } - const FieldDecl *getDecl() const { return FR->getDecl(); } + const FieldDecl *getDecl() const { +assert(FR); +return FR->getDecl(); + } // When a fieldchain is printed (a list of FieldNode objects), it will have // the following format: @@ -71,6 +81,8 @@ public: /// Print the separator. For example, fields may be separated with '.' or /// "->". virtual void printSeparator(llvm::raw_ostream &Out) const = 0; + + virtual bool isBase() const { return false; } }; /// Returns with Field's name. This is a helper function to get the correct name @@ -94,15 +106,24 @@ private: FieldChain::Factory &ChainFactory; FieldChain Chain; + FieldChainInfo(FieldChain::Factory &F, FieldChain NewChain) + : FieldChainInfo(F) { +Chain = NewChain; + } + public: FieldChainInfo() = delete; FieldChainInfo(FieldChain::Factory &F) : ChainFactory(F) {} FieldChainInfo(const FieldChainInfo &Other) = default; template FieldChainInfo add(const FieldNodeT &FN); + template FieldChainInfo replaceHead(const FieldNodeT &FN); bool contains(const FieldRegion *FR) const; + bool isEmpty() const { return Chain.isEmpty(); } + const FieldRegion *getUninitRegion() const; + const FieldNode &getHead() { return Chain.getHead(); } void printNoteMsg(llvm::raw_ostream &Out) const; }; @@ -250,6 +271,12 @@ inline FieldChainInfo FieldChainInfo::ad return NewChain; } +template +inline FieldChainInfo FieldChainInfo::replaceHead(const FieldNodeT &FN) { + FieldChainInfo NewChain(ChainFactory, Chain.getTail()); + return NewChain.add(FN); +} + } // end of namespace ento } // end of namespace clang Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp?rev=340272&r1=340271&r2=340272&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp Tue Aug 21 05:16:59 2018 @@ -93,6 +93,33 @@ public: } }; +/// Represents that the FieldNode that comes after this is
r340280 - [analyzer] Correctly marked a virtual function 'override'
Author: szelethus Date: Tue Aug 21 08:09:22 2018 New Revision: 340280 URL: http://llvm.org/viewvc/llvm-project?rev=340280&view=rev Log: [analyzer] Correctly marked a virtual function 'override' Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp?rev=340280&r1=340279&r2=340280&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp Tue Aug 21 08:09:22 2018 @@ -117,7 +117,7 @@ public: virtual void printSeparator(llvm::raw_ostream &Out) const override {} - virtual bool isBase() const { return true; } + virtual bool isBase() const override { return true; } }; } // end of anonymous namespace ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r333080 - Test commit
Author: szelethus Date: Wed May 23 05:48:55 2018 New Revision: 333080 URL: http://llvm.org/viewvc/llvm-project?rev=333080&view=rev Log: Test commit Modified: cfe/trunk/examples/PrintFunctionNames/CMakeLists.txt Modified: cfe/trunk/examples/PrintFunctionNames/CMakeLists.txt URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/examples/PrintFunctionNames/CMakeLists.txt?rev=333080&r1=333079&r2=333080&view=diff == --- cfe/trunk/examples/PrintFunctionNames/CMakeLists.txt (original) +++ cfe/trunk/examples/PrintFunctionNames/CMakeLists.txt Wed May 23 05:48:55 2018 @@ -1,7 +1,7 @@ # If we don't need RTTI or EH, there's no reason to export anything # from the plugin. -if( NOT MSVC ) # MSVC mangles symbols differently, and -# PrintFunctionNames.export contains C++ symbols. +if( NOT MSVC ) # MSVC mangles symbols differently, and + # PrintFunctionNames.export contains C++ symbols. if( NOT LLVM_REQUIRES_RTTI ) if( NOT LLVM_REQUIRES_EH ) set(LLVM_EXPORTED_SYMBOL_FILE ${CMAKE_CURRENT_SOURCE_DIR}/PrintFunctionNames.exports) ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r333275 - [analyzer] Added template argument lists to the Pathdiagnostic output
Author: szelethus Date: Fri May 25 06:18:38 2018 New Revision: 333275 URL: http://llvm.org/viewvc/llvm-project?rev=333275&view=rev Log: [analyzer] Added template argument lists to the Pathdiagnostic output Because template parameter lists were not displayed in the plist output, it was difficult to decide in some cases whether a given checker found a true or a false positive. This patch aims to correct this. Differential Revision: https://reviews.llvm.org/D46933 Added: cfe/trunk/test/Analysis/plist-diagnostics-template-function.cpp cfe/trunk/test/Analysis/plist-diagnostics-template-record.cpp Modified: cfe/trunk/lib/StaticAnalyzer/Core/PathDiagnostic.cpp Modified: cfe/trunk/lib/StaticAnalyzer/Core/PathDiagnostic.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/PathDiagnostic.cpp?rev=333275&r1=333274&r2=333275&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Core/PathDiagnostic.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Core/PathDiagnostic.cpp Fri May 25 06:18:38 2018 @@ -16,6 +16,7 @@ #include "clang/AST/DeclBase.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" +#include "clang/AST/DeclTemplate.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/OperationKinds.h" @@ -1000,11 +1001,49 @@ void PathDiagnosticCallPiece::setCallee( CalleeCtx->getAnalysisDeclContext()->isBodyAutosynthesized()); } +static void describeTemplateParameters(raw_ostream &Out, + const ArrayRef TAList, + const LangOptions &LO, + StringRef Prefix = StringRef(), + StringRef Postfix = StringRef()); + +static void describeTemplateParameter(raw_ostream &Out, + const TemplateArgument &TArg, + const LangOptions &LO) { + + if (TArg.getKind() == TemplateArgument::ArgKind::Pack) { +describeTemplateParameters(Out, TArg.getPackAsArray(), LO); + } else { +TArg.print(PrintingPolicy(LO), Out); + } +} + +static void describeTemplateParameters(raw_ostream &Out, + const ArrayRef TAList, + const LangOptions &LO, + StringRef Prefix, StringRef Postfix) { + if (TAList.empty()) +return; + + Out << Prefix; + for (int I = 0, Last = TAList.size() - 1; I != Last; ++I) { +describeTemplateParameter(Out, TAList[I], LO); +Out << ", "; + } + describeTemplateParameter(Out, TAList[TAList.size() - 1], LO); + Out << Postfix; +} + static void describeClass(raw_ostream &Out, const CXXRecordDecl *D, StringRef Prefix = StringRef()) { if (!D->getIdentifier()) return; - Out << Prefix << '\'' << *D << '\''; + Out << Prefix << '\'' << *D; + if (const auto T = dyn_cast(D)) +describeTemplateParameters(Out, T->getTemplateArgs().asArray(), + D->getASTContext().getLangOpts(), "<", ">"); + + Out << '\''; } static bool describeCodeDecl(raw_ostream &Out, const Decl *D, @@ -1062,7 +1101,16 @@ static bool describeCodeDecl(raw_ostream return true; } - Out << Prefix << '\'' << cast(*D) << '\''; + Out << Prefix << '\'' << cast(*D); + + // Adding template parameters. + if (const auto FD = dyn_cast(D)) +if (const TemplateArgumentList *TAList = +FD->getTemplateSpecializationArgs()) + describeTemplateParameters(Out, TAList->asArray(), + FD->getASTContext().getLangOpts(), "<", ">"); + + Out << '\''; return true; } Added: cfe/trunk/test/Analysis/plist-diagnostics-template-function.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/plist-diagnostics-template-function.cpp?rev=333275&view=auto == --- cfe/trunk/test/Analysis/plist-diagnostics-template-function.cpp (added) +++ cfe/trunk/test/Analysis/plist-diagnostics-template-function.cpp Fri May 25 06:18:38 2018 @@ -0,0 +1,41 @@ +// RUN: %clang_analyze_cc1 -analyzer-output=plist -o %t.plist -std=c++11 -analyzer-checker=core %s +// RUN: FileCheck --input-file=%t.plist %s + +bool ret(); + +template +void f(int i) { + if (ret()) +i = i / (i - 5); +} + +template <> +void f(int i) { + if (ret()) +i = i / (i - 5); +} + +template +void defaultTemplateParameterFunction(int i) { + if (ret()) +int a = 10 / i; +} + +template +void variadicTemplateFunction(int i) { + if (ret()) +int a = 10 / i; +} + +int main() { + f(5); + f(5); + defaultTemplateParameterFunction<>(0); + variadicTemplateFunction(0); +} + +// CHECK: Calling 'f' +// CHECK: Calling 'f ' +// CHECK: Calling 'defaultTemplateParamet
r333278 - [analyzer] Added a getLValue method to ProgramState for bases
Author: szelethus Date: Fri May 25 07:48:33 2018 New Revision: 333278 URL: http://llvm.org/viewvc/llvm-project?rev=333278&view=rev Log: [analyzer] Added a getLValue method to ProgramState for bases Differential Revision: https://reviews.llvm.org/D46891 Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h?rev=333278&r1=333277&r2=333278&view=diff == --- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h (original) +++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h Fri May 25 07:48:33 2018 @@ -294,6 +294,13 @@ public: ProgramStateRef enterStackFrame(const CallEvent &Call, const StackFrameContext *CalleeCtx) const; + /// Get the lvalue for a base class object reference. + Loc getLValue(const CXXBaseSpecifier &BaseSpec, const SubRegion *Super) const; + + /// Get the lvalue for a base class object reference. + Loc getLValue(const CXXRecordDecl *BaseClass, const SubRegion *Super, +bool IsVirtual) const; + /// Get the lvalue for a variable reference. Loc getLValue(const VarDecl *D, const LocationContext *LC) const; @@ -724,6 +731,22 @@ inline ProgramStateRef ProgramState::bin return this; } +inline Loc ProgramState::getLValue(const CXXBaseSpecifier &BaseSpec, + const SubRegion *Super) const { + const auto *Base = BaseSpec.getType()->getAsCXXRecordDecl(); + return loc::MemRegionVal( + getStateManager().getRegionManager().getCXXBaseObjectRegion( +Base, Super, BaseSpec.isVirtual())); +} + +inline Loc ProgramState::getLValue(const CXXRecordDecl *BaseClass, + const SubRegion *Super, + bool IsVirtual) const { + return loc::MemRegionVal( + getStateManager().getRegionManager().getCXXBaseObjectRegion( + BaseClass, Super, IsVirtual)); +} + inline Loc ProgramState::getLValue(const VarDecl *VD, const LocationContext *LC) const { return getStateManager().StoreMgr->getLValueVar(VD, LC); ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r342213 - [analyzer][UninitializedObjectChecker] Fixed dereferencing
Author: szelethus Date: Fri Sep 14 01:58:21 2018 New Revision: 342213 URL: http://llvm.org/viewvc/llvm-project?rev=342213&view=rev Log: [analyzer][UninitializedObjectChecker] Fixed dereferencing iThis patch aims to fix derefencing, which has been debated for months now. Instead of working with SVals, the function now relies on TypedValueRegion. Differential Revision: https://reviews.llvm.org/D51057 Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp cfe/trunk/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp cfe/trunk/test/Analysis/cxx-uninitialized-object.cpp cfe/trunk/test/Analysis/objcpp-uninitialized-object.mm Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h?rev=342213&r1=342212&r2=342213&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h Fri Sep 14 01:58:21 2018 @@ -87,7 +87,7 @@ public: /// Returns with Field's name. This is a helper function to get the correct name /// even if Field is a captured lambda variable. -StringRef getVariableName(const FieldDecl *Field); +std::string getVariableName(const FieldDecl *Field); /// Represents a field chain. A field chain is a vector of fields where the /// first element of the chain is the object under checking (not stored), and @@ -255,7 +255,13 @@ private: /// ease. This also helps ensuring that every special field type is handled /// correctly. inline bool isPrimitiveType(const QualType &T) { - return T->isBuiltinType() || T->isEnumeralType() || T->isMemberPointerType(); + return T->isBuiltinType() || T->isEnumeralType() || + T->isMemberPointerType() || T->isBlockPointerType() || + T->isFunctionType(); +} + +inline bool isDereferencableType(const QualType &T) { + return T->isAnyPointerType() || T->isReferenceType(); } // Template method definitions. Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp?rev=342213&r1=342212&r2=342213&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp Fri Sep 14 01:58:21 2018 @@ -252,9 +252,12 @@ bool FindUninitializedFields::isNonUnion !R->getValueType()->isUnionType() && "This method only checks non-union record objects!"); - const RecordDecl *RD = - R->getValueType()->getAs()->getDecl()->getDefinition(); - assert(RD && "Referred record has no definition"); + const RecordDecl *RD = R->getValueType()->getAsRecordDecl()->getDefinition(); + + if (!RD) { +IsAnyFieldInitialized = true; +return true; + } bool ContainsUninitField = false; @@ -292,8 +295,7 @@ bool FindUninitializedFields::isNonUnion continue; } -if (T->isAnyPointerType() || T->isReferenceType() || -T->isBlockPointerType()) { +if (isDereferencableType(T)) { if (isPointerOrReferenceUninit(FR, LocalChain)) ContainsUninitField = true; continue; @@ -487,7 +489,7 @@ static bool willObjectBeAnalyzedLater(co return false; } -StringRef clang::ento::getVariableName(const FieldDecl *Field) { +std::string clang::ento::getVariableName(const FieldDecl *Field) { // If Field is a captured lambda variable, Field->getName() will return with // an empty string. We can however acquire it's name from the lambda's // captures. @@ -496,7 +498,16 @@ StringRef clang::ento::getVariableName(c if (CXXParent && CXXParent->isLambda()) { assert(CXXParent->captures_begin()); auto It = CXXParent->captures_begin() + Field->getFieldIndex(); -return It->getCapturedVar()->getName(); + +if (It->capturesVariable()) + return llvm::Twine("/*captured variable*/" + + It->getCapturedVar()->getName()) + .str(); + +if (It->capturesThis()) + return "/*'this' capture*/"; + +llvm_unreachable("No other capture type is expected!"); } return Field->getName(); Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedP
r342215 - [analyzer][UninitializedObjectChecker] Updated comments
Author: szelethus Date: Fri Sep 14 02:07:40 2018 New Revision: 342215 URL: http://llvm.org/viewvc/llvm-project?rev=342215&view=rev Log: [analyzer][UninitializedObjectChecker] Updated comments Some of the comments are incorrect, imprecise, or simply nonexistent. Since I have a better grasp on how the analyzer works, it makes sense to update most of them in a single swoop. I tried not to flood the code with comments too much, this amount feels just right to me. Differential Revision: https://reviews.llvm.org/D51417 Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h?rev=342215&r1=342214&r2=342215&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h Fri Sep 14 02:07:40 2018 @@ -26,31 +26,36 @@ namespace clang { namespace ento { -/// Represent a single field. This is only an interface to abstract away special -/// cases like pointers/references. +/// A lightweight polymorphic wrapper around FieldRegion *. We'll use this +/// interface to store addinitional information about fields. As described +/// later, a list of these objects (i.e. "fieldchain") will be constructed and +/// used for printing note messages should an uninitialized value be found. class FieldNode { protected: const FieldRegion *FR; + /// FieldNodes are never meant to be created on the heap, see + /// FindUninitializedFields::addFieldToUninits(). /* non-virtual */ ~FieldNode() = default; public: FieldNode(const FieldRegion *FR) : FR(FR) {} + // We'll delete all of these special member functions to force the users of + // this interface to only store references to FieldNode objects in containers. FieldNode() = delete; FieldNode(const FieldNode &) = delete; FieldNode(FieldNode &&) = delete; FieldNode &operator=(const FieldNode &) = delete; FieldNode &operator=(const FieldNode &&) = delete; - /// Profile - Used to profile the contents of this object for inclusion in a - /// FoldingSet. void Profile(llvm::FoldingSetNodeID &ID) const { ID.AddPointer(this); } - // Helper method for uniqueing. + /// Helper method for uniqueing. bool isSameRegion(const FieldRegion *OtherFR) const { -// Special FieldNode descendants may wrap nullpointers -- we wouldn't like -// to unique these objects. +// Special FieldNode descendants may wrap nullpointers (for example if they +// describe a special relationship between two elements of the fieldchain) +// -- we wouldn't like to unique these objects. if (FR == nullptr) return false; @@ -63,19 +68,22 @@ public: return FR->getDecl(); } - // When a fieldchain is printed (a list of FieldNode objects), it will have - // the following format: - // 'this->...' + // When a fieldchain is printed, it will have the following format (without + // newline, indices are in order of insertion, from 1 to n): + // + // '... + // this->...' - /// If this is the last element of the fieldchain, this method will be called. + /// If this is the last element of the fieldchain, this method will print the + /// note message associated with it. /// The note message should state something like "uninitialized field" or /// "uninitialized pointee" etc. virtual void printNoteMsg(llvm::raw_ostream &Out) const = 0; - /// Print any prefixes before the fieldchain. + /// Print any prefixes before the fieldchain. Could contain casts, etc. virtual void printPrefix(llvm::raw_ostream &Out) const = 0; - /// Print the node. Should contain the name of the field stored in getRegion. + /// Print the node. Should contain the name of the field stored in FR. virtual void printNode(llvm::raw_ostream &Out) const = 0; /// Print the separator. For example, fields may be separated with '.' or @@ -89,14 +97,14 @@ public: /// even if Field is a captured lambda variable. std::string getVariableName(const FieldDecl *Field); -/// Represents a field chain. A field chain is a vector of fields where the -/// first element of the chain is the object under checking (not stored), and -/// every other element is a field, and the element that precedes it is the -/// object that contains it. +/// Represents a field chain. A field chain is a list of fields where the first +/// element of the chain is the object under checking (not stored), and every +/// other element is a field, and t
r342217 - [analyzer][UninitializedObjectChecker] Correct dynamic type is acquired for record pointees
Author: szelethus Date: Fri Sep 14 02:13:36 2018 New Revision: 342217 URL: http://llvm.org/viewvc/llvm-project?rev=342217&view=rev Log: [analyzer][UninitializedObjectChecker] Correct dynamic type is acquired for record pointees Differential Revision: https://reviews.llvm.org/D50892 Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp cfe/trunk/test/Analysis/cxx-uninitialized-object-inheritance.cpp Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp?rev=342217&r1=342216&r2=342217&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp Fri Sep 14 02:13:36 2018 @@ -234,5 +234,13 @@ static llvm::Optional d break; } + while (R->getAs()) { +NeedsCastBack = true; + +if (!isa(R->getSuperRegion())) + break; +R = R->getSuperRegion()->getAs(); + } + return std::make_pair(R, NeedsCastBack); } Modified: cfe/trunk/test/Analysis/cxx-uninitialized-object-inheritance.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/cxx-uninitialized-object-inheritance.cpp?rev=342217&r1=342216&r2=342217&view=diff == --- cfe/trunk/test/Analysis/cxx-uninitialized-object-inheritance.cpp (original) +++ cfe/trunk/test/Analysis/cxx-uninitialized-object-inheritance.cpp Fri Sep 14 02:13:36 2018 @@ -781,21 +781,53 @@ void fVirtualDiamondInheritanceTest3() { // Dynamic type test. //===--===// -struct DynTBase {}; -struct DynTDerived : DynTBase { - // TODO: we'd expect the note: {{uninitialized field 'this->x'}} - int x; // no-note +struct DynTBase1 {}; +struct DynTDerived1 : DynTBase1 { + int y; // expected-note{{uninitialized field 'static_cast(this->bptr)->y'}} }; -struct DynamicTypeTest { - DynTBase *bptr; +struct DynamicTypeTest1 { + DynTBase1 *bptr; int i = 0; - // TODO: we'd expect the warning: {{1 uninitialized field}} - DynamicTypeTest(DynTBase *bptr) : bptr(bptr) {} // no-warning + DynamicTypeTest1(DynTBase1 *bptr) : bptr(bptr) {} // expected-warning{{1 uninitialized field}} }; -void f() { - DynTDerived d; - DynamicTypeTest t(&d); +void fDynamicTypeTest1() { + DynTDerived1 d; + DynamicTypeTest1 t(&d); }; + +struct DynTBase2 { + int x; // expected-note{{uninitialized field 'static_cast(this->bptr)->DynTBase2::x'}} +}; +struct DynTDerived2 : DynTBase2 { + int y; // expected-note{{uninitialized field 'static_cast(this->bptr)->y'}} +}; + +struct DynamicTypeTest2 { + DynTBase2 *bptr; + int i = 0; + + DynamicTypeTest2(DynTBase2 *bptr) : bptr(bptr) {} // expected-warning{{2 uninitialized fields}} +}; + +void fDynamicTypeTest2() { + DynTDerived2 d; + DynamicTypeTest2 t(&d); +} + +struct SymbolicSuperRegionBase { + SymbolicSuperRegionBase() {} +}; + +struct SymbolicSuperRegionDerived : SymbolicSuperRegionBase { + SymbolicSuperRegionBase *bptr; // no-crash + SymbolicSuperRegionDerived(SymbolicSuperRegionBase *bptr) : bptr(bptr) {} +}; + +SymbolicSuperRegionDerived *getSymbolicRegion(); + +void fSymbolicSuperRegionTest() { + SymbolicSuperRegionDerived test(getSymbolicRegion()); +} ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r342219 - [analyzer][UninitializedObjectChecker] Refactored checker options
Author: szelethus Date: Fri Sep 14 02:39:26 2018 New Revision: 342219 URL: http://llvm.org/viewvc/llvm-project?rev=342219&view=rev Log: [analyzer][UninitializedObjectChecker] Refactored checker options Since I plan to add a number of new flags, it made sense to encapsulate them in a new struct, in order not to pollute FindUninitializedFields's constructor with new boolean options with super long names. This revision practically reverts D50508, since FindUninitializedFields now accesses the pedantic flag anyways. Differential Revision: https://reviews.llvm.org/D51679 Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h?rev=342219&r1=342218&r2=342219&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h Fri Sep 14 02:39:26 2018 @@ -10,8 +10,39 @@ // This file defines helper classes for UninitializedObjectChecker and // documentation about the logic of it. // -// To read about command line options and a description what this checker does, -// refer to UninitializedObjectChecker.cpp. +// The checker reports uninitialized fields in objects created after a +// constructor call. +// +// This checker has several options: +// - "Pedantic" (boolean). If its not set or is set to false, the checker +// won't emit warnings for objects that don't have at least one initialized +// field. This may be set with +// +// `-analyzer-config alpha.cplusplus.UninitializedObject:Pedantic=true`. +// +// - "NotesAsWarnings" (boolean). 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. Defaults to false. +// +// `-analyzer-config \ +// alpha.cplusplus.UninitializedObject:NotesAsWarnings=true`. +// +// - "CheckPointeeInitialization" (boolean). 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. Defaults to false. +// +// `-analyzer-config \ +// alpha.cplusplus.UninitializedObject:CheckPointeeInitialization=true`. +// +// TODO: With some clever heuristics, some pointers should be dereferenced +// by default. For example, if the pointee is constructed within the +// constructor call, it's reasonable to say that no external object +// references it, and we wouldn't generate multiple report on the same +// pointee. +// +// Most of the following methods as well as the checker itself is defined in +// UninitializedObjectChecker.cpp. // // Some methods are implemented in UninitializedPointee.cpp, to reduce the // complexity of the main checker file. @@ -26,6 +57,12 @@ namespace clang { namespace ento { +struct UninitObjCheckerOptions { + bool IsPedantic = false; + bool ShouldConvertNotesToWarnings = false; + bool CheckPointeeInitialization = false; +}; + /// A lightweight polymorphic wrapper around FieldRegion *. We'll use this /// interface to store addinitional information about fields. As described /// later, a list of these objects (i.e. "fieldchain") will be constructed and @@ -147,7 +184,7 @@ class FindUninitializedFields { ProgramStateRef State; const TypedValueRegion *const ObjectR; - const bool CheckPointeeInitialization; + const UninitObjCheckerOptions Opts; bool IsAnyFieldInitialized = false; FieldChainInfo::FieldChain::Factory ChainFactory; @@ -169,7 +206,7 @@ public: /// uninitialized fields in R. FindUninitializedFields(ProgramStateRef State, const TypedValueRegion *const R, - bool CheckPointeeInitialization); + const UninitObjCheckerOptions &Opts); const UninitFieldMap &getUninitFields() { return UninitFields; } Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp?rev=342219&r1=342218&r2=342219&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/Uninitial
r342220 - [analyzer][UninitializedObjectChecker] New flag to ignore records based on it's fields
Author: szelethus Date: Fri Sep 14 03:10:09 2018 New Revision: 342220 URL: http://llvm.org/viewvc/llvm-project?rev=342220&view=rev Log: [analyzer][UninitializedObjectChecker] New flag to ignore records based on it's fields Based on a suggestion from @george.karpenkov. In some cases, structs are used as unions with a help of a tag/kind field. This patch adds a new string flag (a pattern), that is matched against the fields of a record, and should a match be found, the entire record is ignored. For more info refer to http://lists.llvm.org/pipermail/cfe-dev/2018-August/058906.html and to the responses to that, especially http://lists.llvm.org/pipermail/cfe-dev/2018-August/059215.html. Differential Revision: https://reviews.llvm.org/D51680 Added: cfe/trunk/test/Analysis/cxx-uninitialized-object-unionlike-constructs.cpp Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp cfe/trunk/www/analyzer/alpha_checks.html Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h?rev=342220&r1=342219&r2=342220&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h Fri Sep 14 03:10:09 2018 @@ -35,6 +35,13 @@ // `-analyzer-config \ // alpha.cplusplus.UninitializedObject:CheckPointeeInitialization=true`. // +// - "IgnoreRecordsWithField" (string). If supplied, the checker will not +// analyze structures that have a field with a name or type name that +// matches the given pattern. Defaults to "". +// +// `-analyzer-config \ +// alpha.cplusplus.UninitializedObject:IgnoreRecordsWithField="[Tt]ag|[Kk]ind"`. +// // TODO: With some clever heuristics, some pointers should be dereferenced // by default. For example, if the pointee is constructed within the // constructor call, it's reasonable to say that no external object @@ -60,7 +67,8 @@ namespace ento { struct UninitObjCheckerOptions { bool IsPedantic = false; bool ShouldConvertNotesToWarnings = false; - bool CheckPointeeInitialization = false; + bool CheckPointeeInitialization = false; + std::string IgnoredRecordsWithFieldPattern; }; /// A lightweight polymorphic wrapper around FieldRegion *. We'll use this Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp?rev=342220&r1=342219&r2=342220&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp Fri Sep 14 03:10:09 2018 @@ -109,6 +109,10 @@ getObjectVal(const CXXConstructorDecl *C static bool willObjectBeAnalyzedLater(const CXXConstructorDecl *Ctor, CheckerContext &Context); +/// Checks whether RD contains a field with a name or type name that matches +/// \p Pattern. +static bool shouldIgnoreRecord(const RecordDecl *RD, StringRef Pattern); + //===--===// // Methods for UninitializedObjectChecker. //===--===// @@ -228,6 +232,12 @@ bool FindUninitializedFields::isNonUnion return true; } + if (!Opts.IgnoredRecordsWithFieldPattern.empty() && + shouldIgnoreRecord(RD, Opts.IgnoredRecordsWithFieldPattern)) { +IsAnyFieldInitialized = true; +return false; + } + bool ContainsUninitField = false; // Are all of this non-union's fields initialized? @@ -442,6 +452,19 @@ static bool willObjectBeAnalyzedLater(co return false; } +static bool shouldIgnoreRecord(const RecordDecl *RD, StringRef Pattern) { + llvm::Regex R(Pattern); + + for (const FieldDecl *FD : RD->fields()) { +if (R.match(FD->getType().getAsString())) + return true; +if (R.match(FD->getName())) + return true; + } + + return false; +} + std::string clang::ento::getVariableName(const FieldDecl *Field) { // If Field is a captured lambda variable, Field->getName() will return with // an empty string. We can however acquire it's name from the lambda's @@ -472,10 +495,13 @@ void ento::registerUninitializedObjectCh AnalyzerOptions &AnOpts = Mgr.getAnalyzerOptions(); UninitObjCheckerOptions &ChOpts = Chk->Opts; - ChOpts.IsPedantic = A
r342221 - [analyzer][UninitializedObjectChecker] Support for nonloc::LocAsInteger
Author: szelethus Date: Fri Sep 14 03:18:26 2018 New Revision: 342221 URL: http://llvm.org/viewvc/llvm-project?rev=342221&view=rev Log: [analyzer][UninitializedObjectChecker] Support for nonloc::LocAsInteger Differential Revision: https://reviews.llvm.org/D49437 Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp cfe/trunk/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp?rev=342221&r1=342220&r2=342221&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp Fri Sep 14 03:18:26 2018 @@ -274,15 +274,15 @@ bool FindUninitializedFields::isNonUnion continue; } -if (isDereferencableType(T)) { +SVal V = State->getSVal(FieldVal); + +if (isDereferencableType(T) || V.getAs()) { if (isDereferencableUninit(FR, LocalChain)) ContainsUninitField = true; continue; } if (isPrimitiveType(T)) { - SVal V = State->getSVal(FieldVal); - if (isPrimitiveUninit(V)) { if (addFieldToUninits(LocalChain.add(RegularField(FR ContainsUninitField = true; Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp?rev=342221&r1=342220&r2=342221&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp Fri Sep 14 03:18:26 2018 @@ -57,9 +57,9 @@ public: } }; -/// Represents a void* field that needs to be casted back to its dynamic type -/// for a correct note message. -class NeedsCastLocField final : public FieldNode { +/// Represents a nonloc::LocAsInteger or void* field, that point to objects, but +/// needs to be casted back to its dynamic type for a correct note message. +class NeedsCastLocField : public FieldNode { QualType CastBackType; public: @@ -71,7 +71,13 @@ public: } virtual void printPrefix(llvm::raw_ostream &Out) const override { -Out << "static_cast" << '<' << CastBackType.getAsString() << ">("; +// If this object is a nonloc::LocAsInteger. +if (getDecl()->getType()->isIntegerType()) + Out << "reinterpret_cast"; +// If this pointer's dynamic type is different then it's static type. +else + Out << "static_cast"; +Out << '<' << CastBackType.getAsString() << ">("; } virtual void printNode(llvm::raw_ostream &Out) const override { @@ -106,11 +112,12 @@ static llvm::Optional d bool FindUninitializedFields::isDereferencableUninit( const FieldRegion *FR, FieldChainInfo LocalChain) { - assert(isDereferencableType(FR->getDecl()->getType()) && - "This method only checks dereferencable objects!"); - SVal V = State->getSVal(FR); + assert((isDereferencableType(FR->getDecl()->getType()) || + V.getAs()) && + "This method only checks dereferencable objects!"); + if (V.isUnknown() || V.getAs()) { IsAnyFieldInitialized = true; return false; @@ -196,13 +203,15 @@ static llvm::Optional d llvm::SmallSet VisitedRegions; - // If the static type of the field is a void pointer, we need to cast it back - // to the dynamic type before dereferencing. - bool NeedsCastBack = isVoidPointer(FR->getDecl()->getType()); - SVal V = State->getSVal(FR); assert(V.getAsRegion() && "V must have an underlying region!"); + // If the static type of the field is a void pointer, or it is a + // nonloc::LocAsInteger, we need to cast it back to the dynamic type before + // dereferencing. + bool NeedsCastBack = isVoidPointer(FR->getDecl()->getType()) || + V.getAs(); + // The region we'd like to acquire. const auto *R = V.getAsRegion()->getAs(); if (!R) Modified: cfe/trunk/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp?rev=342221&r1=342220&r2=342221&view=diff == --- cfe/trunk/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp (original) +++ cfe/trunk/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp Fri Sep 14 03:18:26 2018 @@ -22,6 +22,24 @@ void fConcreteInt
r342223 - [analyzer] Attempt to make a windows buildbot happy.
Author: szelethus Date: Fri Sep 14 04:20:16 2018 New Revision: 342223 URL: http://llvm.org/viewvc/llvm-project?rev=342223&view=rev Log: [analyzer] Attempt to make a windows buildbot happy. Got an error that a cast is happening from a pointer type to long, which is smaller. Modified: cfe/trunk/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp Modified: cfe/trunk/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp?rev=342223&r1=34&r2=342223&view=diff == --- cfe/trunk/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp (original) +++ cfe/trunk/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp Fri Sep 14 04:20:16 2018 @@ -25,7 +25,7 @@ void fConcreteIntLocTest() { // nonloc::LocAsInteger tests. //===--===// -using intptr_t = long; +using intptr_t = unsigned long long; struct LocAsIntegerTest { intptr_t ptr; // expected-note{{uninitialized pointee 'reinterpret_cast(this->ptr)'}} ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r334935 - [analyzer] Checker for uninitialized C++ objects
Author: szelethus Date: Mon Jun 18 04:50:17 2018 New Revision: 334935 URL: http://llvm.org/viewvc/llvm-project?rev=334935&view=rev Log: [analyzer] Checker for uninitialized C++ objects This checker analyzes C++ constructor calls, and reports uninitialized fields. Due to the nature of this problem (uninitialized fields after an object construction), this checker doesn't search for bugs, but rather is a tool to enforce a specific programming model where every field needs to be initialized. This checker lands in alpha for now, and a number of followup patches will be made to reduce false negatives and to make it easier for the user to understand what rules the checker relies on, eg. whether a derived class' constructor is responsible for initializing inherited data members or whether it should be handled in the base class' constructor. Differential Revision: https://reviews.llvm.org/D45532 Added: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObjectChecker.cpp cfe/trunk/test/Analysis/Inputs/system-header-simulator-for-cxx-uninitialized-object.h cfe/trunk/test/Analysis/cxx-uninitialized-object-inheritance.cpp cfe/trunk/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp cfe/trunk/test/Analysis/cxx-uninitialized-object.cpp Modified: cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td cfe/trunk/lib/StaticAnalyzer/Checkers/CMakeLists.txt Modified: cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td?rev=334935&r1=334934&r2=334935&view=diff == --- cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td (original) +++ cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td Mon Jun 18 04:50:17 2018 @@ -319,6 +319,10 @@ def MisusedMovedObjectChecker: Checker<" "object will be reported">, DescFile<"MisusedMovedObjectChecker.cpp">; +def UninitializedObjectChecker: Checker<"UninitializedObject">, + HelpText<"Reports uninitialized fields after object construction">, + DescFile<"UninitializedObjectChecker.cpp">; + } // end: "alpha.cplusplus" Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/CMakeLists.txt URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/CMakeLists.txt?rev=334935&r1=334934&r2=334935&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Checkers/CMakeLists.txt (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/CMakeLists.txt Mon Jun 18 04:50:17 2018 @@ -92,6 +92,7 @@ add_clang_library(clangStaticAnalyzerChe UndefResultChecker.cpp UndefinedArraySubscriptChecker.cpp UndefinedAssignmentChecker.cpp + UninitializedObjectChecker.cpp UnixAPIChecker.cpp UnreachableCodeChecker.cpp VforkChecker.cpp Added: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObjectChecker.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObjectChecker.cpp?rev=334935&view=auto == --- cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObjectChecker.cpp (added) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObjectChecker.cpp Mon Jun 18 04:50:17 2018 @@ -0,0 +1,669 @@ +//===- UninitializedObjectChecker.cpp *- 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 checker that reports uninitialized fields in objects +// created after a constructor call. +// +// This checker has an option "Pedantic" (boolean). If its not set or is set to +// false, the checker won't emit warnings for objects that don't have at least +// one initialized field. This may be set with +// `-analyzer-config alpha.cplusplus.UninitializedObject:Pedantic=true`. +// +//===--===// + +#include "ClangSACheckers.h" +#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" +#include "clang/StaticAnalyzer/Core/Checker.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" +#include + +using namespace clang; +using namespace clang::ento; + +namespace { + +class UninitializedObjectChecker : public Checker { + std::unique_ptr BT_uninitField; + +public: + bool IsPedantic; // Will be initialized when registering the checker. + + UninitializedObjectChecker() + : BT_uninitField(new BuiltinBug(this, "Uninitialized fields")) {} + void checkEndFunction(CheckerContext &C) const; +}; + +llvm::ImmutableListFactory Factory; + +/// Represents a field chain. A field chain is a vector of fields where
r335030 - [analyzer] Made a buildbot happy.
Author: szelethus Date: Tue Jun 19 01:35:02 2018 New Revision: 335030 URL: http://llvm.org/viewvc/llvm-project?rev=335030&view=rev Log: [analyzer] Made a buildbot happy. Since `isPrimitiveType` was only used in an assert, a builbot with `-Werror` and no asserts enabled failed to build it as it was unused. Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObjectChecker.cpp Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObjectChecker.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObjectChecker.cpp?rev=335030&r1=335029&r2=335030&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObjectChecker.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObjectChecker.cpp Tue Jun 19 01:35:02 2018 @@ -384,15 +384,17 @@ bool FindUninitializedFields::isNonUnion continue; } -assert(isPrimitiveType(T) && "Non-primitive type! " - "At this point FR must be primitive!"); +if (isPrimitiveType(T)) { + SVal V = State->getSVal(FieldVal); -SVal V = State->getSVal(FieldVal); - -if (isPrimitiveUninit(V)) { - if (addFieldToUninits({LocalChain, FR})) -ContainsUninitField = true; + if (isPrimitiveUninit(V)) { +if (addFieldToUninits({LocalChain, FR})) + ContainsUninitField = true; + } + continue; } + +llvm_unreachable("All cases are handled!"); } // Checking bases. ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r344242 - [analyzer][UninitializedObjectChecker] Reports Loc fields pointing to themselves
Author: szelethus Date: Thu Oct 11 04:58:53 2018 New Revision: 344242 URL: http://llvm.org/viewvc/llvm-project?rev=344242&view=rev Log: [analyzer][UninitializedObjectChecker] Reports Loc fields pointing to themselves I've added a new functionality, the checker is now able to detect and report fields pointing to themselves. I figured this would fit well into the checker as there's no reason for a pointer to point to itself instead of being nullptr. Differential Revision: https://reviews.llvm.org/D51305 Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp cfe/trunk/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp?rev=344242&r1=344241&r2=344242&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp Thu Oct 11 04:58:53 2018 @@ -89,15 +89,39 @@ public: } }; +/// Represents a Loc field that points to itself. +class CyclicLocField final : public FieldNode { + +public: + CyclicLocField(const FieldRegion *FR) : FieldNode(FR) {} + + virtual void printNoteMsg(llvm::raw_ostream &Out) const override { +Out << "object references itself "; + } + + virtual void printPrefix(llvm::raw_ostream &Out) const override {} + + virtual void printNode(llvm::raw_ostream &Out) const override { +Out << getVariableName(getDecl()); + } + + virtual void printSeparator(llvm::raw_ostream &Out) const override { +llvm_unreachable("CyclicLocField objects must be the last node of the " + "fieldchain!"); + } +}; + } // end of anonymous namespace // Utility function declarations. -/// Returns whether \p T can be (transitively) dereferenced to a void pointer -/// type (void*, void**, ...). -static bool isVoidPointer(QualType T); - -using DereferenceInfo = std::pair; +struct DereferenceInfo { + const TypedValueRegion *R; + const bool NeedsCastBack; + const bool IsCyclic; + DereferenceInfo(const TypedValueRegion *R, bool NCB, bool IC) + : R(R), NeedsCastBack(NCB), IsCyclic(IC) {} +}; /// Dereferences \p FR and returns with the pointee's region, and whether it /// needs to be casted back to it's location type. If for whatever reason @@ -105,6 +129,10 @@ using DereferenceInfo = std::pair dereference(ProgramStateRef State, const FieldRegion *FR); +/// Returns whether \p T can be (transitively) dereferenced to a void pointer +/// type (void*, void**, ...). +static bool isVoidPointer(QualType T); + //===--===// // Methods for FindUninitializedFields. //===--===// @@ -141,8 +169,11 @@ bool FindUninitializedFields::isDerefere return false; } - const TypedValueRegion *R = DerefInfo->first; - const bool NeedsCastBack = DerefInfo->second; + if (DerefInfo->IsCyclic) +return addFieldToUninits(LocalChain.add(CyclicLocField(FR))); + + const TypedValueRegion *R = DerefInfo->R; + const bool NeedsCastBack = DerefInfo->NeedsCastBack; QualType DynT = R->getLocationType(); QualType PointeeT = DynT->getPointeeType(); @@ -189,15 +220,6 @@ bool FindUninitializedFields::isDerefere // Utility functions. //===--===// -static bool isVoidPointer(QualType T) { - while (!T.isNull()) { -if (T->isVoidPointerType()) - return true; -T = T->getPointeeType(); - } - return false; -} - static llvm::Optional dereference(ProgramStateRef State, const FieldRegion *FR) { @@ -229,9 +251,8 @@ static llvm::Optional d return None; // We found a cyclic pointer, like int *ptr = (int *)&ptr. -// TODO: Should we report these fields too? if (!VisitedRegions.insert(R).second) - return None; + return DereferenceInfo{R, NeedsCastBack, /*IsCyclic*/ true}; DynT = R->getLocationType(); // In order to ensure that this loop terminates, we're also checking the @@ -248,5 +269,14 @@ static llvm::Optional d R = R->getSuperRegion()->getAs(); } - return std::make_pair(R, NeedsCastBack); + return DereferenceInfo{R, NeedsCastBack, /*IsCyclic*/ false}; +} + +static bool isVoidPointer(QualType T) { + while (!T.isNull()) { +if (T->isVoidPointerType()) + return true; +T = T->getPointeeType(); + } + return false; } Modified: cfe/trunk/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp URL: ht
r344870 - [analyzer][NFC] Fix inconsistencies in AnalyzerOptions
Author: szelethus Date: Sun Oct 21 11:19:32 2018 New Revision: 344870 URL: http://llvm.org/viewvc/llvm-project?rev=344870&view=rev Log: [analyzer][NFC] Fix inconsistencies in AnalyzerOptions I'm in the process of refactoring AnalyzerOptions. The main motivation behind here is to emit warnings if an invalid -analyzer-config option is given from the command line, and be able to list them all. This first NFC patch contains small modifications to make AnalyzerOptions.cpp a little more consistent. Differential Revision: https://reviews.llvm.org/D53274 Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h cfe/trunk/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp cfe/trunk/lib/StaticAnalyzer/Core/CoreEngine.cpp Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h?rev=344870&r1=344869&r2=344870&view=diff == --- cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h (original) +++ cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h Sun Oct 21 11:19:32 2018 @@ -85,7 +85,7 @@ enum CXXInlineableMemberKind { // Uninitialized = 0, /// A dummy mode in which no C++ inlining is enabled. - CIMK_None = 1, + CIMK_None, /// Refers to regular member function and operator calls. CIMK_MemberFunctions, @@ -102,8 +102,6 @@ enum CXXInlineableMemberKind { /// Describes the different modes of inter-procedural analysis. enum IPAKind { - IPAK_NotSet = 0, - /// Perform only intra-procedural analysis. IPAK_None = 1, @@ -188,16 +186,11 @@ public: UnexploredFirstQueue, UnexploredFirstLocationQueue, BFSBlockDFSContents, -NotSet }; private: - ExplorationStrategyKind ExplorationStrategy = ExplorationStrategyKind::NotSet; - /// Describes the kinds for high-level analyzer mode. enum UserModeKind { -UMK_NotSet = 0, - /// Perform shallow but fast analyzes. UMK_Shallow = 1, @@ -205,16 +198,18 @@ private: UMK_Deep = 2 }; + llvm::Optional ExplorationStrategy; + /// Controls the high-level analyzer mode, which influences the default /// settings for some of the lower-level config options (such as IPAMode). /// \sa getUserMode - UserModeKind UserMode = UMK_NotSet; + llvm::Optional UserMode; /// Controls the mode of inter-procedural analysis. - IPAKind IPAMode = IPAK_NotSet; + llvm::Optional IPAMode; /// Controls which C++ member functions will be considered for inlining. - CXXInlineableMemberKind CXXMemberInliningMode; + llvm::Optional CXXMemberInliningMode; /// \sa includeImplicitDtorsInCFG Optional IncludeImplicitDtorsInCFG; @@ -420,6 +415,12 @@ public: const ento::CheckerBase *C = nullptr, bool SearchInParents = false); + + unsigned getOptionAsUInt(Optional &V, StringRef Name, + unsigned DefaultVal, + const ento::CheckerBase *C = nullptr, + bool SearchInParents = false); + /// Query an option's string value. /// /// If an option value is not provided, returns the given \p DefaultVal. @@ -437,6 +438,11 @@ public: const ento::CheckerBase *C = nullptr, bool SearchInParents = false); + StringRef getOptionAsString(Optional &V, StringRef Name, + StringRef DefaultVal, + const ento::CheckerBase *C = nullptr, + bool SearchInParents = false); + /// Retrieves and sets the UserMode. This is a high-level option, /// which is used to set other low-level options. It is not accessible /// outside of AnalyzerOptions. Modified: cfe/trunk/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp?rev=344870&r1=344869&r2=344870&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp Sun Oct 21 11:19:32 2018 @@ -50,27 +50,24 @@ AnalyzerOptions::getRegisteredCheckers(b } AnalyzerOptions::UserModeKind AnalyzerOptions::getUserMode() { - if (UserMode == UMK_NotSet) { -StringRef ModeStr = -Config.insert(std::make_pair("mode", "deep")).first->second; -UserMode = llvm::StringSwitch(ModeStr) + if (!UserMode.hasValue()) { +StringRef ModeStr = getOptionAsString("mode", "deep"); +UserMode = llvm::StringSwitch>(ModeStr) .Case("shallow", UMK_Shallow) .Case("deep", UMK_Deep) - .Default(UMK_NotSet); -assert(UserMode != UMK_NotSet && "User mode is invalid."); + .Default(None); +assert(UserMode.getValue() && "User mode is in
r344878 - [analyzer][www] Update alpha_checks.html
Author: szelethus Date: Sun Oct 21 15:10:15 2018 New Revision: 344878 URL: http://llvm.org/viewvc/llvm-project?rev=344878&view=rev Log: [analyzer][www] Update alpha_checks.html I added some missing doc. I have not developed any of these checkers, it might worth really inspecting whether I wrote something terribly incorrect. Differential Revision: https://reviews.llvm.org/D52969 Modified: cfe/trunk/www/analyzer/alpha_checks.html cfe/trunk/www/analyzer/available_checks.html Modified: cfe/trunk/www/analyzer/alpha_checks.html URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/www/analyzer/alpha_checks.html?rev=344878&r1=344877&r2=344878&view=diff == --- cfe/trunk/www/analyzer/alpha_checks.html (original) +++ cfe/trunk/www/analyzer/alpha_checks.html Sun Oct 21 15:10:15 2018 @@ -107,6 +107,7 @@ void test(void) { } + alpha.core.CastSize (C) @@ -276,6 +277,33 @@ int test(struct s *p) { +alpha.core.StackAddressAsyncEscape +(C) +Check that addresses to stack memory do not escape the function that involves +dispatch_after or dispatch_async. This checker is +a part of core.StackAddressEscape, but is +https://reviews.llvm.org/D41042>temporarily disabled until some +false positives are fixed. + + +dispatch_block_t test_block_inside_block_async_leak() { + int x = 123; + void (^inner)(void) = ^void(void) { +int y = x; +++y; + }; + void (^outer)(void) = ^void(void) { +int z = x; +++z; +inner(); + }; + return outer; // warn: address of stack-allocated block is captured by a +// returned block +} + + + + alpha.core.TestAfterDivZero (C, C++, ObjC) Check for division by variable that is later compared against 0. @@ -289,6 +317,7 @@ void test(int x) { } + @@ -296,72 +325,142 @@ void test(int x) { Name, DescriptionExample - + + -alpha.cplusplus.VirtualCall +alpha.cplusplus.DeleteWithNonVirtualDtor (C++) -Check virtual member function calls during construction or -destruction. +Reports destructions of polymorphic objects with a non-virtual destructor in +their base class + -class A { -public: - A() { -f(); // warn - } - virtual void f(); -}; - +NonVirtual *create() { + NonVirtual *x = new NVDerived(); // note: conversion from derived to base + // happened here + return x; +} + +void sink(NonVirtual *x) { + delete x; // warn: destruction of a polymorphic object with no virtual +// destructor +} + + + + +alpha.cplusplus.InvalidatedIterator +(C++) +Check for use of invalidated iterators. + + -class A { -public: - ~A() { -this->f(); // warn - } - virtual void f(); +void bad_copy_assign_operator_list1(std::list &L1, +const std::list &L2) { + auto i0 = L1.cbegin(); + L1 = L2; + *i0; // warn: invalidated iterator accessed +} + + + + +alpha.cplusplus.IteratorRange +(C++) +Check for iterators used outside their valid ranges. + + + +void simple_bad_end(const std::vector &v) { + auto i = v.end(); + *i; // warn: iterator accessed outside of its range +} + + + + +alpha.cplusplus.MismatchedIterator +(C++) +Check for use of iterators of different containers where iterators of the same +container are expected. + + + +void bad_insert3(std::vector &v1, std::vector &v2) { + v2.insert(v1.cbegin(), v2.cbegin(), v2.cend()); // warn: container accessed + // using foreign + // iterator argument + v1.insert(v1.cbegin(), v1.cbegin(), v2.cend()); // warn: iterators of + // different containers + // used where the same + // container is + // expected + v1.insert(v1.cbegin(), v2.cbegin(), v1.cend()); // warn: iterators of + // different containers + // used where the same + // container is + // expected +} + + + + +alpha.cplusplus.MisusedMovedObject +(C++) +Method calls on a moved-from object and copying a moved-from object will be +reported. + + + +struct A { + void foo() {} }; + +void f() { + A a; + A b = std::move(a); // note: 'a' became 'moved-from' here + a.foo();// warn: method call on a 'moved-from' object 'a' +} - + alpha.cplusplus.UninitializedObject (C++) -This checker reports uninitialized fields in objects created -after a constructor call. It doesn't only find direct uninitialized -fields, but rather makes a deep inspection of the object, -analyzing all of it's fields subfields.
r344879 - [analyzer][UninitializedObjectChecker] No longer using nonloc::LazyCompoundVal
Author: szelethus Date: Sun Oct 21 16:30:01 2018 New Revision: 344879 URL: http://llvm.org/viewvc/llvm-project?rev=344879&view=rev Log: [analyzer][UninitializedObjectChecker] No longer using nonloc::LazyCompoundVal As rightly pointed out by @NoQ, nonloc::LazyCompoundVals were only used to acquire a constructed object's region, which isn't what LazyCompoundVal was made for. Differential Revision: https://reviews.llvm.org/D51300 Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp?rev=344879&r1=344878&r2=344879&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp Sun Oct 21 16:30:01 2018 @@ -96,12 +96,11 @@ public: // Utility function declarations. -/// Returns the object that was constructed by CtorDecl, or None if that isn't -/// possible. -// TODO: Refactor this function so that it returns the constructed object's -// region. -static Optional -getObjectVal(const CXXConstructorDecl *CtorDecl, CheckerContext &Context); +/// Returns the region that was constructed by CtorDecl, or nullptr if that +/// isn't possible. +static const TypedValueRegion * +getConstructedRegion(const CXXConstructorDecl *CtorDecl, + CheckerContext &Context); /// Checks whether the object constructed by \p Ctor will be analyzed later /// (e.g. if the object is a field of another object, in which case we'd check @@ -135,11 +134,11 @@ void UninitializedObjectChecker::checkEn if (willObjectBeAnalyzedLater(CtorDecl, Context)) return; - Optional Object = getObjectVal(CtorDecl, Context); - if (!Object) + const TypedValueRegion *R = getConstructedRegion(CtorDecl, Context); + if (!R) return; - FindUninitializedFields F(Context.getState(), Object->getRegion(), Opts); + FindUninitializedFields F(Context.getState(), R, Opts); const UninitFieldMap &UninitFields = F.getUninitFields(); @@ -400,25 +399,27 @@ static void printTail(llvm::raw_ostream // Utility functions. //===--===// -static Optional -getObjectVal(const CXXConstructorDecl *CtorDecl, CheckerContext &Context) { +static const TypedValueRegion * +getConstructedRegion(const CXXConstructorDecl *CtorDecl, + CheckerContext &Context) { - Loc ThisLoc = Context.getSValBuilder().getCXXThis(CtorDecl->getParent(), + Loc ThisLoc = Context.getSValBuilder().getCXXThis(CtorDecl, Context.getStackFrame()); - // Getting the value for 'this'. - SVal This = Context.getState()->getSVal(ThisLoc); - // Getting the value for '*this'. - SVal Object = Context.getState()->getSVal(This.castAs()); + SVal ObjectV = Context.getState()->getSVal(ThisLoc); - return Object.getAs(); + auto *R = ObjectV.getAsRegion()->getAs(); + if (R && !R->getValueType()->getAsCXXRecordDecl()) +return nullptr; + + return R; } static bool willObjectBeAnalyzedLater(const CXXConstructorDecl *Ctor, CheckerContext &Context) { - Optional CurrentObject = getObjectVal(Ctor, Context); - if (!CurrentObject) + const TypedValueRegion *CurrRegion = getConstructedRegion(Ctor, Context); + if (!CurrRegion) return false; const LocationContext *LC = Context.getLocationContext(); @@ -429,14 +430,14 @@ static bool willObjectBeAnalyzedLater(co if (!OtherCtor) continue; -Optional OtherObject = -getObjectVal(OtherCtor, Context); -if (!OtherObject) +const TypedValueRegion *OtherRegion = +getConstructedRegion(OtherCtor, Context); +if (!OtherRegion) continue; -// If the CurrentObject is a subregion of OtherObject, it will be analyzed -// during the analysis of OtherObject. -if (CurrentObject->getRegion()->isSubRegionOf(OtherObject->getRegion())) +// If the CurrRegion is a subregion of OtherRegion, it will be analyzed +// during the analysis of OtherRegion. +if (CurrRegion->isSubRegionOf(OtherRegion)) return true; } ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r345531 - [analyzer][NFC] Refactor PlistDiagnostics to use a class instead of passing 9 parameters around
Author: szelethus Date: Mon Oct 29 13:06:30 2018 New Revision: 345531 URL: http://llvm.org/viewvc/llvm-project?rev=345531&view=rev Log: [analyzer][NFC] Refactor PlistDiagnostics to use a class instead of passing 9 parameters around This has been a long time coming. Note the usage of AnalyzerOptions: I'll need it for D52742, and added it in rC343620. The main motivation for this was that I'll need to add yet another parameter to every single function, and some functions would reach their 10th parameter with that change. Modified: cfe/trunk/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp Modified: cfe/trunk/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp?rev=345531&r1=345530&r2=345531&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp Mon Oct 29 13:06:30 2018 @@ -24,10 +24,16 @@ #include "llvm/ADT/Statistic.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Support/Casting.h" + using namespace clang; using namespace ento; using namespace markup; +//===--===// +// Declarations of helper classes and functions for emitting bug reports in +// plist format. +//===--===// + namespace { class PlistDiagnostics : public PathDiagnosticConsumer { const std::string OutputFile; @@ -59,34 +65,91 @@ namespace { }; } // end anonymous namespace -PlistDiagnostics::PlistDiagnostics(AnalyzerOptions &AnalyzerOpts, - const std::string& output, - const Preprocessor &PP, - bool supportsMultipleFiles) - : OutputFile(output), PP(PP), AnOpts(AnalyzerOpts), -SupportsCrossFileDiagnostics(supportsMultipleFiles) {} +namespace { -void ento::createPlistDiagnosticConsumer(AnalyzerOptions &AnalyzerOpts, - PathDiagnosticConsumers &C, - const std::string& s, - const Preprocessor &PP) { - C.push_back(new PlistDiagnostics(AnalyzerOpts, s, PP, - /*supportsMultipleFiles*/ false)); -} +/// A helper class for emitting a single report. +class PlistPrinter { + const FIDMap& FM; + AnalyzerOptions &AnOpts; + const Preprocessor &PP; + +public: + PlistPrinter(const FIDMap& FM, AnalyzerOptions &AnOpts, + const Preprocessor &PP) +: FM(FM), AnOpts(AnOpts), PP(PP) { + } -void ento::createPlistMultiFileDiagnosticConsumer(AnalyzerOptions &AnalyzerOpts, - PathDiagnosticConsumers &C, - const std::string &s, - const Preprocessor &PP) { - C.push_back(new PlistDiagnostics(AnalyzerOpts, s, PP, - /*supportsMultipleFiles*/ true)); -} + void ReportDiag(raw_ostream &o, const PathDiagnosticPiece& P) { +ReportPiece(o, P, /*indent*/ 4, /*depth*/ 0, /*includeControlFlow*/ true); + +// Don't emit a warning about an unused private field. +(void)AnOpts; + } + +private: + void ReportPiece(raw_ostream &o, const PathDiagnosticPiece &P, + unsigned indent, unsigned depth, bool includeControlFlow, + bool isKeyEvent = false) { +switch (P.getKind()) { + case PathDiagnosticPiece::ControlFlow: +if (includeControlFlow) + ReportControlFlow(o, cast(P), indent); +break; + case PathDiagnosticPiece::Call: +ReportCall(o, cast(P), indent, + depth); +break; + case PathDiagnosticPiece::Event: +ReportEvent(o, cast(P), indent, depth, +isKeyEvent); +break; + case PathDiagnosticPiece::Macro: +ReportMacro(o, cast(P), indent, depth); +break; + case PathDiagnosticPiece::Note: +ReportNote(o, cast(P), indent); +break; +} + } + + void EmitRanges(raw_ostream &o, const ArrayRef Ranges, + unsigned indent); + void EmitMessage(raw_ostream &o, StringRef Message, unsigned indent); + + void ReportControlFlow(raw_ostream &o, + const PathDiagnosticControlFlowPiece& P, + unsigned indent); + void ReportEvent(raw_ostream &o, const PathDiagnosticEventPiece& P, + unsigned indent, unsigned depth, bool isKeyEvent = false); + void ReportCall(raw_ostream &o, const PathDiagnosticCallPiece &P, + unsigned indent, unsigned depth); + void ReportMacro(raw_ostream &o, const PathDiagnosticMacroPiece& P, + unsigned indent,
r352277 - [analyzer] Supply all checkers with a shouldRegister function
Author: szelethus Date: Sat Jan 26 06:23:08 2019 New Revision: 352277 URL: http://llvm.org/viewvc/llvm-project?rev=352277&view=rev Log: [analyzer] Supply all checkers with a shouldRegister function Introduce the boolean ento::shouldRegister##CHECKERNAME(const LangOptions &LO) function very similarly to ento::register##CHECKERNAME. This will force every checker to implement this function, but maybe it isn't that bad: I saw a lot of ObjC or C++ specific checkers that should probably not register themselves based on some LangOptions (mine too), but they do anyways. A big benefit of this is that all registry functions now register their checker, once it is called, registration is guaranteed. This patch is a part of a greater effort to reinvent checker registration, more info here: D54438#1315953 Differential Revision: https://reviews.llvm.org/D55424 Modified: cfe/trunk/include/clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h cfe/trunk/include/clang/StaticAnalyzer/Core/Checker.h cfe/trunk/include/clang/StaticAnalyzer/Frontend/CheckerRegistry.h cfe/trunk/include/clang/StaticAnalyzer/Frontend/FrontendActions.h cfe/trunk/lib/FrontendTool/ExecuteCompilerInvocation.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/AnalysisOrderChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/AnalyzerStatsChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/ArrayBoundChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/BoolAssignmentChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/CStringChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/CXXSelfAssignmentChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/CastToStructChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/CheckObjCDealloc.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/CheckObjCInstMethSignature.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/CheckSizeofPointer.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/CloneChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/ConversionChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/DebugCheckers.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/DeleteWithNonVirtualDtorChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/DirectIvarAssignment.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/DivZeroChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/DynamicTypeChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/EnumCastOutOfRangeChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/FixedAddressChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/GCDAntipatternChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/GTestChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/IdenticalExprChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/InnerPointerChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/IvarInvalidationChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/LLVMConventionsChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/MallocOverflowSecurityChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/MallocSizeofChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/MmapWriteExecChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/MoveChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/NSAutoreleasePoolChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/NSErrorChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/NoReturnFunctionChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/NonnullGlobalConstantsChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/NumberObjectConversionChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/Obj
r352278 - [analyzer] Split unix.API up to UnixAPIMisuseChecker and UnixAPIPortabilityChecker
Author: szelethus Date: Sat Jan 26 07:56:40 2019 New Revision: 352278 URL: http://llvm.org/viewvc/llvm-project?rev=352278&view=rev Log: [analyzer] Split unix.API up to UnixAPIMisuseChecker and UnixAPIPortabilityChecker The actual implementation of unix.API features a dual-checker: two checkers in one, even though they don't even interact at all. Split them up, as this is a problem for establishing dependencies. I added no new code at all, just merely moved it around. Since the plist files change (and that's a benefit!) this patch isn't NFC. Differential Revision: https://reviews.llvm.org/D55425 Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp cfe/trunk/test/Analysis/Inputs/expected-plists/unix-fns.c.plist Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp?rev=352278&r1=352277&r2=352278&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp Sat Jan 26 07:56:40 2019 @@ -20,10 +20,7 @@ #include "llvm/ADT/Optional.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallString.h" -#include "llvm/ADT/StringExtras.h" -#include "llvm/ADT/StringSwitch.h" #include "llvm/Support/raw_ostream.h" -#include using namespace clang; using namespace ento; @@ -39,8 +36,9 @@ enum class OpenVariant { }; namespace { -class UnixAPIChecker : public Checker< check::PreStmt > { - mutable std::unique_ptr BT_open, BT_pthreadOnce, BT_mallocZero; + +class UnixAPIMisuseChecker : public Checker< check::PreStmt > { + mutable std::unique_ptr BT_open, BT_pthreadOnce; mutable Optional Val_O_CREAT; public: @@ -50,8 +48,25 @@ public: void CheckOpen(CheckerContext &C, const CallExpr *CE) const; void CheckOpenAt(CheckerContext &C, const CallExpr *CE) const; - void CheckPthreadOnce(CheckerContext &C, const CallExpr *CE) const; + + void CheckOpenVariant(CheckerContext &C, +const CallExpr *CE, OpenVariant Variant) const; + + void ReportOpenBug(CheckerContext &C, + ProgramStateRef State, + const char *Msg, + SourceRange SR) const; + +}; + +class UnixAPIPortabilityChecker : public Checker< check::PreStmt > { +public: + void checkPreStmt(const CallExpr *CE, CheckerContext &C) const; + +private: + mutable std::unique_ptr BT_mallocZero; + void CheckCallocZero(CheckerContext &C, const CallExpr *CE) const; void CheckMallocZero(CheckerContext &C, const CallExpr *CE) const; void CheckReallocZero(CheckerContext &C, const CallExpr *CE) const; @@ -60,13 +75,6 @@ public: void CheckAllocaWithAlignZero(CheckerContext &C, const CallExpr *CE) const; void CheckVallocZero(CheckerContext &C, const CallExpr *CE) const; - typedef void (UnixAPIChecker::*SubChecker)(CheckerContext &, - const CallExpr *) const; -private: - - void CheckOpenVariant(CheckerContext &C, -const CallExpr *CE, OpenVariant Variant) const; - bool ReportZeroByteAllocation(CheckerContext &C, ProgramStateRef falseState, const Expr *arg, @@ -76,48 +84,75 @@ private: const unsigned numArgs, const unsigned sizeArg, const char *fn) const; - void LazyInitialize(std::unique_ptr &BT, const char *name) const { -if (BT) - return; -BT.reset(new BugType(this, name, categories::UnixAPI)); - } - void ReportOpenBug(CheckerContext &C, - ProgramStateRef State, - const char *Msg, - SourceRange SR) const; }; + } //end anonymous namespace +static void LazyInitialize(const CheckerBase *Checker, + std::unique_ptr &BT, + const char *name) { + if (BT) +return; + BT.reset(new BugType(Checker, name, categories::UnixAPI)); +} + //===--===// // "open" (man 2 open) -//===--===// +//===--===/ + +void UnixAPIMisuseChecker::checkPreStmt(const CallExpr *CE, +CheckerContext &C) const { + const FunctionDecl *FD = C.getCalleeDecl(CE); + if (!FD || FD->getKind() != Decl::Function) +return; + + // Don't treat functions in namespaces with the same name a Unix function + // as a call to the Unix function. + const DeclContext *NamespaceCtx = FD->getEnclosingNamespaceContext(); + if (NamespaceCtx && isa(NamespaceCtx)) +return; -void UnixAPIChecker::ReportOpenBug(CheckerContext &C,
r352279 - [analyzer][NFC] Supply CheckerRegistry with AnalyzerOptions
Author: szelethus Date: Sat Jan 26 07:59:21 2019 New Revision: 352279 URL: http://llvm.org/viewvc/llvm-project?rev=352279&view=rev Log: [analyzer][NFC] Supply CheckerRegistry with AnalyzerOptions Since pretty much all methods of CheckerRegistry has AnalyzerOptions as an argument, it makes sense to just simply require it in it's constructor. Differential Revision: https://reviews.llvm.org/D56988 Modified: cfe/trunk/include/clang/StaticAnalyzer/Frontend/CheckerRegistry.h cfe/trunk/include/clang/StaticAnalyzer/Frontend/FrontendActions.h cfe/trunk/lib/FrontendTool/ExecuteCompilerInvocation.cpp cfe/trunk/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp cfe/trunk/lib/StaticAnalyzer/Frontend/CheckerRegistry.cpp Modified: cfe/trunk/include/clang/StaticAnalyzer/Frontend/CheckerRegistry.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Frontend/CheckerRegistry.h?rev=352279&r1=352278&r2=352279&view=diff == --- cfe/trunk/include/clang/StaticAnalyzer/Frontend/CheckerRegistry.h (original) +++ cfe/trunk/include/clang/StaticAnalyzer/Frontend/CheckerRegistry.h Sat Jan 26 07:59:21 2019 @@ -82,7 +82,7 @@ namespace ento { class CheckerRegistry { public: CheckerRegistry(ArrayRef plugins, DiagnosticsEngine &diags, - const LangOptions &LangOpts); + AnalyzerOptions &AnOpts, const LangOptions &LangOpts); /// Initialization functions perform any necessary setup for a checker. /// They should include a call to CheckerManager::registerChecker. @@ -137,24 +137,24 @@ public: /// all checkers specified by the given CheckerOptInfo list. The order of this /// list is significant; later options can be used to reverse earlier ones. /// This can be used to exclude certain checkers in an included package. - void initializeManager(CheckerManager &mgr, - const AnalyzerOptions &Opts) const; + void initializeManager(CheckerManager &mgr) 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 printList(raw_ostream &out) const; private: - CheckerInfoSet getEnabledCheckers(const AnalyzerOptions &Opts) const; + CheckerInfoSet getEnabledCheckers() const; mutable CheckerInfoList Checkers; mutable llvm::StringMap Packages; DiagnosticsEngine &Diags; + AnalyzerOptions &AnOpts; const LangOptions &LangOpts; }; Modified: cfe/trunk/include/clang/StaticAnalyzer/Frontend/FrontendActions.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Frontend/FrontendActions.h?rev=352279&r1=352278&r2=352279&view=diff == --- cfe/trunk/include/clang/StaticAnalyzer/Frontend/FrontendActions.h (original) +++ cfe/trunk/include/clang/StaticAnalyzer/Frontend/FrontendActions.h Sat Jan 26 07:59:21 2019 @@ -51,10 +51,13 @@ private: llvm::StringMap &Bodies; }; -void printCheckerHelp(raw_ostream &OS, ArrayRef plugins, - DiagnosticsEngine &diags, const LangOptions &LangOpts); +void printCheckerHelp(raw_ostream &OS, + ArrayRef plugins, + AnalyzerOptions &opts, + DiagnosticsEngine &diags, + const LangOptions &LangOpts); void printEnabledCheckerList(raw_ostream &OS, ArrayRef plugins, - const AnalyzerOptions &opts, + AnalyzerOptions &opts, DiagnosticsEngine &diags, const LangOptions &LangOpts); void printAnalyzerConfigList(raw_ostream &OS); Modified: cfe/trunk/lib/FrontendTool/ExecuteCompilerInvocation.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/FrontendTool/ExecuteCompilerInvocation.cpp?rev=352279&r1=352278&r2=352279&view=diff == --- cfe/trunk/lib/FrontendTool/ExecuteCompilerInvocation.cpp (original) +++ cfe/trunk/lib/FrontendTool/ExecuteCompilerInvocation.cpp Sat Jan 26 07:59:21 2019 @@ -237,8 +237,11 @@ bool ExecuteCompilerInvocation(CompilerI // Honor -analyzer-checker-help. // This should happen AFTER plugins have been loaded! if (Clang->getAnalyzerOpts()->ShowCheckerHelp) { -ento::printCheckerHelp(llvm::outs(), Clang->getFrontendOpts().Plugins, - Clang->getDiagnostics(), Clang->getLangOpts()); +ento::printCheckerHelp(llvm::outs(), + Clang->ge
r352282 - [analyzer][NFC] Keep track of whether enabling a checker was explictly specified in command line arguments
Author: szelethus Date: Sat Jan 26 08:35:33 2019 New Revision: 352282 URL: http://llvm.org/viewvc/llvm-project?rev=352282&view=rev Log: [analyzer][NFC] Keep track of whether enabling a checker was explictly specified in command line arguments I added a new enum to CheckerInfo, so we can easily track whether the check is explicitly enabled, explicitly disabled, or isn't specified in this regard. Checkers belonging in the latter category may be implicitly enabled through dependencies in the followup patch. I also made sure that this is done within CheckerRegisty's constructor, leading to very significant simplifications in its query-like methods. Differential Revision: https://reviews.llvm.org/D56989 Modified: cfe/trunk/include/clang/StaticAnalyzer/Frontend/CheckerRegistry.h cfe/trunk/lib/StaticAnalyzer/Frontend/CheckerRegistry.cpp Modified: cfe/trunk/include/clang/StaticAnalyzer/Frontend/CheckerRegistry.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Frontend/CheckerRegistry.h?rev=352282&r1=352281&r2=352282&view=diff == --- cfe/trunk/include/clang/StaticAnalyzer/Frontend/CheckerRegistry.h (original) +++ cfe/trunk/include/clang/StaticAnalyzer/Frontend/CheckerRegistry.h Sat Jan 26 08:35:33 2019 @@ -90,11 +90,25 @@ public: using ShouldRegisterFunction = bool (*)(const LangOptions &); struct CheckerInfo { +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; ShouldRegisterFunction ShouldRegister; StringRef FullName; StringRef Desc; StringRef DocumentationUri; +StateFromCmdLine State = StateFromCmdLine::State_Unspecified; + +bool isEnabled(const LangOptions &LO) const { + return State == StateFromCmdLine::State_Enabled && ShouldRegister(LO); +} CheckerInfo(InitializationFunction Fn, ShouldRegisterFunction sfn, StringRef Name, StringRef Desc, StringRef DocsUri) @@ -102,7 +116,9 @@ public: DocumentationUri(DocsUri) {} }; + using StateFromCmdLine = CheckerInfo::StateFromCmdLine; using CheckerInfoList = std::vector; + using CheckerInfoListRange = llvm::iterator_range; using CheckerInfoSet = llvm::SetVector; private: @@ -133,6 +149,7 @@ public: &CheckerRegistry::returnTrue, FullName, Desc, DocsUri); } + // 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. @@ -150,8 +167,13 @@ public: private: CheckerInfoSet getEnabledCheckers() const; - mutable CheckerInfoList Checkers; - mutable llvm::StringMap Packages; + /// 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; + llvm::StringMap Packages; DiagnosticsEngine &Diags; AnalyzerOptions &AnOpts; Modified: cfe/trunk/lib/StaticAnalyzer/Frontend/CheckerRegistry.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Frontend/CheckerRegistry.cpp?rev=352282&r1=352281&r2=352282&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Frontend/CheckerRegistry.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Frontend/CheckerRegistry.cpp Sat Jan 26 08:35:33 2019 @@ -38,12 +38,66 @@ static bool isCompatibleAPIVersion(const return strcmp(versionString, CLANG_ANALYZER_API_VERSION_STRING) == 0; } +static bool checkerNameLT(const CheckerRegistry::CheckerInfo &a, + const CheckerRegistry::CheckerInfo &b) { + return a.FullName < b.FullName; +} + +static constexpr char PackageSeparator = '.'; + +static bool isInPackage(const CheckerRegistry::CheckerInfo &checker, +StringRef packageName) { + // Does the checker's full name have the package as a prefix? + if (!checker.FullName.startswith(packageName)) +return false; + + // Is the package actually just the name of a specific checker? + if (checker.FullName.size() == packageName.size()) +return true; + + // Is the checker in the package (or a subpackage)? + if (checker.FullName[packageName.size()] == PackageSeparator) +return true; + + return false; +} + +CheckerRegistry::CheckerInfoListRange +CheckerRegistry::getMutableCheckersForCmdLineArg(StringRef CmdLineArg) { + + assert(std::is_s
r352284 - [analyzer] Fix an bug where statically linked, but not registered checkers weren't recognized
Author: szelethus Date: Sat Jan 26 09:27:40 2019 New Revision: 352284 URL: http://llvm.org/viewvc/llvm-project?rev=352284&view=rev Log: [analyzer] Fix an bug where statically linked, but not registered checkers weren't recognized My last patch, D56989, moved the validation of whether a checker exists into its constructor, but we do support statically linked (and non-plugin) checkers that were do not have an entry in Checkers.td. However, the handling of this happens after the creation of the CheckerRegistry object. This patch fixes this bug by moving even this functionality into CheckerRegistry's constructor. Modified: cfe/trunk/include/clang/StaticAnalyzer/Frontend/CheckerRegistry.h cfe/trunk/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp cfe/trunk/lib/StaticAnalyzer/Frontend/CheckerRegistry.cpp Modified: cfe/trunk/include/clang/StaticAnalyzer/Frontend/CheckerRegistry.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Frontend/CheckerRegistry.h?rev=352284&r1=352283&r2=352284&view=diff == --- cfe/trunk/include/clang/StaticAnalyzer/Frontend/CheckerRegistry.h (original) +++ cfe/trunk/include/clang/StaticAnalyzer/Frontend/CheckerRegistry.h Sat Jan 26 09:27:40 2019 @@ -81,8 +81,11 @@ namespace ento { /// "core.builtin", or the full name "core.builtin.NoReturnFunctionChecker". class CheckerRegistry { public: - CheckerRegistry(ArrayRef plugins, DiagnosticsEngine &diags, - AnalyzerOptions &AnOpts, const LangOptions &LangOpts); + CheckerRegistry( + ArrayRef plugins, DiagnosticsEngine &diags, + AnalyzerOptions &AnOpts, const LangOptions &LangOpts, + ArrayRef> + checkerRegistrationFns = {}); /// Initialization functions perform any necessary setup for a checker. /// They should include a call to CheckerManager::registerChecker. Modified: cfe/trunk/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp?rev=352284&r1=352283&r2=352284&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp Sat Jan 26 09:27:40 2019 @@ -33,10 +33,8 @@ std::unique_ptr ento::cr DiagnosticsEngine &diags) { auto checkerMgr = llvm::make_unique(context, opts); - CheckerRegistry allCheckers(plugins, diags, opts, context.getLangOpts()); - - for (const auto &Fn : checkerRegistrationFns) -Fn(allCheckers); + CheckerRegistry allCheckers(plugins, diags, opts, context.getLangOpts(), + checkerRegistrationFns); allCheckers.initializeManager(*checkerMgr); allCheckers.validateCheckerOptions(); Modified: cfe/trunk/lib/StaticAnalyzer/Frontend/CheckerRegistry.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Frontend/CheckerRegistry.cpp?rev=352284&r1=352283&r2=352284&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Frontend/CheckerRegistry.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Frontend/CheckerRegistry.cpp Sat Jan 26 09:27:40 2019 @@ -91,10 +91,11 @@ CheckerRegistry::getMutableCheckersForCm return { it, it + size }; } -CheckerRegistry::CheckerRegistry(ArrayRef plugins, - DiagnosticsEngine &diags, - AnalyzerOptions &AnOpts, - const LangOptions &LangOpts) +CheckerRegistry::CheckerRegistry( + ArrayRef plugins, DiagnosticsEngine &diags, + AnalyzerOptions &AnOpts, const LangOptions &LangOpts, + ArrayRef> + checkerRegistrationFns) : Diags(diags), AnOpts(AnOpts), LangOpts(LangOpts) { // Register builtin checkers. @@ -137,6 +138,13 @@ CheckerRegistry::CheckerRegistry(ArrayRe registerPluginCheckers(*this); } + // Register statically linked checkers, that aren't generated from the tblgen + // file, but rather passed their registry function as a parameter in + // checkerRegistrationFns. + + for (const auto &Fn : checkerRegistrationFns) +Fn(*this); + // Sort checkers for efficient collection. // FIXME: Alphabetical sort puts 'experimental' in the middle. // Would it be better to name it '~experimental' or something else ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] r352290 - Fix a lit test failure after D54438
Author: szelethus Date: Sat Jan 26 13:22:58 2019 New Revision: 352290 URL: http://llvm.org/viewvc/llvm-project?rev=352290&view=rev Log: Fix a lit test failure after D54438 Modified: clang-tools-extra/trunk/test/clang-tidy/static-analyzer-config.cpp Modified: clang-tools-extra/trunk/test/clang-tidy/static-analyzer-config.cpp URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clang-tidy/static-analyzer-config.cpp?rev=352290&r1=352289&r2=352290&view=diff == --- clang-tools-extra/trunk/test/clang-tidy/static-analyzer-config.cpp (original) +++ clang-tools-extra/trunk/test/clang-tidy/static-analyzer-config.cpp Sat Jan 26 13:22:58 2019 @@ -1,5 +1,5 @@ // REQUIRES: static-analyzer -// RUN: clang-tidy %s -checks='-*,clang-analyzer-unix.Malloc' -config='{CheckOptions: [{ key: "clang-analyzer-unix.Malloc:Optimistic", value: true}]}' -- | FileCheck %s +// RUN: clang-tidy %s -checks='-*,clang-analyzer-unix.Malloc' -config='{CheckOptions: [{ key: "clang-analyzer-unix.DynamicMemoryModeling:Optimistic", value: true}]}' -- | FileCheck %s typedef __typeof(sizeof(int)) size_t; void *malloc(size_t); void free(void *); ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r352292 - [analyzer] Add CheckerManager::getChecker, make sure that a registry function registers no more than 1 checker
Author: szelethus Date: Sat Jan 26 13:41:50 2019 New Revision: 352292 URL: http://llvm.org/viewvc/llvm-project?rev=352292&view=rev Log: [analyzer] Add CheckerManager::getChecker, make sure that a registry function registers no more than 1 checker This patch effectively fixes the almost decade old checker naming issue. The solution is to assert when CheckerManager::getChecker is called on an unregistered checker, and assert when CheckerManager::registerChecker is called on a checker that is already registered. Differential Revision: https://reviews.llvm.org/D55429 Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/CheckerManager.h cfe/trunk/lib/StaticAnalyzer/Checkers/CStringChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/DirectIvarAssignment.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/IvarInvalidationChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/NSErrorChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/ValistChecker.cpp cfe/trunk/test/Analysis/analyzer-checker-config.c cfe/trunk/test/Analysis/free.c cfe/trunk/test/Analysis/outofbound.c cfe/trunk/test/Analysis/undef-buffers.c Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/CheckerManager.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/CheckerManager.h?rev=352292&r1=352291&r2=352292&view=diff == --- cfe/trunk/include/clang/StaticAnalyzer/Core/CheckerManager.h (original) +++ cfe/trunk/include/clang/StaticAnalyzer/Core/CheckerManager.h Sat Jan 26 13:41:50 2019 @@ -141,7 +141,7 @@ public: using CheckerDtor = CheckerFn; //===--===// -// registerChecker +// Checker registration. //===--===// /// Used to register checkers. @@ -153,8 +153,7 @@ public: CHECKER *registerChecker(AT &&... Args) { CheckerTag tag = getTag(); CheckerRef &ref = CheckerTags[tag]; -if (ref) - return static_cast(ref); // already registered. +assert(!ref && "Checker already registered, use getChecker!"); CHECKER *checker = new CHECKER(std::forward(Args)...); checker->Name = CurrentCheckName; @@ -164,8 +163,17 @@ public: return checker; } + template + CHECKER *getChecker() { +CheckerTag tag = getTag(); +assert(CheckerTags.count(tag) != 0 && + "Requested checker is not registered! Maybe you should add it as a " + "dependency in Checkers.td?"); +return static_cast(CheckerTags[tag]); + } + //===--===// -// Functions for running checkers for AST traversing.. +// Functions for running checkers for AST traversing. //===--===// /// Run checkers handling Decls. Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/CStringChecker.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/CStringChecker.cpp?rev=352292&r1=352291&r2=352292&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Checkers/CStringChecker.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/CStringChecker.cpp Sat Jan 26 13:41:50 2019 @@ -2485,7 +2485,7 @@ bool ento::shouldRegisterCStringModeling #define REGISTER_CHECKER(name) \ void ento::register##name(CheckerManager &mgr) { \ -CStringChecker *checker = mgr.registerChecker(); \ +CStringChecker *checker = mgr.getChecker(); \ checker->Filter.Check##name = true; \ checker->Filter.CheckName##name = mgr.getCurrentCheckName(); \ } \ Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp?rev=352292&r1=352291&r2=352292&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/CallAnd
r352693 - [analyzer] Make NullReturnedFromNonnullChecker depend on NullabilityBase
Author: szelethus Date: Wed Jan 30 15:48:37 2019 New Revision: 352693 URL: http://llvm.org/viewvc/llvm-project?rev=352693&view=rev Log: [analyzer] Make NullReturnedFromNonnullChecker depend on NullabilityBase Accidentally left this dependency out after D54438. Added: cfe/trunk/test/Analysis/checker-dependencies.c Modified: cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td Modified: cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td?rev=352693&r1=352692&r2=352693&view=diff == --- cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td (original) +++ cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td Wed Jan 30 15:48:37 2019 @@ -230,6 +230,7 @@ def NullPassedToNonnullChecker : Checker def NullReturnedFromNonnullChecker : Checker<"NullReturnedFromNonnull">, HelpText<"Warns when a null pointer is returned from a function that has " "_Nonnull return type.">, + Dependencies<[NullabilityBase]>, Documentation; def NullableDereferencedChecker : Checker<"NullableDereferenced">, Added: cfe/trunk/test/Analysis/checker-dependencies.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/checker-dependencies.c?rev=352693&view=auto == --- cfe/trunk/test/Analysis/checker-dependencies.c (added) +++ cfe/trunk/test/Analysis/checker-dependencies.c Wed Jan 30 15:48:37 2019 @@ -0,0 +1,3 @@ +// RUN: %clang_analyze_cc1 %s \ +// RUN: -analyzer-checker=core \ +// RUN: -analyzer-checker=nullability.NullReturnedFromNonnull ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r345724 - [analyzer][PlistMacroExpansion] Part 1.: New expand-macros flag
Author: szelethus Date: Wed Oct 31 07:54:27 2018 New Revision: 345724 URL: http://llvm.org/viewvc/llvm-project?rev=345724&view=rev Log: [analyzer][PlistMacroExpansion] Part 1.: New expand-macros flag This is the first part of the implementation of the inclusion of macro expansions into the plist output. It adds a new flag that adds a new "macro_expansions" entry to each report that has PathDiagnosticPieces that were expanded from a macro. While there's an entry for each macro expansion, both the name of the macro and what it expands to is missing, and will be implemented in followup patches. Differential Revision: https://reviews.llvm.org/D52742 Added: cfe/trunk/test/Analysis/Inputs/expected-plists/plist-macros-with-expansion.cpp.plist cfe/trunk/test/Analysis/plist-macros-with-expansion.cpp Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h cfe/trunk/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp cfe/trunk/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h?rev=345724&r1=345723&r2=345724&view=diff == --- cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h (original) +++ cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h Wed Oct 31 07:54:27 2018 @@ -307,6 +307,9 @@ private: /// \sa shouldDisplayNotesAsEvents Optional DisplayNotesAsEvents; + /// \sa shouldDisplayMacroExpansions + Optional DisplayMacroExpansions; + /// \sa shouldAggressivelySimplifyBinaryOperation Optional AggressiveBinaryOperationSimplification; @@ -693,6 +696,13 @@ public: /// to false when unset. bool shouldDisplayNotesAsEvents(); + /// Returns true if macros related to the bugpath should be expanded and + /// included in the plist output. + /// + /// This is controlled by the 'expand-macros' option, which defaults to false + /// when unset. + bool shouldDisplayMacroExpansions(); + /// Returns true if SValBuilder should rearrange comparisons and additive /// operations of symbolic expressions which consist of a sum of a symbol and /// a concrete integer into the format where symbols are on the left-hand Modified: cfe/trunk/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp?rev=345724&r1=345723&r2=345724&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp Wed Oct 31 07:54:27 2018 @@ -464,6 +464,13 @@ bool AnalyzerOptions::shouldDisplayNotes return DisplayNotesAsEvents.getValue(); } +bool AnalyzerOptions::shouldDisplayMacroExpansions() { + if (!DisplayMacroExpansions.hasValue()) +DisplayMacroExpansions = +getBooleanOption("expand-macros", /*Default=*/false); + return DisplayMacroExpansions.getValue(); +} + bool AnalyzerOptions::shouldAggressivelySimplifyBinaryOperation() { if (!AggressiveBinaryOperationSimplification.hasValue()) AggressiveBinaryOperationSimplification = Modified: cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp?rev=345724&r1=345723&r2=345724&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp Wed Oct 31 07:54:27 2018 @@ -546,7 +546,8 @@ static void updateStackPiecesWithMessage } } -static void CompactPathDiagnostic(PathPieces &path, const SourceManager& SM); +static void CompactMacroExpandedPieces(PathPieces &path, + const SourceManager& SM); std::shared_ptr generateDiagForSwitchOP( @@ -1972,8 +1973,6 @@ static std::unique_ptr g PathDiagnosticLocation::createBegin(D, SM)); } - if (!AddPathEdges && GenerateDiagnostics) -CompactPathDiagnostic(PD->getMutablePieces(), SM); // Finally, prune the diagnostic path of uninteresting stuff. if (!PD->path.empty()) { @@ -2007,6 +2006,10 @@ static std::unique_ptr g removeRedundantMsgs(PD->getMutablePieces()); removeEdgesToDefaultInitializers(PD->getMutablePieces()); } + + if (GenerateDiagnostics && Opts.shouldDisplayMacroExpansions()) +CompactMacroExpandedPieces(PD->getMutablePieces(), SM); + return PD; } @@ -2436,9 +2439,10 @@ bool TrimmedGraph::popNextReportGraph(Re return true; } -/// CompactPathDiagnostic - This function postprocesses a PathDiagnostic object -/// and collapses PathDiagosticPieces that are expanded by macros. -static void CompactPa
r345741 - [Lex] Make MacroDirective::findDirectiveAtLoc take const SourceManager
Author: szelethus Date: Wed Oct 31 10:19:20 2018 New Revision: 345741 URL: http://llvm.org/viewvc/llvm-project?rev=345741&view=rev Log: [Lex] Make MacroDirective::findDirectiveAtLoc take const SourceManager I'm currently working on including macro expansions in the Static Analyzer's plist output, where I can only access a const SourceManager. Differential Revision: https://reviews.llvm.org/D53940 Modified: cfe/trunk/include/clang/Lex/MacroInfo.h cfe/trunk/lib/Lex/MacroInfo.cpp Modified: cfe/trunk/include/clang/Lex/MacroInfo.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Lex/MacroInfo.h?rev=345741&r1=345740&r2=345741&view=diff == --- cfe/trunk/include/clang/Lex/MacroInfo.h (original) +++ cfe/trunk/include/clang/Lex/MacroInfo.h Wed Oct 31 10:19:20 2018 @@ -395,7 +395,8 @@ public: /// Find macro definition active in the specified source location. If /// this macro was not defined there, return NULL. - const DefInfo findDirectiveAtLoc(SourceLocation L, SourceManager &SM) const; + const DefInfo findDirectiveAtLoc(SourceLocation L, + const SourceManager &SM) const; void dump() const; Modified: cfe/trunk/lib/Lex/MacroInfo.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/MacroInfo.cpp?rev=345741&r1=345740&r2=345741&view=diff == --- cfe/trunk/lib/Lex/MacroInfo.cpp (original) +++ cfe/trunk/lib/Lex/MacroInfo.cpp Wed Oct 31 10:19:20 2018 @@ -200,7 +200,8 @@ MacroDirective::DefInfo MacroDirective:: } const MacroDirective::DefInfo -MacroDirective::findDirectiveAtLoc(SourceLocation L, SourceManager &SM) const { +MacroDirective::findDirectiveAtLoc(SourceLocation L, + const SourceManager &SM) const { assert(L.isValid() && "SourceLocation is invalid."); for (DefInfo Def = getDefinition(); Def; Def = Def.getPreviousDefinition()) { if (Def.getLocation().isInvalid() || // For macros defined on the command line. ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r345985 - [analyzer][NFC] Fix some incorrect uses of -analyzer-config options
Author: szelethus Date: Fri Nov 2 08:48:10 2018 New Revision: 345985 URL: http://llvm.org/viewvc/llvm-project?rev=345985&view=rev Log: [analyzer][NFC] Fix some incorrect uses of -analyzer-config options I'm in the process of refactoring AnalyzerOptions. The main motivation behind here is to emit warnings if an invalid -analyzer-config option is given from the command line, and be able to list them all. In this patch, I found some flags that should've been used as checker options, or have absolutely no mention of in AnalyzerOptions, or are nonexistent. - NonLocalizedStringChecker now uses its "AggressiveReport" flag as a checker option - lib/StaticAnalyzer/Frontend/ModelInjector.cpp now accesses the "model-path" option through a getter in AnalyzerOptions - -analyzer-config path-diagnostics-alternate=false is not a thing, I removed it, - lib/StaticAnalyzer/Checkers/AllocationDiagnostics.cpp and lib/StaticAnalyzer/Checkers/AllocationDiagnostics.h are weird, they actually only contain an option getter. I deleted them, and fixed RetainCountChecker to get it's "leak-diagnostics-reference-allocation" option as a checker option, - "region-store-small-struct-limit" has a proper getter now. Differential Revision: https://reviews.llvm.org/D53276 Removed: cfe/trunk/lib/StaticAnalyzer/Checkers/AllocationDiagnostics.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/AllocationDiagnostics.h Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h cfe/trunk/lib/StaticAnalyzer/Checkers/CMakeLists.txt cfe/trunk/lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.h cfe/trunk/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp cfe/trunk/lib/StaticAnalyzer/Frontend/ModelInjector.cpp cfe/trunk/test/Analysis/analyzer-config.c cfe/trunk/test/Analysis/analyzer-config.cpp cfe/trunk/test/Analysis/cstring-plist.c cfe/trunk/test/Analysis/localization-aggressive.m Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h?rev=345985&r1=345984&r2=345985&view=diff == --- cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h (original) +++ cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h Fri Nov 2 08:48:10 2018 @@ -328,6 +328,11 @@ private: /// \sa shouldElideConstructors Optional ElideConstructors; + /// \sa getModelPath + Optional ModelPath; + + /// \sa getRegionStoreSmallStructLimit + Optional RegionStoreSmallStructLimit; /// A helper function that retrieves option for a given full-qualified /// checker name. @@ -745,6 +750,21 @@ public: /// Starting with C++17 some elisions become mandatory, and in these cases /// the option will be ignored. bool shouldElideConstructors(); + + /// The largest number of fields a struct can have and still be + /// considered "small". + /// + /// This is currently used to decide whether or not it is worth "forcing" a + /// LazyCompoundVal on bind. + /// + /// This is controlled by 'region-store-small-struct-limit' option. + /// To disable all small-struct-dependent behavior, set the option to "0". + unsigned getRegionStoreSmallStructLimit(); + + /// The analyzer can inline an alternative implementation written in C at the + /// call site if the called function's body is not available. This is a path + /// where to look for those alternative implementations (called models) + StringRef getModelPath(); }; using AnalyzerOptionsRef = IntrusiveRefCntPtr; Removed: cfe/trunk/lib/StaticAnalyzer/Checkers/AllocationDiagnostics.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/AllocationDiagnostics.cpp?rev=345984&view=auto == --- cfe/trunk/lib/StaticAnalyzer/Checkers/AllocationDiagnostics.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/AllocationDiagnostics.cpp (removed) @@ -1,24 +0,0 @@ -//=- AllocationDiagnostics.cpp - Config options for allocation diags *- C++ -*-// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===--===// -// -// Declares the configuration functions for leaks/allocation diagnostics. -// -//===-- - -#include "AllocationDiagnostics.h" - -namespace clang { -namespace ento { - -bool shouldIncludeAllocationSiteInLeakDiagnostics(AnalyzerOptions &AOpts) { - return AOpts.getBooleanOption("leak-diagnostics-refere
r345986 - [analyzer][NFC] Collect all -analyzer-config options in a .def file
Author: szelethus Date: Fri Nov 2 08:50:44 2018 New Revision: 345986 URL: http://llvm.org/viewvc/llvm-project?rev=345986&view=rev Log: [analyzer][NFC] Collect all -analyzer-config options in a .def file I'm in the process of refactoring AnalyzerOptions. The main motivation behind here is to emit warnings if an invalid -analyzer-config option is given from the command line, and be able to list them all. In this patch, I'm moving all analyzer options to a def file, and move 2 enums to global namespace. Differential Revision: https://reviews.llvm.org/D53277 Added: cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h cfe/trunk/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp cfe/trunk/lib/StaticAnalyzer/Core/CoreEngine.cpp Added: cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def?rev=345986&view=auto == --- cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def (added) +++ cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def Fri Nov 2 08:50:44 2018 @@ -0,0 +1,467 @@ +//===-- AnalyzerOptions.def - Metadata about Static Analyses *- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===--===// +// +// This file defines the analyzer options avaible with -analyzer-config. +// +// This file is in part intended for method generation. If it's not included +// for that purpose, the following function-like macros should be predefined, +// through which all registered options are accessible: +// +//* ANALYZER_OPTION: Register a new option. +//* ANALYZER_OPTION_DEPENDS_ON_USER_MODE: Register a new option, default +// value depends on the "user-mode" option. +// +// Options where a simple getter method is sufficient are registered with the +// following macros: +// +//* ANALYZER_OPTION_GEN_FN: Register a new option, and generate a getter +// method for it in AnalyzerOptions. +// +//* ANALYZER_OPTION_GEN_FN_DEPENDS_ON_USER_MODE: Same as above, but +// generates a getter function that depends on the "user-mode" option. +// +// You can only include this file when both or none of the above two macros +// are defined! +// When they are defined, entries that do not generate functions won't appear, +// and when they aren't, all entries are converted to ANALYZER_OPTION or to +// ANALYZER_OPTION_DEPENDS_ON_USER_MODE. +// +//===--===// + +#ifndef LLVM_ADT_STRINGREF_H +#error This .def file is expected to be included in translation units where \ +"llvm/ADT/StringRef.h" is already included! +#endif + +#ifdef ANALYZER_OPTION +#ifndef ANALYZER_OPTION_DEPENDS_ON_USER_MODE +#error If you didn't include this file with the intent of generating methods, \ +define both 'ANALYZER_OPTION' and 'ANALYZER_OPTION_DEPENDS_ON_USER_MODE' macros! +#endif +#endif + +#ifndef ANALYZER_OPTION_DEPENDS_ON_USER_MODE +#ifdef ANALYZER_OPTION +#error If you didn't include this file with the intent of generating methods, \ +define both 'ANALYZER_OPTION' and 'ANALYZER_OPTION_DEPENDS_ON_USER_MODE' macros! +#endif +#endif + +#ifdef ANALYZER_OPTION_GEN_FN +#ifndef ANALYZER_OPTION_GEN_FN_DEPENDS_ON_USER_MODE +#error If you include this file with the intent of generating functions, \ +define both 'ANALYZER_OPTION_GEN_FN' and \ +'ANALYZER_OPTION_GEN_FN_DEPENDS_ON_USER_MODE' macros! +#endif +#endif + +#ifdef ANALYZER_OPTION_GEN_FN_DEPENDS_ON_USER_MODE +#ifndef ANALYZER_OPTION_GEN_FN +#error If you include this file with the intent of generating functions, \ +define both 'ANALYZER_OPTION_GEN_FN' and \ +'ANALYZER_OPTION_GEN_FN_DEPENDS_ON_USER_MODE' macros! +#endif +#endif + +#ifndef ANALYZER_OPTION +/// Create a new analyzer option, but dont generate a method for it in +/// AnalyzerOptions. +/// +/// TYPE - The type of the option object that will be stored in +/// AnalyzerOptions. This file is expected to be icluded in translation +/// units where AnalyzerOptions.h is included, so types from that +/// header should be used. +/// NAME - The name of the option object. +/// CMDFLAG - The command line flag for the option. +/// (-analyzer-config CMDFLAG=VALUE) +/// DESC - Description of the flag. +/// DEFAULT_VAL - The default value for CMDFLAG. +#define ANALYZER_OPTION(TYPE, NAME, CMDFLAG, DESC, DEFAULT_VAL) +#endif + +#ifndef ANALYZER_OPTION_DEPENDS_ON_USER_MODE +/// Create a new analyzer option, but dont generate a method for it in +/// AnalyzerOptions. It's value depends on the opti
r345989 - [analyzer] New flag to print all -analyzer-config options
Author: szelethus Date: Fri Nov 2 08:59:37 2018 New Revision: 345989 URL: http://llvm.org/viewvc/llvm-project?rev=345989&view=rev Log: [analyzer] New flag to print all -analyzer-config options A new -cc1 flag is avaible for the said purpose: -analyzer-config-help Differential Revision: https://reviews.llvm.org/D53296 Added: cfe/trunk/test/Analysis/analyzer-list-configs.c Modified: cfe/trunk/include/clang/Driver/CC1Options.td cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h cfe/trunk/include/clang/StaticAnalyzer/Frontend/FrontendActions.h cfe/trunk/lib/Frontend/CompilerInvocation.cpp cfe/trunk/lib/FrontendTool/ExecuteCompilerInvocation.cpp cfe/trunk/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp Modified: cfe/trunk/include/clang/Driver/CC1Options.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/CC1Options.td?rev=345989&r1=345988&r2=345989&view=diff == --- cfe/trunk/include/clang/Driver/CC1Options.td (original) +++ cfe/trunk/include/clang/Driver/CC1Options.td Fri Nov 2 08:59:37 2018 @@ -129,6 +129,9 @@ def analyzer_disable_all_checks : Flag<[ def analyzer_checker_help : Flag<["-"], "analyzer-checker-help">, HelpText<"Display the list of analyzer checkers that are available">; +def analyzer_config_help : Flag<["-"], "analyzer-config-help">, + HelpText<"Display the list of -analyzer-config options">; + def analyzer_list_enabled_checkers : Flag<["-"], "analyzer-list-enabled-checkers">, HelpText<"Display the list of enabled analyzer checkers">; Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h?rev=345989&r1=345988&r2=345989&view=diff == --- cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h (original) +++ cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h Fri Nov 2 08:59:37 2018 @@ -175,6 +175,7 @@ public: unsigned ShowCheckerHelp : 1; unsigned ShowEnabledCheckerList : 1; + unsigned ShowConfigOptionsList : 1; unsigned AnalyzeAll : 1; unsigned AnalyzerDisplayProgress : 1; unsigned AnalyzeNestedBlocks : 1; Modified: cfe/trunk/include/clang/StaticAnalyzer/Frontend/FrontendActions.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Frontend/FrontendActions.h?rev=345989&r1=345988&r2=345989&view=diff == --- cfe/trunk/include/clang/StaticAnalyzer/Frontend/FrontendActions.h (original) +++ cfe/trunk/include/clang/StaticAnalyzer/Frontend/FrontendActions.h Fri Nov 2 08:59:37 2018 @@ -55,6 +55,7 @@ private: void printCheckerHelp(raw_ostream &OS, ArrayRef plugins); void printEnabledCheckerList(raw_ostream &OS, ArrayRef plugins, const AnalyzerOptions &opts); +void printAnalyzerConfigList(raw_ostream &OS); } // end GR namespace Modified: cfe/trunk/lib/Frontend/CompilerInvocation.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/CompilerInvocation.cpp?rev=345989&r1=345988&r2=345989&view=diff == --- cfe/trunk/lib/Frontend/CompilerInvocation.cpp (original) +++ cfe/trunk/lib/Frontend/CompilerInvocation.cpp Fri Nov 2 08:59:37 2018 @@ -279,6 +279,7 @@ static bool ParseAnalyzerArgs(AnalyzerOp } Opts.ShowCheckerHelp = Args.hasArg(OPT_analyzer_checker_help); + Opts.ShowConfigOptionsList = Args.hasArg(OPT_analyzer_config_help); Opts.ShowEnabledCheckerList = Args.hasArg(OPT_analyzer_list_enabled_checkers); Opts.DisableAllChecks = Args.hasArg(OPT_analyzer_disable_all_checks); Modified: cfe/trunk/lib/FrontendTool/ExecuteCompilerInvocation.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/FrontendTool/ExecuteCompilerInvocation.cpp?rev=345989&r1=345988&r2=345989&view=diff == --- cfe/trunk/lib/FrontendTool/ExecuteCompilerInvocation.cpp (original) +++ cfe/trunk/lib/FrontendTool/ExecuteCompilerInvocation.cpp Fri Nov 2 08:59:37 2018 @@ -241,11 +241,19 @@ bool ExecuteCompilerInvocation(CompilerI ento::printCheckerHelp(llvm::outs(), Clang->getFrontendOpts().Plugins); return true; } + + // Honor -analyzer-list-enabled-checkers. if (Clang->getAnalyzerOpts()->ShowEnabledCheckerList) { ento::printEnabledCheckerList(llvm::outs(), Clang->getFrontendOpts().Plugins, *Clang->getAnalyzerOpts()); } + + // Honor -analyzer-config-help. + if (Clang->getAnalyzerOpts()->ShowConfigOptionsList) { +ento::printAnalyzerConfigList(llvm::outs()); +return true; + } #endif // If there were errors in processing
r345990 - [analyzer] Put llvm.Conventions back in alpha
Author: szelethus Date: Fri Nov 2 09:02:10 2018 New Revision: 345990 URL: http://llvm.org/viewvc/llvm-project?rev=345990&view=rev Log: [analyzer] Put llvm.Conventions back in alpha Interestingly, this many year old (when I last looked I remember 2010ish) checker was committed without any tests, so I thought I'd implement them, but I was shocked to see how I barely managed to get it working. The code is severely outdated, I'm not even sure it has ever been used, so I'd propose to move it back into alpha, and possibly even remove it. Differential Revision: https://reviews.llvm.org/D53856 Added: cfe/trunk/test/Analysis/llvm-conventions.cpp Modified: cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td cfe/trunk/lib/StaticAnalyzer/Checkers/LLVMConventionsChecker.cpp cfe/trunk/test/Analysis/Inputs/system-header-simulator-cxx.h cfe/trunk/test/Analysis/diagnostics/explicit-suppression.cpp cfe/trunk/test/Analysis/inner-pointer.cpp cfe/trunk/test/Analysis/temporaries.cpp cfe/trunk/www/analyzer/alpha_checks.html Modified: cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td?rev=345990&r1=345989&r2=345990&view=diff == --- cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td (original) +++ cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td Fri Nov 2 09:02:10 2018 @@ -83,6 +83,7 @@ def LocalizabilityOptIn : Package<"local def MPI : Package<"mpi">, InPackage; def LLVM : Package<"llvm">; +def LLVMAlpha : Package<"llvm">, InPackage, Hidden; // The APIModeling package is for checkers that model APIs and don't perform // any diagnostics. These checkers are always turned on; this package is @@ -730,7 +731,7 @@ let ParentPackage = MPI in { //===--===// def LLVMConventionsChecker : Checker<"Conventions">, - InPackage, + InPackage, HelpText<"Check code for LLVM codebase conventions">, DescFile<"LLVMConventionsChecker.cpp">; Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/LLVMConventionsChecker.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/LLVMConventionsChecker.cpp?rev=345990&r1=345989&r2=345990&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Checkers/LLVMConventionsChecker.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/LLVMConventionsChecker.cpp Fri Nov 2 09:02:10 2018 @@ -32,8 +32,7 @@ static bool IsLLVMStringRef(QualType T) if (!RT) return false; - return StringRef(QualType(RT, 0).getAsString()) == - "class StringRef"; + return StringRef(QualType(RT, 0).getAsString()) == "class StringRef"; } /// Check whether the declaration is semantically inside the top-level Modified: cfe/trunk/test/Analysis/Inputs/system-header-simulator-cxx.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/Inputs/system-header-simulator-cxx.h?rev=345990&r1=345989&r2=345990&view=diff == --- cfe/trunk/test/Analysis/Inputs/system-header-simulator-cxx.h (original) +++ cfe/trunk/test/Analysis/Inputs/system-header-simulator-cxx.h Fri Nov 2 09:02:10 2018 @@ -12,6 +12,13 @@ typedef __typeof__((char*)0-(char*)0) pt void *memmove(void *s1, const void *s2, size_t n); namespace std { + typedef size_t size_type; +#if __cplusplus >= 201103L + using nullptr_t = decltype(nullptr); +#endif +} + +namespace std { struct input_iterator_tag { }; struct output_iterator_tag { }; struct forward_iterator_tag : public input_iterator_tag { }; @@ -517,6 +524,42 @@ namespace std { const T& front() const { return *begin(); } }; + template + class basic_string { + public: +basic_string(); +basic_string(const CharT *s); + +~basic_string(); +void clear(); + +basic_string &operator=(const basic_string &str); +basic_string &operator+=(const basic_string &str); + +const CharT *c_str() const; +const CharT *data() const; +CharT *data(); + +basic_string &append(size_type count, CharT ch); +basic_string &assign(size_type count, CharT ch); +basic_string &erase(size_type index, size_type count); +basic_string &insert(size_type index, size_type count, CharT ch); +basic_string &replace(size_type pos, size_type count, const basic_string &str); +void pop_back(); +void push_back(CharT ch); +void reserve(size_type new_cap); +void resize(size_type count); +void shrink_to_fit(); +void swap(basic_string &other); + }; + + typedef basic_string string; + typedef basic_string wstring; +#if __cplusplus >= 201103L + typedef basic_string u16string; + typedef basic_string u32string; +#endif + class exception { public:
r345993 - Didn't -> didnt, because #errors complains about untermianted '
Author: szelethus Date: Fri Nov 2 09:32:15 2018 New Revision: 345993 URL: http://llvm.org/viewvc/llvm-project?rev=345993&view=rev Log: Didn't -> didnt, because #errors complains about untermianted ' Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def?rev=345993&r1=345992&r2=345993&view=diff == --- cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def (original) +++ cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def Fri Nov 2 09:32:15 2018 @@ -41,14 +41,14 @@ #ifdef ANALYZER_OPTION #ifndef ANALYZER_OPTION_DEPENDS_ON_USER_MODE -#error If you didn't include this file with the intent of generating methods, \ +#error If you didnt include this file with the intent of generating methods, \ define both 'ANALYZER_OPTION' and 'ANALYZER_OPTION_DEPENDS_ON_USER_MODE' macros! #endif #endif #ifndef ANALYZER_OPTION_DEPENDS_ON_USER_MODE #ifdef ANALYZER_OPTION -#error If you didn't include this file with the intent of generating methods, \ +#error If you didnt include this file with the intent of generating methods, \ define both 'ANALYZER_OPTION' and 'ANALYZER_OPTION_DEPENDS_ON_USER_MODE' macros! #endif #endif ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r345997 - Remove the duplicated definition of size_t
Author: szelethus Date: Fri Nov 2 10:00:07 2018 New Revision: 345997 URL: http://llvm.org/viewvc/llvm-project?rev=345997&view=rev Log: Remove the duplicated definition of size_t So hopefully windows won't complain. Modified: cfe/trunk/test/Analysis/llvm-conventions.cpp Modified: cfe/trunk/test/Analysis/llvm-conventions.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/llvm-conventions.cpp?rev=345997&r1=345996&r2=345997&view=diff == --- cfe/trunk/test/Analysis/llvm-conventions.cpp (original) +++ cfe/trunk/test/Analysis/llvm-conventions.cpp Fri Nov 2 10:00:07 2018 @@ -7,7 +7,6 @@ // Forward declarations for StringRef tests. //===--===// -using size_t = unsigned long; using size_type = size_t; namespace std { ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r346033 - Attempt to fix 'logical operation on address of string constant'
Author: szelethus Date: Fri Nov 2 12:48:56 2018 New Revision: 346033 URL: http://llvm.org/viewvc/llvm-project?rev=346033&view=rev Log: Attempt to fix 'logical operation on address of string constant' Caused a lot of warnings for Windows: http://lab.llvm.org:8011/builders/llvm-clang-lld-x86_64-scei-ps4-windows10pro-fast/builds/21178/steps/build/logs/warnings%20%2867%29 Modified: cfe/trunk/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp Modified: cfe/trunk/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp?rev=346033&r1=346032&r2=346033&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp Fri Nov 2 12:48:56 2018 @@ -178,7 +178,8 @@ void ento::printAnalyzerConfigList(raw_o { \ CMDFLAG, \ llvm::Twine(llvm::Twine() + "(" + \ - (#TYPE == "StringRef" ? "string" : #TYPE ) + ") " DESC \ + (StringRef(#TYPE) == "StringRef" ? "string" : #TYPE ) + \ + ") " DESC \ " (default: " #DEFAULT_VAL ")").str() \ }, @@ -187,7 +188,8 @@ void ento::printAnalyzerConfigList(raw_o { \ CMDFLAG, \ llvm::Twine(llvm::Twine() + "(" + \ - (#TYPE == "StringRef" ? "string" : #TYPE ) + ") " DESC \ + (StringRef(#TYPE) == "StringRef" ? "string" : #TYPE ) + \ + ") " DESC \ " (default: " #SHALLOW_VAL " in shallow mode, " #DEEP_VAL \ " in deep mode)").str() \ }, ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r346095 - [analyzer][PlistMacroExpansion] Part 2.: Retrieving the macro name and primitive expansion
Author: szelethus Date: Sun Nov 4 05:59:44 2018 New Revision: 346095 URL: http://llvm.org/viewvc/llvm-project?rev=346095&view=rev Log: [analyzer][PlistMacroExpansion] Part 2.: Retrieving the macro name and primitive expansion This patch adds a couple new functions to acquire the macro's name, and also expands it, although it doesn't expand the arguments, as seen from the test files Differential Revision: https://reviews.llvm.org/D52794 Modified: cfe/trunk/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp cfe/trunk/test/Analysis/Inputs/expected-plists/plist-macros-with-expansion.cpp.plist cfe/trunk/test/Analysis/plist-macros-with-expansion.cpp Modified: cfe/trunk/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp?rev=346095&r1=346094&r2=346095&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp Sun Nov 4 05:59:44 2018 @@ -16,6 +16,7 @@ #include "clang/Basic/SourceManager.h" #include "clang/Basic/Version.h" #include "clang/Lex/Preprocessor.h" +#include "clang/Lex/TokenConcatenation.h" #include "clang/Rewrite/Core/HTMLRewrite.h" #include "clang/StaticAnalyzer/Core/AnalyzerOptions.h" #include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h" @@ -400,12 +401,6 @@ void PlistPrinter::ReportNote(raw_ostrea // Static function definitions. //===--===// -static ExpansionInfo getExpandedMacro(SourceLocation MacroLoc, - const Preprocessor &PP) { - // TODO: Implement macro expansion. - return { "", "" }; -} - /// Print coverage information to output stream {@code o}. /// May modify the used list of files {@code Fids} by inserting new ones. static void printCoverage(const PathDiagnostic *D, @@ -721,3 +716,196 @@ void PlistDiagnostics::FlushDiagnosticsI // Finish. o << "\n"; } + +//===--===// +// Declarations of helper functions and data structures for expanding macros. +//===--===// + +namespace { + +struct MacroNameAndInfo { + std::string Name; + const MacroInfo *MI = nullptr; + + MacroNameAndInfo(std::string N, const MacroInfo *MI) +: Name(std::move(N)), MI(MI) {} +}; + +/// Helper class for printing tokens. +class TokenPrinter { + llvm::raw_ostream &OS; + const Preprocessor &PP; + + Token PrevTok, PrevPrevTok; + TokenConcatenation ConcatInfo; + +public: + TokenPrinter(llvm::raw_ostream &OS, const Preprocessor &PP) +: OS(OS), PP(PP), ConcatInfo(PP) { +PrevTok.setKind(tok::unknown); +PrevPrevTok.setKind(tok::unknown); + } + + void printToken(const Token &Tok); +}; + +} // end of anonymous namespace + +static std::string getMacroNameAndPrintExpansion(TokenPrinter &Printer, + SourceLocation MacroLoc, + const Preprocessor &PP); + +/// Retrieves the name of the macro and its MacroInfo. +static MacroNameAndInfo getMacroNameAndInfo(SourceLocation ExpanLoc, +const Preprocessor &PP); + +/// Retrieves the ')' token that matches '(' \p It points to. +static MacroInfo::tokens_iterator getMatchingRParen( +MacroInfo::tokens_iterator It, +MacroInfo::tokens_iterator End); + +/// Retrieves the macro info for \p II refers to at \p Loc. This is important +/// because macros can be redefined or undefined. +static const MacroInfo *getMacroInfoForLocation(const Preprocessor &PP, +const SourceManager &SM, +const IdentifierInfo *II, +SourceLocation Loc); + +//===--===// +// Definitions of helper functions and methods for expanding macros. +//===--===// + +static ExpansionInfo getExpandedMacro(SourceLocation MacroLoc, + const Preprocessor &PP) { + + llvm::SmallString<200> ExpansionBuf; + llvm::raw_svector_ostream OS(ExpansionBuf); + TokenPrinter Printer(OS, PP); + return { getMacroNameAndPrintExpansion(Printer, MacroLoc, PP), OS.str() }; +} + +static std::string getMacroNameAndPrintExpansion(TokenPrinter &Printer, + SourceLocation MacroLoc, + const Preprocessor &PP) { + + const SourceManager &SM = PP.getSourceManager(); + + MacroNameAndInfo Info = getMacroNameAndInfo(SM.getExpansionLoc(MacroLoc), PP); + const MacroInfo *MI =
r346096 - Revert '[analyzer][PlistMacroExpansion] Part 2.: Retrieving the macro name and primitive expansion'
Author: szelethus Date: Sun Nov 4 06:18:37 2018 New Revision: 346096 URL: http://llvm.org/viewvc/llvm-project?rev=346096&view=rev Log: Revert '[analyzer][PlistMacroExpansion] Part 2.: Retrieving the macro name and primitive expansion' Modified: cfe/trunk/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp cfe/trunk/test/Analysis/Inputs/expected-plists/plist-macros-with-expansion.cpp.plist cfe/trunk/test/Analysis/plist-macros-with-expansion.cpp Modified: cfe/trunk/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp?rev=346096&r1=346095&r2=346096&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp Sun Nov 4 06:18:37 2018 @@ -16,7 +16,6 @@ #include "clang/Basic/SourceManager.h" #include "clang/Basic/Version.h" #include "clang/Lex/Preprocessor.h" -#include "clang/Lex/TokenConcatenation.h" #include "clang/Rewrite/Core/HTMLRewrite.h" #include "clang/StaticAnalyzer/Core/AnalyzerOptions.h" #include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h" @@ -401,6 +400,12 @@ void PlistPrinter::ReportNote(raw_ostrea // Static function definitions. //===--===// +static ExpansionInfo getExpandedMacro(SourceLocation MacroLoc, + const Preprocessor &PP) { + // TODO: Implement macro expansion. + return { "", "" }; +} + /// Print coverage information to output stream {@code o}. /// May modify the used list of files {@code Fids} by inserting new ones. static void printCoverage(const PathDiagnostic *D, @@ -716,196 +721,3 @@ void PlistDiagnostics::FlushDiagnosticsI // Finish. o << "\n"; } - -//===--===// -// Declarations of helper functions and data structures for expanding macros. -//===--===// - -namespace { - -struct MacroNameAndInfo { - std::string Name; - const MacroInfo *MI = nullptr; - - MacroNameAndInfo(std::string N, const MacroInfo *MI) -: Name(std::move(N)), MI(MI) {} -}; - -/// Helper class for printing tokens. -class TokenPrinter { - llvm::raw_ostream &OS; - const Preprocessor &PP; - - Token PrevTok, PrevPrevTok; - TokenConcatenation ConcatInfo; - -public: - TokenPrinter(llvm::raw_ostream &OS, const Preprocessor &PP) -: OS(OS), PP(PP), ConcatInfo(PP) { -PrevTok.setKind(tok::unknown); -PrevPrevTok.setKind(tok::unknown); - } - - void printToken(const Token &Tok); -}; - -} // end of anonymous namespace - -static std::string getMacroNameAndPrintExpansion(TokenPrinter &Printer, - SourceLocation MacroLoc, - const Preprocessor &PP); - -/// Retrieves the name of the macro and its MacroInfo. -static MacroNameAndInfo getMacroNameAndInfo(SourceLocation ExpanLoc, -const Preprocessor &PP); - -/// Retrieves the ')' token that matches '(' \p It points to. -static MacroInfo::tokens_iterator getMatchingRParen( -MacroInfo::tokens_iterator It, -MacroInfo::tokens_iterator End); - -/// Retrieves the macro info for \p II refers to at \p Loc. This is important -/// because macros can be redefined or undefined. -static const MacroInfo *getMacroInfoForLocation(const Preprocessor &PP, -const SourceManager &SM, -const IdentifierInfo *II, -SourceLocation Loc); - -//===--===// -// Definitions of helper functions and methods for expanding macros. -//===--===// - -static ExpansionInfo getExpandedMacro(SourceLocation MacroLoc, - const Preprocessor &PP) { - - llvm::SmallString<200> ExpansionBuf; - llvm::raw_svector_ostream OS(ExpansionBuf); - TokenPrinter Printer(OS, PP); - return { getMacroNameAndPrintExpansion(Printer, MacroLoc, PP), OS.str() }; -} - -static std::string getMacroNameAndPrintExpansion(TokenPrinter &Printer, - SourceLocation MacroLoc, - const Preprocessor &PP) { - - const SourceManager &SM = PP.getSourceManager(); - - MacroNameAndInfo Info = getMacroNameAndInfo(SM.getExpansionLoc(MacroLoc), PP); - const MacroInfo *MI = Info.MI; - - // Iterate over the macro's tokens and stringify them. - for (auto It = MI->tokens_begin(), E = MI->tokens_end(); It != E; ++It) { -Token T = *It; - -// If this token is not an identif
r346111 - Reland '[analyzer][PlistMacroExpansion] Part 2.: Retrieving the macro name and primitive expansion'
Author: szelethus Date: Sun Nov 4 18:14:36 2018 New Revision: 346111 URL: http://llvm.org/viewvc/llvm-project?rev=346111&view=rev Log: Reland '[analyzer][PlistMacroExpansion] Part 2.: Retrieving the macro name and primitive expansion' Modified: cfe/trunk/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp cfe/trunk/test/Analysis/Inputs/expected-plists/plist-macros-with-expansion.cpp.plist cfe/trunk/test/Analysis/plist-macros-with-expansion.cpp Modified: cfe/trunk/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp?rev=346111&r1=346110&r2=346111&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp Sun Nov 4 18:14:36 2018 @@ -16,6 +16,7 @@ #include "clang/Basic/SourceManager.h" #include "clang/Basic/Version.h" #include "clang/Lex/Preprocessor.h" +#include "clang/Lex/TokenConcatenation.h" #include "clang/Rewrite/Core/HTMLRewrite.h" #include "clang/StaticAnalyzer/Core/AnalyzerOptions.h" #include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h" @@ -400,12 +401,6 @@ void PlistPrinter::ReportNote(raw_ostrea // Static function definitions. //===--===// -static ExpansionInfo getExpandedMacro(SourceLocation MacroLoc, - const Preprocessor &PP) { - // TODO: Implement macro expansion. - return { "", "" }; -} - /// Print coverage information to output stream {@code o}. /// May modify the used list of files {@code Fids} by inserting new ones. static void printCoverage(const PathDiagnostic *D, @@ -721,3 +716,196 @@ void PlistDiagnostics::FlushDiagnosticsI // Finish. o << "\n"; } + +//===--===// +// Declarations of helper functions and data structures for expanding macros. +//===--===// + +namespace { + +struct MacroNameAndInfo { + std::string Name; + const MacroInfo *MI = nullptr; + + MacroNameAndInfo(std::string N, const MacroInfo *MI) +: Name(std::move(N)), MI(MI) {} +}; + +/// Helper class for printing tokens. +class TokenPrinter { + llvm::raw_ostream &OS; + const Preprocessor &PP; + + Token PrevTok, PrevPrevTok; + TokenConcatenation ConcatInfo; + +public: + TokenPrinter(llvm::raw_ostream &OS, const Preprocessor &PP) +: OS(OS), PP(PP), ConcatInfo(PP) { +PrevTok.setKind(tok::unknown); +PrevPrevTok.setKind(tok::unknown); + } + + void printToken(const Token &Tok); +}; + +} // end of anonymous namespace + +static std::string getMacroNameAndPrintExpansion(TokenPrinter &Printer, + SourceLocation MacroLoc, + const Preprocessor &PP); + +/// Retrieves the name of the macro and its MacroInfo. +static MacroNameAndInfo getMacroNameAndInfo(SourceLocation ExpanLoc, +const Preprocessor &PP); + +/// Retrieves the ')' token that matches '(' \p It points to. +static MacroInfo::tokens_iterator getMatchingRParen( +MacroInfo::tokens_iterator It, +MacroInfo::tokens_iterator End); + +/// Retrieves the macro info for \p II refers to at \p Loc. This is important +/// because macros can be redefined or undefined. +static const MacroInfo *getMacroInfoForLocation(const Preprocessor &PP, +const SourceManager &SM, +const IdentifierInfo *II, +SourceLocation Loc); + +//===--===// +// Definitions of helper functions and methods for expanding macros. +//===--===// + +static ExpansionInfo getExpandedMacro(SourceLocation MacroLoc, + const Preprocessor &PP) { + + llvm::SmallString<200> ExpansionBuf; + llvm::raw_svector_ostream OS(ExpansionBuf); + TokenPrinter Printer(OS, PP); + return { getMacroNameAndPrintExpansion(Printer, MacroLoc, PP), OS.str() }; +} + +static std::string getMacroNameAndPrintExpansion(TokenPrinter &Printer, + SourceLocation MacroLoc, + const Preprocessor &PP) { + + const SourceManager &SM = PP.getSourceManager(); + + MacroNameAndInfo Info = getMacroNameAndInfo(SM.getExpansionLoc(MacroLoc), PP); + const MacroInfo *MI = Info.MI; + + // Iterate over the macro's tokens and stringify them. + for (auto It = MI->tokens_begin(), E = MI->tokens_end(); It != E; ++It) { +Token T = *It; + +// If this token is not an identif
r346112 - Ensure the correct order of evaluation in part 2. of PlistMacroExpansion
Author: szelethus Date: Sun Nov 4 18:37:29 2018 New Revision: 346112 URL: http://llvm.org/viewvc/llvm-project?rev=346112&view=rev Log: Ensure the correct order of evaluation in part 2. of PlistMacroExpansion Windows buildbots break with the previous commit '[analyzer][PlistMacroExpansion] Part 2.: Retrieving the macro name and primitive expansion'. This patch attempts to solve this issue. Modified: cfe/trunk/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp Modified: cfe/trunk/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp?rev=346112&r1=346111&r2=346112&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp Sun Nov 4 18:37:29 2018 @@ -781,7 +781,8 @@ static ExpansionInfo getExpandedMacro(So llvm::SmallString<200> ExpansionBuf; llvm::raw_svector_ostream OS(ExpansionBuf); TokenPrinter Printer(OS, PP); - return { getMacroNameAndPrintExpansion(Printer, MacroLoc, PP), OS.str() }; + std::string MacroName = getMacroNameAndPrintExpansion(Printer, MacroLoc, PP); + return { MacroName, OS.str() }; } static std::string getMacroNameAndPrintExpansion(TokenPrinter &Printer, ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r346113 - [analyzer] Restrict AnalyzerOptions' interface so that non-checker objects have to be registered
Author: szelethus Date: Sun Nov 4 19:50:37 2018 New Revision: 346113 URL: http://llvm.org/viewvc/llvm-project?rev=346113&view=rev Log: [analyzer] Restrict AnalyzerOptions' interface so that non-checker objects have to be registered One of the reasons why AnalyzerOptions is so chaotic is that options can be retrieved from the command line whenever and wherever. This allowed for some options to be forgotten for a looong time. Have you ever heard of "region-store-small-struct-limit"? In order to prevent this in the future, I'm proposing to restrict AnalyzerOptions' interface so that only checker options can be retrieved without special getters. I would like to make every option be accessible only through a getter, but checkers from plugins are a thing, so I'll have to figure something out for that. This also forces developers who'd like to add a new option to register it properly in the .def file. This is done by * making the third checker pointer parameter non-optional, and checked by an assert to be non-null. * I added new, but private non-checkers option initializers, meant only for internal use, * Renamed these methods accordingly (mind the consistent name for once with getBooleanOption!): - getOptionAsString -> getCheckerStringOption, - getOptionAsInteger -> getCheckerIntegerOption * The 3 functions meant for initializing data members (with the not very descriptive getBooleanOption, getOptionAsString and getOptionAsUInt names) were renamed to be overloads of the getAndInitOption function name. * All options were in some way retrieved via getCheckerOption. I removed it, and moved the logic to getStringOption and getCheckerStringOption. This did cause some code duplication, but that's the only way I could do it, now that checker and non-checker options are separated. Note that the non-checker version inserts the new option to the ConfigTable with the default value, but the checker version only attempts to find already existing entries. This is how it always worked, but this is clunky and I might end reworking that too, so we can eventually get a ConfigTable that contains the entire configuration of the analyzer. Differential Revision: https://reviews.llvm.org/D53483 Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h cfe/trunk/lib/StaticAnalyzer/Checkers/AnalysisOrderChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/CloneChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/MmapWriteExecChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/NumberObjectConversionChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/VirtualCallChecker.cpp cfe/trunk/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp cfe/trunk/unittests/StaticAnalyzer/AnalyzerOptionsTest.cpp Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h?rev=346113&r1=346112&r2=346113&view=diff == --- cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h (original) +++ cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h Sun Nov 4 19:50:37 2018 @@ -137,6 +137,28 @@ enum UserModeKind { UMK_Deep = 2 }; +/// Stores options for the analyzer from the command line. +/// +/// Some options are frontend flags (e.g.: -analyzer-output), but some are +/// analyzer configuration options, which are preceded by -analyzer-config +/// (e.g.: -analyzer-config notes-as-events=true). +/// +/// If you'd like to add a new frontend flag, add it to +/// include/clang/Driver/CC1Options.td, add a new field to store the value of +/// that flag in this class, and initialize it in +/// lib/Frontend/CompilerInvocation.cpp. +/// +/// If you'd like to add a new non-checker configuration, register it in +/// include/clang/StaticAnalyzer/Core/AnalyzerOptions.def, and refer to the +/// top of the file for documentation. +/// +/// If you'd like to add a new checker option, call getChecker*Option() +/// whenever. +/// +/// Some of the options are controlled by raw frontend flags for no good reason, +/// and should be eventually converted into -analyzer-config flags. New analyzer +/// options should not be implemented as frontend flags. Frontend flags still +/// make sense for things that do not affect the actual analysis. class AnalyzerOptions : public RefCountedBase { public: using ConfigTable = llvm::StringMap; @@ -209,32 +231,21 @@ private: #undef ANALYZER_OPTIO
r346680 - [analyzer] Drastically simplify the tblgen files used for checkers
Author: szelethus Date: Mon Nov 12 09:49:51 2018 New Revision: 346680 URL: http://llvm.org/viewvc/llvm-project?rev=346680&view=rev Log: [analyzer] Drastically simplify the tblgen files used for checkers Interestingly, only about the quarter of the emitter file is used, the DescFile entry hasn't ever been touched [1], and the entire concept of groups is a mystery, so I removed them. [1] http://lists.llvm.org/pipermail/cfe-dev/2018-October/059664.html Differential Revision: https://reviews.llvm.org/D53995 Modified: cfe/trunk/include/clang/Driver/CC1Options.td cfe/trunk/include/clang/StaticAnalyzer/Checkers/CheckerBase.td cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td cfe/trunk/lib/StaticAnalyzer/Checkers/ClangCheckers.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/ClangSACheckers.h cfe/trunk/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp cfe/trunk/lib/StaticAnalyzer/Core/SarifDiagnostics.cpp cfe/trunk/utils/TableGen/ClangSACheckersEmitter.cpp Modified: cfe/trunk/include/clang/Driver/CC1Options.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/CC1Options.td?rev=346680&r1=346679&r2=346680&view=diff == --- cfe/trunk/include/clang/Driver/CC1Options.td (original) +++ cfe/trunk/include/clang/Driver/CC1Options.td Mon Nov 12 09:49:51 2018 @@ -106,11 +106,11 @@ def analyzer_checker : Separate<["-"], " ValuesCode<[{ const char *Values = #define GET_CHECKERS -#define CHECKER(FULLNAME, CLASS, DESCFILE, HT, G, H) FULLNAME "," +#define CHECKER(FULLNAME, CLASS, HT) FULLNAME "," #include "clang/StaticAnalyzer/Checkers/Checkers.inc" #undef GET_CHECKERS #define GET_PACKAGES -#define PACKAGE(FULLNAME, G, D) FULLNAME "," +#define PACKAGE(FULLNAME) FULLNAME "," #include "clang/StaticAnalyzer/Checkers/Checkers.inc" #undef GET_PACKAGES ; Modified: cfe/trunk/include/clang/StaticAnalyzer/Checkers/CheckerBase.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Checkers/CheckerBase.td?rev=346680&r1=346679&r2=346680&view=diff == --- cfe/trunk/include/clang/StaticAnalyzer/Checkers/CheckerBase.td (original) +++ cfe/trunk/include/clang/StaticAnalyzer/Checkers/CheckerBase.td Mon Nov 12 09:49:51 2018 @@ -11,29 +11,34 @@ // //===--===// -class CheckerGroup { - string GroupName = name; -} -class InGroup { CheckerGroup Group = G; } - +/// Describes a package. Every checker is a part of a package, for example, +/// 'NullDereference' is part of the 'core' package, hence it's full name is +/// 'core.NullDereference'. +/// Example: +/// def Core : Package<"core">; class Package { string PackageName = name; - bit Hidden = 0; Package ParentPackage; - CheckerGroup Group; } -class InPackage { Package ParentPackage = P; } -// All checkers are an indirect subclass of this. +/// Describes a 'super' package that holds another package inside it. This is +/// used to nest packages in one another. One may, for example, create the +/// 'builtin' package inside 'core', thus creating the package 'core.builtin'. +/// Example: +/// def CoreBuiltin : Package<"builtin">, ParentPackage; +class ParentPackage { Package ParentPackage = P; } + +/// A description. May be displayed to the user when clang is invoked with +/// a '-help'-like command line option. +class HelpText { string HelpText = text; } + +/// Describes a checker. Every builtin checker has to be registered with the use +/// of this class (out-of-trunk checkers loaded from plugins obviously don't). +/// Note that a checker has a name (e.g.: 'NullDereference'), and a fullname, +/// that is autogenerated with the help of the ParentPackage field, that also +/// includes package names (e.g.: 'core.NullDereference'). class Checker { string CheckerName = name; - string DescFile; string HelpText; - bit Hidden = 0; Package ParentPackage; - CheckerGroup Group; } - -class DescFile { string DescFile = filename; } -class HelpText { string HelpText = text; } -class Hidden { bit Hidden = 1; } Modified: cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td?rev=346680&r1=346679&r2=346680&view=diff == --- cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td (original) +++ cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td Mon Nov 12 09:49:51 2018 @@ -21,9 +21,9 @@ include "CheckerBase.td" def Alpha : Package<"alpha">; def Core : Package<"core">; -def CoreBuiltin : Package<"builtin">, InPackage; -def CoreUninitialized : Package<"uninitialized">, InPackage; -def CoreAlp
r347006 - [analyzer] ConversionChecker: handle floating point
Author: szelethus Date: Thu Nov 15 17:00:55 2018 New Revision: 347006 URL: http://llvm.org/viewvc/llvm-project?rev=347006&view=rev Log: [analyzer] ConversionChecker: handle floating point Extend the alpha.core.Conversion checker to handle implicit converions where a too large integer value is converted to a floating point type. Each floating point type has a range where it can exactly represent all integers; we emit a warning when the integer value is above this range. Although it is possible to exactly represent some integers which are outside of this range (those that are divisible by a large enough power of 2); we still report cast involving those, because their usage may lead to bugs. (For example, if 1<<24 is stored in a float variable x, then x==x+1 holds.) Patch by: Donát Nagy! Differential Revision: https://reviews.llvm.org/D52730 Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/ConversionChecker.cpp cfe/trunk/test/Analysis/conversion.c Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/ConversionChecker.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/ConversionChecker.cpp?rev=347006&r1=347005&r2=347006&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Checkers/ConversionChecker.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/ConversionChecker.cpp Thu Nov 15 17:00:55 2018 @@ -14,8 +14,10 @@ // of expressions. A warning is reported when: // * a negative value is implicitly converted to an unsigned value in an // assignment, comparison or multiplication. -// * assignment / initialization when source value is greater than the max -// value of target +// * assignment / initialization when the source value is greater than the max +// value of the target integer type +// * assignment / initialization when the source integer is above the range +// where the target floating point type can represent all integers // // Many compilers and tools have similar checks that are based on semantic // analysis. Those checks are sound but have poor precision. ConversionChecker @@ -28,6 +30,9 @@ #include "clang/StaticAnalyzer/Core/Checker.h" #include "clang/StaticAnalyzer/Core/CheckerManager.h" #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" +#include "llvm/ADT/APFloat.h" + +#include using namespace clang; using namespace ento; @@ -40,11 +45,9 @@ public: private: mutable std::unique_ptr BT; - // Is there loss of precision bool isLossOfPrecision(const ImplicitCastExpr *Cast, QualType DestType, CheckerContext &C) const; - // Is there loss of sign bool isLossOfSign(const ImplicitCastExpr *Cast, CheckerContext &C) const; void reportBug(ExplodedNode *N, CheckerContext &C, const char Msg[]) const; @@ -132,19 +135,51 @@ bool ConversionChecker::isLossOfPrecisio QualType SubType = Cast->IgnoreParenImpCasts()->getType(); - if (!DestType->isIntegerType() || !SubType->isIntegerType()) + if (!DestType->isRealType() || !SubType->isIntegerType()) return false; - if (C.getASTContext().getIntWidth(DestType) >= - C.getASTContext().getIntWidth(SubType)) + const bool isFloat = DestType->isFloatingType(); + + const auto &AC = C.getASTContext(); + + // We will find the largest RepresentsUntilExp value such that the DestType + // can exactly represent all nonnegative integers below 2^RepresentsUntilExp. + unsigned RepresentsUntilExp; + + if (isFloat) { +const llvm::fltSemantics &Sema = AC.getFloatTypeSemantics(DestType); +RepresentsUntilExp = llvm::APFloat::semanticsPrecision(Sema); + } else { +RepresentsUntilExp = AC.getIntWidth(DestType); +if (RepresentsUntilExp == 1) { + // This is just casting a number to bool, probably not a bug. + return false; +} +if (DestType->isSignedIntegerType()) + RepresentsUntilExp--; + } + + if (RepresentsUntilExp >= sizeof(unsigned long long) * CHAR_BIT) { +// Avoid overflow in our later calculations. return false; + } + + unsigned CorrectedSrcWidth = AC.getIntWidth(SubType); + if (SubType->isSignedIntegerType()) +CorrectedSrcWidth--; - unsigned W = C.getASTContext().getIntWidth(DestType); - if (W == 1 || W >= 64U) + if (RepresentsUntilExp >= CorrectedSrcWidth) { +// Simple case: the destination can store all values of the source type. return false; + } - unsigned long long MaxVal = 1ULL << W; + unsigned long long MaxVal = 1ULL << RepresentsUntilExp; + if (isFloat) { +// If this is a floating point type, it can also represent MaxVal exactly. +MaxVal++; + } return C.isGreaterOrEqual(Cast->getSubExpr(), MaxVal); + // TODO: maybe also check negative values with too large magnitude. } bool ConversionChecker::isLossOfSign(const ImplicitCastExpr *Cast, Modified: cfe/trunk/test/Analysis/conversion.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/conversion.c?rev=3
r347153 - [analyzer][UninitializedObjectChecker] Uninit regions are only reported once
Author: szelethus Date: Sun Nov 18 03:34:10 2018 New Revision: 347153 URL: http://llvm.org/viewvc/llvm-project?rev=347153&view=rev Log: [analyzer][UninitializedObjectChecker] Uninit regions are only reported once Especially with pointees, a lot of meaningless reports came from uninitialized regions that were already reported. This is fixed by storing all reported fields to the GDM. Differential Revision: https://reviews.llvm.org/D51531 Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp cfe/trunk/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h?rev=347153&r1=347152&r2=347153&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h Sun Nov 18 03:34:10 2018 @@ -215,7 +215,11 @@ public: const TypedValueRegion *const R, const UninitObjCheckerOptions &Opts); - const UninitFieldMap &getUninitFields() { return UninitFields; } + /// Returns with the modified state and a map of (uninitialized region, + /// note message) pairs. + std::pair getResults() { +return {State, UninitFields}; + } /// Returns whether the analyzed region contains at least one initialized /// field. Note that this includes subfields as well, not just direct ones, @@ -296,14 +300,16 @@ private: // TODO: Add a support for nonloc::LocAsInteger. /// Processes LocalChain and attempts to insert it into UninitFields. Returns - /// true on success. + /// true on success. Also adds the head of the list and \p PointeeR (if + /// supplied) to the GDM as already analyzed objects. /// /// Since this class analyzes regions with recursion, we'll only store /// references to temporary FieldNode objects created on the stack. This means /// that after analyzing a leaf of the directed tree described above, the /// elements LocalChain references will be destructed, so we can't store it /// directly. - bool addFieldToUninits(FieldChainInfo LocalChain); + bool addFieldToUninits(FieldChainInfo LocalChain, + const MemRegion *PointeeR = nullptr); }; /// Returns true if T is a primitive type. An object of a primitive type only Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp?rev=347153&r1=347152&r2=347153&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp Sun Nov 18 03:34:10 2018 @@ -28,9 +28,14 @@ using namespace clang; using namespace clang::ento; +/// We'll mark fields (and pointee of fields) that are confirmed to be +/// uninitialized as already analyzed. +REGISTER_SET_WITH_PROGRAMSTATE(AnalyzedRegions, const MemRegion *) + namespace { -class UninitializedObjectChecker : public Checker { +class UninitializedObjectChecker +: public Checker { std::unique_ptr BT_uninitField; public: @@ -39,7 +44,9 @@ public: UninitializedObjectChecker() : BT_uninitField(new BuiltinBug(this, "Uninitialized fields")) {} + void checkEndFunction(const ReturnStmt *RS, CheckerContext &C) const; + void checkDeadSymbols(SymbolReaper &SR, CheckerContext &C) const; }; /// A basic field type, that is not a pointer or a reference, it's dynamic and @@ -140,14 +147,20 @@ void UninitializedObjectChecker::checkEn FindUninitializedFields F(Context.getState(), R, Opts); - const UninitFieldMap &UninitFields = F.getUninitFields(); + std::pair UninitInfo = + F.getResults(); - if (UninitFields.empty()) + ProgramStateRef UpdatedState = UninitInfo.first; + const UninitFieldMap &UninitFields = UninitInfo.second; + + if (UninitFields.empty()) { +Context.addTransition(UpdatedState); return; + } // There are uninitialized fields in the record. - ExplodedNode *Node = Context.generateNonFatalErrorNode(Context.getState()); + ExplodedNode *Node = Context.generateNonFatalErrorNode(UpdatedState); if (!Node) return; @@ -188,6 +201,15 @@ void UninitializedObjectChecker::checkEn Context.emitReport(std::move(Report)); } +void Uninitiali
r347157 - [analyzer][NFC] Move CheckerOptInfo to CheckerRegistry.cpp, and make it local
Author: szelethus Date: Sun Nov 18 04:47:03 2018 New Revision: 347157 URL: http://llvm.org/viewvc/llvm-project?rev=347157&view=rev Log: [analyzer][NFC] Move CheckerOptInfo to CheckerRegistry.cpp, and make it local CheckerOptInfo feels very much out of place in CheckerRegistration.cpp, so I moved it to CheckerRegistry.h. Differential Revision: https://reviews.llvm.org/D54397 Removed: cfe/trunk/include/clang/StaticAnalyzer/Core/CheckerOptInfo.h Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/CheckerRegistry.h cfe/trunk/lib/StaticAnalyzer/Core/CheckerRegistry.cpp cfe/trunk/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp Removed: cfe/trunk/include/clang/StaticAnalyzer/Core/CheckerOptInfo.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/CheckerOptInfo.h?rev=347156&view=auto == --- cfe/trunk/include/clang/StaticAnalyzer/Core/CheckerOptInfo.h (original) +++ cfe/trunk/include/clang/StaticAnalyzer/Core/CheckerOptInfo.h (removed) @@ -1,44 +0,0 @@ -//===--- CheckerOptInfo.h - Specifies which checkers to use -*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===--===// - -#ifndef LLVM_CLANG_STATICANALYZER_CORE_CHECKEROPTINFO_H -#define LLVM_CLANG_STATICANALYZER_CORE_CHECKEROPTINFO_H - -#include "clang/Basic/LLVM.h" -#include "llvm/ADT/StringRef.h" - -namespace clang { -namespace ento { - -/// Represents a request to include or exclude a checker or package from a -/// specific analysis run. -/// -/// \sa CheckerRegistry::initializeManager -class CheckerOptInfo { - StringRef Name; - bool Enable; - bool Claimed; - -public: - CheckerOptInfo(StringRef name, bool enable) -: Name(name), Enable(enable), Claimed(false) { } - - StringRef getName() const { return Name; } - bool isEnabled() const { return Enable; } - bool isDisabled() const { return !isEnabled(); } - - bool isClaimed() const { return Claimed; } - bool isUnclaimed() const { return !isClaimed(); } - void claim() { Claimed = true; } -}; - -} // end namespace ento -} // end namespace clang - -#endif Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/CheckerRegistry.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/CheckerRegistry.h?rev=347157&r1=347156&r2=347157&view=diff == --- cfe/trunk/include/clang/StaticAnalyzer/Core/CheckerRegistry.h (original) +++ cfe/trunk/include/clang/StaticAnalyzer/Core/CheckerRegistry.h Sun Nov 18 04:47:03 2018 @@ -73,8 +73,6 @@ class DiagnosticsEngine; namespace ento { -class CheckerOptInfo; - /// Manages a set of available checkers for running a static analysis. /// The checkers are organized into packages by full name, where including /// a package will recursively include all subpackages and checkers within it. @@ -123,8 +121,8 @@ public: /// all checkers specified by the given CheckerOptInfo list. The order of this /// list is significant; later options can be used to reverse earlier ones. /// This can be used to exclude certain checkers in an included package. - void initializeManager(CheckerManager &mgr, - SmallVectorImpl &opts) const; + void initializeManager(CheckerManager &mgr, const AnalyzerOptions &Opts, + DiagnosticsEngine &diags) const; /// Check if every option corresponds to a specific checker or package. void validateCheckerOptions(const AnalyzerOptions &opts, @@ -133,8 +131,7 @@ public: /// Prints the name and description of all checkers in this registry. /// This output is not intended to be machine-parseable. void printHelp(raw_ostream &out, size_t maxNameChars = 30) const; - void printList(raw_ostream &out, - SmallVectorImpl &opts) const; + void printList(raw_ostream &out, const AnalyzerOptions &opts) const; private: mutable CheckerInfoList Checkers; Modified: cfe/trunk/lib/StaticAnalyzer/Core/CheckerRegistry.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/CheckerRegistry.cpp?rev=347157&r1=347156&r2=347157&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Core/CheckerRegistry.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Core/CheckerRegistry.cpp Sun Nov 18 04:47:03 2018 @@ -12,7 +12,6 @@ #include "clang/Basic/LLVM.h" #include "clang/Frontend/FrontendDiagnostic.h" #include "clang/StaticAnalyzer/Core/CheckerManager.h" -#include "clang/StaticAnalyzer/Core/CheckerOptInfo.h" #include "clang/StaticAnalyzer/Core/AnalyzerOptions.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SetVector.h" @@ -30,6 +29,41
r347513 - [analyzer] INT50-CPP. Do not cast to an out-of-range enumeration checker
Author: szelethus Date: Sat Nov 24 04:24:27 2018 New Revision: 347513 URL: http://llvm.org/viewvc/llvm-project?rev=347513&view=rev Log: [analyzer] INT50-CPP. Do not cast to an out-of-range enumeration checker This checker implements a solution to the "INT50-CPP. Do not cast to an out-of-range enumeration value" rule [1]. It lands in alpha for now, and a number of followup patches are planned in order to enable it by default. [1] https://www.securecoding.cert.org/confluence/display/cplusplus/INT50-CPP.+Do+not+cast+to+an+out-of-range+enumeration+value Patch by: Endre Fülöp and Alexander Zaitsev! Differential Revision: https://reviews.llvm.org/D33672 Added: cfe/trunk/lib/StaticAnalyzer/Checkers/EnumCastOutOfRangeChecker.cpp cfe/trunk/test/Analysis/enum-cast-out-of-range.cpp Modified: cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td cfe/trunk/lib/StaticAnalyzer/Checkers/CMakeLists.txt cfe/trunk/www/analyzer/alpha_checks.html Modified: cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td?rev=347513&r1=347512&r2=347513&view=diff == --- cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td (original) +++ cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td Sat Nov 24 04:24:27 2018 @@ -290,6 +290,9 @@ def DeleteWithNonVirtualDtorChecker : Ch HelpText<"Reports destructions of polymorphic objects with a non-virtual " "destructor in their base class">; +def EnumCastOutOfRangeChecker : Checker<"EnumCastOutOfRange">, + HelpText<"Check integer to enumeration casts for out of range values">; + def InvalidatedIteratorChecker : Checker<"InvalidatedIterator">, HelpText<"Check for use of invalidated iterators">; Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/CMakeLists.txt URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/CMakeLists.txt?rev=347513&r1=347512&r2=347513&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Checkers/CMakeLists.txt (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/CMakeLists.txt Sat Nov 24 04:24:27 2018 @@ -34,6 +34,7 @@ add_clang_library(clangStaticAnalyzerChe DivZeroChecker.cpp DynamicTypePropagation.cpp DynamicTypeChecker.cpp + EnumCastOutOfRangeChecker.cpp ExprInspectionChecker.cpp FixedAddressChecker.cpp GCDAntipatternChecker.cpp Added: cfe/trunk/lib/StaticAnalyzer/Checkers/EnumCastOutOfRangeChecker.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/EnumCastOutOfRangeChecker.cpp?rev=347513&view=auto == --- cfe/trunk/lib/StaticAnalyzer/Checkers/EnumCastOutOfRangeChecker.cpp (added) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/EnumCastOutOfRangeChecker.cpp Sat Nov 24 04:24:27 2018 @@ -0,0 +1,128 @@ +//===- EnumCastOutOfRangeChecker.cpp ---*- C++ -*--===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===--===// +// +// The EnumCastOutOfRangeChecker is responsible for checking integer to +// enumeration casts that could result in undefined values. This could happen +// if the value that we cast from is out of the value range of the enumeration. +// Reference: +// [ISO/IEC 14882-2014] ISO/IEC 14882-2014. +// Programming Languages â C++, Fourth Edition. 2014. +// C++ Standard, [dcl.enum], in paragraph 8, which defines the range of an enum +// C++ Standard, [expr.static.cast], paragraph 10, which defines the behaviour +// of casting an integer value that is out of range +// SEI CERT C++ Coding Standard, INT50-CPP. Do not cast to an out-of-range +// enumeration value +//===--===// + +#include "ClangSACheckers.h" +#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" + +using namespace clang; +using namespace ento; + +namespace { +// This evaluator checks two SVals for equality. The first SVal is provided via +// the constructor, the second is the parameter of the overloaded () operator. +// It uses the in-built ConstraintManager to resolve the equlity to possible or +// not possible ProgramStates. +class ConstraintBasedEQEvaluator { + const DefinedOrUnknownSVal CompareValue; + const ProgramStateRef PS; + SValBuilder &SVB; + +public: + ConstraintBasedEQEvaluator(CheckerContext &C, + const DefinedOrUnknownSVal CompareValue) + : CompareValue(CompareValue), PS(C.getState()), SVB(C.getSValBuilder()) {} +
r347888 - [analyzer][PlistMacroExpansion] Part 4.: Support for __VA_ARGS__
Author: szelethus Date: Thu Nov 29 09:09:41 2018 New Revision: 347888 URL: http://llvm.org/viewvc/llvm-project?rev=347888&view=rev Log: [analyzer][PlistMacroExpansion] Part 4.: Support for __VA_ARGS__ Differential Revision: https://reviews.llvm.org/D52986 Modified: cfe/trunk/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp cfe/trunk/test/Analysis/Inputs/expected-plists/plist-macros-with-expansion.cpp.plist cfe/trunk/test/Analysis/plist-macros-with-expansion.cpp Modified: cfe/trunk/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp?rev=347888&r1=347887&r2=347888&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp Thu Nov 29 09:09:41 2018 @@ -962,41 +962,62 @@ static MacroNameAndArgs getMacroNameAndA // CALL_FN(someFunctionName(param1, param2)) // we will find tok::l_paren, tok::r_paren, and tok::comma that do not divide // actual macro arguments, or do not represent the macro argument's closing - // parentheses, so we'll count how many parentheses aren't closed yet. + // parantheses, so we'll count how many parantheses aren't closed yet. + // If ParanthesesDepth + // * = 0, then there are no more arguments to lex. + // * = 1, then if we find a tok::comma, we can start lexing the next arg. + // * > 1, then tok::comma is a part of the current arg. int ParenthesesDepth = 1; + // If we encounter __VA_ARGS__, we will lex until the closing tok::r_paren, + // even if we lex a tok::comma and ParanthesesDepth == 1. + const IdentifierInfo *__VA_ARGS__II = PP.getIdentifierInfo("__VA_ARGS__"); + for (const IdentifierInfo *UnexpArgII : MacroArgs) { MacroArgMap::mapped_type ExpandedArgTokens; -// Lex the first token of the next macro parameter. -RawLexer.LexFromRawLexer(TheTok); - -while (TheTok.isNot(tok::comma) || ParenthesesDepth != 1) { - assert(TheTok.isNot(tok::eof) && - "EOF encountered while looking for expanded macro args!"); - - if (TheTok.is(tok::l_paren)) -++ParenthesesDepth; - - if (TheTok.is(tok::r_paren)) ---ParenthesesDepth; +// One could also simply not supply a single argument to __VA_ARGS__ -- this +// results in a preprocessor warning, but is not an error: +// #define VARIADIC(ptr, ...) \ +// someVariadicTemplateFunction(__VA_ARGS__) +// +// int *ptr; +// VARIADIC(ptr); // Note that there are no commas, this isn't just an +// // empty parameter -- there are no parameters for '...'. +// In any other case, ParenthesesDepth mustn't be 0 here. +if (ParenthesesDepth != 0) { - if (ParenthesesDepth == 0) -break; - - if (TheTok.is(tok::raw_identifier)) -PP.LookUpIdentifierInfo(TheTok); - - ExpandedArgTokens.push_back(TheTok); + // Lex the first token of the next macro parameter. RawLexer.LexFromRawLexer(TheTok); + + while (!(ParenthesesDepth == 1 && + (UnexpArgII == __VA_ARGS__II ? false : TheTok.is(tok::comma { +assert(TheTok.isNot(tok::eof) && + "EOF encountered while looking for expanded macro args!"); + +if (TheTok.is(tok::l_paren)) + ++ParenthesesDepth; + +if (TheTok.is(tok::r_paren)) + --ParenthesesDepth; + +if (ParenthesesDepth == 0) + break; + +if (TheTok.is(tok::raw_identifier)) + PP.LookUpIdentifierInfo(TheTok); + +ExpandedArgTokens.push_back(TheTok); +RawLexer.LexFromRawLexer(TheTok); + } +} else { + assert(UnexpArgII == __VA_ARGS__II); } Args.emplace(UnexpArgII, std::move(ExpandedArgTokens)); } - // TODO: The condition really should be TheTok.is(tok::r_paren), but variadic - // macro arguments are not handled yet. - assert(TheTok.isOneOf(tok::r_paren, tok::comma) && + assert(TheTok.is(tok::r_paren) && "Expanded macro argument acquisition failed! After the end of the loop" " this token should be ')'!"); Modified: cfe/trunk/test/Analysis/Inputs/expected-plists/plist-macros-with-expansion.cpp.plist URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/Inputs/expected-plists/plist-macros-with-expansion.cpp.plist?rev=347888&r1=347887&r2=347888&view=diff == --- cfe/trunk/test/Analysis/Inputs/expected-plists/plist-macros-with-expansion.cpp.plist (original) +++ cfe/trunk/test/Analysis/Inputs/expected-plists/plist-macros-with-expansion.cpp.plist Thu Nov 29 09:09:41 2018 @@ -4217,7 +4217,7 @@ file0 nameVARIADIC_SET_TO_NULL - expansionptr = nullptr; variadicFunc( 1) + expansionptr = nullptr; variadicFunc( 1, 5, "haha!")
r348025 - [analyzer][PlistMacroExpansion] Part 5.: Support for # and ##
Author: szelethus Date: Fri Nov 30 11:21:35 2018 New Revision: 348025 URL: http://llvm.org/viewvc/llvm-project?rev=348025&view=rev Log: [analyzer][PlistMacroExpansion] Part 5.: Support for # and ## From what I can see, this should be the last patch needed to replicate macro argument expansions. Differential Revision: https://reviews.llvm.org/D52988 Modified: cfe/trunk/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp cfe/trunk/test/Analysis/Inputs/expected-plists/plist-macros-with-expansion.cpp.plist cfe/trunk/test/Analysis/plist-macros-with-expansion.cpp Modified: cfe/trunk/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp?rev=348025&r1=348024&r2=348025&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp Fri Nov 30 11:21:35 2018 @@ -904,8 +904,6 @@ static std::string getMacroNameAndPrintE continue; } -// TODO: Handle tok::hash and tok::hashhash. - // If control reached here, then this token isn't a macro identifier, nor an // unexpanded macro argument that we need to handle, print it. Printer.printToken(T); @@ -1094,14 +1092,25 @@ void MacroArgMap::expandFromPrevMacro(co } void TokenPrinter::printToken(const Token &Tok) { - // If the tokens were already space separated, or if they must be to avoid - // them being implicitly pasted, add a space between them. // If this is the first token to be printed, don't print space. - if (PrevTok.isNot(tok::unknown) && (Tok.hasLeadingSpace() || - ConcatInfo.AvoidConcat(PrevPrevTok, PrevTok, Tok))) -OS << ' '; + if (PrevTok.isNot(tok::unknown)) { +// If the tokens were already space separated, or if they must be to avoid +// them being implicitly pasted, add a space between them. +if(Tok.hasLeadingSpace() || ConcatInfo.AvoidConcat(PrevPrevTok, PrevTok, + Tok)) { + // AvoidConcat doesn't check for ##, don't print a space around it. + if (PrevTok.isNot(tok::hashhash) && Tok.isNot(tok::hashhash)) { +OS << ' '; + } +} + } - OS << PP.getSpelling(Tok); + if (!Tok.isOneOf(tok::hash, tok::hashhash)) { +if (PrevTok.is(tok::hash)) + OS << '\"' << PP.getSpelling(Tok) << '\"'; +else + OS << PP.getSpelling(Tok); + } PrevPrevTok = PrevTok; PrevTok = Tok; Modified: cfe/trunk/test/Analysis/Inputs/expected-plists/plist-macros-with-expansion.cpp.plist URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/Inputs/expected-plists/plist-macros-with-expansion.cpp.plist?rev=348025&r1=348024&r2=348025&view=diff == --- cfe/trunk/test/Analysis/Inputs/expected-plists/plist-macros-with-expansion.cpp.plist (original) +++ cfe/trunk/test/Analysis/Inputs/expected-plists/plist-macros-with-expansion.cpp.plist Fri Nov 30 11:21:35 2018 @@ -4555,7 +4555,7 @@ file0 nameDECLARE_FUNC_AND_SET_TO_NULL - expansionvoid generated_##whatever(); ptr = nullptr; + expansionvoid generated_whatever(); ptr = nullptr; descriptionDereference of null pointer (loaded from variable 'ptr') @@ -4595,12 +4595,12 @@ start - line357 + line352 col3 file0 - line357 + line352 col5 file0 @@ -4608,12 +4608,181 @@ end - line358 + line353 col3 file0 - line358 + line353 + col19 + file0 + + + + + + + kindevent + location + + line353 + col3 + file0 + + ranges + + + + line353 + col3 + file0 + + + line353 + col53 + file0 + + + + depth0 + extended_message + Null pointer value stored to 'a' + message + Null pointer value stored to 'a' + + + kindcontrol + edges + + +start + + + line354 + col3 + file0 + + + line354 + col3 + file0 + + +end + + + line354 + col6 + file0 + + + line354 + col6 + file0 + + + + + + + kindevent + location + + line354 + col6 + file0 + + ranges + + + + line354 + col4 + file0 +
r348031 - [analyzer] Evaluate all non-checker config options before analysis
Author: szelethus Date: Fri Nov 30 12:44:00 2018 New Revision: 348031 URL: http://llvm.org/viewvc/llvm-project?rev=348031&view=rev Log: [analyzer] Evaluate all non-checker config options before analysis In earlier patches regarding AnalyzerOptions, a lot of effort went into gathering all config options, and changing the interface so that potential misuse can be eliminited. Up until this point, AnalyzerOptions only evaluated an option when it was querried. For example, if we had a "-no-false-positives" flag, AnalyzerOptions would store an Optional field for it that would be None up until somewhere in the code until the flag's getter function is called. However, now that we're confident that we've gathered all configs, we can evaluate off of them before analysis, so we can emit a error on invalid input even if that prticular flag will not matter in that particular run of the analyzer. Another very big benefit of this is that debug.ConfigDumper will now show the value of all configs every single time. Also, almost all options related class have a similar interface, so uniformity is also a benefit. The implementation for errors on invalid input will be commited shorty. Differential Revision: https://reviews.llvm.org/D53692 Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h cfe/trunk/lib/Frontend/CompilerInvocation.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/DebugCheckers.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp cfe/trunk/lib/StaticAnalyzer/Core/AnalysisManager.cpp cfe/trunk/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp cfe/trunk/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp cfe/trunk/lib/StaticAnalyzer/Core/CallEvent.cpp cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp cfe/trunk/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp cfe/trunk/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp cfe/trunk/lib/StaticAnalyzer/Core/SValBuilder.cpp cfe/trunk/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp cfe/trunk/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp cfe/trunk/lib/StaticAnalyzer/Frontend/ModelInjector.cpp cfe/trunk/test/Analysis/analyzer-config.c cfe/trunk/test/Analysis/analyzer-config.cpp Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def?rev=348031&r1=348030&r2=348031&view=diff == --- cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def (original) +++ cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def Fri Nov 30 12:44:00 2018 @@ -9,29 +9,6 @@ // // This file defines the analyzer options avaible with -analyzer-config. // -// This file is in part intended for method generation. If it's not included -// for that purpose, the following function-like macros should be predefined, -// through which all registered options are accessible: -// -//* ANALYZER_OPTION: Register a new option. -//* ANALYZER_OPTION_DEPENDS_ON_USER_MODE: Register a new option, default -// value depends on the "user-mode" option. -// -// Options where a simple getter method is sufficient are registered with the -// following macros: -// -//* ANALYZER_OPTION_GEN_FN: Register a new option, and generate a getter -// method for it in AnalyzerOptions. -// -//* ANALYZER_OPTION_GEN_FN_DEPENDS_ON_USER_MODE: Same as above, but -// generates a getter function that depends on the "user-mode" option. -// -// You can only include this file when both or none of the above two macros -// are defined! -// When they are defined, entries that do not generate functions won't appear, -// and when they aren't, all entries are converted to ANALYZER_OPTION or to -// ANALYZER_OPTION_DEPENDS_ON_USER_MODE. -// //===--===// #ifndef LLVM_ADT_STRINGREF_H @@ -53,22 +30,6 @@ define both 'ANALYZER_OPTION' and 'ANALY #endif #endif -#ifdef ANALYZER_OPTION_GEN_FN -#ifndef ANALYZER_OPTION_GEN_FN_DEPENDS_ON_USER_MODE -#error If you include this file with the intent of generating functions, \ -define both 'ANALYZER_OPTION_GEN_FN' and \ -'ANALYZER_OPTION_GEN_FN_DEPENDS_ON_USER_MODE' macros! -#endif -#endif - -#ifdef ANALYZER_OPTION_GEN_FN_DEPENDS_ON_USER_MODE -#ifndef ANALYZER_OPTION_GEN_FN -#error If you include this file with the intent of generating functions, \ -define both 'ANALYZER_OPTION_GEN_FN' and \ -'ANALYZER_OPTION_GEN_FN_DEPENDS_ON_USER_MODE' macros! -#endif -#endif - #ifndef ANALYZER_OPTION /// Create a new analyzer option, but
r348038 - [analyzer] Emit an error for invalid -analyzer-config inputs
Author: szelethus Date: Fri Nov 30 13:24:31 2018 New Revision: 348038 URL: http://llvm.org/viewvc/llvm-project?rev=348038&view=rev Log: [analyzer] Emit an error for invalid -analyzer-config inputs Differential Revision: https://reviews.llvm.org/D53280 Added: cfe/trunk/test/Analysis/invalid-analyzer-config-value.c Modified: cfe/trunk/include/clang/Basic/DiagnosticDriverKinds.td cfe/trunk/include/clang/Driver/CC1Options.td cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h cfe/trunk/lib/Driver/ToolChains/Clang.cpp cfe/trunk/lib/Frontend/CompilerInvocation.cpp Modified: cfe/trunk/include/clang/Basic/DiagnosticDriverKinds.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticDriverKinds.td?rev=348038&r1=348037&r2=348038&view=diff == --- cfe/trunk/include/clang/Basic/DiagnosticDriverKinds.td (original) +++ cfe/trunk/include/clang/Basic/DiagnosticDriverKinds.td Fri Nov 30 13:24:31 2018 @@ -299,6 +299,9 @@ def err_analyzer_config_no_value : Error "analyzer-config option '%0' has a key but no value">; def err_analyzer_config_multiple_values : Error< "analyzer-config option '%0' should contain only one '='">; +def err_analyzer_config_invalid_input : Error< + "invalid input for analyzer-config option '%0', that expects %1 value">; +def err_analyzer_config_unknown : Error<"unknown analyzer-config '%0'">; def err_drv_invalid_hvx_length : Error< "-mhvx-length is not supported without a -mhvx/-mhvx= flag">; Modified: cfe/trunk/include/clang/Driver/CC1Options.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/CC1Options.td?rev=348038&r1=348037&r2=348038&view=diff == --- cfe/trunk/include/clang/Driver/CC1Options.td (original) +++ cfe/trunk/include/clang/Driver/CC1Options.td Fri Nov 30 13:24:31 2018 @@ -138,6 +138,12 @@ def analyzer_list_enabled_checkers : Fla def analyzer_config : Separate<["-"], "analyzer-config">, HelpText<"Choose analyzer options to enable">; +def analyzer_config_compatibility_mode : Separate<["-"], "analyzer-config-compatibility-mode">, + HelpText<"Don't emit errors on invalid analyzer-config inputs">; + +def analyzer_config_compatibility_mode_EQ : Joined<["-"], "analyzer-config-compatibility-mode=">, + Alias; + //===--===// // Migrator Options //===--===// Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h?rev=348038&r1=348037&r2=348038&view=diff == --- cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h (original) +++ cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h Fri Nov 30 13:24:31 2018 @@ -200,6 +200,7 @@ public: unsigned ShowCheckerHelp : 1; unsigned ShowEnabledCheckerList : 1; unsigned ShowConfigOptionsList : 1; + unsigned ShouldEmitErrorsOnInvalidConfigValue : 1; unsigned AnalyzeAll : 1; unsigned AnalyzerDisplayProgress : 1; unsigned AnalyzeNestedBlocks : 1; @@ -222,6 +223,7 @@ public: /// The mode of function selection used during inlining. AnalysisInliningMode InliningMode = NoRedundancy; + // Create a field for each -analyzer-config option. #define ANALYZER_OPTION_DEPENDS_ON_USER_MODE(TYPE, NAME, CMDFLAG, DESC, \ SHALLOW_VAL, DEEP_VAL) \ ANALYZER_OPTION(TYPE, NAME, CMDFLAG, DESC, SHALLOW_VAL) @@ -233,13 +235,39 @@ public: #undef ANALYZER_OPTION #undef ANALYZER_OPTION_DEPENDS_ON_USER_MODE + // Create an array of all -analyzer-config command line options. Sort it in + // the constructor. + std::vector AnalyzerConfigCmdFlags = { +#define ANALYZER_OPTION_DEPENDS_ON_USER_MODE(TYPE, NAME, CMDFLAG, DESC, \ + SHALLOW_VAL, DEEP_VAL) \ + ANALYZER_OPTION(TYPE, NAME, CMDFLAG, DESC, SHALLOW_VAL) + +#define ANALYZER_OPTION(TYPE, NAME, CMDFLAG, DESC, DEFAULT_VAL) \ +CMDFLAG, + +#include "clang/StaticAnalyzer/Core/AnalyzerOptions.def" +#undef ANALYZER_OPTION +#undef ANALYZER_OPTION_DEPENDS_ON_USER_MODE + }; + + bool isUnknownAnalyzerConfig(StringRef Name) const { + +assert(std::is_sorted(AnalyzerConfigCmdFlags.begin(), + AnalyzerConfigCmdFlags.end())); + +return !std::binary_search(AnalyzerConfigCmdFlags.begin(), + AnalyzerConfigCmdFlags.end(), Name); + } + AnalyzerOptions() : DisableAllChecks(false), ShowCheckerHelp(false), ShowEnabledCheckerList(false), ShowConfigOptionsList(false), AnalyzeAll(fa
r348044 - [analyzer] Deleting unnecessary test file
Author: szelethus Date: Fri Nov 30 14:32:17 2018 New Revision: 348044 URL: http://llvm.org/viewvc/llvm-project?rev=348044&view=rev Log: [analyzer] Deleting unnecessary test file That I really should've done in rC348031. Removed: cfe/trunk/test/Analysis/analyzer-config.cpp Removed: cfe/trunk/test/Analysis/analyzer-config.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/analyzer-config.cpp?rev=348043&view=auto == --- cfe/trunk/test/Analysis/analyzer-config.cpp (original) +++ cfe/trunk/test/Analysis/analyzer-config.cpp (removed) @@ -1,54 +0,0 @@ -// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 %s -o /dev/null -analyzer-checker=core,osx.cocoa,debug.ConfigDumper -analyzer-max-loop 34 > %t 2>&1 -// RUN: FileCheck --input-file=%t %s --match-full-lines - -// CHECK: [config] -// CHECK-NEXT: aggressive-binary-operation-simplification = false -// CHECK-NEXT: avoid-suppressing-null-argument-paths = false -// CHECK-NEXT: c++-allocator-inlining = true -// CHECK-NEXT: c++-container-inlining = false -// CHECK-NEXT: c++-inlining = destructors -// CHECK-NEXT: c++-shared_ptr-inlining = false -// CHECK-NEXT: c++-stdlib-inlining = true -// CHECK-NEXT: c++-temp-dtor-inlining = true -// CHECK-NEXT: c++-template-inlining = true -// CHECK-NEXT: cfg-conditional-static-initializers = true -// CHECK-NEXT: cfg-implicit-dtors = true -// CHECK-NEXT: cfg-lifetime = false -// CHECK-NEXT: cfg-loopexit = false -// CHECK-NEXT: cfg-rich-constructors = true -// CHECK-NEXT: cfg-scopes = false -// CHECK-NEXT: cfg-temporary-dtors = true -// CHECK-NEXT: crosscheck-with-z3 = false -// CHECK-NEXT: ctu-dir = "" -// CHECK-NEXT: ctu-index-name = externalFnMap.txt -// CHECK-NEXT: eagerly-assume = true -// CHECK-NEXT: elide-constructors = true -// CHECK-NEXT:expand-macros = false -// CHECK-NEXT: experimental-enable-naive-ctu-analysis = false -// CHECK-NEXT: exploration_strategy = unexplored_first_queue -// CHECK-NEXT: faux-bodies = true -// CHECK-NEXT: graph-trim-interval = 1000 -// CHECK-NEXT: inline-lambdas = true -// CHECK-NEXT: ipa = dynamic-bifurcate -// CHECK-NEXT: ipa-always-inline-size = 3 -// CHECK-NEXT: max-inlinable-size = 100 -// CHECK-NEXT: max-nodes = 225000 -// CHECK-NEXT: max-symbol-complexity = 35 -// CHECK-NEXT: max-times-inline-large = 32 -// CHECK-NEXT: min-cfg-size-treat-functions-as-large = 14 -// CHECK-NEXT: mode = deep -// CHECK-NEXT: model-path = "" -// CHECK-NEXT: notes-as-events = false -// CHECK-NEXT: objc-inlining = true -// CHECK-NEXT: prune-paths = true -// CHECK-NEXT: region-store-small-struct-limit = 2 -// CHECK-NEXT: report-in-main-source-file = false -// CHECK-NEXT: serialize-stats = false -// CHECK-NEXT: stable-report-filename = false -// CHECK-NEXT: suppress-c++-stdlib = true -// CHECK-NEXT: suppress-inlined-defensive-checks = true -// CHECK-NEXT: suppress-null-return-paths = true -// CHECK-NEXT: unroll-loops = false -// CHECK-NEXT: widen-loops = false -// CHECK-NEXT: [stats] -// CHECK-NEXT: num-entries = 48 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r355297 - [analyzer] Enable subcheckers to possess checker options
Author: szelethus Date: Sun Mar 3 16:28:16 2019 New Revision: 355297 URL: http://llvm.org/viewvc/llvm-project?rev=355297&view=rev Log: [analyzer] Enable subcheckers to possess checker options Under the term "subchecker", I mean checkers that do not have a checker class on their own, like unix.MallocChecker to unix.DynamicMemoryModeling. Since a checker object was required in order to retrieve checker options, subcheckers couldn't possess options on their own. This patch is also an excuse to change the argument order of getChecker*Option, it always bothered me, now it resembles the actual command line argument (checkername:option=value). Differential Revision: https://reviews.llvm.org/D57579 Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h cfe/trunk/lib/StaticAnalyzer/Checkers/AnalysisOrderChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/CloneChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/MmapWriteExecChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/MoveChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/NumberObjectConversionChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/VirtualCallChecker.cpp cfe/trunk/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp cfe/trunk/unittests/StaticAnalyzer/AnalyzerOptionsTest.cpp Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h?rev=355297&r1=355296&r2=355297&view=diff == --- cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h (original) +++ cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h Sun Mar 3 16:28:16 2019 @@ -272,54 +272,74 @@ 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] 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] 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 :OptionName=Value. /// @param [in] SearchInParents If set to true and the searched option was not /// specified for the given checker the options for the parent packages will /// be searched as well. The inner packages take precedence over the outer /// ones. - bool getCheckerBooleanOption(StringRef Name, bool DefaultVal, -const ento::CheckerBase *C, -bool SearchInParents = false) const; + bool getCheckerBooleanOption(StringRef CheckerName, StringRef OptionName, + bool DefaultVal, + bool SearchInParents = false) const; + bool getCheckerBooleanOption(const ento::CheckerBase *C, StringRef OptionName, + bool DefaultVal, + 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] 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] 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 :OptionName=Value. /// @param [in] SearchInParents If set to true and the searched option was not /// specified for the given checker the options for the parent packages will /// be searched as well. The inner packages take precedence over the outer /// ones. - int getCh
r355396 - [analyzer] Fix taint propagation in GenericTaintChecker
Author: szelethus Date: Tue Mar 5 04:42:59 2019 New Revision: 355396 URL: http://llvm.org/viewvc/llvm-project?rev=355396&view=rev Log: [analyzer] Fix taint propagation in GenericTaintChecker The gets function has no SrcArgs. Because the default value for isTainted was false, it didn't mark its DstArgs as tainted. Patch by Gábor Borsik! Differential Revision: https://reviews.llvm.org/D58828 Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp cfe/trunk/test/Analysis/taint-generic.c Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp?rev=355396&r1=355395&r2=355396&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp Tue Mar 5 04:42:59 2019 @@ -458,7 +458,7 @@ GenericTaintChecker::TaintPropagationRul ProgramStateRef State = C.getState(); // Check for taint in arguments. - bool IsTainted = false; + bool IsTainted = true; for (unsigned ArgNum : SrcArgs) { if (ArgNum >= CE->getNumArgs()) return State; Modified: cfe/trunk/test/Analysis/taint-generic.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/taint-generic.c?rev=355396&r1=355395&r2=355396&view=diff == --- cfe/trunk/test/Analysis/taint-generic.c (original) +++ cfe/trunk/test/Analysis/taint-generic.c Tue Mar 5 04:42:59 2019 @@ -2,6 +2,7 @@ // RUN: %clang_analyze_cc1 -DFILE_IS_STRUCT -analyzer-checker=alpha.security.taint,core,alpha.security.ArrayBoundV2 -Wno-format-security -verify %s int scanf(const char *restrict format, ...); +char *gets(char *str); int getchar(void); typedef struct _FILE FILE; @@ -142,6 +143,12 @@ void testTaintSystemCall3() { system(buffern2); // expected-warning {{Untrusted data is passed to a system call}} } +void testGets() { + char str[50]; + gets(str); + system(str); // expected-warning {{Untrusted data is passed to a system call}} +} + void testTaintedBufferSize() { size_t ts; scanf("%zd", &ts); ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r355703 - [analyzer] Use the new infrastructure of expressing taint propagation, NFC
Author: szelethus Date: Fri Mar 8 07:47:56 2019 New Revision: 355703 URL: http://llvm.org/viewvc/llvm-project?rev=355703&view=rev Log: [analyzer] Use the new infrastructure of expressing taint propagation, NFC In D55734, we implemented a far more general way of describing taint propagation rules for functions, like being able to specify an unlimited amount of source and destination parameters. Previously, we didn't have a particularly elegant way of expressing the propagation rules for functions that always return (either through an out-param or return value) a tainted value. In this patch, we model these functions similarly to other ones, by assigning them a TaintPropagationRule that describes that they "create a tainted value out of nothing". The socket C function is somewhat special, because for certain parameters (for example, if we supply localhost as parameter), none of the out-params should be tainted. For this, we added a general solution of being able to specify custom taint propagation rules through function pointers. Patch by Gábor Borsik! Differential Revision: https://reviews.llvm.org/D59055 Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp?rev=355703&r1=355702&r2=355703&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp Fri Mar 8 07:47:56 2019 @@ -62,9 +62,6 @@ private: /// Propagate taint generated at pre-visit. bool propagateFromPre(const CallExpr *CE, CheckerContext &C) const; - /// Add taint sources on a post visit. - void addSourcesPost(const CallExpr *CE, CheckerContext &C) const; - /// Check if the region the expression evaluates to is the standard input, /// and thus, is tainted. static bool isStdin(const Expr *E, CheckerContext &C); @@ -72,16 +69,6 @@ private: /// Given a pointer argument, return the value it points to. static Optional getPointedToSVal(CheckerContext &C, const Expr *Arg); - /// Functions defining the attack surface. - using FnCheck = ProgramStateRef (GenericTaintChecker::*)( - const CallExpr *, CheckerContext &C) const; - ProgramStateRef postScanf(const CallExpr *CE, CheckerContext &C) const; - ProgramStateRef postSocket(const CallExpr *CE, CheckerContext &C) const; - ProgramStateRef postRetTaint(const CallExpr *CE, CheckerContext &C) const; - - /// Taint the scanned input if the file is tainted. - ProgramStateRef preFscanf(const CallExpr *CE, CheckerContext &C) const; - /// Check for CWE-134: Uncontrolled Format String. static const char MsgUncontrolledFormatString[]; bool checkUncontrolledFormatString(const CallExpr *CE, @@ -118,6 +105,9 @@ private: struct TaintPropagationRule { enum class VariadicType { None, Src, Dst }; +using PropagationFuncType = bool (*)(bool IsTainted, const CallExpr *, + CheckerContext &C); + /// List of arguments which can be taint sources and should be checked. ArgVector SrcArgs; /// List of arguments which should be tainted on function return. @@ -127,16 +117,21 @@ private: /// Show when a function has variadic parameters. If it has, it marks all /// of them as source or destination. VariadicType VarType; +/// Special function for tainted source determination. If defined, it can +/// override the default behavior. +PropagationFuncType PropagationFunc; TaintPropagationRule() -: VariadicIndex(InvalidArgIndex), VarType(VariadicType::None) {} +: VariadicIndex(InvalidArgIndex), VarType(VariadicType::None), + PropagationFunc(nullptr) {} TaintPropagationRule(std::initializer_list &&Src, std::initializer_list &&Dst, VariadicType Var = VariadicType::None, - unsigned VarIndex = InvalidArgIndex) + unsigned VarIndex = InvalidArgIndex, + PropagationFuncType Func = nullptr) : SrcArgs(std::move(Src)), DstArgs(std::move(Dst)), - VariadicIndex(VarIndex), VarType(Var) {} + VariadicIndex(VarIndex), VarType(Var), PropagationFunc(Func) {} /// Get the propagation rule for a given function. static TaintPropagationRule @@ -170,6 +165,10 @@ private: /// Pre-process a function which propagates taint according to the /// taint rule. ProgramStateRef process(const CallExpr *CE, CheckerContext &C) const; + +// Functions for custom taintedness propagation. +static bool postSocket(bool IsTainted, const CallExpr *CE, + CheckerContext &C); }; }; @@ -206,25 +205,42 @@ GenericTaintChecker::Taint
r355704 - [analyzer] Emit an error rather than assert on invalid checker option input
Author: szelethus Date: Fri Mar 8 08:00:42 2019 New Revision: 355704 URL: http://llvm.org/viewvc/llvm-project?rev=355704&view=rev Log: [analyzer] Emit an error rather than assert on invalid checker option input Asserting on invalid input isn't very nice, hence the patch to emit an error instead. This is the first of many patches to overhaul the way we handle checker options. Differential Revision: https://reviews.llvm.org/D57850 Modified: cfe/trunk/include/clang/Basic/DiagnosticDriverKinds.td cfe/trunk/include/clang/StaticAnalyzer/Core/CheckerManager.h cfe/trunk/lib/StaticAnalyzer/Checkers/CheckObjCDealloc.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/CloneChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/MoveChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp cfe/trunk/lib/StaticAnalyzer/Core/CheckerManager.cpp cfe/trunk/test/Analysis/copypaste/suspicious-clones.cpp cfe/trunk/test/Analysis/cxx-uninitialized-object-unionlike-constructs.cpp cfe/trunk/test/Analysis/outofbound.c cfe/trunk/test/Analysis/padding_c.c cfe/trunk/test/Analysis/undef-buffers.c cfe/trunk/test/Analysis/use-after-move.cpp Modified: cfe/trunk/include/clang/Basic/DiagnosticDriverKinds.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticDriverKinds.td?rev=355704&r1=355703&r2=355704&view=diff == --- cfe/trunk/include/clang/Basic/DiagnosticDriverKinds.td (original) +++ cfe/trunk/include/clang/Basic/DiagnosticDriverKinds.td Fri Mar 8 08:00:42 2019 @@ -303,6 +303,8 @@ def err_analyzer_config_multiple_values def err_analyzer_config_invalid_input : Error< "invalid input for analyzer-config option '%0', that expects %1 value">; def err_analyzer_config_unknown : Error<"unknown analyzer-config '%0'">; +def err_analyzer_checker_option_invalid_input : Error< + "invalid input for checker option '%0', that expects %1">; def err_drv_invalid_hvx_length : Error< "-mhvx-length is not supported without a -mhvx/-mhvx= flag">; Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/CheckerManager.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/CheckerManager.h?rev=355704&r1=355703&r2=355704&view=diff == --- cfe/trunk/include/clang/StaticAnalyzer/Core/CheckerManager.h (original) +++ cfe/trunk/include/clang/StaticAnalyzer/Core/CheckerManager.h Fri Mar 8 08:00:42 2019 @@ -136,6 +136,12 @@ 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; Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/CheckObjCDealloc.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/CheckObjCDealloc.cpp?rev=355704&r1=355703&r2=355704&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Checkers/CheckObjCDealloc.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/CheckObjCDealloc.cpp Fri Mar 8 08:00:42 2019 @@ -1086,14 +1086,10 @@ bool ObjCDeallocChecker::isNibLoadedIvar } void ento::registerObjCDeallocChecker(CheckerManager &Mgr) { - const LangOptions &LangOpts = Mgr.getLangOpts(); - // These checker only makes sense under MRR. - if (LangOpts.getGC() == LangOptions::GCOnly || LangOpts.ObjCAutoRefCount) -return; - Mgr.registerChecker(); } bool ento::shouldRegisterObjCDeallocChecker(const LangOptions &LO) { - return true; + // These checker only makes sense under MRR. + return LO.getGC() != LangOptions::GCOnly && !LO.ObjCAutoRefCount; } Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/CloneChecker.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/CloneChecker.cpp?rev=355704&r1=355703&r2=355704&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Checkers/CloneChecker.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/CloneChecker.cpp Fri Mar 8 08:00:42 2019 @@ -27,6 +27,13 @@ using namespace ento; namespace { class CloneChecker : public Checker { +public: + // Checker options. + int MinComplexity; + bool ReportNormalClones; + StringRef IgnoredFilesPattern; + +private: mutable CloneDetector Detector; mutable std::unique_ptr BT_Exact, BT_Suspicious; @@ -62,19 +69,6
r355705 - [analyzer] Fix infinite recursion in printing macros
Author: szelethus Date: Fri Mar 8 08:26:29 2019 New Revision: 355705 URL: http://llvm.org/viewvc/llvm-project?rev=355705&view=rev Log: [analyzer] Fix infinite recursion in printing macros In the commited testfile, macro expansion (the one implemented for the plist output) runs into an infinite recursion. The issue originates from the algorithm being faulty, as in #define value REC_MACRO_FUNC(value) the "value" is being (or at least attempted) expanded from the same macro. The solved this issue by gathering already visited macros in a set, which does resolve the crash, but will result in an incorrect macro expansion, that would preferably be fixed down the line. Patch by Tibor Brunner! Differential Revision: https://reviews.llvm.org/D57891 Modified: cfe/trunk/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp cfe/trunk/test/Analysis/Inputs/expected-plists/plist-macros-with-expansion.cpp.plist cfe/trunk/test/Analysis/plist-macros-with-expansion.cpp Modified: cfe/trunk/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp?rev=355705&r1=355704&r2=355705&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp Fri Mar 8 08:26:29 2019 @@ -22,6 +22,7 @@ #include "clang/StaticAnalyzer/Core/IssueHash.h" #include "clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h" #include "llvm/ADT/Statistic.h" +#include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Support/Casting.h" @@ -776,10 +777,20 @@ public: /// As we expand the last line, we'll immediately replace PRINT(str) with /// print(x). The information that both 'str' and 'x' refers to the same string /// is an information we have to forward, hence the argument \p PrevArgs. -static std::string getMacroNameAndPrintExpansion(TokenPrinter &Printer, - SourceLocation MacroLoc, - const Preprocessor &PP, - const MacroArgMap &PrevArgs); +/// +/// To avoid infinite recursion we maintain the already processed tokens in +/// a set. This is carried as a parameter through the recursive calls. The set +/// is extended with the currently processed token and after processing it, the +/// token is removed. If the token is already in the set, then recursion stops: +/// +/// #define f(y) x +/// #define x f(x) +static std::string getMacroNameAndPrintExpansion( +TokenPrinter &Printer, +SourceLocation MacroLoc, +const Preprocessor &PP, +const MacroArgMap &PrevArgs, +llvm::SmallPtrSet &AlreadyProcessedTokens); /// Retrieves the name of the macro and what it's arguments expand into /// at \p ExpanLoc. @@ -828,19 +839,35 @@ static ExpansionInfo getExpandedMacro(So llvm::SmallString<200> ExpansionBuf; llvm::raw_svector_ostream OS(ExpansionBuf); TokenPrinter Printer(OS, PP); + llvm::SmallPtrSet AlreadyProcessedTokens; + std::string MacroName = -getMacroNameAndPrintExpansion(Printer, MacroLoc, PP, MacroArgMap{}); +getMacroNameAndPrintExpansion(Printer, MacroLoc, PP, MacroArgMap{}, + AlreadyProcessedTokens); return { MacroName, OS.str() }; } -static std::string getMacroNameAndPrintExpansion(TokenPrinter &Printer, - SourceLocation MacroLoc, - const Preprocessor &PP, - const MacroArgMap &PrevArgs) { +static std::string getMacroNameAndPrintExpansion( +TokenPrinter &Printer, +SourceLocation MacroLoc, +const Preprocessor &PP, +const MacroArgMap &PrevArgs, +llvm::SmallPtrSet &AlreadyProcessedTokens) { const SourceManager &SM = PP.getSourceManager(); MacroNameAndArgs Info = getMacroNameAndArgs(SM.getExpansionLoc(MacroLoc), PP); + IdentifierInfo* IDInfo = PP.getIdentifierInfo(Info.Name); + + // TODO: If the macro definition contains another symbol then this function is + // called recursively. In case this symbol is the one being defined, it will + // be an infinite recursion which is stopped by this "if" statement. However, + // in this case we don't get the full expansion text in the Plist file. See + // the test file where "value" is expanded to "garbage_" instead of + // "garbage_value". + if (AlreadyProcessedTokens.find(IDInfo) != AlreadyProcessedTokens.end()) +return Info.Name; + AlreadyProcessedTokens.insert(IDInfo); if (!Info.MI) return Info.Name; @@ -867,7 +894,8 @@ static std::string getMacroNameAndPrintE // macro. if (const MacroInfo *MI = getMacroInfoForLocation(PP, SM, II, T.getLocation())) { - getMacroNa
r355903 - [analyzer] Fix function macro crash
Author: szelethus Date: Tue Mar 12 03:03:32 2019 New Revision: 355903 URL: http://llvm.org/viewvc/llvm-project?rev=355903&view=rev Log: [analyzer] Fix function macro crash When there is a functor-like macro which is passed as parameter to another "function" macro then its parameters are not listed at the place of expansion: #define foo(x) int bar() { return x; } #define hello(fvar) fvar(0) hello(foo) int main() { 1 / bar(); } Expansion of hello(foo) asserted Clang, because it expected an l_paren token in the 3rd line after "foo", since it is a function-like token. Patch by Tibor Brunner! Differential Revision: https://reviews.llvm.org/D57893 Modified: cfe/trunk/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp cfe/trunk/test/Analysis/Inputs/expected-plists/plist-macros-with-expansion.cpp.plist cfe/trunk/test/Analysis/plist-macros-with-expansion.cpp Modified: cfe/trunk/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp?rev=355903&r1=355902&r2=355903&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp Tue Mar 12 03:03:32 2019 @@ -900,7 +900,7 @@ static std::string getMacroNameAndPrintE // If this is a function-like macro, skip its arguments, as // getExpandedMacro() already printed them. If this is the case, let's // first jump to the '(' token. - if (MI->getNumParams() != 0) + if (std::next(It)->is(tok::l_paren)) It = getMatchingRParen(++It, E); continue; } @@ -928,7 +928,15 @@ static std::string getMacroNameAndPrintE getMacroNameAndPrintExpansion(Printer, ArgIt->getLocation(), PP, Info.Args, AlreadyProcessedTokens); -if (MI->getNumParams() != 0) +// Peek the next token if it is a tok::l_paren. This way we can decide +// if this is the application or just a reference to a function maxro +// symbol: +// +// #define apply(f) ... +// #define func(x) ... +// apply(func) +// apply(func(42)) +if (std::next(ArgIt)->is(tok::l_paren)) ArgIt = getMatchingRParen(++ArgIt, ArgEnd); } continue; @@ -990,8 +998,16 @@ static MacroNameAndArgs getMacroNameAndA return { MacroName, MI, {} }; RawLexer.LexFromRawLexer(TheTok); - assert(TheTok.is(tok::l_paren) && - "The token after the macro's identifier token should be '('!"); + // When this is a token which expands to another macro function then its + // parentheses are not at its expansion locaiton. For example: + // + // #define foo(x) int bar() { return x; } + // #define apply_zero(f) f(0) + // apply_zero(foo) + // ^ + // This is not a tok::l_paren, but foo is a function. + if (TheTok.isNot(tok::l_paren)) +return { MacroName, MI, {} }; MacroArgMap Args; Modified: cfe/trunk/test/Analysis/Inputs/expected-plists/plist-macros-with-expansion.cpp.plist URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/Inputs/expected-plists/plist-macros-with-expansion.cpp.plist?rev=355903&r1=355902&r2=355903&view=diff == --- cfe/trunk/test/Analysis/Inputs/expected-plists/plist-macros-with-expansion.cpp.plist (original) +++ cfe/trunk/test/Analysis/Inputs/expected-plists/plist-macros-with-expansion.cpp.plist Tue Mar 12 03:03:32 2019 @@ -5577,6 +5577,484 @@ + + path + + + kindcontrol + edges + + +start + + + line459 + col33 + file0 + + + line459 + col33 + file0 + + +end + + + line459 + col37 + file0 + + + line459 + col39 + file0 + + + + + + + kindevent + location + + line459 + col37 + file0 + + ranges + + + + line459 + col37 + file0 + + + line459 + col41 + file0 + + + + depth0 + extended_message + Calling 'foo' + message + Calling 'foo' + + + kindevent + location + + line458 + col1 + file0 + + depth1 + extended_message + Entered call from 'useZeroApplier1' + message + Entered call from 'useZeroApplier1' + + + kindevent + location + + line458 + col1 + file0 + + ranges + + + + line458 + col1 + file0 + + + line458 + col16
r355911 - Revert "[analyzer] Fix function macro crash"
Author: szelethus Date: Tue Mar 12 04:22:30 2019 New Revision: 355911 URL: http://llvm.org/viewvc/llvm-project?rev=355911&view=rev Log: Revert "[analyzer] Fix function macro crash" Buildbot breaks when LLVm is compiled with memory sanitizer. WARNING: MemorySanitizer: use-of-uninitialized-value #0 0xa3d16d8 in getMacroNameAndPrintExpansion(blahblah) lib/StaticAnalyzer/Core/PlistDiagnostics.cpp:903:11 Modified: cfe/trunk/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp cfe/trunk/test/Analysis/Inputs/expected-plists/plist-macros-with-expansion.cpp.plist cfe/trunk/test/Analysis/plist-macros-with-expansion.cpp Modified: cfe/trunk/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp?rev=355911&r1=355910&r2=355911&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp Tue Mar 12 04:22:30 2019 @@ -900,7 +900,7 @@ static std::string getMacroNameAndPrintE // If this is a function-like macro, skip its arguments, as // getExpandedMacro() already printed them. If this is the case, let's // first jump to the '(' token. - if (std::next(It)->is(tok::l_paren)) + if (MI->getNumParams() != 0) It = getMatchingRParen(++It, E); continue; } @@ -928,15 +928,7 @@ static std::string getMacroNameAndPrintE getMacroNameAndPrintExpansion(Printer, ArgIt->getLocation(), PP, Info.Args, AlreadyProcessedTokens); -// Peek the next token if it is a tok::l_paren. This way we can decide -// if this is the application or just a reference to a function maxro -// symbol: -// -// #define apply(f) ... -// #define func(x) ... -// apply(func) -// apply(func(42)) -if (std::next(ArgIt)->is(tok::l_paren)) +if (MI->getNumParams() != 0) ArgIt = getMatchingRParen(++ArgIt, ArgEnd); } continue; @@ -998,16 +990,8 @@ static MacroNameAndArgs getMacroNameAndA return { MacroName, MI, {} }; RawLexer.LexFromRawLexer(TheTok); - // When this is a token which expands to another macro function then its - // parentheses are not at its expansion locaiton. For example: - // - // #define foo(x) int bar() { return x; } - // #define apply_zero(f) f(0) - // apply_zero(foo) - // ^ - // This is not a tok::l_paren, but foo is a function. - if (TheTok.isNot(tok::l_paren)) -return { MacroName, MI, {} }; + assert(TheTok.is(tok::l_paren) && + "The token after the macro's identifier token should be '('!"); MacroArgMap Args; Modified: cfe/trunk/test/Analysis/Inputs/expected-plists/plist-macros-with-expansion.cpp.plist URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/Inputs/expected-plists/plist-macros-with-expansion.cpp.plist?rev=355911&r1=355910&r2=355911&view=diff == --- cfe/trunk/test/Analysis/Inputs/expected-plists/plist-macros-with-expansion.cpp.plist (original) +++ cfe/trunk/test/Analysis/Inputs/expected-plists/plist-macros-with-expansion.cpp.plist Tue Mar 12 04:22:30 2019 @@ -5577,484 +5577,6 @@ - - path - - - kindcontrol - edges - - -start - - - line459 - col33 - file0 - - - line459 - col33 - file0 - - -end - - - line459 - col37 - file0 - - - line459 - col39 - file0 - - - - - - - kindevent - location - - line459 - col37 - file0 - - ranges - - - - line459 - col37 - file0 - - - line459 - col41 - file0 - - - - depth0 - extended_message - Calling 'foo' - message - Calling 'foo' - - - kindevent - location - - line458 - col1 - file0 - - depth1 - extended_message - Entered call from 'useZeroApplier1' - message - Entered call from 'useZeroApplier1' - - - kindevent - location - - line458 - col1 - file0 - - ranges - - - - line458 - col1 - file0 - - - line458 - col16 - file0 - - - - depth1 - extended_message - Returning zero - message - Returning zero - - - kindevent - location - - line459 - col37 -
r356142 - [analyzer] Fix function macro crash
Author: szelethus Date: Thu Mar 14 06:38:16 2019 New Revision: 356142 URL: http://llvm.org/viewvc/llvm-project?rev=356142&view=rev Log: [analyzer] Fix function macro crash Re-commit D57893. Differential Revision: https://reviews.llvm.org/D57893 Modified: cfe/trunk/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp cfe/trunk/test/Analysis/Inputs/expected-plists/plist-macros-with-expansion.cpp.plist cfe/trunk/test/Analysis/plist-macros-with-expansion.cpp Modified: cfe/trunk/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp?rev=356142&r1=356141&r2=356142&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp Thu Mar 14 06:38:16 2019 @@ -900,7 +900,8 @@ static std::string getMacroNameAndPrintE // If this is a function-like macro, skip its arguments, as // getExpandedMacro() already printed them. If this is the case, let's // first jump to the '(' token. - if (MI->getNumParams() != 0) + auto N = std::next(It); + if (N != E && N->is(tok::l_paren)) It = getMatchingRParen(++It, E); continue; } @@ -928,7 +929,16 @@ static std::string getMacroNameAndPrintE getMacroNameAndPrintExpansion(Printer, ArgIt->getLocation(), PP, Info.Args, AlreadyProcessedTokens); -if (MI->getNumParams() != 0) +// Peek the next token if it is a tok::l_paren. This way we can decide +// if this is the application or just a reference to a function maxro +// symbol: +// +// #define apply(f) ... +// #define func(x) ... +// apply(func) +// apply(func(42)) +auto N = std::next(ArgIt); +if (N != ArgEnd && N->is(tok::l_paren)) ArgIt = getMatchingRParen(++ArgIt, ArgEnd); } continue; @@ -990,8 +1000,16 @@ static MacroNameAndArgs getMacroNameAndA return { MacroName, MI, {} }; RawLexer.LexFromRawLexer(TheTok); - assert(TheTok.is(tok::l_paren) && - "The token after the macro's identifier token should be '('!"); + // When this is a token which expands to another macro function then its + // parentheses are not at its expansion locaiton. For example: + // + // #define foo(x) int bar() { return x; } + // #define apply_zero(f) f(0) + // apply_zero(foo) + // ^ + // This is not a tok::l_paren, but foo is a function. + if (TheTok.isNot(tok::l_paren)) +return { MacroName, MI, {} }; MacroArgMap Args; Modified: cfe/trunk/test/Analysis/Inputs/expected-plists/plist-macros-with-expansion.cpp.plist URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/Inputs/expected-plists/plist-macros-with-expansion.cpp.plist?rev=356142&r1=356141&r2=356142&view=diff == --- cfe/trunk/test/Analysis/Inputs/expected-plists/plist-macros-with-expansion.cpp.plist (original) +++ cfe/trunk/test/Analysis/Inputs/expected-plists/plist-macros-with-expansion.cpp.plist Thu Mar 14 06:38:16 2019 @@ -5577,6 +5577,484 @@ + + path + + + kindcontrol + edges + + +start + + + line459 + col33 + file0 + + + line459 + col33 + file0 + + +end + + + line459 + col37 + file0 + + + line459 + col39 + file0 + + + + + + + kindevent + location + + line459 + col37 + file0 + + ranges + + + + line459 + col37 + file0 + + + line459 + col41 + file0 + + + + depth0 + extended_message + Calling 'foo' + message + Calling 'foo' + + + kindevent + location + + line458 + col1 + file0 + + depth1 + extended_message + Entered call from 'useZeroApplier1' + message + Entered call from 'useZeroApplier1' + + + kindevent + location + + line458 + col1 + file0 + + ranges + + + + line458 + col1 + file0 + + + line458 + col16 + file0 + + + + depth1 + extended_message + Returning zero + message + Returning zero + + + kindevent + location + + line459 + col37 + file0 + + ranges + + + + line459 + col37 + file0 + + +
r356161 - [analyzer] Fix an assertation failure for invalid sourcelocation, add a new debug checker
Author: szelethus Date: Thu Mar 14 09:10:29 2019 New Revision: 356161 URL: http://llvm.org/viewvc/llvm-project?rev=356161&view=rev Log: [analyzer] Fix an assertation failure for invalid sourcelocation, add a new debug checker For a rather short code snippet, if debug.ReportStmts (added in this patch) was enabled, a bug reporter visitor crashed: struct h { operator int(); }; int k() { return h(); } Ultimately, this originated from PathDiagnosticLocation::createMemberLoc, as it didn't handle the case where it's MemberExpr typed parameter returned and invalid SourceLocation for MemberExpr::getMemberLoc. The solution was to find any related valid SourceLocaion, and Stmt::getBeginLoc happens to be just that. Differential Revision: https://reviews.llvm.org/D58777 Added: cfe/trunk/test/Analysis/diagnostics/invalid-srcloc-fix.cpp Modified: cfe/trunk/docs/analyzer/developer-docs/DebugChecks.rst cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td cfe/trunk/lib/StaticAnalyzer/Checkers/DebugCheckers.cpp cfe/trunk/lib/StaticAnalyzer/Core/PathDiagnostic.cpp cfe/trunk/test/Analysis/plist-html-macros.c Modified: cfe/trunk/docs/analyzer/developer-docs/DebugChecks.rst URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/analyzer/developer-docs/DebugChecks.rst?rev=356161&r1=356160&r2=356161&view=diff == --- cfe/trunk/docs/analyzer/developer-docs/DebugChecks.rst (original) +++ cfe/trunk/docs/analyzer/developer-docs/DebugChecks.rst Thu Mar 14 09:10:29 2019 @@ -285,3 +285,10 @@ There is also an additional -analyzer-st statistics within the analyzer engine. Note the Stats checker (which produces at least one bug report per function) may actually change the values reported by -analyzer-stats. + +Output testing checkers +=== + +- debug.ReportStmts reports a warning at **every** statement, making it a very + useful tool for testing thoroughly bug report construction and output + emission. Modified: cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td?rev=356161&r1=356160&r2=356161&view=diff == --- cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td (original) +++ cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td Thu Mar 14 09:10:29 2019 @@ -1019,6 +1019,10 @@ def ExplodedGraphViewer : Checker<"ViewE HelpText<"View Exploded Graphs using GraphViz">, Documentation; +def ReportStmts : Checker<"ReportStmts">, + HelpText<"Emits a warning for every statement.">, + Documentation; + } // end "debug" Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/DebugCheckers.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/DebugCheckers.cpp?rev=356161&r1=356160&r2=356161&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Checkers/DebugCheckers.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/DebugCheckers.cpp Thu Mar 14 09:10:29 2019 @@ -266,3 +266,34 @@ void ento::registerExplodedGraphViewer(C bool ento::shouldRegisterExplodedGraphViewer(const LangOptions &LO) { return true; } + +//===--===// +// Emits a report for every Stmt that the analyzer visits. +//===--===// + +namespace { + +class ReportStmts : public Checker> { + BuiltinBug BT_stmtLoc{this, "Statement"}; + +public: + void checkPreStmt(const Stmt *S, CheckerContext &C) const { +ExplodedNode *Node = C.generateNonFatalErrorNode(); +if (!Node) + return; + +auto Report = llvm::make_unique(BT_stmtLoc, "Statement", Node); + +C.emitReport(std::move(Report)); + } +}; + +} // end of anonymous namespace + +void ento::registerReportStmts(CheckerManager &mgr) { + mgr.registerChecker(); +} + +bool ento::shouldRegisterReportStmts(const LangOptions &LO) { + return true; +} Modified: cfe/trunk/lib/StaticAnalyzer/Core/PathDiagnostic.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/PathDiagnostic.cpp?rev=356161&r1=356160&r2=356161&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Core/PathDiagnostic.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Core/PathDiagnostic.cpp Thu Mar 14 09:10:29 2019 @@ -571,6 +571,8 @@ static SourceLocation getValidSourceLoca } while (!L.isValid()); } + // FIXME: Ironically, this assert actually fails in some cases. + //assert(L.isValid()); return L; } @@ -671,7 +673,15 @@ PathDiagnosticLocation::createConditiona PathDiagnosticLocation PathDiagnosticLocation::createMemberLoc(const MemberExpr *ME,
r358609 - [analyzer] PR41185: Fix regression where __builtin_* functions weren't recognized
Author: szelethus Date: Wed Apr 17 12:56:40 2019 New Revision: 358609 URL: http://llvm.org/viewvc/llvm-project?rev=358609&view=rev Log: [analyzer] PR41185: Fix regression where __builtin_* functions weren't recognized For the following code snippet: void builtin_function_call_crash_fixes(char *c) { __builtin_strncpy(c, "", 6); __builtin_memset(c, '\0', (0)); __builtin_memcpy(c, c, 0); } security.insecureAPI.DeprecatedOrUnsafeBufferHandling caused a regression, as it didn't recognize functions starting with __builtin_. Fixed exactly that. I wanted to modify an existing test file, but the two I found didn't seem like perfect candidates. While I was there, I prettified their RUN: lines. Differential Revision: https://reviews.llvm.org/D59812 Added: cfe/trunk/test/Analysis/security-syntax-checks.c Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp cfe/trunk/test/Analysis/security-syntax-checks-no-emit.c cfe/trunk/test/Analysis/security-syntax-checks.m Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp?rev=358609&r1=358608&r2=358609&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp Wed Apr 17 12:56:40 2019 @@ -740,7 +740,11 @@ void WalkAST::checkDeprecatedOrUnsafeBuf // Issue a warning. ArgIndex == -1: Deprecated but not unsafe (has size // restrictions). enum { DEPR_ONLY = -1, UNKNOWN_CALL = -2 }; + StringRef Name = FD->getIdentifier()->getName(); + if (Name.startswith("__builtin_")) +Name = Name.substr(10); + int ArgIndex = llvm::StringSwitch(Name) .Cases("scanf", "wscanf", "vscanf", "vwscanf", 0) Modified: cfe/trunk/test/Analysis/security-syntax-checks-no-emit.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/security-syntax-checks-no-emit.c?rev=358609&r1=358608&r2=358609&view=diff == --- cfe/trunk/test/Analysis/security-syntax-checks-no-emit.c (original) +++ cfe/trunk/test/Analysis/security-syntax-checks-no-emit.c Wed Apr 17 12:56:40 2019 @@ -1,4 +1,7 @@ -// RUN: %clang_analyze_cc1 -triple i686-pc-linux-gnu -analyzer-checker=security.insecureAPI,security.FloatLoopCounter %s -verify +// RUN: %clang_analyze_cc1 -triple i686-pc-linux-gnu %s -verify \ +// RUN: -analyzer-checker=security.insecureAPI \ +// RUN: -analyzer-checker=security.FloatLoopCounter + // expected-no-diagnostics // This file complements 'security-syntax-checks.m', but tests that we omit Added: cfe/trunk/test/Analysis/security-syntax-checks.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/security-syntax-checks.c?rev=358609&view=auto == --- cfe/trunk/test/Analysis/security-syntax-checks.c (added) +++ cfe/trunk/test/Analysis/security-syntax-checks.c Wed Apr 17 12:56:40 2019 @@ -0,0 +1,8 @@ +// RUN: %clang_analyze_cc1 %s -verify \ +// RUN: -analyzer-checker=security.insecureAPI + +void builtin_function_call_crash_fixes(char *c) { + __builtin_strncpy(c, "", 6); // expected-warning{{Call to function 'strncpy' is insecure as it does not provide security checks introduced in the C11 standard.}} + __builtin_memset(c, '\0', (0)); // expected-warning{{Call to function 'memset' is insecure as it does not provide security checks introduced in the C11 standard.}} + __builtin_memcpy(c, c, 0); // expected-warning{{Call to function 'memcpy' is insecure as it does not provide security checks introduced in the C11 standard.}} +} Modified: cfe/trunk/test/Analysis/security-syntax-checks.m URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/security-syntax-checks.m?rev=358609&r1=358608&r2=358609&view=diff == --- cfe/trunk/test/Analysis/security-syntax-checks.m (original) +++ cfe/trunk/test/Analysis/security-syntax-checks.m Wed Apr 17 12:56:40 2019 @@ -1,11 +1,40 @@ -// RUN: %clang_analyze_cc1 -triple i386-apple-darwin10 -analyzer-checker=security.insecureAPI,security.FloatLoopCounter %s -verify -// RUN: %clang_analyze_cc1 -triple i386-apple-darwin10 -DUSE_BUILTINS -analyzer-checker=security.insecureAPI,security.FloatLoopCounter %s -verify -// RUN: %clang_analyze_cc1 -triple i386-apple-darwin10 -DVARIANT -analyzer-checker=security.insecureAPI,security.FloatLoopCounter %s -verify -// RUN: %clang_analyze_cc1 -triple i386-apple-darwin10 -DUSE_BUILTINS -DVARIANT -analyzer-checker=security.insecureAPI,security.FloatLoopCounter %s -verify -// RUN: %clang_analyze_cc1 -triple x86_64-unknown-cloudabi -analyzer-checker=security.insecureAPI,security.FloatLoopCoun
r358676 - [analyzer][NFC] Use capital variable names, move methods out-of-line, rename some in CheckerRegistry
Author: szelethus Date: Thu Apr 18 08:19:16 2019 New Revision: 358676 URL: http://llvm.org/viewvc/llvm-project?rev=358676&view=rev Log: [analyzer][NFC] Use capital variable names, move methods out-of-line, rename some in CheckerRegistry There are barely any lines I haven't changed in these files, so I think I could might as well leave it in an LLVM coding style conforming state. I also renamed 2 functions and moved addDependency out of line to ease on followup patches. Differential Revision: https://reviews.llvm.org/D59457 Modified: cfe/trunk/include/clang/StaticAnalyzer/Frontend/CheckerRegistry.h cfe/trunk/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp cfe/trunk/lib/StaticAnalyzer/Frontend/CheckerRegistry.cpp Modified: cfe/trunk/include/clang/StaticAnalyzer/Frontend/CheckerRegistry.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Frontend/CheckerRegistry.h?rev=358676&r1=358675&r2=358676&view=diff == --- cfe/trunk/include/clang/StaticAnalyzer/Frontend/CheckerRegistry.h (original) +++ cfe/trunk/include/clang/StaticAnalyzer/Frontend/CheckerRegistry.h Thu Apr 18 08:19:16 2019 @@ -164,40 +164,23 @@ public: /// Makes the checker with the full name \p fullName depends on the checker /// called \p dependency. - void addDependency(StringRef fullName, StringRef dependency) { -auto CheckerThatNeedsDeps = - [&fullName](const CheckerInfo &Chk) { return Chk.FullName == fullName; }; -auto Dependency = - [&dependency](const CheckerInfo &Chk) { -return Chk.FullName == dependency; - }; - -auto CheckerIt = llvm::find_if(Checkers, CheckerThatNeedsDeps); -assert(CheckerIt != Checkers.end() && - "Failed to find the checker while attempting to set up it's " - "dependencies!"); - -auto DependencyIt = llvm::find_if(Checkers, Dependency); -assert(DependencyIt != Checkers.end() && - "Failed to find the dependency of a checker!"); - -CheckerIt->Dependencies.push_back(&*DependencyIt); - } + void addDependency(StringRef FullName, StringRef Dependency); // 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; + void initializeManager(CheckerManager &CheckerMgr) const; /// Check if every option corresponds to a specific checker or package. 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; + void printCheckerWithDescList(raw_ostream &Out, +size_t MaxNameChars = 30) const; + void printEnabledCheckerList(raw_ostream &Out) const; private: /// Collect all enabled checkers. The returned container preserves the order @@ -211,7 +194,7 @@ private: CheckerInfoListRange getMutableCheckersForCmdLineArg(StringRef CmdLineArg); CheckerInfoList Checkers; - llvm::StringMap Packages; + llvm::StringMap PackageSizes; DiagnosticsEngine &Diags; AnalyzerOptions &AnOpts; Modified: cfe/trunk/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp?rev=358676&r1=358675&r2=358676&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp Thu Apr 18 08:19:16 2019 @@ -50,7 +50,8 @@ void ento::printCheckerHelp(raw_ostream out << "OVERVIEW: Clang Static Analyzer Checkers List\n\n"; out << "USAGE: -analyzer-checker \n\n"; - CheckerRegistry(plugins, diags, anopts, langOpts).printHelp(out); + CheckerRegistry(plugins, diags, anopts, langOpts) + .printCheckerWithDescList(out); } void ento::printEnabledCheckerList(raw_ostream &out, @@ -60,7 +61,8 @@ void ento::printEnabledCheckerList(raw_o const LangOptions &langOpts) { out << "OVERVIEW: Clang Static Analyzer Enabled Checkers List\n\n"; - CheckerRegistry(plugins, diags, anopts, langOpts).printList(out); + CheckerRegistry(plugins, diags, anopts, langOpts) + .printEnabledCheckerList(out); } void ento::printAnalyzerConfigList(raw_ostream &out) { Modified: cfe/trunk/lib/StaticAnalyzer/Frontend/CheckerRegistry.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyze
r358695 - [analyzer][NFC] Prefer binary searches in CheckerRegistry
Author: szelethus Date: Thu Apr 18 10:34:45 2019 New Revision: 358695 URL: http://llvm.org/viewvc/llvm-project?rev=358695&view=rev Log: [analyzer][NFC] Prefer binary searches in CheckerRegistry Differential Revision: https://reviews.llvm.org/D59459 Modified: cfe/trunk/include/clang/StaticAnalyzer/Frontend/CheckerRegistry.h cfe/trunk/lib/StaticAnalyzer/Frontend/CheckerRegistry.cpp Modified: cfe/trunk/include/clang/StaticAnalyzer/Frontend/CheckerRegistry.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Frontend/CheckerRegistry.h?rev=358695&r1=358694&r2=358695&view=diff == --- cfe/trunk/include/clang/StaticAnalyzer/Frontend/CheckerRegistry.h (original) +++ cfe/trunk/include/clang/StaticAnalyzer/Frontend/CheckerRegistry.h Thu Apr 18 10:34:45 2019 @@ -108,8 +108,8 @@ public: State_Enabled }; -InitializationFunction Initialize; -ShouldRegisterFunction ShouldRegister; +InitializationFunction Initialize = nullptr; +ShouldRegisterFunction ShouldRegister = nullptr; StringRef FullName; StringRef Desc; StringRef DocumentationUri; @@ -129,6 +129,9 @@ public: StringRef Name, StringRef Desc, StringRef DocsUri) : Initialize(Fn), ShouldRegister(sfn), FullName(Name), Desc(Desc), DocumentationUri(DocsUri) {} + +// Used for lower_bound. +explicit CheckerInfo(StringRef FullName) : FullName(FullName) {} }; using StateFromCmdLine = CheckerInfo::StateFromCmdLine; Modified: cfe/trunk/lib/StaticAnalyzer/Frontend/CheckerRegistry.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Frontend/CheckerRegistry.cpp?rev=358695&r1=358694&r2=358695&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Frontend/CheckerRegistry.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Frontend/CheckerRegistry.cpp Thu Apr 18 10:34:45 2019 @@ -48,6 +48,28 @@ template struct FullNameLT { using CheckerNameLT = FullNameLT; } // end of anonymous namespace +template +static +typename std::conditional::value, + typename CheckerOrPackageInfoList::const_iterator, + typename CheckerOrPackageInfoList::iterator>::type +binaryFind(CheckerOrPackageInfoList &Collection, StringRef FullName) { + + using CheckerOrPackage = typename CheckerOrPackageInfoList::value_type; + using CheckerOrPackageFullNameLT = FullNameLT; + + assert(std::is_sorted(Collection.begin(), Collection.end(), +CheckerOrPackageFullNameLT{}) && + "In order to efficiently gather checkers/packages, this function " + "expects them to be already sorted!"); + + typename CheckerOrPackageInfoList::value_type Info(FullName); + + return llvm::lower_bound( + Collection, Info, + FullNameLT{}); +} + static constexpr char PackageSeparator = '.'; static bool isInPackage(const CheckerRegistry::CheckerInfo &Checker, @@ -69,16 +91,7 @@ static bool isInPackage(const CheckerReg CheckerRegistry::CheckerInfoListRange CheckerRegistry::getMutableCheckersForCmdLineArg(StringRef CmdLineArg) { - - assert(std::is_sorted(Checkers.begin(), Checkers.end(), CheckerNameLT{}) && - "In order to efficiently gather checkers, this function expects them " - "to be already sorted!"); - - // Use a binary search to find the possible start of the package. - CheckerRegistry::CheckerInfo PackageInfo(nullptr, nullptr, CmdLineArg, "", - ""); - auto It = std::lower_bound(Checkers.begin(), Checkers.end(), PackageInfo, - CheckerNameLT{}); + auto It = binaryFind(Checkers, CmdLineArg); if (!isInPackage(*It, CmdLineArg)) return {Checkers.end(), Checkers.end()}; @@ -268,24 +281,18 @@ void CheckerRegistry::addChecker(Initial } } -void CheckerRegistry::addDependency(StringRef FullName, StringRef dependency) { - auto CheckerThatNeedsDeps = [&FullName](const CheckerInfo &Chk) { -return Chk.FullName == FullName; - }; - auto Dependency = [&dependency](const CheckerInfo &Chk) { -return Chk.FullName == dependency; - }; - - auto CheckerIt = llvm::find_if(Checkers, CheckerThatNeedsDeps); - assert(CheckerIt != Checkers.end() && +void CheckerRegistry::addDependency(StringRef FullName, StringRef Dependency) { + auto CheckerIt = binaryFind(Checkers, FullName); + assert(CheckerIt != Checkers.end() && CheckerIt->FullName == FullName && "Failed to find the checker while attempting to set up its " "dependencies!"); - auto DependencyIt = llvm::find_if(Checkers, Dependency); + auto DependencyIt = binaryFind(Checkers, Dependency); assert(DependencyIt != Checkers.end() && + DependencyIt->FullName == Dependency && "Failed to find the dependency of a checker!"); - Check
r358694 - [analyzer][NFC] Clang-format CheckerRegistry
Author: szelethus Date: Thu Apr 18 10:32:51 2019 New Revision: 358694 URL: http://llvm.org/viewvc/llvm-project?rev=358694&view=rev Log: [analyzer][NFC] Clang-format CheckerRegistry Differential Revision: https://reviews.llvm.org/D59458 Modified: cfe/trunk/include/clang/StaticAnalyzer/Frontend/CheckerRegistry.h cfe/trunk/lib/StaticAnalyzer/Frontend/CheckerRegistry.cpp Modified: cfe/trunk/include/clang/StaticAnalyzer/Frontend/CheckerRegistry.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Frontend/CheckerRegistry.h?rev=358694&r1=358693&r2=358694&view=diff == --- cfe/trunk/include/clang/StaticAnalyzer/Frontend/CheckerRegistry.h (original) +++ cfe/trunk/include/clang/StaticAnalyzer/Frontend/CheckerRegistry.h Thu Apr 18 10:32:51 2019 @@ -81,11 +81,10 @@ namespace ento { /// "core.builtin", or the full name "core.builtin.NoReturnFunctionChecker". class CheckerRegistry { public: - CheckerRegistry( - ArrayRef plugins, DiagnosticsEngine &diags, - AnalyzerOptions &AnOpts, const LangOptions &LangOpts, - ArrayRef> - checkerRegistrationFns = {}); + CheckerRegistry(ArrayRef plugins, DiagnosticsEngine &diags, + AnalyzerOptions &AnOpts, const LangOptions &LangOpts, + ArrayRef> + checkerRegistrationFns = {}); /// Initialization functions perform any necessary setup for a checker. /// They should include a call to CheckerManager::registerChecker. @@ -135,14 +134,11 @@ public: using StateFromCmdLine = CheckerInfo::StateFromCmdLine; private: - template - static void initializeManager(CheckerManager &mgr) { + template static void initializeManager(CheckerManager &mgr) { mgr.registerChecker(); } - - template - static bool returnTrue(const LangOptions &LO) { + template static bool returnTrue(const LangOptions &LO) { return true; } Modified: cfe/trunk/lib/StaticAnalyzer/Frontend/CheckerRegistry.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Frontend/CheckerRegistry.cpp?rev=358694&r1=358693&r2=358694&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Frontend/CheckerRegistry.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Frontend/CheckerRegistry.cpp Thu Apr 18 10:32:51 2019 @@ -11,8 +11,8 @@ #include "clang/Basic/LLVM.h" #include "clang/Frontend/FrontendDiagnostic.h" #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h" -#include "clang/StaticAnalyzer/Core/CheckerManager.h" #include "clang/StaticAnalyzer/Core/AnalyzerOptions.h" +#include "clang/StaticAnalyzer/Core/CheckerManager.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SetVector.h" #include "llvm/ADT/StringMap.h" @@ -39,8 +39,7 @@ static bool isCompatibleAPIVersion(const } namespace { -template -struct FullNameLT { +template struct FullNameLT { bool operator()(const T &Lhs, const T &Rhs) { return Lhs.FullName < Rhs.FullName; } @@ -76,13 +75,13 @@ CheckerRegistry::getMutableCheckersForCm "to be already sorted!"); // Use a binary search to find the possible start of the package. - CheckerRegistry::CheckerInfo - PackageInfo(nullptr, nullptr, CmdLineArg, "", ""); - auto It = std::lower_bound(Checkers.begin(), Checkers.end(), - PackageInfo, CheckerNameLT{}); + CheckerRegistry::CheckerInfo PackageInfo(nullptr, nullptr, CmdLineArg, "", + ""); + auto It = std::lower_bound(Checkers.begin(), Checkers.end(), PackageInfo, + CheckerNameLT{}); if (!isInPackage(*It, CmdLineArg)) -return { Checkers.end(), Checkers.end() }; +return {Checkers.end(), Checkers.end()}; // See how large the package is. // If the package doesn't exist, assume the option refers to a single @@ -94,15 +93,14 @@ CheckerRegistry::getMutableCheckersForCm if (PackageSize != PackageSizes.end()) Size = PackageSize->getValue(); - return { It, It + Size }; + return {It, It + Size}; } CheckerRegistry::CheckerRegistry( - ArrayRef Plugins, DiagnosticsEngine &Diags, - AnalyzerOptions &AnOpts, const LangOptions &LangOpts, - ArrayRef> - CheckerRegistrationFns) - : Diags(Diags), AnOpts(AnOpts), LangOpts(LangOpts) { +ArrayRef Plugins, DiagnosticsEngine &Diags, +AnalyzerOptions &AnOpts, const LangOptions &LangOpts, +ArrayRef> CheckerRegistrationFns) +: Diags(Diags), AnOpts(AnOpts), LangOpts(LangOpts) { // Register builtin checkers. #define GET_CHECKERS @@ -135,22 +133,21 @@ CheckerRegistry::CheckerRegistry( Diags.Report(diag::warn_incompatible_analyzer_plugin_api) << llvm::sys::path::filename(Plugin); Diags.Report(diag::note_incompatible_analyzer_plugin_api) - << CLANG_ANALYZER_API_VERSION_STRING - <
r358750 - [analyzer] Fix an assertion failure if plugins added dependencies
Author: szelethus Date: Fri Apr 19 04:01:35 2019 New Revision: 358750 URL: http://llvm.org/viewvc/llvm-project?rev=358750&view=rev Log: [analyzer] Fix an assertion failure if plugins added dependencies Ideally, there is no reason behind not being able to depend on checkers that come from a different plugin (or on builtin checkers) -- however, this is only possible if all checkers are added to the registry before resolving checker dependencies. Since I used a binary search in my addDependency method, this also resulted in an assertion failure (due to CheckerRegistry::Checkers not being sorted), since the function used by plugins to register their checkers (clang_registerCheckers) calls addDependency. This patch resolves this issue by only noting which dependencies have to established when addDependency is called, and resolves them at a later stage when no more checkers are added to the registry, by which point CheckerRegistry::Checkers is already sorted. Differential Revision: https://reviews.llvm.org/D59461 Modified: cfe/trunk/include/clang/StaticAnalyzer/Frontend/CheckerRegistry.h cfe/trunk/lib/StaticAnalyzer/Frontend/CheckerRegistry.cpp cfe/trunk/test/Analysis/checker-dependencies.c Modified: cfe/trunk/include/clang/StaticAnalyzer/Frontend/CheckerRegistry.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Frontend/CheckerRegistry.h?rev=358750&r1=358749&r2=358750&view=diff == --- cfe/trunk/include/clang/StaticAnalyzer/Frontend/CheckerRegistry.h (original) +++ cfe/trunk/include/clang/StaticAnalyzer/Frontend/CheckerRegistry.h Fri Apr 19 04:01:35 2019 @@ -195,6 +195,12 @@ private: CheckerInfoList Checkers; llvm::StringMap PackageSizes; + /// Contains all (Dependendent checker, Dependency) pairs. We need this, as + /// we'll resolve dependencies after all checkers were added first. + llvm::SmallVector, 0> Dependencies; + + void resolveDependencies(); + DiagnosticsEngine &Diags; AnalyzerOptions &AnOpts; const LangOptions &LangOpts; Modified: cfe/trunk/lib/StaticAnalyzer/Frontend/CheckerRegistry.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Frontend/CheckerRegistry.cpp?rev=358750&r1=358749&r2=358750&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Frontend/CheckerRegistry.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Frontend/CheckerRegistry.cpp Fri Apr 19 04:01:35 2019 @@ -177,6 +177,8 @@ CheckerRegistry::CheckerRegistry( #undef CHECKER_DEPENDENCY #undef GET_CHECKER_DEPENDENCIES + resolveDependencies(); + // Parse '-analyzer-checker' and '-analyzer-disable-checker' options from the // command line. for (const std::pair &Opt : AnOpts.CheckersControlList) { @@ -278,18 +280,26 @@ void CheckerRegistry::addChecker(Initial } } -void CheckerRegistry::addDependency(StringRef FullName, StringRef Dependency) { - auto CheckerIt = binaryFind(Checkers, FullName); - assert(CheckerIt != Checkers.end() && CheckerIt->FullName == FullName && - "Failed to find the checker while attempting to set up its " - "dependencies!"); - - auto DependencyIt = binaryFind(Checkers, Dependency); - assert(DependencyIt != Checkers.end() && - DependencyIt->FullName == Dependency && - "Failed to find the dependency of a checker!"); +void CheckerRegistry::resolveDependencies() { + for (const std::pair &Entry : Dependencies) { +auto CheckerIt = binaryFind(Checkers, Entry.first); +assert(CheckerIt != Checkers.end() && CheckerIt->FullName == Entry.first && + "Failed to find the checker while attempting to set up its " + "dependencies!"); + +auto DependencyIt = binaryFind(Checkers, Entry.second); +assert(DependencyIt != Checkers.end() && + DependencyIt->FullName == Entry.second && + "Failed to find the dependency of a checker!"); + +CheckerIt->Dependencies.emplace_back(&*DependencyIt); + } - CheckerIt->Dependencies.emplace_back(&*DependencyIt); + Dependencies.clear(); +} + +void CheckerRegistry::addDependency(StringRef FullName, StringRef Dependency) { + Dependencies.emplace_back(FullName, Dependency); } void CheckerRegistry::initializeManager(CheckerManager &CheckerMgr) const { Modified: cfe/trunk/test/Analysis/checker-dependencies.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/checker-dependencies.c?rev=358750&r1=358749&r2=358750&view=diff == --- cfe/trunk/test/Analysis/checker-dependencies.c (original) +++ cfe/trunk/test/Analysis/checker-dependencies.c Fri Apr 19 04:01:35 2019 @@ -1,3 +1,20 @@ // RUN: %clang_analyze_cc1 %s \ // RUN: -analyzer-checker=core \ // RUN: -analyzer-checker=nullability.NullReturnedFromNonnull + +// RUN: %clang_analyze_cc1 %s \ +// RUN: -analyzer
r358752 - [analyzer][NFC] Reimplement checker options
Author: szelethus Date: Fri Apr 19 05:32:10 2019 New Revision: 358752 URL: http://llvm.org/viewvc/llvm-project?rev=358752&view=rev Log: [analyzer][NFC] Reimplement checker options TL;DR: * Add checker and package options to the TableGen files * Added a new class called CmdLineOption, and both Package and Checker recieved a list field. * Added every existing checker and package option to Checkers.td. * The CheckerRegistry class * Received some comments to most of it's inline classes * Received the CmdLineOption and PackageInfo inline classes, a list of CmdLineOption was added to CheckerInfo and PackageInfo * Added addCheckerOption and addPackageOption * Added a new field called Packages, used in addPackageOptions, filled up in addPackage Detailed description: In the last couple months, a lot of effort was put into tightening the analyzer's command line interface. The main issue is that it's spectacularly easy to mess up a lenghty enough invocation of the analyzer, and the user was given no warnings or errors at all in that case. We can divide the effort of resolving this into several chapters: * Non-checker analyzer configurations: Gather every analyzer configuration into a dedicated file. Emit errors for non-existent configurations or incorrect values. Be able to list these configurations. Tighten AnalyzerOptions interface to disallow making such a mistake in the future. * Fix the "Checker Naming Bug" by reimplementing checker dependencies: When cplusplus.InnerPointer was enabled, it implicitly registered unix.Malloc, which implicitly registered some sort of a modeling checker from the CStringChecker family. This resulted in all of these checker objects recieving the name "cplusplus.InnerPointer", making AnalyzerOptions asking for the wrong checker options from the command line: cplusplus.InnerPointer:Optimisic istead of unix.Malloc:Optimistic. This was resolved by making CheckerRegistry responsible for checker dependency handling, instead of checkers themselves. * Checker options: (this patch included!) Same as the first item, but for checkers. (+ minor fixes here and there, and everything else that is yet to come) There were several issues regarding checker options, that non-checker configurations didn't suffer from: checker plugins are loaded runtime, and they could add new checkers and new options, meaning that unlike for non-checker configurations, we can't collect every checker option purely by generating code. Also, as seen from the "Checker Naming Bug" issue raised above, they are very rarely used in practice, and all sorts of skeletons fell out of the closet while working on this project. They were extremely problematic for users as well, purely because of how long they were. Consider the following monster of a checker option: alpha.cplusplus.UninitializedObject:CheckPointeeInitialization=false While we were able to verify whether the checker itself (the part before the colon) existed, any errors past that point were unreported, easily resulting in 7+ hours of analyses going to waste. This patch, similarly to how dependencies were reimplemented, uses TableGen to register checker options into Checkers.td, so that Checkers.inc now contains entries for both checker and package options. Using the preprocessor, Checkers.inc is converted into code in CheckerRegistry, adding every builtin (checkers and packages that have an entry in the Checkers.td file) checker and package option to the registry. The new addPackageOption and addCheckerOption functions expose the same functionality to statically-linked non-builtin and plugin checkers and packages as well. Emitting errors for incorrect user input, being able to list these options, and some other functionalies will land in later patches. Differential Revision: https://reviews.llvm.org/D57855 Added: cfe/trunk/test/Analysis/invalid-checker-option.c Modified: cfe/trunk/include/clang/Basic/DiagnosticCommonKinds.td cfe/trunk/include/clang/StaticAnalyzer/Checkers/CheckerBase.td cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td cfe/trunk/include/clang/StaticAnalyzer/Frontend/CheckerRegistry.h cfe/trunk/lib/Frontend/CompilerInvocation.cpp cfe/trunk/lib/StaticAnalyzer/Frontend/CheckerRegistry.cpp cfe/trunk/test/Analysis/disable-all-checks.c cfe/trunk/utils/TableGen/ClangSACheckersEmitter.cpp Modified: cfe/trunk/include/clang/Basic/DiagnosticCommonKinds.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticCommonKinds.td?rev=358752&r1=358751&r2=358752&view=diff == --- cfe/trunk/include/clang/Basic/DiagnosticCommonKinds.td (original) +++ cfe/trunk/include/clang/Basic/DiagnosticCommonKinds.td Fri Apr 19 05:32:10 2019 @@ -292,7 +292,7 @@ def err_omp_more_one_clause : Error< // Static Analyzer Core def err_unk
r358797 - [analyzer] Move UninitializedObjectChecker out of alpha
Author: szelethus Date: Fri Apr 19 16:33:50 2019 New Revision: 358797 URL: http://llvm.org/viewvc/llvm-project?rev=358797&view=rev Log: [analyzer] Move UninitializedObjectChecker out of alpha Moved UninitializedObjectChecker from the 'alpha.cplusplus' to the 'optin.cplusplus' package. Differential Revision: https://reviews.llvm.org/D58573 Modified: cfe/trunk/docs/analyzer/checkers.rst cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h cfe/trunk/test/Analysis/cxx-uninitialized-object-inheritance.cpp cfe/trunk/test/Analysis/cxx-uninitialized-object-no-dereference.cpp cfe/trunk/test/Analysis/cxx-uninitialized-object-notes-as-warnings.cpp cfe/trunk/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp cfe/trunk/test/Analysis/cxx-uninitialized-object-unguarded-access.cpp cfe/trunk/test/Analysis/cxx-uninitialized-object-unionlike-constructs.cpp cfe/trunk/test/Analysis/cxx-uninitialized-object.cpp cfe/trunk/test/Analysis/objcpp-uninitialized-object.mm cfe/trunk/www/analyzer/alpha_checks.html cfe/trunk/www/analyzer/available_checks.html Modified: cfe/trunk/docs/analyzer/checkers.rst URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/analyzer/checkers.rst?rev=358797&r1=358796&r2=358797&view=diff == --- cfe/trunk/docs/analyzer/checkers.rst (original) +++ cfe/trunk/docs/analyzer/checkers.rst Fri Apr 19 16:33:50 2019 @@ -339,6 +339,110 @@ optin Checkers for portability, performance or coding style specific rules. +optin.cplusplus.UninitializedObject (C++) +""" + +This checker reports uninitialized fields in objects created after a constructor +call. It doesn't only find direct uninitialized fields, but rather makes a deep +inspection of the object, analyzing all of it's fields subfields. +The checker regards inherited fields as direct fields, so one will recieve +warnings for uninitialized inherited data members as well. + +.. code-block:: cpp + + // With Pedantic and CheckPointeeInitialization set to true + + struct A { + struct B { + int x; // note: uninitialized field 'this->b.x' + // note: uninitialized field 'this->bptr->x' + int y; // note: uninitialized field 'this->b.y' + // note: uninitialized field 'this->bptr->y' + }; + int *iptr; // note: uninitialized pointer 'this->iptr' + B b; + B *bptr; + char *cptr; // note: uninitialized pointee 'this->cptr' + + A (B *bptr, char *cptr) : bptr(bptr), cptr(cptr) {} + }; + + void f() { + A::B b; + char c; + A a(&b, &c); // warning: 6 uninitialized fields + // after the constructor call + } + + // With Pedantic set to false and + // CheckPointeeInitialization set to true + // (every field is uninitialized) + + struct A { + struct B { + int x; + int y; + }; + int *iptr; + B b; + B *bptr; + char *cptr; + + A (B *bptr, char *cptr) : bptr(bptr), cptr(cptr) {} + }; + + void f() { + A::B b; + char c; + A a(&b, &c); // no warning + } + + // With Pedantic set to true and + // CheckPointeeInitialization set to false + // (pointees are regarded as initialized) + + struct A { + struct B { + int x; // note: uninitialized field 'this->b.x' + int y; // note: uninitialized field 'this->b.y' + }; + int *iptr; // note: uninitialized pointer 'this->iptr' + B b; + B *bptr; + char *cptr; + + A (B *bptr, char *cptr) : bptr(bptr), cptr(cptr) {} + }; + + void f() { + A::B b; + char c; + A a(&b, &c); // warning: 3 uninitialized fields + // after the constructor call + } + + +**Options** + +This checker has several options which can be set from command line (e.g. +``-analyzer-config optin.cplusplus.UninitializedObject:Pedantic=true``): + +* ``Pedantic`` (boolean). If to false, the checker won't emit warnings for + objects that don't have at least one initialized field. Defaults to false. + +* ``NotesAsWarnings`` (boolean). 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. *Defaults to false*. + +* ``CheckPointeeInitialization`` (boolean). 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. *Defaults to false*. + +* ``IgnoreRecordsWithField`` (string). If supplied, the checker will not analyze + structures that have a field with a name or type name that matches the given + pattern. *Defaults to ""*. + optin.cplusplus.VirtualCall (C++) " Check virtual function calls during construction or destruction. @@ -1383,102 +1487,6 @@ Method calls on a moved-from object and a.foo();// warn: method call on a 'moved-from' objec
r358877 - [analyzer][www] Moving MoveChecker out of alpha is no longer an open project.
Author: szelethus Date: Mon Apr 22 02:20:23 2019 New Revision: 358877 URL: http://llvm.org/viewvc/llvm-project?rev=358877&view=rev Log: [analyzer][www] Moving MoveChecker out of alpha is no longer an open project. Modified: cfe/trunk/www/analyzer/open_projects.html Modified: cfe/trunk/www/analyzer/open_projects.html URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/www/analyzer/open_projects.html?rev=358877&r1=358876&r2=358877&view=diff == --- cfe/trunk/www/analyzer/open_projects.html (original) +++ cfe/trunk/www/analyzer/open_projects.html Mon Apr 22 02:20:23 2019 @@ -48,16 +48,6 @@ mailing list to notify other members (Difficulty: Medium) - alpha.cplusplus.MisusedMovedObject -The checker emits a warning on objects which were used after -https://en.cppreference.com/w/cpp/utility/move";>move. -Currently it has an overly high false positive rate due to classes -which have a well-defined semantics for use-after-move. -This property does not hold for STL objects, but is often the case -for custom containers. - (Difficulty: Medium) - - alpha.unix.StreamChecker A SimpleStreamChecker has been presented in the Building a Checker in 24 Hours talk ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r359230 - [analyzer][UninitializedObjectChecker] PR41590: Regard _Atomic types as primitive
Author: szelethus Date: Thu Apr 25 13:00:51 2019 New Revision: 359230 URL: http://llvm.org/viewvc/llvm-project?rev=359230&view=rev Log: [analyzer][UninitializedObjectChecker] PR41590: Regard _Atomic types as primitive https://bugs.llvm.org/show_bug.cgi?id=41590 For the following code snippet, UninitializedObjectChecker crashed: struct MyAtomicInt { _Atomic(int) x; MyAtomicInt() {} }; void entry() { MyAtomicInt b; } The problem was that _Atomic types were not regular records, unions, dereferencable or primitive, making the checker hit the llvm_unreachable at lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp:347. The solution is to regard these types as primitive as well. The test case shows that with this addition, not only are we able to get rid of the crash, but we can identify x as uninitialized. Differential Revision: https://reviews.llvm.org/D61106 Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h cfe/trunk/test/Analysis/cxx-uninitialized-object.cpp Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h?rev=359230&r1=359229&r2=359230&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h Thu Apr 25 13:00:51 2019 @@ -324,7 +324,7 @@ private: inline bool isPrimitiveType(const QualType &T) { return T->isBuiltinType() || T->isEnumeralType() || T->isMemberPointerType() || T->isBlockPointerType() || - T->isFunctionType(); + T->isFunctionType() || T->isAtomicType(); } inline bool isDereferencableType(const QualType &T) { Modified: cfe/trunk/test/Analysis/cxx-uninitialized-object.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/cxx-uninitialized-object.cpp?rev=359230&r1=359229&r2=359230&view=diff == --- cfe/trunk/test/Analysis/cxx-uninitialized-object.cpp (original) +++ cfe/trunk/test/Analysis/cxx-uninitialized-object.cpp Thu Apr 25 13:00:51 2019 @@ -1130,3 +1130,18 @@ void fCXX11MemberInitTest2() { // TODO: we'd expect the warning: {{2 uninitializeds field}} CXX11MemberInitTest2(); // no-warning } + +//===--===// +// _Atomic tests. +//===--===// + +struct MyAtomicInt { + _Atomic(int) x; // expected-note{{uninitialized field 'this->x'}} + int dontGetFilteredByNonPedanticMode = 0; + + MyAtomicInt() {} // expected-warning{{1 uninitialized field}} +}; + +void entry() { + MyAtomicInt b; +} ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r359539 - [analyzer][UninitializedObjectChecker] PR41611: Regard vector types as primitive
Author: szelethus Date: Tue Apr 30 01:47:56 2019 New Revision: 359539 URL: http://llvm.org/viewvc/llvm-project?rev=359539&view=rev Log: [analyzer][UninitializedObjectChecker] PR41611: Regard vector types as primitive https://bugs.llvm.org/show_bug.cgi?id=41611 Similarly to D61106, the checker ran over an llvm_unreachable for vector types: struct VectorSizeLong { VectorSizeLong() {} __attribute__((__vector_size__(16))) long x; }; void __vector_size__LongTest() { VectorSizeLong v; } Since, according to my short research, "The vector_size attribute is only applicable to integral and float scalars, although arrays, pointers, and function return values are allowed in conjunction with this construct." [src: https://gcc.gnu.org/onlinedocs/gcc-4.6.1/gcc/Vector-Extensions.html#Vector-Extensions] vector types are safe to regard as primitive. Differential Revision: https://reviews.llvm.org/D61246 Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h cfe/trunk/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp cfe/trunk/test/Analysis/cxx-uninitialized-object.cpp Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h?rev=359539&r1=359538&r2=359539&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h Tue Apr 30 01:47:56 2019 @@ -324,7 +324,8 @@ private: inline bool isPrimitiveType(const QualType &T) { return T->isBuiltinType() || T->isEnumeralType() || T->isMemberPointerType() || T->isBlockPointerType() || - T->isFunctionType() || T->isAtomicType(); + T->isFunctionType() || T->isAtomicType() || + T->isVectorType(); } inline bool isDereferencableType(const QualType &T) { Modified: cfe/trunk/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp?rev=359539&r1=359538&r2=359539&view=diff == --- cfe/trunk/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp (original) +++ cfe/trunk/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp Tue Apr 30 01:47:56 2019 @@ -256,6 +256,29 @@ void fCharPointerTest() { CharPointerTest(); } +struct VectorSizePointer { + VectorSizePointer() {} // expected-warning{{1 uninitialized field}} + __attribute__((__vector_size__(8))) int *x; // expected-note{{uninitialized pointer 'this->x'}} + int dontGetFilteredByNonPedanticMode = 0; +}; + +void __vector_size__PointerTest() { + VectorSizePointer v; +} + +struct VectorSizePointee { + using MyVectorType = __attribute__((__vector_size__(8))) int; + MyVectorType *x; + + VectorSizePointee(decltype(x) x) : x(x) {} +}; + +void __vector_size__PointeeTest() { + VectorSizePointee::MyVectorType i; + // TODO: Report v.x's pointee. + VectorSizePointee v(&i); +} + struct CyclicPointerTest1 { int *ptr; // expected-note{{object references itself 'this->ptr'}} int dontGetFilteredByNonPedanticMode = 0; Modified: cfe/trunk/test/Analysis/cxx-uninitialized-object.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/cxx-uninitialized-object.cpp?rev=359539&r1=359538&r2=359539&view=diff == --- cfe/trunk/test/Analysis/cxx-uninitialized-object.cpp (original) +++ cfe/trunk/test/Analysis/cxx-uninitialized-object.cpp Tue Apr 30 01:47:56 2019 @@ -1132,7 +1132,7 @@ void fCXX11MemberInitTest2() { } //===--===// -// _Atomic tests. +// "Esoteric" primitive type tests. //===--===// struct MyAtomicInt { @@ -1142,6 +1142,17 @@ struct MyAtomicInt { MyAtomicInt() {} // expected-warning{{1 uninitialized field}} }; -void entry() { +void _AtomicTest() { MyAtomicInt b; } + +struct VectorSizeLong { + VectorSizeLong() {} + __attribute__((__vector_size__(16))) long x; +}; + +void __vector_size__LongTest() { + // TODO: Warn for v.x. + VectorSizeLong v; + v.x[0] = 0; +} ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r359720 - [analyzer] Don't display implementation checkers under -analyzer-checker-help, but do under the new flag -analyzer-checker-help-hidden
Author: szelethus Date: Wed May 1 12:56:47 2019 New Revision: 359720 URL: http://llvm.org/viewvc/llvm-project?rev=359720&view=rev Log: [analyzer] Don't display implementation checkers under -analyzer-checker-help, but do under the new flag -analyzer-checker-help-hidden During my work on analyzer dependencies, I created a great amount of new checkers that emitted no diagnostics at all, and were purely modeling some function or another. However, the user shouldn't really disable/enable these by hand, hence this patch, which hides these by default. I intentionally chose not to hide alpha checkers, because they have a scary enough name, in my opinion, to cause no surprise when they emit false positives or cause crashes. The patch introduces the Hidden bit into the TableGen files (you may remember it before I removed it in D53995), and checkers that are either marked as hidden, or are in a package that is marked hidden won't be displayed under -analyzer-checker-help. -analyzer-checker-help-hidden, a new flag meant for developers only, displays the full list. Differential Revision: https://reviews.llvm.org/D60925 Added: cfe/trunk/test/Analysis/show-checker-list.c Modified: cfe/trunk/include/clang/Driver/CC1Options.td cfe/trunk/include/clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h cfe/trunk/include/clang/StaticAnalyzer/Checkers/CheckerBase.td cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h cfe/trunk/include/clang/StaticAnalyzer/Frontend/CheckerRegistry.h cfe/trunk/lib/Frontend/CompilerInvocation.cpp cfe/trunk/lib/FrontendTool/ExecuteCompilerInvocation.cpp cfe/trunk/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp cfe/trunk/lib/StaticAnalyzer/Core/SarifDiagnostics.cpp cfe/trunk/lib/StaticAnalyzer/Frontend/CheckerRegistry.cpp cfe/trunk/utils/TableGen/ClangSACheckersEmitter.cpp Modified: cfe/trunk/include/clang/Driver/CC1Options.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/CC1Options.td?rev=359720&r1=359719&r2=359720&view=diff == --- cfe/trunk/include/clang/Driver/CC1Options.td (original) +++ cfe/trunk/include/clang/Driver/CC1Options.td Wed May 1 12:56:47 2019 @@ -107,7 +107,7 @@ def analyzer_checker : Separate<["-"], " ValuesCode<[{ const char *Values = #define GET_CHECKERS -#define CHECKER(FULLNAME, CLASS, HT, DOC_URI) FULLNAME "," +#define CHECKER(FULLNAME, CLASS, HT, DOC_URI, IS_HIDDEN) FULLNAME "," #include "clang/StaticAnalyzer/Checkers/Checkers.inc" #undef GET_CHECKERS #define GET_PACKAGES @@ -130,6 +130,10 @@ def analyzer_disable_all_checks : Flag<[ def analyzer_checker_help : Flag<["-"], "analyzer-checker-help">, HelpText<"Display the list of analyzer checkers that are available">; +def analyzer_checker_help_hidden : Flag<["-"], "analyzer-checker-help-hidden">, + HelpText<"Display the list of analyzer checkers that are available, " + "including modeling checkers">; + def analyzer_config_help : Flag<["-"], "analyzer-config-help">, HelpText<"Display the list of -analyzer-config options">; Modified: cfe/trunk/include/clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h?rev=359720&r1=359719&r2=359720&view=diff == --- cfe/trunk/include/clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h (original) +++ cfe/trunk/include/clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h Wed May 1 12:56:47 2019 @@ -26,7 +26,7 @@ class CheckerManager; class CheckerRegistry; #define GET_CHECKERS -#define CHECKER(FULLNAME, CLASS, HELPTEXT, DOC_URI) \ +#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" Modified: cfe/trunk/include/clang/StaticAnalyzer/Checkers/CheckerBase.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Checkers/CheckerBase.td?rev=359720&r1=359719&r2=359720&view=diff == --- cfe/trunk/include/clang/StaticAnalyzer/Checkers/CheckerBase.td (original) +++ cfe/trunk/include/clang/StaticAnalyzer/Checkers/CheckerBase.td Wed May 1 12:56:47 2019 @@ -49,6 +49,7 @@ class Package { // This field is optional. list PackageOptions; Package ParentPackage; + bit Hidden = 0; } /// Describes a 'super' package that holds another package inside it. This is @@ -91,6 +92,7 @@ class Checker { list Dependenc
r359727 - [analyzer] Fix buildbot failures caused by a forgotten initialization
Author: szelethus Date: Wed May 1 14:09:32 2019 New Revision: 359727 URL: http://llvm.org/viewvc/llvm-project?rev=359727&view=rev Log: [analyzer] Fix buildbot failures caused by a forgotten initialization Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h?rev=359727&r1=359726&r2=359727&view=diff == --- cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h (original) +++ cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h Wed May 1 14:09:32 2019 @@ -261,11 +261,12 @@ 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) { +ShowCheckerHelpHidden(false), ShowEnabledCheckerList(false), +ShowConfigOptionsList(false), AnalyzeAll(false), +AnalyzerDisplayProgress(false), AnalyzeNestedBlocks(false), +eagerlyAssumeBinOpBifurcation(false), TrimGraph(false), +visualizeExplodedGraphWithGraphViz(false), UnoptimizedCFG(false), +PrintStats(false), NoRetryExhausted(false) { llvm::sort(AnalyzerConfigCmdFlags); } ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r359998 - [analyzer][UninitializedObjectChecker] PR41741: Regard all scalar types as primitive.
Author: szelethus Date: Sun May 5 12:42:33 2019 New Revision: 359998 URL: http://llvm.org/viewvc/llvm-project?rev=359998&view=rev Log: [analyzer][UninitializedObjectChecker] PR41741: Regard all scalar types as primitive. https://bugs.llvm.org/show_bug.cgi?id=41741 Pretty much the same as D61246 and D61106, this time for __complex__ types. Upon further investigation, I realized that we should regard all types Type::isScalarType returns true for as primitive, so I merged isMemberPointerType(), isBlockPointerType() and isAnyComplexType()` into that instead. I also stumbled across yet another bug, https://bugs.llvm.org/show_bug.cgi?id=41753, but it seems to be unrelated to this checker. Differential Revision: https://reviews.llvm.org/D61569 Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h cfe/trunk/test/Analysis/cxx-uninitialized-object.cpp Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h?rev=359998&r1=359997&r2=359998&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h Sun May 5 12:42:33 2019 @@ -323,9 +323,8 @@ private: /// needs to be analyzed as much as checking whether their value is undefined. inline bool isPrimitiveType(const QualType &T) { return T->isBuiltinType() || T->isEnumeralType() || - T->isMemberPointerType() || T->isBlockPointerType() || T->isFunctionType() || T->isAtomicType() || - T->isVectorType(); + T->isVectorType() || T->isScalarType(); } inline bool isDereferencableType(const QualType &T) { Modified: cfe/trunk/test/Analysis/cxx-uninitialized-object.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/cxx-uninitialized-object.cpp?rev=359998&r1=359997&r2=359998&view=diff == --- cfe/trunk/test/Analysis/cxx-uninitialized-object.cpp (original) +++ cfe/trunk/test/Analysis/cxx-uninitialized-object.cpp Sun May 5 12:42:33 2019 @@ -1,11 +1,15 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=core,optin.cplusplus.UninitializedObject \ +// RUN: %clang_analyze_cc1 -std=c++14 -verify %s \ +// RUN: -analyzer-checker=core \ +// RUN: -analyzer-checker=optin.cplusplus.UninitializedObject \ // RUN: -analyzer-config optin.cplusplus.UninitializedObject:Pedantic=true -DPEDANTIC \ -// RUN: -analyzer-config optin.cplusplus.UninitializedObject:CheckPointeeInitialization=true \ -// RUN: -std=c++14 -verify %s +// RUN: -analyzer-config \ +// RUN: optin.cplusplus.UninitializedObject:CheckPointeeInitialization=true -// RUN: %clang_analyze_cc1 -analyzer-checker=core,optin.cplusplus.UninitializedObject \ -// RUN: -analyzer-config optin.cplusplus.UninitializedObject:CheckPointeeInitialization=true \ -// RUN: -std=c++14 -verify %s +// RUN: %clang_analyze_cc1 -std=c++14 -verify %s \ +// RUN: -analyzer-checker=core \ +// RUN: -analyzer-checker=optin.cplusplus.UninitializedObject \ +// RUN: -analyzer-config \ +// RUN: optin.cplusplus.UninitializedObject:CheckPointeeInitialization=true //===--===// // Default constructor test. @@ -1156,3 +1160,28 @@ void __vector_size__LongTest() { VectorSizeLong v; v.x[0] = 0; } + +struct ComplexUninitTest { + ComplexUninitTest() {} + __complex__ float x; + __complex__ int y; +}; + +// FIXME: Currently this causes (unrelated to this checker) an assertion +// failure. +// +//struct ComplexInitTest { +// ComplexInitTest() { +//x = {1.0f, 1.0f}; +//y = {1, 1}; +// } +// __complex__ float x; +// __complex__ int y; +//}; + +void fComplexTest() { +// ComplexInitTest x; + + // TODO: we should emit a warning for x2.x and x2.y. + ComplexUninitTest x2; +} ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r342834 - [analyzer][UninitializedObjectChecker] Using the new const methods of ImmutableList
Author: szelethus Date: Sun Sep 23 02:16:27 2018 New Revision: 342834 URL: http://llvm.org/viewvc/llvm-project?rev=342834&view=rev Log: [analyzer][UninitializedObjectChecker] Using the new const methods of ImmutableList Differential Revision: https://reviews.llvm.org/D51886 Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h?rev=342834&r1=342833&r2=342834&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h Sun Sep 23 02:16:27 2018 @@ -152,7 +152,6 @@ std::string getVariableName(const FieldD /// functions such as add() and replaceHead(). class FieldChainInfo { public: - using FieldChainImpl = llvm::ImmutableListImpl; using FieldChain = llvm::ImmutableList; private: @@ -179,8 +178,8 @@ public: bool contains(const FieldRegion *FR) const; bool isEmpty() const { return Chain.isEmpty(); } - const FieldRegion *getUninitRegion() const; - const FieldNode &getHead() { return Chain.getHead(); } + const FieldNode &getHead() const { return Chain.getHead(); } + const FieldRegion *getUninitRegion() const { return getHead().getRegion(); } void printNoteMsg(llvm::raw_ostream &Out) const; }; Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp?rev=342834&r1=342833&r2=342834&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp Sun Sep 23 02:16:27 2018 @@ -339,14 +339,6 @@ bool FindUninitializedFields::isPrimitiv // Methods for FieldChainInfo. //===--===// -const FieldRegion *FieldChainInfo::getUninitRegion() const { - assert(!Chain.isEmpty() && "Empty fieldchain!"); - - // ImmutableList::getHead() isn't a const method, hence the not too nice - // implementation. - return (*Chain.begin()).getRegion(); -} - bool FieldChainInfo::contains(const FieldRegion *FR) const { for (const FieldNode &Node : Chain) { if (Node.isSameRegion(FR)) @@ -360,7 +352,7 @@ bool FieldChainInfo::contains(const Fiel /// recursive function to print the fieldchain correctly. The last element in /// the chain is to be printed by `FieldChainInfo::print`. static void printTail(llvm::raw_ostream &Out, - const FieldChainInfo::FieldChainImpl *L); + const FieldChainInfo::FieldChain L); // FIXME: This function constructs an incorrect string in the following case: // @@ -379,8 +371,7 @@ void FieldChainInfo::printNoteMsg(llvm:: if (Chain.isEmpty()) return; - const FieldChainImpl *L = Chain.getInternalPointer(); - const FieldNode &LastField = L->getHead(); + const FieldNode &LastField = getHead(); LastField.printNoteMsg(Out); Out << '\''; @@ -389,20 +380,20 @@ void FieldChainInfo::printNoteMsg(llvm:: Node.printPrefix(Out); Out << "this->"; - printTail(Out, L->getTail()); + printTail(Out, Chain.getTail()); LastField.printNode(Out); Out << '\''; } static void printTail(llvm::raw_ostream &Out, - const FieldChainInfo::FieldChainImpl *L) { - if (!L) + const FieldChainInfo::FieldChain L) { + if (L.isEmpty()) return; - printTail(Out, L->getTail()); + printTail(Out, L.getTail()); - L->getHead().printNode(Out); - L->getHead().printSeparator(Out); + L.getHead().printNode(Out); + L.getHead().printSeparator(Out); } //===--===// ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r343204 - [Lex] TokenConcatenation now takes const Preprocessor
Author: szelethus Date: Thu Sep 27 05:40:16 2018 New Revision: 343204 URL: http://llvm.org/viewvc/llvm-project?rev=343204&view=rev Log: [Lex] TokenConcatenation now takes const Preprocessor Differential Revision: https://reviews.llvm.org/D52502 Modified: cfe/trunk/include/clang/Lex/TokenConcatenation.h cfe/trunk/lib/Lex/TokenConcatenation.cpp cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h Modified: cfe/trunk/include/clang/Lex/TokenConcatenation.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Lex/TokenConcatenation.h?rev=343204&r1=343203&r2=343204&view=diff == --- cfe/trunk/include/clang/Lex/TokenConcatenation.h (original) +++ cfe/trunk/include/clang/Lex/TokenConcatenation.h Thu Sep 27 05:40:16 2018 @@ -29,7 +29,7 @@ namespace clang { /// and ")" next to each other is safe. /// class TokenConcatenation { -Preprocessor &PP; +const Preprocessor &PP; enum AvoidConcatInfo { /// By default, a token never needs to avoid concatenation. Most tokens @@ -56,7 +56,7 @@ namespace clang { /// method. char TokenInfo[tok::NUM_TOKENS]; public: -TokenConcatenation(Preprocessor &PP); +TokenConcatenation(const Preprocessor &PP); bool AvoidConcat(const Token &PrevPrevTok, const Token &PrevTok, Modified: cfe/trunk/lib/Lex/TokenConcatenation.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/TokenConcatenation.cpp?rev=343204&r1=343203&r2=343204&view=diff == --- cfe/trunk/lib/Lex/TokenConcatenation.cpp (original) +++ cfe/trunk/lib/Lex/TokenConcatenation.cpp Thu Sep 27 05:40:16 2018 @@ -67,7 +67,7 @@ bool TokenConcatenation::IsIdentifierStr return IsStringPrefix(StringRef(PP.getSpelling(Tok)), LangOpts.CPlusPlus11); } -TokenConcatenation::TokenConcatenation(Preprocessor &pp) : PP(pp) { +TokenConcatenation::TokenConcatenation(const Preprocessor &pp) : PP(pp) { memset(TokenInfo, 0, sizeof(TokenInfo)); // These tokens have custom code in AvoidConcat. @@ -126,7 +126,7 @@ TokenConcatenation::TokenConcatenation(P /// GetFirstChar - Get the first character of the token \arg Tok, /// avoiding calls to getSpelling where possible. -static char GetFirstChar(Preprocessor &PP, const Token &Tok) { +static char GetFirstChar(const Preprocessor &PP, const Token &Tok) { if (IdentifierInfo *II = Tok.getIdentifierInfo()) { // Avoid spelling identifiers, the most common form of token. return II->getNameStart()[0]; Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h?rev=343204&r1=343203&r2=343204&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h Thu Sep 27 05:40:16 2018 @@ -79,9 +79,9 @@ class FieldNode { protected: const FieldRegion *FR; - /// FieldNodes are never meant to be created on the heap, see - /// FindUninitializedFields::addFieldToUninits(). - /* non-virtual */ ~FieldNode() = default; + // TODO: This destructor shouldn't be virtual, but breaks buildbots with + // -Werror -Wnon-virtual-dtor. + virtual ~FieldNode() = default; public: FieldNode(const FieldRegion *FR) : FR(FR) {} ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r343205 - Revert untintentionally commited changes
Author: szelethus Date: Thu Sep 27 05:46:37 2018 New Revision: 343205 URL: http://llvm.org/viewvc/llvm-project?rev=343205&view=rev Log: Revert untintentionally commited changes Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h?rev=343205&r1=343204&r2=343205&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h Thu Sep 27 05:46:37 2018 @@ -79,9 +79,9 @@ class FieldNode { protected: const FieldRegion *FR; - // TODO: This destructor shouldn't be virtual, but breaks buildbots with - // -Werror -Wnon-virtual-dtor. - virtual ~FieldNode() = default; + /// FieldNodes are never meant to be created on the heap, see + /// FindUninitializedFields::addFieldToUninits(). + /* non-virtual */ ~FieldNode() = default; public: FieldNode(const FieldRegion *FR) : FR(FR) {} ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r343511 - [analyzer][NFC] Refactor functions in PlistDiagnostics to take Preproc as parameter
Author: szelethus Date: Mon Oct 1 11:11:51 2018 New Revision: 343511 URL: http://llvm.org/viewvc/llvm-project?rev=343511&view=rev Log: [analyzer][NFC] Refactor functions in PlistDiagnostics to take Preproc as parameter This is patch is a preparation for the proposed inclusion of macro expansions in the plist output. Differential Revision: https://reviews.llvm.org/D52735 Modified: cfe/trunk/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp Modified: cfe/trunk/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp?rev=343511&r1=343510&r2=343511&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp Mon Oct 1 11:11:51 2018 @@ -31,13 +31,13 @@ using namespace markup; namespace { class PlistDiagnostics : public PathDiagnosticConsumer { const std::string OutputFile; -const LangOptions &LangOpts; +const Preprocessor &PP; const bool SupportsCrossFileDiagnostics; const bool SerializeStatistics; public: PlistDiagnostics(AnalyzerOptions &AnalyzerOpts, const std::string& prefix, - const LangOptions &LangOpts, + const Preprocessor &PP, bool supportsMultipleFiles); ~PlistDiagnostics() override {} @@ -61,10 +61,9 @@ namespace { PlistDiagnostics::PlistDiagnostics(AnalyzerOptions &AnalyzerOpts, const std::string& output, - const LangOptions &LO, + const Preprocessor &PP, bool supportsMultipleFiles) - : OutputFile(output), -LangOpts(LO), + : OutputFile(output), PP(PP), SupportsCrossFileDiagnostics(supportsMultipleFiles), SerializeStatistics(AnalyzerOpts.shouldSerializeStats()) {} @@ -72,23 +71,20 @@ void ento::createPlistDiagnosticConsumer PathDiagnosticConsumers &C, const std::string& s, const Preprocessor &PP) { - C.push_back(new PlistDiagnostics(AnalyzerOpts, s, - PP.getLangOpts(), false)); + C.push_back(new PlistDiagnostics(AnalyzerOpts, s, PP, false)); } void ento::createPlistMultiFileDiagnosticConsumer(AnalyzerOptions &AnalyzerOpts, PathDiagnosticConsumers &C, const std::string &s, const Preprocessor &PP) { - C.push_back(new PlistDiagnostics(AnalyzerOpts, s, - PP.getLangOpts(), true)); + C.push_back(new PlistDiagnostics(AnalyzerOpts, s, PP, true)); } static void EmitRanges(raw_ostream &o, const ArrayRef Ranges, const FIDMap& FM, - const SourceManager &SM, - const LangOptions &LangOpts, + const Preprocessor &PP, unsigned indent) { if (Ranges.empty()) @@ -97,6 +93,10 @@ static void EmitRanges(raw_ostream &o, Indent(o, indent) << "ranges\n"; Indent(o, indent) << "\n"; ++indent; + + const SourceManager &SM = PP.getSourceManager(); + const LangOptions &LangOpts = PP.getLangOpts(); + for (auto &R : Ranges) EmitRange(o, SM, Lexer::getAsCharRange(SM.getExpansionRange(R), SM, LangOpts), @@ -122,10 +122,12 @@ static void EmitMessage(raw_ostream &o, static void ReportControlFlow(raw_ostream &o, const PathDiagnosticControlFlowPiece& P, const FIDMap& FM, - const SourceManager &SM, - const LangOptions &LangOpts, + const Preprocessor &PP, unsigned indent) { + const SourceManager &SM = PP.getSourceManager(); + const LangOptions &LangOpts = PP.getLangOpts(); + Indent(o, indent) << "\n"; ++indent; @@ -175,12 +177,13 @@ static void ReportControlFlow(raw_ostrea static void ReportEvent(raw_ostream &o, const PathDiagnosticEventPiece& P, const FIDMap& FM, -const SourceManager &SM, -const LangOptions &LangOpts, +const Preprocessor &PP, unsigned indent, unsigned depth, bool isKeyEvent = false) { + const SourceManager &SM = PP.getSourceManager(); + Indent(o, indent) << "\n"; ++indent; @@ -198,7 +201,7 @@ static void ReportEvent(raw_ostream &o, // Output the ranges (if any). ArrayRef Ranges = P.getRange
r343620 - [analyzer][NFC] Refactor functions in PlistDiagnostics to take AnalyzerOptions as parameter
Author: szelethus Date: Tue Oct 2 12:27:34 2018 New Revision: 343620 URL: http://llvm.org/viewvc/llvm-project?rev=343620&view=rev Log: [analyzer][NFC] Refactor functions in PlistDiagnostics to take AnalyzerOptions as parameter I intend to add a new flag macro-expnasions-as-events, and unfortunately I'll only be able to convert the macro piece into an event one once I'm about to emit it, due to the lack of an avaible Preprocessor object in the BugReporter. Differential Revision: https://reviews.llvm.org/D52787 Modified: cfe/trunk/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp Modified: cfe/trunk/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp?rev=343620&r1=343619&r2=343620&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp Tue Oct 2 12:27:34 2018 @@ -32,8 +32,8 @@ namespace { class PlistDiagnostics : public PathDiagnosticConsumer { const std::string OutputFile; const Preprocessor &PP; +AnalyzerOptions &AnOpts; const bool SupportsCrossFileDiagnostics; -const bool SerializeStatistics; public: PlistDiagnostics(AnalyzerOptions &AnalyzerOpts, const std::string& prefix, @@ -63,22 +63,23 @@ PlistDiagnostics::PlistDiagnostics(Analy const std::string& output, const Preprocessor &PP, bool supportsMultipleFiles) - : OutputFile(output), PP(PP), -SupportsCrossFileDiagnostics(supportsMultipleFiles), -SerializeStatistics(AnalyzerOpts.shouldSerializeStats()) {} + : OutputFile(output), PP(PP), AnOpts(AnalyzerOpts), +SupportsCrossFileDiagnostics(supportsMultipleFiles) {} void ento::createPlistDiagnosticConsumer(AnalyzerOptions &AnalyzerOpts, PathDiagnosticConsumers &C, const std::string& s, const Preprocessor &PP) { - C.push_back(new PlistDiagnostics(AnalyzerOpts, s, PP, false)); + C.push_back(new PlistDiagnostics(AnalyzerOpts, s, PP, + /*supportsMultipleFiles*/ false)); } void ento::createPlistMultiFileDiagnosticConsumer(AnalyzerOptions &AnalyzerOpts, PathDiagnosticConsumers &C, const std::string &s, const Preprocessor &PP) { - C.push_back(new PlistDiagnostics(AnalyzerOpts, s, PP, true)); + C.push_back(new PlistDiagnostics(AnalyzerOpts, s, PP, + /*supportsMultipleFiles*/ true)); } static void EmitRanges(raw_ostream &o, @@ -175,7 +176,8 @@ static void ReportControlFlow(raw_ostrea Indent(o, indent) << "\n"; } -static void ReportEvent(raw_ostream &o, const PathDiagnosticEventPiece& P, +static void ReportEvent(raw_ostream &o, +const PathDiagnosticEventPiece& P, const FIDMap& FM, const Preprocessor &PP, unsigned indent, @@ -219,6 +221,7 @@ static void ReportPiece(raw_ostream &o, const PathDiagnosticPiece &P, const FIDMap& FM, const Preprocessor &PP, +AnalyzerOptions &AnOpts, unsigned indent, unsigned depth, bool includeControlFlow, @@ -228,28 +231,29 @@ static void ReportCall(raw_ostream &o, const PathDiagnosticCallPiece &P, const FIDMap& FM, const Preprocessor &PP, + AnalyzerOptions &AnOpts, unsigned indent, unsigned depth) { if (auto callEnter = P.getCallEnterEvent()) -ReportPiece(o, *callEnter, FM, PP, indent, depth, +ReportPiece(o, *callEnter, FM, PP, AnOpts, indent, depth, /*includeControlFlow*/ true, P.isLastInMainSourceFile()); ++depth; if (auto callEnterWithinCaller = P.getCallEnterWithinCallerEvent()) -ReportPiece(o, *callEnterWithinCaller, FM, PP, indent, depth, +ReportPiece(o, *callEnterWithinCaller, FM, PP, AnOpts, indent, depth, /*includeControlFlow*/ true); for (PathPieces::const_iterator I = P.path.begin(), E = P.path.end();I!=E;++I) -ReportPiece(o, **I, FM, PP, indent, depth, +ReportPiece(o, **I, FM, PP, AnOpts, indent, depth, /*includeControlFlow*/ true); --depth; if (auto callExit = P.getCallExitEvent()) -ReportPiece(o, *callExit, FM, PP, indent, depth, +ReportPiece(o, *callExit, FM, PP
r344031 - [analyzer][www] Add more useful links
Author: szelethus Date: Tue Oct 9 03:05:08 2018 New Revision: 344031 URL: http://llvm.org/viewvc/llvm-project?rev=344031&view=rev Log: [analyzer][www] Add more useful links Differential Revision: https://reviews.llvm.org/D52993 Modified: cfe/trunk/www/analyzer/checker_dev_manual.html Modified: cfe/trunk/www/analyzer/checker_dev_manual.html URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/www/analyzer/checker_dev_manual.html?rev=344031&r1=344030&r2=344031&view=diff == --- cfe/trunk/www/analyzer/checker_dev_manual.html (original) +++ cfe/trunk/www/analyzer/checker_dev_manual.html Tue Oct 9 03:05:08 2018 @@ -681,28 +681,37 @@ Here are some additional resources that Static Analyzer: +http://lcs.ios.ac.cn/~xuzb/canalyze/memmodel.pdf";>Xu, Zhongxing & +Kremenek, Ted & Zhang, Jian. (2010). A Memory Model for Static Analysis of C +Programs. +https://github.com/llvm-mirror/clang/blob/master/lib/StaticAnalyzer/README.txt";> +The Clang Static Analyzer README +https://github.com/llvm-mirror/clang/blob/master/docs/analyzer/RegionStore.txt";> +Documentation for how the Store works +https://github.com/llvm-mirror/clang/blob/master/docs/analyzer/IPA.txt";> +Documentation about inlining + The "Building a Checker in 24 hours" presentation given at the http://llvm.org/devmtg/2012-11";>November 2012 LLVM Developer's +meeting. Describes the construction of SimpleStreamChecker. http://llvm.org/devmtg/2012-11/Zaks-Rose-Checker24Hours.pdf";>Slides +and https://youtu.be/kdxlsP5QVPw";>video +are available. + +https://github.com/haoNoQ/clang-analyzer-guide/releases/download/v0.1/clang-analyzer-guide-v0.1.pdf";> +Artem Degrachev: Clang Static Analyzer: A Checker Developer's Guide + (reading the previous items first might be a good idea) +The list of Implicit Checkers http://clang.llvm.org/doxygen";>Clang doxygen. Contains up-to-date documentation about the APIs available in Clang. Relevant entries have been linked throughout this page. Also of use is the http://llvm.org/doxygen";>LLVM doxygen, when dealing with classes -from LLVM. +from LLVM. The http://lists.llvm.org/mailman/listinfo/cfe-dev";> cfe-dev mailing list. This is the primary mailing list used for discussion of Clang development (including static code analysis). The http://lists.llvm.org/pipermail/cfe-dev";>archive also contains -a lot of information. - The "Building a Checker in 24 hours" presentation given at the http://llvm.org/devmtg/2012-11";>November 2012 LLVM Developer's -meeting. Describes the construction of SimpleStreamChecker. http://llvm.org/devmtg/2012-11/Zaks-Rose-Checker24Hours.pdf";>Slides -and https://youtu.be/kdxlsP5QVPw";>video -are available. - - -Useful Links - -The list of Implicit Checkers +a lot of information. ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r352959 - [analyzer][UninitializedObjectChecker] New flag to ignore guarded uninitialized fields
Author: szelethus Date: Sat Feb 2 06:50:04 2019 New Revision: 352959 URL: http://llvm.org/viewvc/llvm-project?rev=352959&view=rev Log: [analyzer][UninitializedObjectChecker] New flag to ignore guarded uninitialized fields This patch is an implementation of the ideas discussed on the mailing list[1]. The idea is to somewhat heuristically guess whether the field that was confirmed to be uninitialized is actually guarded with ifs, asserts, switch/cases and so on. Since this is a syntactic check, it is very much prone to drastically reduce the amount of reports the checker emits. The reports however that do not get filtered out though have greater likelihood of them manifesting into actual runtime errors. [1] http://lists.llvm.org/pipermail/cfe-dev/2018-September/059255.html Differential Revision: https://reviews.llvm.org/D51866 Added: cfe/trunk/test/Analysis/cxx-uninitialized-object-unguarded-access.cpp Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h?rev=352959&r1=352958&r2=352959&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObject.h Sat Feb 2 06:50:04 2019 @@ -34,6 +34,12 @@ // `-analyzer-config \ // alpha.cplusplus.UninitializedObject:CheckPointeeInitialization=true`. // +// TODO: With some clever heuristics, some pointers should be dereferenced +// by default. For example, if the pointee is constructed within the +// constructor call, it's reasonable to say that no external object +// references it, and we wouldn't generate multiple report on the same +// pointee. +// // - "IgnoreRecordsWithField" (string). If supplied, the checker will not // analyze structures that have a field with a name or type name that // matches the given pattern. Defaults to "". @@ -41,11 +47,12 @@ // `-analyzer-config \ // alpha.cplusplus.UninitializedObject:IgnoreRecordsWithField="[Tt]ag|[Kk]ind"`. // -// TODO: With some clever heuristics, some pointers should be dereferenced -// by default. For example, if the pointee is constructed within the -// constructor call, it's reasonable to say that no external object -// references it, and we wouldn't generate multiple report on the same -// pointee. +// - "IgnoreGuardedFields" (boolean). If set to true, the checker will analyze +// _syntactically_ whether the found uninitialized object is used without a +// preceding assert call. Defaults to false. +// +// `-analyzer-config \ +// alpha.cplusplus.UninitializedObject:IgnoreGuardedFields=true`. // // Most of the following methods as well as the checker itself is defined in // UninitializedObjectChecker.cpp. @@ -68,6 +75,7 @@ struct UninitObjCheckerOptions { bool ShouldConvertNotesToWarnings = false; bool CheckPointeeInitialization = false; std::string IgnoredRecordsWithFieldPattern; + bool IgnoreGuardedFields = false; }; /// A lightweight polymorphic wrapper around FieldRegion *. We'll use this Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp?rev=352959&r1=352958&r2=352959&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp Sat Feb 2 06:50:04 2019 @@ -19,6 +19,7 @@ #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h" #include "UninitializedObject.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" #include "clang/StaticAnalyzer/Core/Checker.h" #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" @@ -26,6 +27,7 @@ using namespace clang; using namespace clang::ento; +using namespace clang::ast_matchers; /// We'll mark fields (and pointee of fields) that are confirmed to be /// uninitialized as already analyzed. @@ -118,6 +120,16 @@ static bool willObjectBeAnalyzedLater(co /// \p Pattern. static bool shouldIgnoreRecord(const RecordDecl *RD, StringRef Pattern); +/// Checks _syntactically_ whether it is possible to access FD from the record +/// that contains it without a preceding assert (even if that access happens +/// inside a
r353150 - Fix the sphinx buildbot after D54429
Author: szelethus Date: Tue Feb 5 02:19:39 2019 New Revision: 353150 URL: http://llvm.org/viewvc/llvm-project?rev=353150&view=rev Log: Fix the sphinx buildbot after D54429 Modified: cfe/trunk/docs/analyzer/checkers.rst Modified: cfe/trunk/docs/analyzer/checkers.rst URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/analyzer/checkers.rst?rev=353150&r1=353149&r2=353150&view=diff == --- cfe/trunk/docs/analyzer/checkers.rst (original) +++ cfe/trunk/docs/analyzer/checkers.rst Tue Feb 5 02:19:39 2019 @@ -1943,7 +1943,7 @@ debug ^ Checkers used for debugging the analyzer. -:doc:`DebugChecks` page contains a detailed description. +:doc:`developer-docs/DebugChecks` page contains a detailed description. debug.AnalysisOrder """ ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r353698 - [analyzer] New checker for detecting usages of unsafe I/O functions
Author: szelethus Date: Mon Feb 11 05:46:43 2019 New Revision: 353698 URL: http://llvm.org/viewvc/llvm-project?rev=353698&view=rev Log: [analyzer] New checker for detecting usages of unsafe I/O functions There are certain unsafe or deprecated (since C11) buffer handling functions which should be avoided in safety critical code. They could cause buffer overflows. A new checker, 'security.insecureAPI.DeprecatedOrUnsafeBufferHandling' warns for every occurrence of such functions (unsafe or deprecated printf, scanf family, and other buffer handling functions, which now have a secure variant). Patch by Dániel Kolozsvári! Differential Revision: https://reviews.llvm.org/D35068 Modified: cfe/trunk/docs/analyzer/checkers.rst cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td cfe/trunk/lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp cfe/trunk/test/Analysis/security-syntax-checks.m Modified: cfe/trunk/docs/analyzer/checkers.rst URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/analyzer/checkers.rst?rev=353698&r1=353697&r2=353698&view=diff == --- cfe/trunk/docs/analyzer/checkers.rst (original) +++ cfe/trunk/docs/analyzer/checkers.rst Mon Feb 11 05:46:43 2019 @@ -566,6 +566,17 @@ security.insecureAPI.vfork (C) vfork(); // warn } +security.insecureAPI.DeprecatedOrUnsafeBufferHandling (C) +"" + Warn on occurrences of unsafe or deprecated buffer handling functions, which now have a secure variant: ``sprintf, vsprintf, scanf, wscanf, fscanf, fwscanf, vscanf, vwscanf, vfscanf, vfwscanf, sscanf, swscanf, vsscanf, vswscanf, swprintf, snprintf, vswprintf, vsnprintf, memcpy, memmove, strncpy, strncat, memset`` + +.. code-block:: c + + void test() { + char buf [5]; + strncpy(buf, "a", 1); // warn + } + .. _unix-checkers: unix Modified: cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td?rev=353698&r1=353697&r2=353698&view=diff == --- cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td (original) +++ cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td Mon Feb 11 05:46:43 2019 @@ -622,6 +622,13 @@ def UncheckedReturn : Checker<"Unchecked Dependencies<[SecuritySyntaxChecker]>, Documentation; +def DeprecatedOrUnsafeBufferHandling : + Checker<"DeprecatedOrUnsafeBufferHandling">, + HelpText<"Warn on uses of unsecure or deprecated buffer manipulating " + "functions">, + Dependencies<[SecuritySyntaxChecker]>, + Documentation; + } // end "security.insecureAPI" let ParentPackage = Security in { Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp?rev=353698&r1=353697&r2=353698&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp Mon Feb 11 05:46:43 2019 @@ -44,6 +44,7 @@ struct ChecksFilter { DefaultBool check_mktemp; DefaultBool check_mkstemp; DefaultBool check_strcpy; + DefaultBool check_DeprecatedOrUnsafeBufferHandling; DefaultBool check_rand; DefaultBool check_vfork; DefaultBool check_FloatLoopCounter; @@ -57,6 +58,7 @@ struct ChecksFilter { CheckName checkName_mktemp; CheckName checkName_mkstemp; CheckName checkName_strcpy; + CheckName checkName_DeprecatedOrUnsafeBufferHandling; CheckName checkName_rand; CheckName checkName_vfork; CheckName checkName_FloatLoopCounter; @@ -103,6 +105,8 @@ public: void checkCall_mkstemp(const CallExpr *CE, const FunctionDecl *FD); void checkCall_strcpy(const CallExpr *CE, const FunctionDecl *FD); void checkCall_strcat(const CallExpr *CE, const FunctionDecl *FD); + void checkDeprecatedOrUnsafeBufferHandling(const CallExpr *CE, + const FunctionDecl *FD); void checkCall_rand(const CallExpr *CE, const FunctionDecl *FD); void checkCall_random(const CallExpr *CE, const FunctionDecl *FD); void checkCall_vfork(const CallExpr *CE, const FunctionDecl *FD); @@ -148,6 +152,14 @@ void WalkAST::VisitCallExpr(CallExpr *CE .Case("mkstemps", &WalkAST::checkCall_mkstemp) .Cases("strcpy", "__strcpy_chk", &WalkAST::checkCall_strcpy) .Cases("strcat", "__strcat_chk", &WalkAST::checkCall_strcat) +.Cases("sprintf", "vsprintf", "scanf", "wscanf", "fscanf", "fwscanf", + "vscanf", "vwscanf", "vfscanf", "vfwscanf", + &WalkAST::checkDeprecatedOrUnsafeBufferHandling) +.Cases("sscanf", "swscanf", "vsscanf", "vswscanf", "swprintf", + "snprintf", "vswprintf", "vsnprintf", "me
r354235 - [analyzer] Make valist.Uninitialized depend on ValistBase
Author: szelethus Date: Sun Feb 17 11:51:42 2019 New Revision: 354235 URL: http://llvm.org/viewvc/llvm-project?rev=354235&view=rev Log: [analyzer] Make valist.Uninitialized depend on ValistBase Accidentally left this dependency out, resulting in an assert failure if only valist.Uninitialized is enabled from the valist package. Modified: cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td cfe/trunk/test/Analysis/valist-uninitialized.c Modified: cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td?rev=354235&r1=354234&r2=354235&view=diff == --- cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td (original) +++ cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td Sun Feb 17 11:51:42 2019 @@ -508,6 +508,7 @@ def ValistBase : Checker<"ValistBase">, def UninitializedChecker : Checker<"Uninitialized">, HelpText<"Check for usages of uninitialized (or already released) va_lists.">, + Dependencies<[ValistBase]>, Documentation; def UnterminatedChecker : Checker<"Unterminated">, Modified: cfe/trunk/test/Analysis/valist-uninitialized.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/valist-uninitialized.c?rev=354235&r1=354234&r2=354235&view=diff == --- cfe/trunk/test/Analysis/valist-uninitialized.c (original) +++ cfe/trunk/test/Analysis/valist-uninitialized.c Sun Feb 17 11:51:42 2019 @@ -1,5 +1,15 @@ -// RUN: %clang_analyze_cc1 -triple hexagon-unknown-linux -analyzer-checker=core,valist.Uninitialized,valist.CopyToSelf -analyzer-disable-checker=core.CallAndMessage -analyzer-output=text -analyzer-store=region -verify %s -// RUN: %clang_analyze_cc1 -triple x86_64-pc-linux-gnu -analyzer-checker=core,valist.Uninitialized,valist.CopyToSelf -analyzer-disable-checker=core.CallAndMessage -analyzer-output=text -analyzer-store=region -verify %s +// RUN: %clang_analyze_cc1 -triple hexagon-unknown-linux -verify %s \ +// RUN: -analyzer-checker=core,valist.Uninitialized,valist.CopyToSelf \ +// RUN: -analyzer-disable-checker=core.CallAndMessage \ +// RUN: -analyzer-output=text +// +// RUN: %clang_analyze_cc1 -triple x86_64-pc-linux-gnu -verify %s \ +// RUN: -analyzer-checker=core,valist.Uninitialized,valist.CopyToSelf \ +// RUN: -analyzer-disable-checker=core.CallAndMessage \ +// RUN: -analyzer-output=text +// +// RUN: %clang_analyze_cc1 -triple x86_64-pc-linux-gnu %s \ +// RUN: -analyzer-checker=core,valist.Uninitialized #include "Inputs/system-header-simulator-for-valist.h" ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r354806 - [analyzer] Fix infinite recursion in printing macros
Author: szelethus Date: Mon Feb 25 10:49:42 2019 New Revision: 354806 URL: http://llvm.org/viewvc/llvm-project?rev=354806&view=rev Log: [analyzer] Fix infinite recursion in printing macros #define f(y) x #define x f(x) int main() { x; } This example results a compilation error since "x" in the first line was not defined earlier. However, the macro expression printer goes to an infinite recursion on this example. Patch by Tibor Brunner! Differential Revision: https://reviews.llvm.org/D57892 Modified: cfe/trunk/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp Modified: cfe/trunk/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp?rev=354806&r1=354805&r2=354806&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp Mon Feb 25 10:49:42 2019 @@ -842,6 +842,9 @@ static std::string getMacroNameAndPrintE MacroNameAndArgs Info = getMacroNameAndArgs(SM.getExpansionLoc(MacroLoc), PP); + if (!Info.MI) +return Info.Name; + // Manually expand its arguments from the previous macro. Info.Args.expandFromPrevMacro(PrevArgs); @@ -936,7 +939,14 @@ static MacroNameAndArgs getMacroNameAndA assert(II && "Failed to acquire the IndetifierInfo for the macro!"); const MacroInfo *MI = getMacroInfoForLocation(PP, SM, II, ExpanLoc); - assert(MI && "The macro must've been defined at it's expansion location!"); + // assert(MI && "The macro must've been defined at it's expansion location!"); + // + // We should always be able to obtain the MacroInfo in a given TU, but if + // we're running the analyzer with CTU, the Preprocessor won't contain the + // directive history (or anything for that matter) from another TU. + // TODO: assert when we're not running with CTU. + if (!MI) +return { MacroName, MI, {} }; // Acquire the macro's arguments. // ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r362887 - [analyzer][NFC] Add dividers to BugReporterVisitors.cpp
Author: szelethus Date: Sat Jun 8 13:25:39 2019 New Revision: 362887 URL: http://llvm.org/viewvc/llvm-project?rev=362887&view=rev Log: [analyzer][NFC] Add dividers to BugReporterVisitors.cpp Some minor formatting to make the file more readable. Added //===--===// around the implementation of class methods and divided anonymous namespaces as per https://llvm.org/docs/CodingStandards.html#anonymous-namespaces Modified: cfe/trunk/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp Modified: cfe/trunk/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp?rev=362887&r1=362886&r2=362887&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp Sat Jun 8 13:25:39 2019 @@ -197,7 +197,7 @@ getConcreteIntegerValue(const Expr *Cond } //===--===// -// Definitions for bug reporter visitors. +// Implementation of BugReporterVisitor. //===--===// std::shared_ptr @@ -694,6 +694,10 @@ private: } }; +} // end of anonymous namespace + +namespace { + /// Suppress null-pointer-dereference bugs where dereferenced null was returned /// the macro. class MacroNullReturnSuppressionVisitor final : public BugReporterVisitor { @@ -782,6 +786,10 @@ private: } }; +} // end of anonymous namespace + +namespace { + /// Emits an extra note at the return statement of an interesting stack frame. /// /// The returned value is marked as an interesting value, and if it's null, @@ -1057,7 +1065,11 @@ public: } }; -} // namespace +} // end of anonymous namespace + +//===--===// +// Implementation of FindLastStoreBRVisitor. +//===--===// void FindLastStoreBRVisitor::Profile(llvm::FoldingSetNodeID &ID) const { static int tag = 0; @@ -1367,6 +1379,10 @@ FindLastStoreBRVisitor::VisitNode(const return std::make_shared(L, os.str()); } +//===--===// +// Implementation of TrackConstraintBRVisitor. +//===--===// + void TrackConstraintBRVisitor::Profile(llvm::FoldingSetNodeID &ID) const { static int tag = 0; ID.AddPointer(&tag); @@ -1439,6 +1455,10 @@ TrackConstraintBRVisitor::VisitNode(cons return nullptr; } +//===--===// +// Implementation of SuppressInlineDefensiveChecksVisitor. +//===--===// + SuppressInlineDefensiveChecksVisitor:: SuppressInlineDefensiveChecksVisitor(DefinedSVal Value, const ExplodedNode *N) : V(Value) { @@ -1534,6 +1554,10 @@ SuppressInlineDefensiveChecksVisitor::Vi return nullptr; } +//===--===// +// Implementation of trackExpressionValue. +//===--===// + static const MemRegion *getLocationRegionIfReference(const Expr *E, const ExplodedNode *N) { if (const auto *DR = dyn_cast(E)) { @@ -1753,6 +1777,10 @@ bool bugreporter::trackExpressionValue(c return true; } +//===--===// +// Implementation of NulReceiverBRVisitor. +//===--===// + const Expr *NilReceiverBRVisitor::getNilReceiver(const Stmt *S, const ExplodedNode *N) { const auto *ME = dyn_cast(S); @@ -1803,6 +1831,10 @@ NilReceiverBRVisitor::VisitNode(const Ex return std::make_shared(L, OS.str()); } +//===--===// +// Implementation of FindLastStoreBRVisitor. +//===--===// + // Registers every VarDecl inside a Stmt with a last store visitor. void FindLastStoreBRVisitor::registerStatementVarDecls(BugReport &BR, const Stmt *S, @@ -2349,6 +2381,10 @@ bool ConditionBRVisitor::isPieceMessageG Piece->getString() == GenericFalseMessage; } +//===--===// +// Implementation of LikelyFalsePositiveSuppressionBRVisitor. +//===--===// + void LikelyFalsePositiveSuppressionBRVisitor::finalizeVisitor( B
r363509 - [analyzer][NFC] Tease apart and clang-format NoStoreFuncVisitor
Author: szelethus Date: Sun Jun 16 07:09:11 2019 New Revision: 363509 URL: http://llvm.org/viewvc/llvm-project?rev=363509&view=rev Log: [analyzer][NFC] Tease apart and clang-format NoStoreFuncVisitor Make several methods static functions Move non-trivial methods out-of-line Add a divider Turn non-obvious autos into Optional clang-format affected lines Differential Revision: https://reviews.llvm.org/D63086 Modified: cfe/trunk/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp Modified: cfe/trunk/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp?rev=363509&r1=363508&r2=363509&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp Sun Jun 16 07:09:11 2019 @@ -196,37 +196,6 @@ getConcreteIntegerValue(const Expr *Cond return {}; } -//===--===// -// Implementation of BugReporterVisitor. -//===--===// - -std::shared_ptr -BugReporterVisitor::getEndPath(BugReporterContext &, - const ExplodedNode *, BugReport &) { - return nullptr; -} - -void -BugReporterVisitor::finalizeVisitor(BugReporterContext &, -const ExplodedNode *, BugReport &) {} - -std::shared_ptr BugReporterVisitor::getDefaultEndPath( -BugReporterContext &BRC, const ExplodedNode *EndPathNode, BugReport &BR) { - PathDiagnosticLocation L = - PathDiagnosticLocation::createEndOfPath(EndPathNode,BRC.getSourceManager()); - - const auto &Ranges = BR.getRanges(); - - // Only add the statement itself as a range if we didn't specify any - // special ranges for this report. - auto P = std::make_shared( - L, BR.getDescription(), Ranges.begin() == Ranges.end()); - for (SourceRange Range : Ranges) -P->addRange(Range); - - return P; -} - /// \return name of the macro inside the location \p Loc. static StringRef getMacroName(SourceLocation Loc, BugReporterContext &BRC) { @@ -251,36 +220,70 @@ static bool isFunctionMacroExpansion(Sou } /// \return Whether \c RegionOfInterest was modified at \p N, -/// where \p ReturnState is a state associated with the return -/// from the current frame. -static bool wasRegionOfInterestModifiedAt( -const SubRegion *RegionOfInterest, -const ExplodedNode *N, -SVal ValueAfter) { +/// where \p ValueAfter is \c RegionOfInterest's value at the end of the +/// stack frame. +static bool wasRegionOfInterestModifiedAt(const SubRegion *RegionOfInterest, + const ExplodedNode *N, + SVal ValueAfter) { ProgramStateRef State = N->getState(); ProgramStateManager &Mgr = N->getState()->getStateManager(); - if (!N->getLocationAs() - && !N->getLocationAs() - && !N->getLocationAs()) + if (!N->getLocationAs() && !N->getLocationAs() && + !N->getLocationAs()) return false; // Writing into region of interest. if (auto PS = N->getLocationAs()) if (auto *BO = PS->getStmtAs()) if (BO->isAssignmentOp() && RegionOfInterest->isSubRegionOf( -N->getSVal(BO->getLHS()).getAsRegion())) + N->getSVal(BO->getLHS()).getAsRegion())) return true; // SVal after the state is possibly different. SVal ValueAtN = N->getState()->getSVal(RegionOfInterest); - if (!Mgr.getSValBuilder().areEqual(State, ValueAtN, ValueAfter).isConstrainedTrue() && + if (!Mgr.getSValBuilder() + .areEqual(State, ValueAtN, ValueAfter) + .isConstrainedTrue() && (!ValueAtN.isUndef() || !ValueAfter.isUndef())) return true; return false; } +//===--===// +// Implementation of BugReporterVisitor. +//===--===// + +std::shared_ptr +BugReporterVisitor::getEndPath(BugReporterContext &, + const ExplodedNode *, BugReport &) { + return nullptr; +} + +void +BugReporterVisitor::finalizeVisitor(BugReporterContext &, +const ExplodedNode *, BugReport &) {} + +std::shared_ptr BugReporterVisitor::getDefaultEndPath( +BugReporterContext &BRC, const ExplodedNode *EndPathNode, BugReport &BR) { + PathDiagnosticLocation L = + PathDiagnosticLocation::createEndOfPath(EndPathNode,BRC.getSourceManager()); + + const auto &Ranges = BR.getRanges(); + + // Only add the statement itself as a range if we didn't specify any + // special ranges for this report. + auto P = std::make_shared( + L, BR.getDescription(), Ranges.begin() == Ranges.end()); + for (SourceRa
r363510 - [analyzer] Track indices of arrays
Author: szelethus Date: Sun Jun 16 07:52:56 2019 New Revision: 363510 URL: http://llvm.org/viewvc/llvm-project?rev=363510&view=rev Log: [analyzer] Track indices of arrays Often times, when an ArraySubscriptExpr was reported as null or undefined, the bug report was difficult to understand, because the analyzer explained why arr[i] has that value, but didn't realize that in fact i's value is very important as well. This patch fixes this by tracking the indices of arrays. Differential Revision: https://reviews.llvm.org/D63080 Modified: cfe/trunk/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp cfe/trunk/test/Analysis/diagnostics/track_subexpressions.cpp Modified: cfe/trunk/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp?rev=363510&r1=363509&r2=363510&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp Sun Jun 16 07:52:56 2019 @@ -1740,6 +1740,10 @@ bool bugreporter::trackExpressionValue(c if (const Expr *Receiver = NilReceiverBRVisitor::getNilReceiver(Inner, LVNode)) trackExpressionValue(LVNode, Receiver, report, EnableNullFPSuppression); + if (const auto *Arr = dyn_cast(Inner)) +trackExpressionValue( +LVNode, Arr->getIdx(), report, EnableNullFPSuppression); + // See if the expression we're interested refers to a variable. // If so, we can track both its contents and constraints on its value. if (ExplodedGraph::isInterestingLValueExpr(Inner)) { Modified: cfe/trunk/test/Analysis/diagnostics/track_subexpressions.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/diagnostics/track_subexpressions.cpp?rev=363510&r1=363509&r2=363510&view=diff == --- cfe/trunk/test/Analysis/diagnostics/track_subexpressions.cpp (original) +++ cfe/trunk/test/Analysis/diagnostics/track_subexpressions.cpp Sun Jun 16 07:52:56 2019 @@ -17,3 +17,28 @@ void shift_by_undefined_value() { (void)(TCP_MAXWIN << shift_amount); // expected-warning{{The result of the left shift is undefined due to shifting by '255', which is greater or equal to the width of type 'int'}} // expected-note@-1{{The result of the left shift is undefined due to shifting by '255', which is greater or equal to the width of type 'int'}} } + +namespace array_index_tracking { +void consume(int); + +int getIndex(int x) { + int a; + if (x > 0) +a = 3; + else +a = 2; + return a; +} + +int getInt(); + +void testArrayIndexTracking() { + int arr[10]; + + for (int i = 0; i < 3; ++i) +arr[i] = 0; + int x = getInt(); + int n = getIndex(x); + consume(arr[n]); +} +} // end of namespace array_index_tracking ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r363512 - [analyzer] Push correct version of 'Track indices of arrays'
Author: szelethus Date: Sun Jun 16 08:41:25 2019 New Revision: 363512 URL: http://llvm.org/viewvc/llvm-project?rev=363512&view=rev Log: [analyzer] Push correct version of 'Track indices of arrays' Messed up the commit, oops. Modified: cfe/trunk/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp cfe/trunk/test/Analysis/diagnostics/track_subexpressions.cpp Modified: cfe/trunk/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp?rev=363512&r1=363511&r2=363512&view=diff == --- cfe/trunk/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp Sun Jun 16 08:41:25 2019 @@ -1740,9 +1740,10 @@ bool bugreporter::trackExpressionValue(c if (const Expr *Receiver = NilReceiverBRVisitor::getNilReceiver(Inner, LVNode)) trackExpressionValue(LVNode, Receiver, report, EnableNullFPSuppression); + // Track the index if this is an array subscript. if (const auto *Arr = dyn_cast(Inner)) trackExpressionValue( -LVNode, Arr->getIdx(), report, EnableNullFPSuppression); +LVNode, Arr->getIdx(), report, /*EnableNullFPSuppression*/ false); // See if the expression we're interested refers to a variable. // If so, we can track both its contents and constraints on its value. Modified: cfe/trunk/test/Analysis/diagnostics/track_subexpressions.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/diagnostics/track_subexpressions.cpp?rev=363512&r1=363511&r2=363512&view=diff == --- cfe/trunk/test/Analysis/diagnostics/track_subexpressions.cpp (original) +++ cfe/trunk/test/Analysis/diagnostics/track_subexpressions.cpp Sun Jun 16 08:41:25 2019 @@ -23,11 +23,12 @@ void consume(int); int getIndex(int x) { int a; - if (x > 0) -a = 3; + if (x > 0) // expected-note {{Assuming 'x' is > 0}} + // expected-note@-1 {{Taking true branch}} +a = 3; // expected-note {{The value 3 is assigned to 'a'}} else a = 2; - return a; + return a; // expected-note {{Returning the value 3 (loaded from 'a')}} } int getInt(); @@ -36,9 +37,47 @@ void testArrayIndexTracking() { int arr[10]; for (int i = 0; i < 3; ++i) +// expected-note@-1 3{{Loop condition is true. Entering loop body}} +// expected-note@-2 {{Loop condition is false. Execution continues on line 43}} arr[i] = 0; int x = getInt(); - int n = getIndex(x); + int n = getIndex(x); // expected-note {{Calling 'getIndex'}} + // expected-note@-1 {{Returning from 'getIndex'}} + // expected-note@-2 {{'n' initialized to 3}} consume(arr[n]); + // expected-note@-1 {{1st function call argument is an uninitialized value}} + // expected-warning@-2{{1st function call argument is an uninitialized value}} } } // end of namespace array_index_tracking + +namespace multi_array_index_tracking { +void consume(int); + +int getIndex(int x) { + int a; + if (x > 0) // expected-note {{Assuming 'x' is > 0}} + // expected-note@-1 {{Taking true branch}} +a = 3; // expected-note {{The value 3 is assigned to 'a'}} + else +a = 2; + return a; // expected-note {{Returning the value 3 (loaded from 'a')}} +} + +int getInt(); + +void testArrayIndexTracking() { + int arr[2][10]; + + for (int i = 0; i < 3; ++i) +// expected-note@-1 3{{Loop condition is true. Entering loop body}} +// expected-note@-2 {{Loop condition is false. Execution continues on line 75}} +arr[1][i] = 0; + int x = getInt(); + int n = getIndex(x); // expected-note {{Calling 'getIndex'}} + // expected-note@-1 {{Returning from 'getIndex'}} + // expected-note@-2 {{'n' initialized to 3}} + consume(arr[1][n]); + // expected-note@-1 {{1st function call argument is an uninitialized value}} + // expected-warning@-2{{1st function call argument is an uninitialized value}} +} +} // end of namespace mulit_array_index_tracking ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits