PR c++/77337 - auto return and lambda
authorJason Merrill <jason@redhat.com>
Thu, 10 Nov 2016 21:42:36 +0000 (16:42 -0500)
committerJason Merrill <jason@gcc.gnu.org>
Thu, 10 Nov 2016 21:42:36 +0000 (16:42 -0500)
* 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

gcc/cp/ChangeLog
gcc/cp/constexpr.c
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/decl2.c
gcc/cp/pt.c
gcc/testsuite/g++.dg/cpp1y/auto-fn33.C [new file with mode: 0644]

index b19a236f21597804eaf53eba112085257eb687af..678c44d5d40a2e79085337c4720a5caf8b88264b 100644 (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
index 43457d2463fc5c14cab11c56049c419eae39d82c..f75f0b039fa958635e914fafa903039fd7c6e8e0 100644 (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.  */
index 9b5b5bc9bdb8d5c90cac24c878aeea184cf4d0bf..8183775b49ef966457347b4db55f64ba2472973d 100644 (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);
index 4b18d4ea761e312e4ac1fd7147909ea417523e55..185c98bebb8d4ad1322cdbc6d346587d3b333e84 100644 (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");
index e0fff1e81c54e142243d40cdbc75d89ce91af0f8..4ebc7dca8d6467e55c2e644560059e8f72da3cff 100644 (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));
index e8b6afd13abcf78061fee86a7632ddddcbc0f867..d4855d5bc3525831f0ca42b99bba0553e4c97743 100644 (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
diff --git a/gcc/testsuite/g++.dg/cpp1y/auto-fn33.C b/gcc/testsuite/g++.dg/cpp1y/auto-fn33.C
new file mode 100644 (file)
index 0000000..cfd8498
--- /dev/null
@@ -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();
+}