Browse Source

[ATOM-4800] Unclear Error Message for Function Inside Struct (#6)

In order to catch the error of function inside struct
it was necessary to modify the grammar to allow function definitions
and declarations inside "struct" definitions (just like classes,
interfaces and ShaderResourceGroups), this way
the ANTLR parser would let it pass, giving the chance for AZSLc
to provide a meaningful error message.

ANTLR Syntax Error message:
"no viable alternative at input
structParallaxMapping{Texture2Dm_depthMap;floatm_depthFactor;boolm_isHeightmap;floatm_parallaxShadowFactor;float2GetParallaxUV("

New AZSLc produced Error message:
"function_declared_in_struct.azsl(14,4) : Syntax error #516: structs
cannot have member functions; consider using a class."

Signed-off-by: garrieta <[email protected]>
galibzon 3 years ago
parent
commit
5e809f4c60

+ 1 - 0
src/AzslcException.h

@@ -100,6 +100,7 @@ namespace AZ::ShaderCompiler
         ADVANCED_SYNTAX_CONSTANT_BUFFER_ONLY_IN_SRG = 513u,
         ADVANCED_SYNTAX_DOUBLE_SCOPE_RESOLUTION = 514u,
         ADVANCED_RESERVED_NAME_USED = 515u,
+        ADVANCED_SYNTAX_FUNCTION_IN_STRUCT = 516u,
     };
 
     class AzslcException : public antlr4::RuntimeException

+ 18 - 0
src/AzslcListener.cpp

@@ -196,6 +196,15 @@ namespace AZ::ShaderCompiler
 
     void SemaCheckListener::enterFunctionDefinition(azslParser::FunctionDefinitionContext* ctx)
     {
+        // Forbid function definitions inside "struct"s.
+        if (m_ir->m_sema.IsScopeStruct())
+        {
+            throw AzslcException(ADVANCED_SYNTAX_FUNCTION_IN_STRUCT,
+                                 "Syntax",
+                                 ctx->start,
+                                 "structs cannot have member functions; consider using a class.");
+        }
+
         auto signature = ctx->hlslFunctionDefinition()->leadingTypeFunctionSignature();
         auto uqName = ExtractNameFromAnyContextWithName(signature);
 
@@ -226,6 +235,15 @@ namespace AZ::ShaderCompiler
 
     void SemaCheckListener::enterFunctionDeclaration(azslParser::FunctionDeclarationContext* ctx)
     {
+        // Forbid function declarations inside "struct"s.
+        if (m_ir->m_sema.IsScopeStruct())
+        {
+            throw AzslcException(ADVANCED_SYNTAX_FUNCTION_IN_STRUCT,
+                                 "Syntax",
+                                 ctx->start,
+                                 "structs cannot have member functions; consider using a class.");
+        }
+
         auto signature = ctx->hlslFunctionDeclaration()->leadingTypeFunctionSignature();
         auto uqName = ExtractNameFromAnyContextWithName(signature);
         auto& [id, _] = m_ir->m_sema.RegisterFunctionDeclarationAndAddSeenat(uqName, signature);

+ 1 - 1
src/AzslcMain.cpp

@@ -23,7 +23,7 @@ namespace StdFs = std::filesystem;
 // For large features or milestones. Minor version allows for breaking changes. Existing tests can change.
 #define AZSLC_MINOR    "7"
 // For small features or bug fixes. They cannot introduce breaking changes. Existing tests shouldn't change.
-#define AZSLC_REVISION "27" // ATOM-2430
+#define AZSLC_REVISION "28" // ATOM-4800
 
 namespace AZ::ShaderCompiler
 {

+ 6 - 0
src/AzslcSemanticOrchestrator.cpp

@@ -1953,6 +1953,12 @@ namespace AZ::ShaderCompiler
         return found;
     }
 
+    bool SemanticOrchestrator::IsScopeStruct() const
+    {
+        const KindInfo& scopeKind = m_symbols->GetIdAndKindInfo(m_scope->GetNameOfCurScope())->second;
+        return scopeKind.IsKindOneOf(Kind::Struct);
+    }
+
     bool SemanticOrchestrator::IsScopeStructClassInterface() const
     {
         const KindInfo& scopeKind = m_symbols->GetIdAndKindInfo(m_scope->GetNameOfCurScope())->second;

+ 4 - 1
src/AzslcSemanticOrchestrator.h

@@ -351,9 +351,12 @@ namespace AZ::ShaderCompiler
         // another helper to streamline what to do directly with the result from ExtractTypeNameFromAstContext function families.
         auto CreateExtendedTypeInfo(const ExtractedComposedType& extractedComposed, ArrayDimensions dims, Packing::MatrixMajor mtxMajor) const -> ExtendedTypeInfo;
 
-        //! check if current scope is a structured user defined type
+        //! check if current scope is a structured user defined type ("struct", "class" or "interface")
         bool IsScopeStructClassInterface() const;
 
+        //! check if current scope is of type "struct".
+        bool IsScopeStruct() const;
+
         //! Find a concrete function from an overload-set and an argument list.
         //! (adjust the shoot of a lookup to something more precise in case that it's possible)
         //! if maybeOverloadSet is not an overload-set the function returns identity

+ 2 - 0
src/azslParser.g4

@@ -78,6 +78,8 @@ structDefinition:
 
 structMemberDeclaration:
         variableDeclarationStatement
+    |   attributedFunctionDefinition //AZSL+, forbidden, but allows us to provide better error message.
+    |   attributedFunctionDeclaration //AZSL+, forbidden, but allows us to provide better error message.
     |   anyStructuredTypeDefinitionStatement  // AZSL+
     |   typeAliasingDefinitionStatement // AZSL+
 ;

File diff suppressed because it is too large
+ 202 - 179
src/generated/azslParser.cpp


+ 2 - 0
src/generated/azslParser.h

@@ -503,6 +503,8 @@ public:
     StructMemberDeclarationContext(antlr4::ParserRuleContext *parent, size_t invokingState);
     virtual size_t getRuleIndex() const override;
     VariableDeclarationStatementContext *variableDeclarationStatement();
+    AttributedFunctionDefinitionContext *attributedFunctionDefinition();
+    AttributedFunctionDeclarationContext *attributedFunctionDeclaration();
     AnyStructuredTypeDefinitionStatementContext *anyStructuredTypeDefinitionStatement();
     TypeAliasingDefinitionStatementContext *typeAliasingDefinitionStatement();
 

+ 26 - 0
tests/Samples/AsError/function_declared_in_struct.azsl

@@ -0,0 +1,26 @@
+// Syntax error of function declaration inside struct.
+// Syntax error #516: structs cannot have member functions; consider using a class.
+// #EC 516
+
+ShaderResourceGroupSemantic slot1
+{
+    FrequencyId = 1;
+};
+
+struct SomeStruct
+{
+    float4 m_color;
+
+    float4 GetColor();
+};
+
+ShaderResourceGroup DemoSrg : slot1
+{
+    SomeStruct m_data;
+};
+
+float4 MainPS() : SV_Target0
+{
+    float4 color = DemoSrg::m_data.GetColor();
+    return color;
+}

+ 29 - 0
tests/Samples/AsError/function_defined_in_struct.azsl

@@ -0,0 +1,29 @@
+// Syntax error of function definition inside struct.
+// Syntax error #516: structs cannot have member functions; consider using a class.
+// #EC 516
+
+ShaderResourceGroupSemantic slot1
+{
+    FrequencyId = 1;
+};
+
+struct SomeStruct
+{
+    float4 m_color;
+
+    float4 GetColor()
+    {
+        return m_color;
+    }
+};
+
+ShaderResourceGroup DemoSrg : slot1
+{
+    SomeStruct m_data;
+};
+
+float4 MainPS() : SV_Target0
+{
+    float4 color = DemoSrg::m_data.GetColor();
+    return color;
+}

Some files were not shown because too many files changed in this diff