diff options
author | Jason Merrill <jason@redhat.com> | 2016-11-10 16:42:36 -0500 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2016-11-10 16:42:36 -0500 |
commit | f065303fcf9aa29bf376cf9db985b81d338d7709 (patch) | |
tree | 22f95d301fd585185ceb5330742ed82e7eb9e125 /gcc | |
parent | 28d1bf44643294ccac3c609104ad06b567b44149 (diff) | |
download | gcc-f065303fcf9aa29bf376cf9db985b81d338d7709.zip gcc-f065303fcf9aa29bf376cf9db985b81d338d7709.tar.gz gcc-f065303fcf9aa29bf376cf9db985b81d338d7709.tar.bz2 |
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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/ChangeLog | 12 | ||||
-rw-r--r-- | gcc/cp/constexpr.c | 3 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 4 | ||||
-rw-r--r-- | gcc/cp/decl.c | 4 | ||||
-rw-r--r-- | gcc/cp/decl2.c | 9 | ||||
-rw-r--r-- | gcc/cp/pt.c | 7 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp1y/auto-fn33.C | 27 |
7 files changed, 54 insertions, 12 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index b19a236..678c44d 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -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 diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index 43457d2..f75f0b0 100644 --- a/gcc/cp/constexpr.c +++ b/gcc/cp/constexpr.c @@ -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. */ diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 9b5b5bc..8183775 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -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); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 4b18d4e..185c98b 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -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"); diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index e0fff1e..4ebc7dc 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -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)); diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index e8b6afd..d4855d5 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -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 diff --git a/gcc/testsuite/g++.dg/cpp1y/auto-fn33.C b/gcc/testsuite/g++.dg/cpp1y/auto-fn33.C new file mode 100644 index 0000000..cfd8498 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/auto-fn33.C @@ -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(); +} |