Skip to content

Commit 8cb2f95

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 2317c03 commit 8cb2f95

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
@@ -883,7 +883,7 @@ std::optional<uint32_t> RootSignatureParser::handleUIntLiteral() {
883883
// Report that the value has overflowed
884884
PP.getDiagnostics().Report(CurToken.TokLoc,
885885
diag::err_hlsl_number_literal_overflow)
886-
<< 0 << CurToken.NumSpelling;
886+
<< /*integer type*/ 0 << /*is signed*/ 0;
887887
return std::nullopt;
888888
}
889889

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

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

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

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

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

945965
if (Negated)
946966
Val = -Val;
947967

948968
double DoubleVal = Val.convertToDouble();
949969
if (FLT_MAX < DoubleVal || DoubleVal < -FLT_MAX) {
970+
// Report that the value has overflowed
971+
PP.getDiagnostics().Report(CurToken.TokLoc,
972+
diag::err_hlsl_number_literal_overflow)
973+
<< /*float type*/ 1;
950974
return std::nullopt;
951975
}
952976

clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -764,6 +764,90 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidLexOverflowedNumberTest) {
764764
ASSERT_TRUE(Consumer->isSatisfied());
765765
}
766766

767+
TEST_F(ParseHLSLRootSignatureTest, InvalidLexOverflowedFloatTest) {
768+
// This test will check that the lexing fails due to a float overflow
769+
const llvm::StringLiteral Source = R"cc(
770+
StaticSampler(s0, mipLODBias = 3.402823467e+38F)
771+
)cc";
772+
773+
TrivialModuleLoader ModLoader;
774+
auto PP = createPP(Source, ModLoader);
775+
auto TokLoc = SourceLocation();
776+
777+
hlsl::RootSignatureLexer Lexer(Source, TokLoc);
778+
SmallVector<RootElement> Elements;
779+
hlsl::RootSignatureParser Parser(Elements, Lexer, *PP);
780+
781+
// Test correct diagnostic produced
782+
Consumer->setExpected(diag::err_hlsl_number_literal_overflow);
783+
ASSERT_TRUE(Parser.parse());
784+
785+
ASSERT_TRUE(Consumer->isSatisfied());
786+
}
787+
788+
TEST_F(ParseHLSLRootSignatureTest, InvalidLexNegOverflowedFloatTest) {
789+
// This test will check that the lexing fails due to negative float overflow
790+
const llvm::StringLiteral Source = R"cc(
791+
StaticSampler(s0, mipLODBias = -3.402823467e+38F)
792+
)cc";
793+
794+
TrivialModuleLoader ModLoader;
795+
auto PP = createPP(Source, ModLoader);
796+
auto TokLoc = SourceLocation();
797+
798+
hlsl::RootSignatureLexer Lexer(Source, TokLoc);
799+
SmallVector<RootElement> Elements;
800+
hlsl::RootSignatureParser Parser(Elements, Lexer, *PP);
801+
802+
// Test correct diagnostic produced
803+
Consumer->setExpected(diag::err_hlsl_number_literal_overflow);
804+
ASSERT_TRUE(Parser.parse());
805+
806+
ASSERT_TRUE(Consumer->isSatisfied());
807+
}
808+
809+
TEST_F(ParseHLSLRootSignatureTest, InvalidLexOverflowedDoubleTest) {
810+
// This test will check that the lexing fails due to an overflow of double
811+
const llvm::StringLiteral Source = R"cc(
812+
StaticSampler(s0, mipLODBias = 1.e+500)
813+
)cc";
814+
815+
TrivialModuleLoader ModLoader;
816+
auto PP = createPP(Source, ModLoader);
817+
auto TokLoc = SourceLocation();
818+
819+
hlsl::RootSignatureLexer Lexer(Source, TokLoc);
820+
SmallVector<RootElement> Elements;
821+
hlsl::RootSignatureParser Parser(Elements, Lexer, *PP);
822+
823+
// Test correct diagnostic produced
824+
Consumer->setExpected(diag::err_hlsl_number_literal_overflow);
825+
ASSERT_TRUE(Parser.parse());
826+
827+
ASSERT_TRUE(Consumer->isSatisfied());
828+
}
829+
830+
TEST_F(ParseHLSLRootSignatureTest, InvalidLexUnderflowFloatTest) {
831+
// This test will check that the lexing fails due to double underflow
832+
const llvm::StringLiteral Source = R"cc(
833+
StaticSampler(s0, mipLODBias = 10e-309)
834+
)cc";
835+
836+
TrivialModuleLoader ModLoader;
837+
auto PP = createPP(Source, ModLoader);
838+
auto TokLoc = SourceLocation();
839+
840+
hlsl::RootSignatureLexer Lexer(Source, TokLoc);
841+
SmallVector<RootElement> Elements;
842+
hlsl::RootSignatureParser Parser(Elements, Lexer, *PP);
843+
844+
// Test correct diagnostic produced
845+
Consumer->setExpected(diag::err_hlsl_number_literal_underflow);
846+
ASSERT_TRUE(Parser.parse());
847+
848+
ASSERT_TRUE(Consumer->isSatisfied());
849+
}
850+
767851
TEST_F(ParseHLSLRootSignatureTest, InvalidNonZeroFlagsTest) {
768852
// This test will check that parsing fails when a non-zero integer literal
769853
// is given to flags

0 commit comments

Comments
 (0)