This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: New C++ PATCH for c++/10200 et al


On 02/16/2016 07:49 PM, Jason Merrill wrote:
Clearly the DR 141 change is requiring much larger adjustments in the
rest of the compiler than I'm comfortable making at this point in the
GCC 6 schedule, so I'm backing out my earlier changes for 10200 and
69753 and replacing them with a more modest fix for 10200: Now we will
still find member function templates by unqualified lookup, we just
won't find namespace-scope function templates.  The earlier approach
will return in GCC 7 stage 1.

As promised. The prerequisite for the DR 141 change was fixing the C++11 handling of type-dependence of member access expressions, including calls. 14.6.2.2 says,

A class member access expression (5.2.5) is type-dependent if the expression refers to a member of the current instantiation and the type of the referenced member is dependent, or the class member access expression refers to a member of an unknown specialization. [ Note: In an expression of the form x.y or xp->y the type of the expression is usually the type of the member y of the class of x (or the class pointed to by xp). However, if x or xp refers to a dependent type that is not the current instantiation, the type of y is always dependent. If x or xp refers to a non-dependent type or refers to the current instantiation, the type of y is the type of the class member access expression. âend note ]

Previously we had been treating such expressions as type-dependent if the object-expression is type-dependent, even if its type is the current instantiation. Fixing this required a few changes in other areas that now have to deal with non-dependent member function calls within a template.

Tested x86_64-pc-linux-gnu, applying to trunk.

commit 92bfc5a7586b8d862951d2e1a94398a3ab19ef47
Author: Jason Merrill <jason@redhat.com>
Date:   Fri May 13 11:36:35 2016 -0400

    	Fix type-dependence and the current instantiation.
    
    	PR c++/10200
    	PR c++/69753
    	* pt.c (tsubst_decl): Use uses_template_parms.
    	(instantiate_template_1): Handle non-dependent calls in templates.
    	(value_dependent_expression_p): Handle BASELINK, FUNCTION_DECL.
    	(type_dependent_expression_p): Only consider innermost template	args.
    	(dependent_template_arg_p): Check enclosing class of a template here.
    	(dependent_template_p): Not here.
    	(type_dependent_object_expression_p): New.
    	* typeck.c (finish_class_member_access_expr): Use it.
    	* parser.c (cp_parser_postfix_expression): Use it.
    	(cp_parser_postfix_dot_deref_expression): Use it.  Use comptypes
    	to detect the current instantiation.
    	(cp_parser_lookup_name): Really implement DR 141.
    	* search.c (lookup_field_r): Prefer a dependent using-declaration.
    	(any_dependent_bases_p): Split out from...
    	* name-lookup.c (do_class_using_decl): ...here.
    	* call.c (build_new_method_call_1): Use it.
    	* semantics.c (finish_call_expr): 'this' doesn't make a call dependent.
    	* tree.c (non_static_member_function_p): Remove.
    	* typeck2.c (build_x_arrow): Use dependent_scope_p.

diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index a49bbb5..0b59c40 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -8407,6 +8407,9 @@ build_new_method_call_1 (tree instance, tree fns, vec<tree, va_gc> **args,
 		     we know we really need it.  */
 		  cand->first_arg = instance;
 		}
+	      else if (any_dependent_bases_p ())
+		/* We can't tell until instantiation time whether we can use
+		   *this as the implicit object argument.  */;
 	      else
 		{
 		  if (complain & tf_error)
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 556c256..ad21cdf 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -6125,6 +6125,7 @@ extern bool any_dependent_template_arguments_p  (const_tree);
 extern bool dependent_template_p		(tree);
 extern bool dependent_template_id_p		(tree, tree);
 extern bool type_dependent_expression_p		(tree);
+extern bool type_dependent_object_expression_p	(tree);
 extern bool any_type_dependent_arguments_p      (const vec<tree, va_gc> *);
 extern bool any_type_dependent_elements_p       (const_tree);
 extern bool type_dependent_expression_p_push	(tree);
@@ -6233,6 +6234,7 @@ extern tree adjust_result_of_qualified_name_lookup
 extern tree copied_binfo			(tree, tree);
 extern tree original_binfo			(tree, tree);
 extern int shared_member_p			(tree);
+extern bool any_dependent_bases_p (tree = current_nonlambda_class_type ());
 
 /* The representation of a deferred access check.  */
 
@@ -6525,7 +6527,6 @@ extern tree get_first_fn			(tree);
 extern tree ovl_cons				(tree, tree);
 extern tree build_overload			(tree, tree);
 extern tree ovl_scope				(tree);
-extern bool non_static_member_function_p        (tree);
 extern const char *cxx_printable_name		(tree, int);
 extern const char *cxx_printable_name_translate	(tree, int);
 extern tree build_exception_variant		(tree, tree);
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index 86d260c..d32a153 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -3333,8 +3333,6 @@ do_class_using_decl (tree scope, tree name)
   /* True if any of the bases of CURRENT_CLASS_TYPE are dependent.  */
   bool bases_dependent_p;
   tree binfo;
-  tree base_binfo;
-  int i;
 
   if (name == error_mark_node)
     return NULL_TREE;
@@ -3371,16 +3369,7 @@ do_class_using_decl (tree scope, tree name)
 		      || (IDENTIFIER_TYPENAME_P (name)
 			  && dependent_type_p (TREE_TYPE (name))));
 
-  bases_dependent_p = false;
-  if (processing_template_decl)
-    for (binfo = TYPE_BINFO (current_class_type), i = 0;
-	 BINFO_BASE_ITERATE (binfo, i, base_binfo);
-	 i++)
-      if (dependent_type_p (TREE_TYPE (base_binfo)))
-	{
-	  bases_dependent_p = true;
-	  break;
-	}
+  bases_dependent_p = any_dependent_bases_p ();
 
   decl = NULL_TREE;
 
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 7030740..539f165 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -6851,7 +6851,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
 		tree fn = TREE_OPERAND (postfix_expression, 1);
 
 		if (processing_template_decl
-		    && (type_dependent_expression_p (instance)
+		    && (type_dependent_object_expression_p (instance)
 			|| (!BASELINK_P (fn)
 			    && TREE_CODE (fn) != FIELD_DECL)
 			|| type_dependent_expression_p (fn)
@@ -7186,8 +7186,9 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser,
   if (token_type == CPP_DEREF)
     postfix_expression = build_x_arrow (location, postfix_expression,
 					tf_warning_or_error);
-  /* Check to see whether or not the expression is type-dependent.  */
-  dependent_p = type_dependent_expression_p (postfix_expression);
+  /* Check to see whether or not the expression is type-dependent and
+     not the current instantiation.  */
+  dependent_p = type_dependent_object_expression_p (postfix_expression);
   /* The identifier following the `->' or `.' is not qualified.  */
   parser->scope = NULL_TREE;
   parser->qualifying_scope = NULL_TREE;
@@ -7211,7 +7212,10 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser,
 	 required to be of complete type for purposes of class member
 	 access (5.2.5) outside the member function body.  */
       if (postfix_expression != current_class_ref
-	  && !(processing_template_decl && scope == current_class_type))
+	  && !(processing_template_decl
+	       && current_class_type
+	       && (same_type_ignoring_top_level_qualifiers_p
+		   (scope, current_class_type))))
 	scope = complete_type_or_else (scope, postfix_expression);
       /* Let the name lookup machinery know that we are processing a
 	 class member access expression.  */
@@ -24806,24 +24810,11 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
 	decl = NULL_TREE;
 
       if (!decl)
-	{
-	  /* Look it up in the enclosing context.  */
-	  decl = lookup_name_real (name, tag_type != none_type,
-				   /*nonclass=*/0,
-				   /*block_p=*/true, is_namespace, 0);
-	  /* DR 141 says when looking for a template-name after -> or ., only
-	     consider class templates.  We need to fix our handling of
-	     dependent expressions to implement that properly, but for now
-	     let's ignore namespace-scope function templates.  */
-	  if (decl && is_template && !DECL_TYPE_TEMPLATE_P (decl))
-	    {
-	      tree d = decl;
-	      if (is_overloaded_fn (d))
-		d = get_first_fn (d);
-	      if (DECL_P (d) && !DECL_CLASS_SCOPE_P (d))
-		decl = NULL_TREE;
-	    }
-	}
+	/* Look it up in the enclosing context.  DR 141: When looking for a
+	   template-name after -> or ., only consider class templates.  */
+	decl = lookup_name_real (name, tag_type != none_type || is_template,
+				 /*nonclass=*/0,
+				 /*block_p=*/true, is_namespace, 0);
       if (object_type == unknown_type_node)
 	/* The object is type-dependent, so we can't look anything up; we used
 	   this to get the DR 141 behavior.  */
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 1289d64..65bfd42 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -11700,16 +11700,9 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
 	if (TREE_CODE (DECL_TI_TEMPLATE (t)) == TEMPLATE_DECL)
 	  {
 	    tree spec;
-	    bool dependent_p;
 
-	    /* If T is not dependent, just return it.  We have to
-	       increment PROCESSING_TEMPLATE_DECL because
-	       value_dependent_expression_p assumes that nothing is
-	       dependent when PROCESSING_TEMPLATE_DECL is zero.  */
-	    ++processing_template_decl;
-	    dependent_p = value_dependent_expression_p (t);
-	    --processing_template_decl;
-	    if (!dependent_p)
+	    /* If T is not dependent, just return it.  */
+	    if (!uses_template_parms (DECL_TI_ARGS (t)))
 	      RETURN (t);
 
 	    /* Calculate the most general template of which R is a
@@ -17328,12 +17321,14 @@ instantiate_template_1 (tree tmpl, tree orig_args, tsubst_flags_t complain)
 
   /* Check to see if we already have this specialization.  */
   gen_tmpl = most_general_template (tmpl);
-  if (tmpl != gen_tmpl)
-    /* The TMPL is a partial instantiation.  To get a full set of
-       arguments we must add the arguments used to perform the
-       partial instantiation.  */
-    targ_ptr = add_outermost_template_args (DECL_TI_ARGS (tmpl),
-					    targ_ptr);
+  if (TMPL_ARGS_DEPTH (targ_ptr)
+      < TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (gen_tmpl)))
+    /* targ_ptr only has the innermost template args, so add the outer ones
+       from tmpl, which could be either a partial instantiation or gen_tmpl (in
+       the case of a non-dependent call within a template definition).  */
+    targ_ptr = (add_outermost_template_args
+		(DECL_TI_ARGS (DECL_TEMPLATE_RESULT (tmpl)),
+		 targ_ptr));
 
   /* It would be nice to avoid hashing here and then again in tsubst_decl,
      but it doesn't seem to be on the hot path.  */
@@ -22653,6 +22648,22 @@ value_dependent_expression_p (tree expression)
 
   switch (TREE_CODE (expression))
     {
+    case BASELINK:
+      /* A member function of a dependent class has dependent template
+	 arguments from its class.  */
+      if (dependent_type_p (BINFO_TYPE (BASELINK_BINFO (expression))))
+	return true;
+      return value_dependent_expression_p (BASELINK_FUNCTIONS (expression));
+
+    case FUNCTION_DECL:
+      /* A function template specialization is value-dependent if it has any
+	 dependent template arguments, since that means it cannot be
+	 instantiated for constexpr evaluation.  */
+      if (DECL_LANG_SPECIFIC (expression)
+	  && DECL_TEMPLATE_INFO (expression))
+	return any_dependent_template_arguments_p (DECL_TI_ARGS (expression));
+      break;
+
     case IDENTIFIER_NODE:
       /* A name that has not been looked up -- must be dependent.  */
       return true;
@@ -22797,10 +22808,10 @@ value_dependent_expression_p (tree expression)
 
     case CALL_EXPR:
       {
+	if (value_dependent_expression_p (CALL_EXPR_FN (expression)))
+	  return true;
 	tree fn = get_callee_fndecl (expression);
 	int i, nargs;
-	if (!fn && value_dependent_expression_p (CALL_EXPR_FN (expression)))
-	  return true;
 	nargs = call_expr_nargs (expression);
 	for (i = 0; i < nargs; ++i)
 	  {
@@ -22964,13 +22975,6 @@ type_dependent_expression_p (tree expression)
 	      || dependent_scope_p (scope));
     }
 
-  /* A function template specialization is type-dependent if it has any
-     dependent template arguments.  */
-  if (TREE_CODE (expression) == FUNCTION_DECL
-      && DECL_LANG_SPECIFIC (expression)
-      && DECL_TEMPLATE_INFO (expression))
-    return any_dependent_template_arguments_p (DECL_TI_ARGS (expression));
-
   if (TREE_CODE (expression) == TEMPLATE_DECL
       && !DECL_TEMPLATE_TEMPLATE_PARM_P (expression))
     return false;
@@ -23023,13 +23027,18 @@ type_dependent_expression_p (tree expression)
       && DECL_INITIAL (expression))
    return true;
 
-  /* A variable template specialization is type-dependent if it has any
-     dependent template arguments.  */
-  if (VAR_P (expression)
+  /* A function or variable template-id is type-dependent if it has any
+     dependent template arguments.  Note that we only consider the innermost
+     template arguments here, since those are the ones that come from the
+     template-id; the template arguments for the enclosing class do not make it
+     type-dependent, they only make a member function value-dependent.  */
+  if (VAR_OR_FUNCTION_DECL_P (expression)
       && DECL_LANG_SPECIFIC (expression)
       && DECL_TEMPLATE_INFO (expression)
-      && variable_template_p (DECL_TI_TEMPLATE (expression)))
-    return any_dependent_template_arguments_p (DECL_TI_ARGS (expression));
+      && PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (expression))
+      && (any_dependent_template_arguments_p
+	  (INNERMOST_TEMPLATE_ARGS (DECL_TI_ARGS (expression)))))
+    return true;
 
   /* Always dependent, on the number of arguments if nothing else.  */
   if (TREE_CODE (expression) == EXPR_PACK_EXPANSION)
@@ -23087,6 +23096,22 @@ type_dependent_expression_p (tree expression)
   return (dependent_type_p (TREE_TYPE (expression)));
 }
 
+/* [temp.dep.expr]/5: A class member access expression (5.2.5) is
+   type-dependent if the expression refers to a member of the current
+   instantiation and the type of the referenced member is dependent, or the
+   class member access expression refers to a member of an unknown
+   specialization.
+
+   This function returns true if the OBJECT in such a class member access
+   expression is of an unknown specialization.  */
+
+bool
+type_dependent_object_expression_p (tree object)
+{
+  tree scope = TREE_TYPE (object);
+  return (!scope || dependent_scope_p (scope));
+}
+
 /* walk_tree callback function for instantiation_dependent_expression_p,
    below.  Returns non-zero if a dependent subexpression is found.  */
 
@@ -23291,9 +23316,18 @@ dependent_template_arg_p (tree arg)
   if (TREE_CODE (arg) == ARGUMENT_PACK_SELECT)
     arg = ARGUMENT_PACK_SELECT_ARG (arg);
 
-  if (TREE_CODE (arg) == TEMPLATE_DECL
-      || TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM)
-    return dependent_template_p (arg);
+  if (TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM)
+    return true;
+  if (TREE_CODE (arg) == TEMPLATE_DECL)
+    {
+      if (DECL_TEMPLATE_PARM_P (arg))
+	return true;
+      /* A member template of a dependent class is not necessarily
+	 type-dependent, but it is a dependent template argument because it
+	 will be a member of an unknown specialization to that template.  */
+      tree scope = CP_DECL_CONTEXT (arg);
+      return TYPE_P (scope) && dependent_type_p (scope);
+    }
   else if (ARGUMENT_PACK_P (arg))
     {
       tree args = ARGUMENT_PACK_ARGS (arg);
@@ -23389,7 +23423,7 @@ any_dependent_template_arguments_p (const_tree args)
   return false;
 }
 
-/* Returns TRUE if the template TMPL is dependent.  */
+/* Returns TRUE if the template TMPL is type-dependent.  */
 
 bool
 dependent_template_p (tree tmpl)
@@ -23412,9 +23446,6 @@ dependent_template_p (tree tmpl)
   /* So are names that have not been looked up.  */
   if (TREE_CODE (tmpl) == SCOPE_REF || identifier_p (tmpl))
     return true;
-  /* So are member templates of dependent classes.  */
-  if (TYPE_P (CP_DECL_CONTEXT (tmpl)))
-    return dependent_type_p (DECL_CONTEXT (tmpl));
   return false;
 }
 
diff --git a/gcc/cp/search.c b/gcc/cp/search.c
index 503e34b..f47833f 100644
--- a/gcc/cp/search.c
+++ b/gcc/cp/search.c
@@ -1106,6 +1106,14 @@ lookup_field_r (tree binfo, void *data)
   if (!nval)
     /* Look for a data member or type.  */
     nval = lookup_field_1 (type, lfi->name, lfi->want_type);
+  else if (TREE_CODE (nval) == OVERLOAD && OVL_USED (nval))
+    {
+      /* If we have both dependent and non-dependent using-declarations, return
+	 the dependent one rather than an incomplete list of functions.  */
+      tree dep_using = lookup_field_1 (type, lfi->name, lfi->want_type);
+      if (dep_using && TREE_CODE (dep_using) == USING_DECL)
+	nval = dep_using;
+    }
 
   /* If there is no declaration with the indicated name in this type,
      then there's nothing to do.  */
@@ -2844,3 +2852,21 @@ original_binfo (tree binfo, tree here)
   return result;
 }
 
+/* True iff TYPE has any dependent bases (and therefore we can't say
+   definitively that another class is not a base of an instantiation of
+   TYPE).  */
+
+bool
+any_dependent_bases_p (tree type)
+{
+  if (!type || !CLASS_TYPE_P (type) || !processing_template_decl)
+    return false;
+
+  unsigned i;
+  tree base_binfo;
+  FOR_EACH_VEC_SAFE_ELT (BINFO_BASE_BINFOS (TYPE_BINFO (type)), i, base_binfo)
+    if (BINFO_DEPENDENT_BASE_P (base_binfo))
+      return true;
+
+  return false;
+}
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 817ef99..06dee5a 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -2300,18 +2300,7 @@ finish_call_expr (tree fn, vec<tree, va_gc> **args, bool disallow_virtual,
 	 with no type; type_dependent_expression_p recognizes
 	 expressions with no type as being dependent.  */
       if (type_dependent_expression_p (fn)
-	  || any_type_dependent_arguments_p (*args)
-	  /* For a non-static member function that doesn't have an
-	     explicit object argument, we need to specifically
-	     test the type dependency of the "this" pointer because it
-	     is not included in *ARGS even though it is considered to
-	     be part of the list of arguments.  Note that this is
-	     related to CWG issues 515 and 1005.  */
-	  || (TREE_CODE (fn) != COMPONENT_REF
-	      && non_static_member_function_p (fn)
-	      && !DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (get_first_fn (fn))
-	      && current_class_ref
-	      && type_dependent_expression_p (current_class_ref)))
+	  || any_type_dependent_arguments_p (*args))
 	{
 	  result = build_nt_call_vec (fn, *args);
 	  SET_EXPR_LOCATION (result, EXPR_LOC_OR_LOC (fn, input_location));
@@ -2399,17 +2388,6 @@ finish_call_expr (tree fn, vec<tree, va_gc> **args, bool disallow_virtual,
 	object = maybe_dummy_object (BINFO_TYPE (BASELINK_ACCESS_BINFO (fn)),
 				     NULL);
 
-      if (processing_template_decl)
-	{
-	  if (type_dependent_expression_p (object))
-	    {
-	      tree ret = build_nt_call_vec (orig_fn, orig_args);
-	      release_tree_vector (orig_args);
-	      return ret;
-	    }
-	  object = build_non_dependent_expr (object);
-	}
-
       result = build_new_method_call (object, fn, args, NULL_TREE,
 				      (disallow_virtual
 				       ? LOOKUP_NORMAL|LOOKUP_NONVIRTUAL
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 57fc5c1..04702ee 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -2127,23 +2127,6 @@ ovl_scope (tree ovl)
     ovl = OVL_CHAIN (ovl);
   return CP_DECL_CONTEXT (OVL_CURRENT (ovl));
 }
-
-/* Return TRUE if FN is a non-static member function, FALSE otherwise.
-   This function looks into BASELINK and OVERLOAD nodes.  */
-
-bool
-non_static_member_function_p (tree fn)
-{
-  if (fn == NULL_TREE)
-    return false;
-
-  if (is_overloaded_fn (fn))
-    fn = get_first_fn (fn);
-
-  return (DECL_P (fn)
-	  && DECL_NONSTATIC_MEMBER_FUNCTION_P (fn));
-}
-
 
 #define PRINT_RING_SIZE 4
 
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 0d8a980..cd058fa 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -2668,7 +2668,7 @@ finish_class_member_access_expr (cp_expr object, tree name, bool template_p,
   if (processing_template_decl)
     {
       if (/* If OBJECT is dependent, so is OBJECT.NAME.  */
-	  type_dependent_expression_p (object)
+	  type_dependent_object_expression_p (object)
 	  /* If NAME is "f<args>", where either 'f' or 'args' is
 	     dependent, then the expression is dependent.  */
 	  || (TREE_CODE (name) == TEMPLATE_ID_EXPR
@@ -2678,9 +2678,12 @@ finish_class_member_access_expr (cp_expr object, tree name, bool template_p,
 	     expression is dependent.  */
 	  || (TREE_CODE (name) == SCOPE_REF
 	      && TYPE_P (TREE_OPERAND (name, 0))
-	      && dependent_type_p (TREE_OPERAND (name, 0))))
-	return build_min_nt_loc (UNKNOWN_LOCATION, COMPONENT_REF,
-				 object.get_value (), name, NULL_TREE);
+	      && dependent_scope_p (TREE_OPERAND (name, 0))))
+	{
+	dependent:
+	  return build_min_nt_loc (UNKNOWN_LOCATION, COMPONENT_REF,
+				   orig_object, name, NULL_TREE);
+	}
       object = build_non_dependent_expr (object);
     }
   else if (c_dialect_objc ()
@@ -2805,7 +2808,12 @@ finish_class_member_access_expr (cp_expr object, tree name, bool template_p,
 	}
 
       if (TREE_CODE (name) == BIT_NOT_EXPR)
-	member = lookup_destructor (object, scope, name, complain);
+	{
+	  if (dependent_type_p (object_type))
+	    /* The destructor isn't declared yet.  */
+	    goto dependent;
+	  member = lookup_destructor (object, scope, name, complain);
+	}
       else
 	{
 	  /* Look up the member.  */
@@ -2813,6 +2821,9 @@ finish_class_member_access_expr (cp_expr object, tree name, bool template_p,
 				  /*want_type=*/false, complain);
 	  if (member == NULL_TREE)
 	    {
+	      if (dependent_type_p (object_type))
+		/* Try again at instantiation time.  */
+		goto dependent;
 	      if (complain & tf_error)
 		{
 		  tree guessed_id = lookup_member_fuzzy (access_path, name,
@@ -2842,6 +2853,8 @@ finish_class_member_access_expr (cp_expr object, tree name, bool template_p,
 	    }
 	  if (member == error_mark_node)
 	    return error_mark_node;
+	  if (TREE_CODE (member) == USING_DECL && DECL_DEPENDENT_P (member))
+	    goto dependent;
 	}
 
       if (is_template_id)
diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index 1c4e832..833be20 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -1703,7 +1703,10 @@ build_x_arrow (location_t loc, tree expr, tsubst_flags_t complain)
 
   if (processing_template_decl)
     {
-      if (type_dependent_expression_p (expr))
+      if (type && TREE_CODE (type) == POINTER_TYPE
+	  && !dependent_scope_p (TREE_TYPE (type)))
+	/* Pointer to current instantiation, don't treat as dependent.  */;
+      else if (type_dependent_expression_p (expr))
 	return build_min_nt_loc (loc, ARROW_EXPR, expr);
       expr = build_non_dependent_expr (expr);
     }
diff --git a/gcc/testsuite/g++.dg/lookup/member4.C b/gcc/testsuite/g++.dg/lookup/member4.C
new file mode 100644
index 0000000..6fab2f9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lookup/member4.C
@@ -0,0 +1,17 @@
+// PR c++/69753
+// { dg-do compile { target c++11 } }
+
+class A {
+public:
+  template <typename> void As();
+  static A *FromWebContents();
+  A *FromWebContents2();
+};
+template <typename T> class B : A {
+  void FromWebContents() {
+    auto guest = this->A::FromWebContents();
+    guest ? guest->As<T>() : nullptr;
+    auto guest2 = this->A::FromWebContents2();
+    guest2 ? guest2->As<T>() : nullptr;
+  }
+};
diff --git a/gcc/testsuite/g++.dg/lookup/member5.C b/gcc/testsuite/g++.dg/lookup/member5.C
new file mode 100644
index 0000000..fec1ecd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lookup/member5.C
@@ -0,0 +1,32 @@
+// PR c++/69753
+// { dg-do compile { target c++11 } }
+
+struct B {
+  template <class> void bfn ();
+};
+
+template <class T>
+constexpr int x(T) { return 42; }
+
+template <int I>
+struct C
+{
+  template <class> void cfn ();
+};
+
+template <typename T> struct A {
+  static B fn(int);
+  template <class U> static B ft(U);
+
+  void g()
+  {
+    auto b = this->fn(42);
+    b.bfn<int>();
+
+    auto b2 = this->ft(42);
+    b2.bfn<int>();
+
+    auto c = C<x(42)>();
+    c.cfn<int>();
+  }
+};
diff --git a/gcc/testsuite/g++.dg/template/using14.C b/gcc/testsuite/g++.dg/template/using14.C
index 276c40b..f1d97993 100644
--- a/gcc/testsuite/g++.dg/template/using14.C
+++ b/gcc/testsuite/g++.dg/template/using14.C
@@ -17,5 +17,5 @@ template <class T> struct C : public B1<T>, public B2
 int main()
 {
   C<int> c;
-  c.f();			// { dg-message "required" }
+  c.f();
 }

commit 2f6192ba7d231ef7801b55146f9781d0429e34ba
Author: Jason Merrill <jason@redhat.com>
Date:   Thu May 12 15:02:36 2016 -0400

    	Improve diagnostic for forgotten ().
    
    	* parser.c (cp_parser_postfix_dot_deref_expression): Use
    	complete_type_or_else for unknown_type_node, too.

diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index f4c6f74..7030740 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -7207,18 +7207,12 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser,
 	 underlying type here.  */
       scope = non_reference (scope);
       /* The type of the POSTFIX_EXPRESSION must be complete.  */
-      if (scope == unknown_type_node)
-	{
-	  error_at (location, "%qE does not have class type",
-		    postfix_expression.get_value ());
-	  scope = NULL_TREE;
-	}
       /* Unlike the object expression in other contexts, *this is not
 	 required to be of complete type for purposes of class member
 	 access (5.2.5) outside the member function body.  */
-      else if (postfix_expression != current_class_ref
-	       && !(processing_template_decl && scope == current_class_type))
-	scope = complete_type_or_else (scope, NULL_TREE);
+      if (postfix_expression != current_class_ref
+	  && !(processing_template_decl && scope == current_class_type))
+	scope = complete_type_or_else (scope, postfix_expression);
       /* Let the name lookup machinery know that we are processing a
 	 class member access expression.  */
       parser->context->object_type = scope;
diff --git a/gcc/testsuite/g++.dg/gomp/udr-4.C b/gcc/testsuite/g++.dg/gomp/udr-4.C
index 566d7d1..012ff0c 100644
--- a/gcc/testsuite/g++.dg/gomp/udr-4.C
+++ b/gcc/testsuite/g++.dg/gomp/udr-4.C
@@ -1,7 +1,7 @@
 // { dg-do compile }
 
 struct S;					// { dg-message "forward declaration" }
-#pragma omp declare reduction (+:S:omp_out.s += omp_in.s) // { dg-error "invalid use of incomplete type" }
+#pragma omp declare reduction (+:S:omp_out.s += omp_in.s) // { dg-error "incomplete type" }
 struct S { int s; S () : s (1) {} };
 #pragma omp declare reduction (*:S:omp_out.s *= omp_in.s)
 
diff --git a/gcc/testsuite/g++.dg/parse/dot1.C b/gcc/testsuite/g++.dg/parse/dot1.C
index 3b027d7..416ef92 100644
--- a/gcc/testsuite/g++.dg/parse/dot1.C
+++ b/gcc/testsuite/g++.dg/parse/dot1.C
@@ -1,4 +1,4 @@
 // PR c++/24560
 
 struct A { void f(); };
-void g() { A().f.a; } // { dg-error "class" }
+void g() { A().f.a; } // { dg-error "invalid use of member function" }
diff --git a/gcc/testsuite/g++.dg/template/pseudodtor3.C b/gcc/testsuite/g++.dg/template/pseudodtor3.C
index 8700bb9..8f1f6a7 100644
--- a/gcc/testsuite/g++.dg/template/pseudodtor3.C
+++ b/gcc/testsuite/g++.dg/template/pseudodtor3.C
@@ -5,7 +5,7 @@ struct A
 {
   typedef int T;
   T &foo ();
-  A () { foo.~T (); }	// { dg-error "10:does not have class type|expected" }
+  A () { foo.~T (); }	// { dg-error "10:invalid use of member function|expected" }
 };
 
 template <typename T> struct B

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]