diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -314,6 +314,9 @@ (`#61885 `_) - Clang constexpr evaluator now treats comparison of [[gnu::weak]]-attributed member pointer as an invalid expression. +- Emit warning when implicit cast from int to bool happens in an conditional + operator expression + (`#61943 `_) Bug Fixes to Compiler Builtins ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -9284,6 +9284,8 @@ return OP->getOpcode() == UO_LNot; if (E->getType()->isPointerType()) return true; + if (E->getType()->isIntegerType()) + return true; // FIXME: What about overloaded operator calls returning "unspecified boolean // type"s (commonly pointer-to-members)? diff --git a/clang/test/Sema/integer-overflow.c b/clang/test/Sema/integer-overflow.c --- a/clang/test/Sema/integer-overflow.c +++ b/clang/test/Sema/integer-overflow.c @@ -34,7 +34,7 @@ uint64_t not_overflow2 = (1ULL * ((uint64_t)(4608) * (1024 * 1024)) + 2ULL); // expected-warning@+1 2{{overflow in expression; result is 536870912 with type 'int'}} - overflow = 4608 * 1024 * 1024 ? 4608 * 1024 * 1024 : 0; + overflow = (4608 * 1024 * 1024) ? 4608 * 1024 * 1024 : 0; // expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}} overflow = 0 ? 0 : 4608 * 1024 * 1024; diff --git a/clang/test/Sema/parentheses.c b/clang/test/Sema/parentheses.c --- a/clang/test/Sema/parentheses.c +++ b/clang/test/Sema/parentheses.c @@ -84,10 +84,10 @@ // CHECK: fix-it:"{{.*}}":{[[@LINE-5]]:14-[[@LINE-5]]:14}:"(" // CHECK: fix-it:"{{.*}}":{[[@LINE-6]]:24-[[@LINE-6]]:24}:")" - (void)(x % 2 ? 1 : 2); // no warning + (void)(x % 2 ? 1 : 2); // expected-warning {{operator '?:' has lower precedence than '%'}} expected-note 2{{place parenthese}} (void)(x + p ? 1 : 2); // expected-warning {{operator '?:' has lower precedence than '+'}} expected-note 2{{place parentheses}} - (void)(p + x ? 1 : 2); // no warning + (void)(p + x ? 1 : 2); // expected-warning {{operator '?:' has lower precedence than '+'}} expected-note 2{{place parentheses}} (void)(p + b ? 1 : 2); // expected-warning {{operator '?:' has lower precedence than '+'}} expected-note 2{{place parentheses}} diff --git a/clang/test/Sema/parentheses.cpp b/clang/test/Sema/parentheses.cpp --- a/clang/test/Sema/parentheses.cpp +++ b/clang/test/Sema/parentheses.cpp @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -Wparentheses -fsyntax-only -verify %s -// RUN: %clang_cc1 -Wparentheses -fsyntax-only -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s +// RUN: %clang_cc1 -Wparentheses -Woverloaded-shift-op-parentheses -fsyntax-only -verify %s +// RUN: %clang_cc1 -Wparentheses -Woverloaded-shift-op-parentheses -fsyntax-only -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s bool someConditionFunc(); @@ -38,7 +38,7 @@ Stream &operator>>(const char*); }; -void f(Stream& s, bool b) { +void f(Stream& s, bool b, int x) { (void)(s << b ? "foo" : "bar"); // expected-warning {{operator '?:' has lower precedence than '<<'}} \ // expected-note {{place parentheses around the '<<' expression to silence this warning}} \ // expected-note {{place parentheses around the '?:' expression to evaluate it first}} @@ -62,6 +62,30 @@ // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:16-[[@LINE-4]]:16}:")" // CHECK: fix-it:"{{.*}}":{[[@LINE-5]]:15-[[@LINE-5]]:15}:"(" // CHECK: fix-it:"{{.*}}":{[[@LINE-6]]:21-[[@LINE-6]]:21}:")" + + void(s << "Test" << x ? "foo" : "bar"); //expected-warning {{operator '?:' has lower precedence than '<<'}} \ + // expected-note {{place parentheses around the '<<' expression to silence this warning}} \ + // expected-note {{place parentheses around the '?:' expression to evaluate it first}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:8-[[@LINE-3]]:8}:"(" + // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:24-[[@LINE-4]]:24}:")" + // CHECK: fix-it:"{{.*}}":{[[@LINE-5]]:23-[[@LINE-5]]:23}:"(" + // CHECK: fix-it:"{{.*}}":{[[@LINE-6]]:40-[[@LINE-6]]:40}:")" + + void(s << x == 1 ? "foo": "bar"); //expected-warning {{overloaded operator << has higher precedence than comparison operator}} \ + //expected-note {{place parentheses around the '<<' expression to silence this warning}} \ + // expected-note {{place parentheses around comparison expression to evaluate it first}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:8-[[@LINE-3]]:8}:"(" + // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:14-[[@LINE-4]]:14}:")" + // CHECK: fix-it:"{{.*}}":{[[@LINE-5]]:13-[[@LINE-5]]:13}:"(" + // CHECK: fix-it:"{{.*}}":{[[@LINE-6]]:19-[[@LINE-6]]:19}:")" + + void(s << static_cast(x) ? "foo" : "bar"); //expected-warning {{operator '?:' has lower precedence than '<<'}} \ + //expected-note {{place parentheses around the '<<' expression to silence this warning}} \ + //expected-note {{place parentheses around the '?:' expression to evaluate it first}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:8-[[@LINE-3]]:8}:"(" + // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:33-[[@LINE-4]]:33}:")" + // CHECK: fix-it:"{{.*}}":{[[@LINE-5]]:13-[[@LINE-5]]:13}:"(" + // CHECK: fix-it:"{{.*}}":{[[@LINE-6]]:49-[[@LINE-6]]:49}:")" } struct S {