Index: lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp =================================================================== --- lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp +++ lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp @@ -46,7 +46,7 @@ check::PreStmt, check::PreStmt, check::PreStmt, check::PreStmt, check::PostStmt, check::PostStmt, - check::PostStmt, check::DeadSymbols> { + check::PostStmt, check::DeadSymbols, check::NewAllocator> { AllocKind getKindOfNewOp(const CXXNewExpr *NE, const FunctionDecl *FD) const; const MemRegion *getArrayRegion(const MemRegion *Region, bool &Polymorphic, AllocKind &AKind, CheckerContext &C) const; @@ -56,6 +56,9 @@ bool PointedNeeded = false) const; void initAllocIdentifiers(ASTContext &C) const; + void processNewAllocatorAux(const CXXNewExpr *NE, SVal Target, + CheckerContext &C) const; + mutable std::unique_ptr BT_pointerArith; mutable std::unique_ptr BT_polyArray; mutable llvm::SmallSet AllocFunctions; @@ -69,6 +72,8 @@ void checkPostStmt(const CXXNewExpr *NE, CheckerContext &C) const; void checkPostStmt(const CallExpr *CE, CheckerContext &C) const; void checkDeadSymbols(SymbolReaper &SR, CheckerContext &C) const; + void checkNewAllocator(const CXXNewExpr *NE, SVal Target, + CheckerContext &C) const; }; } // end namespace @@ -239,21 +244,34 @@ C.addTransition(State); } -void PointerArithChecker::checkPostStmt(const CXXNewExpr *NE, - CheckerContext &C) const { +void PointerArithChecker::processNewAllocatorAux(const CXXNewExpr *NE, + SVal Target, + CheckerContext &C) const { const FunctionDecl *FD = NE->getOperatorNew(); if (!FD) return; - AllocKind Kind = getKindOfNewOp(NE, FD); - - ProgramStateRef State = C.getState(); - SVal AllocedVal = State->getSVal(NE, C.getLocationContext()); - const MemRegion *Region = AllocedVal.getAsRegion(); + const MemRegion *Region = Target.getAsRegion(); if (!Region) return; - State = State->set(Region, Kind); - C.addTransition(State); + + Region = Region->StripCasts(); + + AllocKind Kind = getKindOfNewOp(NE, FD); + + C.addTransition(C.getState()->set(Region, Kind)); +} + +void PointerArithChecker::checkPostStmt(const CXXNewExpr *NE, + CheckerContext &C) const { + if (!C.getAnalysisManager().getAnalyzerOptions().mayInlineCXXAllocator()) + processNewAllocatorAux(NE, C.getSVal(NE), C); +} + +void PointerArithChecker::checkNewAllocator(const CXXNewExpr *NE, + SVal Target, CheckerContext &C) const { + if (!C.wasInlined) + processNewAllocatorAux(NE, Target, C); } void PointerArithChecker::checkPostStmt(const CastExpr *CE, Index: test/Analysis/ptr-arith.cpp =================================================================== --- test/Analysis/ptr-arith.cpp +++ test/Analysis/ptr-arith.cpp @@ -1,4 +1,5 @@ // RUN: %clang_analyze_cc1 -Wno-unused-value -std=c++14 -analyzer-checker=core,debug.ExprInspection,alpha.core.PointerArithm -verify %s +// RUN: %clang_analyze_cc1 -Wno-unused-value -std=c++14 -analyzer-checker=core,debug.ExprInspection,alpha.core.PointerArithm -analyzer-config c++-allocator-inlining=true -verify %s struct X { int *p; int zero;