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