Skip to content

Commit 5d2a90f

Browse files
committed
add testing for over/underflow and addresses other opStatus
- updates the error message to account for floats and fixes the previous use cases
1 parent d4608c3 commit 5d2a90f

File tree

3 files changed

+120
-8
lines changed

3 files changed

+120
-8
lines changed

clang/include/clang/Basic/DiagnosticParseKinds.td

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1856,7 +1856,11 @@ def err_hlsl_unexpected_end_of_params
18561856
: Error<"expected %0 to denote end of parameters, or, another valid parameter of %1">;
18571857
def err_hlsl_rootsig_repeat_param : Error<"specified the same parameter '%0' multiple times">;
18581858
def err_hlsl_rootsig_missing_param : Error<"did not specify mandatory parameter '%0'">;
1859-
def err_hlsl_number_literal_overflow : Error<"integer literal is too large to be represented as a 32-bit %select{signed |}0 integer type">;
1859+
def err_hlsl_number_literal_overflow : Error<
1860+
"%select{integer|float}0 literal is too large to be represented as a "
1861+
"%select{32-bit %select{signed|}1 integer|float}0 type">;
1862+
def err_hlsl_number_literal_underflow : Error<
1863+
"float literal has a magnitude that is too small to be represented as a float type">;
18601864
def err_hlsl_rootsig_non_zero_flag : Error<"flag value is neither a literal 0 nor a named value">;
18611865

18621866
} // end of Parser diagnostics

clang/lib/Parse/ParseHLSLRootSignature.cpp

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -881,7 +881,7 @@ std::optional<uint32_t> RootSignatureParser::handleUIntLiteral() {
881881
// Report that the value has overflowed
882882
PP.getDiagnostics().Report(CurToken.TokLoc,
883883
diag::err_hlsl_number_literal_overflow)
884-
<< 0 << CurToken.NumSpelling;
884+
<< /*integer type*/ 0 << /*is signed*/ 0;
885885
return std::nullopt;
886886
}
887887

@@ -904,7 +904,7 @@ std::optional<int32_t> RootSignatureParser::handleIntLiteral(bool Negated) {
904904
// Report that the value has overflowed
905905
PP.getDiagnostics().Report(CurToken.TokLoc,
906906
diag::err_hlsl_number_literal_overflow)
907-
<< 0 << CurToken.NumSpelling;
907+
<< /*integer type*/ 0 << /*is signed*/ 1;
908908
return std::nullopt;
909909
}
910910

@@ -923,8 +923,8 @@ std::optional<float> RootSignatureParser::handleFloatLiteral(bool Negated) {
923923
return std::nullopt; // Error has already been reported so just return
924924

925925
assert(Literal.isFloatingLiteral() &&
926-
"NumSpelling is consistent with isNumberChar in "
927-
"LexHLSLRootSignature.cpp");
926+
"NumSpelling consists only of [0-9.ef+-]. Any malformed NumSpelling "
927+
"will be caught and reported by NumericLiteralParser.");
928928

929929
// DXC used `strtod` to convert the token string to a float which corresponds
930930
// to:
@@ -935,16 +935,40 @@ std::optional<float> RootSignatureParser::handleFloatLiteral(bool Negated) {
935935
llvm::APFloat(llvm::APFloat::EnumToSemantics(DXCSemantics));
936936
llvm::APFloat::opStatus Status = Literal.GetFloatValue(Val, DXCRoundingMode);
937937

938-
// The float is valid with opInexect as this just denotes if rounding occured
939-
if (Status != llvm::APFloat::opStatus::opOK &&
940-
Status != llvm::APFloat::opStatus::opInexact)
938+
// Note: we do not error when opStatus::opInexact by itself as this just
939+
// denotes that rounding occured but not that it is invalid
940+
assert(!(Status & llvm::APFloat::opStatus::opInvalidOp) &&
941+
"NumSpelling consists only of [0-9.ef+-]. Any malformed NumSpelling "
942+
"will be caught and reported by NumericLiteralParser.");
943+
944+
assert(!(Status & llvm::APFloat::opStatus::opDivByZero) &&
945+
"It is not possible for a division to be performed when "
946+
"constructing an APFloat from a string");
947+
948+
if (Status & llvm::APFloat::opStatus::opUnderflow) {
949+
// Report that the value has underflowed
950+
PP.getDiagnostics().Report(CurToken.TokLoc,
951+
diag::err_hlsl_number_literal_underflow);
941952
return std::nullopt;
953+
}
954+
955+
if (Status & llvm::APFloat::opStatus::opOverflow) {
956+
// Report that the value has overflowed
957+
PP.getDiagnostics().Report(CurToken.TokLoc,
958+
diag::err_hlsl_number_literal_overflow)
959+
<< /*float type*/ 1;
960+
return std::nullopt;
961+
}
942962

943963
if (Negated)
944964
Val = -Val;
945965

946966
double DoubleVal = Val.convertToDouble();
947967
if (FLT_MAX < DoubleVal || DoubleVal < -FLT_MAX) {
968+
// Report that the value has overflowed
969+
PP.getDiagnostics().Report(CurToken.TokLoc,
970+
diag::err_hlsl_number_literal_overflow)
971+
<< /*float type*/ 1;
948972
return std::nullopt;
949973
}
950974

clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -793,6 +793,90 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidLexOverflowedNumberTest) {
793793
ASSERT_TRUE(Consumer->isSatisfied());
794794
}
795795

796+
TEST_F(ParseHLSLRootSignatureTest, InvalidLexOverflowedFloatTest) {
797+
// This test will check that the lexing fails due to a float overflow
798+
const llvm::StringLiteral Source = R"cc(
799+
StaticSampler(s0, mipLODBias = 3.402823467e+38F)
800+
)cc";
801+
802+
TrivialModuleLoader ModLoader;
803+
auto PP = createPP(Source, ModLoader);
804+
auto TokLoc = SourceLocation();
805+
806+
hlsl::RootSignatureLexer Lexer(Source, TokLoc);
807+
SmallVector<RootElement> Elements;
808+
hlsl::RootSignatureParser Parser(Elements, Lexer, *PP);
809+
810+
// Test correct diagnostic produced
811+
Consumer->setExpected(diag::err_hlsl_number_literal_overflow);
812+
ASSERT_TRUE(Parser.parse());
813+
814+
ASSERT_TRUE(Consumer->isSatisfied());
815+
}
816+
817+
TEST_F(ParseHLSLRootSignatureTest, InvalidLexNegOverflowedFloatTest) {
818+
// This test will check that the lexing fails due to negative float overflow
819+
const llvm::StringLiteral Source = R"cc(
820+
StaticSampler(s0, mipLODBias = -3.402823467e+38F)
821+
)cc";
822+
823+
TrivialModuleLoader ModLoader;
824+
auto PP = createPP(Source, ModLoader);
825+
auto TokLoc = SourceLocation();
826+
827+
hlsl::RootSignatureLexer Lexer(Source, TokLoc);
828+
SmallVector<RootElement> Elements;
829+
hlsl::RootSignatureParser Parser(Elements, Lexer, *PP);
830+
831+
// Test correct diagnostic produced
832+
Consumer->setExpected(diag::err_hlsl_number_literal_overflow);
833+
ASSERT_TRUE(Parser.parse());
834+
835+
ASSERT_TRUE(Consumer->isSatisfied());
836+
}
837+
838+
TEST_F(ParseHLSLRootSignatureTest, InvalidLexOverflowedDoubleTest) {
839+
// This test will check that the lexing fails due to an overflow of double
840+
const llvm::StringLiteral Source = R"cc(
841+
StaticSampler(s0, mipLODBias = 1.e+500)
842+
)cc";
843+
844+
TrivialModuleLoader ModLoader;
845+
auto PP = createPP(Source, ModLoader);
846+
auto TokLoc = SourceLocation();
847+
848+
hlsl::RootSignatureLexer Lexer(Source, TokLoc);
849+
SmallVector<RootElement> Elements;
850+
hlsl::RootSignatureParser Parser(Elements, Lexer, *PP);
851+
852+
// Test correct diagnostic produced
853+
Consumer->setExpected(diag::err_hlsl_number_literal_overflow);
854+
ASSERT_TRUE(Parser.parse());
855+
856+
ASSERT_TRUE(Consumer->isSatisfied());
857+
}
858+
859+
TEST_F(ParseHLSLRootSignatureTest, InvalidLexUnderflowFloatTest) {
860+
// This test will check that the lexing fails due to double underflow
861+
const llvm::StringLiteral Source = R"cc(
862+
StaticSampler(s0, mipLODBias = 10e-309)
863+
)cc";
864+
865+
TrivialModuleLoader ModLoader;
866+
auto PP = createPP(Source, ModLoader);
867+
auto TokLoc = SourceLocation();
868+
869+
hlsl::RootSignatureLexer Lexer(Source, TokLoc);
870+
SmallVector<RootElement> Elements;
871+
hlsl::RootSignatureParser Parser(Elements, Lexer, *PP);
872+
873+
// Test correct diagnostic produced
874+
Consumer->setExpected(diag::err_hlsl_number_literal_underflow);
875+
ASSERT_TRUE(Parser.parse());
876+
877+
ASSERT_TRUE(Consumer->isSatisfied());
878+
}
879+
796880
TEST_F(ParseHLSLRootSignatureTest, InvalidNonZeroFlagsTest) {
797881
// This test will check that parsing fails when a non-zero integer literal
798882
// is given to flags

0 commit comments

Comments
 (0)