Author: dergachev Date: Tue Feb 27 12:54:40 2018 New Revision: 326245 URL: http://llvm.org/viewvc/llvm-project?rev=326245&view=rev Log: [analyzer] Don't crash when dynamic type of a variable is set via placement new.
If a variable or an otherwise a concrete typed-value region is being placement-new'ed into, its dynamic type may change in arbitrary manners. And when the region is used, there may be a third type that's different from both the static and the dynamic type. It cannot be *completely* different from the dynamic type, but it may be a base class of the dynamic type - and in this case there isn't (and shouldn't be) any indication anywhere in the AST that there is a derived-to-base cast from the dynamic type to the third type. Perform a generic cast (evalCast()) from the third type to the dynamic type in this case. From the point of view of the SVal hierarchy, this would have produced non-canonical SVals if we used such generic cast in the normal case, but in this case there doesn't seem to be a better option. Differential Revision: https://reviews.llvm.org/D43659 Added: cfe/trunk/test/Analysis/new-dynamic-types.cpp Modified: cfe/trunk/lib/StaticAnalyzer/Core/CallEvent.cpp Modified: cfe/trunk/lib/StaticAnalyzer/Core/CallEvent.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/CallEvent.cpp?rev=326245&r1=326244&r2=326245&view=diff ============================================================================== --- cfe/trunk/lib/StaticAnalyzer/Core/CallEvent.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Core/CallEvent.cpp Tue Feb 27 12:54:40 2018 @@ -587,7 +587,15 @@ void CXXInstanceCall::getInitialStackFra // 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<CXXMethodDecl>(getDecl()); + const CXXRecordDecl *StaticClass = StaticMD->getParent(); + QualType StaticTy = Ctx.getPointerType(Ctx.getRecordType(StaticClass)); + ThisVal = SVB.evalCast(ThisVal, Ty, StaticTy); + } } if (!ThisVal.isUnknown()) Added: cfe/trunk/test/Analysis/new-dynamic-types.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/new-dynamic-types.cpp?rev=326245&view=auto ============================================================================== --- cfe/trunk/test/Analysis/new-dynamic-types.cpp (added) +++ cfe/trunk/test/Analysis/new-dynamic-types.cpp Tue Feb 27 12:54:40 2018 @@ -0,0 +1,28 @@ +// 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_ub() { + // FIXME: Potentially warn because this code is pretty weird. + B b; + new (&b) D; + b.foo(); // no-crash +} + +void test_non_ub() { + char c[sizeof(D)]; // Should be enough storage. + new (c) D; + ((B *)c)->foo(); // no-crash +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits