diff options
Diffstat (limited to 'source')
| -rw-r--r-- | source/slang/slang-check-expr.cpp | 11 | ||||
| -rw-r--r-- | source/slang/slang-check-impl.h | 2 | ||||
| -rw-r--r-- | source/slang/slang-check-overload.cpp | 2 | ||||
| -rw-r--r-- | source/slang/slang-check-type.cpp | 15 | ||||
| -rw-r--r-- | source/slang/slang-syntax.cpp | 28 | ||||
| -rw-r--r-- | source/slang/slang-val-defs.h | 18 |
6 files changed, 71 insertions, 5 deletions
diff --git a/source/slang/slang-check-expr.cpp b/source/slang/slang-check-expr.cpp index 524bab4e4..adfc36641 100644 --- a/source/slang/slang-check-expr.cpp +++ b/source/slang/slang-check-expr.cpp @@ -828,7 +828,7 @@ namespace Slang return TryConstantFoldExpr(exp); } - RefPtr<IntVal> SemanticsVisitor::CheckIntegerConstantExpression(Expr* inExpr) + RefPtr<IntVal> SemanticsVisitor::CheckIntegerConstantExpression(Expr* inExpr, DiagnosticSink* sink) { // No need to issue further errors if the expression didn't even type-check. if(IsErrorExpr(inExpr)) return nullptr; @@ -840,13 +840,18 @@ namespace Slang if(IsErrorExpr(expr)) return nullptr; auto result = TryCheckIntegerConstantExpression(expr.Ptr()); - if (!result) + if (!result && sink) { - getSink()->diagnose(expr, Diagnostics::expectedIntegerConstantNotConstant); + sink->diagnose(expr, Diagnostics::expectedIntegerConstantNotConstant); } return result; } + RefPtr<IntVal> SemanticsVisitor::CheckIntegerConstantExpression(Expr* inExpr) + { + return CheckIntegerConstantExpression(inExpr, getSink()); + } + RefPtr<IntVal> SemanticsVisitor::CheckEnumConstantExpression(Expr* expr) { // No need to issue further errors if the expression didn't even type-check. diff --git a/source/slang/slang-check-impl.h b/source/slang/slang-check-impl.h index 9363066d1..f51e62699 100644 --- a/source/slang/slang-check-impl.h +++ b/source/slang/slang-check-impl.h @@ -392,6 +392,7 @@ namespace Slang RefPtr<Type> ExtractGenericArgType(RefPtr<Expr> exp); + RefPtr<IntVal> ExtractGenericArgInteger(RefPtr<Expr> exp, DiagnosticSink* sink); RefPtr<IntVal> ExtractGenericArgInteger(RefPtr<Expr> exp); RefPtr<Val> ExtractGenericArgVal(RefPtr<Expr> exp); @@ -834,6 +835,7 @@ namespace Slang // Enforce that an expression resolves to an integer constant, and get its value RefPtr<IntVal> CheckIntegerConstantExpression(Expr* inExpr); + RefPtr<IntVal> CheckIntegerConstantExpression(Expr* inExpr, DiagnosticSink* sink); RefPtr<IntVal> CheckEnumConstantExpression(Expr* expr); diff --git a/source/slang/slang-check-overload.cpp b/source/slang/slang-check-overload.cpp index 20d1af09a..ace495512 100644 --- a/source/slang/slang-check-overload.cpp +++ b/source/slang/slang-check-overload.cpp @@ -196,7 +196,7 @@ namespace Slang } arg = coerce(GetType(valParamRef), arg); - auto val = ExtractGenericArgInteger(arg); + auto val = ExtractGenericArgInteger(arg, context.mode == OverloadResolveContext::Mode::JustTrying ? nullptr : getSink()); checkedArgs.add(val); } else diff --git a/source/slang/slang-check-type.cpp b/source/slang/slang-check-type.cpp index b92f9a8f7..68e14c462 100644 --- a/source/slang/slang-check-type.cpp +++ b/source/slang/slang-check-type.cpp @@ -105,9 +105,22 @@ namespace Slang return ExpectAType(exp); } + RefPtr<IntVal> SemanticsVisitor::ExtractGenericArgInteger(RefPtr<Expr> exp, DiagnosticSink* sink) + { + RefPtr<IntVal> val = CheckIntegerConstantExpression(exp.Ptr(), sink); + if(val) return val; + + // If the argument expression could not be coerced to an integer + // constant expression in context, then we will instead construct + // a dummy "error" value to represent the result. + // + val = new ErrorIntVal(); + return val; + } + RefPtr<IntVal> SemanticsVisitor::ExtractGenericArgInteger(RefPtr<Expr> exp) { - return CheckIntegerConstantExpression(exp.Ptr()); + return ExtractGenericArgInteger(exp, getSink()); } RefPtr<Val> SemanticsVisitor::ExtractGenericArgVal(RefPtr<Expr> exp) diff --git a/source/slang/slang-syntax.cpp b/source/slang/slang-syntax.cpp index 502425da8..c05f9aa0f 100644 --- a/source/slang/slang-syntax.cpp +++ b/source/slang/slang-syntax.cpp @@ -1346,6 +1346,34 @@ void Type::accept(IValVisitor* visitor, void* extra) return this; } + // ErrorIntVal + + bool ErrorIntVal::EqualsVal(Val* val) + { + if( auto errorIntVal = as<ErrorIntVal>(val) ) + { + return true; + } + return false; + } + + String ErrorIntVal::ToString() + { + return "<error>"; + } + + int ErrorIntVal::GetHashCode() + { + return int(typeid(this).hash_code()); + } + + RefPtr<Val> ErrorIntVal::SubstituteImpl(SubstitutionSet subst, int* ioDiff) + { + SLANG_UNUSED(subst); + SLANG_UNUSED(ioDiff); + return this; + } + // Substitutions RefPtr<Substitutions> GenericSubstitution::applySubstitutionsShallow(SubstitutionSet substSet, RefPtr<Substitutions> substOuter, int* ioDiff) diff --git a/source/slang/slang-val-defs.h b/source/slang/slang-val-defs.h index b9d5188ed..5024554d4 100644 --- a/source/slang/slang-val-defs.h +++ b/source/slang/slang-val-defs.h @@ -41,6 +41,24 @@ SYNTAX_CLASS(GenericParamIntVal, IntVal) ) END_SYNTAX_CLASS() + /// An unknown integer value indicating an erroneous sub-expression +SYNTAX_CLASS(ErrorIntVal, IntVal) + + // TODO: We should probably eventually just have an `ErrorVal` here + // and have all `Val`s that represent ordinary values hold their + // `Type` so that we can have an `ErrorVal` of any type. + + RAW( + ErrorIntVal() + {} + + virtual bool EqualsVal(Val* val) override; + virtual String ToString() override; + virtual int GetHashCode() override; + virtual RefPtr<Val> SubstituteImpl(SubstitutionSet subst, int* ioDiff) override; +) +END_SYNTAX_CLASS() + // A witness to the fact that some proposition is true, encoded // at the level of the type system. // |
