Index: lib/StaticAnalyzer/Core/CallEvent.cpp =================================================================== --- lib/StaticAnalyzer/Core/CallEvent.cpp +++ lib/StaticAnalyzer/Core/CallEvent.cpp @@ -583,11 +583,18 @@ ASTContext &Ctx = SVB.getContext(); const CXXRecordDecl *Class = MD->getParent(); QualType Ty = Ctx.getPointerType(Ctx.getRecordType(Class)); - // FIXME: CallEvent maybe shouldn't be directly accessing StoreManager. bool Failed; ThisVal = StateMgr.getStoreManager().attemptDownCast(ThisVal, Ty, Failed); - assert(!Failed && "Calling an incorrectly devirtualized method"); + if (Failed) { + // We might have suffered some sort of placement new earlier, so + // we're constructing in a completely unexpected storage. + // Fall back to a generic pointer cast for this-value. + const CXXMethodDecl *StaticMD = cast(getDecl()); + const CXXRecordDecl *StaticClass = StaticMD->getParent(); + QualType StaticTy = Ctx.getPointerType(Ctx.getRecordType(StaticClass)); + ThisVal = SVB.evalCast(ThisVal, Ty, StaticTy); + } } if (!ThisVal.isUnknown()) Index: test/Analysis/new-dynamic-types.cpp =================================================================== --- /dev/null +++ test/Analysis/new-dynamic-types.cpp @@ -0,0 +1,22 @@ +// RUN: %clang_analyze_cc1 -analyzer-checker=core -std=c++11 -verify %s + +// expected-no-diagnostics + +typedef __typeof(sizeof(int)) size_t; + +void *operator new(size_t size, void *ptr); + +struct B { + virtual void foo(); +}; + +struct D : public B { + virtual void foo() override {} +}; + +void test() { + // FIXME: Potentially warn because this code is pretty weird. + B b; + new (&b) D; + b.foo(); // no-crash +}