re PR c++/45923 (constexpr diagnostics, more more)
PR c++/45923 * class.c (explain_non_literal_class): New. (finalize_literal_type_property): Call it. * cp-tree.h: Declare it. * semantics.c (ensure_literal_type_for_constexpr_object): Call it. (is_valid_constexpr_fn): Likewise. (massage_constexpr_body): Split out from... (register_constexpr_fundef): ...here. (is_instantiation_of_constexpr): New. (expand_or_defer_fn_1): Leave DECL_SAVED_TREE alone in that case. (explain_invalid_constexpr_fn): New. (cxx_eval_call_expression): Call it. (potential_constant_expression_1): Likewise. Avoid redundant errors. * method.c (process_subob_fn): Diagnose non-constexpr. (walk_field_subobs): Likewise. (synthesized_method_walk): Don't shortcut if we want diagnostics. (explain_implicit_non_constexpr): New. (defaulted_late_check): Use it. * call.c (build_cxx_call): Remember location. From-SVN: r175646
This commit is contained in:
parent
874d29e5be
commit
f732fa7b6c
12 changed files with 315 additions and 61 deletions
|
@ -1,5 +1,25 @@
|
|||
2011-06-29 Jason Merrill <jason@redhat.com>
|
||||
|
||||
PR c++/45923
|
||||
* class.c (explain_non_literal_class): New.
|
||||
(finalize_literal_type_property): Call it.
|
||||
* cp-tree.h: Declare it.
|
||||
* semantics.c (ensure_literal_type_for_constexpr_object): Call it.
|
||||
(is_valid_constexpr_fn): Likewise.
|
||||
(massage_constexpr_body): Split out from...
|
||||
(register_constexpr_fundef): ...here.
|
||||
(is_instantiation_of_constexpr): New.
|
||||
(expand_or_defer_fn_1): Leave DECL_SAVED_TREE alone in that case.
|
||||
(explain_invalid_constexpr_fn): New.
|
||||
(cxx_eval_call_expression): Call it.
|
||||
(potential_constant_expression_1): Likewise. Avoid redundant errors.
|
||||
* method.c (process_subob_fn): Diagnose non-constexpr.
|
||||
(walk_field_subobs): Likewise.
|
||||
(synthesized_method_walk): Don't shortcut if we want diagnostics.
|
||||
(explain_implicit_non_constexpr): New.
|
||||
(defaulted_late_check): Use it.
|
||||
* call.c (build_cxx_call): Remember location.
|
||||
|
||||
* method.c (maybe_explain_implicit_delete): Use pointer_set
|
||||
instead of htab.
|
||||
|
||||
|
|
|
@ -6721,7 +6721,10 @@ build_cxx_call (tree fn, int nargs, tree *argarray)
|
|||
{
|
||||
tree fndecl;
|
||||
|
||||
/* Remember roughly where this call is. */
|
||||
location_t loc = EXPR_LOC_OR_HERE (fn);
|
||||
fn = build_call_a (fn, nargs, argarray);
|
||||
SET_EXPR_LOCATION (fn, loc);
|
||||
|
||||
/* If this call might throw an exception, note that fact. */
|
||||
fndecl = get_callee_fndecl (fn);
|
||||
|
|
|
@ -37,6 +37,7 @@ along with GCC; see the file COPYING3. If not see
|
|||
#include "cgraph.h"
|
||||
#include "tree-dump.h"
|
||||
#include "splay-tree.h"
|
||||
#include "pointer-set.h"
|
||||
|
||||
/* The number of nested classes being processed. If we are not in the
|
||||
scope of any class, this is zero. */
|
||||
|
@ -4582,10 +4583,73 @@ finalize_literal_type_property (tree t)
|
|||
{
|
||||
DECL_DECLARED_CONSTEXPR_P (fn) = false;
|
||||
if (!DECL_TEMPLATE_INFO (fn))
|
||||
error ("enclosing class of %q+#D is not a literal type", fn);
|
||||
{
|
||||
error ("enclosing class of constexpr non-static member "
|
||||
"function %q+#D is not a literal type", fn);
|
||||
explain_non_literal_class (t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* T is a non-literal type used in a context which requires a constant
|
||||
expression. Explain why it isn't literal. */
|
||||
|
||||
void
|
||||
explain_non_literal_class (tree t)
|
||||
{
|
||||
static struct pointer_set_t *diagnosed;
|
||||
|
||||
if (!CLASS_TYPE_P (t))
|
||||
return;
|
||||
t = TYPE_MAIN_VARIANT (t);
|
||||
|
||||
if (diagnosed == NULL)
|
||||
diagnosed = pointer_set_create ();
|
||||
if (pointer_set_insert (diagnosed, t) != 0)
|
||||
/* Already explained. */
|
||||
return;
|
||||
|
||||
inform (0, "%q+T is not literal because:", t);
|
||||
if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t))
|
||||
inform (0, " %q+T has a non-trivial destructor", t);
|
||||
else if (CLASSTYPE_NON_AGGREGATE (t)
|
||||
&& !TYPE_HAS_TRIVIAL_DFLT (t)
|
||||
&& !TYPE_HAS_CONSTEXPR_CTOR (t))
|
||||
inform (0, " %q+T is not an aggregate, does not have a trivial "
|
||||
"default constructor, and has no constexpr constructor that "
|
||||
"is not a copy or move constructor", t);
|
||||
else
|
||||
{
|
||||
tree binfo, base_binfo, field; int i;
|
||||
for (binfo = TYPE_BINFO (t), i = 0;
|
||||
BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
|
||||
{
|
||||
tree basetype = TREE_TYPE (base_binfo);
|
||||
if (!CLASSTYPE_LITERAL_P (basetype))
|
||||
{
|
||||
inform (0, " base class %qT of %q+T is non-literal",
|
||||
basetype, t);
|
||||
explain_non_literal_class (basetype);
|
||||
return;
|
||||
}
|
||||
}
|
||||
for (field = TYPE_FIELDS (t); field; field = TREE_CHAIN (field))
|
||||
{
|
||||
tree ftype;
|
||||
if (TREE_CODE (field) != FIELD_DECL)
|
||||
continue;
|
||||
ftype = TREE_TYPE (field);
|
||||
if (!literal_type_p (ftype))
|
||||
{
|
||||
inform (0, " non-static data member %q+D has "
|
||||
"non-literal type", field);
|
||||
if (CLASS_TYPE_P (ftype))
|
||||
explain_non_literal_class (ftype);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Check the validity of the bases and members declared in T. Add any
|
||||
implicitly-generated functions (like copy-constructors and
|
||||
assignment operators). Compute various flag bits (like
|
||||
|
|
|
@ -4816,6 +4816,7 @@ extern bool type_has_virtual_destructor (tree);
|
|||
extern bool type_has_move_constructor (tree);
|
||||
extern bool type_has_move_assign (tree);
|
||||
extern bool type_build_ctor_call (tree);
|
||||
extern void explain_non_literal_class (tree);
|
||||
extern void defaulted_late_check (tree);
|
||||
extern bool defaultable_fn_check (tree);
|
||||
extern void fixup_type_variants (tree);
|
||||
|
@ -5094,6 +5095,7 @@ extern void finish_thunk (tree);
|
|||
extern void use_thunk (tree, bool);
|
||||
extern bool trivial_fn_p (tree);
|
||||
extern bool maybe_explain_implicit_delete (tree);
|
||||
extern void explain_implicit_non_constexpr (tree);
|
||||
extern void synthesize_method (tree);
|
||||
extern tree lazily_declare_fn (special_function_kind,
|
||||
tree);
|
||||
|
@ -5364,6 +5366,7 @@ extern tree maybe_constant_value (tree);
|
|||
extern tree maybe_constant_init (tree);
|
||||
extern bool is_sub_constant_expr (tree);
|
||||
extern bool reduced_constant_expression_p (tree);
|
||||
extern void explain_invalid_constexpr_fn (tree);
|
||||
extern VEC(tree,heap)* cx_error_context (void);
|
||||
|
||||
enum {
|
||||
|
|
|
@ -958,7 +958,15 @@ process_subob_fn (tree fn, bool move_p, tree *spec_p, bool *trivial_p,
|
|||
&& !DECL_TEMPLATE_INSTANTIATED (fn))
|
||||
instantiate_decl (fn, /*defer_ok*/false, /*expl_class*/false);
|
||||
if (!DECL_DECLARED_CONSTEXPR_P (fn))
|
||||
*constexpr_p = false;
|
||||
{
|
||||
*constexpr_p = false;
|
||||
if (msg)
|
||||
{
|
||||
inform (0, "defaulted constructor calls non-constexpr "
|
||||
"%q+D", fn);
|
||||
explain_invalid_constexpr_fn (fn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
|
@ -1037,7 +1045,12 @@ walk_field_subobs (tree fields, tree fnname, special_function_kind sfk,
|
|||
/* FIXME will need adjustment for non-static data member
|
||||
initializers. */
|
||||
if (constexpr_p && !CLASS_TYPE_P (mem_type))
|
||||
*constexpr_p = false;
|
||||
{
|
||||
*constexpr_p = false;
|
||||
if (msg)
|
||||
inform (0, "defaulted default constructor does not "
|
||||
"initialize %q+#D", field);
|
||||
}
|
||||
}
|
||||
|
||||
if (!CLASS_TYPE_P (mem_type))
|
||||
|
@ -1071,8 +1084,9 @@ walk_field_subobs (tree fields, tree fnname, special_function_kind sfk,
|
|||
/* The caller wants to generate an implicit declaration of SFK for CTYPE
|
||||
which is const if relevant and CONST_P is set. If spec_p, trivial_p and
|
||||
deleted_p are non-null, set their referent appropriately. If diag is
|
||||
true, we're being called from maybe_explain_implicit_delete to give
|
||||
errors. */
|
||||
true, we're either being called from maybe_explain_implicit_delete to
|
||||
give errors, or if constexpr_p is non-null, from
|
||||
explain_invalid_constexpr_fn. */
|
||||
|
||||
static void
|
||||
synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p,
|
||||
|
@ -1175,6 +1189,7 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p,
|
|||
resolution, so a constructor can be trivial even if it would otherwise
|
||||
call a non-trivial constructor. */
|
||||
if (expected_trivial
|
||||
&& !diag
|
||||
&& (!copy_arg_p || cxx_dialect < cxx0x))
|
||||
{
|
||||
if (constexpr_p && sfk == sfk_constructor)
|
||||
|
@ -1366,6 +1381,20 @@ maybe_explain_implicit_delete (tree decl)
|
|||
return false;
|
||||
}
|
||||
|
||||
/* DECL is a defaulted function which was declared constexpr. Explain why
|
||||
it can't be constexpr. */
|
||||
|
||||
void
|
||||
explain_implicit_non_constexpr (tree decl)
|
||||
{
|
||||
tree parm_type = TREE_VALUE (FUNCTION_FIRST_USER_PARMTYPE (decl));
|
||||
bool const_p = CP_TYPE_CONST_P (non_reference (parm_type));
|
||||
bool dummy;
|
||||
synthesized_method_walk (DECL_CLASS_CONTEXT (decl),
|
||||
special_function_p (decl), const_p,
|
||||
NULL, NULL, NULL, &dummy, true);
|
||||
}
|
||||
|
||||
/* Implicitly declare the special function indicated by KIND, as a
|
||||
member of TYPE. For copy constructors and assignment operators,
|
||||
CONST_P indicates whether these functions should take a const
|
||||
|
@ -1581,7 +1610,12 @@ defaulted_late_check (tree fn)
|
|||
&& DECL_DECLARED_CONSTEXPR_P (fn))
|
||||
{
|
||||
if (!CLASSTYPE_TEMPLATE_INSTANTIATION (ctx))
|
||||
error ("%qD cannot be declared as constexpr", fn);
|
||||
{
|
||||
error ("explicitly defaulted function %q+D cannot be declared "
|
||||
"as constexpr because the implicit declaration is not "
|
||||
"constexpr:", fn);
|
||||
explain_implicit_non_constexpr (fn);
|
||||
}
|
||||
DECL_DECLARED_CONSTEXPR_P (fn) = false;
|
||||
}
|
||||
|
||||
|
|
|
@ -3538,6 +3538,17 @@ emit_associated_thunks (tree fn)
|
|||
}
|
||||
}
|
||||
|
||||
/* Returns true iff FUN is an instantiation of a constexpr function
|
||||
template. */
|
||||
|
||||
static inline bool
|
||||
is_instantiation_of_constexpr (tree fun)
|
||||
{
|
||||
return (DECL_TEMPLATE_INFO (fun)
|
||||
&& DECL_DECLARED_CONSTEXPR_P (DECL_TEMPLATE_RESULT
|
||||
(DECL_TI_TEMPLATE (fun))));
|
||||
}
|
||||
|
||||
/* Generate RTL for FN. */
|
||||
|
||||
bool
|
||||
|
@ -3567,7 +3578,10 @@ expand_or_defer_fn_1 (tree fn)
|
|||
/* We don't want to process FN again, so pretend we've written
|
||||
it out, even though we haven't. */
|
||||
TREE_ASM_WRITTEN (fn) = 1;
|
||||
DECL_SAVED_TREE (fn) = NULL_TREE;
|
||||
/* If this is an instantiation of a constexpr function, keep
|
||||
DECL_SAVED_TREE for explain_invalid_constexpr_fn. */
|
||||
if (!is_instantiation_of_constexpr (fn))
|
||||
DECL_SAVED_TREE (fn) = NULL_TREE;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -5299,6 +5313,7 @@ ensure_literal_type_for_constexpr_object (tree decl)
|
|||
{
|
||||
error ("the type %qT of constexpr variable %qD is not literal",
|
||||
type, decl);
|
||||
explain_non_literal_class (type);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
@ -5365,8 +5380,11 @@ is_valid_constexpr_fn (tree fun, bool complain)
|
|||
{
|
||||
ret = false;
|
||||
if (complain)
|
||||
error ("invalid type for parameter %d of constexpr "
|
||||
"function %q+#D", DECL_PARM_INDEX (parm), fun);
|
||||
{
|
||||
error ("invalid type for parameter %d of constexpr "
|
||||
"function %q+#D", DECL_PARM_INDEX (parm), fun);
|
||||
explain_non_literal_class (TREE_TYPE (parm));
|
||||
}
|
||||
}
|
||||
|
||||
if (!DECL_CONSTRUCTOR_P (fun))
|
||||
|
@ -5376,8 +5394,11 @@ is_valid_constexpr_fn (tree fun, bool complain)
|
|||
{
|
||||
ret = false;
|
||||
if (complain)
|
||||
error ("invalid return type %qT of constexpr function %q+D",
|
||||
rettype, fun);
|
||||
{
|
||||
error ("invalid return type %qT of constexpr function %q+D",
|
||||
rettype, fun);
|
||||
explain_non_literal_class (rettype);
|
||||
}
|
||||
}
|
||||
|
||||
/* Check this again here for cxx_eval_call_expression. */
|
||||
|
@ -5386,7 +5407,11 @@ is_valid_constexpr_fn (tree fun, bool complain)
|
|||
{
|
||||
ret = false;
|
||||
if (complain)
|
||||
error ("enclosing class of %q+#D is not a literal type", fun);
|
||||
{
|
||||
error ("enclosing class of constexpr non-static member "
|
||||
"function %q+#D is not a literal type", fun);
|
||||
explain_non_literal_class (DECL_CONTEXT (fun));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5640,18 +5665,13 @@ constexpr_fn_retval (tree body)
|
|||
}
|
||||
}
|
||||
|
||||
/* We are processing the definition of the constexpr function FUN.
|
||||
Check that its BODY fulfills the propriate requirements and
|
||||
enter it in the constexpr function definition table.
|
||||
For constructor BODY is actually the TREE_LIST of the
|
||||
member-initializer list. */
|
||||
/* Subroutine of register_constexpr_fundef. BODY is the DECL_SAVED_TREE of
|
||||
FUN; do the necessary transformations to turn it into a single expression
|
||||
that we can store in the hash table. */
|
||||
|
||||
tree
|
||||
register_constexpr_fundef (tree fun, tree body)
|
||||
static tree
|
||||
massage_constexpr_body (tree fun, tree body)
|
||||
{
|
||||
constexpr_fundef entry;
|
||||
constexpr_fundef **slot;
|
||||
|
||||
if (DECL_CONSTRUCTOR_P (fun))
|
||||
body = build_constexpr_constructor_member_initializers
|
||||
(DECL_CONTEXT (fun), body);
|
||||
|
@ -5666,12 +5686,28 @@ register_constexpr_fundef (tree fun, tree body)
|
|||
if (TREE_CODE (body) == CLEANUP_POINT_EXPR)
|
||||
body = TREE_OPERAND (body, 0);
|
||||
body = constexpr_fn_retval (body);
|
||||
if (body == NULL_TREE || body == error_mark_node)
|
||||
{
|
||||
error ("body of constexpr function %qD not a return-statement", fun);
|
||||
DECL_DECLARED_CONSTEXPR_P (fun) = false;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return body;
|
||||
}
|
||||
|
||||
/* We are processing the definition of the constexpr function FUN.
|
||||
Check that its BODY fulfills the propriate requirements and
|
||||
enter it in the constexpr function definition table.
|
||||
For constructor BODY is actually the TREE_LIST of the
|
||||
member-initializer list. */
|
||||
|
||||
tree
|
||||
register_constexpr_fundef (tree fun, tree body)
|
||||
{
|
||||
constexpr_fundef entry;
|
||||
constexpr_fundef **slot;
|
||||
|
||||
body = massage_constexpr_body (fun, body);
|
||||
if (body == NULL_TREE || body == error_mark_node)
|
||||
{
|
||||
error ("body of constexpr function %qD not a return-statement", fun);
|
||||
DECL_DECLARED_CONSTEXPR_P (fun) = false;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!potential_rvalue_constant_expression (body))
|
||||
|
@ -5700,6 +5736,44 @@ register_constexpr_fundef (tree fun, tree body)
|
|||
return fun;
|
||||
}
|
||||
|
||||
/* FUN is a non-constexpr function called in a context that requires a
|
||||
constant expression. If it comes from a constexpr template, explain why
|
||||
the instantiation isn't constexpr. */
|
||||
|
||||
void
|
||||
explain_invalid_constexpr_fn (tree fun)
|
||||
{
|
||||
static struct pointer_set_t *diagnosed;
|
||||
tree body;
|
||||
location_t save_loc;
|
||||
/* Only diagnose instantiations of constexpr templates. */
|
||||
if (!is_instantiation_of_constexpr (fun))
|
||||
return;
|
||||
if (diagnosed == NULL)
|
||||
diagnosed = pointer_set_create ();
|
||||
if (pointer_set_insert (diagnosed, fun) != 0)
|
||||
/* Already explained. */
|
||||
return;
|
||||
|
||||
save_loc = input_location;
|
||||
input_location = DECL_SOURCE_LOCATION (fun);
|
||||
inform (0, "%q+D is not constexpr because it does not satisfy the "
|
||||
"requirements:", fun);
|
||||
/* First check the declaration. */
|
||||
if (is_valid_constexpr_fn (fun, true))
|
||||
{
|
||||
/* Then if it's OK, the body. */
|
||||
if (DECL_DEFAULTED_FN (fun))
|
||||
explain_implicit_non_constexpr (fun);
|
||||
else
|
||||
{
|
||||
body = massage_constexpr_body (fun, DECL_SAVED_TREE (fun));
|
||||
require_potential_rvalue_constant_expression (body);
|
||||
}
|
||||
}
|
||||
input_location = save_loc;
|
||||
}
|
||||
|
||||
/* Objects of this type represent calls to constexpr functions
|
||||
along with the bindings of parameters to their arguments, for
|
||||
the purpose of compile time evaluation. */
|
||||
|
@ -6005,7 +6079,7 @@ cxx_eval_call_expression (const constexpr_call *old_call, tree t,
|
|||
}
|
||||
if (TREE_CODE (fun) != FUNCTION_DECL)
|
||||
{
|
||||
if (!allow_non_constant)
|
||||
if (!allow_non_constant && !*non_constant_p)
|
||||
error_at (loc, "expression %qE does not designate a constexpr "
|
||||
"function", fun);
|
||||
*non_constant_p = true;
|
||||
|
@ -6020,11 +6094,8 @@ cxx_eval_call_expression (const constexpr_call *old_call, tree t,
|
|||
{
|
||||
if (!allow_non_constant)
|
||||
{
|
||||
error_at (loc, "%qD is not a constexpr function", fun);
|
||||
if (DECL_TEMPLATE_INFO (fun)
|
||||
&& DECL_DECLARED_CONSTEXPR_P (DECL_TEMPLATE_RESULT
|
||||
(DECL_TI_TEMPLATE (fun))))
|
||||
is_valid_constexpr_fn (fun, true);
|
||||
error_at (loc, "call to non-constexpr function %qD", fun);
|
||||
explain_invalid_constexpr_fn (fun);
|
||||
}
|
||||
*non_constant_p = true;
|
||||
return t;
|
||||
|
@ -7023,8 +7094,11 @@ cxx_eval_constant_expression (const constexpr_call *call, tree t,
|
|||
if (!literal_type_p (TREE_TYPE (t)))
|
||||
{
|
||||
if (!allow_non_constant)
|
||||
error ("temporary of non-literal type %qT in a "
|
||||
"constant expression", TREE_TYPE (t));
|
||||
{
|
||||
error ("temporary of non-literal type %qT in a "
|
||||
"constant expression", TREE_TYPE (t));
|
||||
explain_non_literal_class (TREE_TYPE (t));
|
||||
}
|
||||
*non_constant_p = true;
|
||||
break;
|
||||
}
|
||||
|
@ -7574,7 +7648,11 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
|
|||
&& !morally_constexpr_builtin_function_p (fun))
|
||||
{
|
||||
if (flags & tf_error)
|
||||
error ("%qD is not %<constexpr%>", fun);
|
||||
{
|
||||
error_at (EXPR_LOC_OR_HERE (t),
|
||||
"call to non-constexpr function %qD", fun);
|
||||
explain_invalid_constexpr_fn (fun);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/* A call to a non-static member function takes the address
|
||||
|
@ -7588,12 +7666,7 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
|
|||
if (is_this_parameter (x))
|
||||
/* OK. */;
|
||||
else if (!potential_constant_expression_1 (x, rval, flags))
|
||||
{
|
||||
if (flags & tf_error)
|
||||
error ("object argument is not a potential "
|
||||
"constant expression");
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
i = 1;
|
||||
}
|
||||
}
|
||||
|
@ -7609,22 +7682,13 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
|
|||
if (potential_constant_expression_1 (fun, rval, flags))
|
||||
/* Might end up being a constant function pointer. */;
|
||||
else
|
||||
{
|
||||
if (flags & tf_error)
|
||||
error ("%qE is not a function name", fun);
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
for (; i < nargs; ++i)
|
||||
{
|
||||
tree x = get_nth_callarg (t, i);
|
||||
if (!potential_constant_expression_1 (x, rval, flags))
|
||||
{
|
||||
if (flags & tf_error)
|
||||
error ("argument in position %qP is not a "
|
||||
"potential constant expression", i);
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -7853,8 +7917,11 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
|
|||
if (!literal_type_p (TREE_TYPE (t)))
|
||||
{
|
||||
if (flags & tf_error)
|
||||
error ("temporary of non-literal type %qT in a "
|
||||
"constant expression", TREE_TYPE (t));
|
||||
{
|
||||
error ("temporary of non-literal type %qT in a "
|
||||
"constant expression", TREE_TYPE (t));
|
||||
explain_non_literal_class (TREE_TYPE (t));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
case INIT_EXPR:
|
||||
|
|
|
@ -1,3 +1,12 @@
|
|||
2011-06-29 Jason Merrill <jason@redhat.com>
|
||||
|
||||
PR c++/45923
|
||||
* g++.dg/cpp0x/constexpr-diag3.C: New.
|
||||
* g++.dg/cpp0x/constexpr-diag1.C: Adjust error message.
|
||||
* g++.dg/cpp0x/constexpr-ex1.C: Adjust error message.
|
||||
* g++.dg/cpp0x/constexpr-friend.C: Adjust error message.
|
||||
* g++.dg/cpp0x/constexpr-incomplete2.C: Adjust error message.
|
||||
|
||||
2011-06-29 Jason Merrill <jason@redhat.com>
|
||||
|
||||
* g++.dg/cpp0x/constexpr-is_literal.C: Adjust.
|
||||
|
|
|
@ -13,7 +13,7 @@ struct B { B(); operator int(); };
|
|||
constexpr A<int> ai = { 42 };
|
||||
constexpr int i = ai.f();
|
||||
|
||||
constexpr int b = A<B>().f(); // { dg-error "not a constexpr function" }
|
||||
constexpr int b = A<B>().f(); // { dg-error "non-constexpr function" }
|
||||
|
||||
template <class T>
|
||||
constexpr int f (T t) { return 42; } // { dg-error "parameter" }
|
||||
|
|
54
gcc/testsuite/g++.dg/cpp0x/constexpr-diag3.C
Normal file
54
gcc/testsuite/g++.dg/cpp0x/constexpr-diag3.C
Normal file
|
@ -0,0 +1,54 @@
|
|||
// PR c++/45923
|
||||
// { dg-options -std=c++0x }
|
||||
|
||||
int f(int);
|
||||
|
||||
template <class T>
|
||||
constexpr T g(T t) { return f(t); } // { dg-error "f.int" }
|
||||
|
||||
int main()
|
||||
{
|
||||
constexpr int i = g(1); // { dg-error "g.T" }
|
||||
}
|
||||
|
||||
// --------------------
|
||||
|
||||
struct complex // { dg-message "no constexpr constructor" }
|
||||
{
|
||||
complex(double r, double i) : re(r), im(i) { }
|
||||
constexpr double real() { return re; } // { dg-error "not a literal type" }
|
||||
double imag() const { return im; }
|
||||
|
||||
private:
|
||||
double re;
|
||||
double im;
|
||||
};
|
||||
|
||||
constexpr complex co1(0, 1); // { dg-error "not literal" }
|
||||
constexpr double dd2 = co1.real(); // { dg-error "non-constexpr function" }
|
||||
|
||||
// --------------------
|
||||
|
||||
struct base // { dg-message "no constexpr constructor" }
|
||||
{
|
||||
int _M_i;
|
||||
base() : _M_i(5) { }
|
||||
};
|
||||
|
||||
struct derived : public base // { dg-message "base class" }
|
||||
{
|
||||
constexpr derived(): base() { } // { dg-error "non-constexpr function" }
|
||||
};
|
||||
|
||||
constexpr derived obj; // { dg-error "not literal" }
|
||||
|
||||
// --------------------
|
||||
|
||||
struct Def
|
||||
{
|
||||
int _M_i; // { dg-message "does not initialize" }
|
||||
|
||||
constexpr Def() = default; // { dg-error "implicit declaration is not constexpr" }
|
||||
};
|
||||
|
||||
constexpr Def defobj; // { dg-error "uninitialized" }
|
|
@ -88,7 +88,7 @@ struct resource {
|
|||
}
|
||||
};
|
||||
constexpr resource f(resource d)
|
||||
{ return d; } // { dg-error "not .constexpr" }
|
||||
{ return d; } // { dg-error "non-constexpr" }
|
||||
constexpr resource d = f(9); // { dg-error "resource" }
|
||||
|
||||
// 4.4 floating-point constant expressions
|
||||
|
|
|
@ -19,5 +19,5 @@ struct C
|
|||
|
||||
constexpr int i = f(C<int>());
|
||||
constexpr int j = C<int>().m(C<int>());
|
||||
constexpr int k = C<double>().m(A()); // { dg-error "not a constexpr function" }
|
||||
constexpr int l = g(C<double>(),A()); // { dg-error "not a constexpr function" }
|
||||
constexpr int k = C<double>().m(A()); // { dg-error "non-constexpr function" }
|
||||
constexpr int l = g(C<double>(),A()); // { dg-error "non-constexpr function" }
|
||||
|
|
|
@ -28,4 +28,4 @@ struct D
|
|||
C<D> c;
|
||||
};
|
||||
|
||||
constexpr D d {}; // { dg-error "not a constexpr function" }
|
||||
constexpr D d {}; // { dg-error "non-constexpr function" }
|
||||
|
|
Loading…
Add table
Reference in a new issue