NoQ created this revision. NoQ added reviewers: dcoughlin, xazax.hun, a.sidorin, george.karpenkov, szepet. Herald added subscribers: cfe-commits, rnkovacs, eraman.
C++ overridable `operator new()` has the following prototype: void *operator new(size_t size, user-defined arguments...); The return value is `void *`. However, before passing it to constructor, we need to make a cast to the respective object pointer type. Hence an implicit cast is present here, which is not represented in the current AST or CFG. Modeling this cast is straightforward though. This is the change i mentioned in https://reviews.llvm.org/D40939. I also noticed that `evalCast` from `void *` to `T *` is uncomfortable to use because sometimes it transforms `&SymRegion{$x}` into `&element{T, 0S32b, SymRegion{$x}}` even when `$x` is already of type `T *`. The form `&SymRegion{$x}` seems to be the canonical form of this symbolic pointer value in the rest of the analyzer, so i decided to change `evalCast` to preserve it. The problem of how to represent memregion value casts better still stands - it wouldn't add much to the analyzer's quality, but we just keep running into it over and over again. Repository: rC Clang https://reviews.llvm.org/D41250 Files: lib/StaticAnalyzer/Core/ExprEngineCXX.cpp lib/StaticAnalyzer/Core/Store.cpp test/Analysis/new-ctor-conservative.cpp test/Analysis/new-ctor-inlined.cpp Index: test/Analysis/new-ctor-inlined.cpp =================================================================== --- test/Analysis/new-ctor-inlined.cpp +++ test/Analysis/new-ctor-inlined.cpp @@ -27,3 +27,12 @@ // Check that bindings are correct (and also not dying). clang_analyzer_eval(s->x == 1); // expected-warning{{TRUE}} } + +void checkNewPOD() { + int *i = new int; + clang_analyzer_eval(*i == 0); // expected-warning{{UNKNOWN}} + int *j = new int(); + clang_analyzer_eval(*j == 0); // expected-warning{{TRUE}} + int *k = new int(5); + clang_analyzer_eval(*k == 5); // expected-warning{{TRUE}} +} Index: test/Analysis/new-ctor-conservative.cpp =================================================================== --- test/Analysis/new-ctor-conservative.cpp +++ test/Analysis/new-ctor-conservative.cpp @@ -12,3 +12,12 @@ S *s = new S; clang_analyzer_eval(s->x == 1); // expected-warning{{TRUE}} } + +void checkNewPOD() { + int *i = new int; + clang_analyzer_eval(*i == 0); // expected-warning{{UNKNOWN}} + int *j = new int(); + clang_analyzer_eval(*j == 0); // expected-warning{{TRUE}} + int *k = new int(5); + clang_analyzer_eval(*k == 5); // expected-warning{{TRUE}} +} Index: lib/StaticAnalyzer/Core/Store.cpp =================================================================== --- lib/StaticAnalyzer/Core/Store.cpp +++ lib/StaticAnalyzer/Core/Store.cpp @@ -91,13 +91,21 @@ return R; // Handle casts from compatible types. - if (R->isBoundable()) + if (R->isBoundable()) { if (const TypedValueRegion *TR = dyn_cast<TypedValueRegion>(R)) { QualType ObjTy = Ctx.getCanonicalType(TR->getValueType()); if (CanonPointeeTy == ObjTy) return R; } + if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R)) { + QualType SymTy = + Ctx.getCanonicalType(SR->getSymbol()->getType()->getPointeeType()); + if (CanonPointeeTy == SymTy) + return R; + } + } + // Process region cast according to the kind of the region being cast. switch (R->getKind()) { case MemRegion::CXXThisRegionKind: Index: lib/StaticAnalyzer/Core/ExprEngineCXX.cpp =================================================================== --- lib/StaticAnalyzer/Core/ExprEngineCXX.cpp +++ lib/StaticAnalyzer/Core/ExprEngineCXX.cpp @@ -571,6 +571,10 @@ SVal PlacementLoc = State->getSVal(CNE->getPlacementArg(0), LCtx); Result = svalBuilder.evalCast(PlacementLoc, CNE->getType(), CNE->getPlacementArg(0)->getType()); + } else { + Result = + svalBuilder.evalCast(Result, CNE->getType(), + getContext().getPointerType(getContext().VoidTy)); } // Bind the address of the object, then check to see if we cached out.
Index: test/Analysis/new-ctor-inlined.cpp =================================================================== --- test/Analysis/new-ctor-inlined.cpp +++ test/Analysis/new-ctor-inlined.cpp @@ -27,3 +27,12 @@ // Check that bindings are correct (and also not dying). clang_analyzer_eval(s->x == 1); // expected-warning{{TRUE}} } + +void checkNewPOD() { + int *i = new int; + clang_analyzer_eval(*i == 0); // expected-warning{{UNKNOWN}} + int *j = new int(); + clang_analyzer_eval(*j == 0); // expected-warning{{TRUE}} + int *k = new int(5); + clang_analyzer_eval(*k == 5); // expected-warning{{TRUE}} +} Index: test/Analysis/new-ctor-conservative.cpp =================================================================== --- test/Analysis/new-ctor-conservative.cpp +++ test/Analysis/new-ctor-conservative.cpp @@ -12,3 +12,12 @@ S *s = new S; clang_analyzer_eval(s->x == 1); // expected-warning{{TRUE}} } + +void checkNewPOD() { + int *i = new int; + clang_analyzer_eval(*i == 0); // expected-warning{{UNKNOWN}} + int *j = new int(); + clang_analyzer_eval(*j == 0); // expected-warning{{TRUE}} + int *k = new int(5); + clang_analyzer_eval(*k == 5); // expected-warning{{TRUE}} +} Index: lib/StaticAnalyzer/Core/Store.cpp =================================================================== --- lib/StaticAnalyzer/Core/Store.cpp +++ lib/StaticAnalyzer/Core/Store.cpp @@ -91,13 +91,21 @@ return R; // Handle casts from compatible types. - if (R->isBoundable()) + if (R->isBoundable()) { if (const TypedValueRegion *TR = dyn_cast<TypedValueRegion>(R)) { QualType ObjTy = Ctx.getCanonicalType(TR->getValueType()); if (CanonPointeeTy == ObjTy) return R; } + if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R)) { + QualType SymTy = + Ctx.getCanonicalType(SR->getSymbol()->getType()->getPointeeType()); + if (CanonPointeeTy == SymTy) + return R; + } + } + // Process region cast according to the kind of the region being cast. switch (R->getKind()) { case MemRegion::CXXThisRegionKind: Index: lib/StaticAnalyzer/Core/ExprEngineCXX.cpp =================================================================== --- lib/StaticAnalyzer/Core/ExprEngineCXX.cpp +++ lib/StaticAnalyzer/Core/ExprEngineCXX.cpp @@ -571,6 +571,10 @@ SVal PlacementLoc = State->getSVal(CNE->getPlacementArg(0), LCtx); Result = svalBuilder.evalCast(PlacementLoc, CNE->getType(), CNE->getPlacementArg(0)->getType()); + } else { + Result = + svalBuilder.evalCast(Result, CNE->getType(), + getContext().getPointerType(getContext().VoidTy)); } // Bind the address of the object, then check to see if we cached out.
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits