diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -325,6 +325,9 @@ member pointer as an invalid expression. - Fix crash when member function contains invalid default argument. (`#62122 `_) +- Print diagnostic warning about precedence when integer expression is used + without parentheses 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 @@ -9282,6 +9282,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/Analysis/uninit-vals.c b/clang/test/Analysis/uninit-vals.c --- a/clang/test/Analysis/uninit-vals.c +++ b/clang/test/Analysis/uninit-vals.c @@ -32,7 +32,7 @@ int f2_b(void) { int x; // expected-note{{'x' declared without an initial value}} - return ((1+x)+2+((x))) + 1 ? 1 : 2; // expected-warning{{The right operand of '+' is a garbage value}} + return (((1+x)+2+((x))) + 1) ? 1 : 2; // expected-warning{{The right operand of '+' is a garbage value}} // expected-note@-1{{The right operand of '+' is a garbage value}} } 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 @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -Wparentheses -fsyntax-only -verify %s // RUN: %clang_cc1 -Wparentheses -fsyntax-only -verify %s // RUN: %clang_cc1 -Wparentheses -fsyntax-only -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s @@ -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 { diff --git a/clang/test/SemaCXX/array-bounds.cpp b/clang/test/SemaCXX/array-bounds.cpp --- a/clang/test/SemaCXX/array-bounds.cpp +++ b/clang/test/SemaCXX/array-bounds.cpp @@ -87,7 +87,7 @@ } #define SIZE 10 -#define ARR_IN_MACRO(flag, arr, idx) flag ? arr[idx] : 1 +#define ARR_IN_MACRO(flag, arr, idx) (flag ? arr[idx] : 1) int test_no_warn_macro_unreachable() { int arr[SIZE]; // expected-note {{array 'arr' declared here}} diff --git a/clang/test/SemaCXX/integer-overflow.cpp b/clang/test/SemaCXX/integer-overflow.cpp --- a/clang/test/SemaCXX/integer-overflow.cpp +++ b/clang/test/SemaCXX/integer-overflow.cpp @@ -41,7 +41,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/libcxx/include/__chrono/duration.h b/libcxx/include/__chrono/duration.h --- a/libcxx/include/__chrono/duration.h +++ b/libcxx/include/__chrono/duration.h @@ -194,7 +194,7 @@ return __lower; if (__lower_diff > __upper_diff) return __upper; - return __lower.count() & 1 ? __upper : __lower; + return (__lower.count() & 1) ? __upper : __lower; } #endif diff --git a/libcxx/include/strstream b/libcxx/include/strstream --- a/libcxx/include/strstream +++ b/libcxx/include/strstream @@ -300,7 +300,7 @@ _LIBCPP_INLINE_VISIBILITY ostrstream(char* __s, int __n, ios_base::openmode __mode = ios_base::out) : ostream(&__sb_), - __sb_(__s, __n, __s + (__mode & ios::app ? _VSTD::strlen(__s) : 0)) + __sb_(__s, __n, __s + ((__mode & ios::app) ? _VSTD::strlen(__s) : 0)) {} #ifndef _LIBCPP_CXX03_LANG @@ -360,7 +360,7 @@ _LIBCPP_INLINE_VISIBILITY strstream(char* __s, int __n, ios_base::openmode __mode = ios_base::in | ios_base::out) : iostream(&__sb_), - __sb_(__s, __n, __s + (__mode & ios::app ? _VSTD::strlen(__s) : 0)) + __sb_(__s, __n, __s + ((__mode & ios::app) ? _VSTD::strlen(__s) : 0)) {} #ifndef _LIBCPP_CXX03_LANG diff --git a/libcxx/src/filesystem/operations.cpp b/libcxx/src/filesystem/operations.cpp --- a/libcxx/src/filesystem/operations.cpp +++ b/libcxx/src/filesystem/operations.cpp @@ -116,7 +116,7 @@ PosPtr peek() const noexcept { auto TkEnd = getNextTokenStartPos(); auto End = getAfterBack(); - return TkEnd == End ? nullptr : TkEnd; + return (TkEnd == End) ? nullptr : TkEnd; } void increment() noexcept { @@ -311,7 +311,7 @@ PosPtr consumeAllSeparators(PosPtr P, PosPtr End) const noexcept { if (P == nullptr || P == End || !isSeparator(*P)) return nullptr; - const int Inc = P < End ? 1 : -1; + const int Inc = (P < End) ? 1 : -1; P += Inc; while (P != End && isSeparator(*P)) P += Inc; @@ -337,7 +337,7 @@ PosPtr Start = P; if (P == nullptr || P == End || isSeparator(*P)) return nullptr; - const int Inc = P < End ? 1 : -1; + const int Inc = (P < End) ? 1 : -1; P += Inc; while (P != End && !isSeparator(*P)) P += Inc; diff --git a/libcxx/src/locale.cpp b/libcxx/src/locale.cpp --- a/libcxx/src/locale.cpp +++ b/libcxx/src/locale.cpp @@ -1673,7 +1673,7 @@ break; } } - return frm_nxt == frm_end ? ok : partial; + return (frm_nxt == frm_end) ? ok : partial; } codecvt::result @@ -1718,7 +1718,7 @@ } } frm_nxt = frm; - return frm_nxt == frm_end ? ok : partial; + return (frm_nxt == frm_end) ? ok : partial; } if (n == size_t(-1)) return error; @@ -1739,7 +1739,7 @@ break; } } - return frm_nxt == frm_end ? ok : partial; + return (frm_nxt == frm_end) ? ok : partial; } codecvt::result @@ -1806,7 +1806,7 @@ int codecvt::do_max_length() const noexcept { - return __l_ == 0 ? 1 : static_cast(__libcpp_mb_cur_max_l(__l_)); + return (__l_ == 0) ? 1 : static_cast(__libcpp_mb_cur_max_l(__l_)); } #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS @@ -2097,7 +2097,7 @@ return codecvt_base::error; } } - return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok; + return (frm_nxt < frm_end) ? codecvt_base::partial : codecvt_base::ok; } static @@ -2218,7 +2218,7 @@ return codecvt_base::error; } } - return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok; + return (frm_nxt < frm_end) ? codecvt_base::partial : codecvt_base::ok; } static @@ -2488,7 +2488,7 @@ return codecvt_base::error; } } - return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok; + return (frm_nxt < frm_end) ? codecvt_base::partial : codecvt_base::ok; } static @@ -2713,7 +2713,7 @@ return codecvt_base::error; } } - return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok; + return (frm_nxt < frm_end) ? codecvt_base::partial : codecvt_base::ok; } static @@ -2872,7 +2872,7 @@ frm_nxt += 4; } } - return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok; + return (frm_nxt < frm_end) ? codecvt_base::partial : codecvt_base::ok; } static @@ -3004,7 +3004,7 @@ frm_nxt += 4; } } - return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok; + return (frm_nxt < frm_end) ? codecvt_base::partial : codecvt_base::ok; } static @@ -3098,7 +3098,7 @@ *to_nxt = c1; frm_nxt += 2; } - return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok; + return (frm_nxt < frm_end) ? codecvt_base::partial : codecvt_base::ok; } static @@ -3172,7 +3172,7 @@ *to_nxt = c1; frm_nxt += 2; } - return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok; + return (frm_nxt < frm_end) ? codecvt_base::partial : codecvt_base::ok; } static diff --git a/libcxx/src/memory_resource.cpp b/libcxx/src/memory_resource.cpp --- a/libcxx/src/memory_resource.cpp +++ b/libcxx/src/memory_resource.cpp @@ -361,8 +361,8 @@ } void* result = __fixed_pools_[i].__try_allocate_from_vacancies(); if (result == nullptr) { - auto min = [](size_t a, size_t b) { return a < b ? a : b; }; - auto max = [](size_t a, size_t b) { return a < b ? b : a; }; + auto min = [](size_t a, size_t b) { return (a < b) ? a : b; }; + auto max = [](size_t a, size_t b) { return (a < b) ? b : a; }; size_t prev_chunk_size_in_bytes = __fixed_pools_[i].__previous_chunk_size_in_bytes(); size_t prev_chunk_size_in_blocks = prev_chunk_size_in_bytes >> __log2_pool_block_size(i); diff --git a/libcxx/src/ryu/d2fixed.cpp b/libcxx/src/ryu/d2fixed.cpp --- a/libcxx/src/ryu/d2fixed.cpp +++ b/libcxx/src/ryu/d2fixed.cpp @@ -272,7 +272,7 @@ bool __nonzero = false; if (__e2 >= -52) { - const uint32_t __idx = __e2 < 0 ? 0 : __indexForExponent(static_cast(__e2)); + const uint32_t __idx = (__e2 < 0) ? 0 : __indexForExponent(static_cast(__e2)); const uint32_t __p10bits = __pow10BitsForIndex(__idx); const int32_t __len = static_cast(__lengthForIndex(__idx)); for (int32_t __i = __len - 1; __i >= 0; --__i) { @@ -468,7 +468,7 @@ uint32_t __availableDigits = 0; int32_t __exp = 0; if (__e2 >= -52) { - const uint32_t __idx = __e2 < 0 ? 0 : __indexForExponent(static_cast(__e2)); + const uint32_t __idx = (__e2 < 0) ? 0 : __indexForExponent(static_cast(__e2)); const uint32_t __p10bits = __pow10BitsForIndex(__idx); const int32_t __len = static_cast(__lengthForIndex(__idx)); for (int32_t __i = __len - 1; __i >= 0; --__i) { @@ -640,7 +640,7 @@ _Sign_character = '+'; } - const int _Exponent_part_length = __exp >= 100 + const int _Exponent_part_length = (__exp >= 100) ? 5 // "e+NNN" : 4; // "e+NN" diff --git a/libcxx/src/ryu/f2s.cpp b/libcxx/src/ryu/f2s.cpp --- a/libcxx/src/ryu/f2s.cpp +++ b/libcxx/src/ryu/f2s.cpp @@ -393,7 +393,7 @@ _LIBCPP_ASSERT(_Data[_Idx] == 0, ""); } - const uint32_t _Data_olength = _Data[0] >= 1000000000 ? 10 : __decimalLength9(_Data[0]); + const uint32_t _Data_olength = (_Data[0] >= 1000000000) ? 10 : __decimalLength9(_Data[0]); const uint32_t _Total_fixed_length = _Data_olength + 9 * _Filled_blocks; if (_Last - _First < static_cast(_Total_fixed_length)) { diff --git a/libcxxabi/src/cxa_default_handlers.cpp b/libcxxabi/src/cxa_default_handlers.cpp --- a/libcxxabi/src/cxa_default_handlers.cpp +++ b/libcxxabi/src/cxa_default_handlers.cpp @@ -55,10 +55,9 @@ if (!__isOurExceptionClass(unwind_exception)) abort_message("terminating due to %s foreign exception", cause); - void* thrown_object = - __getExceptionClass(unwind_exception) == kOurDependentExceptionClass ? - ((__cxa_dependent_exception*)exception_header)->primaryException : - exception_header + 1; + void* thrown_object = (__getExceptionClass(unwind_exception) == kOurDependentExceptionClass) + ? ((__cxa_dependent_exception*)exception_header)->primaryException + : exception_header + 1; const __shim_type_info* thrown_type = static_cast(exception_header->exceptionType); auto name = demangle(thrown_type->name()); diff --git a/libcxxabi/src/cxa_demangle.cpp b/libcxxabi/src/cxa_demangle.cpp --- a/libcxxabi/src/cxa_demangle.cpp +++ b/libcxxabi/src/cxa_demangle.cpp @@ -402,6 +402,6 @@ if (Status) *Status = InternalStatus; - return InternalStatus == demangle_success ? Buf : nullptr; + return (InternalStatus == demangle_success) ? Buf : nullptr; } } // __cxxabiv1 diff --git a/libcxxabi/src/cxa_exception.cpp b/libcxxabi/src/cxa_exception.cpp --- a/libcxxabi/src/cxa_exception.cpp +++ b/libcxxabi/src/cxa_exception.cpp @@ -455,8 +455,8 @@ if (native_exception) { // Increment the handler count, removing the flag about being rethrown - exception_header->handlerCount = exception_header->handlerCount < 0 ? - -exception_header->handlerCount + 1 : exception_header->handlerCount + 1; + exception_header->handlerCount = (exception_header->handlerCount < 0) ? -exception_header->handlerCount + 1 + : exception_header->handlerCount + 1; // place the exception on the top of the stack if it's not already // there by a previous rethrow if (exception_header != globals->caughtExceptions) diff --git a/libcxxabi/src/cxa_personality.cpp b/libcxxabi/src/cxa_personality.cpp --- a/libcxxabi/src/cxa_personality.cpp +++ b/libcxxabi/src/cxa_personality.cpp @@ -718,9 +718,7 @@ if (actionEntry == 0) { // Found a cleanup - results.reason = actions & _UA_SEARCH_PHASE - ? _URC_CONTINUE_UNWIND - : _URC_HANDLER_FOUND; + results.reason = (actions & _UA_SEARCH_PHASE) ? _URC_CONTINUE_UNWIND : _URC_HANDLER_FOUND; return; } // Convert 1-based byte offset into @@ -832,9 +830,8 @@ // End of action list. If this is phase 2 and we have found // a cleanup (ttypeIndex=0), return _URC_HANDLER_FOUND; // otherwise return _URC_CONTINUE_UNWIND. - results.reason = hasCleanup && actions & _UA_CLEANUP_PHASE - ? _URC_HANDLER_FOUND - : _URC_CONTINUE_UNWIND; + results.reason = + (hasCleanup && (actions & _UA_CLEANUP_PHASE)) ? _URC_HANDLER_FOUND : _URC_CONTINUE_UNWIND; return; } // Go to next action @@ -1243,10 +1240,9 @@ { const __shim_type_info* excpType = static_cast(new_exception_header->exceptionType); - adjustedPtr = - __getExceptionClass(&new_exception_header->unwindHeader) == kOurDependentExceptionClass ? - ((__cxa_dependent_exception*)new_exception_header)->primaryException : - new_exception_header + 1; + adjustedPtr = (__getExceptionClass(&new_exception_header->unwindHeader) == kOurDependentExceptionClass) + ? ((__cxa_dependent_exception*)new_exception_header)->primaryException + : new_exception_header + 1; if (!exception_spec_can_catch(ttypeIndex, classInfo, ttypeEncoding, excpType, adjustedPtr, unwind_exception, base)) diff --git a/libcxxabi/src/demangle/ItaniumDemangle.h b/libcxxabi/src/demangle/ItaniumDemangle.h --- a/libcxxabi/src/demangle/ItaniumDemangle.h +++ b/libcxxabi/src/demangle/ItaniumDemangle.h @@ -1306,7 +1306,7 @@ const Node *getSyntaxNode(OutputBuffer &OB) const override { initializePackExpansion(OB); size_t Idx = OB.CurrentPackIndex; - return Idx < Data.size() ? Data[Idx]->getSyntaxNode(OB) : this; + return (Idx < Data.size()) ? Data[Idx]->getSyntaxNode(OB) : this; } void printLeft(OutputBuffer &OB) const override { @@ -2499,7 +2499,7 @@ return false; } - char consume() { return First != Last ? *First++ : '\0'; } + char consume() { return (First != Last) ? *First++ : '\0'; } char look(unsigned Lookahead = 0) const { if (static_cast(Last - First) <= Lookahead)