diff mbox

C++ PATCH for C++17 class template argument deduction issues

Message ID CADzB+2n-CV1C8-APXZ4M0oqJc-iLu9YoO7SXZummxOCjWgwwQg@mail.gmail.com
State New
Headers show

Commit Message

Jason Merrill March 6, 2017, 2:44 p.m. UTC
On Thu, Mar 2, 2017 at 3:26 PM, Jason Merrill <jason@redhat.com> wrote:
> On Wed, Mar 1, 2017 at 3:58 PM, Jason Merrill <jason@redhat.com> wrote:
>> On Tue, Feb 28, 2017 at 1:56 PM, Jason Merrill <jason@redhat.com> wrote:
>>> This patch implements some proposed resolutions to open issues with
>>> C++17 class template argument deduction.
>
> This patch handles the issues of references to members of the class
> template differently, by also allowing explicit guides to refer to
> them:

The committee didn't like this direction, so I'm reverting it.
commit 522ce181ad77238b7e314377bf21f45579e7b6e8
Author: Jason Merrill <jason@redhat.com>
Date:   Sat Mar 4 13:18:47 2017 -1000

            Revert "Allow deduction guides to look into primary template."
    
            * cp-tree.h, parser.c, pt.c, search.c: Revert.
diff mbox

Patch

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 7583672..68f2722 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -1272,7 +1272,6 @@  struct GTY(()) saved_scope {
   vec<tree, va_gc> *lang_base;
   tree lang_name;
   tree template_parms;
-  tree deduction_guide_type;
   cp_binding_level *x_previous_class_level;
   tree x_saved_tree;
 
@@ -5423,9 +5422,6 @@  struct cp_decl_specifier_seq {
   BOOL_BITFIELD gnu_thread_keyword_p : 1;
   /* True iff the type is a decltype.  */
   BOOL_BITFIELD decltype_p : 1;
-  /* True iff the declaration declares a constructor or C++17 deduction
-     guide.  */
-  BOOL_BITFIELD constructor_p : 1;
 };
 
 /* The various kinds of declarators.  */
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index fbe864f..e684870 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -13313,8 +13313,6 @@  cp_parser_decl_specifier_seq (cp_parser* parser,
 	   && constructor_possible_p
 	   && (cp_parser_constructor_declarator_p
 	       (parser, decl_spec_seq_has_spec_p (decl_specs, ds_friend))));
-      if (constructor_p)
-	decl_specs->constructor_p = true;
 
       /* If we don't have a DECL_SPEC yet, then we must be looking at
 	 a type-specifier.  */
@@ -19012,7 +19010,7 @@  cp_parser_init_declarator (cp_parser* parser,
   enum cpp_ttype initialization_kind;
   bool is_direct_init = false;
   bool is_non_constant_init;
-  int ctor_dtor_or_conv_p = decl_specifiers->constructor_p ? -1 : 0;
+  int ctor_dtor_or_conv_p;
   bool friend_p = cp_parser_friend_p (decl_specifiers);
   tree pushed_scope = NULL_TREE;
   bool range_for_decl_p = false;
@@ -19050,9 +19048,6 @@  cp_parser_init_declarator (cp_parser* parser,
 
   parser->default_arg_ok_p = saved_default_arg_ok_p;
 
-  if (cxx_dialect >= cxx1z)
-    scope_chain->deduction_guide_type = NULL_TREE;
-
   /* If the DECLARATOR was erroneous, there's no need to go
      further.  */
   if (declarator == cp_error_declarator)
@@ -19100,6 +19095,25 @@  cp_parser_init_declarator (cp_parser* parser,
 
   if (function_declarator_p (declarator))
     {
+      /* Handle C++17 deduction guides.  */
+      if (!decl_specifiers->type
+	  && ctor_dtor_or_conv_p <= 0
+	  && cxx_dialect >= cxx1z)
+	{
+	  cp_declarator *id = get_id_declarator (declarator);
+	  tree name = id->u.id.unqualified_name;
+	  parser->scope = id->u.id.qualifying_scope;
+	  tree tmpl = cp_parser_lookup_name_simple (parser, name, id->id_loc);
+	  if (tmpl
+	      && (DECL_CLASS_TEMPLATE_P (tmpl)
+		  || DECL_TEMPLATE_TEMPLATE_PARM_P (tmpl)))
+	    {
+	      id->u.id.unqualified_name = dguide_name (tmpl);
+	      id->u.id.sfk = sfk_deduction_guide;
+	      ctor_dtor_or_conv_p = 1;
+	    }
+	}
+
       /* Check to see if the token indicates the start of a
 	 function-definition.  */
       if (cp_parser_token_starts_function_definition_p (token))
@@ -19418,10 +19432,8 @@  cp_parser_init_declarator (cp_parser* parser,
 
    If CTOR_DTOR_OR_CONV_P is not NULL, *CTOR_DTOR_OR_CONV_P is used to
    detect constructors, destructors, deduction guides, or conversion operators.
-   The caller should set it before the call, to -1 if parsing the
-   decl-specifier-seq determined that we're declaring a constructor or
-   deduction guide, or 0 otherwise.  This function sets it to -1 if the
-   declarator is a name, and +1 if it is a function. Usually you just want to
+   It is set to -1 if the declarator is a name, and +1 if it is a
+   function. Otherwise it is set to zero. Usually you just want to
    test for >0, but internally the negative value is used.
 
    (The reason for CTOR_DTOR_OR_CONV_P is that a declaration must have
@@ -19452,6 +19464,11 @@  cp_parser_declarator (cp_parser* parser,
   tree class_type;
   tree gnu_attributes = NULL_TREE, std_attributes = NULL_TREE;
 
+  /* Assume this is not a constructor, destructor, or type-conversion
+     operator.  */
+  if (ctor_dtor_or_conv_p)
+    *ctor_dtor_or_conv_p = 0;
+
   if (cp_parser_allow_gnu_extensions_p (parser))
     gnu_attributes = cp_parser_gnu_attributes_opt (parser);
 
@@ -19749,6 +19766,9 @@  cp_parser_direct_declarator (cp_parser* parser,
 	  /* Parse an array-declarator.  */
 	  tree bounds, attrs;
 
+	  if (ctor_dtor_or_conv_p)
+	    *ctor_dtor_or_conv_p = 0;
+
 	  first = false;
 	  parser->default_arg_ok_p = false;
 	  parser->in_declarator_p = true;
@@ -20003,34 +20023,6 @@  cp_parser_direct_declarator (cp_parser* parser,
 		      *ctor_dtor_or_conv_p = -1;
 		  }
 	      }
-
-	    if (cxx_dialect >= cxx1z
-		&& sfk == sfk_none
-		&& ctor_dtor_or_conv_p
-		&& *ctor_dtor_or_conv_p == -1)
-	      {
-		/* If *ctor_dtor_or_conv_p is set and we aren't declaring a
-		   constructor, we must be declaring a deduction guide.  */
-		tree tmpl;
-		if (qualifying_scope)
-		  tmpl = (lookup_qualified_name
-			  (qualifying_scope, unqualified_name,
-			   /*prefer_type*/false, /*complain*/true));
-		else
-		  tmpl = lookup_name (unqualified_name);
-		if (tmpl
-		    && (DECL_CLASS_TEMPLATE_P (tmpl)
-			|| DECL_TEMPLATE_TEMPLATE_PARM_P (tmpl)))
-		  {
-		    unqualified_name = dguide_name (tmpl);
-		    scope_chain->deduction_guide_type
-		      = TREE_TYPE (unqualified_name);
-		    sfk = sfk_deduction_guide;
-		  }
-		else
-		  gcc_checking_assert (false);
-	      }
-
 	    declarator = make_id_declarator (qualifying_scope,
 					     unqualified_name,
 					     sfk);
@@ -23259,7 +23251,7 @@  cp_parser_member_declaration (cp_parser* parser)
 	      cp_declarator *declarator;
 	      tree initializer;
 	      tree asm_specification;
-	      int ctor_dtor_or_conv_p = decl_specifiers.constructor_p ? -1 : 0;
+	      int ctor_dtor_or_conv_p;
 
 	      /* Parse the declarator.  */
 	      declarator
@@ -28342,7 +28334,7 @@  cp_parser_cache_defarg (cp_parser *parser, bool nsdmi)
 		     declarator.  */
 		  do
 		    {
-		      int ctor_dtor_or_conv_p = 0;
+		      int ctor_dtor_or_conv_p;
 		      cp_lexer_consume_token (parser->lexer);
 		      cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
 					    &ctor_dtor_or_conv_p,
@@ -29663,7 +29655,7 @@  cp_parser_objc_class_ivars (cp_parser* parser)
 	{
 	  tree width = NULL_TREE, attributes, first_attribute, decl;
 	  cp_declarator *declarator = NULL;
-	  int ctor_dtor_or_conv_p = 0;
+	  int ctor_dtor_or_conv_p;
 
 	  /* Check for a (possibly unnamed) bitfield declaration.  */
 	  token = cp_lexer_peek_token (parser->lexer);
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 13293eb..416f132 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -14641,6 +14641,15 @@  tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
 	     have to substitute this with one having context `D<int>'.  */
 
 	  tree context = tsubst (DECL_CONTEXT (t), args, complain, in_decl);
+	  if (dependent_scope_p (context))
+	    {
+	      /* When rewriting a constructor into a deduction guide, a
+		 non-dependent name can become dependent, so memtmpl<args>
+		 becomes context::template memtmpl<args>.  */
+	      tree type = tsubst (TREE_TYPE (t), args, complain, in_decl);
+	      return build_qualified_name (type, context, DECL_NAME (t),
+					   /*template*/true);
+	    }
 	  return lookup_field (context, DECL_NAME(t), 0, false);
 	}
       else
@@ -16624,6 +16633,14 @@  tsubst_copy_and_build (tree t,
 	if (targs == error_mark_node)
 	  return error_mark_node;
 
+	if (TREE_CODE (templ) == SCOPE_REF)
+	  {
+	    tree name = TREE_OPERAND (templ, 1);
+	    tree tid = lookup_template_function (name, targs);
+	    TREE_OPERAND (templ, 1) = tid;
+	    return templ;
+	  }
+
 	if (variable_template_p (templ))
 	  RETURN (lookup_and_finish_template_variable (templ, targs, complain));
 
@@ -23459,9 +23476,6 @@  bool
 dependent_scope_p (tree scope)
 {
   return (scope && TYPE_P (scope) && dependent_type_p (scope)
-	  && !(cxx_dialect >= cxx1z
-	       && scope_chain->deduction_guide_type
-	       && same_type_p (scope, scope_chain->deduction_guide_type))
 	  && !currently_open_class (scope));
 }
 
@@ -25012,7 +25026,6 @@  build_deduction_guide (tree ctor, tree outer_args, tsubst_flags_t complain)
       if (outer_args)
 	ctor = tsubst (ctor, outer_args, complain, ctor);
       type = DECL_CONTEXT (ctor);
-      scope_chain->deduction_guide_type = type;
       tree fn_tmpl;
       if (TREE_CODE (ctor) == TEMPLATE_DECL)
 	{
@@ -25105,7 +25118,6 @@  build_deduction_guide (tree ctor, tree outer_args, tsubst_flags_t complain)
 	  current_template_parms = save_parms;
 	  --processing_template_decl;
 	}
-      scope_chain->deduction_guide_type = NULL_TREE;
     }
 
   if (!memtmpl)
diff --git a/gcc/cp/search.c b/gcc/cp/search.c
index 6eb4124..09c1b4e 100644
--- a/gcc/cp/search.c
+++ b/gcc/cp/search.c
@@ -1279,13 +1279,6 @@  lookup_member (tree xbasetype, tree name, int protect, bool want_type,
     if (tree t = currently_open_class (type))
       type = t;
 
-  /* Declaration of a deduction guide can look inside the primary class
-     template; replace a compatible type with the real one.  */
-  if (cxx_dialect >= cxx1z
-      && scope_chain->deduction_guide_type
-      && same_type_p (type, scope_chain->deduction_guide_type))
-    type = scope_chain->deduction_guide_type;
-
   if (!basetype_path)
     basetype_path = TYPE_BINFO (type);
 
diff --git a/gcc/testsuite/g++.dg/cpp1z/class-deduction37.C b/gcc/testsuite/g++.dg/cpp1z/class-deduction37.C
deleted file mode 100644
index ee21d14..0000000
--- a/gcc/testsuite/g++.dg/cpp1z/class-deduction37.C
+++ /dev/null
@@ -1,16 +0,0 @@ 
-// { dg-options -std=c++1z }
-
-template <class T> struct A
-{
-  using value_t = T;
-  A(value_t);
-};
-
-template <class T>
-A(typename A<T>::value_t) -> A<double>;
-
-template <class,class> struct same;
-template <class T> struct same<T,T> {};
-
-A a(42);
-same<decltype(a),A<double>> s1;