Commit cd61690f by Dodji Seketeli Committed by Dodji Seketeli

PR c++/55663 - constexpr function templ instantiation

Consider the example of the problem report

     1	template <typename>
     2	constexpr bool the_truth () { return true; }
     3
     4	template <bool>
     5	  struct Takes_bool { };
     6
     7	template<bool B>
     8	  using Alias = Takes_bool<B>;
     9
    10	template<typename T>
    11	  struct test { using type = Alias<the_truth<T>()>; };
    12
    13	int main () {
    14	  test<int> a;
    15
    16	  return 0;
    17	}

that yields the error:

    test.cc: In substitution of ‘template<bool B> using Alias = Takes_bool<B> [with bool B = the_truth<int>()]’:
    test.cc:11:51:   required from ‘struct test<int>’
    test.cc:14:13:   required from here
    test.cc:11:51: error: integral expression ‘the_truth<int>()’ is not constant
       struct test { using type = Alias<the_truth<T>()>; };

I think the issue happens in the course of instantiating test<int> at
line 14, when we look into instantiating Alias<the_truth<T>()> (at
line 11) (using instantiate_alias_template) with T = int.

There, when we check the argument 'the_truth<int>()' to see if it
actually is a constant expression, in check_instantiated_arg, we fail
to recognize it constexpr-ness b/c we just look at its TREE_CONSTANT.

At that point, the_truth<int> should have been folded, and it's not,
because instantiate_alias_template forgets to call
coerce_template_parms on its arguments.

Fixed thus, bootstapped and tested on x86_64-unknown-linux-gnu against
trunk.

gcc/cp/

	PR c++/55663
	* pt.c (coerce_innermost_template_parms): New static function.
	(instantiate_alias_template):  Use it here.

gcc/testsuite/

	PR c++/55663
	* g++.dg/cpp0x/alias-decl-31.C: New test.

From-SVN: r195189
parent 955f5a07
2013-01-15 Dodji Seketeli <dodji@redhat.com>
PR c++/55663
* pt.c (coerce_innermost_template_parms): New static function.
(instantiate_alias_template): Use it here.
2013-01-09 Jason Merrill <jason@redhat.com>
PR c++/55878
......
......@@ -128,6 +128,8 @@ static tree tsubst_initializer_list (tree, tree);
static tree get_class_bindings (tree, tree, tree, tree);
static tree coerce_template_parms (tree, tree, tree, tsubst_flags_t,
bool, bool);
static tree coerce_innermost_template_parms (tree, tree, tree, tsubst_flags_t,
bool, bool);
static void tsubst_enum (tree, tree, tree);
static tree add_to_template_args (tree, tree);
static tree add_outermost_template_args (tree, tree);
......@@ -6740,6 +6742,61 @@ coerce_template_parms (tree parms,
return new_inner_args;
}
/* Like coerce_template_parms. If PARMS represents all template
parameters levels, this function returns a vector of vectors
representing all the resulting argument levels. Note that in this
case, only the innermost arguments are coerced because the
outermost ones are supposed to have been coerced already.
Otherwise, if PARMS represents only (the innermost) vector of
parameters, this function returns a vector containing just the
innermost resulting arguments. */
static tree
coerce_innermost_template_parms (tree parms,
tree args,
tree in_decl,
tsubst_flags_t complain,
bool require_all_args,
bool use_default_args)
{
int parms_depth = TMPL_PARMS_DEPTH (parms);
int args_depth = TMPL_ARGS_DEPTH (args);
tree coerced_args;
if (parms_depth > 1)
{
coerced_args = make_tree_vec (parms_depth);
tree level;
int cur_depth;
for (level = parms, cur_depth = parms_depth;
parms_depth > 0 && level != NULL_TREE;
level = TREE_CHAIN (level), --cur_depth)
{
tree l;
if (cur_depth == args_depth)
l = coerce_template_parms (TREE_VALUE (level),
args, in_decl, complain,
require_all_args,
use_default_args);
else
l = TMPL_ARGS_LEVEL (args, cur_depth);
if (l == error_mark_node)
return error_mark_node;
SET_TMPL_ARGS_LEVEL (coerced_args, cur_depth, l);
}
}
else
coerced_args = coerce_template_parms (INNERMOST_TEMPLATE_PARMS (parms),
args, in_decl, complain,
require_all_args,
use_default_args);
return coerced_args;
}
/* Returns 1 if template args OT and NT are equivalent. */
static int
......@@ -14640,6 +14697,13 @@ instantiate_alias_template (tree tmpl, tree args, tsubst_flags_t complain)
ggc_free (tinst);
return error_mark_node;
}
args =
coerce_innermost_template_parms (DECL_TEMPLATE_PARMS (tmpl),
args, tmpl, complain,
/*require_all_args=*/true,
/*use_default_args=*/true);
tree r = instantiate_template (tmpl, args, complain);
pop_tinst_level ();
/* We can't free this if a pending_template entry or last_error_tinst_level
......
2013-01-15 Dodji Seketeli <dodji@redhat.com>
PR c++/55663
* g++.dg/cpp0x/alias-decl-31.C: New test.
2013-01-15 Paul Thomas <pault@gcc.gnu.org>
PR fortran/54286
......
// Origin: PR c++/55663
// { dg-do compile { target c++11 } }
template <typename>
constexpr bool the_truth () { return true; }
template <bool>
struct Takes_bool { };
template<bool B>
using Alias = Takes_bool<B>;
template<typename T>
struct test { using type = Alias<the_truth<T>()>; };
int main () {
test<int> a;
return 0;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment