]> granicus.if.org Git - clang/commitdiff
[analyzer] Type information from C++ new expressions is perfect.
authorJordan Rose <jordan_rose@apple.com>
Mon, 22 Apr 2013 21:36:44 +0000 (21:36 +0000)
committerJordan Rose <jordan_rose@apple.com>
Mon, 22 Apr 2013 21:36:44 +0000 (21:36 +0000)
This improves our handling of dynamic_cast and devirtualization for
objects allocated by 'new'.

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

lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp
test/Analysis/inline.cpp
test/Analysis/inlining/dyn-dispatch-bifurcate.cpp

index 9f176a4b5bf7df7931273d5b09ad6a1441aec19a..759aa6605ee70c9b9e69524603d500d4cb65d166 100644 (file)
@@ -27,7 +27,8 @@ namespace {
 class DynamicTypePropagation:
     public Checker< check::PreCall,
                     check::PostCall,
-                    check::PostStmt<ImplicitCastExpr> > {
+                    check::PostStmt<ImplicitCastExpr>,
+                    check::PostStmt<CXXNewExpr> > {
   const ObjCObjectType *getObjectTypeForAllocAndNew(const ObjCMessageExpr *MsgE,
                                                     CheckerContext &C) const;
 
@@ -38,6 +39,7 @@ public:
   void checkPreCall(const CallEvent &Call, CheckerContext &C) const;
   void checkPostCall(const CallEvent &Call, CheckerContext &C) const;
   void checkPostStmt(const ImplicitCastExpr *CastE, CheckerContext &C) const;
+  void checkPostStmt(const CXXNewExpr *NewE, CheckerContext &C) const;
 };
 }
 
@@ -190,6 +192,20 @@ void DynamicTypePropagation::checkPostStmt(const ImplicitCastExpr *CastE,
   return;
 }
 
+void DynamicTypePropagation::checkPostStmt(const CXXNewExpr *NewE,
+                                           CheckerContext &C) const {
+  if (NewE->isArray())
+    return;
+
+  // We only track dynamic type info for regions.
+  const MemRegion *MR = C.getSVal(NewE).getAsRegion();
+  if (!MR)
+    return;
+  
+  C.addTransition(C.getState()->setDynamicTypeInfo(MR, NewE->getType(),
+                                                   /*CanBeSubclass=*/false));
+}
+
 const ObjCObjectType *
 DynamicTypePropagation::getObjectTypeForAllocAndNew(const ObjCMessageExpr *MsgE,
                                                     CheckerContext &C) const {
index a16fa00d12b0b41e60a10d64eed693b0efbb49f8..62bce284721b55621820304133ec2d13ad0de2e2 100644 (file)
@@ -351,9 +351,7 @@ namespace VirtualWithSisterCasts {
 
   void testCastViaNew(B *b) {
     Grandchild *g = new (b) Grandchild();
-    // FIXME: We actually now have perfect type info because of 'new'.
-    // This should be TRUE.
-    clang_analyzer_eval(g->foo() == 42); // expected-warning{{UNKNOWN}}
+    clang_analyzer_eval(g->foo() == 42); // expected-warning{{TRUE}}
 
     g->x = 42;
     clang_analyzer_eval(g->x == 42); // expected-warning{{TRUE}}
index 890e5640cefbf04fb04c70e024f1cb4c1753bce3..d219446fc963744242a8f7d108d0ea9a85d451ba 100644 (file)
@@ -16,6 +16,11 @@ void testKnown() {
   clang_analyzer_eval(a.get() == 0); // expected-warning{{TRUE}}
 }
 
+void testNew() {
+  A *a = new A();
+  clang_analyzer_eval(a->get() == 0); // expected-warning{{TRUE}}
+}
+
 
 namespace ReinterpretDisruptsDynamicTypeInfo {
   class Parent {};