diff options
| author | Darren Wihandi <65404740+fairywreath@users.noreply.github.com> | 2024-12-03 16:40:09 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-12-03 13:40:09 -0800 |
| commit | 98cab6fa86c9e594fb69571cf1d864294b0aae45 (patch) | |
| tree | 37528d00b3d280c6ea68f26657aafa539c7b5636 /source | |
| parent | 600cce28606ba36b31756bf0422d892d0e242b63 (diff) | |
Conform non-suffixed integer literals (#5717)
* Make non-suffixed integer literal type resolution conform to C
* Update integer literal tests
* Clean up integer literal implementation a bit
* Update docs on integer literals
* Clean up docs update
* Clean up docs update
* Add comment on INT64_MIN edge case
* Fixed failing test, fixed formatting and cleaned up code
---------
Co-authored-by: Yong He <yonghe@outlook.com>
Diffstat (limited to 'source')
| -rw-r--r-- | source/compiler-core/slang-lexer.cpp | 10 | ||||
| -rw-r--r-- | source/compiler-core/slang-lexer.h | 5 | ||||
| -rw-r--r-- | source/slang/slang-diagnostic-defs.h | 6 | ||||
| -rw-r--r-- | source/slang/slang-parser.cpp | 83 |
4 files changed, 92 insertions, 12 deletions
diff --git a/source/compiler-core/slang-lexer.cpp b/source/compiler-core/slang-lexer.cpp index bf109e7fb..84a4df93b 100644 --- a/source/compiler-core/slang-lexer.cpp +++ b/source/compiler-core/slang-lexer.cpp @@ -673,7 +673,10 @@ static int _readOptionalBase(char const** ioCursor) } -IntegerLiteralValue getIntegerLiteralValue(Token const& token, UnownedStringSlice* outSuffix) +IntegerLiteralValue getIntegerLiteralValue( + Token const& token, + UnownedStringSlice* outSuffix, + bool* outIsDecimalBase) { IntegerLiteralValue value = 0; @@ -698,6 +701,11 @@ IntegerLiteralValue getIntegerLiteralValue(Token const& token, UnownedStringSlic *outSuffix = UnownedStringSlice(cursor, end); } + if (outIsDecimalBase) + { + *outIsDecimalBase = (base == 10); + } + return value; } diff --git a/source/compiler-core/slang-lexer.h b/source/compiler-core/slang-lexer.h index a9883ced6..a36719ab7 100644 --- a/source/compiler-core/slang-lexer.h +++ b/source/compiler-core/slang-lexer.h @@ -172,7 +172,10 @@ String getFileNameTokenValue(Token const& token); typedef int64_t IntegerLiteralValue; typedef double FloatingPointLiteralValue; -IntegerLiteralValue getIntegerLiteralValue(Token const& token, UnownedStringSlice* outSuffix = 0); +IntegerLiteralValue getIntegerLiteralValue( + Token const& token, + UnownedStringSlice* outSuffix = 0, + bool* outIsDecimalBase = 0); FloatingPointLiteralValue getFloatingPointLiteralValue( Token const& token, UnownedStringSlice* outSuffix = 0); diff --git a/source/slang/slang-diagnostic-defs.h b/source/slang/slang-diagnostic-defs.h index f37d6a8b6..d0f743e5c 100644 --- a/source/slang/slang-diagnostic-defs.h +++ b/source/slang/slang-diagnostic-defs.h @@ -1574,6 +1574,12 @@ DIAGNOSTIC( Error, invalidFloatingPointLiteralSuffix, "invalid suffix '$0' on floating-point literal") +DIAGNOSTIC( + 39999, + Warning, + integerLiteralTooLarge, + "integer literal is too large to be represented in a signed integer type, interpreting as " + "unsigned") DIAGNOSTIC( 39999, diff --git a/source/slang/slang-parser.cpp b/source/slang/slang-parser.cpp index 61d6ca1dc..8fb3be39c 100644 --- a/source/slang/slang-parser.cpp +++ b/source/slang/slang-parser.cpp @@ -3136,8 +3136,7 @@ static Modifier* ParseSemantic(Parser* parser) BitFieldModifier* bitWidthMod = parser->astBuilder->create<BitFieldModifier>(); parser->FillPosition(bitWidthMod); const auto token = parser->tokenReader.advanceToken(); - UnownedStringSlice suffix; - bitWidthMod->width = getIntegerLiteralValue(token, &suffix); + bitWidthMod->width = getIntegerLiteralValue(token); return bitWidthMod; } else if (parser->LookAheadToken(TokenType::CompletionRequest)) @@ -6638,6 +6637,64 @@ static IntegerLiteralValue _fixIntegerLiteral( return value; } +static BaseType _determineNonSuffixedIntegerLiteralType( + IntegerLiteralValue value, + bool isDecimalBase, + Token* token, + DiagnosticSink* sink) +{ + const uint64_t rawValue = (uint64_t)value; + + /// Non-suffixed integer literal types + /// + /// The type is the first from the following list in which the value can fit: + /// - For decimal bases: + /// - `int` + /// - `int64_t` + /// - For non-decimal bases: + /// - `int` + /// - `uint` + /// - `int64_t` + /// - `uint64_t` + /// + /// The lexer scans the negative(-) part of literal separately, and the value part here + /// is always positive hence it is sufficient to only compare with the maximum limits. + BaseType baseType; + if (rawValue <= INT32_MAX) + { + baseType = BaseType::Int; + } + else if ((rawValue <= UINT32_MAX) && !isDecimalBase) + { + baseType = BaseType::UInt; + } + else if (rawValue <= INT64_MAX) + { + baseType = BaseType::Int64; + } + else + { + baseType = BaseType::UInt64; + + if (isDecimalBase) + { + // There is an edge case here where 9223372036854775808 or INT64_MAX + 1 + // brings us here, but the complete literal is -9223372036854775808 or INT64_MIN and is + // valid. Unfortunately because the lexer handles the negative(-) part of the literal + // separately it is impossible to know whether the literal has a negative sign or not. + // We emit the warning and initially process it as a uint64 anyways, and the negative + // sign will be properly parsed and the value will still be properly stored as a + // negative INT64_MIN. + + // Decimal integer is too large to be represented as signed. + // Output warning that it is represented as unsigned instead. + sink->diagnose(*token, Diagnostics::integerLiteralTooLarge); + } + } + + return baseType; +} + static bool _isCast(Parser* parser, Expr* expr) { if (as<PointerTypeExpr>(expr)) @@ -6925,20 +6982,18 @@ static Expr* parseAtomicExpr(Parser* parser) constExpr->token = token; UnownedStringSlice suffix; - IntegerLiteralValue value = getIntegerLiteralValue(token, &suffix); + bool isDecimalBase; + IntegerLiteralValue value = getIntegerLiteralValue(token, &suffix, &isDecimalBase); // Look at any suffix on the value char const* suffixCursor = suffix.begin(); const char* const suffixEnd = suffix.end(); + const bool suffixExists = (suffixCursor != suffixEnd); - // If no suffix is defined go with the default - BaseType suffixBaseType = BaseType::Int; - - if (suffixCursor < suffixEnd) + // Mark as void, taken as an error + BaseType suffixBaseType = BaseType::Void; + if (suffixExists) { - // Mark as void, taken as an error - suffixBaseType = BaseType::Void; - int lCount = 0; int uCount = 0; int zCount = 0; @@ -7008,6 +7063,14 @@ static Expr* parseAtomicExpr(Parser* parser) suffixBaseType = BaseType::Int; } } + else + { + suffixBaseType = _determineNonSuffixedIntegerLiteralType( + value, + isDecimalBase, + &token, + parser->sink); + } value = _fixIntegerLiteral(suffixBaseType, value, &token, parser->sink); |
