aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
authorMarek Polacek <polacek@redhat.com>2018-09-18 19:16:28 +0000
committerMarek Polacek <mpolacek@gcc.gnu.org>2018-09-18 19:16:28 +0000
commitbf8d83098ffafe1273b11eb5f4a596f96c90c42e (patch)
tree69c54203512e9f57ce7c3840298da4c7fe1adf99 /gcc/cp
parente8db6cd5fb1ad254329e426dcc8e958c02e2284f (diff)
downloadgcc-bf8d83098ffafe1273b11eb5f4a596f96c90c42e.zip
gcc-bf8d83098ffafe1273b11eb5f4a596f96c90c42e.tar.gz
gcc-bf8d83098ffafe1273b11eb5f4a596f96c90c42e.tar.bz2
P1064R0 - Allowing Virtual Function Calls in Constant Expressions
P1064R0 - Allowing Virtual Function Calls in Constant Expressions * call.c (build_over_call): No longer check if we're outside a template function. * class.c (build_vtbl_initializer): Build vtable's constructor with indexes. * constexpr.c (cxx_eval_constant_expression): Don't ignore _vptr's initializer. Handle OBJ_TYPE_REF. (potential_constant_expression_1): Handle OBJ_TYPE_REF. * decl.c (maybe_commonize_var): Bail out for any DECL_ARTIFICIAL. (initialize_artificial_var): Mark the variable as constexpr. (grokdeclarator): Change error to pedwarn. Only warn when pedantic and not C++2a. * gimple-fold.c (gimple_get_virt_method_for_vtable): Adjust assert. * g++.dg/cpp0x/constexpr-virtual5.C: Adjust dg-error. * g++.dg/cpp2a/constexpr-virtual1.C: New test. * g++.dg/cpp2a/constexpr-virtual2.C: New test. * g++.dg/cpp2a/constexpr-virtual3.C: New test. * g++.dg/cpp2a/constexpr-virtual4.C: New test. * g++.dg/cpp2a/constexpr-virtual5.C: New test. * g++.dg/cpp2a/constexpr-virtual6.C: New test. * g++.dg/cpp2a/constexpr-virtual7.C: New test. * g++.dg/cpp2a/constexpr-virtual8.C: New test. * g++.dg/cpp2a/constexpr-virtual9.C: New test. * g++.dg/diagnostic/virtual-constexpr.C: Skip for C++2a. Use -pedantic-errors. Adjust dg-error. From-SVN: r264408
Diffstat (limited to 'gcc/cp')
-rw-r--r--gcc/cp/ChangeLog15
-rw-r--r--gcc/cp/call.c5
-rw-r--r--gcc/cp/class.c7
-rw-r--r--gcc/cp/constexpr.c42
-rw-r--r--gcc/cp/decl.c17
5 files changed, 72 insertions, 14 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index fdc1247..7ea4b6d 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,18 @@
+2018-09-18 Marek Polacek <polacek@redhat.com>
+
+ P1064R0 - Allowing Virtual Function Calls in Constant Expressions
+ * call.c (build_over_call): No longer check if we're outside a template
+ function.
+ * class.c (build_vtbl_initializer): Build vtable's constructor with
+ indexes.
+ * constexpr.c (cxx_eval_constant_expression): Don't ignore _vptr's
+ initializer. Handle OBJ_TYPE_REF.
+ (potential_constant_expression_1): Handle OBJ_TYPE_REF.
+ * decl.c (maybe_commonize_var): Bail out for any DECL_ARTIFICIAL.
+ (initialize_artificial_var): Mark the variable as constexpr.
+ (grokdeclarator): Change error to pedwarn. Only warn when
+ pedantic and not C++2a.
+
2018-09-18 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/85065
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 69503ca..ddf0ed0 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -8399,10 +8399,7 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
&& DECL_BUILT_IN_CLASS (fn) == BUILT_IN_NORMAL)
maybe_warn_class_memaccess (input_location, fn, args);
- if (DECL_VINDEX (fn) && (flags & LOOKUP_NONVIRTUAL) == 0
- /* Don't mess with virtual lookup in instantiate_non_dependent_expr;
- virtual functions can't be constexpr. */
- && !in_template_function ())
+ if (DECL_VINDEX (fn) && (flags & LOOKUP_NONVIRTUAL) == 0)
{
tree t;
tree binfo = lookup_base (TREE_TYPE (TREE_TYPE (argarray[0])),
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index e950a74..9ca4644 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -9266,6 +9266,7 @@ build_vtbl_initializer (tree binfo,
tree vcall_index;
tree fn, fn_original;
tree init = NULL_TREE;
+ tree idx = size_int (jx++);
fn = BV_FN (v);
fn_original = fn;
@@ -9369,7 +9370,7 @@ build_vtbl_initializer (tree binfo,
int i;
if (init == size_zero_node)
for (i = 0; i < TARGET_VTABLE_USES_DESCRIPTORS; ++i)
- CONSTRUCTOR_APPEND_ELT (*inits, NULL_TREE, init);
+ CONSTRUCTOR_APPEND_ELT (*inits, idx, init);
else
for (i = 0; i < TARGET_VTABLE_USES_DESCRIPTORS; ++i)
{
@@ -9377,11 +9378,11 @@ build_vtbl_initializer (tree binfo,
fn, build_int_cst (NULL_TREE, i));
TREE_CONSTANT (fdesc) = 1;
- CONSTRUCTOR_APPEND_ELT (*inits, NULL_TREE, fdesc);
+ CONSTRUCTOR_APPEND_ELT (*inits, idx, fdesc);
}
}
else
- CONSTRUCTOR_APPEND_ELT (*inits, NULL_TREE, init);
+ CONSTRUCTOR_APPEND_ELT (*inits, idx, init);
}
}
diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index 88c7378..aa33319 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -4209,7 +4209,11 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
CONST_DECL for aggregate constants. */
if (lval)
return t;
+ /* is_really_empty_class doesn't take into account _vptr, so initializing
+ otherwise empty class with { } would overwrite the initializer that
+ initialize_vtable created for us. */
if (COMPLETE_TYPE_P (TREE_TYPE (t))
+ && !TYPE_POLYMORPHIC_P (TREE_TYPE (t))
&& is_really_empty_class (TREE_TYPE (t)))
{
/* If the class is empty, we aren't actually loading anything. */
@@ -4778,7 +4782,6 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
case MODOP_EXPR:
/* GCC internal stuff. */
case VA_ARG_EXPR:
- case OBJ_TYPE_REF:
case NON_DEPENDENT_EXPR:
case BASELINK:
case OFFSET_REF:
@@ -4788,6 +4791,34 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
*non_constant_p = true;
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);
+ /* We expect something in the form of &x.D.2103.D.2094; get x. */
+ if (TREE_CODE (obj) != ADDR_EXPR)
+ {
+ if (!ctx->quiet)
+ error_at (cp_expr_loc_or_loc (t, input_location),
+ "expression %qE is not a constant expression", t);
+ *non_constant_p = true;
+ return t;
+ }
+ obj = TREE_OPERAND (obj, 0);
+ while (handled_component_p (obj))
+ obj = TREE_OPERAND (obj, 0);
+ tree objtype = TREE_TYPE (obj);
+ /* 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));
+ r = TREE_VALUE (chain_index (token, virtuals));
+ break;
+ }
+
case PLACEHOLDER_EXPR:
/* Use of the value or address of the current object. */
if (tree ctor = lookup_placeholder (ctx, lval, TREE_TYPE (t)))
@@ -5871,7 +5902,6 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
case OACC_UPDATE:
/* GCC internal stuff. */
case VA_ARG_EXPR:
- case OBJ_TYPE_REF:
case TRANSACTION_EXPR:
case ASM_EXPR:
case AT_ENCODE_EXPR:
@@ -5880,6 +5910,14 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
error_at (loc, "expression %qE is not a constant expression", t);
return false;
+ case OBJ_TYPE_REF:
+ if (cxx_dialect >= cxx2a)
+ /* In C++2a virtual calls can be constexpr, don't give up yet. */
+ return true;
+ else if (flags & tf_error)
+ error_at (loc, "virtual functions cannot be constexpr before C++2a");
+ return false;
+
case TYPEID_EXPR:
/* -- a typeid expression whose operand is of polymorphic
class type; */
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 50b60e8..827c172 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -5583,11 +5583,13 @@ layout_var_decl (tree decl)
void
maybe_commonize_var (tree decl)
{
+ /* Don't mess with __FUNCTION__ and similar. */
+ if (DECL_ARTIFICIAL (decl))
+ return;
+
/* Static data in a function with comdat linkage also has comdat
linkage. */
if ((TREE_STATIC (decl)
- /* Don't mess with __FUNCTION__. */
- && ! DECL_ARTIFICIAL (decl)
&& DECL_FUNCTION_SCOPE_P (decl)
&& vague_linkage_p (DECL_CONTEXT (decl)))
|| (TREE_PUBLIC (decl) && DECL_INLINE_VAR_P (decl)))
@@ -6774,6 +6776,10 @@ initialize_artificial_var (tree decl, vec<constructor_elt, va_gc> *v)
gcc_assert (TREE_CODE (init) == CONSTRUCTOR);
DECL_INITIAL (decl) = init;
DECL_INITIALIZED_P (decl) = 1;
+ /* Mark the decl as constexpr so that we can access its content
+ at compile time. */
+ DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl) = true;
+ DECL_DECLARED_CONSTEXPR_P (decl) = true;
determine_visibility (decl);
layout_var_decl (decl);
maybe_commonize_var (decl);
@@ -10854,12 +10860,13 @@ grokdeclarator (const cp_declarator *declarator,
storage_class = sc_none;
staticp = 0;
}
- if (constexpr_p)
+ if (constexpr_p && cxx_dialect < cxx2a)
{
gcc_rich_location richloc (declspecs->locations[ds_virtual]);
richloc.add_range (declspecs->locations[ds_constexpr]);
- error_at (&richloc, "member %qD cannot be declared both %<virtual%> "
- "and %<constexpr%>", dname);
+ pedwarn (&richloc, OPT_Wpedantic, "member %qD can be declared both "
+ "%<virtual%> and %<constexpr%> only in -std=c++2a or "
+ "-std=gnu++2a", dname);
}
}
friendp = decl_spec_seq_has_spec_p (declspecs, ds_friend);