]> granicus.if.org Git - clang/commitdiff
[analyzer] Handle UserDefinedConversion casts in C++.
authorJordan Rose <jordan_rose@apple.com>
Thu, 23 Aug 2012 23:01:39 +0000 (23:01 +0000)
committerJordan Rose <jordan_rose@apple.com>
Thu, 23 Aug 2012 23:01:39 +0000 (23:01 +0000)
This is trivial; the UserDefinedConversion always wraps a CXXMemberCallExpr
for the appropriate conversion function, so it's just a matter of
propagating that value to the CastExpr itself.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@162494 91177308-0d34-0410-b5e6-96231b3b80d8

lib/StaticAnalyzer/Core/ExprEngineC.cpp
test/Analysis/operator-calls.cpp

index 935d7aea0ca8350f35c20c87e816fbcca0521220..f65a6ebc3468e20a6c8a668e296ec22785962451 100644 (file)
@@ -242,7 +242,9 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex,
        I != E; ++I) {
     
     Pred = *I;
-    
+    ProgramStateRef state = Pred->getState();
+    const LocationContext *LCtx = Pred->getLocationContext();
+
     switch (CastE->getCastKind()) {
       case CK_LValueToRValue:
         llvm_unreachable("LValueToRValue casts handled earlier.");
@@ -262,6 +264,7 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex,
       case CK_NonAtomicToAtomic:
         // True no-ops.
       case CK_NoOp:
+      case CK_UserDefinedConversion:
       case CK_FunctionToPointerDecay: {
         // Copy the SVal of Ex to CastE.
         ProgramStateRef state = Pred->getState();
@@ -299,8 +302,6 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex,
       case CK_AnyPointerToBlockPointerCast:  
       case CK_ObjCObjectLValueCast: {
         // Delegate to SValBuilder to process.
-        ProgramStateRef state = Pred->getState();
-        const LocationContext *LCtx = Pred->getLocationContext();
         SVal V = state->getSVal(Ex, LCtx);
         V = svalBuilder.evalCast(V, T, ExTy);
         state = state->BindExpr(CastE, LCtx, V);
@@ -310,8 +311,6 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex,
       case CK_DerivedToBase:
       case CK_UncheckedDerivedToBase: {
         // For DerivedToBase cast, delegate to the store manager.
-        ProgramStateRef state = Pred->getState();
-        const LocationContext *LCtx = Pred->getLocationContext();
         SVal val = state->getSVal(Ex, LCtx);
         val = getStoreManager().evalDerivedToBase(val, CastE);
         state = state->BindExpr(CastE, LCtx, val);
@@ -320,8 +319,6 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex,
       }
       // Handle C++ dyn_cast.
       case CK_Dynamic: {
-        ProgramStateRef state = Pred->getState();
-        const LocationContext *LCtx = Pred->getLocationContext();
         SVal val = state->getSVal(Ex, LCtx);
 
         // Compute the type of the result.
@@ -369,7 +366,6 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex,
       case CK_BaseToDerivedMemberPointer:
       case CK_DerivedToBaseMemberPointer:
       case CK_ReinterpretMemberPointer:
-      case CK_UserDefinedConversion:
       case CK_ConstructorConversion:
       case CK_VectorSplat:
       case CK_MemberPointerToBoolean:
@@ -378,12 +374,10 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex,
         QualType resultType = CastE->getType();
         if (CastE->isGLValue())
           resultType = getContext().getPointerType(resultType);
-        const LocationContext *LCtx = Pred->getLocationContext();
         SVal result = svalBuilder.conjureSymbolVal(0, CastE, LCtx,
                                                    resultType,
                                                    currBldrCtx->blockCount());
-        ProgramStateRef state = Pred->getState()->BindExpr(CastE, LCtx,
-                                                               result);
+        state = state->BindExpr(CastE, LCtx, result);
         Bldr.generateNode(CastE, Pred, state);
         continue;
       }
index dbc63bc4bed827eefd15db3e9737bc6dfed1cac5..4fb214f901366299bf3a6d28690ff10e21f14a2e 100644 (file)
@@ -30,3 +30,22 @@ struct IntComparable {
 void testMemberOperator(IntComparable B) {
   clang_analyzer_eval(B == 0); // expected-warning{{TRUE}}
 }
+
+
+
+namespace UserDefinedConversions {
+  class Convertible {
+  public:
+    operator int() const {
+      return 42;
+    }
+    operator bool() const {
+      return true;
+    }
+  };
+
+  void test(const Convertible &obj) {
+    clang_analyzer_eval((int)obj == 42); // expected-warning{{TRUE}}
+    clang_analyzer_eval(obj); // expected-warning{{TRUE}}
+  }
+}