r369728 - [analyzer] CastValueChecker: Provide DynamicTypeMap with pointer types only.
Artem Dergachev via cfe-commits
cfe-commits at lists.llvm.org
Thu Aug 22 20:24:01 PDT 2019
Author: dergachev
Date: Thu Aug 22 20:24:01 2019
New Revision: 369728
URL: http://llvm.org/viewvc/llvm-project?rev=369728&view=rev
Log:
[analyzer] CastValueChecker: Provide DynamicTypeMap with pointer types only.
The idea to drop this requirement is good, but for now every other user
of DynamicTypeInfo expects pointer types.
Fixes a crash.
Modified:
cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicType.h
cfe/trunk/lib/StaticAnalyzer/Checkers/CastValueChecker.cpp
cfe/trunk/lib/StaticAnalyzer/Core/DynamicType.cpp
cfe/trunk/test/Analysis/cast-value-logic.cpp
cfe/trunk/test/Analysis/cast-value-state-dump.cpp
Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicType.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicType.h?rev=369728&r1=369727&r2=369728&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicType.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicType.h Thu Aug 22 20:24:01 2019
@@ -54,7 +54,7 @@ ProgramStateRef setDynamicTypeInfo(Progr
ProgramStateRef setDynamicTypeAndCastInfo(ProgramStateRef State,
const MemRegion *MR,
QualType CastFromTy,
- QualType CastToTy, QualType ResultTy,
+ QualType CastToTy,
bool IsCastSucceeds);
/// Removes the dead type informations from \p State.
Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/CastValueChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/CastValueChecker.cpp?rev=369728&r1=369727&r2=369728&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/CastValueChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/CastValueChecker.cpp Thu Aug 22 20:24:01 2019
@@ -92,18 +92,6 @@ private:
};
} // namespace
-static QualType getRecordType(QualType Ty) {
- Ty = Ty.getCanonicalType();
-
- if (Ty->isPointerType())
- Ty = Ty->getPointeeType();
-
- if (Ty->isReferenceType())
- Ty = Ty.getNonReferenceType();
-
- return Ty.getUnqualifiedType();
-}
-
static bool isInfeasibleCast(const DynamicCastInfo *CastInfo,
bool CastSucceeds) {
if (!CastInfo)
@@ -117,8 +105,8 @@ static const NoteTag *getNoteTag(Checker
QualType CastToTy, const Expr *Object,
bool CastSucceeds, bool IsKnownCast) {
std::string CastToName =
- CastInfo ? CastInfo->to()->getAsCXXRecordDecl()->getNameAsString()
- : CastToTy->getAsCXXRecordDecl()->getNameAsString();
+ CastInfo ? CastInfo->to()->getPointeeCXXRecordDecl()->getNameAsString()
+ : CastToTy->getPointeeCXXRecordDecl()->getNameAsString();
Object = Object->IgnoreParenImpCasts();
return C.getNoteTag(
@@ -160,14 +148,14 @@ static void addCastTransition(const Call
const Expr *Object;
QualType CastFromTy;
- QualType CastToTy = getRecordType(Call.getResultType());
+ QualType CastToTy = Call.getResultType();
if (Call.getNumArgs() > 0) {
Object = Call.getArgExpr(0);
- CastFromTy = getRecordType(Call.parameters()[0]->getType());
+ CastFromTy = Call.parameters()[0]->getType();
} else {
Object = cast<CXXInstanceCall>(&Call)->getCXXThisExpr();
- CastFromTy = getRecordType(Object->getType());
+ CastFromTy = Object->getType();
}
const MemRegion *MR = DV.getAsRegion();
@@ -193,7 +181,7 @@ static void addCastTransition(const Call
bool IsKnownCast = CastInfo || IsCheckedCast || CastFromTy == CastToTy;
if (!IsKnownCast || IsCheckedCast)
State = setDynamicTypeAndCastInfo(State, MR, CastFromTy, CastToTy,
- Call.getResultType(), CastSucceeds);
+ CastSucceeds);
SVal V = CastSucceeds ? DV : C.getSValBuilder().makeNull();
C.addTransition(
@@ -206,8 +194,20 @@ static void addInstanceOfTransition(cons
ProgramStateRef State, CheckerContext &C,
bool IsInstanceOf) {
const FunctionDecl *FD = Call.getDecl()->getAsFunction();
+ QualType CastFromTy = Call.parameters()[0]->getType();
QualType CastToTy = FD->getTemplateSpecializationArgs()->get(0).getAsType();
- QualType CastFromTy = getRecordType(Call.parameters()[0]->getType());
+ if (CastFromTy->isPointerType())
+ CastToTy = C.getASTContext().getPointerType(CastToTy);
+ else if (CastFromTy->isLValueReferenceType() &&
+ CastFromTy.isConstQualified()) {
+ CastToTy.addConst();
+ CastToTy = C.getASTContext().getLValueReferenceType(CastToTy);
+ } else if (CastFromTy->isLValueReferenceType())
+ CastToTy = C.getASTContext().getLValueReferenceType(CastToTy);
+ else if (CastFromTy->isRValueReferenceType())
+ CastToTy = C.getASTContext().getRValueReferenceType(CastToTy);
+ else
+ return;
const MemRegion *MR = DV.getAsRegion();
const DynamicCastInfo *CastInfo =
@@ -228,7 +228,7 @@ static void addInstanceOfTransition(cons
bool IsKnownCast = CastInfo || CastFromTy == CastToTy;
if (!IsKnownCast)
State = setDynamicTypeAndCastInfo(State, MR, CastFromTy, CastToTy,
- Call.getResultType(), IsInstanceOf);
+ IsInstanceOf);
C.addTransition(
State->BindExpr(Call.getOriginExpr(), C.getLocationContext(),
@@ -373,11 +373,6 @@ bool CastValueChecker::evalCall(const Ca
const CastCheck &Check = Lookup->first;
CallKind Kind = Lookup->second;
- // We need to obtain the record type of the call's result to model it.
- if (Kind != CallKind::InstanceOf &&
- !getRecordType(Call.getResultType())->isRecordType())
- return false;
-
Optional<DefinedOrUnknownSVal> DV;
switch (Kind) {
Modified: cfe/trunk/lib/StaticAnalyzer/Core/DynamicType.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/DynamicType.cpp?rev=369728&r1=369727&r2=369728&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/DynamicType.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/DynamicType.cpp Thu Aug 22 20:24:01 2019
@@ -91,13 +91,16 @@ ProgramStateRef setDynamicTypeInfo(Progr
ProgramStateRef setDynamicTypeAndCastInfo(ProgramStateRef State,
const MemRegion *MR,
QualType CastFromTy,
- QualType CastToTy, QualType ResultTy,
+ QualType CastToTy,
bool CastSucceeds) {
if (!MR)
return State;
- if (CastSucceeds)
- State = State->set<DynamicTypeMap>(MR, ResultTy);
+ if (CastSucceeds) {
+ assert((CastToTy->isAnyPointerType() || CastToTy->isReferenceType()) &&
+ "DynamicTypeInfo should always be a pointer.");
+ State = State->set<DynamicTypeMap>(MR, CastToTy);
+ }
DynamicCastInfo::CastResult ResultKind =
CastSucceeds ? DynamicCastInfo::CastResult::Success
Modified: cfe/trunk/test/Analysis/cast-value-logic.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/cast-value-logic.cpp?rev=369728&r1=369727&r2=369728&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/cast-value-logic.cpp (original)
+++ cfe/trunk/test/Analysis/cast-value-logic.cpp Thu Aug 22 20:24:01 2019
@@ -15,6 +15,8 @@ struct Shape {
template <typename T>
const T *getAs() const;
+
+ virtual double area();
};
class Triangle : public Shape {};
class Circle : public Shape {};
@@ -141,4 +143,10 @@ void test_non_reference_temporary_crash(
auto P = foo();
auto Q = cast<Circle>(std::move(P)); // no-crash
}
+
+double test_virtual_method_after_call(Shape *S) {
+ if (isa<Circle>(S))
+ return S->area();
+ return S->area() / 2;
+}
} // namespace crashes
Modified: cfe/trunk/test/Analysis/cast-value-state-dump.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/cast-value-state-dump.cpp?rev=369728&r1=369727&r2=369728&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/cast-value-state-dump.cpp (original)
+++ cfe/trunk/test/Analysis/cast-value-state-dump.cpp Thu Aug 22 20:24:01 2019
@@ -35,8 +35,8 @@ void evalNonNullParamNonNullReturn(const
// CHECK-NEXT: ],
// CHECK-NEXT: "dynamic_casts": [
// CHECK: { "region": "SymRegion{reg_$0<const struct clang::Shape * S>}", "casts": [
- // CHECK-NEXT: { "from": "struct clang::Shape", "to": "class clang::Circle", "kind": "success" },
- // CHECK-NEXT: { "from": "struct clang::Shape", "to": "class clang::Square", "kind": "fail" }
+ // CHECK-NEXT: { "from": "const struct clang::Shape *", "to": "const class clang::Circle *", "kind": "success" },
+ // CHECK-NEXT: { "from": "const struct clang::Shape *", "to": "const class clang::Square *", "kind": "fail" }
// CHECK-NEXT: ]}
(void)(1 / !C);
More information about the cfe-commits
mailing list