[C++] Avoid weird warning about pure virtual inline being used but not defined (PR c++/92695)

Message ID 20191127234300.GE10088@tucnak
State New
Headers show
Series
  • [C++] Avoid weird warning about pure virtual inline being used but not defined (PR c++/92695)
Related show

Commit Message

Jakub Jelinek Nov. 27, 2019, 11:43 p.m.
Hi!

While working on the PR92695 bug, I've noticed a weird warning, when
the testcase contained (pointless, but not invalid) constexpr specifier on
pure virtual function.  constexpr implies DECL_DECLARED_INLINE_P and
we would note_vague_linkage_fn and later complain that the inline
function wasn't ever defined.
As can be seen in the testcase, for inline pure virtual we warn the same.
The specifiers don't make much sense, but Jonathan nor I could find anything
that would say that inline pure virtual or constexpr pure virtual is
invalid.  clang++ accepts those without warnings too.

Fixed thusly, bootstrapped/regtested on x86_64-linux and i686-linux, ok for
trunk?

2019-11-27  Jakub Jelinek  <jakub@redhat.com>

	PR c++/92695
	* decl2.c (mark_used): Don't call note_vague_linkage_fn for pure
	virtual functions, even if they are declared inline.

	* g++.dg/warn/inline3.C: New test.


	Jakub

Comments

Jason Merrill Nov. 28, 2019, 3:54 a.m. | #1
On 11/27/19 6:43 PM, Jakub Jelinek wrote:
> Hi!

> 

> While working on the PR92695 bug, I've noticed a weird warning, when

> the testcase contained (pointless, but not invalid) constexpr specifier on

> pure virtual function.  constexpr implies DECL_DECLARED_INLINE_P and

> we would note_vague_linkage_fn and later complain that the inline

> function wasn't ever defined.

> As can be seen in the testcase, for inline pure virtual we warn the same.

> The specifiers don't make much sense, but Jonathan nor I could find anything

> that would say that inline pure virtual or constexpr pure virtual is

> invalid.  clang++ accepts those without warnings too.

> 

> Fixed thusly, bootstrapped/regtested on x86_64-linux and i686-linux, ok for

> trunk?


OK.


> 2019-11-27  Jakub Jelinek  <jakub@redhat.com>

> 

> 	PR c++/92695

> 	* decl2.c (mark_used): Don't call note_vague_linkage_fn for pure

> 	virtual functions, even if they are declared inline.

> 

> 	* g++.dg/warn/inline3.C: New test.

> 

> --- gcc/cp/decl2.c.jj	2019-11-12 09:09:33.658814862 +0100

> +++ gcc/cp/decl2.c	2019-11-27 18:26:53.698018564 +0100

> @@ -5596,8 +5596,11 @@ mark_used (tree decl, tsubst_flags_t com

>   	vec_safe_push (no_linkage_decls, decl);

>       }

>   

> -  if (TREE_CODE (decl) == FUNCTION_DECL && DECL_DECLARED_INLINE_P (decl)

> -      && !DECL_INITIAL (decl) && !DECL_ARTIFICIAL (decl))

> +  if (TREE_CODE (decl) == FUNCTION_DECL

> +      && DECL_DECLARED_INLINE_P (decl)

> +      && !DECL_INITIAL (decl)

> +      && !DECL_ARTIFICIAL (decl)

> +      && !DECL_PURE_VIRTUAL_P (decl))

>       /* Remember it, so we can check it was defined.  */

>       note_vague_linkage_fn (decl);

>   

> --- gcc/testsuite/g++.dg/warn/inline3.C.jj	2019-11-27 18:13:46.685074239 +0100

> +++ gcc/testsuite/g++.dg/warn/inline3.C	2019-11-27 18:18:40.688577837 +0100

> @@ -0,0 +1,20 @@

> +struct S {

> +  inline virtual void foo () = 0;	// { dg-bogus "used but never defined" }

> +#if __cplusplus > 201703L

> +  constexpr virtual void bar () = 0;	// { dg-bogus "used but never defined" "" { target c++2a } }

> +#else

> +  inline virtual void bar () = 0;	// { dg-bogus "used but never defined" "" { target c++17_down }  }

> +#endif

> +  S () {}

> +};

> +struct T : public S {

> +  inline virtual void foo () {}

> +#if __cplusplus > 201703L

> +  constexpr virtual void bar () {}

> +#else

> +  inline virtual void bar () {}

> +#endif

> +  T () {}

> +};

> +T t;

> +void foo (S *s) { s->foo (); s->bar (); }

> 

> 	Jakub

>

Patch

--- gcc/cp/decl2.c.jj	2019-11-12 09:09:33.658814862 +0100
+++ gcc/cp/decl2.c	2019-11-27 18:26:53.698018564 +0100
@@ -5596,8 +5596,11 @@  mark_used (tree decl, tsubst_flags_t com
 	vec_safe_push (no_linkage_decls, decl);
     }
 
-  if (TREE_CODE (decl) == FUNCTION_DECL && DECL_DECLARED_INLINE_P (decl)
-      && !DECL_INITIAL (decl) && !DECL_ARTIFICIAL (decl))
+  if (TREE_CODE (decl) == FUNCTION_DECL
+      && DECL_DECLARED_INLINE_P (decl)
+      && !DECL_INITIAL (decl)
+      && !DECL_ARTIFICIAL (decl)
+      && !DECL_PURE_VIRTUAL_P (decl))
     /* Remember it, so we can check it was defined.  */
     note_vague_linkage_fn (decl);
 
--- gcc/testsuite/g++.dg/warn/inline3.C.jj	2019-11-27 18:13:46.685074239 +0100
+++ gcc/testsuite/g++.dg/warn/inline3.C	2019-11-27 18:18:40.688577837 +0100
@@ -0,0 +1,20 @@ 
+struct S {
+  inline virtual void foo () = 0;	// { dg-bogus "used but never defined" }
+#if __cplusplus > 201703L
+  constexpr virtual void bar () = 0;	// { dg-bogus "used but never defined" "" { target c++2a } }
+#else
+  inline virtual void bar () = 0;	// { dg-bogus "used but never defined" "" { target c++17_down }  }
+#endif
+  S () {}
+};
+struct T : public S {
+  inline virtual void foo () {}
+#if __cplusplus > 201703L
+  constexpr virtual void bar () {}
+#else
+  inline virtual void bar () {}
+#endif
+  T () {}
+};
+T t;
+void foo (S *s) { s->foo (); s->bar (); }