On Tue, Feb 07, 2017 at 01:44:44PM +0000, Jonathan Wakely wrote:
> On 07/02/17 14:27 +0100, Marek Polacek wrote:
> > > You could drop the namespace. Also "struct A" would be better, because
> > > otherwise fn1 is a private and thus unaccessible in fn2.
> >
> > True. So how about this extended version, which also mentions more examples
> > of what might now fail?
> >
> > Index: porting_to.html
> > ===================================================================
> > RCS file: /cvs/gcc/wwwdocs/htdocs/gcc-7/porting_to.html,v
> > retrieving revision 1.3
> > diff -u -r1.3 porting_to.html
> > --- porting_to.html 3 Feb 2017 07:55:27 -0000 1.3
> > +++ porting_to.html 7 Feb 2017 13:27:28 -0000
> > @@ -33,6 +33,68 @@
> >
> > <h2 id="cxx">C++ language issues</h2>
> >
> > +<h3 id="hypothetical-instantiation">Stricter rules when using
> > templates</h3>
> > +
> > +<p>
> > +GCC 7 no longer accepts various ill-formed code involving use of templates.
> > +The C++ standard says:
> > +</p>
> > +
> > +<p><em>
> > +14.6/8: "If a hypothetical instantiation of a template immediately
> > +following its definition would be ill-formed due to a construct that
> > +does not depend on a template parameter, the program is ill-formed; no
> > +diagnostic is required. If the interpretation of such a construct in
> > +the hypothetical instantiation is different from the interpretation of
> > +the corresponding construct in any actual instantiation of the
> > +template, the program is ill-formed; no diagnostic is required."
> > +</em></p>
> > +
> > +<p>
> > +As a consequence, the following examples are now invalid and G++ will no
> > longer
>
> I'd remove "now" since they've always been invalid, we just didn't
> diagnose them until now.
Right, removed.
> > +compile them:
> > +<pre><code>
> > +struct C;
> > +struct A {
> > + C fn1();
> > +};
> > +template <typename> class B : A {
> > + void fn2() { fn1().x; }
> > +};
> > +</code></pre>
> > +will result in
> > +<blockquote><pre>
> > +<span class="boldred">error:</span> invalid use of incomplete type
> > <b>'struct C'</b>
> > +</pre></blockquote>
> > +
> > +<pre><code>
> > +class A {
>
> Make this a struct, not a class. Otherwise the code would also be
> invalid because of an access error, which isn't relevant to the
> example.
Okay.
> > + int m_class;
>
> I suggest changing "m_class" (in both places) to something more
> generic, like "m_val" or just "x". And "m_fn1" is a funny member
> function name, "fn1" (as in the previous example) would be better.
Done. I think creduce came up with these names.
> > +};
> > +template <class> class B : A { void m_fn1(); };
>
> Unless you want to vary the examples intentionally, I'd change "<class>"
> to "<typename>" for consistency with the other two examples. The
> fewer unrelated differences between the examples the better, so users
> don't waste time wondering if the unrelated differences are
> significant to the example.
>
> > +template <class T> void B<T>::m_fn1() { foo
> > (this->m_class); }
>
> This function could be defined inline, as in the previous example.
> Whether it's defined out of the class body isn't relevant.
>
> So simply:
>
> struct A {
> int x;
> };
> template<typename> struct B : A {
> void fn1() { foo (this->x); }
> };
Donezo.
>
> > +</code></pre>
> > +will result in
> > +<blockquote><pre>
> > +<span class="boldred">error:</span> there are no arguments to <b>'foo'</b>
> > that depend on a template parameter, so a declaration of <b>'foo'</b> must
> > be available
> > +</pre></blockquote>
> > +
> > +<pre><code>
> > +class A {
>
> This can be a struct again.
>
> > + void *a;
>
> Idiomatic C++ would say "void* a" not "void *a" but you could use
> "void * a" to keep both groups of people happy ;-)
>
> > +};
> > +template <typename> class B : A {
> > + void m_fn1() { this->a[0]; }
>
> s/m_fn1/fn1/ again
Fixed.
Thanks much for the review. Looks ok now?
Index: porting_to.html
===================================================================
RCS file: /cvs/gcc/wwwdocs/htdocs/gcc-7/porting_to.html,v
retrieving revision 1.3
diff -u -r1.3 porting_to.html
--- porting_to.html 3 Feb 2017 07:55:27 -0000 1.3
+++ porting_to.html 7 Feb 2017 14:03:42 -0000
@@ -33,6 +33,69 @@
<h2 id="cxx">C++ language issues</h2>
+<h3 id="hypothetical-instantiation">Stricter rules when using templates</h3>
+
+<p>
+GCC 7 no longer accepts various ill-formed code involving use of templates.
+The C++ standard says:
+</p>
+
+<p><em>
+14.6/8: "If a hypothetical instantiation of a template immediately
+following its definition would be ill-formed due to a construct that
+does not depend on a template parameter, the program is ill-formed; no
+diagnostic is required. If the interpretation of such a construct in
+the hypothetical instantiation is different from the interpretation of
+the corresponding construct in any actual instantiation of the
+template, the program is ill-formed; no diagnostic is required."
+</em></p>
+
+<p>
+As a consequence, the following examples are invalid and G++ will no longer
+compile them:
+<pre><code>
+struct C;
+struct A {
+ C fn1();
+};
+template <typename> class B : A {
+ void fn2() { fn1().x; }
+};
+</code></pre>
+will result in
+<blockquote><pre>
+<span class="boldred">error:</span> invalid use of incomplete type <b>'struct
C'</b>
+</pre></blockquote>
+
+<pre><code>
+struct A {
+ int x;
+};
+template <typename> struct B : A {
+ void fn1() { foo (this->x); }
+};
+</code></pre>
+will result in
+<blockquote><pre>
+<span class="boldred">error:</span> there are no arguments to <b>'foo'</b>
that depend on a template parameter, so a declaration of <b>'foo'</b> must be
available
+</pre></blockquote>
+
+<pre><code>
+struct A {
+ void* a;
+};
+template <typename> class B : A {
+ void fn1() { this->a[0]; }
+};
+</code></pre>
+will result in
+<blockquote><pre>
+<span class="boldred">error:</span> <b>'void*'</b> is not a pointer-to-object
type
+</pre></blockquote>
+because there's no instantiation of that template that can be valid, it will
+always dereference a <code>void*</code>.
+</p>
+
<h3 id="conversion-op-mangling">Mangling change for conversion operators</h3>
<p>
Marek