[PATCH] D49627: [CFG] [analyzer] Constructors of member CXXOperatorCallExpr's argument 0 are not argument constructors.

Artem Dergachev via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Fri Jul 20 17:46:00 PDT 2018


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

Because `CXXOperatorCallExpr`'s argument 0 is the `this`-argument of the operator if the operator is a member. This doesn't correspond to operator declaration parameters.

Do not provide argument construction context for such arguments. For the remaining arguments, provide a context, even though argument index still doesn't match parameter index; the user would, unfortunately, need to work around that, as we can't satisfy both.

Actually supporting such this-argument construction contexts would address the FIXME that we've added in https://reviews.llvm.org/D32642?id=153023#inline-426950 but this patch doesn't go that far.


Repository:
  rC Clang

https://reviews.llvm.org/D49627

Files:
  include/clang/Analysis/ConstructionContext.h
  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
@@ -960,3 +960,37 @@
   C c = C();
 }
 } // namespace copy_elision_with_extra_arguments
+
+
+namespace operators {
+class C {
+public:
+  C(int);
+  C &operator+(C Other);
+};
+
+// FIXME: Find construction context for the this-argument of the operator.
+// CHECK: void testOperators()
+// CHECK:        [B1]
+// CHECK-NEXT:     1: operator+
+// CHECK-NEXT:     2: [B1.1] (ImplicitCastExpr, FunctionToPointerDecay, class operators::C &(*)(class operators::C))
+// CHECK-NEXT:     3: 1
+// CXX11-NEXT:     4: [B1.3] (CXXConstructExpr, class operators::C)
+// CXX11-NEXT:     5: operators::C([B1.4]) (CXXFunctionalCastExpr, ConstructorConversion, class operators::C)
+// CXX11-NEXT:     6: 2
+// CXX11-ELIDE-NEXT:     7: [B1.6] (CXXConstructExpr, [B1.9], [B1.10], class operators::C)
+// CXX11-NOELIDE-NEXT:     7: [B1.6] (CXXConstructExpr, [B1.9], class operators::C)
+// CXX11-NEXT:     8: operators::C([B1.7]) (CXXFunctionalCastExpr, ConstructorConversion, class operators::C)
+// CXX11-NEXT:     9: [B1.8]
+// CXX11-NEXT:    10: [B1.9] (CXXConstructExpr, [B1.11]+1, class operators::C)
+// CXX11-NEXT:    11: [B1.5] + [B1.10] (OperatorCall)
+// CXX17-NEXT:     4: [B1.3] (CXXConstructExpr, class operators::C)
+// CXX17-NEXT:     5: operators::C([B1.4]) (CXXFunctionalCastExpr, ConstructorConversion, class operators::C)
+// CXX17-NEXT:     6: 2
+// CXX17-NEXT:     7: [B1.6] (CXXConstructExpr, [B1.9]+1, class operators::C)
+// CXX17-NEXT:     8: operators::C([B1.7]) (CXXFunctionalCastExpr, ConstructorConversion, class operators::C)
+// CXX17-NEXT:     9: [B1.5] + [B1.8] (OperatorCall)
+void testOperators() {
+  C(1) + C(2);
+}
+} // namespace operators
Index: lib/Analysis/CFG.cpp
===================================================================
--- lib/Analysis/CFG.cpp
+++ lib/Analysis/CFG.cpp
@@ -684,7 +684,7 @@
   void findConstructionContexts(const ConstructionContextLayer *Layer,
                                 Stmt *Child);
 
-  // Scan all arguments of a call expression for a construction context.
+  // Scan all arguments of a call-like expression for a construction context.
   // These sorts of call expressions don't have a common superclass,
   // hence strict duck-typing.
   template <typename CallLikeExpr,
@@ -694,6 +694,18 @@
                 std::is_same<CallLikeExpr, ObjCMessageExpr>::value>>
   void findConstructionContextsForArguments(CallLikeExpr *E) {
     for (unsigned i = 0, e = E->getNumArgs(); i != e; ++i) {
+      if (i == 0) {
+        // FIXME: This check will run for non-CallExpr variants as well,
+        // which is redundant.
+        if (const auto *OE = dyn_cast<CXXOperatorCallExpr>(E))
+          if (dyn_cast_or_null<CXXMethodDecl>(OE->getDirectCallee())) {
+            // It's an operator's this-argument that's mistaken for argument 0
+            // due to an AST inconsistency.
+            // FIXME: Actually introduce the respective construction context.
+            continue;
+          }
+      }
+
       Expr *Arg = E->getArg(i);
       if (Arg->getType()->getAsCXXRecordDecl() && !Arg->isGLValue())
         findConstructionContexts(
Index: include/clang/Analysis/ConstructionContext.h
===================================================================
--- include/clang/Analysis/ConstructionContext.h
+++ include/clang/Analysis/ConstructionContext.h
@@ -597,9 +597,14 @@
 };
 
 class ArgumentConstructionContext : public ConstructionContext {
-  const Expr *CE; // The call of which the context is an argument.
-  unsigned Index; // Which argument we're constructing.
-  const CXXBindTemporaryExpr *BTE; // Whether the object needs to be destroyed.
+  // The call of which the context is an argument.
+  const Expr *CE;
+  // Which argument we're constructing. Note that when numbering between
+  // arguments and parameters is inconsistent (eg., operator calls),
+  // this is the index of the argument, not of the parameter.
+  unsigned Index;
+  // Whether the object needs to be destroyed.
+  const CXXBindTemporaryExpr *BTE;
 
   friend class ConstructionContext; // Allows to create<>() itself.
 


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D49627.156652.patch
Type: text/x-patch
Size: 4283 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20180721/70f5019c/attachment.bin>


More information about the cfe-commits mailing list