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