ychen updated this revision to Diff 374078. ychen edited the summary of this revision. ychen added a comment. Herald added a project: libc++. Herald added a subscriber: libcxx-commits. Herald added a reviewer: libc++. This revision now requires review to proceed.
- Check the scope correctly: first line of `DiagIfReachable` should be `getCurFunctionOrMethodDecl()`. And the `FunctionScopes` should be kept to deal with `requires` expression where `FunctionScopes` could be empty. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D103938/new/ https://reviews.llvm.org/D103938 Files: clang/include/clang/Basic/DiagnosticSemaKinds.td clang/include/clang/Sema/Sema.h clang/lib/Sema/SemaExpr.cpp clang/lib/Sema/SemaExprCXX.cpp clang/lib/Sema/SemaStmt.cpp clang/test/Analysis/dead-stores.c clang/test/CXX/basic/basic.link/p8.cpp clang/test/CXX/drs/dr14xx.cpp clang/test/CXX/drs/dr20xx.cpp clang/test/CXX/drs/dr7xx.cpp clang/test/CXX/temp/temp.constr/temp.constr.constr/partial-specializations.cpp clang/test/CodeCompletion/pragma-macro-token-caching.c clang/test/Frontend/fixed_point_crash.c clang/test/PCH/cxx-explicit-specifier.cpp clang/test/Parser/cxx-ambig-decl-expr.cpp clang/test/Parser/cxx0x-ambig.cpp clang/test/Parser/cxx1z-init-statement.cpp clang/test/Parser/objc-messaging-1.m clang/test/Parser/objc-try-catch-1.m clang/test/Parser/objcxx11-attributes.mm clang/test/Sema/const-eval.c clang/test/Sema/exprs.c clang/test/Sema/i-c-e.c clang/test/Sema/sizeless-1.c clang/test/Sema/switch-1.c clang/test/Sema/vla-2.c clang/test/Sema/warn-type-safety.c clang/test/Sema/warn-unused-value.c clang/test/SemaCXX/attr-annotate.cpp clang/test/SemaCXX/builtin-constant-p.cpp clang/test/SemaCXX/constant-expression-cxx2a.cpp clang/test/SemaCXX/constant-expression.cpp clang/test/SemaCXX/expression-traits.cpp clang/test/SemaCXX/matrix-type-operators.cpp clang/test/SemaCXX/overloaded-operator.cpp clang/test/SemaCXX/sizeless-1.cpp clang/test/SemaCXX/vector.cpp clang/test/SemaCXX/warn-comma-operator.cpp clang/test/SemaCXX/warn-unused-value.cpp clang/test/SemaTemplate/derived.cpp clang/test/SemaTemplate/lambda-capture-pack.cpp libcxx/include/variant
Index: libcxx/include/variant =================================================================== --- libcxx/include/variant +++ libcxx/include/variant @@ -549,7 +549,7 @@ inline _LIBCPP_INLINE_VISIBILITY static constexpr auto __make_fdiagonal_impl() { return __make_dispatch<_Fp, _Vs...>( - index_sequence<(__identity<_Vs>{}, _Ip)...>{}); + index_sequence<((void)__identity<_Vs>{}, _Ip)...>{}); } template <class _Fp, class... _Vs, size_t... _Is> Index: clang/test/SemaTemplate/lambda-capture-pack.cpp =================================================================== --- clang/test/SemaTemplate/lambda-capture-pack.cpp +++ clang/test/SemaTemplate/lambda-capture-pack.cpp @@ -18,7 +18,7 @@ namespace PR41576 { template <class... Xs> constexpr int f(Xs ...xs) { return [&](auto ...ys) { // expected-note {{instantiation}} - return ((xs + ys), ...); // expected-warning {{unused}} + return ((xs + ys), ...); // expected-warning {{left operand of comma operator has no effect}} }(1, 2); } static_assert(f(3, 4) == 6); // expected-note {{instantiation}} Index: clang/test/SemaTemplate/derived.cpp =================================================================== --- clang/test/SemaTemplate/derived.cpp +++ clang/test/SemaTemplate/derived.cpp @@ -49,6 +49,6 @@ class A { TFP m_p; - void Enable() { 0, A(); } // expected-warning {{unused}} + void Enable() { 0, A(); } // expected-warning {{left operand of comma operator has no effect}} }; } Index: clang/test/SemaCXX/warn-unused-value.cpp =================================================================== --- clang/test/SemaCXX/warn-unused-value.cpp +++ clang/test/SemaCXX/warn-unused-value.cpp @@ -1,6 +1,7 @@ // RUN: %clang_cc1 -fsyntax-only -verify -Wunused-value %s // RUN: %clang_cc1 -fsyntax-only -verify -Wunused-value -std=c++98 %s // RUN: %clang_cc1 -fsyntax-only -verify -Wunused-value -std=c++11 %s +// RUN: %clang_cc1 -fsyntax-only -verify -Wunused-value -std=c++17 %s // PR4806 namespace test0 { @@ -138,3 +139,26 @@ (void)arr3; (void)arr4; } + +#if __cplusplus >= 201103L // C++11 or later +namespace test5 { +int v[(5, 6)]; // expected-warning {{left operand of comma operator has no effect}} +void foo() { + new double[false ? (1, 2) : 3] + // FIXME: We shouldn't diagnose the unreachable constant expression + // here. + [false ? (1, 2) : 3]; // expected-warning {{left operand of comma operator has no effect}} +} +} // namespace test5 +#endif + +#if __cplusplus >= 201703L // C++17 or later +namespace test6 { +auto b() { + if constexpr (false) + return (1,0); + else + return (1.0,0.0); // expected-warning {{left operand of comma operator has no effect}} +} +} // namespace test6 +#endif Index: clang/test/SemaCXX/warn-comma-operator.cpp =================================================================== --- clang/test/SemaCXX/warn-comma-operator.cpp +++ clang/test/SemaCXX/warn-comma-operator.cpp @@ -242,8 +242,8 @@ template <typename... xs> class Foo { - typedef bool_seq<(xs::value, true)...> all_true; - typedef bool_seq<(xs::value, false)...> all_false; + typedef bool_seq<((void)xs::value, true)...> all_true; + typedef bool_seq<((void)xs::value, false)...> all_false; typedef bool_seq<xs::value...> seq; }; Index: clang/test/SemaCXX/vector.cpp =================================================================== --- clang/test/SemaCXX/vector.cpp +++ clang/test/SemaCXX/vector.cpp @@ -381,8 +381,8 @@ typedef int inte2 __attribute__((__ext_vector_type__(2))); void test_vector_literal(inte4 res) { - inte2 a = (inte2)(1, 2); //expected-warning{{expression result unused}} - inte4 b = (inte4)(a, a); //expected-error{{C-style cast from vector 'inte2' (vector of 2 'int' values) to vector 'inte4' (vector of 4 'int' values) of different size}} //expected-warning{{expression result unused}} + inte2 a = (inte2)(1, 2); //expected-warning{{left operand of comma operator has no effect}} + inte4 b = (inte4)(a, a); //expected-error{{C-style cast from vector 'inte2' (vector of 2 'int' values) to vector 'inte4' (vector of 4 'int' values) of different size}} //expected-warning{{left operand of comma operator has no effect}} } typedef __attribute__((__ext_vector_type__(4))) float vector_float4; Index: clang/test/SemaCXX/sizeless-1.cpp =================================================================== --- clang/test/SemaCXX/sizeless-1.cpp +++ clang/test/SemaCXX/sizeless-1.cpp @@ -85,9 +85,9 @@ (void)local_int8; - local_int8, 0; // expected-warning + {{expression result unused}} + local_int8, 0; // expected-warning {{left operand of comma operator has no effect}} - 0, local_int8; // expected-warning + {{expression result unused}} + 0, local_int8; // expected-warning {{left operand of comma operator has no effect}} expected-warning {{expression result unused}} svint8_t init_int8 = local_int8; svint8_t bad_init_int8 = for; // expected-error {{expected expression}} Index: clang/test/SemaCXX/overloaded-operator.cpp =================================================================== --- clang/test/SemaCXX/overloaded-operator.cpp +++ clang/test/SemaCXX/overloaded-operator.cpp @@ -157,7 +157,7 @@ void test_comma(X x, Y y) { bool& b1 = (x, y); - X& xr = (x, x); // expected-warning {{expression result unused}} + X& xr = (x, x); // expected-warning {{left operand of comma operator has no effect}} } struct Callable { Index: clang/test/SemaCXX/matrix-type-operators.cpp =================================================================== --- clang/test/SemaCXX/matrix-type-operators.cpp +++ clang/test/SemaCXX/matrix-type-operators.cpp @@ -179,12 +179,12 @@ a[4, 5] = 5.0; // expected-error@-1 {{comma expressions are not allowed as indices in matrix subscript expressions}} - // expected-warning@-2 {{expression result unused}} + // expected-warning@-2 {{left operand of comma operator has no effect}} a[4, 5, 4] = 5.0; // expected-error@-1 {{comma expressions are not allowed as indices in matrix subscript expressions}} - // expected-warning@-2 {{expression result unused}} - // expected-warning@-3 {{expression result unused}} + // expected-warning@-2 {{left operand of comma operator has no effect}} + // expected-warning@-3 {{left operand of comma operator has no effect}} } void extract(sx5x10_t a, float f) { Index: clang/test/SemaCXX/expression-traits.cpp =================================================================== --- clang/test/SemaCXX/expression-traits.cpp +++ clang/test/SemaCXX/expression-traits.cpp @@ -583,10 +583,10 @@ // Can't use the ASSERT_XXXX macros without adding parens around // the comma expression. - static_assert(__is_lvalue_expr(x,x), "expected an lvalue"); - static_assert(__is_rvalue_expr(x,1), "expected an rvalue"); - static_assert(__is_lvalue_expr(1,x), "expected an lvalue"); - static_assert(__is_rvalue_expr(1,1), "expected an rvalue"); + static_assert(__is_lvalue_expr((void)x,x), "expected an lvalue"); + static_assert(__is_rvalue_expr((void)x,1), "expected an rvalue"); + static_assert(__is_lvalue_expr((void)1,x), "expected an lvalue"); + static_assert(__is_rvalue_expr((void)1,1), "expected an rvalue"); } #if 0 Index: clang/test/SemaCXX/constant-expression.cpp =================================================================== --- clang/test/SemaCXX/constant-expression.cpp +++ clang/test/SemaCXX/constant-expression.cpp @@ -88,8 +88,8 @@ void diags(int n) { switch (n) { - case (1/0, 1): // expected-error {{not an integral constant expression}} expected-note {{division by zero}} - case (int)(1/0, 2.0): // expected-error {{not an integral constant expression}} expected-note {{division by zero}} + case (1/0, 1): // expected-error {{not an integral constant expression}} expected-note {{division by zero}} expected-warning {{left operand of comma operator has no effect}} + case (int)(1/0, 2.0): // expected-error {{not an integral constant expression}} expected-note {{division by zero}} expected-warning {{left operand of comma operator has no effect}} case __imag(1/0): // expected-error {{not an integral constant expression}} expected-note {{division by zero}} case (int)__imag((double)(1/0)): // expected-error {{not an integral constant expression}} expected-note {{division by zero}} ; Index: clang/test/SemaCXX/constant-expression-cxx2a.cpp =================================================================== --- clang/test/SemaCXX/constant-expression-cxx2a.cpp +++ clang/test/SemaCXX/constant-expression-cxx2a.cpp @@ -745,7 +745,7 @@ // Ensure that we can handle temporary cleanups for array temporaries. struct ArrElem { constexpr ~ArrElem() {} }; using Arr = ArrElem[3]; - static_assert((Arr{}, true)); + static_assert(((void)Arr{}, true)); } namespace dynamic_alloc { Index: clang/test/SemaCXX/builtin-constant-p.cpp =================================================================== --- clang/test/SemaCXX/builtin-constant-p.cpp +++ clang/test/SemaCXX/builtin-constant-p.cpp @@ -157,12 +157,12 @@ constexpr ~A() { *p = 0; } }; struct Q { int n; constexpr int *get() { return &n; } }; - static_assert(!__builtin_constant_p((A{}, 123))); + static_assert(!__builtin_constant_p(((void)A{}, 123))); // FIXME: We should probably accept this. GCC does. // However, GCC appears to do so by running the destructors at the end of the // enclosing full-expression, which seems broken; running them at the end of // the evaluation of the __builtin_constant_p argument would be more // defensible. - static_assert(!__builtin_constant_p((A{Q().get()}, 123))); + static_assert(!__builtin_constant_p(((void)A{Q().get()}, 123))); } #endif Index: clang/test/SemaCXX/attr-annotate.cpp =================================================================== --- clang/test/SemaCXX/attr-annotate.cpp +++ clang/test/SemaCXX/attr-annotate.cpp @@ -42,7 +42,7 @@ template<typename T> struct B { - [[clang::annotate("test", (T{}, 9))]] void t() {} + [[clang::annotate("test", ((void)T{}, 9))]] void t() {} // expected-error@-1 {{illegal initializer type 'void'}} }; B<int> b; @@ -73,7 +73,7 @@ [[clang::annotate("jui", b, cf)]] void t2() {} // expected-error@-1 {{'annotate' attribute requires parameter 1 to be a constant expression}} // expected-note@-2 {{is not allowed in a constant expression}} - [[clang::annotate("jui", (b, 0), cf)]] [[clang::annotate("jui", &b, cf, &foo::t2, str())]] void t3() {} + [[clang::annotate("jui", ((void)b, 0), cf)]] [[clang::annotate("jui", &b, cf, &foo::t2, str())]] void t3() {} }; }; Index: clang/test/Sema/warn-unused-value.c =================================================================== --- clang/test/Sema/warn-unused-value.c +++ clang/test/Sema/warn-unused-value.c @@ -9,31 +9,31 @@ // PR4806 void pr4806() { - 1,foo(); // expected-warning {{expression result unused}} + 1,foo(); // expected-warning {{left operand of comma operator has no effect}} // other foo(); i; // expected-warning {{expression result unused}} - i,foo(); // expected-warning {{expression result unused}} + i,foo(); // expected-warning {{left operand of comma operator has no effect}} foo(),i; // expected-warning {{expression result unused}} - i,j,foo(); // expected-warning {{expression result unused}} expected-warning {{expression result unused}} - i,foo(),j; // expected-warning {{expression result unused}} expected-warning {{expression result unused}} - foo(),i,j; // expected-warning {{expression result unused}} expected-warning {{expression result unused}} + i,j,foo(); // expected-warning 2{{left operand of comma operator has no effect}} + i,foo(),j; // expected-warning {{left operand of comma operator has no effect}} expected-warning {{expression result unused}} + foo(),i,j; // expected-warning {{expression result unused}} expected-warning {{left operand of comma operator has no effect}} i++; i++,foo(); foo(),i++; - i++,j,foo(); // expected-warning {{expression result unused}} + i++,j,foo(); // expected-warning {{left operand of comma operator has no effect}} i++,foo(),j; // expected-warning {{expression result unused}} foo(),i++,j; // expected-warning {{expression result unused}} - i,j++,foo(); // expected-warning {{expression result unused}} - i,foo(),j++; // expected-warning {{expression result unused}} - foo(),i,j++; // expected-warning {{expression result unused}} + i,j++,foo(); // expected-warning {{left operand of comma operator has no effect}} + i,foo(),j++; // expected-warning {{left operand of comma operator has no effect}} + foo(),i,j++; // expected-warning {{left operand of comma operator has no effect}} i++,j++,foo(); i++,foo(),j++; @@ -86,7 +86,7 @@ void f0(int a); void f1(struct s0 *a) { // rdar://8139785 - f0((int)(a->f0 + 1, 10)); // expected-warning {{expression result unused}} + f0((int)(a->f0 + 1, 10)); // expected-warning {{left operand of comma operator has no effect}} } void blah(int a); Index: clang/test/Sema/warn-type-safety.c =================================================================== --- clang/test/Sema/warn-type-safety.c +++ clang/test/Sema/warn-type-safety.c @@ -145,7 +145,7 @@ void test_tag_expresssion(int b) { fcntl(0, b ? F_DUPFD : F_SETLK, 10); // no-warning fcntl(0, b + F_DUPFD, 10); // no-warning - fcntl(0, (b, F_DUPFD), 10); // expected-warning {{expression result unused}} + fcntl(0, (b, F_DUPFD), 10); // expected-warning {{left operand of comma operator has no effect}} } // Check that using 64-bit magic values as tags works and tag values do not Index: clang/test/Sema/vla-2.c =================================================================== --- clang/test/Sema/vla-2.c +++ clang/test/Sema/vla-2.c @@ -4,14 +4,14 @@ // a different codepath when we have already emitted an error.) int PotentiallyEvaluatedSizeofWarn(int n) { - return (int)sizeof *(0 << 32,(int(*)[n])0); // expected-warning {{expression result unused}} expected-warning {{shift count >= width of type}} + return (int)sizeof *(0 << 32,(int(*)[n])0); // expected-warning {{left operand of comma operator has no effect}} expected-warning {{shift count >= width of type}} } void PotentiallyEvaluatedTypeofWarn(int n) { - __typeof(*(0 << 32,(int(*)[n])0)) x; // expected-warning {{expression result unused}} expected-warning {{shift count >= width of type}} + __typeof(*(0 << 32,(int(*)[n])0)) x; // expected-warning {{left operand of comma operator has no effect}} expected-warning {{shift count >= width of type}} (void)x; } void PotentiallyEvaluatedArrayBoundWarn(int n) { - (void)*(int(*)[(0 << 32,n)])0; // FIXME: We should warn here. + (void)*(int(*)[(0 << 32,n)])0; // expected-warning {{left operand of comma operator has no effect}} } Index: clang/test/Sema/switch-1.c =================================================================== --- clang/test/Sema/switch-1.c +++ clang/test/Sema/switch-1.c @@ -50,7 +50,7 @@ return 0; } return (i, 65537) * 65537; // expected-warning {{overflow in expression; result is 131073 with type 'int'}} \ - // expected-warning {{expression result unused}} + // expected-warning {{left operand of comma operator has no effect}} } // rdar://18405357 Index: clang/test/Sema/sizeless-1.c =================================================================== --- clang/test/Sema/sizeless-1.c +++ clang/test/Sema/sizeless-1.c @@ -76,9 +76,9 @@ (void)local_int8; - local_int8, 0; // expected-warning + {{expression result unused}} + local_int8, 0; // expected-warning {{left operand of comma operator has no effect}} - 0, local_int8; // expected-warning + {{expression result unused}} + 0, local_int8; // expected-warning {{left operand of comma operator has no effect}} expected-warning {{expression result unused}} svint8_t init_int8 = local_int8; svint8_t bad_init_int8 = for; // expected-error {{expected expression}} Index: clang/test/Sema/i-c-e.c =================================================================== --- clang/test/Sema/i-c-e.c +++ clang/test/Sema/i-c-e.c @@ -70,10 +70,12 @@ char z[__builtin_constant_p(4) ? 1 : -1]; // Comma tests -int comma1[0?1,2:3]; -int comma2[1||(1,2)]; // expected-warning {{use of logical '||' with constant operand}} \ - // expected-note {{use '|' for a bitwise operation}} -int comma3[(1,2)]; // expected-warning {{variable length array folded to constant array as an extension}} +int comma1[0?1,2:3]; // expected-warning {{left operand of comma operator has no effect}} +int comma2[1 || (1, 2)]; // expected-warning {{use of logical '||' with constant operand}} \ + // expected-note {{use '|' for a bitwise operation}} \ + // expected-warning {{left operand of comma operator has no effect}} +int comma3[(1, 2)]; // expected-warning {{variable length array folded to constant array as an extension}} \ + // expected-warning {{left operand of comma operator has no effect}} // Pointer + __builtin_constant_p char pbcp[__builtin_constant_p(4) ? (intptr_t)&expr : 0]; // expected-error {{variable length array declaration not allowed at file scope}} Index: clang/test/Sema/exprs.c =================================================================== --- clang/test/Sema/exprs.c +++ clang/test/Sema/exprs.c @@ -16,7 +16,7 @@ // This test should be left as is, as it also tests CFG functionality. void radar9171946() { if (0) { - 0 / (0 ? 1 : 0); // expected-warning {{expression result unused}} + 0 / (0 ? 1 : 0); // no-warning } } Index: clang/test/Sema/const-eval.c =================================================================== --- clang/test/Sema/const-eval.c +++ clang/test/Sema/const-eval.c @@ -74,7 +74,7 @@ EVAL_EXPR(35, constbool) EVAL_EXPR(36, constbool) -EVAL_EXPR(37, (1,2.0) == 2.0 ? 1 : -1) +EVAL_EXPR(37, ((void)1,2.0) == 2.0 ? 1 : -1) EVAL_EXPR(38, __builtin_expect(1,1) == 1 ? 1 : -1) // PR7884 Index: clang/test/Parser/objcxx11-attributes.mm =================================================================== --- clang/test/Parser/objcxx11-attributes.mm +++ clang/test/Parser/objcxx11-attributes.mm @@ -22,7 +22,7 @@ // A message send which contains a message send is OK. [ [ X alloc ] init ]; - [ [ int(), noreturn getSelf ] getSize ]; // expected-warning {{unused}} + [ [ int(), noreturn getSelf ] getSize ]; // expected-warning {{left operand of comma operator has no effect}} // A message send which contains a lambda is OK. [ [noreturn] { return noreturn; } () setSize: 4 ]; Index: clang/test/Parser/objc-try-catch-1.m =================================================================== --- clang/test/Parser/objc-try-catch-1.m +++ clang/test/Parser/objc-try-catch-1.m @@ -28,14 +28,13 @@ } @catch (Frob* ex) { @throw 1,2; // expected-error {{@throw requires an Objective-C object type ('int' invalid)}} \ - // expected-warning {{expression result unused}} + // expected-warning {{left operand of comma operator has no effect}} } @catch (float x) { // expected-error {{@catch parameter is not a pointer to an interface type}} } @catch(...) { - @throw (4,3,proc()); // expected-warning {{expression result unused}} \ - // expected-warning {{expression result unused}} + @throw (4,3,proc()); // expected-warning 2{{left operand of comma operator has no effect}} } } Index: clang/test/Parser/objc-messaging-1.m =================================================================== --- clang/test/Parser/objc-messaging-1.m +++ clang/test/Parser/objc-messaging-1.m @@ -7,20 +7,20 @@ [a ii]; // expected-warning{{not found}} [a if: 1 :2]; // expected-warning{{not found}} [a inout: 1 :2 another:(2,3,4)]; // expected-warning{{not found}} \ - // expected-warning 2{{expression result unused}} + // expected-warning 2{{left operand of comma operator has no effect}} [a inout: 1 :2 another:(2,3,4), 6,6,8]; // expected-warning{{not found}} \ - // expected-warning 2{{expression result unused}} + // expected-warning 2{{left operand of comma operator has no effect}} [a inout: 1 :2 another:(2,3,4), (6,4,5),6,8]; // expected-warning{{not found}} \ - // expected-warning 4{{expression result unused}} + // expected-warning 4{{left operand of comma operator has no effect}} [a inout: 1 :2 another:(i+10), (i,j-1,5),6,8]; // expected-warning{{not found}} \ - // expected-warning 2{{expression result unused}} + // expected-warning 2{{left operand of comma operator has no effect}} [a long: 1 :2 another:(i+10), (i,j-1,5),6,8]; // expected-warning{{not found}} \ - // expected-warning 2{{expression result unused}} + // expected-warning 2{{left operand of comma operator has no effect}} [a : "Hello\n" :2 another:(i+10), (i,j-1,5),6,8]; // expected-warning{{not found}} \ - // expected-warning 2{{expression result unused}} + // expected-warning 2{{left operand of comma operator has no effect}} // Comma expression as receiver (rdar://6222856) [a, b, c foo]; // expected-warning{{not found}} \ - // expected-warning 2{{expression result unused}} + // expected-warning 2{{left operand of comma operator has no effect}} } Index: clang/test/Parser/cxx1z-init-statement.cpp =================================================================== --- clang/test/Parser/cxx1z-init-statement.cpp +++ clang/test/Parser/cxx1z-init-statement.cpp @@ -14,8 +14,8 @@ // init-statement expressions if (T{f()}; f()) {} // expected-warning {{expression result unused}} - if (T{f()}, g, h; f()) {} // expected-warning 2{{unused}} expected-warning {{expression result unused}} - if (T(f()), g, h + 1; f()) {} // expected-warning 2{{unused}} expected-warning {{expression result unused}} + if (T{f()}, g, h; f()) {} // expected-warning 2{{left operand of comma operator has no effect}} expected-warning {{expression result unused}} + if (T(f()), g, h + 1; f()) {} // expected-warning 2{{left operand of comma operator has no effect}} expected-warning {{expression result unused}} // condition declarations if (T(n){g}) {} @@ -26,8 +26,8 @@ // condition expressions if (T(f())) {} if (T{f()}) {} - if (T(f()), g, h) {} // expected-warning 2{{unused}} - if (T{f()}, g, h) {} // expected-warning 2{{unused}} + if (T(f()), g, h) {} // expected-warning 2{{left operand of comma operator has no effect}} + if (T{f()}, g, h) {} // expected-warning 2{{left operand of comma operator has no effect}} // none of the above, disambiguated as expression (can't be a declaration) if (T(n)(g)) {} // expected-error {{undeclared identifier 'n'}} Index: clang/test/Parser/cxx0x-ambig.cpp =================================================================== --- clang/test/Parser/cxx0x-ambig.cpp +++ clang/test/Parser/cxx0x-ambig.cpp @@ -163,7 +163,7 @@ (void)p1; UnsignedTmplArgSink<T(CtorSink(t ...)) ...> *t0; // ok - UnsignedTmplArgSink<((T *)0, 42u) ...> **t0p = &t0; + UnsignedTmplArgSink<((T *)0, 42u) ...> **t0p = &t0; // expected-warning 2{{left operand of comma operator has no effect}} } template void foo(int, int, int); // expected-note {{in instantiation of function template specialization 'ellipsis::foo<int, int>' requested here}} Index: clang/test/Parser/cxx-ambig-decl-expr.cpp =================================================================== --- clang/test/Parser/cxx-ambig-decl-expr.cpp +++ clang/test/Parser/cxx-ambig-decl-expr.cpp @@ -24,7 +24,7 @@ // This is array indexing not an array declarator because a comma expression // is not syntactically a constant-expression. - int(x[1,1]); // expected-warning 2{{unused}} + int(x[1,1]); // expected-warning {{left operand of comma operator has no effect}} expected-warning {{unused}} // This is array indexing not an array declaration because a braced-init-list // is not syntactically a constant-expression. @@ -36,8 +36,8 @@ int(a[{0}]); // expected-warning {{unused}} // These are array declarations. - int(x[(1,1)]); // expected-error {{redefinition}} - int(x[true ? 1,1 : 1]); // expected-error {{redefinition}} + int(x[((void)1,1)]); // expected-error {{redefinition}} + int(x[true ? 1 : (1,1)]); // expected-error {{redefinition}} // expected-warning {{left operand of comma operator has no effect}} int (*_Atomic atomic_ptr_to_int); *atomic_ptr_to_int = 42; Index: clang/test/PCH/cxx-explicit-specifier.cpp =================================================================== --- clang/test/PCH/cxx-explicit-specifier.cpp +++ clang/test/PCH/cxx-explicit-specifier.cpp @@ -12,7 +12,7 @@ template<typename X, typename Y> struct T { template<typename A> - explicit((Y{}, true)) T(A &&a) {} + explicit(((void)Y{}, true)) T(A &&a) {} }; template<typename X, typename Y> struct U : T<X, Y> { @@ -28,7 +28,7 @@ U<S, char> a = foo('0'); } -//CHECK: explicit((char{} , true)) +//CHECK: explicit(((void)char{} , true)) #endif Index: clang/test/Frontend/fixed_point_crash.c =================================================================== --- clang/test/Frontend/fixed_point_crash.c +++ clang/test/Frontend/fixed_point_crash.c @@ -14,7 +14,7 @@ int fn2() { union a m; m.x = 7, 5.6k; // expected-warning {{expression result unused}} - return m.x, m.i; // expected-warning {{expression result unused}} + return m.x, m.i; // expected-warning {{left operand of comma operator has no effect}} } -_Accum acc = (0.5r, 6.9k); // expected-warning {{expression result unused}} +_Accum acc = (0.5r, 6.9k); // expected-warning {{left operand of comma operator has no effect}} Index: clang/test/CodeCompletion/pragma-macro-token-caching.c =================================================================== --- clang/test/CodeCompletion/pragma-macro-token-caching.c +++ clang/test/CodeCompletion/pragma-macro-token-caching.c @@ -12,7 +12,7 @@ void completeParamPragmaError(int param) { Outer(__extension__({ _Pragma(2) })); // expected-error {{_Pragma takes a parenthesized string literal}} - param; // expected-warning {{expression result unused}} + param; } // RUN: %clang_cc1 -fsyntax-only -verify -code-completion-at=%s:16:1 %s | FileCheck %s Index: clang/test/CXX/temp/temp.constr/temp.constr.constr/partial-specializations.cpp =================================================================== --- clang/test/CXX/temp/temp.constr/temp.constr.constr/partial-specializations.cpp +++ clang/test/CXX/temp/temp.constr/temp.constr.constr/partial-specializations.cpp @@ -26,7 +26,7 @@ template<typename T> requires (T{}) // expected-error{{atomic constraint must be of type 'bool' (found 'int')}} struct B<T**> {}; - static_assert((B<int**>{}, true)); // expected-note{{while checking constraint satisfaction for class template partial specialization 'B<int *>' required here}} + static_assert(((void)B<int**>{}, true)); // expected-note{{while checking constraint satisfaction for class template partial specialization 'B<int *>' required here}} // expected-note@-1{{while checking constraint satisfaction for class template partial specialization 'B<int>' required here}} // expected-note@-2{{during template argument deduction for class template partial specialization 'B<T *>' [with T = int *]}} // expected-note@-3{{during template argument deduction for class template partial specialization 'B<T **>' [with T = int]}} Index: clang/test/CXX/drs/dr7xx.cpp =================================================================== --- clang/test/CXX/drs/dr7xx.cpp +++ clang/test/CXX/drs/dr7xx.cpp @@ -26,12 +26,12 @@ use(a); use((a)); use(cond ? a : a); - use((cond, a)); // expected-warning 2{{unused}} FIXME: should only warn once + use((cond, a)); // expected-warning 2{{left operand of comma operator has no effect}} FIXME: should only warn once (void)a; // FIXME: expected-error {{declared in enclosing}} (void)(a); // FIXME: expected-error {{declared in enclosing}} (void)(cond ? a : a); // FIXME: expected-error 2{{declared in enclosing}} - (void)(cond, a); // FIXME: expected-error {{declared in enclosing}} expected-warning {{unused}} + (void)(cond, a); // FIXME: expected-error {{declared in enclosing}} expected-warning {{left operand of comma operator has no effect}} } }; } Index: clang/test/CXX/drs/dr20xx.cpp =================================================================== --- clang/test/CXX/drs/dr20xx.cpp +++ clang/test/CXX/drs/dr20xx.cpp @@ -221,7 +221,7 @@ a.*&A::x; // expected-warning {{unused}} true ? a.x : a.y; // expected-warning {{unused}} (void)a.x; - a.x, discarded_lval(); // expected-warning {{unused}} + a.x, discarded_lval(); // expected-warning {{left operand of comma operator has no effect}} #if 1 // FIXME: These errors are all incorrect; the above code is valid. // expected-error@-6 {{enclosing function}} // expected-error@-6 {{enclosing function}} Index: clang/test/CXX/drs/dr14xx.cpp =================================================================== --- clang/test/CXX/drs/dr14xx.cpp +++ clang/test/CXX/drs/dr14xx.cpp @@ -18,7 +18,7 @@ Check<true ? 0 : A::unknown_spec>::type *var1; // expected-error {{undeclared identifier 'var1'}} Check<true ? 0 : a>::type *var2; // ok, variable declaration expected-note 0+{{here}} Check<true ? 0 : b>::type *var3; // expected-error {{undeclared identifier 'var3'}} - Check<true ? 0 : (c, 0)>::type *var4; // expected-error {{undeclared identifier 'var4'}} + Check<true ? 0 : ((void)c, 0)>::type *var4; // expected-error {{undeclared identifier 'var4'}} // value-dependent because of the implied type-dependent 'this->', not because of 'd' Check<true ? 0 : (d(), 0)>::type *var5; // expected-error {{undeclared identifier 'var5'}} // value-dependent because of the value-dependent '&' operator, not because of 'A::d' Index: clang/test/CXX/basic/basic.link/p8.cpp =================================================================== --- clang/test/CXX/basic/basic.link/p8.cpp +++ clang/test/CXX/basic/basic.link/p8.cpp @@ -27,7 +27,7 @@ void linkage2f(Linkage2); void use_linkage() { - &linkage1v, &linkage1iv, &linkage2v, &linkage2iv, &linkaget1v; // expected-warning 5{{unused}} + &linkage1v, &linkage1iv, &linkage2v, &linkage2iv, &linkaget1v; // expected-warning 4{{left operand of comma operator has no effect}} expected-warning {{unused}} linkage1f(); linkage2f({}); } Index: clang/test/Analysis/dead-stores.c =================================================================== --- clang/test/Analysis/dead-stores.c +++ clang/test/Analysis/dead-stores.c @@ -339,12 +339,12 @@ (void)(0 && x); (void)y7; (void)(0 || (y8, ({ return; }), 1)); - // non-nested-warning@-1 {{expression result unused}} + // non-nested-warning@-1 {{left operand of comma operator has no effect}} (void)x; break; case 8: (void)(1 && (y9, ({ return; }), 1)); - // non-nested-warning@-1 {{expression result unused}} + // non-nested-warning@-1 {{left operand of comma operator has no effect}} (void)x; break; case 9: Index: clang/lib/Sema/SemaStmt.cpp =================================================================== --- clang/lib/Sema/SemaStmt.cpp +++ clang/lib/Sema/SemaStmt.cpp @@ -216,9 +216,9 @@ return S.Diag(Loc, diag::warn_unused_result_msg) << A << Msg << R1 << R2; } -void Sema::DiagnoseUnusedExprResult(const Stmt *S) { +void Sema::DiagnoseUnusedExprResult(const Stmt *S, unsigned DiagID) { if (const LabelStmt *Label = dyn_cast_or_null<LabelStmt>(S)) - return DiagnoseUnusedExprResult(Label->getSubStmt()); + return DiagnoseUnusedExprResult(Label->getSubStmt(), DiagID); const Expr *E = dyn_cast_or_null<Expr>(S); if (!E) @@ -264,7 +264,6 @@ // Okay, we have an unused result. Depending on what the base expression is, // we might want to make a more specific diagnostic. Check for one of these // cases now. - unsigned DiagID = diag::warn_unused_expr; if (const FullExpr *Temps = dyn_cast<FullExpr>(E)) E = Temps->getSubExpr(); if (const CXXBindTemporaryExpr *TempExpr = dyn_cast<CXXBindTemporaryExpr>(E)) @@ -339,7 +338,7 @@ if (LangOpts.OpenMP && isa<CallExpr>(Source) && POE->getNumSemanticExprs() == 1 && isa<CallExpr>(POE->getSemanticExpr(0))) - return DiagnoseUnusedExprResult(POE->getSemanticExpr(0)); + return DiagnoseUnusedExprResult(POE->getSemanticExpr(0), DiagID); if (isa<ObjCSubscriptRefExpr>(Source)) DiagID = diag::warn_unused_container_subscript_expr; else @@ -379,7 +378,8 @@ return; } - DiagRuntimeBehavior(Loc, nullptr, PDiag(DiagID) << R1 << R2); + DiagIfReachable(Loc, S ? llvm::makeArrayRef(S) : llvm::None, + PDiag(DiagID) << R1 << R2); } void Sema::ActOnStartOfCompoundStmt(bool IsStmtExpr) { Index: clang/lib/Sema/SemaExprCXX.cpp =================================================================== --- clang/lib/Sema/SemaExprCXX.cpp +++ clang/lib/Sema/SemaExprCXX.cpp @@ -8524,7 +8524,7 @@ if (FullExpr.isInvalid()) return ExprError(); - DiagnoseUnusedExprResult(FullExpr.get()); + DiagnoseUnusedExprResult(FullExpr.get(), diag::warn_unused_expr); } FullExpr = CorrectDelayedTyposInExpr(FullExpr.get(), /*InitDecl=*/nullptr, Index: clang/lib/Sema/SemaExpr.cpp =================================================================== --- clang/lib/Sema/SemaExpr.cpp +++ clang/lib/Sema/SemaExpr.cpp @@ -28,6 +28,7 @@ #include "clang/AST/RecursiveASTVisitor.h" #include "clang/AST/TypeLoc.h" #include "clang/Basic/Builtins.h" +#include "clang/Basic/DiagnosticSema.h" #include "clang/Basic/PartialDiagnostic.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/TargetInfo.h" @@ -13371,7 +13372,7 @@ if (LHS.isInvalid()) return QualType(); - S.DiagnoseUnusedExprResult(LHS.get()); + S.DiagnoseUnusedExprResult(LHS.get(), diag::warn_unused_comma_left_operand); if (!S.getLangOpts().CPlusPlus) { RHS = S.DefaultFunctionArrayLvalueConversion(RHS.get()); @@ -18898,6 +18899,38 @@ EvaluatedExprMarker(*this, SkipLocalVariables).Visit(E); } +/// Emit a diagnostic when statements are reachable. +/// FIXME: check for reachability even in expressions for which we don't build a +/// CFG (eg, in the initializer of a global or in a constant expression). +/// For example, +/// namespace { auto *p = new double[3][false ? (1, 2) : 3]; } +bool Sema::DiagIfReachable(SourceLocation Loc, ArrayRef<const Stmt *> Stmts, + const PartialDiagnostic &PD) { + if (!Stmts.empty() && getCurFunctionOrMethodDecl()) { + if (!FunctionScopes.empty()) + FunctionScopes.back()->PossiblyUnreachableDiags.push_back( + sema::PossiblyUnreachableDiag(PD, Loc, Stmts)); + return true; + } + + // The initializer of a constexpr variable or of the first declaration of a + // static data member is not syntactically a constant evaluated constant, + // but nonetheless is always required to be a constant expression, so we + // can skip diagnosing. + // FIXME: Using the mangling context here is a hack. + if (auto *VD = dyn_cast_or_null<VarDecl>( + ExprEvalContexts.back().ManglingContextDecl)) { + if (VD->isConstexpr() || + (VD->isStaticDataMember() && VD->isFirstDecl() && !VD->isInline())) + return false; + // FIXME: For any other kind of variable, we should build a CFG for its + // initializer and check whether the context in question is reachable. + } + + Diag(Loc, PD); + return true; +} + /// Emit a diagnostic that describes an effect on the run-time behavior /// of the program being compiled. /// @@ -18930,28 +18963,7 @@ case ExpressionEvaluationContext::PotentiallyEvaluated: case ExpressionEvaluationContext::PotentiallyEvaluatedIfUsed: - if (!Stmts.empty() && getCurFunctionOrMethodDecl()) { - FunctionScopes.back()->PossiblyUnreachableDiags. - push_back(sema::PossiblyUnreachableDiag(PD, Loc, Stmts)); - return true; - } - - // The initializer of a constexpr variable or of the first declaration of a - // static data member is not syntactically a constant evaluated constant, - // but nonetheless is always required to be a constant expression, so we - // can skip diagnosing. - // FIXME: Using the mangling context here is a hack. - if (auto *VD = dyn_cast_or_null<VarDecl>( - ExprEvalContexts.back().ManglingContextDecl)) { - if (VD->isConstexpr() || - (VD->isStaticDataMember() && VD->isFirstDecl() && !VD->isInline())) - break; - // FIXME: For any other kind of variable, we should build a CFG for its - // initializer and check whether the context in question is reachable. - } - - Diag(Loc, PD); - return true; + return DiagIfReachable(Loc, Stmts, PD); } return false; Index: clang/include/clang/Sema/Sema.h =================================================================== --- clang/include/clang/Sema/Sema.h +++ clang/include/clang/Sema/Sema.h @@ -4912,7 +4912,7 @@ /// DiagnoseUnusedExprResult - If the statement passed in is an expression /// whose result is unused, warn. - void DiagnoseUnusedExprResult(const Stmt *S); + void DiagnoseUnusedExprResult(const Stmt *S, unsigned DiagID); void DiagnoseUnusedNestedTypedefs(const RecordDecl *D); void DiagnoseUnusedDecl(const NamedDecl *ND); @@ -5118,6 +5118,16 @@ /// conversion. ExprResult tryConvertExprToType(Expr *E, QualType Ty); + /// Conditionally issue a diagnostic based on the statement's reachability + /// analysis evaluation context. + /// + /// \param Statement If Statement is non-null, delay reporting the + /// diagnostic until the function body is parsed, and then do a basic + /// reachability analysis to determine if the statement is reachable. + /// If it is unreachable, the diagnostic will not be emitted. + bool DiagIfReachable(SourceLocation Loc, ArrayRef<const Stmt *> Stmts, + const PartialDiagnostic &PD); + /// Conditionally issue a diagnostic based on the current /// evaluation context. /// Index: clang/include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticSemaKinds.td +++ clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -8565,6 +8565,9 @@ "'__builtin_choose_expr' requires a constant expression">; def warn_unused_expr : Warning<"expression result unused">, InGroup<UnusedValue>; +def warn_unused_comma_left_operand : Warning< + "left operand of comma operator has no effect">, + InGroup<UnusedValue>; def warn_unused_voidptr : Warning< "expression result unused; should this cast be to 'void'?">, InGroup<UnusedValue>;
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits