Szelethus created this revision. Szelethus added reviewers: NoQ, george.karpenkov, rnkovacs, xazax.hun. Herald added subscribers: cfe-commits, mikhail.ramalho, a.sidorin, szepet, whisperity.
The idea came from both @george.karpenkov (https://reviews.llvm.org/D45532#1145592) and from bugzilla (https://bugs.llvm.org/show_bug.cgi?id=37965). Assigning an object with uninitialized value to a pointer/reference could be intentional, especially if one writes a class that just initializes values. struct Initializer { int *a; void initialize(/* ... */) { a = /* ... */; } Initializer(int *a) : a(a) {} }; void f() { int b; Initializer init(&b); // ... init.initialize(/* ... */); } I actually have seen some examples for this in LLVM. While I absolutely agree that a flag like this would be neat, I also think that it should be disabled by default, as for example some objects are only created with `malloc`/`new`, and because I didn't find this functionality to be too noisy. Repository: rC Clang https://reviews.llvm.org/D49438 Files: lib/StaticAnalyzer/Checkers/UninitializedObjectChecker.cpp test/Analysis/cxx-uninitialized-no-dereference.cpp
Index: test/Analysis/cxx-uninitialized-no-dereference.cpp =================================================================== --- /dev/null +++ test/Analysis/cxx-uninitialized-no-dereference.cpp @@ -0,0 +1,26 @@ +// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.cplusplus.UninitializedObject -analyzer-config alpha.cplusplus.UninitializedObject:NoDereference=true -std=c++11 -DPEDANTIC -verify %s + +class UninitPointerTest { + int *ptr; // expected-note{{uninitialized pointer 'this->ptr'}} + int dontGetFilteredByNonPedanticMode = 0; + +public: + UninitPointerTest() {} // expected-warning{{1 uninitialized field}} +}; + +void fUninitPointerTest() { + UninitPointerTest(); +} + +class UninitPointeeTest { + int *ptr; // no-note + int dontGetFilteredByNonPedanticMode = 0; + +public: + UninitPointeeTest(int *ptr) : ptr(ptr) {} // no-warning +}; + +void fUninitPointeeTest() { + int a; + UninitPointeeTest t(&a); +} Index: lib/StaticAnalyzer/Checkers/UninitializedObjectChecker.cpp =================================================================== --- lib/StaticAnalyzer/Checkers/UninitializedObjectChecker.cpp +++ lib/StaticAnalyzer/Checkers/UninitializedObjectChecker.cpp @@ -10,7 +10,7 @@ // 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 @@ -24,6 +24,12 @@ // // `-analyzer-config alpha.cplusplus.UninitializedObject:NotesAsWarnings=true`. // +// - "NoDereference" (boolean). If set to true, 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:NoDereference=true`. +// //===----------------------------------------------------------------------===// #include "ClangSACheckers.h" @@ -44,6 +50,7 @@ // These fields will be initialized when registering the checker. bool IsPedantic; bool ShouldConvertNotesToWarnings; + bool ShouldDereference; UninitializedObjectChecker() : BT_uninitField(new BuiltinBug(this, "Uninitialized fields")) {} @@ -109,13 +116,16 @@ const TypedValueRegion *const ObjectR; const bool IsPedantic; + const bool ShouldDereference; + bool IsAnyFieldInitialized = false; UninitFieldSet UninitFields; public: FindUninitializedFields(ProgramStateRef State, - const TypedValueRegion *const R, bool IsPedantic); + const TypedValueRegion *const R, bool IsPedantic, + bool ShouldDereference); const UninitFieldSet &getUninitFields(); private: @@ -261,8 +271,8 @@ if (!Object) return; - FindUninitializedFields F(Context.getState(), Object->getRegion(), - IsPedantic); + FindUninitializedFields F(Context.getState(), Object->getRegion(), IsPedantic, + ShouldDereference); const UninitFieldSet &UninitFields = F.getUninitFields(); @@ -326,8 +336,10 @@ //===----------------------------------------------------------------------===// 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 ShouldDereference) + : State(State), ObjectR(R), IsPedantic(IsPedantic), + ShouldDereference(ShouldDereference) {} const UninitFieldSet &FindUninitializedFields::getUninitFields() { isNonUnionUninit(ObjectR, FieldChainInfo()); @@ -474,6 +486,11 @@ return addFieldToUninits({LocalChain, FR}); } + if (!ShouldDereference) { + IsAnyFieldInitialized = true; + return false; + } + const FieldDecl *FD = FR->getDecl(); // TODO: The dynamic type of a void pointer may be retrieved with @@ -700,4 +717,6 @@ "Pedantic", /*DefaultVal*/ false, Chk); Chk->ShouldConvertNotesToWarnings = Mgr.getAnalyzerOptions().getBooleanOption( "NotesAsWarnings", /*DefaultVal*/ false, Chk); + Chk->ShouldDereference = !Mgr.getAnalyzerOptions().getBooleanOption( + "NoDereference", /*DefaultVal*/ false, Chk); }
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits