NoQ updated this revision to Diff 133142.
NoQ added a comment.

Rebase.


https://reviews.llvm.org/D42719

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

Index: test/Analysis/temp-obj-dtors-cfg-output.cpp
===================================================================
--- test/Analysis/temp-obj-dtors-cfg-output.cpp
+++ test/Analysis/temp-obj-dtors-cfg-output.cpp
@@ -1,8 +1,23 @@
 // RUN: rm -f %t
-// RUN: %clang_analyze_cc1 -analyzer-checker=debug.DumpCFG -analyzer-config cfg-temporary-dtors=true -std=c++98 %s > %t 2>&1
-// RUN: FileCheck --input-file=%t -check-prefix=CXX98 -check-prefix=CHECK %s
-// RUN: %clang_analyze_cc1 -analyzer-checker=debug.DumpCFG -analyzer-config cfg-temporary-dtors=true -std=c++11 %s > %t 2>&1
-// RUN: FileCheck --input-file=%t -check-prefix=CXX11 -check-prefix=CHECK %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=debug.DumpCFG -analyzer-config cfg-temporary-dtors=true,cfg-rich-constructors=false -std=c++98 %s > %t 2>&1
+// RUN: FileCheck --input-file=%t -check-prefixes=CHECK,CXX98,WARNINGS,CXX98-WARNINGS %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=debug.DumpCFG -analyzer-config cfg-temporary-dtors=true,cfg-rich-constructors=false -std=c++11 %s > %t 2>&1
+// RUN: FileCheck --input-file=%t -check-prefixes=CHECK,CXX11,WARNINGS,CXX11-WARNINGS %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=debug.DumpCFG -analyzer-config cfg-temporary-dtors=true,cfg-rich-constructors=true -std=c++98 %s > %t 2>&1
+// RUN: FileCheck --input-file=%t -check-prefixes=CHECK,CXX98,ANALYZER,CXX98-ANALYZER %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=debug.DumpCFG -analyzer-config cfg-temporary-dtors=true,cfg-rich-constructors=true -std=c++11 %s > %t 2>&1
+// RUN: FileCheck --input-file=%t -check-prefixes=CHECK,CXX11,ANALYZER,CXX11-ANALYZER %s
+
+// This file tests how we construct two different flavors of the Clang CFG -
+// the CFG used by the Sema analysis-based warnings and the CFG used by the
+// static analyzer. The difference in the behavior is checked via FileCheck
+// prefixes (WARNINGS and ANALYZER respectively). When introducing new analyzer
+// flags, no new run lines should be added - just these flags would go to the
+// respective line depending on where is it turned on and where is it turned
+// off. Feel free to add tests that test only one of the CFG flavors if you're
+// not sure how the other flavor is supposed to work in your case.
+
+// Additionally, different C++ standards are checked.
 
 class A {
 public:
@@ -492,7 +507,8 @@
 // CHECK:     1: [B10.5] ? [B8.6] : [B9.15]
 // CHECK:     2: [B7.1] (ImplicitCastExpr, NoOp, const class A)
 // CHECK:     3: [B7.2]
-// CHECK:     4: [B7.3] (CXXConstructExpr, class A)
+// WARNINGS:     4: [B7.3] (CXXConstructExpr, class A)
+// ANALYZER:     4: [B7.3] (CXXConstructExpr, [B7.5], class A)
 // CHECK:     5: A a = B() ? A() : A(B());
 // CHECK:     T: (Temp Dtor) [B9.2]
 // CHECK:     Preds (2): B8 B9
@@ -625,7 +641,8 @@
 // CHECK:     2: [B4.1] (BindTemporary)
 // CHECK:     3: [B4.2] (ImplicitCastExpr, NoOp, const struct C)
 // CHECK:     4: [B4.3]
-// CHECK:     5: [B4.4] (CXXConstructExpr, struct C)
+// WARNINGS:     5: [B4.4] (CXXConstructExpr, struct C)
+// ANALYZER:     5: [B4.4] (CXXConstructExpr, [B4.6], struct C)
 // CHECK:     6: C c = C();
 // CHECK:     7: ~C() (Temporary object destructor)
 // CHECK:     8: c
@@ -675,15 +692,17 @@
 // CHECK:     1: D() (CXXConstructExpr, struct D)
 // CXX98:     2: [B3.1] (ImplicitCastExpr, NoOp, const struct D)
 // CXX98:     3: [B3.2]
-// CXX98:     4: [B3.3] (CXXConstructExpr, struct D)
+// CXX98-WARNINGS:     4: [B3.3] (CXXConstructExpr, struct D)
+// CXX98-ANALYZER:     4: [B3.3] (CXXConstructExpr, [B3.5], struct D)
 // CXX98:     5: D d = D();
 // CXX98:     6: d
 // CXX98:     7: [B3.6].operator bool
 // CXX98:     8: [B3.6]
 // CXX98:     9: [B3.8] (ImplicitCastExpr, UserDefinedConversion, _Bool)
 // CXX98:     T: if [B3.9]
 // CXX11:     2: [B3.1]
-// CXX11:     3: [B3.2] (CXXConstructExpr, struct D)
+// CXX11-WARNINGS:     3: [B3.2] (CXXConstructExpr, struct D)
+// CXX11-ANALYZER:     3: [B3.2] (CXXConstructExpr, [B3.4], struct D)
 // CXX11:     4: D d = D();
 // CXX11:     5: d
 // CXX11:     6: [B3.5].operator bool
@@ -838,7 +857,8 @@
 // CXX11:     1: [B7.3] ?: [B6.6]
 // CHECK:     2: [B4.1] (ImplicitCastExpr, NoOp, const class A)
 // CHECK:     3: [B4.2]
-// CHECK:     4: [B4.3] (CXXConstructExpr, class A)
+// WARNINGS:     4: [B4.3] (CXXConstructExpr, class A)
+// ANALYZER:     4: [B4.3] (CXXConstructExpr, [B4.5], class A)
 // CHECK:     5: A a = A() ?: A();
 // CHECK:     T: (Temp Dtor) [B6.2]
 // CHECK:     Preds (2): B5 B6
@@ -993,7 +1013,8 @@
 // CHECK:     2: [B1.1] (BindTemporary)
 // CHECK:     3: [B1.2] (ImplicitCastExpr, NoOp, const class A)
 // CHECK:     4: [B1.3]
-// CHECK:     5: [B1.4] (CXXConstructExpr, class A)
+// WARNINGS:     5: [B1.4] (CXXConstructExpr, class A)
+// ANALYZER:     5: [B1.4] (CXXConstructExpr, [B1.6], class A)
 // CHECK:     6: A a = A();
 // CHECK:     7: ~A() (Temporary object destructor)
 // CHECK:     8: int b;
@@ -1033,7 +1054,8 @@
 // CHECK:     4: [B1.3] (BindTemporary)
 // CHECK:     5: [B1.4] (ImplicitCastExpr, NoOp, const class A)
 // CHECK:     6: [B1.5]
-// CHECK:     7: [B1.6] (CXXConstructExpr, class A)
+// WARNINGS:     7: [B1.6] (CXXConstructExpr, class A)
+// ANALYZER:     7: [B1.6] (CXXConstructExpr, [B1.8], class A)
 // CHECK:     8: A a = A::make();
 // CHECK:     9: ~A() (Temporary object destructor)
 // CHECK:    10: int b;
Index: test/Analysis/cfg-rich-constructors.cpp
===================================================================
--- test/Analysis/cfg-rich-constructors.cpp
+++ test/Analysis/cfg-rich-constructors.cpp
@@ -92,18 +92,45 @@
   C c{new C()};
 }
 
-// TODO: Should find construction target here.
 // CHECK: void simpleVariableInitializedByValue()
 // CHECK:          1: C::get
 // CHECK-NEXT:     2: [B1.1] (ImplicitCastExpr, FunctionToPointerDecay, class C (*)(void))
 // CHECK-NEXT:     3: [B1.2]()
 // CHECK-NEXT:     4: [B1.3]
-// CHECK-NEXT:     5: [B1.4] (CXXConstructExpr, class C)
+// CHECK-NEXT:     5: [B1.4] (CXXConstructExpr, [B1.6], class C)
 // CHECK-NEXT:     6: C c = C::get();
 void simpleVariableInitializedByValue() {
   C c = C::get();
 }
 
+// TODO: Should find construction target for the three temporaries as well.
+// CHECK: void simpleVariableWithTernaryOperator(bool coin)
+// CHECK:        [B1]
+// CHECK-NEXT:     1: [B4.2] ? [B2.5] : [B3.6]
+// CHECK-NEXT:     2: [B1.1]
+// CHECK-NEXT:     3: [B1.2] (CXXConstructExpr, [B1.4], class C)
+// CHECK-NEXT:     4: C c = coin ? C::get() : C(0);
+// CHECK:        [B2]
+// CHECK-NEXT:     1: C::get
+// CHECK-NEXT:     2: [B2.1] (ImplicitCastExpr, FunctionToPointerDecay, class C (*)(void))
+// CHECK-NEXT:     3: [B2.2]()
+// CHECK-NEXT:     4: [B2.3]
+// CHECK-NEXT:     5: [B2.4] (CXXConstructExpr, class C)
+// CHECK:        [B3]
+// CHECK-NEXT:     1: 0
+// CHECK-NEXT:     2: [B3.1] (ImplicitCastExpr, NullToPointer, class C *)
+// CHECK-NEXT:     3: [B3.2] (CXXConstructExpr, class C)
+// CHECK-NEXT:     4: C([B3.3]) (CXXFunctionalCastExpr, ConstructorConversion, class C)
+// CHECK-NEXT:     5: [B3.4]
+// CHECK-NEXT:     6: [B3.5] (CXXConstructExpr, class C)
+// CHECK:        [B4]
+// CHECK-NEXT:     1: coin
+// CHECK-NEXT:     2: [B4.1] (ImplicitCastExpr, LValueToRValue, _Bool)
+// CHECK-NEXT:     T: [B4.2] ? ... : ...
+void simpleVariableWithTernaryOperator(bool coin) {
+  C c = coin ? C::get() : C(0);
+}
+
 // TODO: Should find construction target here.
 // CHECK: void referenceVariableThatInstantlyDies()
 // CHECK:          1: 0
@@ -125,6 +152,34 @@
   const C &c = C();
 }
 
+// TODO: Should find construction targets here.
+// CHECK: void referenceVariableWithTernaryOperator(bool coin)
+// CHECK:        [B1]
+// CHECK-NEXT:     1: [B4.2] ? [B2.5] : [B3.6]
+// CHECK-NEXT:     2: [B1.1] (ImplicitCastExpr, NoOp, const class C)
+// CHECK-NEXT:     3: [B1.2]
+// CHECK-NEXT:     4: const C &c = coin ? C::get() : C(0);
+// CHECK:        [B2]
+// CHECK-NEXT:     1: C::get
+// CHECK-NEXT:     2: [B2.1] (ImplicitCastExpr, FunctionToPointerDecay, class C (*)(void))
+// CHECK-NEXT:     3: [B2.2]()
+// CHECK-NEXT:     4: [B2.3]
+// CHECK-NEXT:     5: [B2.4] (CXXConstructExpr, class C)
+// CHECK:        [B3]
+// CHECK-NEXT:     1: 0
+// CHECK-NEXT:     2: [B3.1] (ImplicitCastExpr, NullToPointer, class C *)
+// CHECK-NEXT:     3: [B3.2] (CXXConstructExpr, class C)
+// CHECK-NEXT:     4: C([B3.3]) (CXXFunctionalCastExpr, ConstructorConversion, class C)
+// CHECK-NEXT:     5: [B3.4]
+// CHECK-NEXT:     6: [B3.5] (CXXConstructExpr, class C)
+// CHECK:        [B4]
+// CHECK-NEXT:     1: coin
+// CHECK-NEXT:     2: [B4.1] (ImplicitCastExpr, LValueToRValue, _Bool)
+// CHECK-NEXT:     T: [B4.2] ? ... : ...
+void referenceVariableWithTernaryOperator(bool coin) {
+  const C &c = coin ? C::get() : C(0);
+}
+
 } // end namespace decl_stmt
 
 namespace ctor_initializers {
@@ -148,6 +203,24 @@
 // CHECK:          1:  (CXXConstructExpr, D() (Delegating initializer), class ctor_initializers::D)
 // CHECK-NEXT:     2: D([B1.1]) (Delegating initializer)
   D(int): D() {}
+
+// CHECK: D(double)
+// CHECK:          1: C::get
+// CHECK-NEXT:     2: [B1.1] (ImplicitCastExpr, FunctionToPointerDecay, class C (*)(void))
+// CHECK-NEXT:     3: [B1.2]()
+// CHECK-NEXT:     4: [B1.3]
+// CHECK-NEXT:     5: [B1.4] (CXXConstructExpr, C([B1.4]) (Base initializer), class C)
+// CHECK-NEXT:     6: C([B1.5]) (Base initializer)
+// CHECK-NEXT:     7: CFGNewAllocator(C *)
+// CHECK-NEXT:     8: C::get
+// CHECK-NEXT:     9: [B1.8] (ImplicitCastExpr, FunctionToPointerDecay, class C (*)(void))
+// CHECK-NEXT:    10: [B1.9]()
+// CHECK-NEXT:    11: [B1.10]
+// CHECK-NEXT:    12: [B1.11] (CXXConstructExpr, [B1.13], class C)
+// CHECK-NEXT:    13: new C([B1.12])
+// CHECK-NEXT:    14: [B1.13] (CXXConstructExpr, c1([B1.13]) (Member initializer), class C)
+// CHECK-NEXT:    15: c1([B1.14]) (Member initializer)
+  D(double): C(C::get()), c1(new C(C::get())) {}
 };
 
 } // end namespace ctor_initializers
Index: lib/Analysis/CFG.cpp
===================================================================
--- lib/Analysis/CFG.cpp
+++ lib/Analysis/CFG.cpp
@@ -1158,6 +1158,8 @@
     assert(CurrentConstructionContext.isNull() &&
            "Already within a construction context!");
     CurrentConstructionContext = ConstructionContext(Trigger);
+  } else if (auto *Cleanups = dyn_cast<ExprWithCleanups>(Child)) {
+    EnterConstructionContextIfNecessary(Trigger, Cleanups->getSubExpr());
   }
 }
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to