summaryrefslogtreecommitdiffstats
path: root/source/slang
diff options
context:
space:
mode:
authorYong He <yonghe@outlook.com>2023-12-06 12:05:07 -0800
committerGitHub <noreply@github.com>2023-12-06 12:05:07 -0800
commit11111e5733b189127dc2c4934d67693b9bc6e764 (patch)
tree0ba84df3e856eb104abec2ecac47242bc70a7b7d /source/slang
parentfa6d8717d02912697c09f2d7de802723ac6d6e47 (diff)
Support visibility control and default to `internal`. (#3380)
* Support visibility control and default to `internal`. * Fix wip. * Fixes. * Fix. * Fix test. * Add legacy language detection and compatibility for existing code. * Add doc. --------- Co-authored-by: Yong He <yhe@nvidia.com>
Diffstat (limited to 'source/slang')
-rw-r--r--source/slang/diff.meta.slang2
-rw-r--r--source/slang/glsl.meta.slang394
-rw-r--r--source/slang/slang-ast-decl.h9
-rw-r--r--source/slang/slang-ast-modifier.h5
-rw-r--r--source/slang/slang-ast-support-types.h8
-rw-r--r--source/slang/slang-check-conversion.cpp2
-rw-r--r--source/slang/slang-check-decl.cpp100
-rw-r--r--source/slang/slang-check-expr.cpp463
-rw-r--r--source/slang/slang-check-impl.h54
-rw-r--r--source/slang/slang-check-modifier.cpp84
-rw-r--r--source/slang/slang-check-overload.cpp62
-rw-r--r--source/slang/slang-diagnostic-defs.h9
-rw-r--r--source/slang/slang-emit-c-like.cpp4
-rw-r--r--source/slang/slang-ir-autodiff.cpp5
-rw-r--r--source/slang/slang-ir-dll-export.cpp6
-rw-r--r--source/slang/slang-ir-generics-lowering-context.cpp9
-rw-r--r--source/slang/slang-ir-link.cpp9
-rw-r--r--source/slang/slang-ir-lower-generic-type.cpp4
-rw-r--r--source/slang/slang-ir-pytorch-cpp-binding.cpp10
-rw-r--r--source/slang/slang-language-server-completion.cpp2
-rw-r--r--source/slang/slang-lookup.cpp16
-rw-r--r--source/slang/slang-lookup.h5
-rw-r--r--source/slang/slang-lower-to-ir.cpp41
-rw-r--r--source/slang/slang-parser.cpp29
-rw-r--r--source/slang/slang-syntax.cpp11
-rw-r--r--source/slang/slang-syntax.h1
26 files changed, 907 insertions, 437 deletions
diff --git a/source/slang/diff.meta.slang b/source/slang/diff.meta.slang
index 31ed5845e..6f4888a5d 100644
--- a/source/slang/diff.meta.slang
+++ b/source/slang/diff.meta.slang
@@ -26,7 +26,7 @@ __attributeTarget(FunctionDeclBase)
attribute_syntax [NoDiffThis] : NoDiffThisAttribute;
// A 'none-type' that acts as a run-time sentinel for zero differentials.
-public struct NullDifferential : IDifferentiable
+export struct NullDifferential : IDifferentiable
{
// for now, we'll use at least one field to make sure the type is non-empty
uint dummy;
diff --git a/source/slang/glsl.meta.slang b/source/slang/glsl.meta.slang
index 98f30cd3c..a43a7ba3c 100644
--- a/source/slang/glsl.meta.slang
+++ b/source/slang/glsl.meta.slang
@@ -2,385 +2,385 @@
// From the GLSL spec, section 4.1. 'asic Types'
//
-typealias vec2 = vector<float, 2>;
-typealias vec3 = vector<float, 3>;
-typealias vec4 = vector<float, 4>;
-
-typealias dvec2 = vector<double, 2>;
-typealias dvec3 = vector<double, 3>;
-typealias dvec4 = vector<double, 4>;
-
-typealias bvec2 = vector<bool, 2>;
-typealias bvec3 = vector<bool, 3>;
-typealias bvec4 = vector<bool, 4>;
-
-typealias ivec2 = vector<int, 2>;
-typealias ivec3 = vector<int, 3>;
-typealias ivec4 = vector<int, 4>;
-
-typealias uvec2 = vector<uint, 2>;
-typealias uvec3 = vector<uint, 3>;
-typealias uvec4 = vector<uint, 4>;
-
-typealias i8vec2 = vector<int8_t, 2>;
-typealias i8vec3 = vector<int8_t, 3>;
-typealias i8vec4 = vector<int8_t, 4>;
-
-typealias u8vec2 = vector<uint8_t, 2>;
-typealias u8vec3 = vector<uint8_t, 3>;
-typealias u8vec4 = vector<uint8_t, 4>;
-
-typealias i16vec2 = vector<int16_t, 2>;
-typealias i16vec3 = vector<int16_t, 3>;
-typealias i16vec4 = vector<int16_t, 4>;
-
-typealias u16vec2 = vector<uint16_t, 2>;
-typealias u16vec3 = vector<uint16_t, 3>;
-typealias u16vec4 = vector<uint16_t, 4>;
-
-typealias i64vec2 = vector<int64_t, 2>;
-typealias i64vec3 = vector<int64_t, 3>;
-typealias i64vec4 = vector<int64_t, 4>;
-
-typealias u64vec2 = vector<uint64_t, 2>;
-typealias u64vec3 = vector<uint64_t, 3>;
-typealias u64vec4 = vector<uint64_t, 4>;
-
-typealias mat2 = matrix<float, 2, 2>;
-typealias mat3 = matrix<float, 3, 3>;
-typealias mat4 = matrix<float, 4, 4>;
-
-typealias mat2x2 = matrix<float, 2, 2>;
-typealias mat2x3 = matrix<float, 3, 2>;
-typealias mat2x4 = matrix<float, 4, 2>;
-
-typealias mat3x2 = matrix<float, 2, 3>;
-typealias mat3x3 = matrix<float, 3, 3>;
-typealias mat3x4 = matrix<float, 4, 3>;
-
-typealias mat4x2 = matrix<float, 2, 4>;
-typealias mat4x3 = matrix<float, 3, 4>;
-typealias mat4x4 = matrix<float, 4, 4>;
-
-typealias dmat2 = matrix<double, 2, 2>;
-typealias dmat3 = matrix<double, 3, 3>;
-typealias dmat4 = matrix<double, 4, 4>;
-
-typealias dmat2x2 = matrix<double, 2, 2>;
-typealias dmat2x3 = matrix<double, 3, 2>;
-typealias dmat2x4 = matrix<double, 4, 2>;
-
-typealias dmat3x2 = matrix<double, 2, 3>;
-typealias dmat3x3 = matrix<double, 3, 3>;
-typealias dmat3x4 = matrix<double, 4, 3>;
-
-typealias dmat4x2 = matrix<double, 2, 4>;
-typealias dmat4x3 = matrix<double, 3, 4>;
-typealias dmat4x4 = matrix<double, 4, 4>;
-
-typealias usampler1D = Sampler1D<uint4>;
-typealias isampler1D = Sampler1D<int4>;
-typealias sampler1D = Sampler1D<float4>;
-
-typealias usampler2D = Sampler2D<uint4>;
-typealias isampler2D = Sampler2D<int4>;
-typealias sampler2D = Sampler2D<float4>;
-
-typealias usampler3D = Sampler3D<uint4>;
-typealias isampler3D = Sampler3D<int4>;
-typealias sampler3D = Sampler3D<float4>;
-
-typealias usamplerCube = SamplerCube<uint4>;
-typealias isamplerCube = SamplerCube<int4>;
-typealias samplerCube = SamplerCube<float4>;
-
-typealias Sampler1DShadow<T=float> = __TextureImpl<T, __Shape1D, /*isArray:*/ 0, /*isMS:*/ 0, /*sampleCount:*/ 0, /*access:*/ 0, /*isShadow: */ 1, /*isCombined: */ 1, /*format*/ 0>;
-typealias usampler1DShadow = Sampler1DShadow<uint>;
-typealias isampler1DShadow = Sampler1DShadow<int>;
-typealias sampler1DShadow = Sampler1DShadow<float>;
-
-typealias Sampler2DShadow<T=float> = __TextureImpl<T, __Shape2D, /*isArray:*/ 0, /*isMS:*/ 0, /*sampleCount:*/ 0, /*access:*/ 0, /*isShadow: */ 1, /*isCombined: */ 1, /*format*/ 0>;
-typealias usampler2DShadow = Sampler2DShadow<uint>;
-typealias isampler2DShadow = Sampler2DShadow<int>;
-typealias sampler2DShadow = Sampler2DShadow<float>;
-
-typealias SamplerCubeShadow<T=float> = __TextureImpl<T, __ShapeCube, /*isArray:*/ 0, /*isMS:*/ 0, /*sampleCount:*/ 0, /*access:*/ 0, /*isShadow: */ 1, /*isCombined: */ 1, /*format*/ 0>;
-typealias usamplerCubeShadow = SamplerCubeShadow<uint>;
-typealias isamplerCubeShadow = SamplerCubeShadow<int>;
-typealias samplerCubeShadow = SamplerCubeShadow<float>;
-
-typealias usampler1DArray = Sampler1DArray<uint4>;
-typealias isampler1DArray = Sampler1DArray<int4>;
-typealias sampler1DArray = Sampler1DArray<float4>;
-
-typealias usampler2DArray = Sampler2DArray<uint4>;
-typealias isampler2DArray = Sampler2DArray<int4>;
-typealias sampler2DArray = Sampler2DArray<float4>;
-
-typealias usamplerCubeArray = SamplerCubeArray<uint4>;
-typealias isamplerCubeArray = SamplerCubeArray<int4>;
-typealias samplerCubeArray = SamplerCubeArray<float4>;
-
-typealias Sampler1DArrayShadow<T=float> = __TextureImpl<T, __Shape1D, /*isArray:*/ 1, /*isMS:*/ 0, /*sampleCount:*/ 0, /*access:*/ 0, /*isShadow: */ 1, /*isCombined: */ 1, /*format*/ 0>;
-typealias usampler1DArrayShadow = Sampler1DArrayShadow<uint>;
-typealias isampler1DArrayShadow = Sampler1DArrayShadow<int>;
-typealias sampler1DArrayShadow = Sampler1DArrayShadow<float>;
+public typealias vec2 = vector<float, 2>;
+public typealias vec3 = vector<float, 3>;
+public typealias vec4 = vector<float, 4>;
+
+public typealias dvec2 = vector<double, 2>;
+public typealias dvec3 = vector<double, 3>;
+public typealias dvec4 = vector<double, 4>;
+
+public typealias bvec2 = vector<bool, 2>;
+public typealias bvec3 = vector<bool, 3>;
+public typealias bvec4 = vector<bool, 4>;
+
+public typealias ivec2 = vector<int, 2>;
+public typealias ivec3 = vector<int, 3>;
+public typealias ivec4 = vector<int, 4>;
+
+public typealias uvec2 = vector<uint, 2>;
+public typealias uvec3 = vector<uint, 3>;
+public typealias uvec4 = vector<uint, 4>;
+
+public typealias i8vec2 = vector<int8_t, 2>;
+public typealias i8vec3 = vector<int8_t, 3>;
+public typealias i8vec4 = vector<int8_t, 4>;
+
+public typealias u8vec2 = vector<uint8_t, 2>;
+public typealias u8vec3 = vector<uint8_t, 3>;
+public typealias u8vec4 = vector<uint8_t, 4>;
+
+public typealias i16vec2 = vector<int16_t, 2>;
+public typealias i16vec3 = vector<int16_t, 3>;
+public typealias i16vec4 = vector<int16_t, 4>;
+
+public typealias u16vec2 = vector<uint16_t, 2>;
+public typealias u16vec3 = vector<uint16_t, 3>;
+public typealias u16vec4 = vector<uint16_t, 4>;
+
+public typealias i64vec2 = vector<int64_t, 2>;
+public typealias i64vec3 = vector<int64_t, 3>;
+public typealias i64vec4 = vector<int64_t, 4>;
+
+public typealias u64vec2 = vector<uint64_t, 2>;
+public typealias u64vec3 = vector<uint64_t, 3>;
+public typealias u64vec4 = vector<uint64_t, 4>;
+
+public typealias mat2 = matrix<float, 2, 2>;
+public typealias mat3 = matrix<float, 3, 3>;
+public typealias mat4 = matrix<float, 4, 4>;
+
+public typealias mat2x2 = matrix<float, 2, 2>;
+public typealias mat2x3 = matrix<float, 3, 2>;
+public typealias mat2x4 = matrix<float, 4, 2>;
+
+public typealias mat3x2 = matrix<float, 2, 3>;
+public typealias mat3x3 = matrix<float, 3, 3>;
+public typealias mat3x4 = matrix<float, 4, 3>;
+
+public typealias mat4x2 = matrix<float, 2, 4>;
+public typealias mat4x3 = matrix<float, 3, 4>;
+public typealias mat4x4 = matrix<float, 4, 4>;
+
+public typealias dmat2 = matrix<double, 2, 2>;
+public typealias dmat3 = matrix<double, 3, 3>;
+public typealias dmat4 = matrix<double, 4, 4>;
+
+public typealias dmat2x2 = matrix<double, 2, 2>;
+public typealias dmat2x3 = matrix<double, 3, 2>;
+public typealias dmat2x4 = matrix<double, 4, 2>;
+
+public typealias dmat3x2 = matrix<double, 2, 3>;
+public typealias dmat3x3 = matrix<double, 3, 3>;
+public typealias dmat3x4 = matrix<double, 4, 3>;
+
+public typealias dmat4x2 = matrix<double, 2, 4>;
+public typealias dmat4x3 = matrix<double, 3, 4>;
+public typealias dmat4x4 = matrix<double, 4, 4>;
+
+public typealias usampler1D = Sampler1D<uint4>;
+public typealias isampler1D = Sampler1D<int4>;
+public typealias sampler1D = Sampler1D<float4>;
+
+public typealias usampler2D = Sampler2D<uint4>;
+public typealias isampler2D = Sampler2D<int4>;
+public typealias sampler2D = Sampler2D<float4>;
+
+public typealias usampler3D = Sampler3D<uint4>;
+public typealias isampler3D = Sampler3D<int4>;
+public typealias sampler3D = Sampler3D<float4>;
+
+public typealias usamplerCube = SamplerCube<uint4>;
+public typealias isamplerCube = SamplerCube<int4>;
+public typealias samplerCube = SamplerCube<float4>;
+
+public typealias Sampler1DShadow<T=float> = __TextureImpl<T, __Shape1D, /*isArray:*/ 0, /*isMS:*/ 0, /*sampleCount:*/ 0, /*access:*/ 0, /*isShadow: */ 1, /*isCombined: */ 1, /*format*/ 0>;
+public typealias usampler1DShadow = Sampler1DShadow<uint>;
+public typealias isampler1DShadow = Sampler1DShadow<int>;
+public typealias sampler1DShadow = Sampler1DShadow<float>;
+
+public typealias Sampler2DShadow<T=float> = __TextureImpl<T, __Shape2D, /*isArray:*/ 0, /*isMS:*/ 0, /*sampleCount:*/ 0, /*access:*/ 0, /*isShadow: */ 1, /*isCombined: */ 1, /*format*/ 0>;
+public typealias usampler2DShadow = Sampler2DShadow<uint>;
+public typealias isampler2DShadow = Sampler2DShadow<int>;
+public typealias sampler2DShadow = Sampler2DShadow<float>;
+
+public typealias SamplerCubeShadow<T=float> = __TextureImpl<T, __ShapeCube, /*isArray:*/ 0, /*isMS:*/ 0, /*sampleCount:*/ 0, /*access:*/ 0, /*isShadow: */ 1, /*isCombined: */ 1, /*format*/ 0>;
+public typealias usamplerCubeShadow = SamplerCubeShadow<uint>;
+public typealias isamplerCubeShadow = SamplerCubeShadow<int>;
+public typealias samplerCubeShadow = SamplerCubeShadow<float>;
+
+public typealias usampler1DArray = Sampler1DArray<uint4>;
+public typealias isampler1DArray = Sampler1DArray<int4>;
+public typealias sampler1DArray = Sampler1DArray<float4>;
+
+public typealias usampler2DArray = Sampler2DArray<uint4>;
+public typealias isampler2DArray = Sampler2DArray<int4>;
+public typealias sampler2DArray = Sampler2DArray<float4>;
+
+public typealias usamplerCubeArray = SamplerCubeArray<uint4>;
+public typealias isamplerCubeArray = SamplerCubeArray<int4>;
+public typealias samplerCubeArray = SamplerCubeArray<float4>;
+
+public typealias Sampler1DArrayShadow<T=float> = __TextureImpl<T, __Shape1D, /*isArray:*/ 1, /*isMS:*/ 0, /*sampleCount:*/ 0, /*access:*/ 0, /*isShadow: */ 1, /*isCombined: */ 1, /*format*/ 0>;
+public typealias usampler1DArrayShadow = Sampler1DArrayShadow<uint>;
+public typealias isampler1DArrayShadow = Sampler1DArrayShadow<int>;
+public typealias sampler1DArrayShadow = Sampler1DArrayShadow<float>;
-typealias Sampler2DArrayShadow<T=float> = __TextureImpl<T, __Shape2D, /*isArray:*/ 1, /*isMS:*/ 0, /*sampleCount:*/ 0, /*access:*/ 0, /*isShadow: */ 1, /*isCombined: */ 1, /*format*/ 0>;
-typealias usampler2DArrayShadow = Sampler2DArrayShadow<uint>;
-typealias isampler2DArrayShadow = Sampler2DArrayShadow<int>;
-typealias sampler2DArrayShadow = Sampler2DArrayShadow<float>;
-
-typealias SamplerCubeArrayShadow<T=float> = __TextureImpl<T, __ShapeCube, /*isArray:*/ 1, /*isMS:*/ 0, /*sampleCount:*/ 0, /*access:*/ 0, /*isShadow: */ 1, /*isCombined: */ 1, /*format*/ 0>;
-typealias usamplerCubeArrayShadow = SamplerCubeArrayShadow<uint>;
-typealias isamplerCubeArrayShadow = SamplerCubeArrayShadow<int>;
-typealias samplerCubeArrayShadow = SamplerCubeArrayShadow<float>;
+public typealias Sampler2DArrayShadow<T=float> = __TextureImpl<T, __Shape2D, /*isArray:*/ 1, /*isMS:*/ 0, /*sampleCount:*/ 0, /*access:*/ 0, /*isShadow: */ 1, /*isCombined: */ 1, /*format*/ 0>;
+public typealias usampler2DArrayShadow = Sampler2DArrayShadow<uint>;
+public typealias isampler2DArrayShadow = Sampler2DArrayShadow<int>;
+public typealias sampler2DArrayShadow = Sampler2DArrayShadow<float>;
+
+public typealias SamplerCubeArrayShadow<T=float> = __TextureImpl<T, __ShapeCube, /*isArray:*/ 1, /*isMS:*/ 0, /*sampleCount:*/ 0, /*access:*/ 0, /*isShadow: */ 1, /*isCombined: */ 1, /*format*/ 0>;
+public typealias usamplerCubeArrayShadow = SamplerCubeArrayShadow<uint>;
+public typealias isamplerCubeArrayShadow = SamplerCubeArrayShadow<int>;
+public typealias samplerCubeArrayShadow = SamplerCubeArrayShadow<float>;
[ForceInline]
-vector<T,4> texelFetch<T:__BuiltinArithmeticType, let N : int> (Sampler1D<vector<T,N>> sampler, int p, int lod)
+public vector<T,4> texelFetch<T:__BuiltinArithmeticType, let N : int> (Sampler1D<vector<T,N>> sampler, int p, int lod)
{
return __vectorReshape<4>(sampler.Load(int2(p, lod)));
}
[ForceInline]
-vector<T,4> texelFetch<T:__BuiltinArithmeticType, let N : int> (Sampler2D<vector<T,N>> sampler, ivec2 p, int lod)
+public vector<T,4> texelFetch<T:__BuiltinArithmeticType, let N : int> (Sampler2D<vector<T,N>> sampler, ivec2 p, int lod)
{
return __vectorReshape<4>(sampler.Load(int3(p, lod)));
}
[ForceInline]
-vector<T,4> texelFetch<T:__BuiltinArithmeticType, let N : int> (Sampler3D<vector<T,N>> sampler, ivec3 p, int lod)
+public vector<T,4> texelFetch<T:__BuiltinArithmeticType, let N : int> (Sampler3D<vector<T,N>> sampler, ivec3 p, int lod)
{
return __vectorReshape<4>(sampler.Load(int4(p, lod)));
}
[ForceInline]
-vector<T,4> texelFetch<T:__BuiltinArithmeticType, let N : int> (Sampler1DArray<vector<T,N>> sampler, ivec2 p, int lod)
+public vector<T,4> texelFetch<T:__BuiltinArithmeticType, let N : int> (Sampler1DArray<vector<T,N>> sampler, ivec2 p, int lod)
{
return __vectorReshape<4>(sampler.Load(int3(p, lod)));
}
[ForceInline]
-vector<T,4> texelFetch<T:__BuiltinArithmeticType, let N : int> (Sampler2DArray<vector<T,N>> sampler, ivec3 p, int lod)
+public vector<T,4> texelFetch<T:__BuiltinArithmeticType, let N : int> (Sampler2DArray<vector<T,N>> sampler, ivec3 p, int lod)
{
return __vectorReshape<4>(sampler.Load(int4(p, lod)));
}
[ForceInline]
-vector<T,4> texture<T:__BuiltinArithmeticType, let N : int> (Sampler1D<vector<T,N>> sampler, float p, float bias = 0.0)
+public vector<T,4> texture<T:__BuiltinArithmeticType, let N : int> (Sampler1D<vector<T,N>> sampler, float p, float bias = 0.0)
{
return __vectorReshape<4>(sampler.SampleBias(p, bias));
}
[ForceInline]
-vector<T,4> texture<T:__BuiltinArithmeticType, let N : int> (Sampler2D<vector<T,N>> sampler, float2 p, float bias = 0.0)
+public vector<T,4> texture<T:__BuiltinArithmeticType, let N : int> (Sampler2D<vector<T,N>> sampler, float2 p, float bias = 0.0)
{
return __vectorReshape<4>(sampler.SampleBias(p, bias));
}
[ForceInline]
-vector<T,4> texture<T:__BuiltinArithmeticType, let N : int> (Sampler3D<vector<T,N>> sampler, float3 p, float bias = 0.0)
+public vector<T,4> texture<T:__BuiltinArithmeticType, let N : int> (Sampler3D<vector<T,N>> sampler, float3 p, float bias = 0.0)
{
return __vectorReshape<4>(sampler.SampleBias(p, bias));
}
[ForceInline]
-vector<T,4> texture<T:__BuiltinArithmeticType, let N : int> (SamplerCube<vector<T,N>> sampler, float3 p, float bias = 0.0)
+public vector<T,4> texture<T:__BuiltinArithmeticType, let N : int> (SamplerCube<vector<T,N>> sampler, float3 p, float bias = 0.0)
{
return __vectorReshape<4>(sampler.SampleBias(p, bias));
}
[ForceInline]
-float texture<T:__BuiltinArithmeticType, let N : int> (Sampler1DShadow<vector<T,N>> sampler, float2 p)
+public float texture<T:__BuiltinArithmeticType, let N : int> (Sampler1DShadow<vector<T,N>> sampler, float2 p)
{
return sampler.SampleCmp(p.x, p.y);
}
[ForceInline]
-float texture<T:__BuiltinArithmeticType, let N : int> (Sampler2DShadow<vector<T,N>> sampler, float3 p)
+public float texture<T:__BuiltinArithmeticType, let N : int> (Sampler2DShadow<vector<T,N>> sampler, float3 p)
{
return sampler.SampleCmp(p.xy, p.z);
}
[ForceInline]
-float texture<T:__BuiltinArithmeticType, let N : int> (SamplerCubeShadow<vector<T,N>> sampler, float4 p)
+public float texture<T:__BuiltinArithmeticType, let N : int> (SamplerCubeShadow<vector<T,N>> sampler, float4 p)
{
return sampler.SampleCmp(p.xyz, p.w);
}
[ForceInline]
-vector<T,4> texture<T:__BuiltinArithmeticType, let N : int> (Sampler1DArray<vector<T,N>> sampler, float2 p, float bias = 0.0)
+public vector<T,4> texture<T:__BuiltinArithmeticType, let N : int> (Sampler1DArray<vector<T,N>> sampler, float2 p, float bias = 0.0)
{
return __vectorReshape<4>(sampler.SampleBias(p, bias));
}
[ForceInline]
-vector<T,4> texture<T:__BuiltinArithmeticType, let N : int> (Sampler2DArray<vector<T,N>> sampler, float3 p, float bias = 0.0)
+public vector<T,4> texture<T:__BuiltinArithmeticType, let N : int> (Sampler2DArray<vector<T,N>> sampler, float3 p, float bias = 0.0)
{
return __vectorReshape<4>(sampler.SampleBias(p, bias));
}
[ForceInline]
-vector<T,4> texture<T:__BuiltinArithmeticType, let N : int> (SamplerCubeArray<vector<T,N>> sampler, float4 p, float bias = 0.0)
+public vector<T,4> texture<T:__BuiltinArithmeticType, let N : int> (SamplerCubeArray<vector<T,N>> sampler, float4 p, float bias = 0.0)
{
return __vectorReshape<4>(sampler.SampleBias(p, bias));
}
[ForceInline]
-float texture<T:__BuiltinArithmeticType, let N : int> (Sampler1DArrayShadow<vector<T,N>> sampler, float3 p)
+public float texture<T:__BuiltinArithmeticType, let N : int> (Sampler1DArrayShadow<vector<T,N>> sampler, float3 p)
{
return sampler.SampleCmp(p.xy, p.z);
}
[ForceInline]
-float texture<T:__BuiltinArithmeticType, let N : int> (Sampler2DArrayShadow<vector<T,N>> sampler, float4 p)
+public float texture<T:__BuiltinArithmeticType, let N : int> (Sampler2DArrayShadow<vector<T,N>> sampler, float4 p)
{
return sampler.SampleCmp(p.xyz, p.w);
}
__generic<T:__BuiltinArithmeticType, let N : int, shape:__ITextureShape, let sampleCount: int, let isArray:int, let format:int>
-vector<T,4> textureGrad(__TextureImpl<vector<T,N>, shape, isArray, 0, sampleCount, 0, 1, 1, format> sampler, vector<float, shape.dimensions+isArray> P, vector<float,shape.planeDimensions> dPdx, vector<float,shape.planeDimensions> dPdy)
+public vector<T,4> textureGrad(__TextureImpl<vector<T,N>, shape, isArray, 0, sampleCount, 0, 1, 1, format> sampler, vector<float, shape.dimensions+isArray> P, vector<float,shape.planeDimensions> dPdx, vector<float,shape.planeDimensions> dPdy)
{
return __vectorReshape<4>(sampler.SampleGrad(P, dPdx, dPdy));
}
-out float4 gl_Position : SV_Position;
-out float gl_PointSize : SV_PointSize;
-in vec4 gl_FragCoord : SV_Position;
-out float gl_FragDepth : SV_Depth;
-out int gl_FragStencilRef : SV_StencilRef;
+public out float4 gl_Position : SV_Position;
+public out float gl_PointSize : SV_PointSize;
+public in vec4 gl_FragCoord : SV_Position;
+public out float gl_FragDepth : SV_Depth;
+public out int gl_FragStencilRef : SV_StencilRef;
-in uvec3 gl_GlobalInvocationID : SV_DispatchThreadID;
-in uvec3 gl_WorkGroupID : SV_GroupID;
-in uvec3 gl_LocalInvocationIndex : SV_GroupIndex;
-in uvec3 gl_LocalInvocationID : SV_GroupThreadID;
+public in uvec3 gl_GlobalInvocationID : SV_DispatchThreadID;
+public in uvec3 gl_WorkGroupID : SV_GroupID;
+public in uvec3 gl_LocalInvocationIndex : SV_GroupIndex;
+public in uvec3 gl_LocalInvocationID : SV_GroupThreadID;
// TODO: define overload for tessellation control stage.
-in int gl_InvocationID : SV_GSInstanceID;
+public in int gl_InvocationID : SV_GSInstanceID;
-in int gl_InstanceIndex : SV_InstanceID;
-in bool gl_FrontFacing : SV_IsFrontFace;
+public in int gl_InstanceIndex : SV_InstanceID;
+public in bool gl_FrontFacing : SV_IsFrontFace;
// TODO: define overload for geometry stage.
-in int gl_Layer : SV_RenderTargetArrayIndex;
+public in int gl_Layer : SV_RenderTargetArrayIndex;
-in int gl_SampleID : SV_SampleIndex;
-in int gl_VertexIndex : SV_VertexID;
-in int gl_ViewIndex : SV_ViewID;
-in int gl_ViewportIndex : SV_ViewportArrayIndex;
+public in int gl_SampleID : SV_SampleIndex;
+public in int gl_VertexIndex : SV_VertexID;
+public in int gl_ViewIndex : SV_ViewID;
+public in int gl_ViewportIndex : SV_ViewportArrayIndex;
// Override operator* behavior to compute algebric product of matrices and vectors.
[OverloadRank(15)]
[ForceInline]
-matrix<float, N, N> operator*<let N : int>(matrix<float, N, N> m1, matrix<float, N, N> m2)
+public matrix<float, N, N> operator*<let N : int>(matrix<float, N, N> m1, matrix<float, N, N> m2)
{
return mul(m2, m1);
}
[OverloadRank(15)]
[ForceInline]
-matrix<half, N, N> operator*<let N : int>(matrix<half, N, N> m1, matrix<half, N, N> m2)
+public matrix<half, N, N> operator*<let N : int>(matrix<half, N, N> m1, matrix<half, N, N> m2)
{
return mul(m2, m1);
}
[OverloadRank(15)]
[ForceInline]
-matrix<double, N, N> operator*<let N : int>(matrix<double, N, N> m1, matrix<double, N, N> m2)
+public matrix<double, N, N> operator*<let N : int>(matrix<double, N, N> m1, matrix<double, N, N> m2)
{
return mul(m2, m1);
}
[ForceInline]
[OverloadRank(15)]
-matrix<T, R, L> operator*<T:__BuiltinFloatingPointType, let L : int, let C : int, let R : int>(matrix<T, C, L> m1, matrix<T, R, C> m2)
+public matrix<T, R, L> operator*<T:__BuiltinFloatingPointType, let L : int, let C : int, let R : int>(matrix<T, C, L> m1, matrix<T, R, C> m2)
{
return mul(m2, m1);
}
[ForceInline]
[OverloadRank(15)]
-vector<T, R> operator*<T:__BuiltinFloatingPointType, let C : int, let R : int>(vector<T, C> v, matrix<T, R, C> m)
+public vector<T, R> operator*<T:__BuiltinFloatingPointType, let C : int, let R : int>(vector<T, C> v, matrix<T, R, C> m)
{
return mul(m, v);
}
[ForceInline]
[OverloadRank(15)]
-vector<T, C> operator*<T:__BuiltinFloatingPointType, let C : int, let R : int>(matrix<T, R, C> m, vector<T, R> v)
+public vector<T, C> operator*<T:__BuiltinFloatingPointType, let C : int, let R : int>(matrix<T, R, C> m, vector<T, R> v)
{
return mul(v, m);
}
__intrinsic_op(mul)
-matrix<T, N, M> matrixCompMult<T:__BuiltinFloatingPointType, let N : int, let M : int>(matrix<T,N,M> left, matrix<T,N,M> right);
+public matrix<T, N, M> matrixCompMult<T:__BuiltinFloatingPointType, let N : int, let M : int>(matrix<T,N,M> left, matrix<T,N,M> right);
__intrinsic_op(cmpLE)
-vector<bool, N> lessThanEqual<T, let N:int>(vector<T, N> x, vector<T, N> y);
+public vector<bool, N> lessThanEqual<T, let N:int>(vector<T, N> x, vector<T, N> y);
__intrinsic_op(cmpLT)
-vector<bool, N> lessThan<T, let N:int>(vector<T, N> x, vector<T, N> y);
+public vector<bool, N> lessThan<T, let N:int>(vector<T, N> x, vector<T, N> y);
__intrinsic_op(cmpGT)
-vector<bool, N> greaterThan<T, let N:int>(vector<T, N> x, vector<T, N> y);
+public vector<bool, N> greaterThan<T, let N:int>(vector<T, N> x, vector<T, N> y);
__intrinsic_op(cmpGE)
-vector<bool, N> greaterThanEqual<T, let N:int>(vector<T, N> x, vector<T, N> y);
+public vector<bool, N> greaterThanEqual<T, let N:int>(vector<T, N> x, vector<T, N> y);
__intrinsic_op(cmpEQ)
-vector<bool, N> equal<T, let N:int>(vector<T, N> x, vector<T, N> y);
+public vector<bool, N> equal<T, let N:int>(vector<T, N> x, vector<T, N> y);
__intrinsic_op(cmpNE)
-vector<bool, N> notEqual<T, let N:int>(vector<T, N> x, vector<T, N> y);
+public vector<bool, N> notEqual<T, let N:int>(vector<T, N> x, vector<T, N> y);
__generic<T>
-extension vector<T, 2>
+public extension vector<T, 2>
{
- [ForceInline] __init(vector<T, 3> bigger) { this = bigger.xy; }
- [ForceInline] __init(vector<T, 4> bigger) { this = bigger.xy; }
+ [ForceInline] public __init(vector<T, 3> bigger) { this = bigger.xy; }
+ [ForceInline] public __init(vector<T, 4> bigger) { this = bigger.xy; }
}
__generic<T>
-extension vector<T, 3>
+public extension vector<T, 3>
{
- [ForceInline] __init(vector<T, 4> bigger) { this = bigger.xyz; }
+ [ForceInline] public __init(vector<T, 4> bigger) { this = bigger.xyz; }
}
[ForceInline]
[OverloadRank(15)]
-bool operator==<T:__BuiltinArithmeticType, let N : int>(vector<T, N> left, vector<T, N> right)
+public bool operator==<T:__BuiltinArithmeticType, let N : int>(vector<T, N> left, vector<T, N> right)
{
return all(equal(left, right));
}
[ForceInline]
[OverloadRank(15)]
-bool operator!=<T:__BuiltinArithmeticType, let N : int>(vector<T, N> left, vector<T, N> right)
+public bool operator!=<T:__BuiltinArithmeticType, let N : int>(vector<T, N> left, vector<T, N> right)
{
return any(notEqual(left, right));
}
[ForceInline]
[OverloadRank(14)]
-bool operator==<T:__BuiltinFloatingPointType, let N : int>(vector<T, N> left, vector<T, N> right)
+public bool operator==<T:__BuiltinFloatingPointType, let N : int>(vector<T, N> left, vector<T, N> right)
{
return all(equal(left, right));
}
[ForceInline]
[OverloadRank(14)]
-bool operator!=<T:__BuiltinFloatingPointType, let N : int>(vector<T, N> left, vector<T, N> right)
+public bool operator!=<T:__BuiltinFloatingPointType, let N : int>(vector<T, N> left, vector<T, N> right)
{
return any(notEqual(left, right));
}
[ForceInline]
[OverloadRank(14)]
-bool operator==<T:__BuiltinLogicalType, let N : int>(vector<T, N> left, vector<T, N> right)
+public bool operator==<T:__BuiltinLogicalType, let N : int>(vector<T, N> left, vector<T, N> right)
{
return all(equal(left, right));
}
[ForceInline]
[OverloadRank(14)]
-bool operator!=<T:__BuiltinLogicalType, let N : int>(vector<T, N> left, vector<T, N> right)
+public bool operator!=<T:__BuiltinLogicalType, let N : int>(vector<T, N> left, vector<T, N> right)
{
return any(notEqual(left, right));
}
@@ -392,14 +392,14 @@ for (auto type : kBaseTypes) {
}}}}
[ForceInline]
[OverloadRank(15)]
-bool operator==<let N : int>(vector<$(typeName), N> left, vector<$(typeName), N> right)
+public bool operator==<let N : int>(vector<$(typeName), N> left, vector<$(typeName), N> right)
{
return all(equal(left, right));
}
[ForceInline]
[OverloadRank(15)]
-bool operator!=<let N : int>(vector<$(typeName), N> left, vector<$(typeName), N> right)
+public bool operator!=<let N : int>(vector<$(typeName), N> left, vector<$(typeName), N> right)
{
return any(notEqual(left, right));
}
@@ -407,13 +407,13 @@ ${{{{
}
}}}}
-[ForceInline] int findLSB(int v) { return firstbitlow(v); }
-[ForceInline] uint findLSB(uint v) { return firstbitlow(v); }
-[ForceInline] vector<int,N> findLSB<let N:int>(vector<int,N> value)
+[ForceInline] public int findLSB(int v) { return firstbitlow(v); }
+[ForceInline] public uint findLSB(uint v) { return firstbitlow(v); }
+[ForceInline] public vector<int,N> findLSB<let N:int>(vector<int,N> value)
{
return firstbitlow(value);
}
-[ForceInline] vector<uint,N> findLSB<let N:int>(vector<uint,N> value)
+[ForceInline] public vector<uint,N> findLSB<let N:int>(vector<uint,N> value)
{
return firstbitlow(value);
}
diff --git a/source/slang/slang-ast-decl.h b/source/slang/slang-ast-decl.h
index ddff39502..ab4fbaf17 100644
--- a/source/slang/slang-ast-decl.h
+++ b/source/slang/slang-ast-decl.h
@@ -426,6 +426,15 @@ class ModuleDecl : public NamespaceDeclBase
///
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.
+ bool isInLegacyLanguage = true;
+
SLANG_UNREFLECTED
/// Map a type to the list of extensions of that type (if any) declared in this module
diff --git a/source/slang/slang-ast-modifier.h b/source/slang/slang-ast-modifier.h
index 9ee3fea86..ae87c4e10 100644
--- a/source/slang/slang-ast-modifier.h
+++ b/source/slang/slang-ast-modifier.h
@@ -16,7 +16,10 @@ class ConstModifier : public Modifier { SLANG_AST_CLASS(ConstModifier)};
class InstanceModifier : public Modifier { SLANG_AST_CLASS(InstanceModifier)};
class BuiltinModifier : public Modifier { SLANG_AST_CLASS(BuiltinModifier)};
class InlineModifier : public Modifier { SLANG_AST_CLASS(InlineModifier)};
-class PublicModifier : public Modifier { SLANG_AST_CLASS(PublicModifier)};
+class VisibilityModifier : public Modifier {SLANG_AST_CLASS(VisibilityModifier)};
+class PublicModifier : public VisibilityModifier { SLANG_AST_CLASS(PublicModifier)};
+class PrivateModifier : public VisibilityModifier { SLANG_AST_CLASS(PrivateModifier) };
+class InternalModifier : public VisibilityModifier { SLANG_AST_CLASS(InternalModifier) };
class RequireModifier : public Modifier { SLANG_AST_CLASS(RequireModifier)};
class ParamModifier : public Modifier { SLANG_AST_CLASS(ParamModifier)};
class ExternModifier : public Modifier { SLANG_AST_CLASS(ExternModifier)};
diff --git a/source/slang/slang-ast-support-types.h b/source/slang/slang-ast-support-types.h
index 5da19f377..1e71d0c4a 100644
--- a/source/slang/slang-ast-support-types.h
+++ b/source/slang/slang-ast-support-types.h
@@ -1598,7 +1598,13 @@ namespace Slang
/// Get the operator name from the higher order invoke expr.
UnownedStringSlice getHigherOrderOperatorName(HigherOrderInvokeExpr* expr);
-
+ enum class DeclVisibility
+ {
+ Private,
+ Internal,
+ Public,
+ Default = Internal,
+ };
} // namespace Slang
#endif
diff --git a/source/slang/slang-check-conversion.cpp b/source/slang/slang-check-conversion.cpp
index c2cfabcfe..d76b2a80e 100644
--- a/source/slang/slang-check-conversion.cpp
+++ b/source/slang/slang-check-conversion.cpp
@@ -1063,7 +1063,7 @@ namespace Slang
overloadContext.argCount = 1;
overloadContext.argTypes = &fromType.type;
overloadContext.args = &fromExpr;
-
+ overloadContext.sourceScope = m_outerScope;
overloadContext.originalExpr = nullptr;
if(fromExpr)
{
diff --git a/source/slang/slang-check-decl.cpp b/source/slang/slang-check-decl.cpp
index b4cc6c00a..671bb26dd 100644
--- a/source/slang/slang-check-decl.cpp
+++ b/source/slang/slang-check-decl.cpp
@@ -298,7 +298,9 @@ namespace Slang
{
// Things at the global scope are always "members" of their module.
//
- if(as<ModuleDecl>(parentDecl))
+ if(as<NamespaceDeclBase>(parentDecl))
+ return false;
+ if (as<FileDecl>(parentDecl))
return false;
// Anything explicitly marked `static` and not at module scope
@@ -373,7 +375,7 @@ namespace Slang
auto parentDecl = decl->parentDecl;
if (auto genericDecl = as<GenericDecl>(parentDecl))
parentDecl = genericDecl->parentDecl;
- return as<NamespaceDeclBase>(parentDecl) != nullptr;
+ return as<NamespaceDeclBase>(parentDecl) != nullptr || as<FileDecl>(parentDecl) != nullptr;
}
/// Is `decl` a global shader parameter declaration?
@@ -385,7 +387,7 @@ namespace Slang
// A global shader parameter must be declared at global or namespace
// scope, so that it has a single definition across the module.
//
- if(!as<NamespaceDeclBase>(decl->parentDecl)) return false;
+ if(!isGlobalDecl(decl)) return false;
// A global variable marked `static` indicates a traditional
// global variable (albeit one that is implicitly local to
@@ -733,6 +735,7 @@ namespace Slang
// The coding of this loop is somewhat defensive to deal
// with special cases that will be described along the way.
//
+ auto outerScope = getScope(decl);
for(;;)
{
// The first thing is to check what state the decl is
@@ -757,6 +760,8 @@ namespace Slang
// cannot affect the state in which the declaration is *checked*.
//
SemanticsContext subContext = baseContext ? SemanticsContext(*baseContext) : SemanticsContext(getShared());
+ if (outerScope)
+ subContext = subContext.withOuterScope(outerScope);
_dispatchDeclCheckingVisitor(decl, nextState, subContext);
// In the common case, the visitor will have done the necessary
@@ -1245,6 +1250,8 @@ namespace Slang
}
}
}
+
+ checkVisibility(varDecl);
}
void SemanticsDeclHeaderVisitor::visitStructDecl(StructDecl* structDecl)
@@ -1261,11 +1268,12 @@ namespace Slang
{
addModifier(structDecl, m_astBuilder->create<NVAPIMagicModifier>());
}
+ checkVisibility(structDecl);
}
void SemanticsDeclHeaderVisitor::visitClassDecl(ClassDecl* classDecl)
{
- SLANG_UNUSED(classDecl);
+ checkVisibility(classDecl);
}
void SemanticsDeclBodyVisitor::checkVarDeclCommon(VarDeclBase* varDecl)
@@ -1313,6 +1321,7 @@ namespace Slang
OverloadResolveContext overloadContext;
overloadContext.loc = varDecl->nameAndLoc.loc;
overloadContext.mode = OverloadResolveContext::Mode::JustTrying;
+ overloadContext.sourceScope = m_outerScope;
AddTypeOverloadCandidates(type, overloadContext);
if(overloadContext.bestCandidates.getCount() != 0)
@@ -1368,6 +1377,24 @@ namespace Slang
}
}
+ void addVisibilityModifier(ASTBuilder* builder, Decl* decl, DeclVisibility vis)
+ {
+ switch (vis)
+ {
+ case DeclVisibility::Public:
+ addModifier(decl, builder->create<PublicModifier>());
+ break;
+ case DeclVisibility::Internal:
+ addModifier(decl, builder->create<InternalModifier>());
+ break;
+ case DeclVisibility::Private:
+ addModifier(decl, builder->create<PrivateModifier>());
+ break;
+ default:
+ break;
+ }
+ }
+
bool SemanticsVisitor::trySynthesizeDifferentialAssociatedTypeRequirementWitness(
ConformanceCheckingContext* context,
DeclRef<AssocTypeDecl> requirementDeclRef,
@@ -1434,6 +1461,10 @@ namespace Slang
diffField->checkState = DeclCheckState::SignatureChecked;
diffField->parentDecl = aggTypeDecl;
aggTypeDecl->members.add(diffField);
+
+ auto visibility = getDeclVisibility(member);
+ addVisibilityModifier(m_astBuilder, diffField, visibility);
+
aggTypeDecl->invalidateMemberDictionary();
// Inject a `DerivativeMember` modifier on the differential field to point to itself.
@@ -1539,6 +1570,15 @@ namespace Slang
addModifier(aggTypeDecl, m_astBuilder->create<SynthesizedModifier>());
+ // The visibility of synthesized decl should be the min of the parent decl and the requirement.
+ if (auto visModifier = requirementDeclRef.getDecl()->findModifier<VisibilityModifier>())
+ {
+ auto requirementVisibility = getDeclVisibility(requirementDeclRef.getDecl());
+ auto thisVisibility = getDeclVisibility(context->parentDecl);
+ auto visibility = Math::Min(thisVisibility, requirementVisibility);
+ addVisibilityModifier(m_astBuilder, aggTypeDecl, visibility);
+ }
+
// Synthesize the rest of IDifferential method conformances by recursively checking
// conformance on the synthesized decl.
checkAggTypeConformance(aggTypeDecl);
@@ -1890,6 +1930,7 @@ namespace Slang
DeclCheckState::ModifiersChecked,
DeclCheckState::ReadyForReference,
DeclCheckState::ReadyForLookup,
+ DeclCheckState::ReadyForConformances,
DeclCheckState::Checked
};
for(auto s : states)
@@ -2810,6 +2851,7 @@ namespace Slang
{
synFuncDecl->nameAndLoc.name = getSession()->getNameObj("$__syn_" + synFuncDecl->nameAndLoc.name->text);
}
+
// The result type of our synthesized method will be the expected
// result type from the interface requirement.
//
@@ -2933,6 +2975,14 @@ namespace Slang
auto attr = m_astBuilder->create<BackwardDifferentiableAttribute>();
addModifier(synFuncDecl, attr);
}
+ // The visibility of synthesized decl should be the min of the parent decl and the requirement.
+ if (auto visModifier = requiredMemberDeclRef.getDecl()->findModifier<VisibilityModifier>())
+ {
+ auto requirementVisibility = getDeclVisibility(requiredMemberDeclRef.getDecl());
+ auto thisVisibility = getDeclVisibility(context->parentDecl);
+ auto visibility = Math::Min(thisVisibility, requirementVisibility);
+ addVisibilityModifier(m_astBuilder, synFuncDecl, visibility);
+ }
}
return synFuncDecl;
@@ -3471,6 +3521,15 @@ namespace Slang
synPropertyDecl->parentDecl = context->parentDecl;
+ // The visibility of synthesized decl should be the min of the parent decl and the requirement.
+ if (auto visModifier = requiredMemberDeclRef.getDecl()->findModifier<VisibilityModifier>())
+ {
+ auto requirementVisibility = getDeclVisibility(requiredMemberDeclRef.getDecl());
+ auto thisVisibility = getDeclVisibility(context->parentDecl);
+ auto visibility = Math::Min(thisVisibility, requirementVisibility);
+ addVisibilityModifier(m_astBuilder, synPropertyDecl, visibility);
+ }
+
// Once our synthesized declaration is complete, we need
// to install it as the witness that satifies the given
// requirement.
@@ -3969,7 +4028,7 @@ namespace Slang
// requests will be handled further down. For now we include
// lookup results that might be usable, but not as-is.
//
- auto lookupResult = lookUpMember(m_astBuilder, this, name, subType, LookupMask::Default, LookupOptions::IgnoreBaseInterfaces);
+ auto lookupResult = lookUpMember(m_astBuilder, this, name, subType, nullptr, LookupMask::Default, LookupOptions::IgnoreBaseInterfaces);
if(!lookupResult.isValid())
{
@@ -4502,6 +4561,8 @@ namespace Slang
void SemanticsDeclBasesVisitor::visitInterfaceDecl(InterfaceDecl* decl)
{
+ SLANG_OUTER_SCOPE_CONTEXT_DECL_RAII(this, decl);
+ checkVisibility(decl);
for( auto inheritanceDecl : decl->getMembersOfType<InheritanceDecl>() )
{
ensureDecl(inheritanceDecl, DeclCheckState::CanUseBaseOfInheritanceDecl);
@@ -4567,6 +4628,8 @@ namespace Slang
// Furthermore, only the first inheritance clause (in source
// order) is allowed to declare a base `struct` type.
//
+ SLANG_OUTER_SCOPE_CONTEXT_DECL_RAII(this, decl);
+
Index inheritanceClauseCounter = 0;
for( auto inheritanceDecl : decl->getMembersOfType<InheritanceDecl>() )
{
@@ -4636,6 +4699,7 @@ namespace Slang
// Furthermore, only the first inheritance clause (in source
// order) is allowed to declare a base `class` type.
//
+ SLANG_OUTER_SCOPE_CONTEXT_DECL_RAII(this, decl);
Index inheritanceClauseCounter = 0;
for (auto inheritanceDecl : decl->getMembersOfType<InheritanceDecl>())
{
@@ -4768,6 +4832,9 @@ namespace Slang
void SemanticsDeclBasesVisitor::visitEnumDecl(EnumDecl* decl)
{
+ SLANG_OUTER_SCOPE_CONTEXT_DECL_RAII(this, decl);
+ checkVisibility(decl);
+
// An `enum` type can inherit from interfaces, and also
// from a single "tag" type that must:
//
@@ -4775,7 +4842,6 @@ namespace Slang
// * come first in the list of base types
//
Index inheritanceClauseCounter = 0;
-
Type* tagType = nullptr;
InheritanceDecl* tagTypeInheritanceDecl = nullptr;
for(auto inheritanceDecl : decl->getMembersOfType<InheritanceDecl>())
@@ -4938,6 +5004,8 @@ namespace Slang
void SemanticsDeclBodyVisitor::visitEnumDecl(EnumDecl* decl)
{
+ SLANG_OUTER_SCOPE_CONTEXT_DECL_RAII(this, decl);
+
auto enumType = DeclRefType::create(m_astBuilder, makeDeclRef(decl));
auto tagType = decl->tagType;
@@ -5063,6 +5131,7 @@ namespace Slang
void SemanticsDeclHeaderVisitor::visitTypeDefDecl(TypeDefDecl* decl)
{
decl->type = CheckProperType(decl->type);
+ checkVisibility(decl);
}
void SemanticsDeclHeaderVisitor::visitGlobalGenericParamDecl(GlobalGenericParamDecl* decl)
@@ -5079,6 +5148,7 @@ namespace Slang
auto interfaceDecl = as<InterfaceDecl>(decl->parentDecl);
if (!interfaceDecl)
getSink()->diagnose(decl, Slang::Diagnostics::assocTypeInInterfaceOnly);
+ checkVisibility(decl);
}
void SemanticsDeclBodyVisitor::visitFunctionDeclBase(FunctionDeclBase* decl)
@@ -6154,6 +6224,7 @@ namespace Slang
}
}
}
+ checkVisibility(decl);
}
void SemanticsDeclHeaderVisitor::visitFuncDecl(FuncDecl* funcDecl)
@@ -6464,6 +6535,7 @@ namespace Slang
{
decl->type = CheckUsableType(decl->type);
visitAbstractStorageDeclCommon(decl);
+ checkVisibility(decl);
}
Type* SemanticsDeclHeaderVisitor::_getAccessorStorageType(AccessorDecl* decl)
@@ -6768,13 +6840,19 @@ namespace Slang
importedModulesList.add(moduleDecl);
importedModulesSet.add(moduleDecl);
- // Create a new sub-scope to wire the module
+ // Create a new sub-scope to wire the module's scope and its nested FileDecl's scopes
// into our lookup chain.
- auto subScope = getASTBuilder()->create<Scope>();
- subScope->containerDecl = moduleDecl;
+ for (auto moduleScope = moduleDecl->ownedScope; moduleScope; moduleScope = moduleScope->nextSibling)
+ {
+ if (moduleScope->containerDecl != moduleDecl && moduleScope->containerDecl->parentDecl != moduleDecl)
+ continue;
- subScope->nextSibling = scope->nextSibling;
- scope->nextSibling = subScope;
+ auto subScope = getASTBuilder()->create<Scope>();
+ subScope->containerDecl = moduleScope->containerDecl;
+
+ subScope->nextSibling = scope->nextSibling;
+ scope->nextSibling = subScope;
+ }
// Also import any modules from nested `import` declarations
// with the `__exported` modifier
diff --git a/source/slang/slang-check-expr.cpp b/source/slang/slang-check-expr.cpp
index 7edf27b30..dd868f70c 100644
--- a/source/slang/slang-check-expr.cpp
+++ b/source/slang/slang-check-expr.cpp
@@ -225,6 +225,20 @@ namespace Slang
return expr;
}
+ Scope* SemanticsVisitor::getScope(SyntaxNode* node)
+ {
+ while (auto declBase = as<Decl>(node))
+ {
+ if (auto container = as<ContainerDecl>(node))
+ {
+ if (container->ownedScope)
+ return container->ownedScope;
+ }
+ node = declBase->parentDecl;
+ }
+ return nullptr;
+ }
+
static SourceLoc _getMemberOpLoc(Expr* expr)
{
if (auto m = as<MemberExpr>(expr))
@@ -794,6 +808,121 @@ namespace Slang
}
}
+ DeclVisibility SemanticsVisitor::getDeclVisibility(Decl* decl)
+ {
+ if (as<GenericTypeParamDecl>(decl) || as<GenericValueParamDecl>(decl) || as<GenericTypeConstraintDecl>(decl))
+ {
+ auto genericDecl = as<GenericDecl>(decl->parentDecl);
+ if (!genericDecl)
+ return DeclVisibility::Default;
+ if (genericDecl->inner)
+ return getDeclVisibility(genericDecl->inner);
+ return DeclVisibility::Default;
+ }
+ if (auto genericDecl = as<GenericDecl>(decl))
+ decl = genericDecl->inner;
+ for (; decl; decl = getParentDecl(decl))
+ {
+ if (as<AccessorDecl>(decl))
+ continue;
+ if (as<EnumCaseDecl>(decl))
+ continue;
+ break;
+ }
+ if (!decl)
+ return DeclVisibility::Public;
+
+ for (auto modifier : decl->modifiers)
+ {
+ if (as<PublicModifier>(modifier))
+ return DeclVisibility::Public;
+ else if (as<InternalModifier>(modifier))
+ return DeclVisibility::Internal;
+ else if (as<PrivateModifier>(modifier))
+ return DeclVisibility::Private;
+ }
+
+ if (auto parentModule = getModuleDecl(decl))
+ return parentModule->isInLegacyLanguage ? DeclVisibility::Public : DeclVisibility::Internal;
+
+ return DeclVisibility::Default;
+ }
+
+ DeclVisibility SemanticsVisitor::getTypeVisibility(Type* type)
+ {
+ if (auto declRefType = as<DeclRefType>(type))
+ {
+ auto v = getDeclVisibility(declRefType->getDeclRef().getDecl());
+ auto args = findInnerMostGenericArgs(SubstitutionSet(declRefType->getDeclRef()));
+ for (auto arg : args)
+ {
+ if (auto typeArg = as<DeclRefType>(arg))
+ v = Math::Min(v, getTypeVisibility(typeArg));
+ }
+ return v;
+ }
+ return DeclVisibility::Public;
+ }
+
+ bool SemanticsVisitor::isDeclVisibleFromScope(DeclRef<Decl> declRef, Scope* scope)
+ {
+ auto visibility = getDeclVisibility(declRef.getDecl());
+ if (visibility == DeclVisibility::Public)
+ return true;
+ if (visibility == DeclVisibility::Internal)
+ {
+ // Check that the decl is in the same module as the scope.
+ auto declModule = getModuleDecl(declRef.getDecl());
+ if (declModule == getModuleDecl(scope))
+ return true;
+ }
+ if (visibility == DeclVisibility::Private)
+ {
+ // Check that the decl is in the same or parent container decl as scope.
+ Decl* parentContainer = declRef.getDecl();
+ for (;parentContainer; parentContainer = parentContainer->parentDecl)
+ {
+ if (as<AggTypeDeclBase>(parentContainer))
+ break;
+ if (as<NamespaceDeclBase>(parentContainer))
+ break;
+ }
+
+ for (auto s = scope; s; s = s->parent)
+ {
+ if (s->containerDecl == parentContainer)
+ return true;
+ }
+ return false;
+ }
+ return false;
+ }
+
+ LookupResult SemanticsVisitor::filterLookupResultByVisibility(const LookupResult& lookupResult)
+ {
+ if (!m_outerScope)
+ return lookupResult;
+ LookupResult filteredResult;
+ for (auto item : lookupResult)
+ {
+ if (isDeclVisibleFromScope(item.declRef, m_outerScope))
+ AddToLookupResult(filteredResult, item);
+ }
+ return filteredResult;
+ }
+
+ LookupResult SemanticsVisitor::filterLookupResultByVisibilityAndDiagnose(const LookupResult& lookupResult, SourceLoc loc, bool& outDiagnosed)
+ {
+ outDiagnosed = false;
+ auto result = filterLookupResultByVisibility(lookupResult);
+ if (lookupResult.isValid() && !result.isValid())
+ {
+ getSink()->diagnose(loc, Diagnostics::declIsNotVisible, lookupResult.item.declRef);
+ outDiagnosed = true;
+ }
+ return result;
+ }
+
LookupResult SemanticsVisitor::resolveOverloadedLookup(LookupResult const& inResult)
{
// If the result isn't actually overloaded, it is fine as-is
@@ -987,6 +1116,7 @@ namespace Slang
this,
getName("Differential"),
type,
+ nullptr,
Slang::LookupMask::type,
Slang::LookupOptions::None);
@@ -1141,7 +1271,7 @@ namespace Slang
// a scope in place. If we do, we will re-use it for any sub-expressions.
// If not, we need to create one.
//
- if(getExprLocalScope())
+ if (getExprLocalScope())
{
return dispatchExpr(term, *this);
}
@@ -1860,11 +1990,15 @@ namespace Slang
this,
operatorName,
baseType,
+ m_outerScope,
LookupMask::Default,
LookupOptions::NoDeref);
+ bool diagnosed = false;
+ lookupResult = filterLookupResultByVisibilityAndDiagnose(lookupResult, subscriptExpr->loc, diagnosed);
if (!lookupResult.isValid())
{
- getSink()->diagnose(subscriptExpr, Diagnostics::subscriptNonArray, baseType);
+ if (!diagnosed)
+ getSink()->diagnose(subscriptExpr, Diagnostics::subscriptNonArray, baseType);
return CreateErrorExpr(subscriptExpr);
}
auto subscriptFuncExpr = createLookupResultExpr(
@@ -2333,6 +2467,9 @@ namespace Slang
auto lookupResult = lookUp(
m_astBuilder,
this, expr->name, expr->scope);
+
+ bool diagnosed = false;
+ lookupResult = filterLookupResultByVisibilityAndDiagnose(lookupResult, expr->loc, diagnosed);
if (expr->name == getSession()->getCompletionRequestTokenName())
{
@@ -2353,7 +2490,8 @@ namespace Slang
expr);
}
- getSink()->diagnose(expr, Diagnostics::undefinedIdentifier2, expr->name);
+ if (!diagnosed)
+ getSink()->diagnose(expr, Diagnostics::undefinedIdentifier2, expr->name);
return expr;
}
@@ -3387,161 +3525,183 @@ namespace Slang
Expr* SemanticsVisitor::_lookupStaticMember(DeclRefExpr* expr, Expr* baseExpression)
{
- auto& baseType = baseExpression->type;
+ LookupResult globalLookupResult;
+ bool hasErrors = false;
+ Expr* base = nullptr;
+ auto handleLeafCase = [&](DeclRef<Decl> baseDeclRef, Type* type)
+ {
+ auto aggTypeDeclRef = as<AggTypeDeclBase>(baseDeclRef);
- // TODO: Need to handle overloaded case (in case we
- // have multiple visible types and/or namespaces
- // with the same name).
+ if (auto namespaceDeclRef = as<NamespaceDeclBase>(baseDeclRef))
+ {
+ // We are looking up a namespace member.
+ //
+ // This ought to be the easy case, because
+ // there are no restrictions on whether
+ // we can reference the declaration here.
+ //
+ LookupResult nsLookupResult = lookUpDirectAndTransparentMembers(
+ m_astBuilder,
+ this,
+ expr->name,
+ namespaceDeclRef.getDecl(),
+ namespaceDeclRef);
+ AddToLookupResult(globalLookupResult, nsLookupResult);
- if (auto namespaceType = as<NamespaceType>(baseType))
- {
- // We are looking up a namespace member.
- //
- auto namespaceDeclRef = namespaceType->getDeclRef();
+ }
+ else if (aggTypeDeclRef || type)
+ {
+ // We are looking up a member inside a type.
+ // We want to be careful here because we should only find members
+ // that are implicitly or explicitly `static`.
+ //
+ if (type == nullptr)
+ type = DeclRefType::create(m_astBuilder, aggTypeDeclRef);
- // This ought to be the easy case, because
- // there are no restrictions on whether
- // we can reference the declaration here.
- //
- LookupResult lookupResult = lookUpDirectAndTransparentMembers(
- m_astBuilder,
- this,
- expr->name,
- namespaceDeclRef.getDecl(),
- namespaceDeclRef);
- if (!lookupResult.isValid())
- {
- return lookupMemberResultFailure(expr, baseType);
- }
+ if (as<ErrorType>(type))
+ {
+ return;
+ }
- if (expr->name == getSession()->getCompletionRequestTokenName())
- {
- suggestCompletionItems(CompletionSuggestions::ScopeKind::Member, lookupResult);
- }
- return createLookupResultExpr(
- expr->name,
- lookupResult,
- nullptr,
- expr->loc,
- expr);
- }
- else if (auto typeType = as<TypeType>(baseType))
- {
- // We are looking up a member inside a type.
- // We want to be careful here because we should only find members
- // that are implicitly or explicitly `static`.
- //
- // TODO: this duplicates a *lot* of logic with the case below.
- // We need to fix that.
- auto type = typeType->getType();
+ LookupResult lookupResult = lookUpMember(
+ m_astBuilder,
+ this,
+ expr->name,
+ type,
+ m_outerScope);
- if (as<ErrorType>(type))
- {
- return CreateErrorExpr(expr);
- }
+ // We need to confirm that whatever member we
+ // are trying to refer to is usable via static reference.
+ //
+ // TODO: eventually we might allow a non-static
+ // member to be adapted by turning it into something
+ // like a closure that takes the missing `this` parameter.
+ //
+ // E.g., a static reference to a method could be treated
+ // as a value with a function type, where the first parameter
+ // is `type`.
+ //
+ // The biggest challenge there is that we'd need to arrange
+ // to generate "dispatcher" functions that could be used
+ // to implement that function, in the case where we are
+ // making a static reference to some kind of polymorphic declaration.
+ //
+ // (Also, static references to fields/properties would get even
+ // harder, because you'd have to know whether a getter/setter/ref-er
+ // is needed).
+ //
+ // For now let's just be expedient and disallow all of that, because
+ // we can always add it back in later.
- LookupResult lookupResult = lookUpMember(
- m_astBuilder,
- this,
- expr->name,
- type);
- if (!lookupResult.isValid())
- {
- return lookupMemberResultFailure(expr, baseType);
- }
+ // If the lookup result is valid, then we want to filter
+ // it to just those candidates that can be referenced statically,
+ // and ignore any that would only be allowed as instance members.
+ //
+ if (lookupResult.isValid())
+ {
+ // We track both the usable items, and whether or
+ // not there were any non-static items that need
+ // to be ignored.
+ //
+ bool anyNonStatic = false;
+ List<LookupResultItem> staticItems;
+ for (auto item : lookupResult)
+ {
+ // Is this item usable as a static member?
+ if (isUsableAsStaticMember(item))
+ {
+ // If yes, then it will be part of the output.
+ staticItems.add(item);
+ }
+ else
+ {
+ // If no, then we might need to output an error.
+ anyNonStatic = true;
+ }
+ }
- // We need to confirm that whatever member we
- // are trying to refer to is usable via static reference.
- //
- // TODO: eventually we might allow a non-static
- // member to be adapted by turning it into something
- // like a closure that takes the missing `this` parameter.
- //
- // E.g., a static reference to a method could be treated
- // as a value with a function type, where the first parameter
- // is `type`.
- //
- // The biggest challenge there is that we'd need to arrange
- // to generate "dispatcher" functions that could be used
- // to implement that function, in the case where we are
- // making a static reference to some kind of polymorphic declaration.
- //
- // (Also, static references to fields/properties would get even
- // harder, because you'd have to know whether a getter/setter/ref-er
- // is needed).
- //
- // For now let's just be expedient and disallow all of that, because
- // we can always add it back in later.
+ // Was there anything non-static in the list?
+ if (anyNonStatic)
+ {
+ // If we had some static items, then that's okay,
+ // we just want to use our newly-filtered list.
+ if (staticItems.getCount())
+ {
+ lookupResult.items = staticItems;
+ lookupResult.item = staticItems[0];
+ }
+ else
+ {
+ // Otherwise, it is time to report an error.
+ getSink()->diagnose(
+ expr->loc,
+ Diagnostics::staticRefToNonStaticMember,
+ type,
+ expr->name);
+ hasErrors = true;
+ return;
+ }
+ }
+ // If there were no non-static items, then the `items`
+ // array already represents what we'd get by filtering...
- // If the lookup result is valid, then we want to filter
- // it to just those candidates that can be referenced statically,
- // and ignore any that would only be allowed as instance members.
- //
- if(lookupResult.isValid())
- {
- // We track both the usable items, and whether or
- // not there were any non-static items that need
- // to be ignored.
- //
- bool anyNonStatic = false;
- List<LookupResultItem> staticItems;
- for (auto item : lookupResult)
- {
- // Is this item usable as a static member?
- if (isUsableAsStaticMember(item))
- {
- // If yes, then it will be part of the output.
- staticItems.add(item);
- }
- else
- {
- // If no, then we might need to output an error.
- anyNonStatic = true;
+ AddToLookupResult(globalLookupResult, lookupResult);
+ base = baseExpression;
}
}
+ };
- // Was there anything non-static in the list?
- if (anyNonStatic)
- {
- // If we had some static items, then that's okay,
- // we just want to use our newly-filtered list.
- if (staticItems.getCount())
- {
- lookupResult.items = staticItems;
- lookupResult.item = staticItems[0];
- }
- else
- {
- // Otherwise, it is time to report an error.
- getSink()->diagnose(
- expr->loc,
- Diagnostics::staticRefToNonStaticMember,
- type,
- expr->name);
- return CreateErrorExpr(expr);
- }
- }
- // If there were no non-static items, then the `items`
- // array already represents what we'd get by filtering...
- }
- if (expr->name == getSession()->getCompletionRequestTokenName())
+ auto handleLeafExpr = [&](Expr* e)
{
- suggestCompletionItems(CompletionSuggestions::ScopeKind::Member, lookupResult);
+ if (auto nsType = as<NamespaceType>(e->type))
+ handleLeafCase(nsType->getDeclRef(), nsType);
+ else if (auto aggType = as<DeclRefType>(e->type))
+ handleLeafCase(aggType->getDeclRef(), aggType);
+ else if (auto typetype = as<TypeType>(e->type))
+ handleLeafCase(DeclRef<Decl>(), typetype->getType());
+ };
+
+ auto& baseType = baseExpression->type;
+ if (as<ErrorType>(baseType))
+ {
+ return CreateErrorExpr(expr);
+ }
+
+ if (auto overloaded = as<OverloadedExpr>(baseExpression))
+ {
+ for (auto candidate : overloaded->lookupResult2.items)
+ handleLeafCase(candidate.declRef, nullptr);
+ }
+ else if (auto overloaded2 = as<OverloadedExpr2>(baseExpression))
+ {
+ for (auto candidate : overloaded2->candidiateExprs)
+ {
+ handleLeafExpr(candidate);
}
- return createLookupResultExpr(
- expr->name,
- lookupResult,
- baseExpression,
- expr->loc,
- expr);
}
- else if (as<ErrorType>(baseType))
+ else
{
- return CreateErrorExpr(expr);
+ handleLeafExpr(baseExpression);
+ }
+
+ bool diagnosed = false;
+ globalLookupResult = filterLookupResultByVisibilityAndDiagnose(globalLookupResult, expr->loc, diagnosed);
+ diagnosed |= hasErrors;
+ if (!globalLookupResult.isValid())
+ {
+ return lookupMemberResultFailure(expr, baseType, diagnosed);
}
- // Failure
- return lookupMemberResultFailure(expr, baseType);
+ if (expr->name == getSession()->getCompletionRequestTokenName())
+ {
+ suggestCompletionItems(CompletionSuggestions::ScopeKind::Member, globalLookupResult);
+ }
+ return createLookupResultExpr(
+ expr->name,
+ globalLookupResult,
+ base,
+ expr->loc,
+ expr);
}
Expr* SemanticsExprVisitor::visitStaticMemberExpr(StaticMemberExpr* expr)
@@ -3565,12 +3725,14 @@ namespace Slang
Expr* SemanticsVisitor::lookupMemberResultFailure(
DeclRefExpr* expr,
- QualType const& baseType)
+ QualType const& baseType,
+ bool supressDiagnostic)
{
// Check it's a member expression
SLANG_ASSERT(as<StaticMemberExpr>(expr) || as<MemberExpr>(expr));
- getSink()->diagnose(expr, Diagnostics::noMemberOfNameInType, expr->name, baseType);
+ if (!supressDiagnostic)
+ getSink()->diagnose(expr, Diagnostics::noMemberOfNameInType, expr->name, baseType);
expr->type = QualType(m_astBuilder->getErrorType());
return expr;
}
@@ -3678,6 +3840,14 @@ namespace Slang
{
return _lookupStaticMember(expr, expr->baseExpression);
}
+ else if (as<OverloadedExpr>(expr->baseExpression))
+ {
+ return _lookupStaticMember(expr, expr->baseExpression);
+ }
+ else if (as<OverloadedExpr2>(expr->baseExpression))
+ {
+ return _lookupStaticMember(expr, expr->baseExpression);
+ }
else if (as<ErrorType>(baseType))
{
return CreateErrorExpr(expr);
@@ -3688,10 +3858,13 @@ namespace Slang
m_astBuilder,
this,
expr->name,
- baseType.Ptr());
+ baseType.Ptr(),
+ m_outerScope);
+ bool diagnosed = false;
+ lookupResult = filterLookupResultByVisibilityAndDiagnose(lookupResult, expr->loc, diagnosed);
if (!lookupResult.isValid())
{
- return lookupMemberResultFailure(expr, baseType);
+ return lookupMemberResultFailure(expr, baseType, diagnosed);
}
if (expr->name == getSession()->getCompletionRequestTokenName())
{
diff --git a/source/slang/slang-check-impl.h b/source/slang/slang-check-impl.h
index e9654830a..43844cf70 100644
--- a/source/slang/slang-check-impl.h
+++ b/source/slang/slang-check-impl.h
@@ -217,6 +217,7 @@ namespace Slang
FixityChecked,
TypeChecked,
DirectionChecked,
+ VisibilityChecked,
Applicable,
};
Status status = Status::Unchecked;
@@ -773,6 +774,8 @@ namespace Slang
struct SemanticsContext
{
public:
+ friend struct OuterScopeContextRAII;
+
explicit SemanticsContext(
SharedSemanticsContext* shared)
: m_shared(shared)
@@ -804,6 +807,8 @@ namespace Slang
result.m_parentFunc = parentFunc;
result.m_outerStmts = nullptr;
result.m_parentDifferentiableAttr = parentFunc->findModifier<DifferentiableAttribute>();
+ if (parentFunc->ownedScope)
+ result.m_outerScope = parentFunc->ownedScope;
return result;
}
@@ -868,6 +873,7 @@ namespace Slang
};
ExprLocalScope* getExprLocalScope() { return m_exprLocalScope; }
+ Scope* getOuterScope() { return m_outerScope; }
SemanticsContext withExprLocalScope(ExprLocalScope* exprLocalScope)
{
@@ -876,6 +882,13 @@ namespace Slang
return result;
}
+ SemanticsContext withOuterScope(Scope* scope)
+ {
+ SemanticsContext result(*this);
+ result.m_outerScope = scope;
+ return result;
+ }
+
SemanticsContext withTreatAsDifferentiable(TreatAsDifferentiableExpr* expr)
{
SemanticsContext result(*this);
@@ -921,8 +934,31 @@ namespace Slang
TreatAsDifferentiableExpr* m_treatAsDifferentiableExpr = nullptr;
ASTBuilder* m_astBuilder = nullptr;
+
+ Scope* m_outerScope = nullptr;
+ };
+
+ struct OuterScopeContextRAII
+ {
+ SemanticsContext* m_context;
+ Scope* m_oldOuterScope;
+
+ OuterScopeContextRAII(SemanticsContext* context, Scope* outerScope)
+ : m_context(context)
+ , m_oldOuterScope(context->getOuterScope())
+ {
+ context->m_outerScope = outerScope;
+ }
+
+ ~OuterScopeContextRAII()
+ {
+ m_context->m_outerScope = m_oldOuterScope;
+ }
};
+#define SLANG_OUTER_SCOPE_CONTEXT_RAII(context, scope) OuterScopeContextRAII _outerScopeContextRAII(context, scope)
+#define SLANG_OUTER_SCOPE_CONTEXT_DECL_RAII(context, decl) OuterScopeContextRAII _outerScopeContextRAII(context, decl->ownedScope?decl->ownedScope:context->getOuterScope())
+
struct SemanticsVisitor : public SemanticsContext
{
typedef SemanticsContext Super;
@@ -1010,6 +1046,8 @@ namespace Slang
/// If `expr` has Ref<T> Type, convert it into an l-value expr that has T type.
Expr* maybeOpenRef(Expr* expr);
+ Scope* getScope(SyntaxNode* node);
+
void diagnoseDeprecatedDeclRefUsage(DeclRef<Decl> declRef, SourceLoc loc, Expr* originalExpr);
DeclRef<Decl> getDefaultDeclRef(Decl* decl)
@@ -1056,6 +1094,11 @@ namespace Slang
SourceLoc loc,
Expr* originalExpr);
+ DeclVisibility getDeclVisibility(Decl* decl);
+ DeclVisibility getTypeVisibility(Type* type);
+ bool isDeclVisibleFromScope(DeclRef<Decl> declRef, Scope* scope);
+ LookupResult filterLookupResultByVisibility(const LookupResult& lookupResult);
+ LookupResult filterLookupResultByVisibilityAndDiagnose(const LookupResult& lookupResult, SourceLoc loc, bool& outDiagnosed);
Val* resolveVal(Val* val)
{
@@ -1444,6 +1487,7 @@ namespace Slang
ModifiableSyntaxNode* syntaxNode);
void checkModifiers(ModifiableSyntaxNode* syntaxNode);
+ void checkVisibility(Decl* decl);
bool doesSignatureMatchRequirement(
DeclRef<CallableDecl> satisfyingMemberDeclRef,
@@ -1985,6 +2029,9 @@ namespace Slang
// Source location of the "function" part of the expression, if any
SourceLoc funcLoc;
+ // The source scope of the lookup for performing visibiliity tests.
+ Scope* sourceScope = nullptr;
+
// The original arguments to the call
Index argCount = 0;
Expr** args = nullptr;
@@ -2048,6 +2095,10 @@ namespace Slang
OverloadResolveContext& context,
OverloadCandidate const& candidate);
+ bool TryCheckOverloadCandidateVisibility(
+ OverloadResolveContext& context,
+ OverloadCandidate const& candidate);
+
bool TryCheckGenericOverloadCandidateTypes(
OverloadResolveContext& context,
OverloadCandidate& candidate);
@@ -2371,7 +2422,8 @@ namespace Slang
Expr* lookupMemberResultFailure(
DeclRefExpr* expr,
- QualType const& baseType);
+ QualType const& baseType,
+ bool supressDiagnostic = false);
SharedSemanticsContext& operator=(const SharedSemanticsContext &) = delete;
diff --git a/source/slang/slang-check-modifier.cpp b/source/slang/slang-check-modifier.cpp
index 569804ff4..339ecba4c 100644
--- a/source/slang/slang-check-modifier.cpp
+++ b/source/slang/slang-check-modifier.cpp
@@ -950,7 +950,7 @@ namespace Slang
{
if (auto parentExtension = as<ExtensionDecl>(varDecl->parentDecl))
{
- auto originalMemberLookup = lookUpMember(m_astBuilder, this, varDecl->getName(), parentExtension->targetType);
+ auto originalMemberLookup = lookUpMember(m_astBuilder, this, varDecl->getName(), parentExtension->targetType, parentExtension->ownedScope);
LookupResult filteredResult;
for (auto item : originalMemberLookup.items)
{
@@ -1042,6 +1042,23 @@ namespace Slang
}
}
+ if (as<PrivateModifier>(m))
+ {
+ if (as<AggTypeDeclBase>(syntaxNode) || as<NamespaceDeclBase>(syntaxNode))
+ {
+ getSink()->diagnose(m, Diagnostics::invalidUseOfPrivateVisibility, as<Decl>(syntaxNode));
+ }
+ else if (auto decl = as<Decl>(syntaxNode))
+ {
+ // Interface requirements can't be private.
+ if (isInterfaceRequirement(decl))
+ {
+ getSink()->diagnose(m, Diagnostics::invalidUseOfPrivateVisibility, as<Decl>(syntaxNode));
+ }
+ }
+ }
+
+
// Default behavior is to leave things as they are,
// and assume that modifiers are mostly already checked.
//
@@ -1054,6 +1071,71 @@ namespace Slang
return m;
}
+ void SemanticsVisitor::checkVisibility(Decl* decl)
+ {
+ if (as<AccessorDecl>(decl))
+ {
+ return;
+ }
+ ShortList<Type*> typesToVerify;
+ if (auto varDecl = as<VarDeclBase>(decl))
+ {
+ typesToVerify.add(varDecl->type);
+ }
+ else if (auto callable = as<CallableDecl>(decl))
+ {
+ typesToVerify.add(callable->returnType);
+ typesToVerify.add(callable->errorType);
+ for (auto param : callable->getParameters())
+ {
+ typesToVerify.add(param->type);
+ }
+ }
+ else if (auto propertyDecl = as<PropertyDecl>(decl))
+ {
+ typesToVerify.add(propertyDecl->type);
+ }
+ else if (as<AggTypeDeclBase>(decl))
+ {
+ }
+ else if (auto typeDecl = as<TypeDefDecl>(decl))
+ {
+ typesToVerify.add(typeDecl->type);
+ }
+ else
+ {
+ return;
+ }
+ auto thisVisibility = getDeclVisibility(decl);
+
+ // First, we check that the decl's type does not have lower visibility.
+ for (auto type : typesToVerify)
+ {
+ if (!type)
+ continue;
+ DeclVisibility typeVisibility = getTypeVisibility(type);
+ if (typeVisibility < thisVisibility)
+ {
+ getSink()->diagnose(decl, Diagnostics::useOfLessVisibleType, decl, type);
+ break;
+ }
+ }
+
+ // Next, we check that the decl does not have higher visiblity than its parent.
+ Decl* parentDecl = decl;
+ for (; parentDecl; parentDecl = parentDecl->parentDecl)
+ {
+ if (as<AggTypeDeclBase>(parentDecl))
+ break;
+ }
+ if (!parentDecl)
+ return;
+ auto parentVisibility = getDeclVisibility(parentDecl);
+ if (thisVisibility > parentVisibility)
+ {
+ getSink()->diagnose(decl, Diagnostics::declCannotHaveHigherVisibility, decl, parentDecl);
+ }
+ }
void SemanticsVisitor::checkModifiers(ModifiableSyntaxNode* syntaxNode)
{
diff --git a/source/slang/slang-check-overload.cpp b/source/slang/slang-check-overload.cpp
index d7d29a4e1..2912a79b0 100644
--- a/source/slang/slang-check-overload.cpp
+++ b/source/slang/slang-check-overload.cpp
@@ -190,6 +190,33 @@ namespace Slang
}
}
+ bool SemanticsVisitor::TryCheckOverloadCandidateVisibility(OverloadResolveContext& context, OverloadCandidate const& candidate)
+ {
+ // Always succeeds when we are trying out constructors.
+ if (context.mode == OverloadResolveContext::Mode::JustTrying)
+ {
+ if (as<ConstructorDecl>(candidate.item.declRef))
+ return true;
+ }
+
+ if (!context.sourceScope)
+ return true;
+
+ if (!candidate.item.declRef)
+ return true;
+
+ if (!isDeclVisibleFromScope(candidate.item.declRef, context.sourceScope))
+ {
+ if (context.mode == OverloadResolveContext::Mode::ForReal)
+ {
+ getSink()->diagnose(context.loc, Diagnostics::declIsNotVisible, candidate.item.declRef);
+ }
+ return false;
+ }
+
+ return true;
+ }
+
bool SemanticsVisitor::TryCheckGenericOverloadCandidateTypes(
OverloadResolveContext& context,
OverloadCandidate& candidate)
@@ -704,6 +731,10 @@ namespace Slang
if (!TryCheckOverloadCandidateConstraints(context, candidate))
return;
+ candidate.status = OverloadCandidate::Status::VisibilityChecked;
+ if (!TryCheckOverloadCandidateVisibility(context, candidate))
+ return;
+
candidate.status = OverloadCandidate::Status::Applicable;
}
@@ -777,6 +808,9 @@ namespace Slang
if (!TryCheckOverloadCandidateConstraints(context, candidate))
goto error;
+ if (!TryCheckOverloadCandidateVisibility(context, candidate))
+ goto error;
+
{
Expr* baseExpr;
switch(candidate.flavor)
@@ -887,7 +921,6 @@ namespace Slang
}
else
{
- SLANG_DIAGNOSE_UNEXPECTED(getSink(), context.loc, "no original expression for overload result");
return nullptr;
}
}
@@ -1511,6 +1544,7 @@ namespace Slang
this,
getName("$init"),
type,
+ context.sourceScope,
LookupMask::Default,
LookupOptions::NoDeref);
@@ -1885,7 +1919,7 @@ namespace Slang
context.argCount = expr->arguments.getCount();
context.args = expr->arguments.getBuffer();
context.loc = expr->loc;
-
+ context.sourceScope = m_outerScope;
context.baseExpr = GetBaseExpr(funcExpr);
// TODO: We should have a special case here where an `InvokeExpr`
@@ -1975,26 +2009,16 @@ namespace Slang
Index candidateCount = context.bestCandidates.getCount();
Index maxCandidatesToPrint = 10; // don't show too many candidates at once...
Index candidateIndex = 0;
+ context.bestCandidates.sort([](const OverloadCandidate& c1, const OverloadCandidate& c2) { return c1.status < c2.status; });
+
for (auto candidate : context.bestCandidates)
{
String declString = ASTPrinter::getDeclSignatureString(candidate.item, m_astBuilder);
-// declString = declString + "[" + String(candidate.conversionCostSum) + "]";
-
-#if 0
- // Debugging: ensure that we don't consider multiple declarations of the same operation
- if (auto decl = as<CallableDecl>(candidate.item.declRef.decl))
- {
- char buffer[1024];
- sprintf_s(buffer, sizeof(buffer), "[this:%p, primary:%p, next:%p]",
- decl,
- decl->primaryDecl,
- decl->nextDecl);
- declString.append(buffer);
- }
-#endif
-
- getSink()->diagnose(candidate.item.declRef, Diagnostics::overloadCandidate, declString);
+ if (candidate.status == OverloadCandidate::Status::VisibilityChecked)
+ getSink()->diagnose(candidate.item.declRef, Diagnostics::invisibleOverloadCandidate, declString);
+ else
+ getSink()->diagnose(candidate.item.declRef, Diagnostics::overloadCandidate, declString);
candidateIndex++;
if (candidateIndex == maxCandidatesToPrint)
@@ -2126,7 +2150,7 @@ namespace Slang
context.argCount = args.getCount();
context.args = args.getBuffer();
context.loc = genericAppExpr->loc;
-
+ context.sourceScope = m_outerScope;
context.baseExpr = GetBaseExpr(baseExpr);
AddGenericOverloadCandidates(baseExpr, context);
diff --git a/source/slang/slang-diagnostic-defs.h b/source/slang/slang-diagnostic-defs.h
index 8eb0584d0..c95d5ea98 100644
--- a/source/slang/slang-diagnostic-defs.h
+++ b/source/slang/slang-diagnostic-defs.h
@@ -357,6 +357,13 @@ DIAGNOSTIC(30503, Error, primaryModuleFileCannotStartWithImplementingDecl, "a pr
DIAGNOSTIC(30504, Warning, primaryModuleFileMustStartWithModuleDecl, "a primary source file for a module should start with 'module'.")
DIAGNOSTIC(30505, Error, implementingMustReferencePrimaryModuleFile, "the source file referenced by 'implementing' must be a primary module file starting with a 'module' declaration.")
+// Visibilty
+DIAGNOSTIC(30600, Error, declIsNotVisible, "'$0' is not accessible from the current context.")
+DIAGNOSTIC(30601, Error, declCannotHaveHigherVisibility, "'$0' cannot have a higher visibility than '$1'.")
+DIAGNOSTIC(30602, Error, declCannotHaveLowerVisibility, "'$0' cannot have a lower visibility than '$1'.")
+DIAGNOSTIC(30603, Error, invalidUseOfPrivateVisibility, "'$0' cannot have private visibility.")
+DIAGNOSTIC(30604, Error, useOfLessVisibleType, "'$0' references less visible type '$1'.")
+
// Attributes
DIAGNOSTIC(31000, Error, unknownAttributeName, "unknown attribute '$0'")
DIAGNOSTIC(31001, Error, attributeArgumentCountMismatch, "attribute '$0' expects $1 arguments ($2 provided)")
@@ -502,6 +509,8 @@ DIAGNOSTIC(39999, Error, ambiguousOverloadForNameWithArgs, "ambiguous call to '$
DIAGNOSTIC(39999, Error, ambiguousOverloadWithArgs, "ambiguous call to overloaded operation with arguments of type $0")
DIAGNOSTIC(39999, Note, overloadCandidate, "candidate: $0")
+DIAGNOSTIC(39999, Note, invisibleOverloadCandidate, "candidate (invisible): $0")
+
DIAGNOSTIC(39999, Note, moreOverloadCandidates, "$0 more overload candidates")
DIAGNOSTIC(39999, Error, caseOutsideSwitch, "'case' not allowed outside of a 'switch' statement")
diff --git a/source/slang/slang-emit-c-like.cpp b/source/slang/slang-emit-c-like.cpp
index d0efce0f5..7f7e23a1c 100644
--- a/source/slang/slang-emit-c-like.cpp
+++ b/source/slang/slang-emit-c-like.cpp
@@ -4122,8 +4122,8 @@ void CLikeSourceEmitter::computeEmitActions(IRModule* module, List<EmitAction>&
{
if( as<IRType>(inst) )
{
- // Don't emit a type unless it is actually used or is marked public.
- if (!inst->findDecoration<IRPublicDecoration>())
+ // Don't emit a type unless it is actually used or is marked exported.
+ if (!inst->findDecoration<IRHLSLExportDecoration>())
continue;
}
diff --git a/source/slang/slang-ir-autodiff.cpp b/source/slang/slang-ir-autodiff.cpp
index e4f3f3f94..9166c560a 100644
--- a/source/slang/slang-ir-autodiff.cpp
+++ b/source/slang/slang-ir-autodiff.cpp
@@ -2066,20 +2066,15 @@ void releaseNullDifferentialType(AutoDiffSharedContext* context)
{
if (auto nullStruct = context->nullDifferentialStructType)
{
- if (auto publicDecoration = nullStruct->findDecoration<IRPublicDecoration>())
- publicDecoration->removeAndDeallocate();
if (auto keepAliveDecoration = nullStruct->findDecoration<IRKeepAliveDecoration>())
keepAliveDecoration->removeAndDeallocate();
}
if (auto nullWitness = context->nullDifferentialWitness)
{
- if (auto publicDecoration = nullWitness->findDecoration<IRPublicDecoration>())
- publicDecoration->removeAndDeallocate();
if (auto keepAliveDecoration = nullWitness->findDecoration<IRKeepAliveDecoration>())
keepAliveDecoration->removeAndDeallocate();
}
-
}
bool finalizeAutoDiffPass(IRModule* module)
diff --git a/source/slang/slang-ir-dll-export.cpp b/source/slang/slang-ir-dll-export.cpp
index d7a18e665..af5f70eb3 100644
--- a/source/slang/slang-ir-dll-export.cpp
+++ b/source/slang/slang-ir-dll-export.cpp
@@ -4,6 +4,7 @@
#include "slang-ir.h"
#include "slang-ir-insts.h"
#include "slang-ir-marshal-native-call.h"
+#include "slang-ir-util.h"
namespace Slang
{
@@ -26,10 +27,7 @@ struct DllExportContext
builder.addPublicDecoration(wrapper);
builder.addKeepAliveDecoration(wrapper);
builder.addHLSLExportDecoration(wrapper);
- if (auto oldPublicDecoration = func->findDecoration<IRPublicDecoration>())
- {
- oldPublicDecoration->removeFromParent();
- }
+ removeLinkageDecorations(func);
}
void processModule()
diff --git a/source/slang/slang-ir-generics-lowering-context.cpp b/source/slang/slang-ir-generics-lowering-context.cpp
index 325568040..212e16483 100644
--- a/source/slang/slang-ir-generics-lowering-context.cpp
+++ b/source/slang/slang-ir-generics-lowering-context.cpp
@@ -60,7 +60,7 @@ namespace Slang
return result;
IRBuilder builderStorage(module);
auto builder = &builderStorage;
- builder->setInsertBefore(typeInst->next);
+ builder->setInsertAfter(typeInst);
result = builder->emitMakeRTTIObject(typeInst);
@@ -75,10 +75,11 @@ namespace Slang
String rttiObjName = exportDecoration->getMangledName();
builder->addExportDecoration(result, rttiObjName.getUnownedSlice());
}
- // Make sure the RTTI object for a public struct type has public visiblity.
- if (typeInst->findDecoration<IRPublicDecoration>())
+
+ // Make sure the RTTI object for an exported struct type is marked as export if the type is.
+ if (typeInst->findDecoration<IRHLSLExportDecoration>())
{
- builder->addPublicDecoration(result);
+ builder->addHLSLExportDecoration(result);
builder->addKeepAliveDecoration(result);
}
mapTypeToRTTIObject[typeInst] = result;
diff --git a/source/slang/slang-ir-link.cpp b/source/slang/slang-ir-link.cpp
index 87b4f3fde..36769cc34 100644
--- a/source/slang/slang-ir-link.cpp
+++ b/source/slang/slang-ir-link.cpp
@@ -1412,13 +1412,12 @@ struct IRSpecializationState
}
};
-static bool _isPublicOrHLSLExported(IRInst* inst)
+static bool _isHLSLExported(IRInst* inst)
{
for (auto decoration : inst->getDecorations())
{
const auto op = decoration->getOp();
- if (op == kIROp_PublicDecoration ||
- op == kIROp_HLSLExportDecoration)
+ if (op == kIROp_HLSLExportDecoration)
{
return true;
}
@@ -1582,8 +1581,8 @@ LinkedIR linkIR(
{
for (auto inst : irModule->getGlobalInsts())
{
- // Is it `public` or (HLSL) `export` clone
- if (_isPublicOrHLSLExported(inst))
+ // Is it (HLSL) `export` clone
+ if (_isHLSLExported(inst))
{
auto cloned = cloneValue(context, inst);
if (!cloned->findDecorationImpl(kIROp_KeepAliveDecoration))
diff --git a/source/slang/slang-ir-lower-generic-type.cpp b/source/slang/slang-ir-lower-generic-type.cpp
index ae085145c..28eed3582 100644
--- a/source/slang/slang-ir-lower-generic-type.cpp
+++ b/source/slang/slang-ir-lower-generic-type.cpp
@@ -16,10 +16,10 @@ namespace Slang
IRInst* processInst(IRInst* inst)
{
- // Ensure public struct types has RTTI object defined.
+ // Ensure exported struct types has RTTI object defined.
if (as<IRStructType>(inst))
{
- if (inst->findDecoration<IRPublicDecoration>())
+ if (inst->findDecoration<IRHLSLExportDecoration>())
{
sharedContext->maybeEmitRTTIObject(inst);
}
diff --git a/source/slang/slang-ir-pytorch-cpp-binding.cpp b/source/slang/slang-ir-pytorch-cpp-binding.cpp
index 432cd93f3..6a85f0324 100644
--- a/source/slang/slang-ir-pytorch-cpp-binding.cpp
+++ b/source/slang/slang-ir-pytorch-cpp-binding.cpp
@@ -575,7 +575,7 @@ void generateReflectionFunc(IRBuilder* builder, IRFunc* kernelFunc, IRFunc* host
builder->addExternCppDecoration(reflectionFunc, reflFuncExportName.getUnownedSlice());
builder->addTorchEntryPointDecoration(reflectionFunc, reflFuncExportName.getUnownedSlice());
- builder->addPublicDecoration(reflectionFunc);
+ builder->addHLSLExportDecoration(reflectionFunc);
builder->addKeepAliveDecoration(reflectionFunc);
}
@@ -760,7 +760,7 @@ void generateReflectionForType(IRType* type, DiagnosticSink* sink)
builder.addTorchEntryPointDecoration(reflFunc, reflFuncExportName.getUnownedSlice());
builder.addExternCppDecoration(reflFunc, reflFuncExportName.getUnownedSlice());
- builder.addPublicDecoration(reflFunc);
+ builder.addHLSLExportDecoration(reflFunc);
builder.addKeepAliveDecoration(reflFunc);
}
@@ -842,7 +842,7 @@ IRFunc* generateCUDAWrapperForFunc(IRFunc* func, DiagnosticSink* sink)
// Mark for host-side emit logic.
builder.addCudaHostDecoration(hostFunc);
// Keep alive. This method will be accessed externally.
- builder.addPublicDecoration(hostFunc);
+ builder.addHLSLExportDecoration(hostFunc);
builder.addKeepAliveDecoration(hostFunc);
}
@@ -1047,7 +1047,7 @@ void generateDerivativeWrappers(IRModule* module, DiagnosticSink* sink)
builder.addExternCppDecoration(wrapperFunc, nameBuilder.getUnownedSlice());
}
- builder.addPublicDecoration(wrapperFunc);
+ builder.addHLSLExportDecoration(wrapperFunc);
builder.addKeepAliveDecoration(wrapperFunc);
builder.addCudaKernelForwardDerivativeDecoration(func, wrapperFunc);
@@ -1106,7 +1106,7 @@ void generateDerivativeWrappers(IRModule* module, DiagnosticSink* sink)
builder.addExternCppDecoration(wrapperFunc, nameBuilder.getUnownedSlice());
}
- builder.addPublicDecoration(wrapperFunc);
+ builder.addHLSLExportDecoration(wrapperFunc);
builder.addKeepAliveDecoration(wrapperFunc);
builder.addCudaKernelBackwardDerivativeDecoration(func, wrapperFunc);
diff --git a/source/slang/slang-language-server-completion.cpp b/source/slang/slang-language-server-completion.cpp
index 7b01dac34..6038a432a 100644
--- a/source/slang/slang-language-server-completion.cpp
+++ b/source/slang/slang-language-server-completion.cpp
@@ -298,7 +298,7 @@ SlangResult CompletionContext::tryCompleteImport()
Index pos = -1;
for (auto prefix : prefixes)
{
- static auto importStr = UnownedStringSlice(prefix);
+ auto importStr = UnownedStringSlice(prefix);
lineContent = doc->getLine(line);
pos = lineContent.indexOf(importStr);
if (pos == -1)
diff --git a/source/slang/slang-lookup.cpp b/source/slang/slang-lookup.cpp
index ee4518c20..04a855c3c 100644
--- a/source/slang/slang-lookup.cpp
+++ b/source/slang/slang-lookup.cpp
@@ -98,6 +98,19 @@ void AddToLookupResult(
}
}
+void AddToLookupResult(LookupResult& result, const LookupResult& items)
+{
+ if (items.isOverloaded())
+ {
+ for (auto item : items.items)
+ AddToLookupResult(result, item);
+ }
+ else if (items.isValid())
+ {
+ AddToLookupResult(result, items.item);
+ }
+}
+
LookupResult refineLookup(LookupResult const& inResult, LookupMask mask)
{
if (!inResult.isValid()) return inResult;
@@ -894,11 +907,12 @@ LookupResult lookUpMember(
SemanticsVisitor* semantics,
Name* name,
Type* type,
+ Scope* sourceScope,
LookupMask mask,
LookupOptions options)
{
LookupResult result;
- LookupRequest request = initLookupRequest(semantics, name, mask, options, nullptr);
+ LookupRequest request = initLookupRequest(semantics, name, mask, options, sourceScope);
_lookUpMembersInType(astBuilder, name, type, request, result, nullptr);
return result;
}
diff --git a/source/slang/slang-lookup.h b/source/slang/slang-lookup.h
index 8af760f70..84b453bf2 100644
--- a/source/slang/slang-lookup.h
+++ b/source/slang/slang-lookup.h
@@ -27,6 +27,7 @@ LookupResult lookUpMember(
SemanticsVisitor* semantics,
Name* name,
Type* type,
+ Scope* sourceScope,
LookupMask mask = LookupMask::Default,
LookupOptions options = LookupOptions::None);
@@ -58,7 +59,9 @@ QualType getTypeForDeclRef(
void AddToLookupResult(
LookupResult& result,
LookupResultItem item);
-
+void AddToLookupResult(
+ LookupResult& result,
+ const LookupResult& items);
}
#endif
diff --git a/source/slang/slang-lower-to-ir.cpp b/source/slang/slang-lower-to-ir.cpp
index 609a5d1e5..8f94b7e90 100644
--- a/source/slang/slang-lower-to-ir.cpp
+++ b/source/slang/slang-lower-to-ir.cpp
@@ -1327,7 +1327,6 @@ static void addLinkageDecoration(
if (as<PublicModifier>(modifier))
{
builder->addPublicDecoration(inst);
- builder->addKeepAliveDecoration(inst);
}
else if (as<HLSLExportModifier>(modifier))
{
@@ -1349,43 +1348,50 @@ static void addLinkageDecoration(
else if (as<DllExportAttribute>(modifier))
{
builder->addDllExportDecoration(inst, decl->getName()->text.getUnownedSlice());
- builder->addPublicDecoration(inst);
+ builder->addHLSLExportDecoration(inst);
+ builder->addKeepAliveDecoration(inst);
}
else if (as<CudaDeviceExportAttribute>(modifier))
{
builder->addCudaDeviceExportDecoration(inst, decl->getName()->text.getUnownedSlice());
- builder->addPublicDecoration(inst);
+ builder->addHLSLExportDecoration(inst);
builder->addExternCppDecoration(inst, decl->getName()->text.getUnownedSlice());
+ builder->addKeepAliveDecoration(inst);
}
else if (as<CudaHostAttribute>(modifier))
{
builder->addCudaHostDecoration(inst);
builder->addExternCppDecoration(inst, decl->getName()->text.getUnownedSlice());
+ builder->addKeepAliveDecoration(inst);
}
else if (as<CudaKernelAttribute>(modifier))
{
builder->addCudaKernelDecoration(inst);
builder->addExternCppDecoration(inst, decl->getName()->text.getUnownedSlice());
- builder->addPublicDecoration(inst);
+ builder->addHLSLExportDecoration(inst);
builder->addKeepAliveDecoration(inst);
}
else if (as<TorchEntryPointAttribute>(modifier))
{
builder->addTorchEntryPointDecoration(inst, decl->getName()->text.getUnownedSlice());
builder->addCudaHostDecoration(inst);
- builder->addPublicDecoration(inst);
+ builder->addHLSLExportDecoration(inst);
+ builder->addKeepAliveDecoration(inst);
builder->addExternCppDecoration(inst, decl->getName()->text.getUnownedSlice());
}
else if (as<AutoPyBindCudaAttribute>(modifier))
{
builder->addAutoPyBindCudaDecoration(inst, decl->getName()->text.getUnownedSlice());
builder->addAutoPyBindExportInfoDecoration(inst);
+ builder->addKeepAliveDecoration(inst);
+ builder->addHLSLExportDecoration(inst);
}
else if (auto pyExportModifier = as<PyExportAttribute>(modifier))
{
builder->addPyExportDecoration(inst, pyExportModifier->name.getLength()
? pyExportModifier->name.getUnownedSlice()
: decl->getName()->text.getUnownedSlice());
+ builder->addHLSLExportDecoration(inst);
}
else if (auto knownBuiltinModifier = as<KnownBuiltinAttribute>(modifier))
{
@@ -7012,15 +7018,11 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo>
return LoweredValInfo::simple(inst);
}
- bool isPublicType(Type* type)
+ bool isExportedType(Type* type)
{
- // TODO(JS):
- // Not clear how should handle HLSLExportModifier here.
- // In the HLSL spec 'export' is only applicable to functions. So for now we ignore.
-
if (auto declRefType = as<DeclRefType>(type))
{
- if (declRefType->getDeclRef().getDecl()->findModifier<PublicModifier>())
+ if (declRefType->getDeclRef().getDecl()->findModifier<HLSLExportModifier>())
return true;
}
return false;
@@ -7077,9 +7079,9 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo>
astReqWitnessTable->witnessedType,
astReqWitnessTable->baseType);
subBuilder->addExportDecoration(irSatisfyingWitnessTable, mangledName.getUnownedSlice());
- if (isPublicType(astReqWitnessTable->witnessedType))
+ if (isExportedType(astReqWitnessTable->witnessedType))
{
- subBuilder->addPublicDecoration(irSatisfyingWitnessTable);
+ subBuilder->addHLSLExportDecoration(irSatisfyingWitnessTable);
subBuilder->addKeepAliveDecoration(irSatisfyingWitnessTable);
}
@@ -7219,17 +7221,12 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo>
subBuilder->addPublicDecoration(irWitnessTable);
}
- // TODO(JS):
- // Not clear what to do here around HLSLExportModifier.
- // In HLSL it only (currently) applies to functions, so perhaps do nothing is reasonable.
-
- if (parentDecl->findModifier<PublicModifier>())
+ if (parentDecl->findModifier<HLSLExportModifier>())
{
- subBuilder->addPublicDecoration(irWitnessTable);
+ subBuilder->addHLSLExportDecoration(irWitnessTable);
subBuilder->addKeepAliveDecoration(irWitnessTable);
}
-
// Make sure that all the entries in the witness table have been filled in,
// including any cases where there are sub-witness-tables for conformances
Dictionary<WitnessTable*, IRWitnessTable*> mapASTToIRWitnessTable;
@@ -10607,7 +10604,9 @@ struct TypeConformanceIRGenContext
context->irBuilder = builder;
auto witness = lowerSimpleVal(context, typeConformance->getSubtypeWitness());
- builder->addPublicDecoration(witness);
+ builder->addKeepAliveDecoration(witness);
+ builder->addHLSLExportDecoration(witness);
+
if (conformanceIdOverride != -1)
{
builder->addSequentialIDDecoration(witness, conformanceIdOverride);
diff --git a/source/slang/slang-parser.cpp b/source/slang/slang-parser.cpp
index 350bc9443..7367007e6 100644
--- a/source/slang/slang-parser.cpp
+++ b/source/slang/slang-parser.cpp
@@ -105,6 +105,7 @@ namespace Slang
Scope* outerScope = nullptr;
Scope* currentScope = nullptr;
+ ModuleDecl* currentModule = nullptr;
bool hasSeenCompletionToken = false;
@@ -153,12 +154,7 @@ namespace Slang
ModuleDecl* getCurrentModuleDecl()
{
- for (auto scope = currentScope; scope; scope = scope->parent)
- {
- if (auto moduleDecl = as<ModuleDecl>(scope->containerDecl))
- return moduleDecl;
- }
- return nullptr;
+ return currentModule;
}
Parser(
@@ -1157,7 +1153,11 @@ namespace Slang
{
parsedModifier->loc = nameToken.loc;
}
-
+ if (as<VisibilityModifier>(parsedModifier))
+ {
+ if (auto currentModule = parser->getCurrentModuleDecl())
+ currentModule->isInLegacyLanguage = false;
+ }
AddModifier(&modifierLink, parsedModifier);
continue;
}
@@ -1262,6 +1262,8 @@ namespace Slang
{
auto decl = parser->astBuilder->create<IncludeDecl>();
parseFileReferenceDeclBase(parser, decl);
+ if (auto currentModule = parser->getCurrentModuleDecl())
+ currentModule->isInLegacyLanguage = false;
return decl;
}
@@ -1296,6 +1298,8 @@ namespace Slang
decl->nameAndLoc.loc = parser->tokenReader.peekLoc();
}
parser->ReadToken(TokenType::Semicolon);
+ if (auto currentModule = parser->getCurrentModuleDecl())
+ currentModule->isInLegacyLanguage = false;
return decl;
}
@@ -3063,6 +3067,9 @@ namespace Slang
// The first is a type declaration that holds all the members, while
// the second is a variable declaration that uses the buffer type.
StructDecl* bufferDataTypeDecl = parser->astBuilder->create<StructDecl>();
+
+ addModifier(bufferDataTypeDecl, parser->astBuilder->create<PublicModifier>());
+
VarDecl* bufferVarDecl = parser->astBuilder->create<VarDecl>();
// Both declarations will have a location that points to the name
@@ -3646,6 +3653,7 @@ namespace Slang
decl->nameAndLoc = declaratorInfo.nameAndLoc;
decl->type = TypeExp(declaratorInfo.typeSpec);
+ decl->loc = decl->nameAndLoc.loc;
}
parseStorageDeclBody(parser, decl);
@@ -4238,6 +4246,8 @@ namespace Slang
currentScope = outerScope;
}
+ currentModule = getModuleDecl(program);
+
PushScope(program);
// A single `ModuleDecl` might span multiple source files, so it
@@ -6997,7 +7007,7 @@ namespace Slang
syntaxDecl->syntaxClass = syntaxClass;
syntaxDecl->parseCallback = callback;
syntaxDecl->parseUserData = userData;
-
+ addModifier(syntaxDecl, globalASTBuilder->create<PublicModifier>());
AddMember(scope, syntaxDecl);
}
@@ -7511,6 +7521,9 @@ namespace Slang
_makeParseModifier("inline", InlineModifier::kReflectClassInfo),
_makeParseModifier("public", PublicModifier::kReflectClassInfo),
+ _makeParseModifier("private", PrivateModifier::kReflectClassInfo),
+ _makeParseModifier("internal", InternalModifier::kReflectClassInfo),
+
_makeParseModifier("require", RequireModifier::kReflectClassInfo),
_makeParseModifier("param", ParamModifier::kReflectClassInfo),
_makeParseModifier("extern", ExternModifier::kReflectClassInfo),
diff --git a/source/slang/slang-syntax.cpp b/source/slang/slang-syntax.cpp
index 53a02ed87..678d9ec26 100644
--- a/source/slang/slang-syntax.cpp
+++ b/source/slang/slang-syntax.cpp
@@ -765,6 +765,17 @@ Module* getModule(Decl* decl)
return moduleDecl->module;
}
+ModuleDecl* getModuleDecl(Scope* scope)
+{
+ for (; scope; scope = scope->parent)
+ {
+ if (scope->containerDecl)
+ return getModuleDecl(scope->containerDecl);
+ }
+ return nullptr;
+
+}
+
Decl* getParentDecl(Decl* decl)
{
decl = decl->parentDecl;
diff --git a/source/slang/slang-syntax.h b/source/slang/slang-syntax.h
index b2b5deb22..fff567049 100644
--- a/source/slang/slang-syntax.h
+++ b/source/slang/slang-syntax.h
@@ -330,6 +330,7 @@ namespace Slang
/// Get the module dclaration that a declaration is associated with, if any.
ModuleDecl* getModuleDecl(Decl* decl);
+ ModuleDecl* getModuleDecl(Scope* scope);
/// Get the module that a declaration is associated with, if any.
Module* getModule(Decl* decl);