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); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits