Skip to content

Commit 14c4407

Browse files
authored
[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: microsoft/hlsl-specs#229 Resolves #6581
1 parent 773b012 commit 14c4407

4 files changed

Lines changed: 67 additions & 8 deletions

File tree

tools/clang/include/clang/Basic/DiagnosticGroups.td

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -804,4 +804,5 @@ def HLSLStructurizeExitsLifetimeMarkersConflict: DiagGroup<"structurize-exits-li
804804
def HLSLParameterUsage : DiagGroup<"parameter-usage">;
805805
def HLSLAvailability: DiagGroup<"hlsl-availability">;
806806
def HLSLBarrier : DiagGroup<"hlsl-barrier">;
807+
def HLSLLegacyLiterals : DiagGroup<"hlsl-legacy-literal">;
807808
// HLSL Change Ends

tools/clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7959,6 +7959,9 @@ def warn_hlsl_barrier_no_mem_with_required_group_scope: Warning<
79597959
def warn_hlsl_barrier_no_mem_with_required_device_scope: Warning<
79607960
"DEVICE_SCOPE specified for Barrier operation without applicable memory">,
79617961
InGroup<HLSLBarrier>, DefaultError;
7962+
def warn_hlsl_legacy_integer_literal_signedness: Warning<
7963+
"literal value is treated as signed in HLSL 2021 and earlier, and unsigned in later language versions">,
7964+
InGroup<HLSLLegacyLiterals>, DefaultIgnore;
79627965
// HLSL Change Ends
79637966

79647967
// SPIRV Change Starts

tools/clang/lib/Sema/SemaExpr.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3522,6 +3522,15 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) {
35223522
Ty = Context.IntTy;
35233523
}
35243524
}
3525+
if (Literal.getRadix() != 10) {
3526+
uint64_t Val = ResultVal.getLimitedValue();
3527+
if (Val < std::numeric_limits<uint32_t>::max())
3528+
Width = 32;
3529+
uint64_t MSB = 1ull << (Width - 1);
3530+
if ((Val & MSB) != 0)
3531+
Diag(Tok.getLocation(),
3532+
diag::warn_hlsl_legacy_integer_literal_signedness);
3533+
}
35253534
return IntegerLiteral::Create(Context, ResultVal, Ty, Tok.getLocation());
35263535
// HLSL Change Ends
35273536

@@ -3550,6 +3559,9 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) {
35503559
MaxWidth = 128;
35513560
llvm::APInt ResultVal(MaxWidth, 0);
35523561

3562+
// HLSL Change - 202x integer warnings.
3563+
uint64_t MSB = 1ull << (MaxWidth - 1);
3564+
35533565
if (Literal.GetIntegerValue(ResultVal)) {
35543566
// If this value didn't fit into uintmax_t, error and force to ull.
35553567
Diag(Tok.getLocation(), diag::err_integer_literal_too_large)
@@ -3672,7 +3684,16 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) {
36723684

36733685
if (ResultVal.getBitWidth() != Width)
36743686
ResultVal = ResultVal.trunc(Width);
3687+
MSB = 1ull << (Width - 1); // HLSL Change - 202x integer warnings.
3688+
}
3689+
// HLSL Change Begin - 202x integer warnings.
3690+
if (Literal.getRadix() != 10) {
3691+
uint64_t Val = ResultVal.getLimitedValue();
3692+
if ((Val & MSB) != 0)
3693+
Diag(Tok.getLocation(),
3694+
diag::warn_hlsl_legacy_integer_literal_signedness);
36753695
}
3696+
// HLSL Change End - 202x integer warnings.
36763697
Res = IntegerLiteral::Create(Context, ResultVal, Ty, Tok.getLocation());
36773698
}
36783699

tools/clang/test/SemaHLSL/v202x/conforming-literals/valid-literals.hlsl

Lines changed: 42 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,7 @@
1-
// RUN: %dxc -T lib_6_3 -HV 202x -verify %s
2-
// RUN: %dxc -T lib_6_3 -HV 202x -enable-16bit-types -verify %s
3-
// RUN: %dxc -T lib_6_3 -HV 2021 -verify %s
4-
// RUN: %dxc -T lib_6_3 -HV 2021 -enable-16bit-types -verify %s
5-
6-
#if __HLSL_VERSION <= 2021
7-
// expected-no-diagnostics
8-
#endif
1+
// RUN: %dxc -T lib_6_3 -HV 202x -Whlsl-legacy-literal -verify %s
2+
// RUN: %dxc -T lib_6_3 -HV 202x -Whlsl-legacy-literal -enable-16bit-types -verify %s
3+
// RUN: %dxc -T lib_6_3 -HV 2021 -Whlsl-legacy-literal -verify %s
4+
// RUN: %dxc -T lib_6_3 -HV 2021 -Whlsl-legacy-literal -enable-16bit-types -verify %s
95

106
template <typename T, typename U>
117
struct is_same {
@@ -52,9 +48,11 @@ static const uint64_t V = 9223372036854775808;
5248

5349
_Static_assert(is_same<__decltype(0x0), int>::value, "0x0 is int");
5450
_Static_assert(is_same<__decltype(0x70000000), int>::value, "0x70000000 is int");
51+
// expected-warning@+1{{literal value is treated as signed in HLSL 2021 and earlier, and unsigned in later language versions}}
5552
_Static_assert(is_same<__decltype(0xF0000000), uint>::value, "0xF0000000 is uint");
5653

5754
_Static_assert(is_same<__decltype(0x7000000000000000), int64_t>::value, "0x7000000000000000 is int64_t");
55+
// expected-warning@+1{{literal value is treated as signed in HLSL 2021 and earlier, and unsigned in later language versions}}
5856
_Static_assert(is_same<__decltype(0xF000000000000000), uint64_t>::value, "0xF000000000000000 is uint64_t");
5957

6058
#else
@@ -84,6 +82,42 @@ _Static_assert(!is_same<__decltype(1), int>::value, "Literals are not int");
8482
_Static_assert(!is_same<__decltype(1), uint>::value, "Literals are not uint");
8583
_Static_assert(!is_same<__decltype(1), int64_t>::value, "Literals are not int64_t");
8684
_Static_assert(!is_same<__decltype(1), uint64_t>::value, "Literals are not uint64_t");
85+
86+
uint UnsignedBitMask32() {
87+
// expected-warning@+1{{literal value is treated as signed in HLSL 2021 and earlier, and unsigned in later language versions}}
88+
return 0xF0000000;
89+
}
90+
91+
uint64_t UnsignedBitMask64() {
92+
// expected-warning@+1{{literal value is treated as signed in HLSL 2021 and earlier, and unsigned in later language versions}}
93+
return 0xF000000000000000;
94+
}
95+
96+
uint SignedBitMask32() {
97+
return 0x70000000; // No warning
98+
}
99+
100+
uint64_t SignedBitMask64() {
101+
return 0x7000000000000000; // No warning
102+
}
103+
104+
uint OctUnsignedBitMask32() {
105+
// expected-warning@+1{{literal value is treated as signed in HLSL 2021 and earlier, and unsigned in later language versions}}
106+
return 020000000000;
107+
}
108+
109+
uint64_t OctUnsignedBitMask64() {
110+
// expected-warning@+1{{literal value is treated as signed in HLSL 2021 and earlier, and unsigned in later language versions}}
111+
return 01000000000000000000000;
112+
}
113+
114+
uint OctSignedBitMask32() {
115+
return 010000000000; // No warning
116+
}
117+
118+
uint64_t OctSignedBitMask64() {
119+
return 0400000000000000000000; // No warning
120+
}
87121
#endif
88122

89123
////////////////////////////////////////////////////////////////////////////////

0 commit comments

Comments
 (0)