]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR c++/20293 (Wrong diagnostic for ambiguous access)
authorMark Mitchell <mark@codesourcery.com>
Mon, 14 Nov 2005 01:45:19 +0000 (01:45 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Mon, 14 Nov 2005 01:45:19 +0000 (01:45 +0000)
PR c++/20293
* cxx-pretty-print.c (pp_cxx_statement): Print qualifying scopes
for namespaces.
(pp_cxx_original_namespace_definition): Likewise.
* name-lookup.c (ambiguous_decl): Don't issue error messages;
instead return lists of ambiguous candidates.
(select_decl): Handle ambiguous namespace lookups.
* parser.c (cp_token): Add ambiguous_p.
(cp_lexer_get_preprocessor_token): Set it.
(cp_parser_diagnose_invalid_type_name): Avoid duplicate messages
when a qualified name uses an invalid scope.
(cp_parser_primary_expression): Print ambiguous candidates.
(cp_parser_type_parameter): Adjust comment to reflect new
parameter name for cp_parser_lookup_name.
(cp_parser_template_argument): Likewise.
(cp_parser_elaborated_type_specifier): Likewise.
(cp_parser_namespace_name): Likewise.
(cp_parser_class_name): Print ambiguous candidates.
(cp_parser_lookup_name): Rename ambiguous_p parameter to
ambiguous_decls.  Use it to return a list of ambiguous candiates
when a lookup is ambiguous.
(cp_parser_lookup_name_simple): Adjust comment to reflect new
parameter name for cp_parser_lookup_name.

PR c++/20293
* g++.dg/parse/ambig4.C: New test.
* g++.dg/tc1/dr101.C: Adjust error markers.
* g++.dg/lookup/strong-using-2.C: Likewise.
* g++.dg/lookup/ambig5.C: Likewise.
* g++.dg/lookup/ambig4.C: Likewise.
* g++.dg/parse/crash22.C: Likewise.

From-SVN: r106879

gcc/cp/ChangeLog
gcc/cp/cxx-pretty-print.c
gcc/cp/name-lookup.c
gcc/cp/parser.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/lookup/ambig4.C
gcc/testsuite/g++.dg/lookup/ambig5.C
gcc/testsuite/g++.dg/lookup/strong-using-2.C
gcc/testsuite/g++.dg/parse/ambig4.C [new file with mode: 0644]
gcc/testsuite/g++.dg/parse/crash22.C
gcc/testsuite/g++.dg/tc1/dr101.C

index 6edab04fe2bb488927df1ea676f0a05f737aeb14..4fafe495d2e68e2cf3f4924c1cc2d39e2bffabe4 100644 (file)
@@ -1,3 +1,29 @@
+2005-11-13  Mark Mitchell  <mark@codesourcery.com>
+
+       PR c++/20293
+       * cxx-pretty-print.c (pp_cxx_statement): Print qualifying scopes
+       for namespaces.
+       (pp_cxx_original_namespace_definition): Likewise.
+       * name-lookup.c (ambiguous_decl): Don't issue error messages;
+       instead return lists of ambiguous candidates.
+       (select_decl): Handle ambiguous namespace lookups.
+       * parser.c (cp_token): Add ambiguous_p.
+       (cp_lexer_get_preprocessor_token): Set it.
+       (cp_parser_diagnose_invalid_type_name): Avoid duplicate messages
+       when a qualified name uses an invalid scope. 
+       (cp_parser_primary_expression): Print ambiguous candidates.
+       (cp_parser_type_parameter): Adjust comment to reflect new
+       parameter name for cp_parser_lookup_name.
+       (cp_parser_template_argument): Likewise.
+       (cp_parser_elaborated_type_specifier): Likewise.
+       (cp_parser_namespace_name): Likewise.
+       (cp_parser_class_name): Print ambiguous candidates.
+       (cp_parser_lookup_name): Rename ambiguous_p parameter to
+       ambiguous_decls.  Use it to return a list of ambiguous candiates
+       when a lookup is ambiguous.
+       (cp_parser_lookup_name_simple): Adjust comment to reflect new
+       parameter name for cp_parser_lookup_name.
+       
 2005-11-12  Jakub Jelinek  <jakub@redhat.com>
 
        PR c++/24780
index f4f8819d1ed4a699074a46cf2d700b27a344590a..cdaf470ce26e2336ffbb3a111f917e8813c566ac 100644 (file)
@@ -1514,6 +1514,8 @@ pp_cxx_statement (cxx_pretty_printer *pp, tree t)
     case USING_STMT:
       pp_cxx_identifier (pp, "using");
       pp_cxx_identifier (pp, "namespace");
+      if (DECL_CONTEXT (t))
+       pp_cxx_nested_name_specifier (pp, DECL_CONTEXT (t));
       pp_cxx_qualified_id (pp, USING_STMT_NAMESPACE (t));
       break;
 
@@ -1701,6 +1703,8 @@ static void
 pp_cxx_original_namespace_definition (cxx_pretty_printer *pp, tree t)
 {
   pp_cxx_identifier (pp, "namespace");
+  if (DECL_CONTEXT (t))
+    pp_cxx_nested_name_specifier (pp, DECL_CONTEXT (t));
   if (DECL_NAME (t))
     pp_cxx_unqualified_id (pp, t);
   pp_cxx_whitespace (pp);
@@ -1723,10 +1727,15 @@ static void
 pp_cxx_namespace_alias_definition (cxx_pretty_printer *pp, tree t)
 {
   pp_cxx_identifier (pp, "namespace");
+  if (DECL_CONTEXT (t))
+    pp_cxx_nested_name_specifier (pp, DECL_CONTEXT (t));
   pp_cxx_unqualified_id (pp, t);
   pp_cxx_whitespace (pp);
   pp_equal (pp);
   pp_cxx_whitespace (pp);
+  if (DECL_CONTEXT (DECL_NAMESPACE_ALIAS (t)))
+    pp_cxx_nested_name_specifier (pp, 
+                                 DECL_CONTEXT (DECL_NAMESPACE_ALIAS (t)));
   pp_cxx_qualified_id (pp, DECL_NAMESPACE_ALIAS (t));
   pp_cxx_semicolon (pp);
 }
index 13d789b1f5612869d7157d5d72bce96e6ac0f4af..20ea311196fa25bbb8816c78b422e6442021ce73 100644 (file)
@@ -3400,20 +3400,9 @@ ambiguous_decl (tree name, struct scope_binding *old, cxx_binding *new,
        old->value = merge_functions (old->value, val);
       else
        {
-         /* Some declarations are functions, some are not.  */
-         if (flags & LOOKUP_COMPLAIN)
-           {
-             /* If we've already given this error for this lookup,
-                old->value is error_mark_node, so let's not
-                repeat ourselves.  */
-             if (old->value != error_mark_node)
-               {
-                 error ("use of %qD is ambiguous", name);
-                 error ("  first declared as %q+#D here", old->value);
-               }
-             error ("  also declared as %q+#D here", val);
-           }
-         old->value = error_mark_node;
+         old->value = tree_cons (NULL_TREE, old->value,
+                                 build_tree_list (NULL_TREE, new->value));
+         TREE_TYPE (old->value) = error_mark_node;
        }
     }
   /* ... and copy the type.  */
@@ -3609,7 +3598,8 @@ select_decl (const struct scope_binding *binding, int flags)
   if (LOOKUP_NAMESPACES_ONLY (flags))
     {
       /* We are not interested in types.  */
-      if (val && TREE_CODE (val) == NAMESPACE_DECL)
+      if (val && (TREE_CODE (val) == NAMESPACE_DECL
+                 || TREE_CODE (val) == TREE_LIST))
        POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, val);
       POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
     }
index bbc5c1156bdcff6b4683da2ab4c931fca0667ce2..2b850c0d197ea339f1d9393af4ea7afdf64de975 100644 (file)
@@ -59,6 +59,10 @@ typedef struct cp_token GTY (())
   BOOL_BITFIELD in_system_header : 1;
   /* True if this token is from a context where it is implicitly extern "C" */
   BOOL_BITFIELD implicit_extern_c : 1;
+  /* True for a CPP_NAME token that is not a keyword (i.e., for which
+     KEYWORD is RID_MAX) iff this name was looked up and found to be
+     ambiguous.  An error has already been reported.  */
+  BOOL_BITFIELD ambiguous_p : 1;
   /* The value associated with this token, if any.  */
   tree value;
   /* The location at which this token was found.  */
@@ -401,18 +405,22 @@ cp_lexer_get_preprocessor_token (cp_lexer *lexer ATTRIBUTE_UNUSED ,
   token->implicit_extern_c = is_extern_c > 0;
 
   /* Check to see if this token is a keyword.  */
-  if (token->type == CPP_NAME
-      && C_IS_RESERVED_WORD (token->value))
+  if (token->type == CPP_NAME)
     {
-      /* Mark this token as a keyword.  */
-      token->type = CPP_KEYWORD;
-      /* Record which keyword.  */
-      token->keyword = C_RID_CODE (token->value);
-      /* Update the value.  Some keywords are mapped to particular
-        entities, rather than simply having the value of the
-        corresponding IDENTIFIER_NODE.  For example, `__const' is
-        mapped to `const'.  */
-      token->value = ridpointers[token->keyword];
+      if (C_IS_RESERVED_WORD (token->value))
+       {
+         /* Mark this token as a keyword.  */
+         token->type = CPP_KEYWORD;
+         /* Record which keyword.  */
+         token->keyword = C_RID_CODE (token->value);
+         /* Update the value.  Some keywords are mapped to particular
+            entities, rather than simply having the value of the
+            corresponding IDENTIFIER_NODE.  For example, `__const' is
+            mapped to `const'.  */
+         token->value = ridpointers[token->keyword];
+       }
+      else
+       token->ambiguous_p = false;
     }
   /* Handle Objective-C++ keywords.  */
   else if (token->type == CPP_AT_NAME)
@@ -1699,7 +1707,7 @@ static tree cp_parser_objc_statement
 /* Utility Routines */
 
 static tree cp_parser_lookup_name
-  (cp_parser *, tree, enum tag_types, bool, bool, bool, bool *);
+  (cp_parser *, tree, enum tag_types, bool, bool, bool, tree *);
 static tree cp_parser_lookup_name_simple
   (cp_parser *, tree);
 static tree cp_parser_maybe_treat_template_as_class
@@ -2052,7 +2060,7 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser, tree scope, tree id)
   if (TREE_CODE (decl) == TEMPLATE_DECL)
     error ("invalid use of template-name %qE without an argument list",
       decl);
-  else if (!parser->scope || parser->scope == error_mark_node)
+  else if (!parser->scope)
     {
       /* Issue an error message.  */
       error ("%qE does not name a type", id);
@@ -2099,7 +2107,7 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser, tree scope, tree id)
     }
   /* Here we diagnose qualified-ids where the scope is actually correct,
      but the identifier does not resolve to a valid type name.  */
-  else
+  else if (parser->scope != error_mark_node)
     {
       if (TREE_CODE (parser->scope) == NAMESPACE_DECL)
        error ("%qE in namespace %qE does not name a type",
@@ -2994,17 +3002,17 @@ cp_parser_primary_expression (cp_parser *parser,
        /* Look up the name.  */
        else
          {
-           bool ambiguous_p;
+           tree ambiguous_decls;
 
            decl = cp_parser_lookup_name (parser, id_expression,
                                          none_type,
                                          template_p,
                                          /*is_namespace=*/false,
                                          /*check_dependency=*/true,
-                                         &ambiguous_p);
+                                         &ambiguous_decls);
            /* If the lookup was ambiguous, an error will already have
               been issued.  */
-           if (ambiguous_p)
+           if (ambiguous_decls)
              return error_mark_node;
 
            /* In Objective-C++, an instance variable (ivar) may be preferred
@@ -3610,16 +3618,32 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
              token = cp_lexer_consume_token (parser->lexer);
              if (!error_p)
                {
-                 tree decl;
-
-                 decl = cp_parser_lookup_name_simple (parser, token->value);
-                 if (TREE_CODE (decl) == TEMPLATE_DECL)
-                   error ("%qD used without template parameters", decl);
-                 else
-                   cp_parser_name_lookup_error
-                     (parser, token->value, decl,
-                      "is not a class or namespace");
-                 parser->scope = NULL_TREE;
+                 if (!token->ambiguous_p)
+                   {
+                     tree decl;
+                     tree ambiguous_decls;
+
+                     decl = cp_parser_lookup_name (parser, token->value,
+                                                   none_type,
+                                                   /*is_template=*/false,
+                                                   /*is_namespace=*/false,
+                                                   /*check_dependency=*/true,
+                                                   &ambiguous_decls);
+                     if (TREE_CODE (decl) == TEMPLATE_DECL)
+                       error ("%qD used without template parameters", decl);
+                     else if (ambiguous_decls)
+                       {
+                         error ("reference to %qD is ambiguous", 
+                                token->value);
+                         print_candidates (ambiguous_decls);
+                         decl = error_mark_node;
+                       }
+                     else
+                       cp_parser_name_lookup_error
+                         (parser, token->value, decl,
+                          "is not a class or namespace");
+                   }
+                 parser->scope = error_mark_node;
                  error_p = true;
                  /* Treat this as a successful nested-name-specifier
                     due to:
@@ -8457,7 +8481,7 @@ cp_parser_type_parameter (cp_parser* parser)
                                         /*is_template=*/is_template,
                                         /*is_namespace=*/false,
                                         /*check_dependency=*/true,
-                                        /*ambiguous_p=*/NULL);
+                                        /*ambiguous_decls=*/NULL);
            /* See if the default argument is valid.  */
            default_argument
              = check_template_template_default_arg (default_argument);
@@ -8813,7 +8837,7 @@ cp_parser_template_name (cp_parser* parser,
                                /*is_template=*/false,
                                /*is_namespace=*/false,
                                check_dependency_p,
-                               /*ambiguous_p=*/NULL);
+                               /*ambiguous_decls=*/NULL);
   decl = maybe_get_template_decl_from_type_decl (decl);
 
   /* If DECL is a template, then the name was a template-name.  */
@@ -9014,7 +9038,7 @@ cp_parser_template_argument (cp_parser* parser)
                                          /*is_template=*/template_p,
                                          /*is_namespace=*/false,
                                          /*check_dependency=*/true,
-                                         /*ambiguous_p=*/NULL);
+                                         /*ambiguous_decls=*/NULL);
       if (TREE_CODE (argument) != TEMPLATE_DECL
          && TREE_CODE (argument) != UNBOUND_CLASS_TEMPLATE)
        cp_parser_error (parser, "expected template-name");
@@ -9937,7 +9961,7 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
                                        /*is_template=*/false,
                                        /*is_namespace=*/false,
                                        /*check_dependency=*/true,
-                                       /*ambiguous_p=*/NULL);
+                                       /*ambiguous_decls=*/NULL);
 
          /* If we are parsing friend declaration, DECL may be a
             TEMPLATE_DECL tree node here.  However, we need to check
@@ -10233,7 +10257,7 @@ cp_parser_namespace_name (cp_parser* parser)
                                          /*is_template=*/false,
                                          /*is_namespace=*/true,
                                          /*check_dependency=*/true,
-                                         /*ambiguous_p=*/NULL);
+                                         /*ambiguous_decls=*/NULL);
   /* If it's not a namespace, issue an error.  */
   if (namespace_decl == error_mark_node
       || TREE_CODE (namespace_decl) != NAMESPACE_DECL)
@@ -12469,9 +12493,13 @@ cp_parser_class_name (cp_parser *parser,
   if (token->type == CPP_NAME
       && !cp_parser_nth_token_starts_template_argument_list_p (parser, 2))
     {
+      cp_token *identifier_token;
       tree identifier;
+      bool ambiguous_p;
 
       /* Look for the identifier.  */
+      identifier_token = cp_lexer_peek_token (parser->lexer);
+      ambiguous_p = identifier_token->ambiguous_p;
       identifier = cp_parser_identifier (parser);
       /* If the next token isn't an identifier, we are certainly not
         looking at a class-name.  */
@@ -12483,6 +12511,15 @@ cp_parser_class_name (cp_parser *parser,
        decl = identifier;
       else
        {
+         tree ambiguous_decls;
+         /* If we already know that this lookup is ambiguous, then
+            we've already issued an error message; there's no reason
+            to check again.  */
+         if (ambiguous_p)
+           {
+             cp_parser_simulate_error (parser);
+             return error_mark_node;
+           }
          /* If the next token is a `::', then the name must be a type
             name.
 
@@ -12499,7 +12536,18 @@ cp_parser_class_name (cp_parser *parser,
                                        /*is_template=*/false,
                                        /*is_namespace=*/false,
                                        check_dependency_p,
-                                       /*ambiguous_p=*/NULL);
+                                       &ambiguous_decls);
+         if (ambiguous_decls)
+           {
+             error ("reference to %qD is ambiguous", identifier);
+             print_candidates (ambiguous_decls);
+             if (cp_parser_parsing_tentatively (parser))
+               {
+                 identifier_token->ambiguous_p = true;
+                 cp_parser_simulate_error (parser);
+               }
+             return error_mark_node;
+           }
        }
     }
   else
@@ -14438,8 +14486,9 @@ cp_parser_label_declaration (cp_parser* parser)
    If CHECK_DEPENDENCY is TRUE, names are not looked up in dependent
    types.
 
-   If AMBIGUOUS_P is non-NULL, it is set to true if name-lookup
-   results in an ambiguity, and false otherwise.  */
+   If AMBIGUOUS_DECLS is non-NULL, *AMBIGUOUS_DECLS is set to a
+   TREE_LIST of candiates if name-lookup results in an ambiguity, and
+   NULL_TREE otherwise.  */ 
 
 static tree
 cp_parser_lookup_name (cp_parser *parser, tree name,
@@ -14447,7 +14496,7 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
                       bool is_template, 
                       bool is_namespace,
                       bool check_dependency,
-                      bool *ambiguous_p)
+                      tree *ambiguous_decls)
 {
   int flags = 0;
   tree decl;
@@ -14457,8 +14506,8 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
     flags |= LOOKUP_COMPLAIN;
 
   /* Assume that the lookup will be unambiguous.  */
-  if (ambiguous_p)
-    *ambiguous_p = false;
+  if (ambiguous_decls)
+    *ambiguous_decls = NULL_TREE;
 
   /* Now that we have looked up the name, the OBJECT_TYPE (if any) is
      no longer valid.  Note that if we are parsing tentatively, and
@@ -14615,8 +14664,8 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
   /* If it's a TREE_LIST, the result of the lookup was ambiguous.  */
   if (TREE_CODE (decl) == TREE_LIST)
     {
-      if (ambiguous_p)
-       *ambiguous_p = true;
+      if (ambiguous_decls)
+       *ambiguous_decls = decl;
       /* The error message we have to print is too complicated for
         cp_parser_error, so we incorporate its actions directly.  */
       if (!cp_parser_simulate_error (parser))
@@ -14658,7 +14707,7 @@ cp_parser_lookup_name_simple (cp_parser* parser, tree name)
                                /*is_template=*/false,
                                /*is_namespace=*/false,
                                /*check_dependency=*/true,
-                               /*ambiguous_p=*/NULL);
+                               /*ambiguous_decls=*/NULL);
 }
 
 /* If DECL is a TEMPLATE_DECL that can be treated like a TYPE_DECL in
index be37ba04c6356e82f92dea18f4aee520f073adde..8480b51cc590f391587530421fc727437a36bff2 100644 (file)
@@ -1,3 +1,13 @@
+2005-11-13  Mark Mitchell  <mark@codesourcery.com>
+
+       PR c++/20293
+       * g++.dg/parse/ambig4.C: New test.
+       * g++.dg/tc1/dr101.C: Adjust error markers.
+       * g++.dg/lookup/strong-using-2.C: Likewise.
+       * g++.dg/lookup/ambig5.C: Likewise.
+       * g++.dg/lookup/ambig4.C: Likewise.
+       * g++.dg/parse/crash22.C: Likewise.
+
 2005-11-14  Hans-Peter Nilsson  <hp@axis.com>
 
        * gcc.dg/pr19340.c: Skip for mmix-*-* and cris-*-*.
index ab1a14518d59c79ab5b42173750490f8e2dd7e36..3a74f7d1c767be43952c63d60ce9aea2ccfe4815 100644 (file)
@@ -4,11 +4,11 @@
 
 namespace N
 {
-  int i;            // { dg-error "declared" }
+  int i;            // { dg-error "i" }
 }
 
-int i;              // { dg-error "declared" }
+int i;              // { dg-error "i" }
 
 using namespace N;
 
-void foo() { i; }   // { dg-error "in this scope|ambiguous" }
+void foo() { i; }   // { dg-error "ambiguous" }
index 8f74efc751843e469f0fa171f4d9b6280cfd8b5c..cebec277910785a14018f610bf02751e2ed1f947 100644 (file)
@@ -4,10 +4,10 @@
 
 namespace N
 {
-  namespace M {}    // { dg-error "declared" }
+  namespace M {}    // { dg-error "M" }
 }
 
-namespace M {}      // { dg-error "declared" }
+namespace M {}      // { dg-error "M" }
 
 using namespace N;
 using namespace M;  // { dg-error "namespace-name|ambiguous" }
index 8d45e00e0e15302ea535fdc2b445ba6551ab6177..f8b5f64fbd24d9c941db2e465d6723e9ce9a6758 100644 (file)
@@ -3,10 +3,10 @@
 // { dg-do compile }
 
 namespace foo_impl {
-  class T; // { dg-error "first declared" "" }
+  class T; // { dg-error "T" "" }
 }
 namespace bar_impl {
-  class T; // { dg-error "also declared" "" }
+  class T; // { dg-error "T" "" }
 }
 namespace foo {
   using namespace foo_impl __attribute__((strong));
diff --git a/gcc/testsuite/g++.dg/parse/ambig4.C b/gcc/testsuite/g++.dg/parse/ambig4.C
new file mode 100644 (file)
index 0000000..868f07c
--- /dev/null
@@ -0,0 +1,18 @@
+// PR c++/20293
+
+namespace hide { // { dg-error "hide" }
+  int k;
+}
+
+namespace {
+  int i; 
+  namespace hide { // { dg-error "hide" }
+    int j; 
+  }
+}
+
+void F(int) {}
+
+int main() {
+  F(hide::j); // { dg-error "ambiguous" }
+}
index d4fe6d15a8ebf70d66d3e9aa910bb7b89e098b2b..eaf4d1a5c08e4f0603783c3c8fa4fcb965ef6c1d 100644 (file)
@@ -4,17 +4,17 @@
 // PR 19030: ICE
 // Origin: Volker Reichelt <reichelt@gcc.gnu.org>
 
-struct A;
+struct A; // { dg-error "A" }
 
 namespace N
 {
-  struct A;
+  struct A; // { dg-error "A" }
 }
 
 using namespace N;
 
-int A::i; // { dg-error "not been declared|declared here" "" }
-int A::i; // { dg-error "not been declared|redefinition of" "" }
+int A::i; // { dg-error "ambiguous|declared here" "" }
+int A::i; // { dg-error "ambiguous|redefinition of" "" }
 
 namespace N
 {
index 8d9cab518b9bd133cbde42745083ef8c05d4a66c..c5b34a472a98611ab26dacb9d3f28d21e586ceb8 100644 (file)
@@ -17,10 +17,10 @@ namespace Test1 {
 
 namespace Test2 {
 
-  typedef unsigned int X;   // { dg-bogus "declared" "" { xfail *-*-* } }
+  typedef unsigned int X;   // { dg-bogus "X" "" { xfail *-*-* } }
   extern "C" int f2();
   namespace N {
-    typedef unsigned int X; // { dg-bogus "declared" "" { xfail *-*-* } }
+    typedef unsigned int X; // { dg-bogus "X" "" { xfail *-*-* } }
     extern "C" int f2();
   }
   using namespace N;