From 318adcc27b8d89ec1d47c445a93239dd81be0b31 Mon Sep 17 00:00:00 2001 From: Yong He Date: Wed, 12 Jun 2024 09:45:26 -0700 Subject: Add compiler option to treat enum types as unscoped. (#4354) --- slang.h | 1 + source/slang/slang-lookup.cpp | 6 +++++ source/slang/slang-options.cpp | 4 +++- source/slang/slang-parser.cpp | 28 ++++++++++++++++++++-- tests/language-feature/enums/anonymous-enum.slang | 19 +++++++++++++++ .../enums/unscoped-enum-option.slang | 19 +++++++++++++++ 6 files changed, 74 insertions(+), 3 deletions(-) create mode 100644 tests/language-feature/enums/anonymous-enum.slang create mode 100644 tests/language-feature/enums/unscoped-enum-option.slang diff --git a/slang.h b/slang.h index d807efec4..ea87daeb4 100644 --- a/slang.h +++ b/slang.h @@ -865,6 +865,7 @@ extern "C" MinimumSlangOptimization, // bool DisableNonEssentialValidations, // bool DisableSourceMap, // bool + UnscopedEnum, // bool PreserveParameters, // bool: preserve all resource parameters in the output code. // Target diff --git a/source/slang/slang-lookup.cpp b/source/slang/slang-lookup.cpp index 5e30e3ce9..c1895d754 100644 --- a/source/slang/slang-lookup.cpp +++ b/source/slang/slang-lookup.cpp @@ -224,6 +224,12 @@ static void _lookUpDirectAndTransparentMembers( } } + // Don't look up transparent members if we are looking for attributes, since + // they are always defined at global scope in the stdlib. Trying to lookup transparent + // members during attribute lookup can lead to infinite recursion on transparent types. + if ((int)request.mask & (int)LookupMask::Attribute) + return; + for(auto transparentInfo : containerDecl->getTransparentMembers()) { // The reference to the transparent member should use the same diff --git a/source/slang/slang-options.cpp b/source/slang/slang-options.cpp index aefb14deb..04d48c85f 100644 --- a/source/slang/slang-options.cpp +++ b/source/slang/slang-options.cpp @@ -347,6 +347,7 @@ void initCommandOptions(CommandOptions& options) { OptionKind::SourceEmbedLanguage, "-source-embed-language", "-source-embed-language ", "The language to be used for source embedding. Defaults to C/C++. Currently only C/C++ are supported"}, { OptionKind::DisableShortCircuit, "-disable-short-circuit", nullptr, "Disable short-circuiting for \"&&\" and \"||\" operations" }, + { OptionKind::UnscopedEnum, "-unscoped-enum", nullptr, "Treat enums types as unscoped by default."} { OptionKind::PreserveParameters, "-preserve-params", nullptr, "Preserve all resource parameters in the output code, even if they are not used by the shader."} }; @@ -1705,8 +1706,9 @@ SlangResult OptionsParser::_parse( case OptionKind::NoHLSLBinding: case OptionKind::NoHLSLPackConstantBufferElements: case OptionKind::LoopInversion: + case OptionKind::UnscopedEnum: case OptionKind::PreserveParameters: - linkage->m_optionSet.set(optionKind, true); break; + linkage->m_optionSet.set(optionKind, true); break; case OptionKind::MatrixLayoutRow: case OptionKind::MatrixLayoutColumn: diff --git a/source/slang/slang-parser.cpp b/source/slang/slang-parser.cpp index f5a217354..3d9f1c199 100644 --- a/source/slang/slang-parser.cpp +++ b/source/slang/slang-parser.cpp @@ -4907,14 +4907,38 @@ namespace Slang // TODO: diagnose this with a warning some day, and move // toward deprecating it. // - AdvanceIf(parser, "class"); + bool isEnumClass = AdvanceIf(parser, "class"); + bool isUnscoped = false; + + if (!isEnumClass) + { + if (parser->options.optionSet.getBoolOption(CompilerOptionName::UnscopedEnum)) + { + isUnscoped = true; + } + } AdvanceIf(parser, TokenType::CompletionRequest); parser->FillPosition(decl); - decl->nameAndLoc = expectIdentifier(parser); + if (parser->tokenReader.peekTokenType() != TokenType::Identifier) + { + decl->nameAndLoc.name = generateName(parser); + decl->nameAndLoc.loc = decl->loc; + isUnscoped = true; + } + else + { + decl->nameAndLoc = expectIdentifier(parser); + } + // If the type needs to be unscoped, insert modifiers to make it so. + if (isUnscoped) + { + addModifier(decl, parser->astBuilder->create()); + addModifier(decl, parser->astBuilder->create()); + } return parseOptGenericDecl(parser, [&](GenericDecl*) { diff --git a/tests/language-feature/enums/anonymous-enum.slang b/tests/language-feature/enums/anonymous-enum.slang new file mode 100644 index 000000000..b9b0a8c00 --- /dev/null +++ b/tests/language-feature/enums/anonymous-enum.slang @@ -0,0 +1,19 @@ +//TEST:SIMPLE(filecheck=CHECK): -target spirv + +// CHECK: OpEntryPoint + +enum +{ + Red,Green,Blue +} + +RWStructuredBuffer buffer; +[numthreads(1, 1, 1)] +void main(int id: SV_DispatchThreadID) +{ + if (id == Red) + { + buffer[0] = Green; + } + buffer[1] = Blue; +} diff --git a/tests/language-feature/enums/unscoped-enum-option.slang b/tests/language-feature/enums/unscoped-enum-option.slang new file mode 100644 index 000000000..4628ac235 --- /dev/null +++ b/tests/language-feature/enums/unscoped-enum-option.slang @@ -0,0 +1,19 @@ +//TEST:SIMPLE(filecheck=CHECK): -target spirv -unscoped-enum + +// CHECK: OpEntryPoint + +enum Color +{ + Red,Green,Blue +} + +RWStructuredBuffer buffer; +[numthreads(1, 1, 1)] +void main(int id: SV_DispatchThreadID) +{ + if (id == Red) + { + buffer[0] = Green; + } + buffer[1] = Blue; +} -- cgit v1.2.3