public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* C++ PATCH for c++/10200 (DR 141, template name lookup after ->)
@ 2016-02-10 15:30 Jason Merrill
  2016-02-11  6:20 ` Markus Trippelsdorf
  0 siblings, 1 reply; 2+ messages in thread
From: Jason Merrill @ 2016-02-10 15:30 UTC (permalink / raw)
  To: gcc-patches List

[-- Attachment #1: Type: text/plain, Size: 568 bytes --]

After . or ->, when we see a name followed by < we look for a template 
name, first in the scope of the object expression and then in the 
enclosing scope.  DR 141 clarified that when we look in the enclosing 
scope, we only consider class templates, since there's no way a 
non-member function template could be correct in that situation.

When I fixed that, I found that we were failing to do the lookup in the 
object scope in the case where that scope is the current instantiation, 
so I needed to fix that as well.

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

[-- Attachment #2: 10200.patch --]
[-- Type: text/x-patch, Size: 5346 bytes --]

commit b3a4e73d776023398007c3d41bf957cee1792683
Author: Jason Merrill <jason@redhat.com>
Date:   Mon Feb 8 23:46:24 2016 -0500

    	PR c++/10200
    
    	* parser.c (cp_parser_lookup_name): When looking for a template
    	after . or ->, only consider class templates.
    	(cp_parser_postfix_dot_deref_expression): Handle the current
    	instantiation.  Remember a dependent object expression.
    	* typeck2.c (build_x_arrow): Handle the current instantiation.

diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 6f47edf..07d1821 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -7184,8 +7184,16 @@ 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);
+  /* According to the standard, no expression should ever have
+     reference type.  Unfortunately, we do not currently match
+     the standard in this respect in that our internal representation
+     of an expression may have reference type even when the standard
+     says it does not.  Therefore, we have to manually obtain the
+     underlying type here.  */
+  scope = non_reference (TREE_TYPE (postfix_expression));
+  /* Check to see whether or not the expression is type-dependent and
+     not the current instantiation.  */
+  dependent_p = !scope || dependent_scope_p (scope);
   /* The identifier following the `->' or `.' is not qualified.  */
   parser->scope = NULL_TREE;
   parser->qualifying_scope = NULL_TREE;
@@ -7194,16 +7202,8 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser,
 
   /* Enter the scope corresponding to the type of the object
      given by the POSTFIX_EXPRESSION.  */
-  if (!dependent_p && TREE_TYPE (postfix_expression) != NULL_TREE)
+  if (!dependent_p)
     {
-      scope = TREE_TYPE (postfix_expression);
-      /* According to the standard, no expression should ever have
-	 reference type.  Unfortunately, we do not currently match
-	 the standard in this respect in that our internal representation
-	 of an expression may have reference type even when the standard
-	 says it does not.  Therefore, we have to manually obtain the
-	 underlying type here.  */
-      scope = non_reference (scope);
       /* The type of the POSTFIX_EXPRESSION must be complete.  */
       if (scope == unknown_type_node)
 	{
@@ -7215,7 +7215,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.  */
       else 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, NULL_TREE);
       /* Let the name lookup machinery know that we are processing a
 	 class member access expression.  */
@@ -7231,6 +7234,10 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser,
       if (scope == error_mark_node)
 	postfix_expression = error_mark_node;
     }
+  else
+    /* Tell cp_parser_lookup_name that there was an object, even though it's
+       type-dependent.  */
+    parser->context->object_type = unknown_type_node;
 
   /* Assume this expression is not a pseudo-destructor access.  */
   pseudo_destructor_p = false;
@@ -24720,10 +24727,15 @@ 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,
+	/* 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.  */
+	object_type = NULL_TREE;
       parser->object_scope = object_type;
       parser->qualifying_scope = NULL_TREE;
     }
diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index 2a76c96..54a432f 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -1694,7 +1694,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/member2.C b/gcc/testsuite/g++.dg/lookup/member2.C
new file mode 100644
index 0000000..5478448
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lookup/member2.C
@@ -0,0 +1,5 @@
+// PR c++/10200
+
+template<class Tp> inline void end(Tp) { }
+
+template <typename T> bool tnegative(const T& t) { return t.end < 0; }

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: C++ PATCH for c++/10200 (DR 141, template name lookup after ->)
  2016-02-10 15:30 C++ PATCH for c++/10200 (DR 141, template name lookup after ->) Jason Merrill
@ 2016-02-11  6:20 ` Markus Trippelsdorf
  0 siblings, 0 replies; 2+ messages in thread
From: Markus Trippelsdorf @ 2016-02-11  6:20 UTC (permalink / raw)
  To: Jason Merrill; +Cc: gcc-patches List

On 2016.02.10 at 10:30 -0500, Jason Merrill wrote:
> After . or ->, when we see a name followed by < we look for a template name,
> first in the scope of the object expression and then in the enclosing scope.
> DR 141 clarified that when we look in the enclosing scope, we only consider
> class templates, since there's no way a non-member function template could
> be correct in that situation.
> 
> When I fixed that, I found that we were failing to do the lookup in the
> object scope in the case where that scope is the current instantiation, so I
> needed to fix that as well.
> 
> Tested x86_64-pc-linux-gnu, applying to trunk.

This commit causes: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69753

-- 
Markus

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2016-02-11  6:20 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-02-10 15:30 C++ PATCH for c++/10200 (DR 141, template name lookup after ->) Jason Merrill
2016-02-11  6:20 ` Markus Trippelsdorf

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).