diff --git a/clang/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp b/clang/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp index 9f176a4b5bf7..759aa6605ee7 100644 --- a/clang/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp @@ -27,7 +27,8 @@ namespace { class DynamicTypePropagation: public Checker< check::PreCall, check::PostCall, - check::PostStmt > { + check::PostStmt, + check::PostStmt > { 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 { diff --git a/clang/test/Analysis/inline.cpp b/clang/test/Analysis/inline.cpp index a16fa00d12b0..62bce284721b 100644 --- a/clang/test/Analysis/inline.cpp +++ b/clang/test/Analysis/inline.cpp @@ -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}} diff --git a/clang/test/Analysis/inlining/dyn-dispatch-bifurcate.cpp b/clang/test/Analysis/inlining/dyn-dispatch-bifurcate.cpp index 890e5640cefb..d219446fc963 100644 --- a/clang/test/Analysis/inlining/dyn-dispatch-bifurcate.cpp +++ b/clang/test/Analysis/inlining/dyn-dispatch-bifurcate.cpp @@ -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 {};