re PR c++/10200 (Weird clash with same names in different scopes)
authorJason Merrill <jason@redhat.com>
Wed, 10 Feb 2016 15:34:52 +0000 (10:34 -0500)
committerJason Merrill <jason@gcc.gnu.org>
Wed, 10 Feb 2016 15:34:52 +0000 (10:34 -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.

From-SVN: r233277

gcc/cp/ChangeLog
gcc/cp/parser.c
gcc/cp/typeck2.c
gcc/testsuite/g++.dg/lookup/member2.C [new file with mode: 0644]

index a117b47ae10a3ae752bd482379c0eb29fec0b873..92e65fcbba46704c5a77a82e010f2b76fdc5aab9 100644 (file)
@@ -1,5 +1,12 @@
 2016-02-10  Jason Merrill  <jason@redhat.com>
 
+       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.
+
        * ptree.c (debug_tree): Implement for cp_expr.
 
 2016-02-08  Patrick Palka  <ppalka@gcc.gnu.org>
index 6f47edf9bd0abec6d22406e185716cc1d35640a5..07d182156d6375230fbeca6f5a6023fbd68f87de 100644 (file)
@@ -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)
-    {
-      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);
+  if (!dependent_p)
+    {
       /* 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;
     }
index 2a76c96c7d48d27e8082fc14924ccc02e132ed0c..54a432f256f3801b63a1b7dcc60ee0273d46e836 100644 (file)
@@ -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 (file)
index 0000000..5478448
--- /dev/null
@@ -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; }