re PR c++/77496 (ICE in instantiate_type, at cp/class.c:8270)
authorBernd Edlinger <bernd.edlinger@hotmail.de>
Mon, 12 Sep 2016 20:18:16 +0000 (20:18 +0000)
committerBernd Edlinger <edlinger@gcc.gnu.org>
Mon, 12 Sep 2016 20:18:16 +0000 (20:18 +0000)
gcc/c-family:
2016-09-12  Bernd Edlinger  <bernd.edlinger@hotmail.de>

        PR c++/77496
        * c-common.c (warn_for_omitted_condop): Also warn for boolean data.

gcc/c:
2016-09-12  Bernd Edlinger  <bernd.edlinger@hotmail.de>

        PR c++/77496
        * c-parser.c (c_parser_conditional_expression): Pass the rightmost
        COMPOUND_EXPR to warn_for_omitted_condop.

gcc/cp:
2016-09-12  Bernd Edlinger  <bernd.edlinger@hotmail.de>

        PR c++/77496
        * call.c (build_conditional_expr_1): Call warn_for_omitted_condop.
        * class.c (instantiate_type): Look through the SAVE_EXPR.

gcc/testsuite:
2016-09-12  Bernd Edlinger  <bernd.edlinger@hotmail.de>

        PR c++/77496
        * c-c++-common/warn-ommitted-condop.c: Add more test cases.
        * g++.dg/ext/pr77496.C: New test.
        * g++.dg/warn/pr77496.C: New test.

From-SVN: r240098

gcc/c-family/ChangeLog
gcc/c-family/c-common.c
gcc/c/ChangeLog
gcc/c/c-parser.c
gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/class.c
gcc/testsuite/ChangeLog
gcc/testsuite/c-c++-common/warn-ommitted-condop.c
gcc/testsuite/g++.dg/ext/pr77496.C [new file with mode: 0644]
gcc/testsuite/g++.dg/warn/pr77496.C [new file with mode: 0644]

index 8ba99f2..71c5e50 100644 (file)
@@ -1,3 +1,8 @@
+2016-09-12  Bernd Edlinger  <bernd.edlinger@hotmail.de>
+
+       PR c++/77496
+       * c-common.c (warn_for_omitted_condop): Also warn for boolean data.
+
 2016-09-12  David Malcolm  <dmalcolm@redhat.com>
 
        PR c/72858
index 16f6548..2215e29 100644 (file)
@@ -10602,17 +10602,21 @@ fold_offsetof (tree expr)
   return convert (size_type_node, fold_offsetof_1 (expr));
 }
 
-/* Warn for A ?: C expressions (with B omitted) where A is a boolean 
+/* Warn for A ?: C expressions (with B omitted) where A is a boolean
    expression, because B will always be true. */
 
 void
-warn_for_omitted_condop (location_t location, tree cond) 
-{ 
-  if (truth_value_p (TREE_CODE (cond))) 
-      warning_at (location, OPT_Wparentheses, 
+warn_for_omitted_condop (location_t location, tree cond)
+{
+  /* In C++ template declarations it can happen that the type is dependent
+     and not yet known, thus TREE_TYPE (cond) == NULL_TREE.  */
+  if (truth_value_p (TREE_CODE (cond))
+      || (TREE_TYPE (cond) != NULL_TREE
+         && TREE_CODE (TREE_TYPE (cond)) == BOOLEAN_TYPE))
+      warning_at (location, OPT_Wparentheses,
                "the omitted middle operand in ?: will always be %<true%>, "
                "suggest explicit middle operand");
-} 
+}
 
 /* Give an error for storing into ARG, which is 'const'.  USE indicates
    how ARG was being used.  */
index a647263..b474de1 100644 (file)
@@ -1,3 +1,9 @@
+2016-09-12  Bernd Edlinger  <bernd.edlinger@hotmail.de>
+
+       PR c++/77496
+       * c-parser.c (c_parser_conditional_expression): Pass the rightmost
+       COMPOUND_EXPR to warn_for_omitted_condop.
+
 2016-09-07  David Malcolm  <dmalcolm@redhat.com>
 
        * c-lang.c (LANG_HOOKS_GET_SUBSTRING_LOCATION): Use
index 0aba51c..a304424 100644 (file)
@@ -6425,14 +6425,17 @@ c_parser_conditional_expression (c_parser *parser, struct c_expr *after,
       tree eptype = NULL_TREE;
 
       middle_loc = c_parser_peek_token (parser)->location;
-      pedwarn (middle_loc, OPT_Wpedantic, 
+      pedwarn (middle_loc, OPT_Wpedantic,
               "ISO C forbids omitting the middle term of a ?: expression");
-      warn_for_omitted_condop (middle_loc, cond.value);
       if (TREE_CODE (cond.value) == EXCESS_PRECISION_EXPR)
        {
          eptype = TREE_TYPE (cond.value);
          cond.value = TREE_OPERAND (cond.value, 0);
        }
+      tree e = cond.value;
+      while (TREE_CODE (e) == COMPOUND_EXPR)
+       e = TREE_OPERAND (e, 1);
+      warn_for_omitted_condop (middle_loc, e);
       /* Make sure first operand is calculated only once.  */
       exp1.value = c_save_expr (default_conversion (cond.value));
       if (eptype)
index 9480993..f572c85 100644 (file)
@@ -1,3 +1,9 @@
+2016-09-12  Bernd Edlinger  <bernd.edlinger@hotmail.de>
+
+       PR c++/77496
+       * call.c (build_conditional_expr_1): Call warn_for_omitted_condop.
+       * class.c (instantiate_type): Look through the SAVE_EXPR.
+
 2016-09-09  Jason Merrill  <jason@redhat.com>
 
        Implement P0035R4, C++17 new of over-aligned types.
index 167d778..393aab9 100644 (file)
@@ -4665,9 +4665,12 @@ build_conditional_expr_1 (location_t loc, tree arg1, tree arg2, tree arg3,
   if (!arg2)
     {
       if (complain & tf_error)
-       pedwarn (loc, OPT_Wpedantic, 
+       pedwarn (loc, OPT_Wpedantic,
                 "ISO C++ forbids omitting the middle term of a ?: expression");
 
+      if ((complain & tf_warning) && !truth_value_p (TREE_CODE (arg1)))
+       warn_for_omitted_condop (loc, arg1);
+
       /* Make sure that lvalues remain lvalues.  See g++.oliva/ext1.C.  */
       if (lvalue_p (arg1))
        arg2 = arg1 = cp_stabilize_reference (arg1);
index a4f3c6b..f7147e6 100644 (file)
@@ -8262,7 +8262,12 @@ instantiate_type (tree lhstype, tree rhs, tsubst_flags_t complain)
       return error_mark_node;
     }
 
-  /* There only a few kinds of expressions that may have a type
+  /* If we instantiate a template, and it is a A ?: C expression
+     with omitted B, look through the SAVE_EXPR.  */
+  if (TREE_CODE (rhs) == SAVE_EXPR)
+    rhs = TREE_OPERAND (rhs, 0);
+
+  /* There are only a few kinds of expressions that may have a type
      dependent on overload resolution.  */
   gcc_assert (TREE_CODE (rhs) == ADDR_EXPR
              || TREE_CODE (rhs) == COMPONENT_REF
index 10936ad..4fc8377 100644 (file)
@@ -1,3 +1,10 @@
+2016-09-12  Bernd Edlinger  <bernd.edlinger@hotmail.de>
+
+       PR c++/77496
+       * c-c++-common/warn-ommitted-condop.c: Add more test cases.
+       * g++.dg/ext/pr77496.C: New test.
+       * g++.dg/warn/pr77496.C: New test.
+
 2016-09-12  David Malcolm  <dmalcolm@redhat.com>
 
        PR c/72858
index 0726f04..678373f 100644 (file)
@@ -1,11 +1,15 @@
 /* { dg-options "-Wparentheses -ftrack-macro-expansion=0" } */
 
+#ifndef __cplusplus
+#define bool _Bool
+#endif
+
 extern void f2 (int);
 
-void bar (int x, int y, int z)
+void bar (int x, int y, int z, bool b)
 {
-#define T(op) f2 (x op y ? : 1) 
-#define T2(op) f2 (x op y ? 2 : 1) 
+#define T(op) f2 (x op y ? : 1)
+#define T2(op) f2 (x op y ? 2 : 1)
 
   T(<); /* { dg-warning "omitted middle operand" } */
   T(>); /* { dg-warning "omitted middle operand" } */
@@ -16,6 +20,8 @@ void bar (int x, int y, int z)
   T(||); /* { dg-warning "omitted middle operand" } */
   T(&&); /* { dg-warning "omitted middle operand" } */
   f2 (!x ? : 1);  /* { dg-warning "omitted middle operand" } */
+  f2 ((x,!x) ? : 1);  /* { dg-warning "omitted middle operand" } */
+  f2 ((x,y,!x) ? : 1);  /* { dg-warning "omitted middle operand" } */
   T2(<); /* { dg-bogus "omitted middle operand" } */
   T2(>); /* { dg-bogus "omitted middle operand" } */
   T2(==); /* { dg-bogus "omitted middle operand" } */
@@ -26,4 +32,5 @@ void bar (int x, int y, int z)
   T(*); /* { dg-bogus "omitted middle operand" } */
   T(/); /* { dg-bogus "omitted middle operand" } */
   T(^); /* { dg-bogus "omitted middle operand" } */
+  f2 (b ? : 1);  /* { dg-warning "omitted middle operand" } */
 }
diff --git a/gcc/testsuite/g++.dg/ext/pr77496.C b/gcc/testsuite/g++.dg/ext/pr77496.C
new file mode 100644 (file)
index 0000000..0b21e0c
--- /dev/null
@@ -0,0 +1,21 @@
+// { dg-do compile }
+// { dg-options "" }
+
+template <class x>
+class z : x
+{
+public:
+  bool zz () { return false; }
+  int f () { return zz ? : 1; } // { dg-error "cannot convert" }
+};
+
+class t
+{
+};
+
+int
+main ()
+{
+  z<t> x;
+  return x.f ();
+}
diff --git a/gcc/testsuite/g++.dg/warn/pr77496.C b/gcc/testsuite/g++.dg/warn/pr77496.C
new file mode 100644 (file)
index 0000000..4b97d09
--- /dev/null
@@ -0,0 +1,21 @@
+// { dg-do compile }
+// { dg-options "-Wparentheses" }
+
+template <class x>
+class z : x
+{
+public:
+  bool zz () { return false; }
+  int f () { return zz () ? : 1; } // { dg-warning "omitted middle operand" }
+};
+
+class t
+{
+};
+
+int
+main ()
+{
+  z<t> x;
+  return x.f ();
+}