From e079dced7a83837e8924e555aea315e4c43fafcd Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Fri, 1 Jun 2018 16:49:43 -0400 Subject: [PATCH] CWG 1581: When are constexpr member functions defined? * constexpr.c (instantiate_cx_fn_r, instantiate_constexpr_fns): New. (cxx_eval_outermost_constant_expr): Call instantiate_constexpr_fns. From-SVN: r261086 --- gcc/cp/ChangeLog | 6 +++ gcc/cp/constexpr.c | 42 ++++++++++++++++++++ gcc/testsuite/g++.dg/cpp2a/constexpr-inst1.C | 13 ++++++ 3 files changed, 61 insertions(+) create mode 100644 gcc/testsuite/g++.dg/cpp2a/constexpr-inst1.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index ec827c25108..d0ed3634a71 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,9 @@ +2018-05-31 Jason Merrill + + CWG 1581: When are constexpr member functions defined? + * constexpr.c (instantiate_cx_fn_r, instantiate_constexpr_fns): New. + (cxx_eval_outermost_constant_expr): Call instantiate_constexpr_fns. + 2018-06-01 Jason Merrill PR c++/58281 - explicit instantiation of constexpr diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index a099408dd28..944c1cdf11e 100644 --- a/gcc/cp/constexpr.c +++ b/gcc/cp/constexpr.c @@ -4813,6 +4813,46 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, return r; } +/* P0859: A function is needed for constant evaluation if it is a constexpr + function that is named by an expression ([basic.def.odr]) that is + potentially constant evaluated. + + So we need to instantiate any constexpr functions mentioned by the + expression even if the definition isn't needed for evaluating the + expression. */ + +static tree +instantiate_cx_fn_r (tree *tp, int *walk_subtrees, void */*data*/) +{ + if (TREE_CODE (*tp) == FUNCTION_DECL + && DECL_DECLARED_CONSTEXPR_P (*tp) + && !DECL_INITIAL (*tp) + && DECL_TEMPLOID_INSTANTIATION (*tp)) + { + ++function_depth; + instantiate_decl (*tp, /*defer_ok*/false, /*expl_inst*/false); + --function_depth; + } + else if (TREE_CODE (*tp) == CALL_EXPR + || TREE_CODE (*tp) == AGGR_INIT_EXPR) + { + if (EXPR_HAS_LOCATION (*tp)) + input_location = EXPR_LOCATION (*tp); + } + + if (!EXPR_P (*tp)) + *walk_subtrees = 0; + + return NULL_TREE; +} +static void +instantiate_constexpr_fns (tree t) +{ + location_t loc = input_location; + cp_walk_tree_without_duplicates (&t, instantiate_cx_fn_r, NULL); + input_location = loc; +} + static tree cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant, bool strict = true, tree object = NULL_TREE) @@ -4858,6 +4898,7 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant, r = TARGET_EXPR_INITIAL (r); } + instantiate_constexpr_fns (r); r = cxx_eval_constant_expression (&ctx, r, false, &non_constant_p, &overflow_p); @@ -4959,6 +5000,7 @@ is_sub_constant_expr (tree t) constexpr_ctx ctx = { NULL, &map, NULL, NULL, NULL, NULL, true, true }; + instantiate_constexpr_fns (t); cxx_eval_constant_expression (&ctx, t, false, &non_constant_p, &overflow_p); return !non_constant_p && !overflow_p; diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-inst1.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-inst1.C new file mode 100644 index 00000000000..1016bec9d3e --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-inst1.C @@ -0,0 +1,13 @@ +// Testcase from P0859 +// { dg-do compile { target c++14 } } + +template constexpr int f() { return T::value; } // { dg-error "int" } +template void g(decltype(B ? f() : 0)); +template void g(...); +template void h(decltype(int{B ? f() : 0})); +template void h(...); +void x() { + g(0); // OK, B ? f() : 0 is not potentially constant evaluated + h(0); // error, instantiates f even though B evaluates to false and + // list-initialization of int from int cannot be narrowing +} -- 2.30.2