[analyzer] NFC: Store the pointee/referenced type for dynamic type tracking.
The successfulness of a dynamic cast depends only on the C++ class, not the pointer or reference. Thus if *A is a *B, then &A is a &B, const *A is a const *B etc. This patch changes DynamicCastInfo to store and check the cast between the unqualified pointed/referenced types. It also removes e.g. SubstTemplateTypeParmType from both the pointer and the pointed type. Differential Revision: https://reviews.llvm.org/D85752
This commit is contained in:
parent
52f1df0923
commit
5a9e778939
|
@ -106,7 +106,7 @@ static const NoteTag *getNoteTag(CheckerContext &C,
|
|||
QualType CastToTy, const Expr *Object,
|
||||
bool CastSucceeds, bool IsKnownCast) {
|
||||
std::string CastToName =
|
||||
CastInfo ? CastInfo->to()->getPointeeCXXRecordDecl()->getNameAsString()
|
||||
CastInfo ? CastInfo->to()->getAsCXXRecordDecl()->getNameAsString()
|
||||
: CastToTy->getPointeeCXXRecordDecl()->getNameAsString();
|
||||
Object = Object->IgnoreParenImpCasts();
|
||||
|
||||
|
|
|
@ -65,6 +65,13 @@ const DynamicTypeInfo *getRawDynamicTypeInfo(ProgramStateRef State,
|
|||
return State->get<DynamicTypeMap>(MR);
|
||||
}
|
||||
|
||||
static void unbox(QualType &Ty) {
|
||||
// FIXME: Why are we being fed references to pointers in the first place?
|
||||
while (Ty->isReferenceType() || Ty->isPointerType())
|
||||
Ty = Ty->getPointeeType();
|
||||
Ty = Ty.getCanonicalType().getUnqualifiedType();
|
||||
}
|
||||
|
||||
const DynamicCastInfo *getDynamicCastInfo(ProgramStateRef State,
|
||||
const MemRegion *MR,
|
||||
QualType CastFromTy,
|
||||
|
@ -73,6 +80,9 @@ const DynamicCastInfo *getDynamicCastInfo(ProgramStateRef State,
|
|||
if (!Lookup)
|
||||
return nullptr;
|
||||
|
||||
unbox(CastFromTy);
|
||||
unbox(CastToTy);
|
||||
|
||||
for (const DynamicCastInfo &Cast : *Lookup)
|
||||
if (Cast.equals(CastFromTy, CastToTy))
|
||||
return &Cast;
|
||||
|
@ -112,6 +122,9 @@ ProgramStateRef setDynamicTypeAndCastInfo(ProgramStateRef State,
|
|||
State = State->set<DynamicTypeMap>(MR, CastToTy);
|
||||
}
|
||||
|
||||
unbox(CastFromTy);
|
||||
unbox(CastToTy);
|
||||
|
||||
DynamicCastInfo::CastResult ResultKind =
|
||||
CastSucceeds ? DynamicCastInfo::CastResult::Success
|
||||
: DynamicCastInfo::CastResult::Failure;
|
||||
|
|
|
@ -35,8 +35,8 @@ void evalNonNullParamNonNullReturn(const Shape *S) {
|
|||
// CHECK-NEXT: ],
|
||||
// CHECK-NEXT: "dynamic_casts": [
|
||||
// CHECK: { "region": "SymRegion{reg_$0<const struct clang::Shape * S>}", "casts": [
|
||||
// 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: { "from": "struct clang::Shape", "to": "class clang::Circle", "kind": "success" },
|
||||
// CHECK-NEXT: { "from": "struct clang::Shape", "to": "class clang::Square", "kind": "fail" }
|
||||
// CHECK-NEXT: ] }
|
||||
|
||||
(void)(1 / !C);
|
||||
|
|
Loading…
Reference in New Issue