From 54dcdb88954b1192b004f8b91fc17a42765c20eb Mon Sep 17 00:00:00 2001 From: Bernd Edlinger Date: Mon, 12 Sep 2016 20:18:16 +0000 Subject: [PATCH] re PR c++/77496 (ICE in instantiate_type, at cp/class.c:8270) gcc/c-family: 2016-09-12 Bernd Edlinger PR c++/77496 * c-common.c (warn_for_omitted_condop): Also warn for boolean data. gcc/c: 2016-09-12 Bernd Edlinger 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 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 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 | 5 +++++ gcc/c-family/c-common.c | 16 ++++++++++------ gcc/c/ChangeLog | 6 ++++++ gcc/c/c-parser.c | 7 +++++-- gcc/cp/ChangeLog | 6 ++++++ gcc/cp/call.c | 5 ++++- gcc/cp/class.c | 7 ++++++- gcc/testsuite/ChangeLog | 7 +++++++ gcc/testsuite/c-c++-common/warn-ommitted-condop.c | 13 ++++++++++--- gcc/testsuite/g++.dg/ext/pr77496.C | 21 +++++++++++++++++++++ gcc/testsuite/g++.dg/warn/pr77496.C | 21 +++++++++++++++++++++ 11 files changed, 101 insertions(+), 13 deletions(-) create mode 100644 gcc/testsuite/g++.dg/ext/pr77496.C create mode 100644 gcc/testsuite/g++.dg/warn/pr77496.C 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 + + PR c++/77496 + * c-common.c (warn_for_omitted_condop): Also warn for boolean data. + 2016-09-12 David Malcolm 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 %, " "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 + + 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 * 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 + + 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 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 + + 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 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 z : x +{ +public: + bool zz () { return false; } + int f () { return zz ? : 1; } // { dg-error "cannot convert" } +}; + +class t +{ +}; + +int +main () +{ + z 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 z : x +{ +public: + bool zz () { return false; } + int f () { return zz () ? : 1; } // { dg-warning "omitted middle operand" } +}; + +class t +{ +}; + +int +main () +{ + z x; + return x.f (); +} -- 2.7.4