]> granicus.if.org Git - clang/commitdiff
[CFG] [analyzer] Recall that we only skip NoOp casts in construction contexts.
authorArtem Dergachev <artem.dergachev@gmail.com>
Thu, 1 Mar 2018 01:09:24 +0000 (01:09 +0000)
committerArtem Dergachev <artem.dergachev@gmail.com>
Thu, 1 Mar 2018 01:09:24 +0000 (01:09 +0000)
For now. We should also add support for ConstructorConversion casts as presented
in the attached test case, but this requires more changes because AST around
them seems different.

The check was originally present but was accidentally lost during r326021.

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

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

lib/Analysis/CFG.cpp
test/Analysis/cfg-rich-constructors.cpp

index 727c304f7a383821955ef45493547d340e4b30fc..f8517cb3b1366286bf25b99a5d86c984854cbf7b 100644 (file)
@@ -1200,7 +1200,9 @@ void CFGBuilder::findConstructionContexts(
   }
   case Stmt::ImplicitCastExprClass: {
     auto *Cast = cast<ImplicitCastExpr>(Child);
-    findConstructionContexts(Layer, Cast->getSubExpr());
+    // TODO: We need to support CK_ConstructorConversion, maybe other kinds?
+    if (Cast->getCastKind() == CK_NoOp)
+      findConstructionContexts(Layer, Cast->getSubExpr());
     break;
   }
   case Stmt::CXXBindTemporaryExprClass: {
index 9613fa2fbead7c2bfa4f02dbc38231121c142843..2ae33d370373a9b77e3713d7c91aef99897b8346 100644 (file)
@@ -484,4 +484,35 @@ void referenceWithFunctionalCast() {
 void constructorInTernaryCondition() {
   const D &d = D(1) ? D(2) : D(3);
 }
+
 } // end namespace temporary_object_expr_with_dtors
+
+namespace implicit_constructor_conversion {
+
+class A {};
+A get();
+
+class B {
+public:
+  B(const A &);
+  ~B() {}
+};
+
+// FIXME: Find construction context for the implicit constructor conversion.
+// CHECK: void implicitConstructionConversionFromFunctionValue()
+// CHECK:          1: get
+// CHECK-NEXT:     2: [B1.1] (ImplicitCastExpr, FunctionToPointerDecay, class implicit_constructor_conver
+// CHECK-NEXT:     3: [B1.2]()
+// CHECK-NEXT:     4: [B1.3] (ImplicitCastExpr, NoOp, const class implicit_constructor_conversion::A)
+// CHECK-NEXT:     5: [B1.4]
+// CHECK-NEXT:     6: [B1.5] (CXXConstructExpr, class implicit_constructor_conversion::B)
+// CHECK-NEXT:     7: [B1.6] (ImplicitCastExpr, ConstructorConversion, class implicit_constructor_convers
+// CHECK-NEXT:     8: [B1.7] (ImplicitCastExpr, NoOp, const class implicit_constructor_conversion::B)
+// CHECK-NEXT:     9: [B1.8]
+// CHECK-NEXT:    10: const implicit_constructor_conversion::B &b = get();
+// CHECK-NEXT:    11: [B1.10].~B() (Implicit destructor)
+void implicitConstructionConversionFromFunctionValue() {
+  const B &b = get(); // no-crash
+}
+
+} // end namespace implicit_constructor_conversion