From 3503cb3572922059b35d86e9f93f172fb6b23bb3 Mon Sep 17 00:00:00 2001 From: Jordan Rose Date: Wed, 27 Mar 2013 18:10:35 +0000 Subject: [PATCH] [analyzer] Use evalBind for C++ new of scalar types. These types will not have a CXXConstructExpr to do the initialization for them. Previously we just used a simple call to ProgramState::bindLoc, but that doesn't trigger proper checker callbacks (like pointer escape). Found by Anton Yartsev. llvm-svn: 178160 --- clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp | 17 ++++++++++------- clang/test/Analysis/new.cpp | 17 ++++++++++++++++- 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp index d1a591c7fe06..0fedf255d6f5 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp @@ -331,20 +331,23 @@ void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred, State = State->BindExpr(CNE, LCtx, symVal); } + Bldr.generateNode(CNE, Pred, State); + // If the type is not a record, we won't have a CXXConstructExpr as an // initializer. Copy the value over. if (const Expr *Init = CNE->getInitializer()) { if (!isa(Init)) { - QualType ObjTy = CNE->getType()->getAs()->getPointeeType(); - (void)ObjTy; - assert(!ObjTy->isRecordType()); + assert(Bldr.getResults().size() == 1); + ExplodedNode *TmpN = *Bldr.getResults().begin(); + Bldr.takeNodes(TmpN); + + assert(!CNE->getType()->getPointeeCXXRecordDecl()); + SVal Location = State->getSVal(CNE, LCtx); - if (Optional LV = Location.getAs()) - State = State->bindLoc(*LV, State->getSVal(Init, LCtx)); + bool FirstInit = (Location == symVal); + evalBind(Dst, CNE, TmpN, Location, State->getSVal(Init, LCtx), FirstInit); } } - - Bldr.generateNode(CNE, Pred, State); } void ExprEngine::VisitCXXDeleteExpr(const CXXDeleteExpr *CDE, diff --git a/clang/test/Analysis/new.cpp b/clang/test/Analysis/new.cpp index 701ac8bc5568..004a05ef94f6 100644 --- a/clang/test/Analysis/new.cpp +++ b/clang/test/Analysis/new.cpp @@ -76,7 +76,22 @@ struct PtrWrapper { PtrWrapper *testNewInvalidation() { // Ensure that we don't consider this a leak. - return new PtrWrapper(static_cast(malloc(4))); + return new PtrWrapper(static_cast(malloc(4))); // no-warning +} + +void testNewInvalidationPlacement(PtrWrapper *w) { + // Ensure that we don't consider this a leak. + new (w) PtrWrapper(static_cast(malloc(4))); // no-warning +} + +int **testNewInvalidationScalar() { + // Ensure that we don't consider this a leak. + return new (int *)(static_cast(malloc(4))); // no-warning +} + +void testNewInvalidationScalarPlacement(int **p) { + // Ensure that we don't consider this a leak. + new (p) (int *)(static_cast(malloc(4))); // no-warning } //--------------------------------------------------------------------