diff --git a/tslang/lib/TypeScript/MLIRGenInterfaces.cpp b/tslang/lib/TypeScript/MLIRGenInterfaces.cpp index ebeb39c4a..cf1ca3c70 100644 --- a/tslang/lib/TypeScript/MLIRGenInterfaces.cpp +++ b/tslang/lib/TypeScript/MLIRGenInterfaces.cpp @@ -42,6 +42,8 @@ namespace mlirgen auto activeBits = 32; mlir::IntegerType::SignednessSemantics currentEnumValueSigedness = mlir::IntegerType::SignednessSemantics::Signless; llvm::APInt currentEnumValue(32, 0); + // a member after a string member has no value to count on from + auto previousIsString = false; for (auto enumMember : enumDeclarationAST->members) { auto location = loc(enumMember); @@ -104,6 +106,12 @@ namespace mlirgen } else { + if (previousIsString) + { + emitError(loc(enumMember)) << "Enum member '" << memberNamePtr << "' must have initializer"; + return mlir::failure(); + } + if (appending && currentEnumValue == 0 && stage == Stages::Discovering && !enumValues.contains(memberNamePtr)) { emitError(loc(enumMember)) @@ -126,6 +134,7 @@ namespace mlirgen LLVM_DEBUG(llvm::dbgs() << "\n!! enum: " << namePtr << " value attr: " << enumValueAttr << "\n"); enumValues[memberNamePtr] = enumValueAttr; + previousIsString = isa(enumValueAttr); // update enum to support req. access SmallVector namedEnumValues; diff --git a/tslang/test/tester/CMakeLists.txt b/tslang/test/tester/CMakeLists.txt index e92db2eb9..60d44f096 100644 --- a/tslang/test/tester/CMakeLists.txt +++ b/tslang/test/tester/CMakeLists.txt @@ -2947,6 +2947,16 @@ set_tests_properties(test-compile-diagnostic-location-implicit-constructor PROPERTIES PASS_REGULAR_EXPRESSION "implicit_constructor\\.ts:9:1: error: Class constructor is not accessable" FAIL_REGULAR_EXPRESSION "Stack dump|Assertion failed|implicit_constructor\\.ts:1:") +# An enum member after a string member needs an initializer: it took the count of the members +# before it. +add_test(NAME test-compile-diagnostic-location-enum-member-initializer + COMMAND $ --emit=obj --no-default-lib -mm=none + "${PROJECT_SOURCE_DIR}/test/tester/diagnostic-location/enum_member_initializer.ts" + -o "${CMAKE_CURRENT_BINARY_DIR}/diagnostic-location-enum-member-initializer.obj") +set_tests_properties(test-compile-diagnostic-location-enum-member-initializer + PROPERTIES PASS_REGULAR_EXPRESSION "enum_member_initializer\\.ts:7:5: error: Enum member 'B' must have initializer" + FAIL_REGULAR_EXPRESSION "Stack dump|Assertion failed|enum_member_initializer\\.ts:5:") + # An error in the code the compiler makes for a statement (a for...of's or for...in's loop) is # reported at the statement, and one in a `using`'s dispose call at the declaration - not at 1:1, # as a node the compiler makes has no position of its own. diff --git a/tslang/test/tester/diagnostic-location/enum_member_initializer.ts b/tslang/test/tester/diagnostic-location/enum_member_initializer.ts new file mode 100644 index 000000000..ce3b64a82 --- /dev/null +++ b/tslang/test/tester/diagnostic-location/enum_member_initializer.ts @@ -0,0 +1,12 @@ +// A member after a string member, with no initializer, had no value to count on from: it +// quietly took the count of the members before. + +enum E { + N, + A = "x", + B, +} + +function main() { + print(E.B); +}