summaryrefslogtreecommitdiff
path: root/source/slang/slang-check-decl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/slang/slang-check-decl.cpp')
-rw-r--r--source/slang/slang-check-decl.cpp54
1 files changed, 54 insertions, 0 deletions
diff --git a/source/slang/slang-check-decl.cpp b/source/slang/slang-check-decl.cpp
index 10e3818c4..4ea8aa7f6 100644
--- a/source/slang/slang-check-decl.cpp
+++ b/source/slang/slang-check-decl.cpp
@@ -56,6 +56,8 @@ namespace Slang
void visitImportDecl(ImportDecl* decl);
+ void visitUsingDecl(UsingDecl* decl);
+
void visitGenericTypeParamDecl(GenericTypeParamDecl* decl);
void visitGenericValueParamDecl(GenericValueParamDecl* decl);
@@ -4615,6 +4617,58 @@ namespace Slang
}
}
+ void SemanticsDeclHeaderVisitor::visitUsingDecl(UsingDecl* decl)
+ {
+ // First, we need to look up whatever the argument of the `using`
+ // declaration names.
+ //
+ decl->arg = CheckTerm(decl->arg);
+
+ // Next, we want to ensure that whatever is being named by `decl->arg`
+ // is a namespace (or a module, since modules are namespace-like).
+ //
+ // TODO: The logic here assumes that we can't have multiple `NamespaceDecl`s
+ // with the same name in scope, but that assumption is only valid in the
+ // context of a single module (where we deduplicate `namespace`s during
+ // parsing). If a user `import`s multiple modules that all have namespaces
+ // of the same name, it would be possible for `decl->arg` to be overloaded.
+ // In that case we should really iterate over all the entities that are
+ // named and import any that are namespace-like.
+ //
+ NamespaceDeclBase* namespaceDecl = nullptr;
+ if( auto declRefExpr = as<DeclRefExpr>(decl->arg) )
+ {
+ if( auto namespaceDeclRef = declRefExpr->declRef.as<NamespaceDeclBase>() )
+ {
+ SLANG_ASSERT(!namespaceDeclRef.substitutions.substitutions);
+ namespaceDecl = namespaceDeclRef.getDecl();
+ }
+ }
+ if( !namespaceDecl )
+ {
+ getSink()->diagnose(decl->arg, Diagnostics::expectedANamespace, decl->arg->type);
+ return;
+ }
+
+ // Once we have identified the namespace to bring into scope,
+ // we need to create a new sibling sub-scope to add to the
+ // lookup scope that was in place when the `using` was parsed.
+ //
+ // Subsequent lookup in that scope will walk through our new
+ // sub-scope and see the namespace.
+ //
+ // TODO: If we update the `containerDecl` in a scope to allow
+ // for a more general `DeclRef`, or even a full `DeclRefExpr`,
+ // then it would be possible for `using` to apply to more kinds
+ // of entities than just namespaces.
+ //
+ auto scope = decl->scope;
+ auto subScope = new Scope();
+ subScope->containerDecl = namespaceDecl;
+ subScope->nextSibling = scope->nextSibling;
+ scope->nextSibling = subScope;
+ }
+
/// Get a reference to the candidate extension list for `typeDecl` in the given dictionary
///
/// Note: this function creates an empty list of candidates for the given type if