This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: C++ PATCH for c++/13950 (DR 176)
- From: Jason Merrill <jason at redhat dot com>
- To: gcc-patches List <gcc-patches at gcc dot gnu dot org>
- Date: Thu, 19 Nov 2009 17:39:04 -0500
- Subject: Re: C++ PATCH for c++/13950 (DR 176)
- References: <4B01FD26.1010003@redhat.com>
On 11/16/2009 08:32 PM, Jason Merrill wrote:
As a result of this, some code that previously worked needs to be
adjusted by adding an explicit scope. Specifically, code that uses the
name of a base class template as a template template argument
(ttp2[23].C) or in a context which does not have access to the
injected-class-name of that base (crash56.C). It seems unfortunate that
we don't just treat it as a template if it's being used as a template
template argument, but that's what the standard says.
It seems rather gratuitous to break code that does that, and I notice
that EDG's G++ compatibility mode allows that code, suggesting that
their customers have asked for it, so I've decided to keep accepting it
with a pedwarn and suggested the change to the committee.
Tested x86_64-pc-linux-gnu, applied to trunk.
commit ee1ca09d8a7fa6ee128e32c3f81c98c4ad122650
Author: Jason Merrill <jason@redhat.com>
Date: Thu Nov 19 13:38:31 2009 -0500
DR 176 permissiveness
gcc/
* dwarf2out.c (get_context_die): Take TYPE_MAIN_VARIANT.
gcc/cp/
* class.c (build_self_reference): Call set_underlying_type.
* decl.c (check_elaborated_type_specifier): Don't complain about
injected-class-name.
(type_is_deprecated): Use TYPE_MAIN_VARIANT.
* pt.c (convert_template_argument): Handle injected-class-name used
as template template argument.
* typeck2.c (abstract_virtuals_error): Use TYPE_MAIN_VARIANT.
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 3cf15fb..38eb73f 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -6513,6 +6513,7 @@ build_self_reference (void)
DECL_CONTEXT (value) = current_class_type;
DECL_ARTIFICIAL (value) = 1;
SET_DECL_SELF_REFERENCE_P (value);
+ set_underlying_type (value);
if (processing_template_decl)
value = push_template_decl (value);
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 29e32c8..7f5a688 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -9787,6 +9787,10 @@ type_is_deprecated (tree type)
&& TREE_DEPRECATED (TYPE_NAME (type)))
return type;
+ /* Do warn about using typedefs to a deprecated class. */
+ if (TAGGED_TYPE_P (type) && type != TYPE_MAIN_VARIANT (type))
+ return type_is_deprecated (TYPE_MAIN_VARIANT (type));
+
code = TREE_CODE (type);
if (code == POINTER_TYPE || code == REFERENCE_TYPE
@@ -10608,6 +10612,7 @@ check_elaborated_type_specifier (enum tag_types tag_code,
elaborated type specifier is the implicit typedef created when
the type is declared. */
else if (!DECL_IMPLICIT_TYPEDEF_P (decl)
+ && !DECL_SELF_REFERENCE_P (decl)
&& tag_code != typename_type)
{
error ("using typedef-name %qD after %qs", decl, tag_name (tag_code));
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 9c82e3c..c3b0f0e 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -5370,6 +5370,22 @@ convert_template_argument (tree parm,
if (TREE_CODE (arg) == TYPE_PACK_EXPANSION)
arg = PACK_EXPANSION_PATTERN (arg);
+ /* Deal with an injected-class-name used as a template template arg. */
+ if (requires_tmpl_type && CLASS_TYPE_P (arg))
+ {
+ tree t = maybe_get_template_decl_from_type_decl (TYPE_NAME (arg));
+ if (TREE_CODE (t) == TEMPLATE_DECL)
+ {
+ if (complain & tf_warning_or_error)
+ pedwarn (input_location, OPT_pedantic, "injected-class-name %qD"
+ " used as template template argument", TYPE_NAME (arg));
+ else if (flag_pedantic_errors)
+ t = arg;
+
+ arg = t;
+ }
+ }
+
is_tmpl_type =
((TREE_CODE (arg) == TEMPLATE_DECL
&& TREE_CODE (DECL_TEMPLATE_RESULT (arg)) == TYPE_DECL)
diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index 6cb1152..a296caa 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -236,6 +236,7 @@ abstract_virtuals_error (tree decl, tree type)
be abstract. */
if (!CLASS_TYPE_P (type))
return 0;
+ type = TYPE_MAIN_VARIANT (type);
/* If the type is incomplete, we register it within a hash table,
so that we can check again once it is completed. This makes sense
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index 3db2092..0394114 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -19089,7 +19089,7 @@ get_context_die (tree context)
{
/* Find die that represents this context. */
if (TYPE_P (context))
- return force_type_die (context);
+ return force_type_die (TYPE_MAIN_VARIANT (context));
else
return force_decl_die (context);
}
diff --git a/gcc/testsuite/g++.dg/ext/injected-ttp.C b/gcc/testsuite/g++.dg/ext/injected-ttp.C
new file mode 100644
index 0000000..405bee8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/injected-ttp.C
@@ -0,0 +1,15 @@
+// Test for doing the right thing with injected-class-name used as template
+// type argument. This is an extension from DR 176.
+
+// { dg-options "-pedantic" }
+
+template <class T>
+struct A { };
+
+template <template <class> class TTP>
+struct B { };
+
+struct C: A<int>
+{
+ B<A> b; // { dg-warning "injected-class-name" }
+};
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/niklas01a.C b/gcc/testsuite/g++.old-deja/g++.pt/niklas01a.C
index 7fe07a2..eec11ab 100644
--- a/gcc/testsuite/g++.old-deja/g++.pt/niklas01a.C
+++ b/gcc/testsuite/g++.old-deja/g++.pt/niklas01a.C
@@ -2,7 +2,7 @@
// { dg-options "-fshow-column" }
struct A { // { dg-error "" } forward declaration
- friend struct B : A { // { dg-error "invalid use of incomplete type 'struct A'" }
+ friend struct B : A { // { dg-error "invalid use of incomplete type 'struct A" }
int x;
}; // { dg-error "class definition may not be declared a friend" "" { target *-*-* } { 5 } }
int y;
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/ttp41.C b/gcc/testsuite/g++.old-deja/g++.pt/ttp41.C
index b260961..564294e 100644
--- a/gcc/testsuite/g++.old-deja/g++.pt/ttp41.C
+++ b/gcc/testsuite/g++.old-deja/g++.pt/ttp41.C
@@ -1,4 +1,5 @@
// { dg-do compile }
+// { dg-options "" }
template<template<class> class D,class E> class C
{
public:
@@ -13,8 +14,8 @@ template<class T> class D
template<class T> int D<T>::f()
{
- C<D,D> c; // { dg-error "" }
- return c.g(); // { dg-error "" }
+ C<D,D> c;
+ return c.g();
}
int main()