C++ PATCH to add -Wclass-conversion
Marek Polacek
polacek@redhat.com
Wed Sep 19 20:32:00 GMT 2018
On Wed, Sep 19, 2018 at 04:14:25PM -0400, Jason Merrill wrote:
> On Wed, Sep 19, 2018 at 3:44 PM, Marek Polacek <polacek@redhat.com> wrote:
> > On Wed, Sep 19, 2018 at 09:40:05PM +0200, Florian Weimer wrote:
> >> Marek Polacek <polacek@redhat.com> writes:
> >>
> >> > +@item -Wno-class-conversion @r{(C++ and Objective-C++ only)}
> >> > +@opindex Wno-class-conversion
> >> > +@opindex Wclass-conversion
> >> > +Disable the warning about user-defined conversions converting a class to
> >> > +the wrong type, such as having a conversion function converting an
> >> > +object to the same type, to a base class of that type, or to void.
> >> > @end table
> >>
> >> I'm not sure if âthe wrong typeâ is correct in this context because
> >> there is no single wrong type here.
> >
> > Maybe "to *a* wrong type" then.
> >
> >> What's the actual problem? That the user-defined conversion operator
> >> will never be called?
> >
> > That such a conversion function will never be called, yes.
>
> And that's what the documentation should say, rather than the vague "wrong".
How about this then?
2018-09-19 Marek Polacek <polacek@redhat.com>
Add -Wclass-conversion.
* c.opt (Wclass-conversion): New.
* decl.c (grok_op_properties): Change a warning from -Wconversion to
-Wclass-conversion. Make it print the types.
* doc/invoke.texi: Document -Wclass-conversion.
* g++.dg/conversion/op4.C: Add dg-warning.
* g++.dg/warn/Wclass-conversion1.C: New test.
* g++.dg/warn/Wclass-conversion2.C: New test.
* g++.dg/warn/Wconversion5.C: Remove file.
* g++.dg/warn/conversion-function-1.C: Use -Wno-class-converison.
* g++.old-deja/g++.bugs/900215_01.C: Adjust dg-warning.
* g++.old-deja/g++.jason/conversion5.C: Likewise.
diff --git gcc/c-family/c.opt gcc/c-family/c.opt
index 092ec940d86..43d1d27ac00 100644
--- gcc/c-family/c.opt
+++ gcc/c-family/c.opt
@@ -850,6 +850,10 @@ Wnon-template-friend
C++ ObjC++ Var(warn_nontemplate_friend) Init(1) Warning
Warn when non-templatized friend functions are declared within a template.
+Wclass-conversion
+C++ ObjC++ Var(warn_class_conversion) Init(1) Warning
+Warn when a conversion function will never be called due to the type it converts to.
+
Wclass-memaccess
C++ ObjC++ Var(warn_class_memaccess) Warning LangEnabledBy(C++ ObjC++, Wall)
Warn for unsafe raw memory writes to objects of class types.
diff --git gcc/cp/decl.c gcc/cp/decl.c
index 503b433cbd1..2d9d56ef6e1 100644
--- gcc/cp/decl.c
+++ gcc/cp/decl.c
@@ -13544,7 +13544,7 @@ grok_op_properties (tree decl, bool complain)
/* Warn about conversion operators that will never be used. */
if (IDENTIFIER_CONV_OP_P (name)
&& ! DECL_TEMPLATE_INFO (decl)
- && warn_conversion)
+ && warn_class_conversion)
{
tree t = TREE_TYPE (name);
int ref = TYPE_REF_P (t);
@@ -13553,27 +13553,29 @@ grok_op_properties (tree decl, bool complain)
t = TYPE_MAIN_VARIANT (TREE_TYPE (t));
if (VOID_TYPE_P (t))
- warning_at (loc, OPT_Wconversion, "conversion to void "
- "will never use a type conversion operator");
+ warning_at (loc, OPT_Wclass_conversion, "converting %qT to %<void%> "
+ "will never use a type conversion operator", class_type);
else if (class_type)
{
if (same_type_ignoring_top_level_qualifiers_p (t, class_type))
- warning_at (loc, OPT_Wconversion,
+ warning_at (loc, OPT_Wclass_conversion,
ref
- ? G_("conversion to a reference to the same type "
+ ? G_("converting %qT to a reference to the same type "
"will never use a type conversion operator")
- : G_("conversion to the same type "
- "will never use a type conversion operator"));
+ : G_("converting %qT to the same type "
+ "will never use a type conversion operator"),
+ class_type);
/* Don't force t to be complete here. */
else if (MAYBE_CLASS_TYPE_P (t)
&& COMPLETE_TYPE_P (t)
&& DERIVED_FROM_P (t, class_type))
- warning_at (loc, OPT_Wconversion,
+ warning_at (loc, OPT_Wclass_conversion,
ref
- ? G_("conversion to a reference to a base class "
- "will never use a type conversion operator")
- : G_("conversion to a base class "
- "will never use a type conversion operator"));
+ ? G_("converting %qT to a reference to a base class "
+ "%qT will never use a type conversion operator")
+ : G_("converting %qT to a base class %qT "
+ "will never use a type conversion operator"),
+ class_type, t);
}
}
diff --git gcc/doc/invoke.texi gcc/doc/invoke.texi
index 685c211e176..aab5fcec35a 100644
--- gcc/doc/invoke.texi
+++ gcc/doc/invoke.texi
@@ -237,6 +237,7 @@ in the following sections.
-Weffc++ -Wstrict-null-sentinel -Wtemplates @gol
-Wno-non-template-friend -Wold-style-cast @gol
-Woverloaded-virtual -Wno-pmf-conversions @gol
+-Wno-class-conversion -Wno-terminate @gol
-Wsign-promo -Wvirtual-inheritance}
@item Objective-C and Objective-C++ Language Options
@@ -3367,6 +3368,13 @@ use the STL. One may also use using directives and qualified names.
@opindex Wno-terminate
Disable the warning about a throw-expression that will immediately
result in a call to @code{terminate}.
+
+@item -Wno-class-conversion @r{(C++ and Objective-C++ only)}
+@opindex Wno-class-conversion
+@opindex Wclass-conversion
+Disable the warning about the case when a conversion function converts an
+object to the same type, to a base class of that type, or to void; such
+a conversion function will never be called.
@end table
@node Objective-C and Objective-C++ Dialect Options
diff --git gcc/testsuite/g++.dg/conversion/op4.C gcc/testsuite/g++.dg/conversion/op4.C
index cb99a380b43..3fb850cb825 100644
--- gcc/testsuite/g++.dg/conversion/op4.C
+++ gcc/testsuite/g++.dg/conversion/op4.C
@@ -4,7 +4,7 @@
struct X {
int x;
X (int i = 0) : x (i) {}
- operator X& (void) const {
+ operator X& (void) const { // { dg-warning "will never use" }
return *(new X);
}
};
diff --git gcc/testsuite/g++.dg/warn/Wclass-conversion1.C gcc/testsuite/g++.dg/warn/Wclass-conversion1.C
index e69de29bb2d..2599a53dbeb 100644
--- gcc/testsuite/g++.dg/warn/Wclass-conversion1.C
+++ gcc/testsuite/g++.dg/warn/Wclass-conversion1.C
@@ -0,0 +1,19 @@
+// PR c++/87357
+// { dg-do compile }
+
+struct B { };
+
+struct X : public B {
+ operator X(); // { dg-warning "3:converting .X. to the same type will never use a type conversion operator" }
+ operator X&(); // { dg-warning "3:converting .X. to a reference to the same type will never use a type conversion operator" }
+ operator X() const; // { dg-warning "3:converting .X. to the same type will never use a type conversion operator" }
+ operator const X(); // { dg-warning "3:converting .X. to the same type will never use a type conversion operator" }
+
+ operator B(); // { dg-warning "3:converting .X. to a base class .B. will never use a type conversion operator" }
+ operator B&(); // { dg-warning "3:converting .X. to a reference to a base class .B. will never use a type conversion operator" }
+ operator B() const; // { dg-warning "3:converting .X. to a base class .B. will never use a type conversion operator" }
+ operator const B(); // { dg-warning "3:converting .X. to a base class .const B. will never use a type conversion operator" }
+
+ operator void(); // { dg-warning "3:converting .X. to .void. will never use a type conversion operator" }
+ operator void() const; // { dg-warning "3:converting .X. to .void. will never use a type conversion operator" }
+};
diff --git gcc/testsuite/g++.dg/warn/Wclass-conversion2.C gcc/testsuite/g++.dg/warn/Wclass-conversion2.C
index e69de29bb2d..b6919f0bfea 100644
--- gcc/testsuite/g++.dg/warn/Wclass-conversion2.C
+++ gcc/testsuite/g++.dg/warn/Wclass-conversion2.C
@@ -0,0 +1,20 @@
+// PR c++/87357
+// { dg-do compile }
+// { dg-options "-Wno-class-conversion" }
+
+struct B { };
+
+struct X : public B {
+ operator X(); // { dg-bogus "3:converting .X. to the same type will never use a type conversion operator" }
+ operator X&(); // { dg-bogus "3:converting .X. to a reference to the same type will never use a type conversion operator" }
+ operator X() const; // { dg-bogus "3:converting .X. to the same type will never use a type conversion operator" }
+ operator const X(); // { dg-bogus "3:converting .X. to the same type will never use a type conversion operator" }
+
+ operator B(); // { dg-bogus "3:converting .X. to a base class .B. will never use a type conversion operator" }
+ operator B&(); // { dg-bogus "3:converting .X. to a reference to a base class .B. will never use a type conversion operator" }
+ operator B() const; // { dg-bogus "3:converting .X. to a base class .B. will never use a type conversion operator" }
+ operator const B(); // { dg-bogus "3:converting .X. to a base class .const B. will never use a type conversion operator" }
+
+ operator void(); // { dg-bogus "3:converting .X. to .void. will never use a type conversion operator" }
+ operator void() const; // { dg-bogus "3:converting .X. to .void. will never use a type conversion operator" }
+};
diff --git gcc/testsuite/g++.dg/warn/conversion-function-1.C gcc/testsuite/g++.dg/warn/conversion-function-1.C
index 878011cf328..890719b3477 100644
--- gcc/testsuite/g++.dg/warn/conversion-function-1.C
+++ gcc/testsuite/g++.dg/warn/conversion-function-1.C
@@ -1,6 +1,6 @@
// Copyright (C) 2003 Free Software Foundation
// Contributed by Gabriel Dos Reis <gdr@integrable-solutions.net>
-// { dg-options "-Wno-conversion" }
+// { dg-options "-Wno-class-conversion" }
struct A {
operator A&();
diff --git gcc/testsuite/g++.old-deja/g++.bugs/900215_01.C gcc/testsuite/g++.old-deja/g++.bugs/900215_01.C
index 0cd9b321e3e..fd075685cec 100644
--- gcc/testsuite/g++.old-deja/g++.bugs/900215_01.C
+++ gcc/testsuite/g++.old-deja/g++.bugs/900215_01.C
@@ -24,7 +24,7 @@
struct struct0 {
- operator void (); // { dg-warning "3:conversion to void will never use a type conversion operator" }
+ operator void (); // { dg-warning "3:converting .struct0. to .void. will never use a type conversion operator" }
};
int exit_status = 1;
diff --git gcc/testsuite/g++.old-deja/g++.jason/conversion5.C gcc/testsuite/g++.old-deja/g++.jason/conversion5.C
index a9531a6d209..7f04de48378 100644
--- gcc/testsuite/g++.old-deja/g++.jason/conversion5.C
+++ gcc/testsuite/g++.old-deja/g++.jason/conversion5.C
@@ -3,7 +3,7 @@
struct A { };
struct B: public A {
A a;
- operator A () { return a; } // { dg-warning "3:conversion to a base class will never use a type conversion operator" }
+ operator A () { return a; } // { dg-warning "3:converting .B. to a base class .A. will never use a type conversion operator" }
};
void f (const A&);
void g()
More information about the Gcc-patches
mailing list