diff options
author | Bernd Edlinger <bernd.edlinger@hotmail.de> | 2016-09-12 20:18:16 +0000 |
---|---|---|
committer | Bernd Edlinger <edlinger@gcc.gnu.org> | 2016-09-12 20:18:16 +0000 |
commit | 54dcdb88954b1192b004f8b91fc17a42765c20eb (patch) | |
tree | 06828e718304e9c4c4e9aa0de02496b72d3bff1b | |
parent | a313485bbdcdee77b1bf891823f9da8984d76bcc (diff) | |
download | gcc-54dcdb88954b1192b004f8b91fc17a42765c20eb.zip gcc-54dcdb88954b1192b004f8b91fc17a42765c20eb.tar.gz gcc-54dcdb88954b1192b004f8b91fc17a42765c20eb.tar.bz2 |
re PR c++/77496 (ICE in instantiate_type, at cp/class.c:8270)
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
-rw-r--r-- | gcc/c-family/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/c-family/c-common.c | 16 | ||||
-rw-r--r-- | gcc/c/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/c/c-parser.c | 7 | ||||
-rw-r--r-- | gcc/cp/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/cp/call.c | 5 | ||||
-rw-r--r-- | gcc/cp/class.c | 7 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/testsuite/c-c++-common/warn-ommitted-condop.c | 13 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/ext/pr77496.C | 21 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/warn/pr77496.C | 21 |
11 files changed, 101 insertions, 13 deletions
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index 8ba99f2..71c5e50 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -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 diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c index 16f6548..2215e29 100644 --- a/gcc/c-family/c-common.c +++ b/gcc/c-family/c-common.c @@ -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. */ diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog index a647263..b474de1 100644 --- a/gcc/c/ChangeLog +++ b/gcc/c/ChangeLog @@ -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 diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c index 0aba51c..a304424 100644 --- a/gcc/c/c-parser.c +++ b/gcc/c/c-parser.c @@ -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) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 9480993..f572c85 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -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. diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 167d778..393aab9 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -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); diff --git a/gcc/cp/class.c b/gcc/cp/class.c index a4f3c6b..f7147e6 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -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 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 10936ad..4fc8377 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -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 diff --git a/gcc/testsuite/c-c++-common/warn-ommitted-condop.c b/gcc/testsuite/c-c++-common/warn-ommitted-condop.c index 0726f04..678373f 100644 --- a/gcc/testsuite/c-c++-common/warn-ommitted-condop.c +++ b/gcc/testsuite/c-c++-common/warn-ommitted-condop.c @@ -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 index 0000000..0b21e0c --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/pr77496.C @@ -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 index 0000000..4b97d09 --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/pr77496.C @@ -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 (); +} |