[PATCH] D50487: [CFG] [analyzer] Find argument constructors in CXXTemporaryObjectExprs.

Artem Dergachev via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Wed Aug 8 18:46:25 PDT 2018


NoQ created this revision.
NoQ added reviewers: dcoughlin, xazax.hun, a.sidorin, george.karpenkov, szepet, rnkovacs.
Herald added subscribers: cfe-commits, mikhail.ramalho, baloghadamsoftware.

`CXXTemporaryObjectExpr` is a sub-class of `CXXConstructExpr` that represents a construct-expression written as `T(Arg1, ..., ArgN)`, where `N` is not equal to 1. If `N` is equal to 1, such expression is parsed as a construction conversion from type of `Arg1` to type `T` instead. Not every temporary object is represented by `CXXTemporaryObjectExpr` (for instance, implicit temporary copies aren't), and `CXXTemporaryObjectExpr` doesn't necessarily represent a temporary object (constructor written as a `CXXTemporaryObjectExpr` may construct a pretty much arbitrary object if copy elision kicks in).

If any of `Arg1`, ..., `ArgN` requires construction, give it a construction context of an argument. For now it only works for `CXXConstructExpr`s that aren't `CXXTemporaryObjectExpr`s. I forgot to add it when i was adding stubs for `CXXConstructExpr` argument constructors in https://reviews.llvm.org/D48249. I thought i had a test for it (`passArgumentIntoAnotherConstructor()`), but in fact in this test `N` was equal to 1, so it wasn't really testing a `CXXTemporaryObjectExpr`.


Repository:
  rC Clang

https://reviews.llvm.org/D50487

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


Index: test/Analysis/cfg-rich-constructors.cpp
===================================================================
--- test/Analysis/cfg-rich-constructors.cpp
+++ test/Analysis/cfg-rich-constructors.cpp
@@ -820,6 +820,7 @@
 class E {
 public:
   E(D d);
+  E(D d1, D d2);
 };
 
 void useC(C c);
@@ -939,6 +940,38 @@
 void passArgumentIntoAnotherConstructor() {
   E e = E(D());
 }
+
+
+// CHECK: void passTwoArgumentsIntoAnotherConstructor()
+// CXX11-ELIDE:          1: argument_constructors::D() (CXXConstructExpr, [B1.2], [B1.4], [B1.5], class argument_constructors::D)
+// CXX11-NOELIDE:          1: argument_constructors::D() (CXXConstructExpr, [B1.2], [B1.4], class argument_constructors::D)
+// CXX11-NEXT:     2: [B1.1] (BindTemporary)
+// CXX11-NEXT:     3: [B1.2] (ImplicitCastExpr, NoOp, const class argument_constructors::D)
+// CXX11-NEXT:     4: [B1.3]
+// CXX11-NEXT:     5: [B1.4] (CXXConstructExpr, [B1.6], [B1.13]+0, class argument_constructors::D)
+// CXX11-NEXT:     6: [B1.5] (BindTemporary)
+// CXX11-ELIDE-NEXT:     7: argument_constructors::D() (CXXConstructExpr, [B1.8], [B1.10], [B1.11], class argument_constructors::D)
+// CXX11-NOELIDE-NEXT:     7: argument_constructors::D() (CXXConstructExpr, [B1.8], [B1.10], class argument_constructors::D)
+// CXX11-NEXT:     8: [B1.7] (BindTemporary)
+// CXX11-NEXT:     9: [B1.8] (ImplicitCastExpr, NoOp, const class argument_constructors::D)
+// CXX11-NEXT:    10: [B1.9]
+// CXX11-NEXT:    11: [B1.10] (CXXConstructExpr, [B1.12], [B1.13]+1, class argument_constructors::D)
+// CXX11-NEXT:    12: [B1.11] (BindTemporary)
+// CXX11-NEXT:    13: argument_constructors::E([B1.6], [B1.12]) (CXXConstructExpr, class argument_constructors::E)
+// CXX11-NEXT:    14: ~argument_constructors::D() (Temporary object destructor)
+// CXX11-NEXT:    15: ~argument_constructors::D() (Temporary object destructor)
+// CXX11-NEXT:    16: ~argument_constructors::D() (Temporary object destructor)
+// CXX11-NEXT:    17: ~argument_constructors::D() (Temporary object destructor)
+// CXX17:          1: argument_constructors::D() (CXXConstructExpr, [B1.2], [B1.5]+0, class argument_constructors::D)
+// CXX17-NEXT:     2: [B1.1] (BindTemporary)
+// CXX17-NEXT:     3: argument_constructors::D() (CXXConstructExpr, [B1.4], [B1.5]+1, class argument_constructors::D)
+// CXX17-NEXT:     4: [B1.3] (BindTemporary)
+// CXX17-NEXT:     5: argument_constructors::E([B1.2], [B1.4]) (CXXConstructExpr, class argument_constructors::E)
+// CXX17-NEXT:     6: ~argument_constructors::D() (Temporary object destructor)
+// CXX17-NEXT:     7: ~argument_constructors::D() (Temporary object destructor)
+void passTwoArgumentsIntoAnotherConstructor() {
+  E(D(), D());
+}
 } // end namespace argument_constructors
 
 namespace copy_elision_with_extra_arguments {
Index: lib/Analysis/CFG.cpp
===================================================================
--- lib/Analysis/CFG.cpp
+++ lib/Analysis/CFG.cpp
@@ -4352,6 +4352,11 @@
 
 CFGBlock *CFGBuilder::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *C,
                                                   AddStmtChoice asc) {
+  // If the constructor takes objects as arguments by value, we need to properly
+  // construct these objects. Construction contexts we find here aren't for the
+  // constructor C, they're for its arguments only.
+  findConstructionContextsForArguments(C);
+
   autoCreateBlock();
   appendConstructor(Block, C);
   return VisitChildren(C);


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D50487.159844.patch
Type: text/x-patch
Size: 3461 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20180809/c33957cd/attachment.bin>


More information about the cfe-commits mailing list