baloghadamsoftware created this revision. baloghadamsoftware added reviewers: NoQ, Charusso. baloghadamsoftware added a project: clang. Herald added subscribers: ASDenysPetrov, martong, steakhal, gamesh411, dkrupp, donat.nagy, Szelethus, mikhail.ramalho, a.sidorin, rnkovacs, szepet, kristof.beyls, xazax.hun, whisperity. Herald added a reviewer: Szelethus. baloghadamsoftware requested review of this revision.
The successfulness of a dynamic cast depends only on the //C++ class//, not the pointer or reference. Thus if `*A` //is a// `*B`, then `&B` //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. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D85752 Files: clang/lib/StaticAnalyzer/Checkers/CastValueChecker.cpp clang/lib/StaticAnalyzer/Core/DynamicType.cpp clang/test/Analysis/cast-value-state-dump.cpp Index: clang/test/Analysis/cast-value-state-dump.cpp =================================================================== --- clang/test/Analysis/cast-value-state-dump.cpp +++ clang/test/Analysis/cast-value-state-dump.cpp @@ -35,8 +35,8 @@ // 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); Index: clang/lib/StaticAnalyzer/Core/DynamicType.cpp =================================================================== --- clang/lib/StaticAnalyzer/Core/DynamicType.cpp +++ clang/lib/StaticAnalyzer/Core/DynamicType.cpp @@ -65,6 +65,19 @@ return State->get<DynamicTypeMap>(MR); } +static void unbox(QualType &Ty) { + if (Ty->isReferenceType()) + Ty = Ty.getNonReferenceType(); + if (const auto *STTPTy = dyn_cast<SubstTemplateTypeParmType>(Ty.getTypePtr())) + Ty = STTPTy->getReplacementType(); + if (Ty->isPointerType()) + Ty = Ty->getPointeeType(); + if (const auto *STTPTy = + dyn_cast<SubstTemplateTypeParmType>(Ty.getTypePtr())) + Ty = STTPTy->getReplacementType(); + Ty = Ty.getUnqualifiedType(); +} + const DynamicCastInfo *getDynamicCastInfo(ProgramStateRef State, const MemRegion *MR, QualType CastFromTy, @@ -73,6 +86,9 @@ if (!Lookup) return nullptr; + unbox(CastFromTy); + unbox(CastToTy); + for (const DynamicCastInfo &Cast : *Lookup) if (Cast.equals(CastFromTy, CastToTy)) return &Cast; @@ -112,6 +128,9 @@ State = State->set<DynamicTypeMap>(MR, CastToTy); } + unbox(CastFromTy); + unbox(CastToTy); + DynamicCastInfo::CastResult ResultKind = CastSucceeds ? DynamicCastInfo::CastResult::Success : DynamicCastInfo::CastResult::Failure; Index: clang/lib/StaticAnalyzer/Checkers/CastValueChecker.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/CastValueChecker.cpp +++ clang/lib/StaticAnalyzer/Checkers/CastValueChecker.cpp @@ -106,7 +106,7 @@ 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();
Index: clang/test/Analysis/cast-value-state-dump.cpp =================================================================== --- clang/test/Analysis/cast-value-state-dump.cpp +++ clang/test/Analysis/cast-value-state-dump.cpp @@ -35,8 +35,8 @@ // 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); Index: clang/lib/StaticAnalyzer/Core/DynamicType.cpp =================================================================== --- clang/lib/StaticAnalyzer/Core/DynamicType.cpp +++ clang/lib/StaticAnalyzer/Core/DynamicType.cpp @@ -65,6 +65,19 @@ return State->get<DynamicTypeMap>(MR); } +static void unbox(QualType &Ty) { + if (Ty->isReferenceType()) + Ty = Ty.getNonReferenceType(); + if (const auto *STTPTy = dyn_cast<SubstTemplateTypeParmType>(Ty.getTypePtr())) + Ty = STTPTy->getReplacementType(); + if (Ty->isPointerType()) + Ty = Ty->getPointeeType(); + if (const auto *STTPTy = + dyn_cast<SubstTemplateTypeParmType>(Ty.getTypePtr())) + Ty = STTPTy->getReplacementType(); + Ty = Ty.getUnqualifiedType(); +} + const DynamicCastInfo *getDynamicCastInfo(ProgramStateRef State, const MemRegion *MR, QualType CastFromTy, @@ -73,6 +86,9 @@ if (!Lookup) return nullptr; + unbox(CastFromTy); + unbox(CastToTy); + for (const DynamicCastInfo &Cast : *Lookup) if (Cast.equals(CastFromTy, CastToTy)) return &Cast; @@ -112,6 +128,9 @@ State = State->set<DynamicTypeMap>(MR, CastToTy); } + unbox(CastFromTy); + unbox(CastToTy); + DynamicCastInfo::CastResult ResultKind = CastSucceeds ? DynamicCastInfo::CastResult::Success : DynamicCastInfo::CastResult::Failure; Index: clang/lib/StaticAnalyzer/Checkers/CastValueChecker.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/CastValueChecker.cpp +++ clang/lib/StaticAnalyzer/Checkers/CastValueChecker.cpp @@ -106,7 +106,7 @@ 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();
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits