On 05/01/2017 02:38 AM, Volker Reichelt wrote:
Hi,
catching exceptions by value is a bad thing, as it may cause slicing, i.e.
a) a superfluous copy
b) which is only partial.
See also
https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#e15-catch-exceptions-from-a-hierarchy-by-reference
To warn the user about catch handlers of non-reference type,
the following patch adds a new C++/ObjC++ warning option "-Wcatch-value".
I think the problems related to catching exceptions by value
apply to (a subset of) class types but not so much to fundamental
types. I would expect indiscriminately warning on every type to
be overly restrictive.
The Enforcement section of the C++ guideline suggests to
Flag by-value exceptions if their types are part of a hierarchy
(could require whole-program analysis to be perfect).
The corresponding CERT C++ Coding Standard guideline offers
a similar suggestion here:
https://www.securecoding.cert.org/confluence/x/TAD5CQ
so I would suggest to model the warning on that approach (within
limits of a single translation unit, of course). I.e., warn only
for catching by value objects of non-trivial types, or perhaps even
only polymorphic types?
Martin
Bootstrapped and regtested on x86_64-pc-linux-gnu.
OK for trunk?
Regards,
Volker
2017-05-01 Volker Reichelt <v.reich...@netcologne.de>
* doc/invoke.texi (-Wcatch-value): Document new warning option.
Index: gcc/doc/invoke.texi
===================================================================
--- gcc/doc/invoke.texi (revision 247416)
+++ gcc/doc/invoke.texi (working copy)
@@ -265,7 +265,7 @@
-Wno-builtin-declaration-mismatch @gol
-Wno-builtin-macro-redefined -Wc90-c99-compat -Wc99-c11-compat @gol
-Wc++-compat -Wc++11-compat -Wc++14-compat -Wcast-align -Wcast-qual @gol
--Wchar-subscripts -Wchkp -Wclobbered -Wcomment @gol
+-Wchar-subscripts -Wchkp -Wcatch-value -Wclobbered -Wcomment @gol
-Wconditionally-supported @gol
-Wconversion -Wcoverage-mismatch -Wno-cpp -Wdangling-else -Wdate-time @gol
-Wdelete-incomplete @gol
@@ -5827,6 +5827,11 @@
literals to @code{char *}. This warning is enabled by default for C++
programs.
+@item -Wcatch-value @r{(C++ and Objective-C++ only)}
+@opindex Wcatch-value
+@opindex Wno-catch-value
+Warn about catch handler of non-reference type.
+
@item -Wclobbered
@opindex Wclobbered
@opindex Wno-clobbered
===================================================================
2017-05-01 Volker Reichelt <v.reich...@netcologne.de>
* c.opt (Wcatch-value): New C++ warning flag.
Index: gcc/c-family/c.opt
===================================================================
--- gcc/c-family/c.opt (revision 247416)
+++ gcc/c-family/c.opt (working copy)
@@ -388,6 +388,10 @@
C ObjC C++ ObjC++ Var(warn_cast_qual) Warning
Warn about casts which discard qualifiers.
+Wcatch-value
+C++ ObjC++ Var(warn_catch_value) Warning
+Warn about catch handlers of non-reference type.
+
Wchar-subscripts
C ObjC C++ ObjC++ Var(warn_char_subscripts) Warning LangEnabledBy(C ObjC C++
ObjC++,Wall)
Warn about subscripts whose type is \"char\".
===================================================================
2017-05-01 Volker Reichelt <v.reich...@netcologne.de>
* semantics.c (finish_handler_parms): Warn about non-reference type
catch handlers.
Index: gcc/cp/semantics.c
===================================================================
--- gcc/cp/semantics.c (revision 247416)
+++ gcc/cp/semantics.c (working copy)
@@ -1321,7 +1321,15 @@
}
}
else
- type = expand_start_catch_block (decl);
+ {
+ type = expand_start_catch_block (decl);
+ if (warn_catch_value
+ && type != NULL_TREE
+ && type != error_mark_node
+ && TREE_CODE (TREE_TYPE (decl)) != REFERENCE_TYPE)
+ warning (OPT_Wcatch_value,
+ "catching non-reference type %qT", TREE_TYPE (decl));
+ }
HANDLER_TYPE (handler) = type;
}
===================================================================
2017-05-01 Volker Reichelt <v.reich...@netcologne.de>
* g++.dg/warn/Wcatch-value-1.C: New test.
Index: gcc/testsuite/g++.dg/warn/Wcatch-value-1.C
===================================================================
--- gcc/testsuite/g++.dg/warn/Wcatch-value-1.C 2017-05-01
+++ gcc/testsuite/g++.dg/warn/Wcatch-value-1.C 2017-05-01
@@ -0,0 +1,45 @@
+// { dg-options "-Wcatch-value" }
+
+struct A {};
+struct B {};
+struct C {};
+
+void foo()
+{
+ try {}
+ catch (int) {} // { dg-warning "catching non-reference type" }
+ catch (double*) {} // { dg-warning "catching non-reference type" }
+ catch (float&) {}
+ catch (A) {} // { dg-warning "catching non-reference type" }
+ catch (A[2]) {} // { dg-warning "catching non-reference type" }
+ catch (B*) {} // { dg-warning "catching non-reference type" }
+ catch (B&) {}
+ catch (const C&) {}
+}
+
+template<typename T> void foo1()
+{
+ try {}
+ catch (T) {}
+}
+
+void bar1()
+{
+ foo1<int&>();
+ foo1<const A&>();
+}
+
+template<typename T> void foo2()
+{
+ try {}
+ catch (T) {} // { dg-warning "catching non-reference type" }
+
+ try {}
+ catch (T&) {}
+}
+
+void bar2()
+{
+ foo2<int*>(); // { dg-message "required" }
+ foo2<A>(); // { dg-message "required" }
+}
===================================================================