summaryrefslogtreecommitdiffstats
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.cpp104
1 files changed, 103 insertions, 1 deletions
diff --git a/source/slang/slang-check-decl.cpp b/source/slang/slang-check-decl.cpp
index 2d6e20622..356105e4f 100644
--- a/source/slang/slang-check-decl.cpp
+++ b/source/slang/slang-check-decl.cpp
@@ -45,7 +45,10 @@ namespace Slang
void visitDecl(Decl*) {}
void visitDeclGroup(DeclGroup*) {}
-
+
+ void checkDerivativeMemberAttribute(VarDeclBase* varDecl, DerivativeMemberAttribute* attr);
+ void checkExtensionExternVarAttribute(VarDeclBase* varDecl, ExtensionExternVarModifier* m);
+
void checkVarDeclCommon(VarDeclBase* varDecl);
void visitVarDecl(VarDecl* varDecl)
@@ -78,6 +81,8 @@ namespace Slang
void checkCallableDeclCommon(CallableDecl* decl);
+ void maybeCheckDifferentiableAccessorSignature(FuncDecl* funcDecl);
+
void visitFuncDecl(FuncDecl* funcDecl);
void visitParamDecl(ParamDecl* paramDecl);
@@ -636,6 +641,9 @@ namespace Slang
bool SemanticsVisitor::isDeclUsableAsStaticMember(
Decl* decl)
{
+ if (m_allowStaticReferenceToNonStaticMember)
+ return true;
+
if(auto genericDecl = as<GenericDecl>(decl))
decl = genericDecl->inner;
@@ -663,6 +671,9 @@ namespace Slang
bool SemanticsVisitor::isUsableAsStaticMember(
LookupResultItem const& item)
{
+ if (m_allowStaticReferenceToNonStaticMember)
+ return true;
+
// There's a bit of a gotcha here, because a lookup result
// item might include "breadcrumbs" that indicate more steps
// along the lookup path. As a result it isn't always
@@ -966,6 +977,87 @@ namespace Slang
tryConstantFoldDeclRef(DeclRef<VarDeclBase>(varDecl, nullptr), nullptr);
}
+ void SemanticsDeclHeaderVisitor::checkDerivativeMemberAttribute(
+ VarDeclBase* varDecl, DerivativeMemberAttribute* derivativeMemberAttr)
+ {
+ auto memberType = checkProperType(getLinkage(), varDecl->type, getSink());
+ auto diffType = _getDifferential(m_astBuilder, memberType);
+ if (as<ErrorType>(diffType))
+ {
+ getSink()->diagnose(derivativeMemberAttr, Diagnostics::typeIsNotDifferentiable, memberType);
+ }
+ auto thisType = calcThisType(makeDeclRef(varDecl->parentDecl));
+ if (!thisType)
+ {
+ getSink()->diagnose(
+ derivativeMemberAttr,
+ Diagnostics::
+ derivativeMemberAttributeCanOnlyBeUsedOnMembers);
+ }
+ auto diffThisType = _getDifferential(m_astBuilder, thisType);
+ if (!thisType)
+ {
+ getSink()->diagnose(
+ derivativeMemberAttr,
+ Diagnostics::invalidUseOfDerivativeMemberAttributeParentTypeIsNotDifferentiable);
+ }
+ SLANG_ASSERT(derivativeMemberAttr->args.getCount() == 1);
+ auto checkedExpr = dispatchExpr(derivativeMemberAttr->args[0], allowStaticReferenceToNonStaticMember());
+ if (auto declRefExpr = as<DeclRefExpr>(checkedExpr))
+ {
+ derivativeMemberAttr->memberDeclRef = declRefExpr;
+ if (!diffType->equals(declRefExpr->type))
+ {
+ getSink()->diagnose(derivativeMemberAttr, Diagnostics::typeMismatch, diffType, declRefExpr->type);
+ }
+ if (!varDecl->parentDecl)
+ {
+ getSink()->diagnose(derivativeMemberAttr, Diagnostics::attributeNotApplicable, diffType, declRefExpr->type);
+ }
+ if (auto memberExpr = as<StaticMemberExpr>(declRefExpr))
+ {
+ auto baseExprType = memberExpr->baseExpression->type.type;
+ if (auto typeType = as<TypeType>(baseExprType))
+ {
+ if (diffThisType->equals(typeType->type))
+ {
+ return;
+ }
+ }
+
+ }
+ }
+ getSink()->diagnose(
+ derivativeMemberAttr,
+ Diagnostics::
+ derivativeMemberAttributeMustNameAMemberInExpectedDifferentialType,
+ diffThisType);
+ }
+
+ void SemanticsDeclHeaderVisitor::checkExtensionExternVarAttribute(VarDeclBase* varDecl, ExtensionExternVarModifier* extensionExternMemberModifier)
+ {
+ if (auto parentExtension = as<ExtensionDecl>(varDecl->parentDecl))
+ {
+ if (auto originalVarDecl = extensionExternMemberModifier->originalDecl.as<VarDeclBase>())
+ {
+ auto originalType = GetTypeForDeclRef(originalVarDecl, originalVarDecl.getLoc());
+ auto extVarType = varDecl->type;
+ if (!extVarType.type || !extVarType.type->equals(originalType))
+ {
+ getSink()->diagnose(varDecl, Diagnostics::typeOfExternDeclMismatchesOriginalDefinition, varDecl, originalType);
+ }
+ else
+ {
+ return;
+ }
+ }
+ else
+ {
+ getSink()->diagnose(varDecl, Diagnostics::definitionOfExternDeclMismatchesOriginalDefinition, varDecl);
+ }
+ }
+ }
+
void SemanticsDeclHeaderVisitor::checkVarDeclCommon(VarDeclBase* varDecl)
{
// A variable that didn't have an explicit type written must
@@ -1136,6 +1228,16 @@ namespace Slang
getSink()->diagnose(varDecl, Diagnostics::valueRequirementMustBeCompileTimeConst);
}
}
+
+ // Check modifiers that can't be checked earlier during modifier checking stage.
+ if (auto derivativeMemberAttr = varDecl->findModifier<DerivativeMemberAttribute>())
+ {
+ checkDerivativeMemberAttribute(varDecl, derivativeMemberAttr);
+ }
+ if (auto extensionExternAttr = varDecl->findModifier<ExtensionExternVarModifier>())
+ {
+ checkExtensionExternVarAttribute(varDecl, extensionExternAttr);
+ }
}
void SemanticsDeclHeaderVisitor::visitStructDecl(StructDecl* structDecl)