summaryrefslogtreecommitdiff
path: root/source/slang/slang-check-expr.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/slang/slang-check-expr.cpp')
-rw-r--r--source/slang/slang-check-expr.cpp51
1 files changed, 51 insertions, 0 deletions
diff --git a/source/slang/slang-check-expr.cpp b/source/slang/slang-check-expr.cpp
index f79e23b42..ee36a21fb 100644
--- a/source/slang/slang-check-expr.cpp
+++ b/source/slang/slang-check-expr.cpp
@@ -1213,6 +1213,57 @@ namespace Slang
}
}
+ void SemanticsVisitor::checkDerivativeMemberAttributeReferences(
+ VarDeclBase* varDecl, DerivativeMemberAttribute* derivativeMemberAttr)
+ {
+ if (derivativeMemberAttr->memberDeclRef)
+ {
+ // Already checked! This usually happens if this attribute is synthesized by the compiler.
+ return;
+ }
+
+ SLANG_ASSERT(derivativeMemberAttr->args.getCount() == 1);
+ auto checkedExpr = dispatchExpr(derivativeMemberAttr->args[0], allowStaticReferenceToNonStaticMember());
+
+ auto memberType = varDecl->type.type; // All types must be fully checked by now.
+ auto diffType = getDifferentialType(m_astBuilder, memberType, varDecl->loc);
+ auto thisType = calcThisType(makeDeclRef(varDecl->parentDecl));
+ if (!thisType) return; // Diagnostic should have been emitted previously.
+
+ auto diffThisType = getDifferentialType(m_astBuilder, thisType, derivativeMemberAttr->loc);
+ if (!diffThisType) return; // Diagnostic should have been emitted previously.
+
+ 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->getType()))
+ {
+ return;
+ }
+ }
+
+ }
+ }
+ getSink()->diagnose(
+ derivativeMemberAttr,
+ Diagnostics::
+ derivativeMemberAttributeMustNameAMemberInExpectedDifferentialType,
+ diffThisType);
+ }
+
Type* SemanticsVisitor::getDifferentialType(ASTBuilder* builder, Type* type, SourceLoc loc)
{
auto result = tryGetDifferentialType(builder, type);