diff options
| author | Jordan Rose <jordan_rose@apple.com> | 2012-06-11 23:20:52 +0000 |
|---|---|---|
| committer | Jordan Rose <jordan_rose@apple.com> | 2012-06-11 23:20:52 +0000 |
| commit | ca00b28a47cf42fa73809dd9a91eda9ce4644dff (patch) | |
| tree | 904baa3f32b4b7d0f777b9e2828be98a7e4f68ee /clang | |
| parent | 23c699e497a8c50b2e91298d1571ac303fb1a5d9 (diff) | |
| download | bcm5719-llvm-ca00b28a47cf42fa73809dd9a91eda9ce4644dff.tar.gz bcm5719-llvm-ca00b28a47cf42fa73809dd9a91eda9ce4644dff.zip | |
[analyzer] Treat LValueBitCasts like regular pointer bit casts.
These casts only appear in very well-defined circumstances, in which the
target of a reinterpret_cast or a function formal parameter is an lvalue
reference. According to the C++ standard, the following are equivalent:
reinterpret_cast<T&>( x)
*reinterpret_cast<T*>(&x)
[expr.reinterpret.cast]p11
llvm-svn: 158338
Diffstat (limited to 'clang')
| -rw-r--r-- | clang/lib/StaticAnalyzer/Core/ExprEngine.cpp | 2 | ||||
| -rw-r--r-- | clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp | 4 | ||||
| -rw-r--r-- | clang/lib/StaticAnalyzer/Core/RegionStore.cpp | 13 | ||||
| -rw-r--r-- | clang/test/Analysis/casts.cpp | 36 |
4 files changed, 48 insertions, 7 deletions
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp index a95f565b6c9..fb41a9384c8 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -1641,7 +1641,7 @@ void ExprEngine::evalLoad(ExplodedNodeSet &Dst, assert(!isa<NonLoc>(location) && "location cannot be a NonLoc."); assert(!isa<loc::ObjCPropRef>(location)); - // Are we loading from a region? This actually results in two loads; one + // Are we loading from a reference? This actually results in two loads; one // to fetch the address of the referenced value and one to fetch the // referenced value. if (const TypedValueRegion *TR = diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp index 67078600093..2e3e9f51e7d 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp @@ -279,6 +279,7 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex, case CK_Dependent: case CK_ArrayToPointerDecay: case CK_BitCast: + case CK_LValueBitCast: case CK_IntegralCast: case CK_NullToPointer: case CK_IntegralToPointer: @@ -377,8 +378,7 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex, case CK_UserDefinedConversion: case CK_ConstructorConversion: case CK_VectorSplat: - case CK_MemberPointerToBoolean: - case CK_LValueBitCast: { + case CK_MemberPointerToBoolean: { // Recover some path-sensitivty by conjuring a new value. QualType resultType = CastE->getType(); if (CastE->isGLValue()) diff --git a/clang/lib/StaticAnalyzer/Core/RegionStore.cpp b/clang/lib/StaticAnalyzer/Core/RegionStore.cpp index 9c00d963432..86a68a6b3a5 100644 --- a/clang/lib/StaticAnalyzer/Core/RegionStore.cpp +++ b/clang/lib/StaticAnalyzer/Core/RegionStore.cpp @@ -878,10 +878,15 @@ SVal RegionStoreManager::ArrayToPointer(Loc Array) { if (!ArrayR) return UnknownVal(); - // Strip off typedefs from the ArrayRegion's ValueType. - QualType T = ArrayR->getValueType().getDesugaredType(Ctx); - const ArrayType *AT = cast<ArrayType>(T); - T = AT->getElementType(); + // Extract the element type from the array region's ValueType. + // Be careful about weird things happening due to user-written casts. + QualType T = ArrayR->getValueType(); + if (const ArrayType *AT = Ctx.getAsArrayType(T)) + T = AT->getElementType(); + else if (const PointerType *PT = T->getAs<PointerType>()) + T = PT->getPointeeType(); + else + return UnknownVal(); NonLoc ZeroIdx = svalBuilder.makeZeroArrayIndex(); return loc::MemRegionVal(MRMgr.getElementRegion(T, ZeroIdx, ArrayR, Ctx)); diff --git a/clang/test/Analysis/casts.cpp b/clang/test/Analysis/casts.cpp new file mode 100644 index 00000000000..046ffb53c8f --- /dev/null +++ b/clang/test/Analysis/casts.cpp @@ -0,0 +1,36 @@ +// RUN: %clang_cc1 -analyze -analyzer-checker=core,experimental.core -analyzer-store=region -verify %s + +void fill_r (int * const &x); + +char testPointer () { + int x[8]; + int *xp = x; + fill_r(xp); + + return x[0]; // no-warning +} + +char testArray () { + int x[8]; + fill_r(x); + + return x[0]; // no-warning +} + +char testReferenceCast () { + int x[8]; + int *xp = x; + fill_r(reinterpret_cast<int * const &>(xp)); + + return x[0]; // no-warning +} + + +void fill (int *x); +char testReferenceCastRValue () { + int x[8]; + int *xp = x; + fill(reinterpret_cast<int * const &>(xp)); + + return x[0]; // no-warning +} |

