Index: include/clang/Analysis/CFG.h =================================================================== --- include/clang/Analysis/CFG.h +++ include/clang/Analysis/CFG.h @@ -162,6 +162,8 @@ bool isNull() const { return Trigger.isNull(); } + TriggerTy getTrigger() const { return Trigger; } + const Stmt *getTriggerStmt() const { return Trigger.dyn_cast(); } @@ -192,6 +194,14 @@ return static_cast(Data2.getPointer()); } + QualType getType() const { + return cast(getStmt())->getType(); + } + + ConstructionContext::TriggerTy getTrigger() const { + return getConstructionContext()->getTrigger(); + } + const Stmt *getTriggerStmt() const { return getConstructionContext()->getTriggerStmt(); } Index: include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h =================================================================== --- include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h +++ include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h @@ -665,13 +665,6 @@ /// constructing into an existing region. const CXXConstructExpr *findDirectConstructorForCurrentCFGElement(); - /// For a CXXConstructExpr, walk forward in the current CFG block to find the - /// CFGElement for the DeclStmt or CXXInitCtorInitializer or CXXNewExpr which - /// is directly constructed by this constructor. Returns None if the current - /// constructor expression did not directly construct into an existing - /// region. - Optional findElementDirectlyInitializedByCurrentConstructor(); - /// For a given constructor, look forward in the current CFG block to /// determine the region into which an object will be constructed by \p CE. /// When the lookahead fails, a temporary region is returned, and the Index: lib/StaticAnalyzer/Core/ExprEngineCXX.cpp =================================================================== --- lib/StaticAnalyzer/Core/ExprEngineCXX.cpp +++ lib/StaticAnalyzer/Core/ExprEngineCXX.cpp @@ -114,12 +114,14 @@ const LocationContext *LCtx = Pred->getLocationContext(); ProgramStateRef State = Pred->getState(); - // See if we're constructing an existing region by looking at the next - // element in the CFG. - - if (auto Elem = findElementDirectlyInitializedByCurrentConstructor()) { - if (Optional StmtElem = Elem->getAs()) { - if (const CXXNewExpr *CNE = dyn_cast(StmtElem->getStmt())) { + // See if we're constructing an existing region by looking at the + // current construction context. + const NodeBuilderContext &CurrBldrCtx = getBuilderContext(); + const CFGBlock *B = CurrBldrCtx.getBlock(); + const CFGElement &E = (*B)[currStmtIdx]; + if (auto CC = E.getAs()) { + if (const Stmt *TriggerStmt = CC->getTriggerStmt()) { + if (const CXXNewExpr *CNE = dyn_cast(TriggerStmt)) { if (AMgr.getAnalyzerOptions().mayInlineCXXAllocator()) { // TODO: Detect when the allocator returns a null pointer. // Constructor shall not be called in this case. @@ -135,7 +137,7 @@ return MR; } } - } else if (auto *DS = dyn_cast(StmtElem->getStmt())) { + } else if (auto *DS = dyn_cast(TriggerStmt)) { if (const auto *Var = dyn_cast(DS->getSingleDecl())) { if (Var->getInit() && Var->getInit()->IgnoreImplicit() == CE) { SVal LValue = State->getLValue(Var, LCtx); @@ -145,11 +147,9 @@ return LValue.getAsRegion(); } } - } else { - llvm_unreachable("Unexpected directly initialized element!"); } - } else if (Optional InitElem = Elem->getAs()) { - const CXXCtorInitializer *Init = InitElem->getInitializer(); + // TODO: Consider other directly initialized elements. + } else if (const CXXCtorInitializer *Init = CC->getTriggerInit()) { assert(Init->isAnyMemberInitializer()); const CXXMethodDecl *CurCtor = cast(LCtx->getDecl()); Loc ThisPtr = @@ -183,53 +183,6 @@ return MRMgr.getCXXTempObjectRegion(CE, LCtx); } -/// Returns true if the initializer for \Elem can be a direct -/// constructor. -static bool canHaveDirectConstructor(CFGElement Elem){ - // DeclStmts and CXXCtorInitializers for fields can be directly constructed. - - if (Optional StmtElem = Elem.getAs()) { - if (isa(StmtElem->getStmt())) { - return true; - } - if (isa(StmtElem->getStmt())) { - return true; - } - } - - if (Elem.getKind() == CFGElement::Initializer) { - return true; - } - - return false; -} - -Optional -ExprEngine::findElementDirectlyInitializedByCurrentConstructor() { - const NodeBuilderContext &CurrBldrCtx = getBuilderContext(); - // See if we're constructing an existing region by looking at the next - // element in the CFG. - const CFGBlock *B = CurrBldrCtx.getBlock(); - assert(isa(((*B)[currStmtIdx]).castAs().getStmt())); - unsigned int NextStmtIdx = currStmtIdx + 1; - if (NextStmtIdx >= B->size()) - return None; - - CFGElement Next = (*B)[NextStmtIdx]; - - // Is this a destructor? If so, we might be in the middle of an assignment - // to a local or member: look ahead one more element to see what we find. - while (Next.getAs() && NextStmtIdx + 1 < B->size()) { - ++NextStmtIdx; - Next = (*B)[NextStmtIdx]; - } - - if (canHaveDirectConstructor(Next)) - return Next; - - return None; -} - const CXXConstructExpr * ExprEngine::findDirectConstructorForCurrentCFGElement() { // Go backward in the CFG to see if the previous element (ignoring @@ -241,7 +194,6 @@ return nullptr; const CFGBlock *B = getBuilderContext().getBlock(); - assert(canHaveDirectConstructor((*B)[currStmtIdx])); unsigned int PreviousStmtIdx = currStmtIdx - 1; CFGElement Previous = (*B)[PreviousStmtIdx];