]> gcc.gnu.org Git - gcc.git/commitdiff
PR c++/13950, DR 176
authorJason Merrill <jason@redhat.com>
Mon, 16 Nov 2009 23:29:25 +0000 (18:29 -0500)
committerJason Merrill <jason@gcc.gnu.org>
Mon, 16 Nov 2009 23:29:25 +0000 (18:29 -0500)
PR c++/13950, DR 176
* search.c (lookup_field_r): Allow lookup to find the
injected-class-name from a template base.
(template_self_reference_p): Remove.
* decl.c (make_typename_type): Diagnose ambiguity.  Use
maybe_get_template_decl_from_type_decl.
* parser.c (cp_parser_template_name): Pass true to is_template
rather than use maybe_get_template_decl_from_type_decl.
(cp_parser_lookup_name): Use maybe_get_template_decl_from_type_decl.
* pt.c (maybe_get_template_decl_from_type_decl): Handle ambiguity.
Use DECL_SELF_REFERENCE_P.

* parser.c (cp_parser_parse_and_diagnose_invalid_type_name):
Avoid duplicate ambiguity error.
* error.c (dump_decl): Don't say "typedef" for injected-class-name.
* pt.c (convert_template_argument): Tweak logic.

From-SVN: r154223

13 files changed:
gcc/cp/ChangeLog
gcc/cp/decl.c
gcc/cp/error.c
gcc/cp/parser.c
gcc/cp/pt.c
gcc/cp/search.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/template/inherit.C
gcc/testsuite/g++.dg/template/injected1.C [new file with mode: 0644]
gcc/testsuite/g++.old-deja/g++.brendan/crash56.C
gcc/testsuite/g++.old-deja/g++.pt/lookup8.C
gcc/testsuite/g++.old-deja/g++.pt/ttp22.C
gcc/testsuite/g++.old-deja/g++.pt/ttp23.C

index ce4415d3f7f4b4e5eb75d167533301660b380811..960cedc2af51c4d5646673c49e938ffadcc03b74 100644 (file)
@@ -1,3 +1,22 @@
+2009-11-16  Jason Merrill  <jason@redhat.com>
+
+       PR c++/13950, DR 176
+       * search.c (lookup_field_r): Allow lookup to find the
+       injected-class-name from a template base.
+       (template_self_reference_p): Remove.
+       * decl.c (make_typename_type): Diagnose ambiguity.  Use
+       maybe_get_template_decl_from_type_decl.
+       * parser.c (cp_parser_template_name): Pass true to is_template
+       rather than use maybe_get_template_decl_from_type_decl.
+       (cp_parser_lookup_name): Use maybe_get_template_decl_from_type_decl.
+       * pt.c (maybe_get_template_decl_from_type_decl): Handle ambiguity.
+       Use DECL_SELF_REFERENCE_P.
+
+       * parser.c (cp_parser_parse_and_diagnose_invalid_type_name):
+       Avoid duplicate ambiguity error.
+       * error.c (dump_decl): Don't say "typedef" for injected-class-name.
+       * pt.c (convert_template_argument): Tweak logic.
+
 2009-11-16  Paolo Carlini  <paolo.carlini@oracle.com>
 
        PR c++/42055
index 73bf995714ff7fa55769ef51755c6f2282622222..851edeb52519d3be9fa37d07c3317035c50ede3d 100644 (file)
@@ -3040,11 +3040,11 @@ make_typename_type (tree context, tree name, enum tag_types tag_type,
   if (!dependent_scope_p (context))
     /* We should only set WANT_TYPE when we're a nested typename type.
        Then we can give better diagnostics if we find a non-type.  */
-    t = lookup_field (context, name, 0, /*want_type=*/true);
+    t = lookup_field (context, name, 2, /*want_type=*/true);
   else
     t = NULL_TREE;
 
-  if (!t && dependent_type_p (context)) 
+  if ((!t || TREE_CODE (t) == TREE_LIST) && dependent_type_p (context))
     return build_typename_type (context, name, fullname, tag_type);
 
   want_template = TREE_CODE (fullname) == TEMPLATE_ID_EXPR;
@@ -3057,6 +3057,20 @@ make_typename_type (tree context, tree name, enum tag_types tag_type,
       return error_mark_node;
     }
   
+  /* Pull out the template from an injected-class-name (or multiple).  */
+  if (want_template)
+    t = maybe_get_template_decl_from_type_decl (t);
+
+  if (TREE_CODE (t) == TREE_LIST)
+    {
+      if (complain & tf_error)
+       {
+         error ("lookup of %qT in %qT is ambiguous", name, context);
+         print_candidates (t);
+       }
+      return error_mark_node;
+    }
+
   if (want_template && !DECL_CLASS_TEMPLATE_P (t))
     {
       if (complain & tf_error)
index f4232075119b32dafd39d41e156244712f2d8f90..7266d8872d50c58236e53106a29c2cff6edfc5b0 100644 (file)
@@ -908,7 +908,8 @@ dump_decl (tree t, int flags)
          dump_type (TREE_TYPE (t), flags);
          break;
        }
-      if (flags & TFF_DECL_SPECIFIERS)
+      if ((flags & TFF_DECL_SPECIFIERS)
+         && !DECL_SELF_REFERENCE_P (t))
        pp_cxx_ws_string (cxx_pp, "typedef");
       dump_simple_decl (t, DECL_ORIGINAL_TYPE (t)
                        ? DECL_ORIGINAL_TYPE (t) : TREE_TYPE (t),
index 3a4b409e738e86e393318110691b3bc2435d84eb..576842641fe8f850a9f2df95a0fea5ee3c05a8ee 100644 (file)
@@ -2430,6 +2430,14 @@ cp_parser_parse_and_diagnose_invalid_type_name (cp_parser *parser)
   tree id;
   cp_token *token = cp_lexer_peek_token (parser->lexer);
 
+  /* Avoid duplicate error about ambiguous lookup.  */
+  if (token->type == CPP_NESTED_NAME_SPECIFIER)
+    {
+      cp_token *next = cp_lexer_peek_nth_token (parser->lexer, 2);
+      if (next->type == CPP_NAME && next->ambiguous_p)
+       goto out;
+    }
+
   cp_parser_parse_tentatively (parser);
   id = cp_parser_id_expression (parser,
                                /*template_keyword_p=*/false,
@@ -2451,6 +2459,7 @@ cp_parser_parse_and_diagnose_invalid_type_name (cp_parser *parser)
   /* Emit a diagnostic for the invalid type.  */
   cp_parser_diagnose_invalid_type_name (parser, parser->scope,
                                        id, token->location);
+ out:
   /* If we aren't in the middle of a declarator (i.e. in a
      parameter-declaration-clause), skip to the end of the declaration;
      there's no point in trying to process it.  */
@@ -11086,12 +11095,11 @@ cp_parser_template_name (cp_parser* parser,
   /* Look up the name.  */
   decl = cp_parser_lookup_name (parser, identifier,
                                none_type,
-                               /*is_template=*/false,
+                               /*is_template=*/true,
                                /*is_namespace=*/false,
                                check_dependency_p,
                                /*ambiguous_decls=*/NULL,
                                token->location);
-  decl = maybe_get_template_decl_from_type_decl (decl);
 
   /* If DECL is a template, then the name was a template-name.  */
   if (TREE_CODE (decl) == TEMPLATE_DECL)
@@ -18045,6 +18053,10 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
   if (!decl || decl == error_mark_node)
     return error_mark_node;
 
+  /* Pull out the template from an injected-class-name (or multiple).  */
+  if (is_template)
+    decl = maybe_get_template_decl_from_type_decl (decl);
+
   /* If it's a TREE_LIST, the result of the lookup was ambiguous.  */
   if (TREE_CODE (decl) == TREE_LIST)
     {
index 4ca94d6a895b46f888c39c73145dbac0babe3e38..9c82e3c19a5885d658680a88e9198388e5129f6d 100644 (file)
@@ -5451,7 +5451,7 @@ convert_template_argument (tree parm,
                                                  complain, in_decl,
                                                  args))
                {
-                 val = orig_arg;
+                 val = arg;
 
                  /* TEMPLATE_TEMPLATE_PARM node is preferred over
                     TEMPLATE_DECL.  */
@@ -5459,12 +5459,8 @@ convert_template_argument (tree parm,
                     {
                       if (DECL_TEMPLATE_TEMPLATE_PARM_P (val))
                         val = TREE_TYPE (val);
-                      else if (TREE_CODE (val) == TYPE_PACK_EXPANSION
-                               && DECL_TEMPLATE_TEMPLATE_PARM_P (arg))
-                        {
-                          val = TREE_TYPE (arg);
-                          val = make_pack_expansion (val);
-                        }
+                     if (TREE_CODE (orig_arg) == TYPE_PACK_EXPANSION)
+                       val = make_pack_expansion (val);
                     }
                }
              else
@@ -5990,15 +5986,43 @@ lookup_template_function (tree fns, tree arglist)
    TEMPLATE_DECL.  If DECL is a TYPE_DECL for current_class_type,
    or one of its enclosing classes, and that type is a template,
    return the associated TEMPLATE_DECL.  Otherwise, the original
-   DECL is returned.  */
+   DECL is returned.
+
+   Also handle the case when DECL is a TREE_LIST of ambiguous
+   injected-class-names from different bases.  */
 
 tree
 maybe_get_template_decl_from_type_decl (tree decl)
 {
+  if (decl == NULL_TREE)
+    return decl;
+
+  /* DR 176: A lookup that finds an injected-class-name (10.2
+     [class.member.lookup]) can result in an ambiguity in certain cases
+     (for example, if it is found in more than one base class). If all of
+     the injected-class-names that are found refer to specializations of
+     the same class template, and if the name is followed by a
+     template-argument-list, the reference refers to the class template
+     itself and not a specialization thereof, and is not ambiguous.  */
+  if (TREE_CODE (decl) == TREE_LIST)
+    {
+      tree t, tmpl = NULL_TREE;
+      for (t = decl; t; t = TREE_CHAIN (t))
+       {
+         tree elt = maybe_get_template_decl_from_type_decl (TREE_VALUE (t));
+         if (!tmpl)
+           tmpl = elt;
+         else if (tmpl != elt)
+           break;
+       }
+      if (tmpl && t == NULL_TREE)
+       return tmpl;
+      else
+       return decl;
+    }
+
   return (decl != NULL_TREE
-         && TREE_CODE (decl) == TYPE_DECL
-         && DECL_ARTIFICIAL (decl)
-         && CLASS_TYPE_P (TREE_TYPE (decl))
+         && DECL_SELF_REFERENCE_P (decl)
          && CLASSTYPE_TEMPLATE_INFO (TREE_TYPE (decl)))
     ? CLASSTYPE_TI_TEMPLATE (TREE_TYPE (decl)) : decl;
 }
index 3adf9e0a1abae19704fda3d8754242577b8582f9..3e9bec011fff8c9799e775d7041f6f8fa130e4a9 100644 (file)
@@ -63,7 +63,6 @@ static tree dfs_access_in_type (tree, void *);
 static access_kind access_in_type (tree, tree);
 static int protected_accessible_p (tree, tree, tree);
 static int friend_accessible_p (tree, tree, tree);
-static int template_self_reference_p (tree, tree);
 static tree dfs_get_pure_virtuals (tree, void *);
 
 \f
@@ -955,24 +954,6 @@ struct lookup_field_info {
   const char *errstr;
 };
 
-/* Within the scope of a template class, you can refer to the to the
-   current specialization with the name of the template itself.  For
-   example:
-
-     template <typename T> struct S { S* sp; }
-
-   Returns nonzero if DECL is such a declaration in a class TYPE.  */
-
-static int
-template_self_reference_p (tree type, tree decl)
-{
-  return  (CLASSTYPE_USE_TEMPLATE (type)
-          && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (type))
-          && TREE_CODE (decl) == TYPE_DECL
-          && DECL_ARTIFICIAL (decl)
-          && DECL_NAME (decl) == constructor_name (type));
-}
-
 /* Nonzero for a class member means that it is shared between all objects
    of that class.
 
@@ -1092,11 +1073,6 @@ lookup_field_r (tree binfo, void *data)
        }
     }
 
-  /* You must name a template base class with a template-id.  */
-  if (!same_type_p (type, lfi->type)
-      && template_self_reference_p (type, nval))
-    goto done;
-
   /* If the lookup already found a match, and the new value doesn't
      hide the old one, we might have an ambiguity.  */
   if (lfi->rval_binfo
index 42702ebd9d5ca286250ef9b5769fed2c3aa933e3..6b3e48cbdac05160712074e86be56c68869825f1 100644 (file)
@@ -1,3 +1,13 @@
+2009-11-16  Jason Merrill  <jason@redhat.com>
+
+       PR c++/13950
+       * g++.dg/template/injected1.C: New.
+       * g++.dg/template/inherit.C: Adjust.
+       * g++.old-deja/g++.brendan/crash56.C: Adjust.
+       * g++.old-deja/g++.pt/lookup8.C: Adjust.
+       * g++.old-deja/g++.pt/ttp22.C: Adjust.
+       * g++.old-deja/g++.pt/ttp23.C: Adjust.
+
 2009-11-16  Paolo Carlini  <paolo.carlini@oracle.com>
 
        PR c++/42055
index bc20345fa0a7c7b57cf28818149a06bbc82560fc..43af3cfc5ac622a8ee3a22ddd6b8342edb11a74a 100644 (file)
@@ -9,5 +9,5 @@ struct Z : X<int> { };
 int main()
 {
   Z z;
-  z.X::f();                     // { dg-error "template parameters" "" }
+  z.X::f();
 }
diff --git a/gcc/testsuite/g++.dg/template/injected1.C b/gcc/testsuite/g++.dg/template/injected1.C
new file mode 100644 (file)
index 0000000..81873b4
--- /dev/null
@@ -0,0 +1,33 @@
+// PR c++/13950, DR 176
+
+template <class T> struct Base { }; // { dg-error "" } candidate
+
+struct D1: Base<void>
+{
+  D1::Base* p1;
+  D1::Base<double>* p2;
+  Base *p3;
+  Base<double>* p4;
+};
+
+struct D2: Base<void>, Base<void*>
+{
+  D2::Base* p1;                        // { dg-error "" }
+  D2::Base<double>* p2;
+  Base *p3;                    // { dg-error "" }
+  Base<double>* p4;
+};
+
+template <class T>
+struct D3: Base<T> {
+  typename D3::Base* p1;
+  typename D3::template Base<double>* p2;
+};
+template struct D3<void>;
+
+template <class T>
+struct D4: Base<T>, Base<T*> {
+  typename D4::Base* p1;       // { dg-error "" }
+  typename D4::template Base<double>* p2;
+};
+template struct D4<void>;      // { dg-message "instantiated" }
index dcb89dc9e48cefb393896debbcd17f3903d0ab57..0932ca4665992c0bc36200d34029b1d936c7b27c 100644 (file)
@@ -342,7 +342,7 @@ operator>=(const SetLD<T>& a, const SetLD<T>& b)
 { return ! (a < b); }
 class String { };
 class IcaseString: public String { };
-template <> class SetLD< IcaseString >: public SetLD<    String  > {   public:  SetLD (): SetLD<    String  >() { };    SetLD (const ListD<   IcaseString  >& other): SetLD<    String  >()    { ListD<   IcaseString  >::Vix x;       for (other.first(x); 0 != x; other.next(x))     add(other(x)); };        SetLD (const  SetLD & other): SetLD<    String  >(other) { };  const    IcaseString  & operator()(const Vix& x) const  { return (   IcaseString  &) SetLD<    String  >::operator()(x); }      };      typedef SetLD<  String > SetLD_String_IcaseString_old_tmp99;    typedef SetLD< IcaseString > SetLD_String_IcaseString_new_tmp99;        
+template <> class SetLD< IcaseString >: public SetLD<    String  > {   public:  SetLD (): SetLD<    String  >() { };    SetLD (const ::ListD<   IcaseString  >& other): SetLD<    String  >()  { ::ListD<   IcaseString  >::Vix x;     for (other.first(x); 0 != x; other.next(x))     add(other(x)); };        SetLD (const  SetLD & other): SetLD<    String  >(other) { };  const    IcaseString  & operator()(const Vix& x) const  { return (   IcaseString  &) SetLD<    String  >::operator()(x); }      };      typedef SetLD<  String > SetLD_String_IcaseString_old_tmp99;    typedef SetLD< IcaseString > SetLD_String_IcaseString_new_tmp99;        
 inline int      operator== (const SetLD_String_IcaseString_new_tmp99& a,       const SetLD_String_IcaseString_new_tmp99& b) // { dg-message "operator==" }
 {
 const SetLD_String_IcaseString_old_tmp99& oa = a;
index 2c6df5583b900ec5d37386034cbb4359607063e4..1662f68c7b654d18c2f6da3c38438f68bdbf6b33 100644 (file)
@@ -11,5 +11,5 @@ class Y : public X<int>
 
 void Y::f()
 {
-  X x; // { dg-error "" } X is not a type.
+  X x;
 }
index 01f08c0dbbe7b61c0d603fd0f4d81bf1bde261a2..de3334e79e6555ed5a9215e86228003ca1e41ebb 100644 (file)
@@ -24,7 +24,7 @@ template<template<class> class DD,class EE> int C<DD,EE>::f()
 class E : C<D,int>
 {
        public:
-               int f() { return C<D,int>::f(); }
+               int f() { return C< ::D,int>::f(); }
 };
 
 int main()
index 8db7f386a0318084c55dc7dc970aaf82955c6785..051a3f33036223ed045e0dae5f2cdea5cc04f385 100644 (file)
@@ -24,7 +24,7 @@ template<template<class> class E,class D> int C<E,D>::f()
 class E : C<D,int>
 {
        public:
-               int f() { return C<D,int>::f(); }
+               int f() { return C< ::D,int>::f(); }
 };
 
 int main()
This page took 0.100609 seconds and 5 git commands to generate.