r326014 - [CFG] Provide construction contexts for lifetime-extended temporaries.
Artem Dergachev via cfe-commits
cfe-commits at lists.llvm.org
Fri Feb 23 18:00:30 PST 2018
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]]]()
More information about the cfe-commits
mailing list