Index: include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- include/clang/Basic/DiagnosticSemaKinds.td +++ include/clang/Basic/DiagnosticSemaKinds.td @@ -5820,6 +5820,9 @@ "taking the address of a destructor">; def err_typecheck_unary_expr : Error< "invalid argument type %0 to unary expression">; +def warn_unsignedtypecheck_unary_minus : Warning< + "unary minus operator applied to type %0, result value is still unsigned">, + InGroup; def err_typecheck_indirection_requires_pointer : Error< "indirection requires pointer operand (%0 invalid)">; def ext_typecheck_indirection_through_void_pointer : ExtWarn< Index: lib/Sema/SemaExpr.cpp =================================================================== --- lib/Sema/SemaExpr.cpp +++ lib/Sema/SemaExpr.cpp @@ -12646,13 +12646,18 @@ resultType = Input.get()->getType(); if (resultType->isDependentType()) break; - if (resultType->isArithmeticType()) // C99 6.5.3.3p1 + if (resultType->isArithmeticType()) { // C99 6.5.3.3p1 + if (Opc == UO_Minus && resultType->isUnsignedIntegerType()) + return Diag(OpLoc, diag::warn_unsignedtypecheck_unary_minus) + << resultType << FixItHint::CreateRemoval(OpLoc) + << FixItHint::CreateInsertion(InputExpr->getBeginLoc(), "0u - ") + << Input.get()->getSourceRange(); break; - else if (resultType->isVectorType() && - // The z vector extensions don't allow + or - with bool vectors. - (!Context.getLangOpts().ZVector || - resultType->getAs()->getVectorKind() != - VectorType::AltiVecBool)) + } else if (resultType->isVectorType() && + // The z vector extensions don't allow + or - with bool vectors. + (!Context.getLangOpts().ZVector || + resultType->getAs()->getVectorKind() != + VectorType::AltiVecBool)) break; else if (getLangOpts().CPlusPlus && // C++ [expr.unary.op]p6 Opc == UO_Plus && Index: test/CXX/drs/dr6xx.cpp =================================================================== --- test/CXX/drs/dr6xx.cpp +++ test/CXX/drs/dr6xx.cpp @@ -91,7 +91,8 @@ struct D : B, C {}; } -int dr610[-0u == 0u ? 1 : -1]; // dr610: yes +int dr610[-0u == 0u ? // expected-warning {{unary minus operator applied to type 'unsigned int', result value is still unsigned}} + 1 : -1]; // dr610: yes namespace dr611 { // dr611: yes int k; Index: test/OpenMP/teams_distribute_thread_limit_messages.cpp =================================================================== --- test/OpenMP/teams_distribute_thread_limit_messages.cpp +++ test/OpenMP/teams_distribute_thread_limit_messages.cpp @@ -51,7 +51,7 @@ #pragma omp teams distribute thread_limit(-2) // expected-error {{argument to 'thread_limit' clause must be a strictly positive integer value}} for (int j=0; j<100; j++) foo(); #pragma omp target -#pragma omp teams distribute thread_limit(-10u) +#pragma omp teams distribute thread_limit(-10u) // expected-warning {{unary minus operator applied to type 'unsigned int', result value is still unsigned}} for (int j=0; j<100; j++) foo(); #pragma omp target #pragma omp teams distribute thread_limit(3.14) // expected-error 2 {{expression must have integral or unscoped enumeration type, not 'double'}} @@ -102,7 +102,7 @@ for (int j=0; j<100; j++) foo(); #pragma omp target -#pragma omp teams distribute thread_limit (-10u) +#pragma omp teams distribute thread_limit (-10u) // expected-warning {{unary minus operator applied to type 'unsigned int', result value is still unsigned}} for (int j=0; j<100; j++) foo(); #pragma omp target Index: test/OpenMP/teams_thread_limit_messages.cpp =================================================================== --- test/OpenMP/teams_thread_limit_messages.cpp +++ test/OpenMP/teams_thread_limit_messages.cpp @@ -51,7 +51,7 @@ #pragma omp teams thread_limit(-2) // expected-error {{argument to 'thread_limit' clause must be a strictly positive integer value}} foo(); #pragma omp target -#pragma omp teams thread_limit(-10u) +#pragma omp teams thread_limit(-10u) // expected-warning {{unary minus operator applied to type 'unsigned int', result value is still unsigned}} foo(); #pragma omp target #pragma omp teams thread_limit(3.14) // expected-error 2 {{expression must have integral or unscoped enumeration type, not 'double'}} @@ -102,7 +102,7 @@ foo(); #pragma omp target -#pragma omp teams thread_limit (-10u) +#pragma omp teams thread_limit (-10u) // expected-warning {{unary minus operator applied to type 'unsigned int', result value is still unsigned}} foo(); #pragma omp target Index: test/Sema/unary-minus-unsigned.c =================================================================== --- test/Sema/unary-minus-unsigned.c +++ test/Sema/unary-minus-unsigned.c @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only + +void test1(void) { + unsigned int a = 1; + unsigned long b = 1; + unsigned long long c = 1; + + unsigned int a2 = -a; // expected-warning {{unary minus operator applied to type 'unsigned int', result value is still unsigned}} + unsigned long b2 = -b; // expected-warning {{unary minus operator applied to type 'unsigned long', result value is still unsigned}} + unsigned long long c2 = -c; // expected-warning {{unary minus operator applied to type 'unsigned long long', result value is still unsigned}} + + int a3 = -a; // expected-warning {{unary minus operator applied to type 'unsigned int', result value is still unsigned}} + long b3 = -b; // expected-warning {{unary minus operator applied to type 'unsigned long', result value is still unsigned}} + long long c3 = -c; // expected-warning {{unary minus operator applied to type 'unsigned long long', result value is still unsigned}} + + unsigned int a4 = -1u; // expected-warning {{unary minus operator applied to type 'unsigned int', result value is still unsigned}} + unsigned long b4 = -1ul; // expected-warning {{unary minus operator applied to type 'unsigned long', result value is still unsigned}} + unsigned long long c4 = -1ull; // expected-warning {{unary minus operator applied to type 'unsigned long long', result value is still unsigned}} +}