Index: include/clang/Analysis/CFG.h =================================================================== --- include/clang/Analysis/CFG.h +++ include/clang/Analysis/CFG.h @@ -138,15 +138,34 @@ // CFGElement's room (pair of pointers). Contains the information // necessary to express what memory is being initialized by // the construction. -struct ConstructionContext { +class ConstructionContext { CXXConstructExpr *Constructor; - Stmt *Trigger; + llvm::PointerUnion Trigger; + +public: + ConstructionContext(CXXConstructExpr *Constructor, + Stmt *Trigger) + : Constructor(Constructor), Trigger(Trigger) {} + + ConstructionContext(CXXConstructExpr *Constructor, + CXXCtorInitializer *Trigger) + : Constructor(Constructor), Trigger(Trigger) {} const ConstructionContext *getPersistentCopy(BumpVectorContext &C) const { ConstructionContext *CC = C.getAllocator().Allocate(); *CC = *this; return CC; } + + const CXXConstructExpr *getConstructor() const { + return Constructor; + } + const Stmt *getTriggerStmt() const { + return Trigger.dyn_cast(); + } + const CXXCtorInitializer *getTriggerInit() const { + return Trigger.dyn_cast(); + } }; /// CFGConstructor - Represents C++ constructor call. Maintains information @@ -161,13 +180,21 @@ return static_cast(Data1.getPointer()); } - CXXConstructExpr *getConstructor() const { - return getConstructionContext()->Constructor; + const CXXConstructExpr *getConstructor() const { + return getConstructionContext()->getConstructor();; + } + + QualType getType() const { + return getConstructor()->getType(); } - QualType getType() const { return getConstructor()->getType(); } + const Stmt *getTriggerStmt() const { + return getConstructionContext()->getTriggerStmt(); + } - Stmt *getTriggerStmt() const { return getConstructionContext()->Trigger; } + const CXXCtorInitializer *getTriggerInit() const { + return getConstructionContext()->getTriggerInit(); + } private: friend class CFGElement; Index: lib/Analysis/CFG.cpp =================================================================== --- lib/Analysis/CFG.cpp +++ lib/Analysis/CFG.cpp @@ -688,7 +688,7 @@ void appendConstructor(CFGBlock *B, CXXConstructExpr *CE) { if (!ConstructionContexts.empty()) { const ConstructionContext &CC = ConstructionContexts.back(); - if (CC.Constructor == CE) { + if (CC.getConstructor() == CE) { B->appendConstructor(CC, cfg->getBumpVectorContext()); return; } @@ -1259,6 +1259,9 @@ appendInitializer(Block, I); if (Init) { + if (CXXConstructExpr *CE = dyn_cast(Init)) + ConstructionContexts.push_back({/*Constructor=*/CE, /*Trigger=*/I}); + if (HasTemporaries) { // For expression with temporaries go directly to subexpression to omit // generating destructors for the second time. @@ -4579,6 +4582,27 @@ } // namespace +static void print_initializer(raw_ostream &OS, StmtPrinterHelper &Helper, + const CXXCtorInitializer *I) { + if (I->isBaseInitializer()) + OS << I->getBaseClass()->getAsCXXRecordDecl()->getName(); + else if (I->isDelegatingInitializer()) + OS << I->getTypeSourceInfo()->getType()->getAsCXXRecordDecl()->getName(); + else + OS << I->getAnyMember()->getName(); + OS << "("; + if (Expr *IE = I->getInit()) + IE->printPretty(OS, &Helper, PrintingPolicy(Helper.getLangOpts())); + OS << ")"; + + if (I->isBaseInitializer()) + OS << " (Base initializer)"; + else if (I->isDelegatingInitializer()) + OS << " (Delegating initializer)"; + else + OS << " (Member initializer)"; +} + static void print_elem(raw_ostream &OS, StmtPrinterHelper &Helper, const CFGElement &E) { if (Optional CS = E.getAs()) { @@ -4628,26 +4652,14 @@ CE->getConstructor()->printPretty(OS, &Helper, PrintingPolicy(Helper.getLangOpts())); OS << " (CXXConstructExpr, "; - Helper.handledStmt((CE->getTriggerStmt()), OS); + if (const Stmt *S = CE->getTriggerStmt()) + Helper.handledStmt((const_cast(S)), OS); + else + print_initializer(OS, Helper, CE->getTriggerInit()); OS << ", " << CE->getType().getAsString() << ")\n"; } else if (Optional IE = E.getAs()) { - const CXXCtorInitializer *I = IE->getInitializer(); - if (I->isBaseInitializer()) - OS << I->getBaseClass()->getAsCXXRecordDecl()->getName(); - else if (I->isDelegatingInitializer()) - OS << I->getTypeSourceInfo()->getType()->getAsCXXRecordDecl()->getName(); - else OS << I->getAnyMember()->getName(); - - OS << "("; - if (Expr *IE = I->getInit()) - IE->printPretty(OS, &Helper, PrintingPolicy(Helper.getLangOpts())); - OS << ")"; - - if (I->isBaseInitializer()) - OS << " (Base initializer)\n"; - else if (I->isDelegatingInitializer()) - OS << " (Delegating initializer)\n"; - else OS << " (Member initializer)\n"; + print_initializer(OS, Helper, IE->getInitializer()); + OS << '\n'; } else if (Optional DE = E.getAs()) { const VarDecl *VD = DE->getVarDecl(); Index: test/Analysis/initializers-cfg-output.cpp =================================================================== --- test/Analysis/initializers-cfg-output.cpp +++ test/Analysis/initializers-cfg-output.cpp @@ -53,13 +53,13 @@ // CHECK: [B2 (ENTRY)] // CHECK: Succs (1): B1 // CHECK: [B1] -// CHECK: 1: (CXXConstructExpr, class A) +// CHECK: 1: (CXXConstructExpr, A() (Base initializer), class A) // CHECK: 2: A([B1.1]) (Base initializer) -// CHECK: 3: (CXXConstructExpr, class C) +// CHECK: 3: (CXXConstructExpr, C() (Base initializer), class C) // CHECK: 4: C([B1.3]) (Base initializer) -// CHECK: 5: (CXXConstructExpr, class B) +// CHECK: 5: (CXXConstructExpr, B() (Base initializer), class B) // CHECK: 6: B([B1.5]) (Base initializer) -// CHECK: 7: (CXXConstructExpr, class A) +// CHECK: 7: (CXXConstructExpr, A() (Base initializer), class A) // CHECK: 8: A([B1.7]) (Base initializer) // CHECK: 9: /*implicit*/(int)0 // CHECK: 10: i([B1.9]) (Member initializer) @@ -107,7 +107,7 @@ // CHECK: [B1] // CHECK: 1: 2 // CHECK: 2: 3 -// CHECK: 3: [B1.1], [B1.2] (CXXConstructExpr, class TestDelegating) +// CHECK: 3: [B1.1], [B1.2] (CXXConstructExpr, TestDelegating([B1.1], [B1.2]) (Delegating initializer), class TestDelegating) // CHECK: 4: TestDelegating([B1.3]) (Delegating initializer) // CHECK: Preds (1): B2 // CHECK: Succs (1): B0