From 7c7a32e0de7fd8c16c02190a7483a0c2411973c1 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Fri, 5 Mar 2021 13:09:55 +0200 Subject: [PATCH] Validate some aspects of type declarations --- source/glsl/validate.cpp | 63 +++++++++++++++++++++++ source/glsl/validate.h | 19 +++++++ tests/glsl/bad_types.glsl | 14 +++++ tests/glsl/struct_member_initializer.glsl | 12 +++++ tests/glsl/undeclared_types.glsl | 7 +++ 5 files changed, 115 insertions(+) create mode 100644 tests/glsl/bad_types.glsl create mode 100644 tests/glsl/struct_member_initializer.glsl create mode 100644 tests/glsl/undeclared_types.glsl diff --git a/source/glsl/validate.cpp b/source/glsl/validate.cpp index 6f0869ea..8e5e996c 100644 --- a/source/glsl/validate.cpp +++ b/source/glsl/validate.cpp @@ -23,6 +23,57 @@ void Validator::diagnose(Node &node, Diagnostic::Severity severity, const string } +TypeValidator::TypeValidator(): + in_struct(false) +{ } + +void TypeValidator::visit(BasicTypeDeclaration &type) +{ + if(type.kind==BasicTypeDeclaration::VECTOR) + { + BasicTypeDeclaration::Kind base_kind = BasicTypeDeclaration::VOID; + if(BasicTypeDeclaration *basic_base = dynamic_cast(type.base_type)) + base_kind = basic_base->kind; + if(base_kind!=BasicTypeDeclaration::BOOL && base_kind!=BasicTypeDeclaration::INT && base_kind!=BasicTypeDeclaration::FLOAT) + error(type, format("Invalid base type '%s' for vector type '%s'", type.base, type.name)); + } + else if(type.kind==BasicTypeDeclaration::ARRAY) + { + if(BasicTypeDeclaration *basic_base = dynamic_cast(type.base_type)) + if(basic_base->kind==BasicTypeDeclaration::VOID) + error(type, format("Invalid base type '%s' for array type '%s'", type.base, type.name)); + } +} + +void TypeValidator::visit(ImageTypeDeclaration &type) +{ + BasicTypeDeclaration::Kind base_kind = BasicTypeDeclaration::VOID; + if(BasicTypeDeclaration *basic_base = dynamic_cast(type.base_type)) + base_kind = basic_base->kind; + if(base_kind!=BasicTypeDeclaration::INT && base_kind!=BasicTypeDeclaration::FLOAT) + error(type, format("Invalid base type '%s' for image type '%s'", type.base, type.name)); +} + +void TypeValidator::visit(StructDeclaration &strct) +{ + SetFlag set_struct(in_struct); + TraversingVisitor::visit(strct); +} + +void TypeValidator::visit(VariableDeclaration &var) +{ + if(in_struct) + { + if(var.layout) + error(var, "Struct members can't have layouts"); + if(var.init_expression) + error(var, "Struct members can't have initializers"); + } + + TraversingVisitor::visit(var); +} + + DeclarationValidator::DeclarationValidator(): anonymous_block(false) { } @@ -113,6 +164,18 @@ void DeclarationValidator::visit(FunctionDeclaration &func) } +void ReferenceValidator::visit(BasicTypeDeclaration &type) +{ + if(!type.base.empty() && !type.base_type) + error(type, format("Use of undeclared type '%s'", type.base)); +} + +void ReferenceValidator::visit(ImageTypeDeclaration &type) +{ + if(!type.base.empty() && !type.base_type) + error(type, format("Use of undeclared type '%s'", type.base)); +} + void ReferenceValidator::visit(VariableReference &var) { if(!var.declaration) diff --git a/source/glsl/validate.h b/source/glsl/validate.h index bf2677e8..e4b9edae 100644 --- a/source/glsl/validate.h +++ b/source/glsl/validate.h @@ -21,6 +21,23 @@ protected: void error(Node &n, const std::string &m) { diagnose(n, Diagnostic::ERR, m); } }; +class TypeValidator: private Validator +{ +private: + bool in_struct; + +public: + TypeValidator(); + + void apply(Stage &s) { stage = &s; s.content.visit(*this); } + +private: + virtual void visit(BasicTypeDeclaration &); + virtual void visit(ImageTypeDeclaration &); + virtual void visit(StructDeclaration &); + virtual void visit(VariableDeclaration &); +}; + class DeclarationValidator: private Validator { private: @@ -56,6 +73,8 @@ public: void apply(Stage &s) { stage = &s; s.content.visit(*this); } private: + virtual void visit(BasicTypeDeclaration &); + virtual void visit(ImageTypeDeclaration &); virtual void visit(VariableReference &); virtual void visit(InterfaceBlockReference &); virtual void visit(VariableDeclaration &); diff --git a/tests/glsl/bad_types.glsl b/tests/glsl/bad_types.glsl new file mode 100644 index 00000000..95f47e42 --- /dev/null +++ b/tests/glsl/bad_types.glsl @@ -0,0 +1,14 @@ +typedef vector(2) void vvec2; +typedef vector(2) mat2 hyper; +typedef vector(2) sampler2D samplervec2; +typedef image(dimensions=2) vec2 vec2sampler; + +#pragma MSP stage(vertex) +void main() { } + +/* Expected error: +:1: Invalid base type 'void' for vector type 'vvec2' +:2: Invalid base type 'mat2' for vector type 'hyper' +:3: Invalid base type 'sampler2D' for vector type 'samplervec2' +:4: Invalid base type 'vec2' for image type 'vec2sampler' +*/ diff --git a/tests/glsl/struct_member_initializer.glsl b/tests/glsl/struct_member_initializer.glsl new file mode 100644 index 00000000..8be2e092 --- /dev/null +++ b/tests/glsl/struct_member_initializer.glsl @@ -0,0 +1,12 @@ +struct Material +{ + vec4 diffuse; + vec4 specular = vec4(0.0); +}; + +#pragma MSP stage(vertex) +void main() { } + +/* Expected error: +:4: Struct members can't have initializers +*/ diff --git a/tests/glsl/undeclared_types.glsl b/tests/glsl/undeclared_types.glsl new file mode 100644 index 00000000..4941ce4a --- /dev/null +++ b/tests/glsl/undeclared_types.glsl @@ -0,0 +1,7 @@ +typedef vector(2) nonexistent nvec2; +typedef image(dimensions=2) nonexistent nsampler2D; + +/* Expected error: +:1: Parse error at 'nonexistent': expected a type +:2: Parse error at 'nonexistent': expected a type +*/ -- 2.45.2