* 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
+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
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. */
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. */
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);
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");
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
/* 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));
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. */
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
--- /dev/null
+// 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();
+}