aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2016-11-10 16:42:36 -0500
committerJason Merrill <jason@gcc.gnu.org>2016-11-10 16:42:36 -0500
commitf065303fcf9aa29bf376cf9db985b81d338d7709 (patch)
tree22f95d301fd585185ceb5330742ed82e7eb9e125 /gcc
parent28d1bf44643294ccac3c609104ad06b567b44149 (diff)
downloadgcc-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/ChangeLog12
-rw-r--r--gcc/cp/constexpr.c3
-rw-r--r--gcc/cp/cp-tree.h4
-rw-r--r--gcc/cp/decl.c4
-rw-r--r--gcc/cp/decl2.c9
-rw-r--r--gcc/cp/pt.c7
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/auto-fn33.C27
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();
+}