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, 43 insertions, 11 deletions
diff --git a/source/slang/slang-check-decl.cpp b/source/slang/slang-check-decl.cpp
index b69c8cf0d..3aeca23cd 100644
--- a/source/slang/slang-check-decl.cpp
+++ b/source/slang/slang-check-decl.cpp
@@ -775,6 +775,24 @@ namespace Slang
return true;
}
+ void SemanticsVisitor::_validateCircularVarDefinition(VarDeclBase* varDecl)
+ {
+ // The easiest way to test if the declaration is circular is to
+ // validate it as a constant.
+ //
+ // TODO: The logic here will only apply for `static const` declarations
+ // of integer type, given that our constant folding currently only
+ // applies to such types. A more robust fix would involve a truly
+ // recursive walk of the AST declarations, and an even *more* robust
+ // fix would wait until after IR linking to detect and diagnose circularity
+ // in case it crosses module boundaries.
+ //
+ //
+ if(!isScalarIntegerType(varDecl->type))
+ return;
+ tryConstantFoldDeclRef(DeclRef<VarDeclBase>(varDecl, nullptr), nullptr);
+ }
+
void SemanticsDeclHeaderVisitor::checkVarDeclCommon(VarDeclBase* varDecl)
{
// A variable that didn't have an explicit type written must
@@ -804,6 +822,8 @@ namespace Slang
varDecl->initExpr = initExpr;
varDecl->type.type = initExpr->type;
+
+ _validateCircularVarDefinition(varDecl);
}
// If we've gone down this path, then the variable
@@ -857,11 +877,16 @@ namespace Slang
{
// If the variable has an explicit initial-value expression,
// then we simply need to check that expression and coerce
- // it to the tyep of the variable.
+ // it to the type of the variable.
//
initExpr = CheckTerm(initExpr);
initExpr = coerce(varDecl->type.Ptr(), initExpr);
varDecl->initExpr = initExpr;
+
+ // We need to ensure that any variable doesn't introduce
+ // a constant with a circular definition.
+ //
+ _validateCircularVarDefinition(varDecl);
}
else
{
@@ -1970,18 +1995,25 @@ namespace Slang
return (BaseTypeInfo::getInfo(baseType).flags & BaseTypeInfo::Flag::Integer) != 0;
}
- void SemanticsVisitor::validateEnumTagType(Type* type, SourceLoc const& loc)
+ bool SemanticsVisitor::isScalarIntegerType(Type* type)
{
- if(auto basicType = as<BasicExpressionType>(type))
- {
- // Allow the built-in integer types.
- if(isIntegerBaseType(basicType->baseType))
- return;
+ auto basicType = as<BasicExpressionType>(type);
+ if(!basicType)
+ return false;
- // By default, don't allow other types to be used
- // as an `enum` tag type.
- }
+ return isIntegerBaseType(basicType->baseType);
+ }
+ void SemanticsVisitor::validateEnumTagType(Type* type, SourceLoc const& loc)
+ {
+ // Allow the built-in integer types.
+ //
+ if(isScalarIntegerType(type))
+ return;
+
+ // By default, don't allow other types to be used
+ // as an `enum` tag type.
+ //
getSink()->diagnose(loc, Diagnostics::invalidEnumTagType, type);
}
@@ -2177,7 +2209,7 @@ namespace Slang
// the tag value for a successor case that doesn't
// provide an explicit tag.
- IntVal* explicitTagVal = TryConstantFoldExpr(explicitTagValExpr);
+ IntVal* explicitTagVal = tryConstantFoldExpr(explicitTagValExpr, nullptr);
if(explicitTagVal)
{
if(auto constIntVal = as<ConstantIntVal>(explicitTagVal))