[202x] Implement -Whlsl-legacy-literal warnings (#6580)

This adds new literal warnings to identify integer literals that may
have breaking behavior changes between HLSL 2021 and 202x as a result of
the conforming literals change.

The spec update for this is in:
https://github.com/microsoft/hlsl-specs/pull/229

Resolves #6581
This commit is contained in:
Chris B 2024-05-07 09:05:33 -05:00 коммит произвёл GitHub
Родитель 773b012727
Коммит 14c440712d
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
4 изменённых файлов: 67 добавлений и 8 удалений

Просмотреть файл

@ -804,4 +804,5 @@ def HLSLStructurizeExitsLifetimeMarkersConflict: DiagGroup<"structurize-exits-li
def HLSLParameterUsage : DiagGroup<"parameter-usage">;
def HLSLAvailability: DiagGroup<"hlsl-availability">;
def HLSLBarrier : DiagGroup<"hlsl-barrier">;
def HLSLLegacyLiterals : DiagGroup<"hlsl-legacy-literal">;
// HLSL Change Ends

Просмотреть файл

@ -7959,6 +7959,9 @@ def warn_hlsl_barrier_no_mem_with_required_group_scope: Warning<
def warn_hlsl_barrier_no_mem_with_required_device_scope: Warning<
"DEVICE_SCOPE specified for Barrier operation without applicable memory">,
InGroup<HLSLBarrier>, DefaultError;
def warn_hlsl_legacy_integer_literal_signedness: Warning<
"literal value is treated as signed in HLSL 2021 and earlier, and unsigned in later language versions">,
InGroup<HLSLLegacyLiterals>, DefaultIgnore;
// HLSL Change Ends
// SPIRV Change Starts

Просмотреть файл

@ -3522,6 +3522,15 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) {
Ty = Context.IntTy;
}
}
if (Literal.getRadix() != 10) {
uint64_t Val = ResultVal.getLimitedValue();
if (Val < std::numeric_limits<uint32_t>::max())
Width = 32;
uint64_t MSB = 1ull << (Width - 1);
if ((Val & MSB) != 0)
Diag(Tok.getLocation(),
diag::warn_hlsl_legacy_integer_literal_signedness);
}
return IntegerLiteral::Create(Context, ResultVal, Ty, Tok.getLocation());
// HLSL Change Ends
@ -3550,6 +3559,9 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) {
MaxWidth = 128;
llvm::APInt ResultVal(MaxWidth, 0);
// HLSL Change - 202x integer warnings.
uint64_t MSB = 1ull << (MaxWidth - 1);
if (Literal.GetIntegerValue(ResultVal)) {
// If this value didn't fit into uintmax_t, error and force to ull.
Diag(Tok.getLocation(), diag::err_integer_literal_too_large)
@ -3672,7 +3684,16 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) {
if (ResultVal.getBitWidth() != Width)
ResultVal = ResultVal.trunc(Width);
MSB = 1ull << (Width - 1); // HLSL Change - 202x integer warnings.
}
// HLSL Change Begin - 202x integer warnings.
if (Literal.getRadix() != 10) {
uint64_t Val = ResultVal.getLimitedValue();
if ((Val & MSB) != 0)
Diag(Tok.getLocation(),
diag::warn_hlsl_legacy_integer_literal_signedness);
}
// HLSL Change End - 202x integer warnings.
Res = IntegerLiteral::Create(Context, ResultVal, Ty, Tok.getLocation());
}

Просмотреть файл

@ -1,11 +1,7 @@
// RUN: %dxc -T lib_6_3 -HV 202x -verify %s
// RUN: %dxc -T lib_6_3 -HV 202x -enable-16bit-types -verify %s
// RUN: %dxc -T lib_6_3 -HV 2021 -verify %s
// RUN: %dxc -T lib_6_3 -HV 2021 -enable-16bit-types -verify %s
#if __HLSL_VERSION <= 2021
// expected-no-diagnostics
#endif
// RUN: %dxc -T lib_6_3 -HV 202x -Whlsl-legacy-literal -verify %s
// RUN: %dxc -T lib_6_3 -HV 202x -Whlsl-legacy-literal -enable-16bit-types -verify %s
// RUN: %dxc -T lib_6_3 -HV 2021 -Whlsl-legacy-literal -verify %s
// RUN: %dxc -T lib_6_3 -HV 2021 -Whlsl-legacy-literal -enable-16bit-types -verify %s
template <typename T, typename U>
struct is_same {
@ -52,9 +48,11 @@ static const uint64_t V = 9223372036854775808;
_Static_assert(is_same<__decltype(0x0), int>::value, "0x0 is int");
_Static_assert(is_same<__decltype(0x70000000), int>::value, "0x70000000 is int");
// expected-warning@+1{{literal value is treated as signed in HLSL 2021 and earlier, and unsigned in later language versions}}
_Static_assert(is_same<__decltype(0xF0000000), uint>::value, "0xF0000000 is uint");
_Static_assert(is_same<__decltype(0x7000000000000000), int64_t>::value, "0x7000000000000000 is int64_t");
// expected-warning@+1{{literal value is treated as signed in HLSL 2021 and earlier, and unsigned in later language versions}}
_Static_assert(is_same<__decltype(0xF000000000000000), uint64_t>::value, "0xF000000000000000 is uint64_t");
#else
@ -84,6 +82,42 @@ _Static_assert(!is_same<__decltype(1), int>::value, "Literals are not int");
_Static_assert(!is_same<__decltype(1), uint>::value, "Literals are not uint");
_Static_assert(!is_same<__decltype(1), int64_t>::value, "Literals are not int64_t");
_Static_assert(!is_same<__decltype(1), uint64_t>::value, "Literals are not uint64_t");
uint UnsignedBitMask32() {
// expected-warning@+1{{literal value is treated as signed in HLSL 2021 and earlier, and unsigned in later language versions}}
return 0xF0000000;
}
uint64_t UnsignedBitMask64() {
// expected-warning@+1{{literal value is treated as signed in HLSL 2021 and earlier, and unsigned in later language versions}}
return 0xF000000000000000;
}
uint SignedBitMask32() {
return 0x70000000; // No warning
}
uint64_t SignedBitMask64() {
return 0x7000000000000000; // No warning
}
uint OctUnsignedBitMask32() {
// expected-warning@+1{{literal value is treated as signed in HLSL 2021 and earlier, and unsigned in later language versions}}
return 020000000000;
}
uint64_t OctUnsignedBitMask64() {
// expected-warning@+1{{literal value is treated as signed in HLSL 2021 and earlier, and unsigned in later language versions}}
return 01000000000000000000000;
}
uint OctSignedBitMask32() {
return 010000000000; // No warning
}
uint64_t OctSignedBitMask64() {
return 0400000000000000000000; // No warning
}
#endif
////////////////////////////////////////////////////////////////////////////////