mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-04-02 05:50:26 +08:00
re PR c++/56041 (Constexpr conversion function definition not found in template argument context)
PR c++/56041 * cp-tree.h (struct processing_template_decl_sentinel): New. * pt.c (instantiate_non_dependent_expr_internal): Split out from... (instantiate_non_dependent_expr_sfinae): Here. (convert_nontype_argument): Use them. * constexpr.c (fold_non_dependent_expr): Use them. From-SVN: r217823
This commit is contained in:
parent
9d39384c6b
commit
1b5695e610
@ -1,5 +1,12 @@
|
||||
2014-11-19 Jason Merrill <jason@redhat.com>
|
||||
|
||||
PR c++/56041
|
||||
* cp-tree.h (struct processing_template_decl_sentinel): New.
|
||||
* pt.c (instantiate_non_dependent_expr_internal): Split out from...
|
||||
(instantiate_non_dependent_expr_sfinae): Here.
|
||||
(convert_nontype_argument): Use them.
|
||||
* constexpr.c (fold_non_dependent_expr): Use them.
|
||||
|
||||
PR c++/63885
|
||||
* constexpr.c (cxx_eval_constant_expression) [PARM_DECL]: Don't
|
||||
complain yet about a reference.
|
||||
|
@ -3506,17 +3506,8 @@ fold_non_dependent_expr (tree t)
|
||||
if (!instantiation_dependent_expression_p (t)
|
||||
&& potential_constant_expression (t))
|
||||
{
|
||||
HOST_WIDE_INT saved_processing_template_decl;
|
||||
|
||||
saved_processing_template_decl = processing_template_decl;
|
||||
processing_template_decl = 0;
|
||||
t = tsubst_copy_and_build (t,
|
||||
/*args=*/NULL_TREE,
|
||||
tf_none,
|
||||
/*in_decl=*/NULL_TREE,
|
||||
/*function_p=*/false,
|
||||
/*integral_constant_expression_p=*/true);
|
||||
processing_template_decl = saved_processing_template_decl;
|
||||
processing_template_decl_sentinel s;
|
||||
t = instantiate_non_dependent_expr_internal (t, tf_none);
|
||||
|
||||
if (type_unknown_p (t)
|
||||
|| BRACE_ENCLOSED_INITIALIZER_P (t))
|
||||
|
@ -1082,6 +1082,8 @@ struct GTY(()) saved_scope {
|
||||
struct saved_scope *prev;
|
||||
};
|
||||
|
||||
extern GTY(()) struct saved_scope *scope_chain;
|
||||
|
||||
/* The current open namespace. */
|
||||
|
||||
#define current_namespace scope_chain->old_namespace
|
||||
@ -1123,6 +1125,24 @@ struct GTY(()) saved_scope {
|
||||
#define processing_specialization scope_chain->x_processing_specialization
|
||||
#define processing_explicit_instantiation scope_chain->x_processing_explicit_instantiation
|
||||
|
||||
/* RAII sentinel to handle clearing processing_template_decl and restoring
|
||||
it when done. */
|
||||
|
||||
struct processing_template_decl_sentinel
|
||||
{
|
||||
int saved;
|
||||
processing_template_decl_sentinel (bool reset = true)
|
||||
: saved (processing_template_decl)
|
||||
{
|
||||
if (reset)
|
||||
processing_template_decl = 0;
|
||||
}
|
||||
~processing_template_decl_sentinel()
|
||||
{
|
||||
processing_template_decl = saved;
|
||||
}
|
||||
};
|
||||
|
||||
/* The cached class binding level, from the most recently exited
|
||||
class, or NULL if none. */
|
||||
|
||||
@ -1140,8 +1160,6 @@ struct GTY(()) saved_scope {
|
||||
|
||||
/* A list of private types mentioned, for deferred access checking. */
|
||||
|
||||
extern GTY(()) struct saved_scope *scope_chain;
|
||||
|
||||
struct GTY((for_user)) cxx_int_tree_map {
|
||||
unsigned int uid;
|
||||
tree to;
|
||||
@ -5716,6 +5734,7 @@ extern void make_args_non_dependent (vec<tree, va_gc> *);
|
||||
extern bool reregister_specialization (tree, tree, tree);
|
||||
extern tree instantiate_non_dependent_expr (tree);
|
||||
extern tree instantiate_non_dependent_expr_sfinae (tree, tsubst_flags_t);
|
||||
extern tree instantiate_non_dependent_expr_internal (tree, tsubst_flags_t);
|
||||
extern bool alias_type_or_template_p (tree);
|
||||
extern bool alias_template_specialization_p (const_tree);
|
||||
extern bool dependent_alias_template_spec_p (const_tree);
|
||||
|
45
gcc/cp/pt.c
45
gcc/cp/pt.c
@ -5212,6 +5212,24 @@ redeclare_class_template (tree type, tree parms)
|
||||
return true;
|
||||
}
|
||||
|
||||
/* The actual substitution part of instantiate_non_dependent_expr_sfinae,
|
||||
to be used when the caller has already checked
|
||||
(processing_template_decl
|
||||
&& !instantiation_dependent_expression_p (expr)
|
||||
&& potential_constant_expression (expr))
|
||||
and cleared processing_template_decl. */
|
||||
|
||||
tree
|
||||
instantiate_non_dependent_expr_internal (tree expr, tsubst_flags_t complain)
|
||||
{
|
||||
return tsubst_copy_and_build (expr,
|
||||
/*args=*/NULL_TREE,
|
||||
complain,
|
||||
/*in_decl=*/NULL_TREE,
|
||||
/*function_p=*/false,
|
||||
/*integral_constant_expression_p=*/true);
|
||||
}
|
||||
|
||||
/* Simplify EXPR if it is a non-dependent expression. Returns the
|
||||
(possibly simplified) expression. */
|
||||
|
||||
@ -5232,17 +5250,8 @@ instantiate_non_dependent_expr_sfinae (tree expr, tsubst_flags_t complain)
|
||||
&& !instantiation_dependent_expression_p (expr)
|
||||
&& potential_constant_expression (expr))
|
||||
{
|
||||
HOST_WIDE_INT saved_processing_template_decl;
|
||||
|
||||
saved_processing_template_decl = processing_template_decl;
|
||||
processing_template_decl = 0;
|
||||
expr = tsubst_copy_and_build (expr,
|
||||
/*args=*/NULL_TREE,
|
||||
complain,
|
||||
/*in_decl=*/NULL_TREE,
|
||||
/*function_p=*/false,
|
||||
/*integral_constant_expression_p=*/true);
|
||||
processing_template_decl = saved_processing_template_decl;
|
||||
processing_template_decl_sentinel s;
|
||||
expr = instantiate_non_dependent_expr_internal (expr, complain);
|
||||
}
|
||||
return expr;
|
||||
}
|
||||
@ -5736,11 +5745,15 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain)
|
||||
so that access checking can be performed when the template is
|
||||
instantiated -- but here we need the resolved form so that we can
|
||||
convert the argument. */
|
||||
bool non_dep = false;
|
||||
if (TYPE_REF_OBJ_P (type)
|
||||
&& has_value_dependent_address (expr))
|
||||
/* If we want the address and it's value-dependent, don't fold. */;
|
||||
else if (!type_unknown_p (expr))
|
||||
expr = instantiate_non_dependent_expr_sfinae (expr, complain);
|
||||
else if (!type_unknown_p (expr)
|
||||
&& processing_template_decl
|
||||
&& !instantiation_dependent_expression_p (expr)
|
||||
&& potential_constant_expression (expr))
|
||||
non_dep = true;
|
||||
if (error_operand_p (expr))
|
||||
return error_mark_node;
|
||||
expr_type = TREE_TYPE (expr);
|
||||
@ -5749,6 +5762,12 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain)
|
||||
else
|
||||
expr = mark_rvalue_use (expr);
|
||||
|
||||
/* If the argument is non-dependent, perform any conversions in
|
||||
non-dependent context as well. */
|
||||
processing_template_decl_sentinel s (non_dep);
|
||||
if (non_dep)
|
||||
expr = instantiate_non_dependent_expr_internal (expr, complain);
|
||||
|
||||
/* 14.3.2/5: The null pointer{,-to-member} conversion is applied
|
||||
to a non-type argument of "nullptr". */
|
||||
if (expr == nullptr_node && TYPE_PTR_OR_PTRMEM_P (type))
|
||||
|
34
gcc/testsuite/g++.dg/cpp0x/constexpr-conv1.C
Normal file
34
gcc/testsuite/g++.dg/cpp0x/constexpr-conv1.C
Normal file
@ -0,0 +1,34 @@
|
||||
// PR c++/56041
|
||||
// { dg-do compile { target c++11 } }
|
||||
|
||||
template< class T, T v >
|
||||
struct integral_constant
|
||||
{
|
||||
using type = integral_constant<T,v>;
|
||||
using value_type = T;
|
||||
static constexpr T value = v;
|
||||
constexpr operator T ( ) noexcept { return value; }
|
||||
};
|
||||
|
||||
using true_type = integral_constant<bool, true>;
|
||||
using false_type = integral_constant<bool, false>;
|
||||
|
||||
template< bool b, class T = void > struct enable_if { using type = T; };
|
||||
template< class T > struct enable_if<false, T> { };
|
||||
|
||||
|
||||
template< class T,
|
||||
class = typename enable_if< true_type{} // should compile; doesn't
|
||||
, T>::type
|
||||
>
|
||||
T try_it( ) { return T{}; }
|
||||
|
||||
int main( )
|
||||
{
|
||||
static_assert( true_type{} , "failed test 1!" );
|
||||
static_assert( true_type{} , "failed test 2!" );
|
||||
static_assert( ! false_type{} , "failed test 3!" );
|
||||
static_assert( !! true_type{} , "failed test 4!" );
|
||||
|
||||
return try_it<int>();
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user