Author: dergachev Date: Fri Feb 23 18:00:30 2018 New Revision: 326014 URL: http://llvm.org/viewvc/llvm-project?rev=326014&view=rev Log: [CFG] Provide construction contexts for lifetime-extended temporaries.
When constructing a temporary that is going to be lifetime-extended through a MaterializeTemporaryExpr later, CFG elements for the respective constructor can now be queried to obtain the reference to that MaterializeTemporaryExpr and therefore gain information about lifetime extension. This may produce multi-layered construction contexts when information about both temporary destruction and lifetime extension is available. Differential Revision: https://reviews.llvm.org/D43477 Modified: cfe/trunk/include/clang/Analysis/CFG.h cfe/trunk/lib/Analysis/CFG.cpp cfe/trunk/test/Analysis/cfg-rich-constructors.cpp cfe/trunk/test/Analysis/temp-obj-dtors-cfg-output.cpp Modified: cfe/trunk/include/clang/Analysis/CFG.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/CFG.h?rev=326014&r1=326013&r2=326014&view=diff ============================================================================== --- cfe/trunk/include/clang/Analysis/CFG.h (original) +++ cfe/trunk/include/clang/Analysis/CFG.h Fri Feb 23 18:00:30 2018 @@ -193,6 +193,17 @@ public: return Trigger.dyn_cast<CXXCtorInitializer *>(); } + const MaterializeTemporaryExpr *getMaterializedTemporary() const { + // TODO: Be more careful to ensure that there's only one MTE around. + for (const ConstructionContext *CC = this; CC; CC = CC->getParent()) { + if (const auto *MTE = dyn_cast_or_null<MaterializeTemporaryExpr>( + CC->getTriggerStmt())) { + return MTE; + } + } + return nullptr; + } + bool isSameAsPartialContext(const ConstructionContext *Other) const { assert(Other); return (Trigger == Other->Trigger); @@ -248,6 +259,10 @@ public: return getConstructionContext()->getTriggerInit(); } + const MaterializeTemporaryExpr *getMaterializedTemporary() const { + return getConstructionContext()->getMaterializedTemporary(); + } + private: friend class CFGElement; Modified: cfe/trunk/lib/Analysis/CFG.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/CFG.cpp?rev=326014&r1=326013&r2=326014&view=diff ============================================================================== --- cfe/trunk/lib/Analysis/CFG.cpp (original) +++ cfe/trunk/lib/Analysis/CFG.cpp Fri Feb 23 18:00:30 2018 @@ -548,6 +548,8 @@ private: Stmt *Term, CFGBlock *TrueBlock, CFGBlock *FalseBlock); + CFGBlock *VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *MTE, + AddStmtChoice asc); CFGBlock *VisitMemberExpr(MemberExpr *M, AddStmtChoice asc); CFGBlock *VisitObjCAtCatchStmt(ObjCAtCatchStmt *S); CFGBlock *VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *S); @@ -1840,6 +1842,10 @@ CFGBlock *CFGBuilder::Visit(Stmt * S, Ad case Stmt::LambdaExprClass: return VisitLambdaExpr(cast<LambdaExpr>(S), asc); + case Stmt::MaterializeTemporaryExprClass: + return VisitMaterializeTemporaryExpr(cast<MaterializeTemporaryExpr>(S), + asc); + case Stmt::MemberExprClass: return VisitMemberExpr(cast<MemberExpr>(S), asc); @@ -2975,6 +2981,16 @@ CFGBlock *CFGBuilder::VisitForStmt(ForSt return EntryConditionBlock; } +CFGBlock * +CFGBuilder::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *MTE, + AddStmtChoice asc) { + findConstructionContexts( + ConstructionContext::create(cfg->getBumpVectorContext(), MTE), + MTE->getTemporary()); + + return VisitStmt(MTE, asc); +} + CFGBlock *CFGBuilder::VisitMemberExpr(MemberExpr *M, AddStmtChoice asc) { if (asc.alwaysAdd(*this, M)) { autoCreateBlock(); @@ -4706,13 +4722,20 @@ static void print_elem(raw_ostream &OS, } else if (const CXXConstructExpr *CCE = dyn_cast<CXXConstructExpr>(S)) { OS << " (CXXConstructExpr, "; if (Optional<CFGConstructor> CE = E.getAs<CFGConstructor>()) { + // TODO: Refactor into ConstructionContext::print(). if (const Stmt *S = CE->getTriggerStmt()) - Helper.handledStmt((const_cast<Stmt *>(S)), OS); + Helper.handledStmt(const_cast<Stmt *>(S), OS); else if (const CXXCtorInitializer *I = CE->getTriggerInit()) print_initializer(OS, Helper, I); else llvm_unreachable("Unexpected trigger kind!"); OS << ", "; + if (const Stmt *S = CE->getMaterializedTemporary()) { + if (S != CE->getTriggerStmt()) { + Helper.handledStmt(const_cast<Stmt *>(S), OS); + OS << ", "; + } + } } OS << CCE->getType().getAsString() << ")"; } else if (const CastExpr *CE = dyn_cast<CastExpr>(S)) { Modified: cfe/trunk/test/Analysis/cfg-rich-constructors.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/cfg-rich-constructors.cpp?rev=326014&r1=326013&r2=326014&view=diff ============================================================================== --- cfe/trunk/test/Analysis/cfg-rich-constructors.cpp (original) +++ cfe/trunk/test/Analysis/cfg-rich-constructors.cpp Fri Feb 23 18:00:30 2018 @@ -133,11 +133,10 @@ void simpleVariableWithTernaryOperator(b C c = coin ? C::get() : C(0); } -// TODO: Should find construction target here. // CHECK: void referenceVariableWithConstructor() // CHECK: 1: 0 // CHECK-NEXT: 2: [B1.1] (ImplicitCastExpr, NullToPointer, class C *) -// CHECK-NEXT: 3: [B1.2] (CXXConstructExpr, const class C) +// CHECK-NEXT: 3: [B1.2] (CXXConstructExpr, [B1.4], const class C) // CHECK-NEXT: 4: [B1.3] // CHECK-NEXT: 5: const C &c(0); void referenceVariableWithConstructor() { @@ -267,9 +266,8 @@ C returnBracesWithMultipleItems() { return {123, 456}; } -// TODO: Should find construction targets for the first constructor as well. // CHECK: C returnTemporary() -// CHECK: 1: C() (CXXConstructExpr, class C) +// CHECK: 1: C() (CXXConstructExpr, [B1.2], class C) // CHECK-NEXT: 2: [B1.1] // CHECK-NEXT: 3: [B1.2] (CXXConstructExpr, [B1.4], class C) // CHECK-NEXT: 4: return [B1.3]; @@ -400,7 +398,7 @@ void temporaryInCondition() { // CHECK: void referenceVariableWithConstructor() // CHECK: 1: 0 -// CHECK-NEXT: 2: [B1.1] (CXXConstructExpr, [B1.3], const class temporary_object_expr_with_dtors::D) +// CHECK-NEXT: 2: [B1.1] (CXXConstructExpr, [B1.3], [B1.4], const class temporary_object_expr_with_dtors::D) // CHECK-NEXT: 3: [B1.2] (BindTemporary) // CHECK-NEXT: 4: [B1.3] // CHECK-NEXT: 5: const temporary_object_expr_with_dtors::D &d(0); Modified: cfe/trunk/test/Analysis/temp-obj-dtors-cfg-output.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/temp-obj-dtors-cfg-output.cpp?rev=326014&r1=326013&r2=326014&view=diff ============================================================================== --- cfe/trunk/test/Analysis/temp-obj-dtors-cfg-output.cpp (original) +++ cfe/trunk/test/Analysis/temp-obj-dtors-cfg-output.cpp Fri Feb 23 18:00:30 2018 @@ -714,7 +714,9 @@ int testConsistencyNestedNormalReturn(bo // CHECK: Preds (1): B3 // CHECK: Succs (1): B0 // CHECK: [B3] -// CHECK: 1: D() (CXXConstructExpr, struct D) +// WARNINGS: 1: D() (CXXConstructExpr, struct D) +// CXX98-ANALYZER: 1: D() (CXXConstructExpr, struct D) +// CXX11-ANALYZER: 1: D() (CXXConstructExpr, [B3.2], struct D) // CXX98: 2: [B3.1] (ImplicitCastExpr, NoOp, const struct D) // CXX98: 3: [B3.2] // CXX98-WARNINGS: 4: [B3.3] (CXXConstructExpr, struct D) @@ -925,7 +927,8 @@ int testConsistencyNestedNormalReturn(bo // CHECK: Succs (1): B4 // CHECK: [B7] // WARNINGS: 1: A() (CXXConstructExpr, class A) -// ANALYZER: 1: A() (CXXConstructExpr, [B7.2], class A) +// ANALYZER-CXX98: 1: A() (CXXConstructExpr, [B7.2], [B7.3], class A) +// ANALYZER-CXX11: 1: A() (CXXConstructExpr, [B7.2], class A) // CHECK: 2: [B7.1] (BindTemporary) // CXX98: 3: [B7.2].operator bool // CXX98: 4: [B7.2] @@ -992,7 +995,8 @@ int testConsistencyNestedNormalReturn(bo // CHECK: 1: foo // CHECK: 2: [B7.1] (ImplicitCastExpr, FunctionToPointerDecay, void (*)(const class A &)) // WARNINGS: 3: A() (CXXConstructExpr, class A) -// ANALYZER: 3: A() (CXXConstructExpr, [B7.4], class A) +// ANALYZER-CXX98: 3: A() (CXXConstructExpr, [B7.4], class A) +// ANALYZER-CXX11: 3: A() (CXXConstructExpr, class A) // CHECK: 4: [B7.3] (BindTemporary) // CXX98: 5: [B7.4].operator bool // CXX98: 6: [B7.4] @@ -1043,7 +1047,8 @@ int testConsistencyNestedNormalReturn(bo // CHECK: Succs (1): B9 // CHECK: [B12] // WARNINGS: 1: A() (CXXConstructExpr, class A) -// ANALYZER: 1: A() (CXXConstructExpr, [B12.2], class A) +// ANALYZER-CXX98: 1: A() (CXXConstructExpr, [B12.2], [B12.3], class A) +// ANALYZER-CXX11: 1: A() (CXXConstructExpr, [B12.2], class A) // CHECK: 2: [B12.1] (BindTemporary) // CXX98: 3: [B12.2].operator bool // CXX98: 4: [B12.2] @@ -1199,7 +1204,8 @@ int testConsistencyNestedNormalReturn(bo // CHECK: [B2 (NORETURN)] // CHECK: 1: int a; // WARNINGS: 2: NoReturn() (CXXConstructExpr, class NoReturn) -// ANALYZER: 2: NoReturn() (CXXConstructExpr, [B2.3], class NoReturn) +// ANALYZER-CXX98: 2: NoReturn() (CXXConstructExpr, [B2.3], [B2.4], class NoReturn) +// ANALYZER-CXX11: 2: NoReturn() (CXXConstructExpr, [B2.3], class NoReturn) // CHECK: 3: [B2.2] (BindTemporary) // CHECK: [[MEMBER:[45]]]: [B2.{{[34]}}].f // CHECK: {{[56]}}: [B2.[[MEMBER]]]() _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits