]> granicus.if.org Git - clang/commitdiff
[CFG] Provide construction contexts for temproary objects.
authorArtem Dergachev <artem.dergachev@gmail.com>
Thu, 15 Feb 2018 03:13:36 +0000 (03:13 +0000)
committerArtem Dergachev <artem.dergachev@gmail.com>
Thu, 15 Feb 2018 03:13:36 +0000 (03:13 +0000)
Constructors of C++ temporary objects that have destructors now can be queried
to discover that they're indeed constructing temporary objects.

The respective CXXBindTemporaryExpr, which is also repsonsible for destroying
the temporary at the end of full-expression, is now available at the
construction site in the CFG. This is all the context we need to provide for
temporary objects that are not lifetime extended. For lifetime-extended
temporaries, more context is necessary.

Differential Revision: https://reviews.llvm.org/D43056

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@325210 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Analysis/CFG.cpp
test/Analysis/auto-obj-dtors-cfg-output.cpp
test/Analysis/cfg-rich-constructors.cpp
test/Analysis/temp-obj-dtors-cfg-output.cpp

index 9fe9ad11bf38a75e772e855194bd89a30d2fbec7..d2d1917c4688b4cb2e658821d78c745b82756fa9 100644 (file)
@@ -3923,6 +3923,8 @@ CFGBlock *CFGBuilder::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E,
     autoCreateBlock();
     appendStmt(Block, E);
 
+    EnterConstructionContextIfNecessary(E, E->getSubExpr());
+
     // We do not want to propagate the AlwaysAdd property.
     asc = asc.withAlwaysAdd(false);
   }
@@ -3992,7 +3994,7 @@ CFGBlock *CFGBuilder::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E,
 CFGBlock *CFGBuilder::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *C,
                                                   AddStmtChoice asc) {
   autoCreateBlock();
-  appendStmt(Block, C);
+  appendConstructor(Block, C);
   return VisitChildren(C);
 }
 
index 843ccd3bd4455ec7186a9526b401f45a75715abb..42e648312f641300df783a662acd13845f8673ab 100644 (file)
@@ -49,7 +49,8 @@ extern const bool UV;
 // CHECK-NEXT:   3: a
 // CHECK-NEXT:   4: [B1.3] (ImplicitCastExpr, NoOp, const class A)
 // CHECK-NEXT:   5: const A &b = a;
-// CHECK-NEXT:   6: A() (CXXConstructExpr, class A)
+// WARNINGS-NEXT:   6: A() (CXXConstructExpr, class A)
+// ANALYZER-NEXT:   6: A() (CXXConstructExpr, [B1.7], class A)
 // CHECK-NEXT:   7: [B1.6] (BindTemporary)
 // CHECK-NEXT:   8: [B1.7] (ImplicitCastExpr, NoOp, const class A)
 // CHECK-NEXT:   9: [B1.8]
index 46125f729f9805608e37b3a462789ca1c4c7e4be..5818912d267a323748805b78ef8af03dc3a528ce 100644 (file)
@@ -1,4 +1,4 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=debug.DumpCFG -triple x86_64-apple-darwin12 -analyzer-config cfg-temporary-dtors=true -std=c++11 %s > %t 2>&1
+// RUN: %clang_analyze_cc1 -analyzer-checker=debug.DumpCFG -triple x86_64-apple-darwin12 -analyzer-config cfg-temporary-dtors=true -std=c++11 -w %s > %t 2>&1
 // RUN: FileCheck --input-file=%t %s
 
 class C {
@@ -8,6 +8,7 @@ public:
   C(int, int);
 
   static C get();
+  operator bool() const;
 };
 
 typedef __typeof(sizeof(int)) size_t;
@@ -226,7 +227,7 @@ public:
 
 } // end namespace ctor_initializers
 
-namespace return_stmt {
+namespace return_stmt_without_dtor {
 
 // CHECK: C returnVariable()
 // CHECK:          1:  (CXXConstructExpr, [B1.2], class C)
@@ -315,4 +316,140 @@ C returnChainOfCopies() {
   return C(C::get());
 }
 
-} // end namespace return_stmt
+} // end namespace return_stmt_without_dtor
+
+namespace return_stmt_with_dtor {
+
+class D {
+public:
+  D();
+  ~D();
+};
+
+// CHECK:  return_stmt_with_dtor::D returnTemporary()
+// CHECK:          1: return_stmt_with_dtor::D() (CXXConstructExpr, [B1.2], class return_stmt_with_dtor::D)
+// CHECK-NEXT:     2: [B1.1] (BindTemporary)
+// CHECK-NEXT:     3: [B1.2] (ImplicitCastExpr, NoOp, const class return_stmt_with_dtor::D)
+// CHECK-NEXT:     4: [B1.3]
+// CHECK-NEXT:     5: [B1.4] (CXXConstructExpr, [B1.7], class return_stmt_with_dtor::D)
+// CHECK-NEXT:     6: ~return_stmt_with_dtor::D() (Temporary object destructor)
+// CHECK-NEXT:     7: return [B1.5];
+D returnTemporary() {
+  return D();
+}
+
+} // end namespace return_stmt_with_dtor
+
+namespace temporary_object_expr_without_dtors {
+
+// TODO: Should provide construction context for the constructor,
+// even if there is no specific trigger statement here.
+// CHECK: void simpleTemporary()
+// CHECK           1: C() (CXXConstructExpr, class C)
+void simpleTemporary() {
+  C();
+}
+
+// TODO: Should provide construction context for the constructor,
+// CHECK: void temporaryInCondition()
+// CHECK:          1: C() (CXXConstructExpr, class C)
+// CHECK-NEXT:     2: [B2.1] (ImplicitCastExpr, NoOp, const class C)
+// CHECK-NEXT:     3: [B2.2].operator bool
+// CHECK-NEXT:     4: [B2.2]
+// CHECK-NEXT:     5: [B2.4] (ImplicitCastExpr, UserDefinedConversion, _Bool)
+// CHECK-NEXT:     T: if [B2.5]
+void temporaryInCondition() {
+  if (C());
+}
+
+} // end namespace temporary_object_expr_without_dtors
+
+namespace temporary_object_expr_with_dtors {
+
+class D {
+public:
+  D();
+  D(int);
+  ~D();
+
+  static D get();
+
+  operator bool() const;
+};
+
+// CHECK: void simpleTemporary()
+// CHECK:          1: temporary_object_expr_with_dtors::D() (CXXConstructExpr, [B1.2], class temporary_object_expr_with_dtors::D)
+// CHECK-NEXT:     2: [B1.1] (BindTemporary)
+// CHECK-NEXT:     3: ~temporary_object_expr_with_dtors::D() (Temporary object destructor)
+void simpleTemporary() {
+  D();
+}
+
+// CHECK:  void temporaryInCondition()
+// CHECK:          1: temporary_object_expr_with_dtors::D() (CXXConstructExpr, [B2.2], class temporary_object_expr_with_dtors::D)
+// CHECK-NEXT:     2: [B2.1] (BindTemporary)
+// CHECK-NEXT:     3: [B2.2] (ImplicitCastExpr, NoOp, const class temporary_object_expr_with_dtors::D)
+// CHECK-NEXT:     4: [B2.3].operator bool
+// CHECK-NEXT:     5: [B2.3]
+// CHECK-NEXT:     6: [B2.5] (ImplicitCastExpr, UserDefinedConversion, _Bool)
+// CHECK-NEXT:     7: ~temporary_object_expr_with_dtors::D() (Temporary object destructor)
+// CHECK-NEXT:     T: if [B2.6]
+void temporaryInCondition() {
+  if (D());
+}
+
+// CHECK: void referenceVariableWithConstructor()
+// CHECK:          1: 0
+// CHECK-NEXT:     2: [B1.1] (CXXConstructExpr, [B1.3], 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);
+// CHECK-NEXT:     6: [B1.5].~D() (Implicit destructor)
+void referenceVariableWithConstructor() {
+  const D &d(0);
+}
+
+// CHECK: void referenceVariableWithInitializer()
+// CHECK:          1: temporary_object_expr_with_dtors::D() (CXXConstructExpr, [B1.2], class temporary_object_expr_with_dtors::D)
+// CHECK-NEXT:     2: [B1.1] (BindTemporary)
+// CHECK-NEXT:     3: [B1.2] (ImplicitCastExpr, NoOp, const class temporary_object_expr_with_dtors::D)
+// CHECK-NEXT:     4: [B1.3]
+// CHECK-NEXT:     5: const temporary_object_expr_with_dtors::D &d = temporary_object_expr_with_dtors::D();
+// CHECK-NEXT:     6: [B1.5].~D() (Implicit destructor)
+void referenceVariableWithInitializer() {
+  const D &d = D();
+}
+
+// CHECK: void referenceVariableWithTernaryOperator(bool coin)
+// CHECK:        [B4]
+// CHECK-NEXT:     1: [B7.2] ? [B5.8] : [B6.8]
+// CHECK-NEXT:     2: [B4.1] (ImplicitCastExpr, NoOp, const class temporary_object_expr_with_dtors::D)
+// CHECK-NEXT:     3: [B4.2]
+// CHECK-NEXT:     4: const temporary_object_expr_with_dtors::D &d = coin ? D::get() : temporary_object_expr_with_dtors::D(0);
+// CHECK-NEXT:     T: (Temp Dtor) [B6.3]
+// CHECK:        [B5]
+// CHECK-NEXT:     1: D::get
+// CHECK-NEXT:     2: [B5.1] (ImplicitCastExpr, FunctionToPointerDecay, class temporary_object_expr_with_dtors::D (*)(void))
+// CHECK-NEXT:     3: [B5.2]()
+// CHECK-NEXT:     4: [B5.3] (BindTemporary)
+// CHECK-NEXT:     5: [B5.4] (ImplicitCastExpr, NoOp, const class temporary_object_expr_with_dtors::D)
+// CHECK-NEXT:     6: [B5.5]
+// CHECK-NEXT:     7: [B5.6] (CXXConstructExpr, [B5.8], class temporary_object_expr_with_dtors::D)
+// CHECK-NEXT:     8: [B5.7] (BindTemporary)
+// CHECK:        [B6]
+// CHECK-NEXT:     1: 0
+// CHECK-NEXT:     2: [B6.1] (CXXConstructExpr, [B6.3], class temporary_object_expr_with_dtors::D)
+// CHECK-NEXT:     3: [B6.2] (BindTemporary)
+// CHECK-NEXT:     4: temporary_object_expr_with_dtors::D([B6.3]) (CXXFunctionalCastExpr, ConstructorConversion, class temporary_object_expr_with_dtors::D)
+// CHECK-NEXT:     5: [B6.4] (ImplicitCastExpr, NoOp, const class temporary_object_expr_with_dtors::D)
+// CHECK-NEXT:     6: [B6.5]
+// CHECK-NEXT:     7: [B6.6] (CXXConstructExpr, [B6.8], class temporary_object_expr_with_dtors::D)
+// CHECK-NEXT:     8: [B6.7] (BindTemporary)
+// CHECK:        [B7]
+// CHECK-NEXT:     1: coin
+// CHECK-NEXT:     2: [B7.1] (ImplicitCastExpr, LValueToRValue, _Bool)
+// CHECK-NEXT:     T: [B7.2] ? ... : ...
+void referenceVariableWithTernaryOperator(bool coin) {
+  const D &d = coin ? D::get() : D(0);
+}
+} // end namespace temporary_object_expr_with_dtors
index 1ddf877861a3d2cb493b1c0155765a2730b2a155..6750f77a8c3f3a80ee1893456085ae218b1656ac 100644 (file)
@@ -216,7 +216,8 @@ int testConsistencyNestedNormalReturn(bool value) {
 // CHECK:   [B2 (ENTRY)]
 // CHECK:     Succs (1): B1
 // CHECK:   [B1]
-// CHECK:     1: A() (CXXConstructExpr, class A)
+// WARNINGS:     1: A() (CXXConstructExpr, class A)
+// ANALYZER:     1: A() (CXXConstructExpr, [B1.2], class A)
 // CHECK:     2: [B1.1] (BindTemporary)
 // CHECK:     3: [B1.2] (ImplicitCastExpr, NoOp, const class A)
 // CHECK:     4: [B1.3]
@@ -275,7 +276,8 @@ int testConsistencyNestedNormalReturn(bool value) {
 // CHECK:   [B2 (ENTRY)]
 // CHECK:     Succs (1): B1
 // CHECK:   [B1]
-// CHECK:     1: A() (CXXConstructExpr, class A)
+// WARNINGS:     1: A() (CXXConstructExpr, class A)
+// ANALYZER:     1: A() (CXXConstructExpr, [B1.2], class A)
 // CHECK:     2: [B1.1] (BindTemporary)
 // CHECK:     3: [B1.2] (ImplicitCastExpr, NoOp, const class A)
 // CHECK:     4: [B1.3]
@@ -290,13 +292,15 @@ int testConsistencyNestedNormalReturn(bool value) {
 // CHECK:   [B2 (ENTRY)]
 // CHECK:     Succs (1): B1
 // CHECK:   [B1]
-// CHECK:     1: A() (CXXConstructExpr, class A)
+// WARNINGS:     1: A() (CXXConstructExpr, class A)
+// ANALYZER:     1: A() (CXXConstructExpr, [B1.2], class A)
 // CHECK:     2: [B1.1] (BindTemporary)
 // CHECK:     3: [B1.2].operator int
 // CHECK:     4: [B1.2]
 // CHECK:     5: [B1.4] (ImplicitCastExpr, UserDefinedConversion, int)
 // CHECK:     6: int([B1.5]) (CXXFunctionalCastExpr, NoOp, int)
-// CHECK:     7: B() (CXXConstructExpr, class B)
+// WARNINGS:     7: B() (CXXConstructExpr, class B)
+// ANALYZER:     7: B() (CXXConstructExpr, [B1.8], class B)
 // CHECK:     8: [B1.7] (BindTemporary)
 // CHECK:     9: [B1.8].operator int
 // CHECK:    10: [B1.8]
@@ -308,13 +312,15 @@ int testConsistencyNestedNormalReturn(bool value) {
 // CHECK:    16: ~A() (Temporary object destructor)
 // CHECK:    17: foo
 // CHECK:    18: [B1.17] (ImplicitCastExpr, FunctionToPointerDecay, void (*)(int))
-// CHECK:    19: A() (CXXConstructExpr, class A)
+// WARNINGS:    19: A() (CXXConstructExpr, class A)
+// ANALYZER:    19: A() (CXXConstructExpr, [B1.20], class A)
 // CHECK:    20: [B1.19] (BindTemporary)
 // CHECK:    21: [B1.20].operator int
 // CHECK:    22: [B1.20]
 // CHECK:    23: [B1.22] (ImplicitCastExpr, UserDefinedConversion, int)
 // CHECK:    24: int([B1.23]) (CXXFunctionalCastExpr, NoOp, int)
-// CHECK:    25: B() (CXXConstructExpr, class B)
+// WARNINGS:    25: B() (CXXConstructExpr, class B)
+// ANALYZER:    25: B() (CXXConstructExpr, [B1.26], class B)
 // CHECK:    26: [B1.25] (BindTemporary)
 // CHECK:    27: [B1.26].operator int
 // CHECK:    28: [B1.26]
@@ -347,7 +353,8 @@ int testConsistencyNestedNormalReturn(bool value) {
 // CHECK:     Preds (2): B4 B5
 // CHECK:     Succs (2): B2 B1
 // CHECK:   [B4]
-// CHECK:     1: B() (CXXConstructExpr, class B)
+// WARNINGS:     1: B() (CXXConstructExpr, class B)
+// ANALYZER:     1: B() (CXXConstructExpr, [B4.2], class B)
 // CHECK:     2: [B4.1] (BindTemporary)
 // CHECK:     3: [B4.2].operator bool
 // CHECK:     4: [B4.2]
@@ -358,7 +365,8 @@ int testConsistencyNestedNormalReturn(bool value) {
 // CHECK:     1: ~A() (Temporary object destructor)
 // CHECK:     2: foo
 // CHECK:     3: [B5.2] (ImplicitCastExpr, FunctionToPointerDecay, void (*)(_Bool))
-// CHECK:     4: A() (CXXConstructExpr, class A)
+// WARNINGS:     4: A() (CXXConstructExpr, class A)
+// ANALYZER:     4: A() (CXXConstructExpr, [B5.5], class A)
 // CHECK:     5: [B5.4] (BindTemporary)
 // CHECK:     6: [B5.5].operator bool
 // CHECK:     7: [B5.5]
@@ -377,7 +385,8 @@ int testConsistencyNestedNormalReturn(bool value) {
 // CHECK:     Preds (2): B8 B9
 // CHECK:     Succs (2): B6 B5
 // CHECK:   [B8]
-// CHECK:     1: B() (CXXConstructExpr, class B)
+// WARNINGS:     1: B() (CXXConstructExpr, class B)
+// ANALYZER:     1: B() (CXXConstructExpr, [B8.2], class B)
 // CHECK:     2: [B8.1] (BindTemporary)
 // CHECK:     3: [B8.2].operator bool
 // CHECK:     4: [B8.2]
@@ -385,7 +394,8 @@ int testConsistencyNestedNormalReturn(bool value) {
 // CHECK:     Preds (1): B9
 // CHECK:     Succs (1): B7
 // CHECK:   [B9]
-// CHECK:     1: A() (CXXConstructExpr, class A)
+// WARNINGS:     1: A() (CXXConstructExpr, class A)
+// ANALYZER:     1: A() (CXXConstructExpr, [B9.2], class A)
 // CHECK:     2: [B9.1] (BindTemporary)
 // CHECK:     3: [B9.2].operator bool
 // CHECK:     4: [B9.2]
@@ -413,7 +423,8 @@ int testConsistencyNestedNormalReturn(bool value) {
 // CHECK:     Preds (2): B4 B5
 // CHECK:     Succs (2): B2 B1
 // CHECK:   [B4]
-// CHECK:     1: B() (CXXConstructExpr, class B)
+// WARNINGS:     1: B() (CXXConstructExpr, class B)
+// ANALYZER:     1: B() (CXXConstructExpr, [B4.2], class B)
 // CHECK:     2: [B4.1] (BindTemporary)
 // CHECK:     3: [B4.2].operator bool
 // CHECK:     4: [B4.2]
@@ -424,7 +435,8 @@ int testConsistencyNestedNormalReturn(bool value) {
 // CHECK:     1: ~A() (Temporary object destructor)
 // CHECK:     2: foo
 // CHECK:     3: [B5.2] (ImplicitCastExpr, FunctionToPointerDecay, void (*)(_Bool))
-// CHECK:     4: A() (CXXConstructExpr, class A)
+// WARNINGS:     4: A() (CXXConstructExpr, class A)
+// ANALYZER:     4: A() (CXXConstructExpr, [B5.5], class A)
 // CHECK:     5: [B5.4] (BindTemporary)
 // CHECK:     6: [B5.5].operator bool
 // CHECK:     7: [B5.5]
@@ -443,7 +455,8 @@ int testConsistencyNestedNormalReturn(bool value) {
 // CHECK:     Preds (2): B8 B9
 // CHECK:     Succs (2): B6 B5
 // CHECK:   [B8]
-// CHECK:     1: B() (CXXConstructExpr, class B)
+// WARNINGS:     1: B() (CXXConstructExpr, class B)
+// ANALYZER:     1: B() (CXXConstructExpr, [B8.2], class B)
 // CHECK:     2: [B8.1] (BindTemporary)
 // CHECK:     3: [B8.2].operator bool
 // CHECK:     4: [B8.2]
@@ -451,7 +464,8 @@ int testConsistencyNestedNormalReturn(bool value) {
 // CHECK:     Preds (1): B9
 // CHECK:     Succs (1): B7
 // CHECK:   [B9]
-// CHECK:     1: A() (CXXConstructExpr, class A)
+// WARNINGS:     1: A() (CXXConstructExpr, class A)
+// ANALYZER:     1: A() (CXXConstructExpr, [B9.2], class A)
 // CHECK:     2: [B9.1] (BindTemporary)
 // CHECK:     3: [B9.2].operator bool
 // CHECK:     4: [B9.2]
@@ -484,7 +498,8 @@ int testConsistencyNestedNormalReturn(bool value) {
 // CHECK:     Succs (1): B1
 // CHECK:   [B4]
 // CHECK:     1: ~B() (Temporary object destructor)
-// CHECK:     2: B() (CXXConstructExpr, class B)
+// WARNINGS:     2: B() (CXXConstructExpr, class B)
+// ANALYZER:     2: B() (CXXConstructExpr, [B4.3], class B)
 // CHECK:     3: [B4.2] (BindTemporary)
 // CHECK:     4: [B4.3].operator bool
 // CHECK:     5: [B4.3]
@@ -516,16 +531,19 @@ int testConsistencyNestedNormalReturn(bool value) {
 // CHECK:     Preds (2): B8 B9
 // CHECK:     Succs (2): B6 B5
 // CHECK:   [B8]
-// CHECK:     1: A() (CXXConstructExpr, class A)
+// WARNINGS:     1: A() (CXXConstructExpr, class A)
+// ANALYZER:     1: A() (CXXConstructExpr, [B8.2], class A)
 // CHECK:     2: [B8.1] (BindTemporary)
 // CHECK:     3: [B8.2] (ImplicitCastExpr, NoOp, const class A)
 // CHECK:     4: [B8.3]
-// CHECK:     5: [B8.4] (CXXConstructExpr, class A)
+// WARNINGS:     5: [B8.4] (CXXConstructExpr, class A)
+// ANALYZER:     5: [B8.4] (CXXConstructExpr, [B8.6], class A)
 // CHECK:     6: [B8.5] (BindTemporary)
 // CHECK:     Preds (1): B10
 // CHECK:     Succs (1): B7
 // CHECK:   [B9]
-// CHECK:     1: B() (CXXConstructExpr, class B)
+// WARNINGS:     1: B() (CXXConstructExpr, class B)
+// ANALYZER:     1: B() (CXXConstructExpr, [B9.2], class B)
 // CHECK:     2: [B9.1] (BindTemporary)
 // CHECK:     3: [B9.2].operator A
 // CHECK:     4: [B9.2]
@@ -533,17 +551,20 @@ int testConsistencyNestedNormalReturn(bool value) {
 // CHECK:     6: [B9.5] (BindTemporary)
 // CHECK:     7: [B9.6] (ImplicitCastExpr, NoOp, const class A)
 // CHECK:     8: [B9.7]
-// CHECK:     9: [B9.8] (CXXConstructExpr, class A)
+// WARNINGS:     9: [B9.8] (CXXConstructExpr, class A)
+// ANALYZER:     9: [B9.8] (CXXConstructExpr, [B9.10], class A)
 // CHECK:    10: [B9.9] (BindTemporary)
 // CHECK:    11: A([B9.10]) (CXXFunctionalCastExpr, ConstructorConversion, class A)
 // CHECK:    12: [B9.11] (ImplicitCastExpr, NoOp, const class A)
 // CHECK:    13: [B9.12]
-// CHECK:    14: [B9.13] (CXXConstructExpr, class A)
+// WARNINGS:    14: [B9.13] (CXXConstructExpr, class A)
+// ANALYZER:    14: [B9.13] (CXXConstructExpr, [B9.15], class A)
 // CHECK:    15: [B9.14] (BindTemporary)
 // CHECK:     Preds (1): B10
 // CHECK:     Succs (1): B7
 // CHECK:   [B10]
-// CHECK:     1: B() (CXXConstructExpr, class B)
+// WARNINGS:     1: B() (CXXConstructExpr, class B)
+// ANALYZER:     1: B() (CXXConstructExpr, [B10.2], class B)
 // CHECK:     2: [B10.1] (BindTemporary)
 // CHECK:     3: [B10.2].operator bool
 // CHECK:     4: [B10.2]
@@ -610,7 +631,8 @@ int testConsistencyNestedNormalReturn(bool value) {
 // CHECK:     Preds (1): B3
 // CHECK:     Succs (1): B0
 // CHECK:   [B3]
-// CHECK:     1: C() (CXXConstructExpr, struct C)
+// WARNINGS:     1: C() (CXXConstructExpr, struct C)
+// ANALYZER:     1: C() (CXXConstructExpr, [B3.2], struct C)
 // CHECK:     2: [B3.1] (BindTemporary)
 // CHECK:     3: [B3.2].operator bool
 // CHECK:     4: [B3.2]
@@ -639,7 +661,8 @@ int testConsistencyNestedNormalReturn(bool value) {
 // CHECK:     Preds (1): B4
 // CHECK:     Succs (1): B0
 // CHECK:   [B4]
-// CHECK:     1: C() (CXXConstructExpr, struct C)
+// WARNINGS:     1: C() (CXXConstructExpr, struct C)
+// ANALYZER:     1: C() (CXXConstructExpr, [B4.2], struct C)
 // CHECK:     2: [B4.1] (BindTemporary)
 // CHECK:     3: [B4.2] (ImplicitCastExpr, NoOp, const struct C)
 // CHECK:     4: [B4.3]
@@ -744,16 +767,19 @@ int testConsistencyNestedNormalReturn(bool value) {
 // CHECK:     Preds (2): B5 B6
 // CHECK:     Succs (2): B3 B2
 // CHECK:   [B5]
-// CHECK:     1: A() (CXXConstructExpr, class A)
+// WARNINGS:     1: A() (CXXConstructExpr, class A)
+// ANALYZER:     1: A() (CXXConstructExpr, [B5.2], class A)
 // CHECK:     2: [B5.1] (BindTemporary)
 // CHECK:     3: [B5.2] (ImplicitCastExpr, NoOp, const class A)
 // CHECK:     4: [B5.3]
-// CHECK:     5: [B5.4] (CXXConstructExpr, class A)
+// WARNINGS:     5: [B5.4] (CXXConstructExpr, class A)
+// ANALYZER:     5: [B5.4] (CXXConstructExpr, [B5.6], class A)
 // CHECK:     6: [B5.5] (BindTemporary)
 // CHECK:     Preds (1): B7
 // CHECK:     Succs (1): B4
 // CHECK:   [B6]
-// CHECK:     1: B() (CXXConstructExpr, class B)
+// WARNINGS:     1: B() (CXXConstructExpr, class B)
+// ANALYZER:     1: B() (CXXConstructExpr, [B6.2], class B)
 // CHECK:     2: [B6.1] (BindTemporary)
 // CHECK:     3: [B6.2].operator A
 // CHECK:     4: [B6.2]
@@ -761,12 +787,14 @@ int testConsistencyNestedNormalReturn(bool value) {
 // CHECK:     6: [B6.5] (BindTemporary)
 // CHECK:     7: [B6.6] (ImplicitCastExpr, NoOp, const class A)
 // CHECK:     8: [B6.7]
-// CHECK:     9: [B6.8] (CXXConstructExpr, class A)
+// WARNINGS:     9: [B6.8] (CXXConstructExpr, class A)
+// ANALYZER:     9: [B6.8] (CXXConstructExpr, [B6.10], class A)
 // CHECK:    10: [B6.9] (BindTemporary)
 // CHECK:    11: A([B6.10]) (CXXFunctionalCastExpr, ConstructorConversion, class A)
 // CHECK:    12: [B6.11] (ImplicitCastExpr, NoOp, const class A)
 // CHECK:    13: [B6.12]
-// CHECK:    14: [B6.13] (CXXConstructExpr, class A)
+// WARNINGS:    14: [B6.13] (CXXConstructExpr, class A)
+// ANALYZER:    14: [B6.13] (CXXConstructExpr, [B6.15], class A)
 // CHECK:    15: [B6.14] (BindTemporary)
 // CHECK:     Preds (1): B7
 // CHECK:     Succs (1): B4
@@ -774,7 +802,8 @@ int testConsistencyNestedNormalReturn(bool value) {
 // CHECK:     1: ~B() (Temporary object destructor)
 // CHECK:     2: foo
 // CHECK:     3: [B7.2] (ImplicitCastExpr, FunctionToPointerDecay, void (*)(const class A &))
-// CHECK:     4: B() (CXXConstructExpr, class B)
+// WARNINGS:     4: B() (CXXConstructExpr, class B)
+// ANALYZER:     4: B() (CXXConstructExpr, [B7.5], class B)
 // CHECK:     5: [B7.4] (BindTemporary)
 // CHECK:     6: [B7.5].operator bool
 // CHECK:     7: [B7.5]
@@ -801,16 +830,19 @@ int testConsistencyNestedNormalReturn(bool value) {
 // CHECK:     Preds (2): B11 B12
 // CHECK:     Succs (2): B9 B8
 // CHECK:   [B11]
-// CHECK:     1: A() (CXXConstructExpr, class A)
+// WARNINGS:     1: A() (CXXConstructExpr, class A)
+// ANALYZER:     1: A() (CXXConstructExpr, [B11.2], class A)
 // CHECK:     2: [B11.1] (BindTemporary)
 // CHECK:     3: [B11.2] (ImplicitCastExpr, NoOp, const class A)
 // CHECK:     4: [B11.3]
-// CHECK:     5: [B11.4] (CXXConstructExpr, class A)
+// WARNINGS:     5: [B11.4] (CXXConstructExpr, class A)
+// ANALYZER:     5: [B11.4] (CXXConstructExpr, [B11.6], class A)
 // CHECK:     6: [B11.5] (BindTemporary)
 // CHECK:     Preds (1): B13
 // CHECK:     Succs (1): B10
 // CHECK:   [B12]
-// CHECK:     1: B() (CXXConstructExpr, class B)
+// WARNINGS:     1: B() (CXXConstructExpr, class B)
+// ANALYZER:     1: B() (CXXConstructExpr, [B12.2], class B)
 // CHECK:     2: [B12.1] (BindTemporary)
 // CHECK:     3: [B12.2].operator A
 // CHECK:     4: [B12.2]
@@ -818,17 +850,20 @@ int testConsistencyNestedNormalReturn(bool value) {
 // CHECK:     6: [B12.5] (BindTemporary)
 // CHECK:     7: [B12.6] (ImplicitCastExpr, NoOp, const class A)
 // CHECK:     8: [B12.7]
-// CHECK:     9: [B12.8] (CXXConstructExpr, class A)
+// WARNINGS:     9: [B12.8] (CXXConstructExpr, class A)
+// ANALYZER:     9: [B12.8] (CXXConstructExpr, [B12.10], class A)
 // CHECK:    10: [B12.9] (BindTemporary)
 // CHECK:    11: A([B12.10]) (CXXFunctionalCastExpr, ConstructorConversion, class A)
 // CHECK:    12: [B12.11] (ImplicitCastExpr, NoOp, const class A)
 // CHECK:    13: [B12.12]
-// CHECK:    14: [B12.13] (CXXConstructExpr, class A)
+// WARNINGS:    14: [B12.13] (CXXConstructExpr, class A)
+// ANALYZER:    14: [B12.13] (CXXConstructExpr, [B12.15], class A)
 // CHECK:    15: [B12.14] (BindTemporary)
 // CHECK:     Preds (1): B13
 // CHECK:     Succs (1): B10
 // CHECK:   [B13]
-// CHECK:     1: B() (CXXConstructExpr, class B)
+// WARNINGS:     1: B() (CXXConstructExpr, class B)
+// ANALYZER:     1: B() (CXXConstructExpr, [B13.2], class B)
 // CHECK:     2: [B13.1] (BindTemporary)
 // CHECK:     3: [B13.2].operator bool
 // CHECK:     4: [B13.2]
@@ -868,24 +903,29 @@ int testConsistencyNestedNormalReturn(bool value) {
 // CHECK:   [B5]
 // CXX98:     1: [B7.2] (ImplicitCastExpr, NoOp, const class A)
 // CXX98:     2: [B5.1]
-// CXX98:     3: [B5.2] (CXXConstructExpr, class A)
+// WARNINGS-CXX98:     3: [B5.2] (CXXConstructExpr, class A)
+// ANALYZER-CXX98:     3: [B5.2] (CXXConstructExpr, [B5.4], class A)
 // CXX98:     4: [B5.3] (BindTemporary)
 // CXX11:     1: [B7.3] (ImplicitCastExpr, NoOp, const class A)
-// CXX11:     2: [B5.1] (CXXConstructExpr, class A)
+// WARNINGS-CXX11:     2: [B5.1] (CXXConstructExpr, class A)
+// ANALYZER-CXX11:     2: [B5.1] (CXXConstructExpr, [B5.3], class A)
 // CXX11:     3: [B5.2] (BindTemporary)
 // CHECK:     Preds (1): B7
 // CHECK:     Succs (1): B4
 // CHECK:   [B6]
-// CHECK:     1: A() (CXXConstructExpr, class A)
+// WARNINGS:     1: A() (CXXConstructExpr, class A)
+// ANALYZER:     1: A() (CXXConstructExpr, [B6.2], class A)
 // CHECK:     2: [B6.1] (BindTemporary)
 // CHECK:     3: [B6.2] (ImplicitCastExpr, NoOp, const class A)
 // CHECK:     4: [B6.3]
-// CHECK:     5: [B6.4] (CXXConstructExpr, class A)
+// WARNINGS:     5: [B6.4] (CXXConstructExpr, class A)
+// ANALYZER:     5: [B6.4] (CXXConstructExpr, [B6.6], class A)
 // CHECK:     6: [B6.5] (BindTemporary)
 // CHECK:     Preds (1): B7
 // CHECK:     Succs (1): B4
 // CHECK:   [B7]
-// CHECK:     1: A() (CXXConstructExpr, class A)
+// WARNINGS:     1: A() (CXXConstructExpr, class A)
+// ANALYZER:     1: A() (CXXConstructExpr, [B7.2], class A)
 // CHECK:     2: [B7.1] (BindTemporary)
 // CXX98:     3: [B7.2].operator bool
 // CXX98:     4: [B7.2]
@@ -928,26 +968,31 @@ int testConsistencyNestedNormalReturn(bool value) {
 // CHECK:   [B5]
 // CXX98:     1: [B7.4] (ImplicitCastExpr, NoOp, const class A)
 // CXX98:     2: [B5.1]
-// CXX98:     3: [B5.2] (CXXConstructExpr, class A)
+// WARNINGS-CXX98:     3: [B5.2] (CXXConstructExpr, class A)
+// ANALYZER-CXX98:     3: [B5.2] (CXXConstructExpr, [B5.4], class A)
 // CXX98:     4: [B5.3] (BindTemporary)
 // CXX11:     1: [B7.5] (ImplicitCastExpr, NoOp, const class A)
-// CXX11:     2: [B5.1] (CXXConstructExpr, class A)
+// WARNINGS-CXX11:     2: [B5.1] (CXXConstructExpr, class A)
+// ANALYZER-CXX11:     2: [B5.1] (CXXConstructExpr, [B5.3], class A)
 // CXX11:     3: [B5.2] (BindTemporary)
 // CHECK:     Preds (1): B7
 // CHECK:     Succs (1): B4
 // CHECK:   [B6]
-// CHECK:     1: A() (CXXConstructExpr, class A)
+// WARNINGS:     1: A() (CXXConstructExpr, class A)
+// ANALYZER:     1: A() (CXXConstructExpr, [B6.2], class A)
 // CHECK:     2: [B6.1] (BindTemporary)
 // CHECK:     3: [B6.2] (ImplicitCastExpr, NoOp, const class A)
 // CHECK:     4: [B6.3]
-// CHECK:     5: [B6.4] (CXXConstructExpr, class A)
+// WARNINGS:     5: [B6.4] (CXXConstructExpr, class A)
+// ANALYZER:     5: [B6.4] (CXXConstructExpr, [B6.6], class A)
 // CHECK:     6: [B6.5] (BindTemporary)
 // CHECK:     Preds (1): B7
 // CHECK:     Succs (1): B4
 // CHECK:   [B7]
 // CHECK:     1: foo
 // CHECK:     2: [B7.1] (ImplicitCastExpr, FunctionToPointerDecay, void (*)(const class A &))
-// CHECK:     3: A() (CXXConstructExpr, class A)
+// WARNINGS:     3: A() (CXXConstructExpr, class A)
+// ANALYZER:     3: A() (CXXConstructExpr, [B7.4], class A)
 // CHECK:     4: [B7.3] (BindTemporary)
 // CXX98:     5: [B7.4].operator bool
 // CXX98:     6: [B7.4]
@@ -976,24 +1021,29 @@ int testConsistencyNestedNormalReturn(bool value) {
 // CHECK:   [B10]
 // CXX98:     1: [B12.2] (ImplicitCastExpr, NoOp, const class A)
 // CXX98:     2: [B10.1]
-// CXX98:     3: [B10.2] (CXXConstructExpr, class A)
+// WARNINGS-CXX98:     3: [B10.2] (CXXConstructExpr, class A)
+// ANALYZER-CXX98:     3: [B10.2] (CXXConstructExpr, [B10.4], class A)
 // CXX98:     4: [B10.3] (BindTemporary)
 // CXX11:     1: [B12.3] (ImplicitCastExpr, NoOp, const class A)
-// CXX11:     2: [B10.1] (CXXConstructExpr, class A)
+// WARNINGS-CXX11:     2: [B10.1] (CXXConstructExpr, class A)
+// ANALYZER-CXX11:     2: [B10.1] (CXXConstructExpr, [B10.3], class A)
 // CXX11:     3: [B10.2] (BindTemporary)
 // CHECK:     Preds (1): B12
 // CHECK:     Succs (1): B9
 // CHECK:   [B11]
-// CHECK:     1: A() (CXXConstructExpr, class A)
+// WARNINGS-CHECK:     1: A() (CXXConstructExpr, class A)
+// ANALYZER-CHECK:     1: A() (CXXConstructExpr, [B11.2], class A)
 // CHECK:     2: [B11.1] (BindTemporary)
 // CHECK:     3: [B11.2] (ImplicitCastExpr, NoOp, const class A)
 // CHECK:     4: [B11.3]
-// CHECK:     5: [B11.4] (CXXConstructExpr, class A)
+// WARNINGS:     5: [B11.4] (CXXConstructExpr, class A)
+// ANALYZER:     5: [B11.4] (CXXConstructExpr, [B11.6], class A)
 // CHECK:     6: [B11.5] (BindTemporary)
 // CHECK:     Preds (1): B12
 // CHECK:     Succs (1): B9
 // CHECK:   [B12]
-// CHECK:     1: A() (CXXConstructExpr, class A)
+// WARNINGS:     1: A() (CXXConstructExpr, class A)
+// ANALYZER:     1: A() (CXXConstructExpr, [B12.2], class A)
 // CHECK:     2: [B12.1] (BindTemporary)
 // CXX98:     3: [B12.2].operator bool
 // CXX98:     4: [B12.2]
@@ -1011,7 +1061,8 @@ int testConsistencyNestedNormalReturn(bool value) {
 // CHECK:   [B2 (ENTRY)]
 // CHECK:     Succs (1): B1
 // CHECK:   [B1]
-// CHECK:     1: A() (CXXConstructExpr, class A)
+// WARNINGS:     1: A() (CXXConstructExpr, class A)
+// ANALYZER:     1: A() (CXXConstructExpr, [B1.2], class A)
 // CHECK:     2: [B1.1] (BindTemporary)
 // CHECK:     3: [B1.2] (ImplicitCastExpr, NoOp, const class A)
 // CHECK:     4: [B1.3]
@@ -1028,14 +1079,16 @@ int testConsistencyNestedNormalReturn(bool value) {
 // CHECK:   [B2 (ENTRY)]
 // CHECK:     Succs (1): B1
 // CHECK:   [B1]
-// CHECK:     1: A() (CXXConstructExpr, class A)
+// WARNINGS:     1: A() (CXXConstructExpr, class A)
+// ANALYZER:     1: A() (CXXConstructExpr, [B1.2], class A)
 // CHECK:     2: [B1.1] (BindTemporary)
 // CHECK:     3: [B1.2] (ImplicitCastExpr, NoOp, const class A)
 // CHECK:     4: [B1.3]
 // CHECK:     5: const A &a = A();
 // CHECK:     6: foo
 // CHECK:     7: [B1.6] (ImplicitCastExpr, FunctionToPointerDecay, void (*)(const class A &))
-// CHECK:     8: A() (CXXConstructExpr, class A)
+// WARNINGS:     8: A() (CXXConstructExpr, class A)
+// ANALYZER:     8: A() (CXXConstructExpr, [B1.9], class A)
 // CHECK:     9: [B1.8] (BindTemporary)
 // CHECK:    10: [B1.9] (ImplicitCastExpr, NoOp, const class A)
 // CHECK:    11: [B1.10]
@@ -1096,7 +1149,8 @@ int testConsistencyNestedNormalReturn(bool value) {
 // CHECK:     Succs (1): B1
 // CHECK:   [B1]
 // CHECK:     1: int a;
-// CHECK:     2: A() (CXXConstructExpr, class A)
+// WARNINGS:     2: A() (CXXConstructExpr, class A)
+// ANALYZER:     2: A() (CXXConstructExpr, [B1.3], class A)
 // CHECK:     3: [B1.2] (BindTemporary)
 // CHECK:     4: [B1.3].operator int
 // CHECK:     5: [B1.3]
@@ -1112,13 +1166,15 @@ int testConsistencyNestedNormalReturn(bool value) {
 // CHECK:   [B2 (ENTRY)]
 // CHECK:     Succs (1): B1
 // CHECK:   [B1]
-// CHECK:     1: A() (CXXConstructExpr, class A)
+// WARNINGS:     1: A() (CXXConstructExpr, class A)
+// ANALYZER:     1: A() (CXXConstructExpr, [B1.2], class A)
 // CHECK:     2: [B1.1] (BindTemporary)
 // CHECK:     3: [B1.2].operator int
 // CHECK:     4: [B1.2]
 // CHECK:     5: [B1.4] (ImplicitCastExpr, UserDefinedConversion, int)
 // CHECK:     6: int([B1.5]) (CXXFunctionalCastExpr, NoOp, int)
-// CHECK:     7: B() (CXXConstructExpr, class B)
+// WARNINGS:     7: B() (CXXConstructExpr, class B)
+// ANALYZER:     7: B() (CXXConstructExpr, [B1.8], class B)
 // CHECK:     8: [B1.7] (BindTemporary)
 // CHECK:     9: [B1.8].operator int
 // CHECK:    10: [B1.8]
@@ -1142,7 +1198,8 @@ int testConsistencyNestedNormalReturn(bool value) {
 // CHECK:     Succs (1): B0
 // CHECK:   [B2 (NORETURN)]
 // CHECK:     1: int a;
-// CHECK:     2: NoReturn() (CXXConstructExpr, class NoReturn)
+// WARNINGS:     2: NoReturn() (CXXConstructExpr, class NoReturn)
+// ANALYZER:     2: NoReturn() (CXXConstructExpr, [B2.3], class NoReturn)
 // CHECK:     3: [B2.2] (BindTemporary)
 // CHECK:     [[MEMBER:[45]]]: [B2.{{[34]}}].f
 // CHECK:     {{[56]}}: [B2.[[MEMBER]]]()
@@ -1159,7 +1216,8 @@ int testConsistencyNestedNormalReturn(bool value) {
 // CHECK:     Succs (1): B0
 // CHECK:   [B2 (NORETURN)]
 // CHECK:     1: int a;
-// CHECK:     2: NoReturn() (CXXConstructExpr, class NoReturn)
+// WARNINGS:     2: NoReturn() (CXXConstructExpr, class NoReturn)
+// ANALYZER:     2: NoReturn() (CXXConstructExpr, [B2.3], class NoReturn)
 // CHECK:     3: [B2.2] (BindTemporary)
 // CHECK:     4: 47
 // CHECK:     5: ... , [B2.4]
@@ -1196,7 +1254,8 @@ int testConsistencyNestedNormalReturn(bool value) {
 // CHECK:   [B6]
 // CHECK:     1: check
 // CHECK:     2: [B6.1] (ImplicitCastExpr, FunctionToPointerDecay, _Bool (*)(const class NoReturn &))
-// CHECK:     3: NoReturn() (CXXConstructExpr, class NoReturn)
+// WARNINGS:     3: NoReturn() (CXXConstructExpr, class NoReturn)
+// ANALYZER:     3: NoReturn() (CXXConstructExpr, [B6.4], class NoReturn)
 // CHECK:     4: [B6.3] (BindTemporary)
 // CHECK:     5: [B6.4] (ImplicitCastExpr, NoOp, const class NoReturn)
 // CHECK:     6: [B6.5]
@@ -1246,7 +1305,8 @@ int testConsistencyNestedNormalReturn(bool value) {
 // CHECK:   [B6]
 // CHECK:     1: check
 // CHECK:     2: [B6.1] (ImplicitCastExpr, FunctionToPointerDecay, _Bool (*)(const class NoReturn &))
-// CHECK:     3: NoReturn() (CXXConstructExpr, class NoReturn)
+// WARNINGS:     3: NoReturn() (CXXConstructExpr, class NoReturn)
+// ANALYZER:     3: NoReturn() (CXXConstructExpr, [B6.4], class NoReturn)
 // CHECK:     4: [B6.3] (BindTemporary)
 // CHECK:     5: [B6.4] (ImplicitCastExpr, NoOp, const class NoReturn)
 // CHECK:     6: [B6.5]
@@ -1303,7 +1363,8 @@ int testConsistencyNestedNormalReturn(bool value) {
 // CHECK:   [B6]
 // CHECK:     1: check
 // CHECK:     2: [B6.1] (ImplicitCastExpr, FunctionToPointerDecay, _Bool (*)(const class NoReturn &))
-// CHECK:     3: NoReturn() (CXXConstructExpr, class NoReturn)
+// WARNINGS:     3: NoReturn() (CXXConstructExpr, class NoReturn)
+// ANALYZER:     3: NoReturn() (CXXConstructExpr, [B6.4], class NoReturn)
 // CHECK:     4: [B6.3] (BindTemporary)
 // CHECK:     5: [B6.4] (ImplicitCastExpr, NoOp, const class NoReturn)
 // CHECK:     6: [B6.5]