summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYong He <yonghe@outlook.com>2024-06-12 09:45:26 -0700
committerGitHub <noreply@github.com>2024-06-12 09:45:26 -0700
commit318adcc27b8d89ec1d47c445a93239dd81be0b31 (patch)
tree939ae1ffe9a3e81a17d03e4c92c8ee13c6d822e8
parentec35febb7f1dcc981e83c7ee3e52ab516b50be8a (diff)
Add compiler option to treat enum types as unscoped. (#4354)
-rw-r--r--slang.h1
-rw-r--r--source/slang/slang-lookup.cpp6
-rw-r--r--source/slang/slang-options.cpp4
-rw-r--r--source/slang/slang-parser.cpp28
-rw-r--r--tests/language-feature/enums/anonymous-enum.slang19
-rw-r--r--tests/language-feature/enums/unscoped-enum-option.slang19
6 files changed, 74 insertions, 3 deletions
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 <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<UnscopedEnumAttribute>());
+ addModifier(decl, parser->astBuilder->create<TransparentModifier>());
+ }
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<int> 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<int> buffer;
+[numthreads(1, 1, 1)]
+void main(int id: SV_DispatchThreadID)
+{
+ if (id == Red)
+ {
+ buffer[0] = Green;
+ }
+ buffer[1] = Blue;
+}