summaryrefslogtreecommitdiffstats
path: root/source
diff options
context:
space:
mode:
authorTim Foley <tfoleyNV@users.noreply.github.com>2019-01-30 14:35:44 -0800
committerGitHub <noreply@github.com>2019-01-30 14:35:44 -0800
commitdc018032ee82911030601fa1cd3ca39ca107ad44 (patch)
treed6af784d70f78e58ab02500c5740ddc812347ba9 /source
parent685a811e3d4405c4619e974e3610902d621efee7 (diff)
Fix parsing of modifiers on generic declarations (#816)
The way we handle generics in the AST is to have a `GenericDecl` AST node that can wrap an arbitrary "inner" `Decl`. This representation has proved valuable, but it also creates some gotchas because a `GenericDecl` is also a `Decl`. One example of where this can be tricky is for attributes and other modifiers attached to something generic: ```hlsl [special] void foo<T>(...) { ... } ``` In this case, the current parser logic was gobbling up a list of `Modifier`s (including the `[special]` attribute here), then parsing the declaration that follows, and then attaching those modifiers to the resulting declaration. In this case, however, the "resulting declaration" is not a `FuncDecl` as one might expect, but the `GenericDecl` that wraps it. The solution is pretty simple: when we are done parsing a declaration and are going to attach the modifiers we parsed to it, we should first "unwrap" any outer `GenericDecl` and apply the modifiers to the thing inside instead. This logic presumes that modifiers always want to apply to the inner declaration and not to the generic, an that seems reasonable for now. If we wanted we could add some special-case logic later in the compiler to implicitly "float" certain modifiers up to the generic, in cases where they are found to be inappropriate for the inner declaration.
Diffstat (limited to 'source')
-rw-r--r--source/slang/parser.cpp9
1 files changed, 8 insertions, 1 deletions
diff --git a/source/slang/parser.cpp b/source/slang/parser.cpp
index 5cc048cf5..914ec0a23 100644
--- a/source/slang/parser.cpp
+++ b/source/slang/parser.cpp
@@ -2992,7 +2992,14 @@ namespace Slang
{
// Add any modifiers we parsed before the declaration to the list
// of modifiers on the declaration itself.
- AddModifiers(decl.Ptr(), modifiers.first);
+ //
+ // We need to be careful, because if `decl` is a generic declaration,
+ // then we really want the modifiers to apply to the inner declaration.
+ //
+ RefPtr<Decl> declToModify = decl;
+ if(auto genericDecl = decl.As<GenericDecl>())
+ declToModify = genericDecl->inner;
+ AddModifiers(declToModify.Ptr(), modifiers.first);
// Make sure the decl is properly nested inside its lexical parent
if (containerDecl)