c++: Fix wrong-code with non-constexpr constructor [PR93169]
authorMarek Polacek <polacek@redhat.com>
Wed, 19 Feb 2020 21:36:38 +0000 (16:36 -0500)
committerMarek Polacek <polacek@redhat.com>
Thu, 20 Feb 2020 00:14:29 +0000 (19:14 -0500)
In order to detect modifying constant objects in constexpr evaluation,
which is UB, in r10-2655 I added code that sets TREE_READONLY on
CONSTRUCTORs of const-qualified objects after they have been fully
constructed.  But I never made sure that what we're setting the flag
on actually is a CONSTRUCTOR.  Consequently, as this test case shows,
we could set TREE_READONLY on a VAR_DECL that in fact wasn't constant,
causing problems later.  Fixed by setting the flag on CONSTRUCTORs
only, and only when the evaluation produced something constant.

2020-02-19  Marek Polacek  <polacek@redhat.com>

PR c++/93169 - wrong-code with a non-constexpr constructor.
* constexpr.c (cxx_eval_call_expression): Only set TREE_READONLY
on constant CONSTRUCTORs.

* g++.dg/cpp0x/constexpr-93169.C: New test.

gcc/cp/ChangeLog
gcc/cp/constexpr.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp0x/constexpr-93169.C [new file with mode: 0644]

index f6b5517d5e43979ddcac14760ef2b11dba98ebce..e1ac5b0f29e2e36ba12295804984ef44f823a401 100644 (file)
@@ -1,3 +1,9 @@
+2020-02-19  Marek Polacek  <polacek@redhat.com>
+
+       PR c++/93169 - wrong-code with a non-constexpr constructor.
+       * constexpr.c (cxx_eval_call_expression): Only set TREE_READONLY
+       on constant CONSTRUCTORs.
+
 2020-02-15  Marek Polacek  <polacek@redhat.com>
 
        PR c++/93710 - poor diagnostic for array initializer.
index bf7a2643003507d2d59def996481ab5f150fb1ea..128f760778bb84d5eba15c774a63aca6ae13dac0 100644 (file)
@@ -2474,7 +2474,8 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
                                                     /*lval*/false,
                                                     non_constant_p,
                                                     overflow_p);
-             TREE_READONLY (e) = true;
+             if (TREE_CODE (e) == CONSTRUCTOR && !*non_constant_p)
+               TREE_READONLY (e) = true;
            }
 
          /* Forget the saved values of the callee's SAVE_EXPRs and
index 049c343fe43cd5d84d939be966f44f8e78cf11b4..a54505ed73e5c129a7dc2a22adf2133a844e0d0d 100644 (file)
@@ -1,3 +1,8 @@
+2020-02-19  Marek Polacek  <polacek@redhat.com>
+
+       PR c++/93169 - wrong-code with a non-constexpr constructor.
+       * g++.dg/cpp0x/constexpr-93169.C: New test.
+
 2020-02-19  Martin Sebor  <msebor@redhat.com>
 
        PR tree-optimization/92128
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-93169.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-93169.C
new file mode 100644 (file)
index 0000000..79fd352
--- /dev/null
@@ -0,0 +1,21 @@
+// PR c++/93169 - Wrong-code with a non-constexpr constructor.
+// { dg-do run { target c++11 } }
+// { dg-options "-O2" }
+
+template <typename T> class B {
+  struct C {
+    T h;
+    constexpr C() {}
+    ~C() {}
+  } c;
+};
+struct S {
+  int g;
+  S() { g = 2; }
+};
+
+int
+main()
+{
+  static const B<S> f;
+}