public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc/devel/c++-modules] c++: Fix complex constexpr virtual cases [PR93310].
@ 2020-06-11 13:17 Nathan Sidwell
  0 siblings, 0 replies; only message in thread
From: Nathan Sidwell @ 2020-06-11 13:17 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:7ece3bd8088983289731450826c238eb2bdd2db5

commit 7ece3bd8088983289731450826c238eb2bdd2db5
Author: Jason Merrill <jason@redhat.com>
Date:   Wed Jun 3 23:50:50 2020 -0400

    c++: Fix complex constexpr virtual cases [PR93310].
    
    The code in constexpr for looking up the actual type of the object and then
    getting the virtual function from there broke for both of these tests: for
    16, it assumed incorrectly that the DECL_VINDEX would apply to the most
    derived type's vtable; for 17, it failed to consider that during
    construction the base subobject is treated as being of the base type.
    
    Fixed by just doing constant evaluation of the expression that looks up the
    function in the vtable.  This means that a virtual call will involve loading
    the vptr, so we will reject some calls through non-constexpr variables that
    we previously accepted, but this seems appropriate to me.  None of our
    testcases were affected.
    
    gcc/cp/ChangeLog:
    
            PR c++/93310
            * constexpr.c (cxx_eval_constant_expression) [OBJ_TYPE_REF]:
            Evaluate OBJ_TYPE_REF_EXPR.
    
    gcc/testsuite/ChangeLog:
    
            PR c++/93310
            * g++.dg/cpp2a/constexpr-virtual16.C: New test.
            * g++.dg/cpp2a/constexpr-virtual17.C: New test.
            * g++.dg/cpp2a/constexpr-new12.C: Adjust diagnostic.

Diff:
---
 gcc/cp/constexpr.c                               | 44 ++----------------------
 gcc/testsuite/g++.dg/cpp2a/constexpr-new12.C     |  2 +-
 gcc/testsuite/g++.dg/cpp2a/constexpr-virtual16.C | 22 ++++++++++++
 gcc/testsuite/g++.dg/cpp2a/constexpr-virtual17.C | 28 +++++++++++++++
 4 files changed, 54 insertions(+), 42 deletions(-)

diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index c7d17e9b86e..c01c42bf886 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -6373,47 +6373,9 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
       break;
 
     case OBJ_TYPE_REF:
-      {
-	/* Virtual function call.  Let the constexpr machinery figure out
-	   the dynamic type.  */
-	int token = tree_to_shwi (OBJ_TYPE_REF_TOKEN (t));
-	tree obj = OBJ_TYPE_REF_OBJECT (t);
-	obj = cxx_eval_constant_expression (ctx, obj, lval, non_constant_p,
-					    overflow_p);
-	STRIP_NOPS (obj);
-	/* We expect something in the form of &x.D.2103.D.2094; get x. */
-	if (TREE_CODE (obj) != ADDR_EXPR
-	    || !DECL_P (get_base_address (TREE_OPERAND (obj, 0))))
-	  {
-	    if (!ctx->quiet)
-	      error_at (loc, "expression %qE is not a constant expression", t);
-	    *non_constant_p = true;
-	    return t;
-	  }
-	obj = TREE_OPERAND (obj, 0);
-	while (TREE_CODE (obj) == COMPONENT_REF
-	       && DECL_FIELD_IS_BASE (TREE_OPERAND (obj, 1)))
-	  obj = TREE_OPERAND (obj, 0);
-	tree objtype = TREE_TYPE (obj);
-	if (VAR_P (obj)
-	    && DECL_NAME (obj) == heap_identifier
-	    && TREE_CODE (objtype) == ARRAY_TYPE)
-	  objtype = TREE_TYPE (objtype);
-	if (!CLASS_TYPE_P (objtype))
-	  {
-	    if (!ctx->quiet)
-	      error_at (loc, "expression %qE is not a constant expression", t);
-	    *non_constant_p = true;
-	    return t;
-	  }
-	/* Find the function decl in the virtual functions list.  TOKEN is
-	   the DECL_VINDEX that says which function we're looking for.  */
-	tree virtuals = BINFO_VIRTUALS (TYPE_BINFO (objtype));
-	if (TARGET_VTABLE_USES_DESCRIPTORS)
-	  token /= MAX (TARGET_VTABLE_USES_DESCRIPTORS, 1);
-	r = TREE_VALUE (chain_index (token, virtuals));
-	break;
-      }
+      /* Virtual function lookup.  We don't need to do anything fancy.  */
+      return cxx_eval_constant_expression (ctx, OBJ_TYPE_REF_EXPR (t),
+					   lval, non_constant_p, overflow_p);
 
     case PLACEHOLDER_EXPR:
       /* Use of the value or address of the current object.  */
diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-new12.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-new12.C
index fcf398f000e..5a3d06a5fab 100644
--- a/gcc/testsuite/g++.dg/cpp2a/constexpr-new12.C
+++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-new12.C
@@ -24,4 +24,4 @@ foo ()
   return r;
 }
 
-constexpr auto a = foo ();	// { dg-error "is not a constant expression" }
+constexpr auto a = foo ();	// { dg-error "constant expression" }
diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-virtual16.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-virtual16.C
new file mode 100644
index 00000000000..8cca8a61723
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-virtual16.C
@@ -0,0 +1,22 @@
+// Test constexpr virtual in non-primary vtable.
+// { dg-do compile { target c++20 } }
+
+struct A
+{
+  virtual constexpr int f() const { return 1; };
+};
+
+struct B
+{
+  virtual constexpr int g() const { return 2; };
+};
+
+struct C: A, B
+{
+};
+
+constexpr C c;
+
+constexpr int g(const B& b) { return b.g(); }
+static_assert (g(c) == 2);
+
diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-virtual17.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-virtual17.C
new file mode 100644
index 00000000000..a8a89952626
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-virtual17.C
@@ -0,0 +1,28 @@
+// PR c++/93310
+// { dg-do compile { target c++20 } }
+
+struct A
+{
+  virtual constexpr char f () const
+  { return 'A'; }
+};
+
+struct B : A
+{
+  char x;
+
+  constexpr B () : x (0)
+  { x = ((A *)this)->f(); }
+
+  virtual constexpr char f () const
+  { return 'B'; }
+};
+
+struct C : B
+{
+  virtual constexpr char f () const
+  { return 'C'; }
+};
+
+constexpr C c;
+static_assert (c.x == 'B');


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2020-06-11 13:17 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-06-11 13:17 [gcc/devel/c++-modules] c++: Fix complex constexpr virtual cases [PR93310] Nathan Sidwell

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).