summaryrefslogtreecommitdiff
path: root/source/slang/slang-check-decl.cpp
diff options
context:
space:
mode:
authorYong He <yonghe@outlook.com>2022-07-12 22:45:05 -0700
committerGitHub <noreply@github.com>2022-07-12 22:45:05 -0700
commit049aac1b80143753b4b3449e529024bafe2250be (patch)
treee6734ef240bf7016562a301009add1761caf06f6 /source/slang/slang-check-decl.cpp
parenta6775666c38ccaeb2a991921a08343afa09c659b (diff)
Support `class` types. (#2321)
* Support `class` types. * Ignore class-keyword test * Fix codereview comments and warnings. Co-authored-by: Yong He <yhe@nvidia.com>
Diffstat (limited to 'source/slang/slang-check-decl.cpp')
-rw-r--r--source/slang/slang-check-decl.cpp78
1 files changed, 78 insertions, 0 deletions
diff --git a/source/slang/slang-check-decl.cpp b/source/slang/slang-check-decl.cpp
index 94858b679..22567c889 100644
--- a/source/slang/slang-check-decl.cpp
+++ b/source/slang/slang-check-decl.cpp
@@ -90,6 +90,8 @@ namespace Slang
void visitStructDecl(StructDecl* decl);
+ void visitClassDecl(ClassDecl* decl);
+
/// Get the type of the storage accessed by an accessor.
///
/// The type of storage is determined by the parent declaration.
@@ -149,6 +151,8 @@ namespace Slang
void visitStructDecl(StructDecl* decl);
+ void visitClassDecl(ClassDecl* decl);
+
void visitEnumDecl(EnumDecl* decl);
/// Validate that the target type of an extension `decl` is valid.
@@ -1065,6 +1069,11 @@ namespace Slang
}
}
+ void SemanticsDeclHeaderVisitor::visitClassDecl(ClassDecl* classDecl)
+ {
+ SLANG_UNUSED(classDecl);
+ }
+
void SemanticsDeclBodyVisitor::checkVarDeclCommon(VarDeclBase* varDecl)
{
if (auto initExpr = varDecl->initExpr)
@@ -3370,6 +3379,75 @@ namespace Slang
}
}
+ void SemanticsDeclBasesVisitor::visitClassDecl(ClassDecl* decl)
+ {
+ // A `class` type can only inherit from `class` or `interface` types.
+ //
+ // Furthermore, only the first inheritance clause (in source
+ // order) is allowed to declare a base `class` type.
+ //
+ Index inheritanceClauseCounter = 0;
+ for (auto inheritanceDecl : decl->getMembersOfType<InheritanceDecl>())
+ {
+ Index inheritanceClauseIndex = inheritanceClauseCounter++;
+
+ ensureDecl(inheritanceDecl, DeclCheckState::CanUseBaseOfInheritanceDecl);
+ auto baseType = inheritanceDecl->base.type;
+
+ // It is possible that there was an error in checking the base type
+ // expression, and in such a case we shouldn't emit a cascading error.
+ //
+ if (auto baseErrorType = as<ErrorType>(baseType))
+ {
+ continue;
+ }
+
+ auto baseDeclRefType = as<DeclRefType>(baseType);
+ if (!baseDeclRefType)
+ {
+ getSink()->diagnose(inheritanceDecl, Diagnostics::baseOfClassMustBeClassOrInterface, decl, baseType);
+ continue;
+ }
+
+ auto baseDeclRef = baseDeclRefType->declRef;
+ if (auto baseInterfaceDeclRef = baseDeclRef.as<InterfaceDecl>())
+ {
+ }
+ else if (auto baseStructDeclRef = baseDeclRef.as<ClassDecl>())
+ {
+ // To simplify the task of reading and maintaining code,
+ // we require that when a `class` inherits from another
+ // `class`, the base `class` is the first item in
+ // the list of bases (before any interfaces).
+ //
+ // This constraint also has the secondary effect of restricting
+ // it so that a `struct` cannot multiply inherit from other
+ // `struct` types.
+ //
+ if (inheritanceClauseIndex != 0)
+ {
+ getSink()->diagnose(inheritanceDecl, Diagnostics::baseClassMustBeListedFirst, decl, baseType);
+ }
+ }
+ else
+ {
+ getSink()->diagnose(inheritanceDecl, Diagnostics::baseOfClassMustBeClassOrInterface, decl, baseType);
+ continue;
+ }
+
+ // TODO: At this point we have the `baseDeclRef`
+ // and could use it to perform further validity checks,
+ // and/or to build up a more refined representation of
+ // the inheritance graph for this type (e.g., a "class
+ // precedence list").
+ //
+ // E.g., we can/should check that we aren't introducing
+ // a circular inheritance relationship.
+
+ _validateCrossModuleInheritance(decl, inheritanceDecl);
+ }
+ }
+
bool SemanticsVisitor::isIntegerBaseType(BaseType baseType)
{
return (BaseTypeInfo::getInfo(baseType).flags & BaseTypeInfo::Flag::Integer) != 0;