summaryrefslogtreecommitdiffstats
path: root/source
diff options
context:
space:
mode:
Diffstat (limited to 'source')
-rw-r--r--source/core/slang-type-text-util.cpp19
-rw-r--r--source/core/slang-type-text-util.h8
-rw-r--r--source/slang-record-replay/record/parameter-recorder.cpp2
-rw-r--r--source/slang-record-replay/replay/json-consumer.cpp2
-rw-r--r--source/slang-record-replay/replay/parameter-decoder.cpp2
-rw-r--r--source/slang/slang-ast-decl.h17
-rw-r--r--source/slang/slang-ast-expr.h10
-rw-r--r--source/slang/slang-ast-iterator.h7
-rw-r--r--source/slang/slang-capabilities.capdef2
-rw-r--r--source/slang/slang-check-decl.cpp35
-rw-r--r--source/slang/slang-check-expr.cpp24
-rw-r--r--source/slang/slang-check-impl.h2
-rw-r--r--source/slang/slang-compiler-options.cpp4
-rw-r--r--source/slang/slang-compiler-options.h9
-rw-r--r--source/slang/slang-compiler.cpp40
-rw-r--r--source/slang/slang-compiler.h3
-rw-r--r--source/slang/slang-diagnostic-defs.h10
-rw-r--r--source/slang/slang-language-server-ast-lookup.cpp8
-rw-r--r--source/slang/slang-lower-to-ir.cpp23
-rw-r--r--source/slang/slang-options.cpp26
-rw-r--r--source/slang/slang-parser.cpp164
-rw-r--r--source/slang/slang-preprocessor.cpp90
-rw-r--r--source/slang/slang-preprocessor.h4
-rw-r--r--source/slang/slang-serialize-ast.cpp5
-rw-r--r--source/slang/slang-type-layout.cpp12
-rw-r--r--source/slang/slang.cpp25
26 files changed, 434 insertions, 119 deletions
diff --git a/source/core/slang-type-text-util.cpp b/source/core/slang-type-text-util.cpp
index 4797395b7..9f55b69e2 100644
--- a/source/core/slang-type-text-util.cpp
+++ b/source/core/slang-type-text-util.cpp
@@ -99,10 +99,10 @@ static const NamesDescriptionValue s_languageInfos[] = {
{SLANG_SOURCE_LANGUAGE_CUDA, "cu,cuda", "CUDA"},
};
-static const NamesDescriptionValue s_stdRevisionInfos[] = {
- {SLANG_STD_REVISION_UNKNOWN, "unknown", "Unknown"},
- {SLANG_STD_REVISION_2025, "2025,default", "Slang language rules for 2025 and older"},
- {SLANG_STD_REVISION_2026, "2026", "Slang language rules for 2026 and newer"},
+static const NamesDescriptionValue s_languageVersionInfos[] = {
+ {SLANG_LANGUAGE_VERSION_LEGACY, "legacy,default,2018", "Legacy Slang language"},
+ {SLANG_LANGUAGE_VERSION_2025, "2025", "Slang language rules for 2025 and older"},
+ {SLANG_LANGUAGE_VERSION_2026, "2026,latest", "Slang language rules for 2026 and newer"},
};
static const NamesDescriptionValue s_compilerInfos[] = {
@@ -223,9 +223,9 @@ static const NamesDescriptionValue s_fileSystemTypes[] = {
return makeConstArrayView(s_languageInfos);
}
-/* static */ ConstArrayView<NamesDescriptionValue> TypeTextUtil::getStdRevisionInfos()
+/* static */ ConstArrayView<NamesDescriptionValue> TypeTextUtil::getLanguageVersionInfos()
{
- return makeConstArrayView(s_stdRevisionInfos);
+ return makeConstArrayView(s_languageVersionInfos);
}
/* static */ ConstArrayView<NamesDescriptionValue> TypeTextUtil::getCompilerInfos()
@@ -328,9 +328,12 @@ static const NamesDescriptionValue s_fileSystemTypes[] = {
return NameValueUtil::findValue(getLanguageInfos(), text, SLANG_SOURCE_LANGUAGE_UNKNOWN);
}
-/* static */ SlangStdRevision TypeTextUtil::findStdRevision(const UnownedStringSlice& text)
+/* static */ SlangLanguageVersion TypeTextUtil::findLanguageVersion(const UnownedStringSlice& text)
{
- return NameValueUtil::findValue(getStdRevisionInfos(), text, SLANG_STD_REVISION_UNKNOWN);
+ return NameValueUtil::findValue(
+ getLanguageVersionInfos(),
+ text,
+ SLANG_LANGUAGE_VERSION_UNKNOWN);
}
/* static */ SlangPassThrough TypeTextUtil::findPassThrough(const UnownedStringSlice& slice)
diff --git a/source/core/slang-type-text-util.h b/source/core/slang-type-text-util.h
index bc136c3ab..eddbcec5e 100644
--- a/source/core/slang-type-text-util.h
+++ b/source/core/slang-type-text-util.h
@@ -33,8 +33,8 @@ struct TypeTextUtil
/// Get the language infos
static ConstArrayView<NamesDescriptionValue> getLanguageInfos();
- /// Get the std revision infos
- static ConstArrayView<NamesDescriptionValue> getStdRevisionInfos();
+ /// Get the language version infos
+ static ConstArrayView<NamesDescriptionValue> getLanguageVersionInfos();
/// Get the compiler infos
static ConstArrayView<NamesDescriptionValue> getCompilerInfos();
/// Get the archive type infos
@@ -73,8 +73,8 @@ struct TypeTextUtil
/// Given a source language name returns a source language. Name here is distinct from extension
static SlangSourceLanguage findSourceLanguage(const UnownedStringSlice& text);
- /// Given a std revision returns a std revision.
- static SlangStdRevision findStdRevision(const UnownedStringSlice& text);
+ /// Given a language version name returns a language revision.
+ static SlangLanguageVersion findLanguageVersion(const UnownedStringSlice& text);
/// Given a name returns the pass through
static SlangPassThrough findPassThrough(const UnownedStringSlice& slice);
diff --git a/source/slang-record-replay/record/parameter-recorder.cpp b/source/slang-record-replay/record/parameter-recorder.cpp
index fd6f75549..712a979b8 100644
--- a/source/slang-record-replay/record/parameter-recorder.cpp
+++ b/source/slang-record-replay/record/parameter-recorder.cpp
@@ -6,7 +6,7 @@ void ParameterRecorder::recordStruct(SlangGlobalSessionDesc const& desc)
{
recordUint32(desc.structureSize);
recordUint32(desc.apiVersion);
- recordUint32(desc.languageVersion);
+ recordUint32(desc.minLanguageVersion);
recordUint32(desc.enableGLSL);
}
diff --git a/source/slang-record-replay/replay/json-consumer.cpp b/source/slang-record-replay/replay/json-consumer.cpp
index c0486341e..ba7a13015 100644
--- a/source/slang-record-replay/replay/json-consumer.cpp
+++ b/source/slang-record-replay/replay/json-consumer.cpp
@@ -631,7 +631,7 @@ void JsonConsumer::_writeGlobalSessionDescHelper(
{
_writePair(builder, indent, "structureSize", (uint32_t)desc.structureSize);
_writePair(builder, indent, "apiVersion", (uint32_t)desc.apiVersion);
- _writePair(builder, indent, "languageVersion", (uint32_t)desc.languageVersion);
+ _writePair(builder, indent, "minLanguageVersion", (uint32_t)desc.minLanguageVersion);
_writePair(builder, indent, "enablGLSL", (uint32_t)desc.enableGLSL);
}
}
diff --git a/source/slang-record-replay/replay/parameter-decoder.cpp b/source/slang-record-replay/replay/parameter-decoder.cpp
index afe4f716d..f986fbfbe 100644
--- a/source/slang-record-replay/replay/parameter-decoder.cpp
+++ b/source/slang-record-replay/replay/parameter-decoder.cpp
@@ -84,7 +84,7 @@ size_t ParameterDecoder::decodeStruct(
SlangGlobalSessionDesc& desc = sessionDesc.getValue();
readByte = decodeUint32(buffer, bufferSize, desc.structureSize);
readByte += decodeUint32(buffer + readByte, bufferSize - readByte, desc.apiVersion);
- readByte += decodeUint32(buffer + readByte, bufferSize - readByte, desc.languageVersion);
+ readByte += decodeUint32(buffer + readByte, bufferSize - readByte, desc.minLanguageVersion);
uint32_t val = 0;
readByte += decodeUint32(buffer + readByte, bufferSize - readByte, val);
desc.enableGLSL = (val != 0);
diff --git a/source/slang/slang-ast-decl.h b/source/slang/slang-ast-decl.h
index d4ac71d83..e281081a7 100644
--- a/source/slang/slang-ast-decl.h
+++ b/source/slang/slang-ast-decl.h
@@ -525,15 +525,14 @@ class ModuleDecl : public NamespaceDeclBase
///
FIDDLE() OrderedDictionary<Decl*, RefPtr<DeclAssociationList>> mapDeclToAssociatedDecls;
- /// Whether the module is defined in legacy language.
- /// The legacy Slang language does not have visibility modifiers and everything is treated as
- /// `public`. Newer version of the language introduces visibility and makes `internal` as the
- /// default. To prevent this from breaking existing code, we need to know whether a module is
- /// written in the legacy language. We detect this by checking whether the module has any
- /// visibility modifiers, or if the module uses new language constructs, e.g. `module`,
- /// `__include`,
- /// `__implementing` etc.
- FIDDLE() bool isInLegacyLanguage = true;
+ /// Whether Slang language version the module is defined in.
+ /// The legacy Slang language (2025) does not have visibility modifiers and everything is
+ /// treated as `public`. Newer version of the language introduces visibility and makes
+ /// `internal` as the default. To prevent this from breaking existing code, we need to know
+ /// whether a module is written in the legacy language. We detect this by checking whether the
+ /// module has any visibility modifiers, or if the module uses new language constructs, e.g.
+ /// `module`, `__include`, `__implementing` etc.
+ FIDDLE() SlangLanguageVersion languageVersion = SLANG_LANGAUGE_VERSION_DEFAULT;
FIDDLE() DeclVisibility defaultVisibility = DeclVisibility::Internal;
diff --git a/source/slang/slang-ast-expr.h b/source/slang/slang-ast-expr.h
index ccbc625c9..950fd6645 100644
--- a/source/slang/slang-ast-expr.h
+++ b/source/slang/slang-ast-expr.h
@@ -575,6 +575,16 @@ class ParenExpr : public Expr
Expr* base = nullptr;
};
+// An expression that constructs a tuple `(arg1, arg2, ...)`
+//
+FIDDLE()
+class TupleExpr : public Expr
+{
+ FIDDLE(...)
+ List<Expr*> elements;
+};
+
+
// An object-oriented `this` expression, used to
// refer to the current instance of an enclosing type.
FIDDLE()
diff --git a/source/slang/slang-ast-iterator.h b/source/slang/slang-ast-iterator.h
index 047c33d1a..18a46b303 100644
--- a/source/slang/slang-ast-iterator.h
+++ b/source/slang/slang-ast-iterator.h
@@ -76,6 +76,13 @@ struct ASTIterator
dispatchIfNotNull(expr->base);
}
+ void visitTupleExpr(TupleExpr* expr)
+ {
+ iterator->maybeDispatchCallback(expr);
+ for (auto element : expr->elements)
+ dispatchIfNotNull(element);
+ }
+
void visitAssignExpr(AssignExpr* expr)
{
iterator->maybeDispatchCallback(expr);
diff --git a/source/slang/slang-capabilities.capdef b/source/slang/slang-capabilities.capdef
index 28fa211e4..ad4c9cb44 100644
--- a/source/slang/slang-capabilities.capdef
+++ b/source/slang/slang-capabilities.capdef
@@ -718,7 +718,7 @@ def spvShaderInvocationReorderNV : SPV_NV_shader_invocation_reorder;
/// [EXT]
def spvRayTracingClusterAccelerationStructureNV : SPV_NV_cluster_acceleration_structure;
-/// Represents the SPIR-V capability for cluster acceleration structure.
+/// Represents the SPIR-V capability for linear swept spheres.
/// [EXT]
def spvRayTracingLinearSweptSpheresGeometryNV : SPV_NV_linear_swept_spheres;
diff --git a/source/slang/slang-check-decl.cpp b/source/slang/slang-check-decl.cpp
index f8a80c09b..71aa71e69 100644
--- a/source/slang/slang-check-decl.cpp
+++ b/source/slang/slang-check-decl.cpp
@@ -34,21 +34,18 @@ static bool isAssociatedTypeDecl(Decl* decl)
return false;
}
-static bool isSlang2026(CompilerOptionSet& optionSet)
+static bool isSlang2026OrLater(SemanticsVisitor* visitor)
{
- if (!optionSet.hasOption(CompilerOptionName::Language))
- return false;
- return SLANG_SOURCE_LANGUAGE_SLANG ==
- SlangSourceLanguage(
- optionSet.getEnumOption<SlangSourceLanguage>(CompilerOptionName::Language)) &&
- SLANG_STD_REVISION_2026 ==
- optionSet.getEnumOption<SlangStdRevision>(CompilerOptionName::StdRevision);
+ return visitor->getShared()->m_module->getModuleDecl()->languageVersion >=
+ SLANG_LANGUAGE_VERSION_2026;
}
-static bool allowExperimentalDynamicDispatch(CompilerOptionSet& optionSet)
+static bool allowExperimentalDynamicDispatch(
+ SemanticsVisitor* visitor,
+ CompilerOptionSet& optionSet)
{
return optionSet.getBoolOption(CompilerOptionName::EnableExperimentalDynamicDispatch) ||
- !isSlang2026(optionSet);
+ !isSlang2026OrLater(visitor);
}
static void validateDynInterfaceUsage(
@@ -57,7 +54,7 @@ static void validateDynInterfaceUsage(
CompilerOptionSet& optionSet,
InterfaceDecl* decl)
{
- if (allowExperimentalDynamicDispatch(optionSet))
+ if (allowExperimentalDynamicDispatch(visitor, optionSet))
return;
if (!decl->hasModifier<DynModifier>())
@@ -134,7 +131,7 @@ static void validateDynInterfaceUseWithInheritanceDecl(
if (!interfaceDeclIsDyn)
return;
- if (!allowExperimentalDynamicDispatch(optionSet))
+ if (!allowExperimentalDynamicDispatch(visitor, optionSet))
{
if (auto extensionDeclParent = as<ExtensionDecl>(decl->parentDecl))
{
@@ -665,6 +662,13 @@ struct SemanticsDeclReferenceVisitor : public SemanticsDeclVisitorBase,
void visitParenExpr(ParenExpr* expr) { dispatchIfNotNull(expr->base); }
+ void visitTupleExpr(TupleExpr* expr)
+ {
+ for (auto element : expr->elements)
+ dispatchIfNotNull(element);
+ }
+
+
void visitAssignExpr(AssignExpr* expr)
{
dispatchIfNotNull(expr->left);
@@ -13817,7 +13821,7 @@ void SemanticsDeclCapabilityVisitor::visitInheritanceDecl(InheritanceDecl* inher
if (!implDecl)
continue;
- if (getModuleDecl(implDecl.getDecl())->isInLegacyLanguage)
+ if (getModuleDecl(implDecl.getDecl())->languageVersion == SLANG_LANGUAGE_VERSION_LEGACY)
break;
ensureDecl(requirementDecl, DeclCheckState::CapabilityChecked);
@@ -13880,8 +13884,9 @@ DeclVisibility getDeclVisibility(Decl* decl)
auto defaultVis = DeclVisibility::Default;
if (auto parentModule = getModuleDecl(decl))
{
- defaultVis = parentModule->isInLegacyLanguage ? DeclVisibility::Public
- : parentModule->defaultVisibility;
+ defaultVis = parentModule->languageVersion == SLANG_LANGUAGE_VERSION_LEGACY
+ ? DeclVisibility::Public
+ : parentModule->defaultVisibility;
}
// Members of other agg type decls will have their default visibility capped to the
diff --git a/source/slang/slang-check-expr.cpp b/source/slang/slang-check-expr.cpp
index 0c0b1ec9d..205575a81 100644
--- a/source/slang/slang-check-expr.cpp
+++ b/source/slang/slang-check-expr.cpp
@@ -2484,6 +2484,30 @@ Expr* SemanticsExprVisitor::visitParenExpr(ParenExpr* expr)
return expr;
}
+Expr* SemanticsExprVisitor::visitTupleExpr(TupleExpr* expr)
+{
+ List<Type*> elementTypes;
+ for (auto& element : expr->elements)
+ {
+ element = CheckTerm(element);
+ auto elementType = element->type.type;
+ if (auto concreteTypePack = as<ConcreteTypePack>(elementType))
+ {
+ // We need to flatten the type pack into a tuple type
+ for (Index i = 0; i < concreteTypePack->getTypeCount(); i++)
+ {
+ elementTypes.add(concreteTypePack->getElementType(i));
+ }
+ }
+ else
+ {
+ elementTypes.add(element->type.type);
+ }
+ }
+ expr->type = m_astBuilder->getTupleType(elementTypes.getArrayView());
+ return expr;
+}
+
void SemanticsVisitor::maybeDiagnoseThisNotLValue(Expr* expr)
{
// We will try to handle expressions of the form:
diff --git a/source/slang/slang-check-impl.h b/source/slang/slang-check-impl.h
index 950a150c4..80436e68a 100644
--- a/source/slang/slang-check-impl.h
+++ b/source/slang/slang-check-impl.h
@@ -2920,6 +2920,8 @@ public:
Expr* visitParenExpr(ParenExpr* expr);
+ Expr* visitTupleExpr(TupleExpr* expr);
+
Expr* visitAssignExpr(AssignExpr* expr);
Expr* visitGenericAppExpr(GenericAppExpr* genericAppExpr);
diff --git a/source/slang/slang-compiler-options.cpp b/source/slang/slang-compiler-options.cpp
index 0d7f19642..5c17121cc 100644
--- a/source/slang/slang-compiler-options.cpp
+++ b/source/slang/slang-compiler-options.cpp
@@ -208,8 +208,8 @@ CompilerOptionValue Slang::CompilerOptionSet::getDefault(CompilerOptionName name
{
case CompilerOptionName::Optimization:
return CompilerOptionValue::fromEnum(OptimizationLevel::Default);
- case CompilerOptionName::StdRevision:
- return CompilerOptionValue::fromEnum(SlangStdRevision::SLANG_STD_REVISION_DEFAULT);
+ case CompilerOptionName::LanguageVersion:
+ return CompilerOptionValue::fromEnum(SLANG_LANGAUGE_VERSION_DEFAULT);
default:
return CompilerOptionValue();
}
diff --git a/source/slang/slang-compiler-options.h b/source/slang/slang-compiler-options.h
index 9de2a2e80..dd413bee4 100644
--- a/source/slang/slang-compiler-options.h
+++ b/source/slang/slang-compiler-options.h
@@ -385,6 +385,15 @@ struct CompilerOptionSet
return getEnumOption<DebugInfoLevel>(CompilerOptionName::DebugInformation);
}
+ SlangLanguageVersion getLanguageVersion()
+ {
+ if (!hasOption(CompilerOptionName::LanguageVersion))
+ {
+ return SLANG_LANGAUGE_VERSION_DEFAULT;
+ }
+ return (SlangLanguageVersion)getIntOption(CompilerOptionName::LanguageVersion);
+ }
+
List<String> getDownstreamArgs(String downstreamToolName);
void serialize(SerializedOptionsData* outData);
diff --git a/source/slang/slang-compiler.cpp b/source/slang/slang-compiler.cpp
index d6659e707..86dcf5d7f 100644
--- a/source/slang/slang-compiler.cpp
+++ b/source/slang/slang-compiler.cpp
@@ -1175,6 +1175,46 @@ SlangResult passthroughDownstreamDiagnostics(
return SLANG_OK;
}
+bool isValidSlangLanguageVersion(SlangLanguageVersion version)
+{
+ switch (version)
+ {
+ case SLANG_LANGUAGE_VERSION_LEGACY:
+ case SLANG_LANGUAGE_VERSION_2025:
+ case SLANG_LANGUAGE_VERSION_2026:
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool isValidGLSLVersion(int version)
+{
+ switch (version)
+ {
+ case 100:
+ case 110:
+ case 120:
+ case 130:
+ case 140:
+ case 150:
+ case 300:
+ case 310:
+ case 320:
+ case 330:
+ case 400:
+ case 410:
+ case 420:
+ case 430:
+ case 440:
+ case 450:
+ case 460:
+ return true;
+ default:
+ return false;
+ }
+}
+
SlangResult CodeGenContext::emitWithDownstreamForEntryPoints(ComPtr<IArtifact>& outArtifact)
{
outArtifact.setNull();
diff --git a/source/slang/slang-compiler.h b/source/slang/slang-compiler.h
index 0fc8e69dd..e06278599 100644
--- a/source/slang/slang-compiler.h
+++ b/source/slang/slang-compiler.h
@@ -3887,6 +3887,9 @@ bool maybeDiagnoseWarningOrError(
}
}
+bool isValidSlangLanguageVersion(SlangLanguageVersion version);
+bool isValidGLSLVersion(int version);
+
} // namespace Slang
#endif
diff --git a/source/slang/slang-diagnostic-defs.h b/source/slang/slang-diagnostic-defs.h
index 0814bb2a0..fc7a4d5bb 100644
--- a/source/slang/slang-diagnostic-defs.h
+++ b/source/slang/slang-diagnostic-defs.h
@@ -147,8 +147,6 @@ DIAGNOSTIC(
"when using multiple source files, entry points must be specified after their corresponding "
"source file(s)")
-DIAGNOSTIC(21, Error, unknownStdRevision, "unknown language standard revision '$0'")
-
DIAGNOSTIC(22, Error, unknownDownstreamCompiler, "unknown downstream compiler '$0'")
DIAGNOSTIC(26, Error, unknownOptimiziationLevel, "unknown optimization level '$0'")
@@ -371,7 +369,13 @@ DIAGNOSTIC(
undefinedIdentifierInPreprocessorExpression,
"undefined identifier '$0' in preprocessor expression will evaluate to zero")
DIAGNOSTIC(15206, Error, expectedIntegralVersionNumber, "Expected integer for #version number")
-
+DIAGNOSTIC(15207, Error, unknownLanguageVersion, "unknown language version '$0'.")
+DIAGNOSTIC(15208, Error, unknownLanguage, "unknown language '$0'.")
+DIAGNOSTIC(
+ 15208,
+ Error,
+ languageVersionDiffersFromIncludingModule,
+ "the source file declares a different language version than the including module.")
DIAGNOSTIC(-1, Note, seeOpeningToken, "see opening '$0'")
// 153xx - #include
diff --git a/source/slang/slang-language-server-ast-lookup.cpp b/source/slang/slang-language-server-ast-lookup.cpp
index d0ed9cdac..53a9f81b9 100644
--- a/source/slang/slang-language-server-ast-lookup.cpp
+++ b/source/slang/slang-language-server-ast-lookup.cpp
@@ -148,6 +148,14 @@ public:
bool visitParenExpr(ParenExpr* expr) { return dispatchIfNotNull(expr->base); }
+ bool visitTupleExpr(TupleExpr* expr)
+ {
+ for (auto element : expr->elements)
+ if (dispatchIfNotNull(element))
+ return true;
+ return false;
+ }
+
bool visitBuiltinCastExpr(BuiltinCastExpr* expr) { return dispatchIfNotNull(expr->base); }
bool visitAssignExpr(AssignExpr* expr)
diff --git a/source/slang/slang-lower-to-ir.cpp b/source/slang/slang-lower-to-ir.cpp
index ebcdaf1e1..758b21e93 100644
--- a/source/slang/slang-lower-to-ir.cpp
+++ b/source/slang/slang-lower-to-ir.cpp
@@ -4668,6 +4668,29 @@ struct ExprLoweringVisitorBase : public ExprVisitor<Derived, LoweredValInfo>
LoweredValInfo visitParenExpr(ParenExpr* expr) { return lowerSubExpr(expr->base); }
+ LoweredValInfo visitTupleExpr(TupleExpr* expr)
+ {
+ List<IRInst*> elements;
+ for (auto element : expr->elements)
+ {
+ auto elementVal = getSimpleVal(context, lowerSubExpr(element));
+ if (auto makeValPack = as<IRMakeValuePack>(elementVal))
+ {
+ // If the element is a value pack, we need to flatten it out
+ // into the tuple.
+ for (UInt i = 0; i < makeValPack->getOperandCount(); ++i)
+ {
+ elements.add(makeValPack->getOperand(i));
+ }
+ continue;
+ }
+ elements.add(elementVal);
+ }
+ auto irMakeTuple =
+ getBuilder()->emitMakeTuple((UInt)elements.getCount(), elements.getBuffer());
+ return LoweredValInfo::simple(irMakeTuple);
+ }
+
LoweredValInfo visitPackExpr(PackExpr* expr)
{
List<IRInst*> irArgs;
diff --git a/source/slang/slang-options.cpp b/source/slang/slang-options.cpp
index 0182b4c22..3ce107135 100644
--- a/source/slang/slang-options.cpp
+++ b/source/slang/slang-options.cpp
@@ -63,7 +63,7 @@ enum class ValueCategory
FileSystemType,
VulkanShift,
SourceEmbedStyle,
- StdRevision,
+ LanguageVersion,
CountOf,
};
@@ -150,10 +150,10 @@ void initCommandOptions(CommandOptions& options)
options.addCategory(
CategoryKind::Value,
- "std-revision",
- "Std Revision",
- UserValue(ValueCategory::StdRevision));
- options.addValues(TypeTextUtil::getStdRevisionInfos());
+ "language-version",
+ "Language Version",
+ UserValue(ValueCategory::LanguageVersion));
+ options.addValues(TypeTextUtil::getLanguageVersionInfos());
options.addCategory(
@@ -455,9 +455,9 @@ void initCommandOptions(CommandOptions& options)
"Display the build version. This is the contents of git describe --tags.\n"
"It is typically only set from automated builds(such as distros available on github).A "
"user build will by default be 'unknown'."},
- {OptionKind::StdRevision,
+ {OptionKind::LanguageVersion,
"-std",
- "-std <std-revision>",
+ "-std <language-version>",
"Specifies the language standard that should be used."},
{OptionKind::WarningsAsErrors,
"-warnings-as-errors",
@@ -2555,21 +2555,21 @@ SlangResult OptionsParser::_parse(int argc, char const* const* argv)
}
break;
}
- case OptionKind::StdRevision:
+ case OptionKind::LanguageVersion:
{
CommandLineArg name;
SLANG_RETURN_ON_FAIL(m_reader.expectArg(name));
- SlangStdRevision stdRevision =
- TypeTextUtil::findStdRevision(name.value.getUnownedSlice());
- if (stdRevision == SLANG_STD_REVISION_UNKNOWN)
+ SlangLanguageVersion stdRevision =
+ TypeTextUtil::findLanguageVersion(name.value.getUnownedSlice());
+ if (stdRevision == SLANG_LANGUAGE_VERSION_UNKNOWN)
{
- m_sink->diagnose(name.loc, Diagnostics::unknownStdRevision, name.value);
+ m_sink->diagnose(name.loc, Diagnostics::unknownLanguageVersion, name.value);
return SLANG_FAIL;
}
else
{
- linkage->m_optionSet.add(OptionKind::StdRevision, stdRevision);
+ linkage->m_optionSet.add(OptionKind::LanguageVersion, stdRevision);
}
break;
}
diff --git a/source/slang/slang-parser.cpp b/source/slang/slang-parser.cpp
index 565cb2e5f..9eb8c1391 100644
--- a/source/slang/slang-parser.cpp
+++ b/source/slang/slang-parser.cpp
@@ -1185,6 +1185,14 @@ bool tryParseUsingSyntaxDecl(
return tryParseUsingSyntaxDeclImpl<T>(parser, syntaxDecl, outSyntax);
}
+static void maybeUpgradeLanguageVersionFromLegacy(SlangLanguageVersion& ver)
+{
+ if (ver == SLANG_LANGUAGE_VERSION_LEGACY)
+ {
+ ver = SLANG_LANGUAGE_VERSION_2025;
+ }
+}
+
static Modifiers ParseModifiers(Parser* parser, LookupMask modifierLookupMask = LookupMask::Default)
{
Modifiers modifiers;
@@ -1216,7 +1224,7 @@ static Modifiers ParseModifiers(Parser* parser, LookupMask modifierLookupMask =
if (as<VisibilityModifier>(parsedModifier))
{
if (auto currentModule = parser->getCurrentModuleDecl())
- currentModule->isInLegacyLanguage = false;
+ maybeUpgradeLanguageVersionFromLegacy(currentModule->languageVersion);
}
AddModifier(&modifierLink, parsedModifier);
continue;
@@ -1321,7 +1329,7 @@ static NodeBase* parseIncludeDecl(Parser* parser, void* /*userData*/)
auto decl = parser->astBuilder->create<IncludeDecl>();
parseFileReferenceDeclBase(parser, decl);
if (auto currentModule = parser->getCurrentModuleDecl())
- currentModule->isInLegacyLanguage = false;
+ maybeUpgradeLanguageVersionFromLegacy(currentModule->languageVersion);
return decl;
}
@@ -1361,7 +1369,7 @@ static NodeBase* parseModuleDeclarationDecl(Parser* parser, void* /*userData*/)
}
parser->ReadToken(TokenType::Semicolon);
if (auto currentModule = parser->getCurrentModuleDecl())
- currentModule->isInLegacyLanguage = false;
+ maybeUpgradeLanguageVersionFromLegacy(currentModule->languageVersion);
return decl;
}
@@ -5153,7 +5161,20 @@ void Parser::parseSourceFile(ContainerDecl* program)
currentModule = getModuleDecl(program);
- // If the program already has a scope, then reuse it instead of overwriting it!
+ // Verify that the language version is valid.
+ if (sourceLanguage == SourceLanguage::Slang)
+ {
+ if (!isValidSlangLanguageVersion(currentModule->languageVersion))
+ {
+ sink->diagnose(
+ program->loc,
+ Diagnostics::unknownLanguageVersion,
+ currentModule->languageVersion);
+ }
+ }
+
+ // If the program already has a scope, then
+ // reuse it instead of overwriting it!
if (program->ownedScope)
PushScope(program->ownedScope);
else
@@ -5607,7 +5628,7 @@ static Decl* _tryResolveDecl(Parser* parser, Expr* expr)
auto lookupResult = lookUpDirectAndTransparentMembers(
parser->astBuilder,
- nullptr, // no semantics visitor available yet
+ parser->semanticsVisitor,
staticMemberExpr->name,
aggTypeDecl,
declRef);
@@ -5627,7 +5648,7 @@ static Decl* _tryResolveDecl(Parser* parser, Expr* expr)
// Do the lookup in the current scope
auto lookupResult = lookUp(
parser->astBuilder,
- nullptr, // no semantics visitor available yet
+ parser->semanticsVisitor,
varExpr->name,
parser->currentScope);
if (!lookupResult.isValid() || lookupResult.isOverloaded())
@@ -5641,11 +5662,8 @@ static Decl* _tryResolveDecl(Parser* parser, Expr* expr)
static bool isTypeName(Parser* parser, Name* name)
{
- auto lookupResult = lookUp(
- parser->astBuilder,
- nullptr, // no semantics visitor available yet
- name,
- parser->currentScope);
+ auto lookupResult =
+ lookUp(parser->astBuilder, parser->semanticsVisitor, name, parser->currentScope);
if (!lookupResult.isValid() || lookupResult.isOverloaded())
return false;
@@ -7201,17 +7219,23 @@ static bool _isCast(Parser* parser, Expr* expr)
return false;
}
-static bool tryParseExpression(Parser* parser, Expr*& outExpr, TokenType tokenTypeAfter)
+template<typename FIsValidFollowToken>
+static bool tryParseExpression(
+ Parser* parser,
+ Expr*& outExpr,
+ Precedence exprLevel,
+ const FIsValidFollowToken& isValidFollowToken)
{
auto cursor = parser->tokenReader.getCursor();
auto isRecovering = parser->isRecovering;
auto oldSink = parser->sink;
DiagnosticSink newSink(parser->sink->getSourceManager(), nullptr);
parser->sink = &newSink;
- outExpr = parser->ParseExpression();
+ outExpr = parser->ParseExpression(exprLevel);
parser->sink = oldSink;
parser->isRecovering = isRecovering;
- if (outExpr && newSink.getErrorCount() == 0 && parser->LookAheadToken(tokenTypeAfter))
+ if (outExpr && newSink.getErrorCount() == 0 &&
+ isValidFollowToken(parser->tokenReader.peekTokenType()))
{
return true;
}
@@ -7297,9 +7321,7 @@ static Expr* parseAtomicExpr(Parser* parser)
tcexpr->loc = openParen.loc;
tcexpr->functionExpr = varExpr;
-
- auto arg = parsePrefixExpr(parser);
- tcexpr->arguments.add(arg);
+ tcexpr->arguments.add(parsePrefixExpr(parser));
return tcexpr;
}
@@ -7313,45 +7335,99 @@ static Expr* parseAtomicExpr(Parser* parser)
Expr* base = nullptr;
if (parser->LookAheadToken(TokenType::RParent))
{
- // We don't support empty parentheses `()` as a valid expression.
- parser->diagnose(openParen, Diagnostics::invalidEmptyParenthesisExpr);
- base = parser->astBuilder->create<IncompleteExpr>();
- base->type = parser->astBuilder->getErrorType();
+ if (parser->currentModule->languageVersion >= SLANG_LANGUAGE_VERSION_2026)
+ {
+ // We support empty parentheses `()` as a valid expression to construct an
+ // empty tuple in Slang 2026.
+ base = parser->astBuilder->create<TupleExpr>();
+ base->loc = openParen.loc;
+ }
+ else
+ {
+ // We don't support empty parentheses `()` as a valid expression prior to
+ // Slang 2026.
+ parser->diagnose(openParen, Diagnostics::invalidEmptyParenthesisExpr);
+ base = parser->astBuilder->create<IncompleteExpr>();
+ base->type = parser->astBuilder->getErrorType();
+ }
}
else
{
- if (!tryParseExpression(parser, base, TokenType::RParent))
+ // When language version is 2026 or later, we no longer parse comma as a
+ // C/C++-style comma operator when it is inside a paranthesis,
+ // but rather as a tuple element separator.
+ //
+ Precedence exprLevel = Precedence::Comma;
+ if (parser->sourceLanguage == SourceLanguage::Slang &&
+ parser->currentModule->languageVersion >= SLANG_LANGUAGE_VERSION_2026)
+ {
+ // Setting exprLevel to Assignment here will allow the following
+ // tryParseExpression call to parse the expression until the next `)` or
+ // `,`, instead of consuming any ',' as a comma operator.
+ exprLevel = Precedence::Assignment;
+ }
+ auto isValidFollowToken = [=](TokenType tokenType)
+ {
+ if (tokenType == TokenType::RParent)
+ return true;
+ if (exprLevel == Precedence::Assignment && tokenType == TokenType::Comma)
+ return true;
+ return false;
+ };
+ if (!tryParseExpression(parser, base, exprLevel, isValidFollowToken))
{
base = parser->ParseType();
}
}
- parser->ReadToken(TokenType::RParent);
-
- // We now try and determine by what base is, if this is actually a cast or an
- // expression in parentheses
- if (_isCast(parser, base))
+ if (parser->LookAheadToken(TokenType::Comma))
{
- // Parse as a cast
-
- TypeCastExpr* tcexpr = parser->astBuilder->create<ExplicitCastExpr>();
- tcexpr->loc = openParen.loc;
-
- tcexpr->functionExpr = base;
-
- auto arg = parsePrefixExpr(parser);
- tcexpr->arguments.add(arg);
-
- return tcexpr;
+ // We have a comma, so we are not done yet.
+ // If we reach here, the language version must be 2026 or later,
+ // where we allow (a,b,c,...) syntax as a tuple, otherwise we would have
+ // parsed it into `base`.
+ //
+ List<Expr*> elementExprs;
+ elementExprs.add(base);
+ while (AdvanceIf(parser, TokenType::Comma))
+ {
+ if (parser->LookAheadToken(TokenType::RParent))
+ break;
+ auto elementExpr = parser->ParseArgExpr();
+ elementExprs.add(elementExpr);
+ }
+ parser->ReadToken(TokenType::RParent);
+ TupleExpr* tupleExpr = parser->astBuilder->create<TupleExpr>();
+ tupleExpr->loc = openParen.loc;
+ tupleExpr->elements = _Move(elementExprs);
+ return tupleExpr;
}
else
{
- // Pass as an expression in parentheses
+ // We parsed an expression in the form of (expr), without
+ // any commas in `expr`.
+ // We now try and determine by what base is, if this is actually a cast or an
+ // expression in parentheses.
+ //
+ parser->ReadToken(TokenType::RParent);
+ if (_isCast(parser, base))
+ {
+ // Parse as a cast
+ TypeCastExpr* tcexpr = parser->astBuilder->create<ExplicitCastExpr>();
+ tcexpr->loc = openParen.loc;
+
+ tcexpr->functionExpr = base;
+ tcexpr->arguments.add(parsePrefixExpr(parser));
- ParenExpr* parenExpr = parser->astBuilder->create<ParenExpr>();
- parenExpr->loc = openParen.loc;
- parenExpr->base = base;
- return parenExpr;
+ return tcexpr;
+ }
+ else
+ {
+ ParenExpr* parenExpr = parser->astBuilder->create<ParenExpr>();
+ parenExpr->loc = openParen.loc;
+ parenExpr->base = base;
+ return parenExpr;
+ }
}
}
}
@@ -8519,7 +8595,7 @@ void parseSourceFile(
Parser parser(astBuilder, tokens, sink, outerScope, options);
parser.namePool = translationUnit->getNamePool();
- parser.sourceLanguage = translationUnit->sourceLanguage;
+ parser.sourceLanguage = sourceLanguage;
return parser.parseSourceFile(parentDecl);
}
diff --git a/source/slang/slang-preprocessor.cpp b/source/slang/slang-preprocessor.cpp
index 3f120d5eb..b29fa2716 100644
--- a/source/slang/slang-preprocessor.cpp
+++ b/source/slang/slang-preprocessor.cpp
@@ -1305,6 +1305,8 @@ struct Preprocessor
/// Detected source language.
SourceLanguage language = SourceLanguage::Unknown;
+ SlangLanguageVersion languageVersion = SLANG_LANGUAGE_VERSION_UNKNOWN;
+
/// Stores macro definition and invocation info for language server.
PreprocessorContentAssistInfo* contentAssistInfo = nullptr;
@@ -4360,7 +4362,7 @@ static void HandleExtensionDirective(PreprocessorDirectiveContext* context)
static void HandleVersionDirective(PreprocessorDirectiveContext* context)
{
- [[maybe_unused]] int version;
+ int version = SLANG_LANGUAGE_VERSION_UNKNOWN;
switch (PeekTokenType(context))
{
case TokenType::IntegerLiteral:
@@ -4374,8 +4376,78 @@ static void HandleVersionDirective(PreprocessorDirectiveContext* context)
}
SkipToEndOfLine(context);
- context->m_preprocessor->language = SourceLanguage::GLSL;
- // TODO, just skip the version for now
+
+ if (isValidGLSLVersion(version))
+ {
+ context->m_preprocessor->language = SourceLanguage::GLSL;
+ }
+ else
+ {
+ GetSink(context)->diagnose(
+ GetDirectiveLoc(context),
+ Diagnostics::unknownLanguageVersion,
+ version);
+ }
+ context->m_preprocessor->languageVersion = (SlangLanguageVersion)version;
+}
+
+static void HandleLanguageDirective(PreprocessorDirectiveContext* context)
+{
+ int version = SLANG_LANGUAGE_VERSION_UNKNOWN;
+ switch (PeekTokenType(context))
+ {
+ case TokenType::IntegerLiteral:
+ version = stringToInt(AdvanceToken(context).getContent());
+ break;
+ case TokenType::Identifier:
+ {
+ auto token = AdvanceToken(context);
+ if (token.getContent().caseInsensitiveEquals(toSlice("slang")))
+ {
+ context->m_preprocessor->language = SourceLanguage::Slang;
+ token = AdvanceToken(context);
+ }
+ else if (token.getContent() == "glsl")
+ {
+ context->m_preprocessor->language = SourceLanguage::GLSL;
+ token = AdvanceToken(context);
+ }
+ if (token.getContent() == "latest")
+ version = SLANG_LANGUAGE_VERSION_LATEST;
+ else if (token.getContent() == "legacy")
+ version = SLANG_LANGUAGE_VERSION_LEGACY;
+ else if (token.type == TokenType::IntegerLiteral)
+ version = stringToInt(token.getContent());
+ else
+ {
+ GetSink(context)->diagnose(
+ GetDirectiveLoc(context),
+ Diagnostics::unknownLanguage,
+ token);
+ }
+ }
+ break;
+ default:
+ GetSink(context)->diagnose(
+ GetDirectiveLoc(context),
+ Diagnostics::expectedIntegralVersionNumber);
+ break;
+ }
+
+ SkipToEndOfLine(context);
+
+ if (isValidSlangLanguageVersion((SlangLanguageVersion)version))
+ {
+ context->m_preprocessor->language = SourceLanguage::Slang;
+ }
+ else
+ {
+ GetSink(context)->diagnose(
+ GetDirectiveLoc(context),
+ Diagnostics::unknownLanguageVersion,
+ version);
+ }
+ context->m_preprocessor->languageVersion = (SlangLanguageVersion)version;
}
// Handle an invalid directive
@@ -4434,6 +4506,9 @@ static const PreprocessorDirective kDirectives[] = {
{"line", &HandleLineDirective, 0},
{"pragma", &HandlePragmaDirective, 0},
+ {"language", &HandleLanguageDirective, 0},
+ {"lang", &HandleLanguageDirective, 0},
+
// GLSL
{"version", &HandleVersionDirective, 0},
{"extension", &HandleExtensionDirective, 0},
@@ -4783,6 +4858,7 @@ TokenList preprocessSource(
Dictionary<String, String> const& defines,
Linkage* linkage,
SourceLanguage& outDetectedLanguage,
+ SlangLanguageVersion& outLanguageVersion,
PreprocessorHandler* handler)
{
PreprocessorDesc desc;
@@ -4806,13 +4882,14 @@ TokenList preprocessSource(
new preprocessor::WarningStateTracker(desc.sourceManager);
desc.sink->setSourceWarningStateTracker(wst);
- return preprocessSource(file, desc, outDetectedLanguage);
+ return preprocessSource(file, desc, outDetectedLanguage, outLanguageVersion);
}
TokenList preprocessSource(
SourceFile* file,
PreprocessorDesc const& desc,
- SourceLanguage& outDetectedLanguage)
+ SourceLanguage& outDetectedLanguage,
+ SlangLanguageVersion& outLanguageVersion)
{
using namespace preprocessor;
@@ -4908,7 +4985,8 @@ TokenList preprocessSource(
#endif
outDetectedLanguage = preprocessor.language;
-
+ if (preprocessor.languageVersion != SLANG_LANGUAGE_VERSION_UNKNOWN)
+ outLanguageVersion = preprocessor.languageVersion;
return tokens;
}
diff --git a/source/slang/slang-preprocessor.h b/source/slang/slang-preprocessor.h
index bde79b649..587bfb594 100644
--- a/source/slang/slang-preprocessor.h
+++ b/source/slang/slang-preprocessor.h
@@ -65,7 +65,8 @@ struct PreprocessorDesc
TokenList preprocessSource(
SourceFile* file,
PreprocessorDesc const& desc,
- SourceLanguage& outDetectedLanguage);
+ SourceLanguage& outDetectedLanguage,
+ SlangLanguageVersion& outLanguageVersion);
/// Convenience wrapper for `preprocessSource` when a `Linkage` is available
TokenList preprocessSource(
@@ -75,6 +76,7 @@ TokenList preprocessSource(
Dictionary<String, String> const& defines,
Linkage* linkage,
SourceLanguage& outDetectedLanguage,
+ SlangLanguageVersion& outLanguageVersion,
PreprocessorHandler* handler = nullptr);
// The following functions are intended to be used inside of implementations
diff --git a/source/slang/slang-serialize-ast.cpp b/source/slang/slang-serialize-ast.cpp
index 9a61dbc5a..3a2d3818e 100644
--- a/source/slang/slang-serialize-ast.cpp
+++ b/source/slang/slang-serialize-ast.cpp
@@ -99,6 +99,11 @@ void serialize(Serializer const& serializer, SPIRVAsmOperand::Flavor& value)
serializeEnum(serializer, value);
}
+void serialize(Serializer const& serializer, SlangLanguageVersion version)
+{
+ serializeEnum(serializer, version);
+}
+
void serialize(Serializer const& serializer, MatrixCoord& value)
{
SLANG_SCOPED_SERIALIZER_TUPLE(serializer);
diff --git a/source/slang/slang-type-layout.cpp b/source/slang/slang-type-layout.cpp
index 5f2cf4ddf..6ac3ba079 100644
--- a/source/slang/slang-type-layout.cpp
+++ b/source/slang/slang-type-layout.cpp
@@ -1771,11 +1771,11 @@ LayoutRulesImpl* CPULayoutRulesFamilyImpl::getVaryingOutputRules()
}
LayoutRulesImpl* CPULayoutRulesFamilyImpl::getSpecializationConstantRules()
{
- return nullptr;
+ return &kCPULayoutRulesImpl_;
}
LayoutRulesImpl* CPULayoutRulesFamilyImpl::getShaderStorageBufferRules(CompilerOptionSet&)
{
- return nullptr;
+ return &kCPULayoutRulesImpl_;
}
LayoutRulesImpl* CPULayoutRulesFamilyImpl::getParameterBlockRules(CompilerOptionSet&)
{
@@ -1829,19 +1829,19 @@ LayoutRulesImpl* CUDALayoutRulesFamilyImpl::getTextureBufferRules(CompilerOption
LayoutRulesImpl* CUDALayoutRulesFamilyImpl::getVaryingInputRules()
{
- return nullptr;
+ return &kCUDALayoutRulesImpl_;
}
LayoutRulesImpl* CUDALayoutRulesFamilyImpl::getVaryingOutputRules()
{
- return nullptr;
+ return &kCUDALayoutRulesImpl_;
}
LayoutRulesImpl* CUDALayoutRulesFamilyImpl::getSpecializationConstantRules()
{
- return nullptr;
+ return &kCUDALayoutRulesImpl_;
}
LayoutRulesImpl* CUDALayoutRulesFamilyImpl::getShaderStorageBufferRules(CompilerOptionSet&)
{
- return nullptr;
+ return &kCUDALayoutRulesImpl_;
}
LayoutRulesImpl* CUDALayoutRulesFamilyImpl::getParameterBlockRules(CompilerOptionSet&)
{
diff --git a/source/slang/slang.cpp b/source/slang/slang.cpp
index 7fc519c03..bda847815 100644
--- a/source/slang/slang.cpp
+++ b/source/slang/slang.cpp
@@ -2730,7 +2730,8 @@ Expr* Linkage::parseTermString(String typeStr, Scope* scope)
// We need to temporarily replace the SourceManager for this CompileRequest
ScopeReplaceSourceManager scopeReplaceSourceManager(this, &localSourceManager);
- SourceLanguage sourceLanguage;
+ SourceLanguage sourceLanguage = SourceLanguage::Slang;
+ SlangLanguageVersion languageVersion = m_optionSet.getLanguageVersion();
auto tokens = preprocessSource(
srcFile,
@@ -2738,7 +2739,8 @@ Expr* Linkage::parseTermString(String typeStr, Scope* scope)
nullptr,
Dictionary<String, String>(),
this,
- sourceLanguage);
+ sourceLanguage,
+ languageVersion);
if (sourceLanguage == SourceLanguage::Unknown)
sourceLanguage = SourceLanguage::Slang;
@@ -3411,7 +3413,9 @@ void FrontEndCompileRequest::parseTranslationUnit(TranslationUnitRequest* transl
for (auto sourceFile : translationUnit->getSourceFiles())
{
- SourceLanguage sourceLanguage = SourceLanguage::Unknown;
+ SourceLanguage sourceLanguage = translationUnit->sourceLanguage;
+ SlangLanguageVersion languageVersion =
+ translationUnit->compileRequest->optionSet.getLanguageVersion();
auto tokens = preprocessSource(
sourceFile,
getSink(),
@@ -3419,8 +3423,11 @@ void FrontEndCompileRequest::parseTranslationUnit(TranslationUnitRequest* transl
combinedPreprocessorDefinitions,
getLinkage(),
sourceLanguage,
+ languageVersion,
&preprocessorHandler);
+ translationUnitSyntax->languageVersion = languageVersion;
+
if (sourceLanguage == SourceLanguage::Unknown)
sourceLanguage = translationUnit->sourceLanguage;
@@ -4915,11 +4922,13 @@ Linkage::IncludeResult Linkage::findAndIncludeFile(
// Create a transparent FileDecl to hold all children from the included file.
auto fileDecl = module->getASTBuilder()->create<FileDecl>();
fileDecl->nameAndLoc.name = name;
+ fileDecl->parentDecl = module->getModuleDecl();
module->getIncludedSourceFileMap().add(sourceFile, fileDecl);
FrontEndPreprocessorHandler preprocessorHandler(module, module->getASTBuilder(), sink);
auto combinedPreprocessorDefinitions = translationUnit->getCombinedPreprocessorDefinitions();
- SourceLanguage sourceLanguage = SourceLanguage::Unknown;
+ SourceLanguage sourceLanguage = translationUnit->sourceLanguage;
+ SlangLanguageVersion slangLanguageVersion = module->getModuleDecl()->languageVersion;
auto tokens = preprocessSource(
sourceFile,
sink,
@@ -4927,11 +4936,19 @@ Linkage::IncludeResult Linkage::findAndIncludeFile(
combinedPreprocessorDefinitions,
this,
sourceLanguage,
+ slangLanguageVersion,
&preprocessorHandler);
if (sourceLanguage == SourceLanguage::Unknown)
sourceLanguage = translationUnit->sourceLanguage;
+ if (slangLanguageVersion != module->getModuleDecl()->languageVersion)
+ {
+ sink->diagnose(
+ tokens.begin()->getLoc(),
+ Diagnostics::languageVersionDiffersFromIncludingModule);
+ }
+
auto outerScope = module->getModuleDecl()->ownedScope;
parseSourceFile(
module->getASTBuilder(),