Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions tools/clang/include/clang/Basic/DiagnosticGroups.td
Original file line number Diff line number Diff line change
Expand Up @@ -808,4 +808,5 @@ def HLSLAvailabilityConstant: DiagGroup<"hlsl-availability-constant">;
def HLSLBarrier : DiagGroup<"hlsl-barrier">;
def HLSLLegacyLiterals : DiagGroup<"hlsl-legacy-literal">;
def HLSLGroupshared202x : DiagGroup<"hlsl-groupshared-202x">;
def HLSL202xExtensions : DiagGroup<"hlsl-202x-extensions", [HLSLGroupshared202x]>;
// HLSL Change Ends
8 changes: 8 additions & 0 deletions tools/clang/include/clang/Basic/DiagnosticLexKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -658,4 +658,12 @@ def err_pp_eof_in_assume_nonnull : Error<

}

// HLSL Change Begin - fixed-size floating-point literal suffixes
def ext_hlsl_fixed_size_float_suffix_202x : ExtWarn<
"fixed-size floating-point literal suffix '%0' is a HLSL 202x extension">,
InGroup<HLSL202xExtensions>;
def err_hlsl_16bit_suffix_requires_native_16bit : Error<
"16-bit floating-point literal suffix '%0' requires '-enable-16bit-types'">;
// HLSL Change End

}
37 changes: 37 additions & 0 deletions tools/clang/lib/Lex/LiteralSupport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -609,6 +609,42 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling,
case 'F':
if (!isFPConstant) break; // Error for integer constant.
if (isFloat || isLong) break; // FF, LF invalid.
// HLSL Change Begin - fixed-size float suffixes f16/f32/f64
if (PP.getLangOpts().HLSL && (s + 2) < ThisTokEnd) {
unsigned Width = 0;
if (s[1] == '1' && s[2] == '6')
Width = 16;
else if (s[1] == '3' && s[2] == '2')
Width = 32;
else if (s[1] == '6' && s[2] == '4')
Width = 64;
if (Width != 0) {
StringRef SuffixStr(s, 3);
if (PP.getLangOpts().HLSLVersion < hlsl::LangStd::v202x) {
PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, s - ThisTokBegin),
diag::ext_hlsl_fixed_size_float_suffix_202x)
<< SuffixStr;
}
if (Width == 16 && PP.getLangOpts().UseMinPrecision) {
PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, s - ThisTokBegin),
diag::err_hlsl_16bit_suffix_requires_native_16bit)
<< SuffixStr;
hadError = true;
}
// Reuse existing width flags: f16 acts like 'h' (half), f32 like
// 'f' (float), f64 like 'l' (double in HLSL). The source token is
// preserved if anything later needs to distinguish the spellings.
if (Width == 16)
isHalf = true;
else if (Width == 32)
isFloat = true;
else
isLong = true;
s += 2; // The outer loop's ++s consumes the leading 'f'/'F'.
continue;
}
}
// HLSL Change End
isFloat = true;
continue; // Success.
// HLSL Change Starts
Expand Down Expand Up @@ -718,6 +754,7 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling,
isUnsigned = false;
isLongLong = false;
isFloat = false;
isHalf = false; // HLSL Change
isImaginary = false;
MicrosoftInteger = 0;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
// RUN: %dxc -T lib_6_3 -HV 202x -enable-16bit-types -verify %s

// Verify that float literal suffixes that look like fixed-size width
// suffixes but specify an unsupported width are rejected. Only 16, 32 and
// 64 are valid widths; everything else must produce an
// "invalid suffix on floating constant" error.

float plausible_f8() {
// 'f8' would be an 8-bit float, which we don't support.
// expected-error@+1{{invalid suffix 'f8' on floating constant}}
return 1.0f8;
}

float plausible_F8() {
// expected-error@+1{{invalid suffix 'F8' on floating constant}}
return 1.0F8;
}

float plausible_f128() {
// 'f128' would be a 128-bit float, which we don't support.
// expected-error@+1{{invalid suffix 'f128' on floating constant}}
return 1.0f128;
}

float plausible_F128() {
// expected-error@+1{{invalid suffix 'F128' on floating constant}}
return 1.0F128;
}

float implausible_f23() {
// 'f23' is not a meaningful width but the parser should still reject it.
// expected-error@+1{{invalid suffix 'f23' on floating constant}}
return 1.0f23;
}

float implausible_f7() {
// 'f7' is not a meaningful width but the parser should still reject it.
// expected-error@+1{{invalid suffix 'f7' on floating constant}}
return 1.0f7;
}

float implausible_f0() {
// expected-error@+1{{invalid suffix 'f0' on floating constant}}
return 1.0f0;
}

float implausible_f31() {
// One off from a valid width.
// expected-error@+1{{invalid suffix 'f31' on floating constant}}
return 1.0f31;
}

float implausible_f33() {
// expected-error@+1{{invalid suffix 'f33' on floating constant}}
return 1.0f33;
}

float trailing_garbage_after_valid_width() {
// A valid fixed-size suffix followed by extra characters is still an
// invalid suffix.
// expected-error@+1{{invalid suffix 'f32x' on floating constant}}
return 1.0f32x;
}

float trailing_number_after_valid_width() {
// A valid fixed-size suffix followed by an extra number is still an invalid
// suffix.
// expected-error@+1{{invalid suffix 'f324' on floating constant}}
return 1.0f324;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// RUN: %dxc -T lib_6_3 -HV 2021 -verify %s

// In HLSL 2021 and earlier, the fixed-size float suffixes f16/f32/f64 should
// still work, but produce an extension warning. With -enable-16bit-types not
// passed, the 16-bit suffix should also error.

template <typename T, typename U>
struct is_same {
static const bool value = false;
};

template <typename T>
struct is_same<T, T> {
static const bool value = true;
};

float test_f32() {
// expected-warning@+1{{fixed-size floating-point literal suffix 'f32' is a HLSL 202x extension}}
return 1.0f32;
}

float test_F32() {
// expected-warning@+1{{fixed-size floating-point literal suffix 'F32' is a HLSL 202x extension}}
return 1.0F32;
}

double test_f64() {
// expected-warning@+1{{fixed-size floating-point literal suffix 'f64' is a HLSL 202x extension}}
return 1.0f64;
}

double test_F64() {
// expected-warning@+1{{fixed-size floating-point literal suffix 'F64' is a HLSL 202x extension}}
return 1.0F64;
}

// Without -enable-16bit-types the 16-bit suffix must error (in addition to the
// extension warning).
min16float test_f16() {
// expected-warning@+2{{fixed-size floating-point literal suffix 'f16' is a HLSL 202x extension}}
// expected-error@+1{{16-bit floating-point literal suffix 'f16' requires '-enable-16bit-types'}}
return 1.0f16;
}

min16float test_F16() {
// expected-warning@+2{{fixed-size floating-point literal suffix 'F16' is a HLSL 202x extension}}
// expected-error@+1{{16-bit floating-point literal suffix 'F16' requires '-enable-16bit-types'}}
return 1.0F16;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// RUN: %dxc -T lib_6_3 -HV 202x -verify %s

// In HLSL 202x mode without -enable-16bit-types, the 16-bit suffix must error
// while f32/f64 are accepted silently.

float test_f32() {
return 1.0f32; // no diagnostic
}

double test_f64() {
return 1.0f64; // no diagnostic
}

min16float test_f16() {
// expected-error@+1{{16-bit floating-point literal suffix 'f16' requires '-enable-16bit-types'}}
return 1.0f16;
}

min16float test_F16() {
// expected-error@+1{{16-bit floating-point literal suffix 'F16' requires '-enable-16bit-types'}}
return 1.0F16;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// RUN: %dxc -T lib_6_3 -HV 202x -enable-16bit-types -verify %s

// Verify that f16/F16/f32/F32/f64/F64 produce the expected types in HLSL 202x
// with native 16-bit types enabled.

template <typename T, typename U>
struct is_same {
static const bool value = false;
};

template <typename T>
struct is_same<T, T> {
static const bool value = true;
};

// expected-no-diagnostics

// 16-bit suffix -> float16_t (a.k.a. half / HalfTy).
_Static_assert(is_same<__decltype(1.0f16), half>::value, "1.0f16 is half");
_Static_assert(is_same<__decltype(1.0F16), half>::value, "1.0F16 is half");
_Static_assert(is_same<__decltype(2.5e1f16), half>::value, "2.5e1f16 is half");

// 32-bit suffix -> float, regardless of UseMinPrecision.
_Static_assert(is_same<__decltype(1.0f32), float>::value, "1.0f32 is float");
_Static_assert(is_same<__decltype(1.0F32), float>::value, "1.0F32 is float");
_Static_assert(is_same<__decltype(0.5e0f32), float>::value, "0.5e0f32 is float");

// 64-bit suffix -> double.
_Static_assert(is_same<__decltype(1.0f64), double>::value, "1.0f64 is double");
_Static_assert(is_same<__decltype(1.0F64), double>::value, "1.0F64 is double");
_Static_assert(is_same<__decltype(0.5e0f64), double>::value, "0.5e0f64 is double");

// Sanity check: the plain 'f' and 'h' suffixes still work.
_Static_assert(is_same<__decltype(1.0f), float>::value, "1.0f is float");
_Static_assert(is_same<__decltype(1.0h), half>::value, "1.0h is half");
_Static_assert(is_same<__decltype(1.0l), double>::value, "1.0l is double");

// The fixed-size suffix must not collide with an integer suffix.
_Static_assert(is_same<__decltype(1.f32), float>::value, ".f32 with no fraction digits is float");
Loading