summaryrefslogtreecommitdiffstats
path: root/source
diff options
context:
space:
mode:
authorTim Foley <tfoleyNV@users.noreply.github.com>2020-10-15 13:13:49 -0700
committerGitHub <noreply@github.com>2020-10-15 13:13:49 -0700
commitd3e255b31b39c9a8979a60023269567078d9dce3 (patch)
treed6915c1d0219eeea4d6fc257f6504ee4522840a4 /source
parent4149bf2c9ce4e9e1a8457da8a497cdb137eaad7c (diff)
Fix a bug in IR lowering (#1578)
The basic problem here is that when a function has multiple declarations with matching signatures (e.g., a forward declaration and then a later definition with a body), the IR lowering logic would lower all declarations whenever the first one was encountered, but then would only register an IR value as the lowered version of the first declaration. Other matching declarations would then run the risk of being lowered again, and in the case where they included features like loops with break/continue labels, that would create the risk of keys getting inserted into certain dictionaries more than one, leading to exceptions. This change ensures that when lowering a function that has multiple matching declarations to IR, we register an IR value for all of those declarations and not just the first. I have added a test case that leads to a crash without this change, to ensure that we don't introduce a regression down the line.
Diffstat (limited to 'source')
-rw-r--r--source/slang/slang-lower-to-ir.cpp13
1 files changed, 13 insertions, 0 deletions
diff --git a/source/slang/slang-lower-to-ir.cpp b/source/slang/slang-lower-to-ir.cpp
index e9381268b..ad7cec773 100644
--- a/source/slang/slang-lower-to-ir.cpp
+++ b/source/slang/slang-lower-to-ir.cpp
@@ -7154,6 +7154,19 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo>
auto funcDecl = as<FunctionDeclBase>(dd);
SLANG_ASSERT(funcDecl);
lowerFuncDecl(funcDecl);
+
+ // Note: Because we are iterating over multiple declarations,
+ // but only one will be registered as the value for `decl`
+ // in the global mapping by `ensureDecl()`, we have to take
+ // responsibility here for registering a lowered value
+ // for the remaining (non-primary) declarations.
+ //
+ // It doesn't really matter which one we register here, because
+ // they will all have the same mangled name in the IR, but we
+ // default to the `result` that is returned from this visitor,
+ // so that all the declarations share the same IR representative.
+ //
+ setGlobalValue(context->shared, funcDecl, result);
}
return result;
}