diff options
| author | Yong He <yonghe@outlook.com> | 2022-07-12 22:45:05 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-07-12 22:45:05 -0700 |
| commit | 049aac1b80143753b4b3449e529024bafe2250be (patch) | |
| tree | e6734ef240bf7016562a301009add1761caf06f6 /source/slang/slang-check-decl.cpp | |
| parent | a6775666c38ccaeb2a991921a08343afa09c659b (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.cpp | 78 |
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; |
