invoke.texi (-Wcatch-value=): Document new warning option.
authorVolker Reichelt <v.reichelt@netcologne.de>
Thu, 25 May 2017 17:05:07 +0000 (17:05 +0000)
committerVolker Reichelt <reichelt@gcc.gnu.org>
Thu, 25 May 2017 17:05:07 +0000 (17:05 +0000)
        * 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

gcc/ChangeLog
gcc/c-family/ChangeLog
gcc/c-family/c.opt
gcc/cp/ChangeLog
gcc/cp/semantics.c
gcc/doc/invoke.texi
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/warn/Wcatch-value-1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/warn/Wcatch-value-2.C [new file with mode: 0644]
gcc/testsuite/g++.dg/warn/Wcatch-value-3.C [new file with mode: 0644]

index 59292354056be87b1da52997d7feae9c37ae5bfe..3d14b4c8ae6bdf59bab0c865520fa808e8916ce5 100644 (file)
@@ -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.
index c8fff24e3752edcd52eb2d6cf53e2180ecc15aad..818d39ba8024f09a8b4befc6a50d217744e49d15 100644 (file)
@@ -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
index 9ad2f6e1fcc54b48cead4c9f2609ac04a233d1cc..648e0add9c64b45010d4206cf6304b8074695364 100644 (file)
@@ -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\".
index f2df2b62611b4c511e2aca7e9a75245d5bdab782..6d71bd66b38776ad9cc5092a6225b10e4e1e7409 100644 (file)
@@ -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.
index 1ba961ec226c2bc94e7b496b499905a619c1a0c6..df83d23c71351e8f149f7531a10f5ca21eff5ba9 100644 (file)
@@ -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;
 }
 
index a65e78f4376fff826de4d95b5714f361d33162ab..1b40c51cc807e5bdf462ab9a522fa1c7d4735100 100644 (file)
@@ -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
index 33b1cc47f8c778ba96099d5d7c9cf1a2f1249ea6..9df0539a14534aa45042d95a5e8e6c150b823449 100644 (file)
@@ -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 (file)
index 0000000..94ee934
--- /dev/null
@@ -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 (file)
index 0000000..1bcf405
--- /dev/null
@@ -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 (file)
index 0000000..88ae698
--- /dev/null
@@ -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" }
+}