aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorVolker Reichelt <v.reichelt@netcologne.de>2017-05-25 17:05:07 +0000
committerVolker Reichelt <reichelt@gcc.gnu.org>2017-05-25 17:05:07 +0000
commit63dbcd13e93578e21e0717d4990c1701d6957e3e (patch)
tree33570c2d557c1068f7b7f286e8a8d7adf1becc24 /gcc
parent932f48ac85f5111b1f3666b2c15718db2d10bcbf (diff)
downloadgcc-63dbcd13e93578e21e0717d4990c1701d6957e3e.zip
gcc-63dbcd13e93578e21e0717d4990c1701d6957e3e.tar.gz
gcc-63dbcd13e93578e21e0717d4990c1701d6957e3e.tar.bz2
invoke.texi (-Wcatch-value=): Document new warning option.
* doc/invoke.texi (-Wcatch-value=): Document new warning option. * c.opt (Wcatch-value=): New C++ warning flag. * semantics.c (finish_handler_parms): Warn about non-reference * type catch handlers. * g++.dg/warn/Wcatch-value-1.C: New test. * g++.dg/warn/Wcatch-value-2.C: New test. * g++.dg/warn/Wcatch-value-3.C: New test. From-SVN: r248466
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog4
-rw-r--r--gcc/c-family/ChangeLog4
-rw-r--r--gcc/c-family/c.opt4
-rw-r--r--gcc/cp/ChangeLog5
-rw-r--r--gcc/cp/semantics.c23
-rw-r--r--gcc/doc/invoke.texi10
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/g++.dg/warn/Wcatch-value-1.C64
-rw-r--r--gcc/testsuite/g++.dg/warn/Wcatch-value-2.C64
-rw-r--r--gcc/testsuite/g++.dg/warn/Wcatch-value-3.C64
10 files changed, 246 insertions, 2 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 5929235..3d14b4c 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,7 @@
+2017-05-25 Volker Reichelt <v.reichelt@netcologne.de>
+
+ * doc/invoke.texi (-Wcatch-value=): Document new warning option.
+
2017-05-25 Nathan Sidwell <nathan@acm.org>
* doc/invoke.texi (--enable-languages): Update documentation.
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog
index c8fff24..818d39b 100644
--- a/gcc/c-family/ChangeLog
+++ b/gcc/c-family/ChangeLog
@@ -1,3 +1,7 @@
+2017-05-25 Volker Reichelt <v.reichelt@netcologne.de>
+
+ * c.opt (Wcatch-value=): New C++ warning flag.
+
2017-05-24 Nathan Sidwell <nathan@acm.org>
* c=common.c (field_decl_cmp, resort_field_decl_cmp): Adjust T
diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index 9ad2f6e..648e0ad 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -388,6 +388,10 @@ Wcast-qual
C ObjC C++ ObjC++ Var(warn_cast_qual) Warning
Warn about casts which discard qualifiers.
+Wcatch-value=
+C++ ObjC++ Var(warn_catch_value) Warning Joined RejectNegative UInteger
+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\".
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index f2df2b6..6d71bd6 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,8 @@
+2017-05-25 Volker Reichelt <v.reichelt@netcologne.de>
+
+ * semantics.c (finish_handler_parms): Warn about non-reference type
+ catch handlers.
+
2017-05-25 Nathan Sidwell <nathan@acm.org>
Reimplement unqualified namespace lookup.
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 1ba961e..df83d23 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -1323,7 +1323,28 @@ finish_handler_parms (tree decl, tree handler)
}
}
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)
+ {
+ tree orig_type = TREE_TYPE (decl);
+ if (CLASS_TYPE_P (orig_type))
+ {
+ if (TYPE_POLYMORPHIC_P (orig_type))
+ warning (OPT_Wcatch_value_,
+ "catching polymorphic type %q#T by value", orig_type);
+ else if (warn_catch_value > 1)
+ warning (OPT_Wcatch_value_,
+ "catching type %q#T by value", orig_type);
+ }
+ else if (warn_catch_value > 2)
+ warning (OPT_Wcatch_value_,
+ "catching non-reference type %q#T", orig_type);
+ }
+ }
HANDLER_TYPE (handler) = type;
}
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index a65e78f..1b40c51 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -265,7 +265,7 @@ Objective-C and Objective-C++ Dialects}.
-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=@var{n} -Wclobbered -Wcomment @gol
-Wconditionally-supported @gol
-Wconversion -Wcoverage-mismatch -Wno-cpp -Wdangling-else -Wdate-time @gol
-Wdelete-incomplete @gol
@@ -5834,6 +5834,14 @@ When compiling C++, warn about the deprecated conversion from string
literals to @code{char *}. This warning is enabled by default for C++
programs.
+@item -Wcatch-value=@var{n} @r{(C++ and Objective-C++ only)}
+@opindex Wcatch-value
+Warn about catch handlers that do not catch via reference.
+With @option{-Wcatch-value=1} warn about polymorphic class types that
+are caught by value. With @option{-Wcatch-value=2} warn about all class
+types that are caught by value. With @option{-Wcatch-value=3} warn about
+all types that are not caught by reference.
+
@item -Wclobbered
@opindex Wclobbered
@opindex Wno-clobbered
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 33b1cc4..9df0539 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2017-05-25 Volker Reichelt <v.reichelt@netcologne.de>
+
+ * g++.dg/warn/Wcatch-value-1.C: New test.
+ * g++.dg/warn/Wcatch-value-2.C: New test.
+ * g++.dg/warn/Wcatch-value-3.C: New test.
+
2017-05-25 Nathan Sidwell <nathan@acm.org>
* g++.dg/lookup/using17.C: Adjust diagnostics.
diff --git a/gcc/testsuite/g++.dg/warn/Wcatch-value-1.C b/gcc/testsuite/g++.dg/warn/Wcatch-value-1.C
new file mode 100644
index 0000000..94ee934
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wcatch-value-1.C
@@ -0,0 +1,64 @@
+// { dg-options "-Wcatch-value=1" }
+
+struct A { virtual ~A() {} };
+struct B : A {};
+struct C {};
+struct D : C {};
+
+void foo()
+{
+ try {}
+ catch (D) {}
+ catch (C) {}
+ catch (B) {} // { dg-warning "catching polymorphic type" }
+ catch (A) {} // { dg-warning "catching polymorphic type" }
+ catch (A*) {}
+ catch (int) {}
+
+ try {}
+ catch (D&) {}
+ catch (C&) {}
+ catch (B&) {}
+ catch (A&) {}
+ catch (A*) {}
+ catch (int&) {}
+}
+
+template<typename T> void foo1()
+{
+ try {}
+ catch (T) {} // { dg-warning "catching polymorphic type" }
+}
+
+template<typename T> void foo2()
+{
+ try {}
+ catch (T*) {}
+
+ try {}
+ catch (T&) {}
+
+ try {}
+ catch (const T&) {}
+}
+
+void bar()
+{
+ foo1<int&>();
+ foo1<const A&>();
+ foo1<B&>();
+ foo1<const C&>();
+ foo1<D&>();
+
+ foo1<int>();
+ foo1<A>(); // { dg-message "required" }
+ foo1<B>(); // { dg-message "required" }
+ foo1<C>();
+ foo1<D>();
+
+ foo2<int>();
+ foo2<A>();
+ foo2<B>();
+ foo2<C>();
+ foo2<D>();
+}
diff --git a/gcc/testsuite/g++.dg/warn/Wcatch-value-2.C b/gcc/testsuite/g++.dg/warn/Wcatch-value-2.C
new file mode 100644
index 0000000..1bcf405
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wcatch-value-2.C
@@ -0,0 +1,64 @@
+// { dg-options "-Wcatch-value=2" }
+
+struct A { virtual ~A() {} };
+struct B : A {};
+struct C {};
+struct D : C {};
+
+void foo()
+{
+ try {}
+ catch (D) {} // { dg-warning "catching type" }
+ catch (C) {} // { dg-warning "catching type" }
+ catch (B) {} // { dg-warning "catching polymorphic type" }
+ catch (A) {} // { dg-warning "catching polymorphic type" }
+ catch (A*) {}
+ catch (int) {}
+
+ try {}
+ catch (D&) {}
+ catch (C&) {}
+ catch (B&) {}
+ catch (A&) {}
+ catch (A*) {}
+ catch (int&) {}
+}
+
+template<typename T> void foo1()
+{
+ try {}
+ catch (T) {} // { dg-warning "catching" }
+}
+
+template<typename T> void foo2()
+{
+ try {}
+ catch (T*) {}
+
+ try {}
+ catch (T&) {}
+
+ try {}
+ catch (const T&) {}
+}
+
+void bar()
+{
+ foo1<int&>();
+ foo1<const A&>();
+ foo1<B&>();
+ foo1<const C&>();
+ foo1<D&>();
+
+ foo1<int>();
+ foo1<A>(); // { dg-message "required" }
+ foo1<B>(); // { dg-message "required" }
+ foo1<C>(); // { dg-message "required" }
+ foo1<D>(); // { dg-message "required" }
+
+ foo2<int>();
+ foo2<A>();
+ foo2<B>();
+ foo2<C>();
+ foo2<D>();
+}
diff --git a/gcc/testsuite/g++.dg/warn/Wcatch-value-3.C b/gcc/testsuite/g++.dg/warn/Wcatch-value-3.C
new file mode 100644
index 0000000..88ae698
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wcatch-value-3.C
@@ -0,0 +1,64 @@
+// { dg-options "-Wcatch-value=3" }
+
+struct A { virtual ~A() {} };
+struct B : A {};
+struct C {};
+struct D : C {};
+
+void foo()
+{
+ try {}
+ catch (D) {} // { dg-warning "catching type" }
+ catch (C) {} // { dg-warning "catching type" }
+ catch (B) {} // { dg-warning "catching polymorphic type" }
+ catch (A) {} // { dg-warning "catching polymorphic type" }
+ catch (A*) {} // { dg-warning "catching non-reference type" }
+ catch (int) {} // { dg-warning "catching non-reference type" }
+
+ try {}
+ catch (D&) {}
+ catch (C&) {}
+ catch (B&) {}
+ catch (A&) {}
+ catch (A*) {} // { dg-warning "catching non-reference type" }
+ catch (int&) {}
+}
+
+template<typename T> void foo1()
+{
+ try {}
+ catch (T) {} // { dg-warning "catching" }
+}
+
+template<typename T> void foo2()
+{
+ try {}
+ catch (T*) {} // { dg-warning "catching non-reference type" }
+
+ try {}
+ catch (T&) {}
+
+ try {}
+ catch (const T&) {}
+}
+
+void bar()
+{
+ foo1<int&>();
+ foo1<const A&>();
+ foo1<B&>();
+ foo1<const C&>();
+ foo1<D&>();
+
+ foo1<int>(); // { dg-message "required" }
+ foo1<A>(); // { dg-message "required" }
+ foo1<B>(); // { dg-message "required" }
+ foo1<C>(); // { dg-message "required" }
+ foo1<D>(); // { dg-message "required" }
+
+ foo2<int>(); // { dg-message "required" }
+ foo2<A>(); // { dg-message "required" }
+ foo2<B>(); // { dg-message "required" }
+ foo2<C>(); // { dg-message "required" }
+ foo2<D>(); // { dg-message "required" }
+}