PR c++/77337 - auto return and lambda

* pt.c (tsubst_friend_function): Don't set DECL_INITIAL.
	(instantiate_decl): It's OK to defer a constexpr function.
	* cp-tree.h (DECL_FRIEND_PSEUDO_TEMPLATE_INSTANTIATION): Check
	DECL_LANG_SPECIFIC.
	* decl2.c (decl_defined_p): Use it.  No longer static.
	* decl.c (redeclaration_error_message): Use decl_defined_p.
	* constexpr.c (cxx_eval_call_expression): Set input_location around
	call to instantiate_decl.

From-SVN: r242056
This commit is contained in:
Jason Merrill 2016-11-10 16:42:36 -05:00 committed by Jason Merrill
parent 28d1bf4464
commit f065303fcf
7 changed files with 54 additions and 12 deletions

View file

@ -1,3 +1,15 @@
2016-11-10 Jason Merrill <jason@redhat.com>
PR c++/77337
* pt.c (tsubst_friend_function): Don't set DECL_INITIAL.
(instantiate_decl): It's OK to defer a constexpr function.
* cp-tree.h (DECL_FRIEND_PSEUDO_TEMPLATE_INSTANTIATION): Check
DECL_LANG_SPECIFIC.
* decl2.c (decl_defined_p): Use it. No longer static.
* decl.c (redeclaration_error_message): Use decl_defined_p.
* constexpr.c (cxx_eval_call_expression): Set input_location around
call to instantiate_decl.
2016-11-10 Jakub Jelinek <jakub@redhat.com>
* mangle.c (mangle_decl): Only emit -Wc++1z-compat warnings for

View file

@ -1464,9 +1464,12 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
if (!DECL_INITIAL (fun)
&& DECL_TEMPLOID_INSTANTIATION (fun))
{
location_t save_loc = input_location;
input_location = loc;
++function_depth;
instantiate_decl (fun, /*defer_ok*/false, /*expl_inst*/false);
--function_depth;
input_location = save_loc;
}
/* If in direct recursive call, optimize definition search. */

View file

@ -4380,7 +4380,8 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter)
instantiated will not be a DECL_TEMPLATE_INSTANTIATION, but will be
a DECL_FRIEND_PSEUDO_TEMPLATE_INSTANTIATION. */
#define DECL_FRIEND_PSEUDO_TEMPLATE_INSTANTIATION(DECL) \
(DECL_TEMPLATE_INFO (DECL) && !DECL_USE_TEMPLATE (DECL))
(DECL_LANG_SPECIFIC (DECL) && DECL_TEMPLATE_INFO (DECL) \
&& !DECL_USE_TEMPLATE (DECL))
/* Nonzero if DECL is a function generated from a function 'temploid',
i.e. template, member of class template, or dependent friend. */
@ -5895,6 +5896,7 @@ extern void import_export_decl (tree);
extern tree build_cleanup (tree);
extern tree build_offset_ref_call_from_tree (tree, vec<tree, va_gc> **,
tsubst_flags_t);
extern bool decl_defined_p (tree);
extern bool decl_constant_var_p (tree);
extern bool decl_maybe_constant_var_p (tree);
extern void no_linkage_error (tree);

View file

@ -2778,8 +2778,8 @@ redeclaration_error_message (tree newdecl, tree olddecl)
warn_extern_redeclared_static. */
/* Defining the same name twice is no good. */
if (DECL_INITIAL (olddecl) != NULL_TREE
&& DECL_INITIAL (newdecl) != NULL_TREE)
if (decl_defined_p (olddecl)
&& decl_defined_p (newdecl))
{
if (DECL_NAME (olddecl) == NULL_TREE)
return G_("%q#D not declared in class");

View file

@ -80,7 +80,6 @@ static void import_export_class (tree);
static tree get_guard_bits (tree);
static void determine_visibility_from_class (tree, tree);
static bool determine_hidden_inline (tree);
static bool decl_defined_p (tree);
static void maybe_instantiate_decl (tree);
/* A list of static class variables. This is needed, because a
@ -4085,11 +4084,15 @@ collect_ada_namespace (tree namespc, const char *source_file)
/* Returns true iff there is a definition available for variable or
function DECL. */
static bool
bool
decl_defined_p (tree decl)
{
if (TREE_CODE (decl) == FUNCTION_DECL)
return (DECL_INITIAL (decl) != NULL_TREE);
return (DECL_INITIAL (decl) != NULL_TREE
/* A pending instantiation of a friend temploid is defined. */
|| (DECL_FRIEND_PSEUDO_TEMPLATE_INSTANTIATION (decl)
&& DECL_INITIAL (DECL_TEMPLATE_RESULT
(DECL_TI_TEMPLATE (decl)))));
else
{
gcc_assert (VAR_P (decl));

View file

@ -9383,10 +9383,6 @@ tsubst_friend_function (tree decl, tree args)
else
new_friend_result_template_info = NULL_TREE;
/* Make the init_value nonzero so pushdecl knows this is a defn. */
if (new_friend_is_defn)
DECL_INITIAL (new_friend) = error_mark_node;
/* Inside pushdecl_namespace_level, we will push into the
current namespace. However, the friend function should go
into the namespace of the template. */
@ -22086,8 +22082,7 @@ instantiate_decl (tree d, int defer_ok,
case that an expression refers to the value of the variable --
if the variable has a constant value the referring expression can
take advantage of that fact. */
if (VAR_P (d)
|| DECL_DECLARED_CONSTEXPR_P (d))
if (VAR_P (d))
defer_ok = 0;
/* Don't instantiate cloned functions. Instead, instantiate the

View file

@ -0,0 +1,27 @@
// PR c++/77337
// { dg-do compile { target c++14 } }
template<typename Functor>
struct fix_type {
Functor functor;
decltype(auto) operator()()
{ return functor(*this); }
};
template<typename Functor>
fix_type<Functor> fix(Functor functor)
{ return { functor }; }
int main()
{
auto zero = fix
([](auto& self) -> int // N.B. non-deduced, non-dependent return type
{
return 0;
self(); // error: use of 'decltype(auto) fix_type<Functor>::operator()() [with Functor = main()::<lambda(auto:1&)>]' before deduction of 'auto'
});
return zero();
}