From 9bec9da4ec633a541cf6048beed99629fefae2b9 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Fri, 5 Mar 2021 01:18:15 +0200 Subject: [PATCH] Check that variable references refer do declared variables --- source/glsl/compiler.cpp | 1 + source/glsl/validate.cpp | 26 ++++++++++++++++++++++++++ source/glsl/validate.h | 11 +++++++++++ tests/glsl/undeclared.glsl | 15 +++++++++++++++ tests/glsl/unlinked_interface.glsl | 25 +++++++++++++++++++++++++ 5 files changed, 78 insertions(+) create mode 100644 tests/glsl/undeclared.glsl create mode 100644 tests/glsl/unlinked_interface.glsl diff --git a/source/glsl/compiler.cpp b/source/glsl/compiler.cpp index f5540139..0f608d6d 100644 --- a/source/glsl/compiler.cpp +++ b/source/glsl/compiler.cpp @@ -260,6 +260,7 @@ void Compiler::generate(Stage &stage, Mode mode) bool Compiler::validate(Stage &stage) { DeclarationValidator().apply(stage); + ReferenceValidator().apply(stage); for(vector::const_iterator i=stage.diagnostics.begin(); i!=stage.diagnostics.end(); ++i) if(i->severity==Diagnostic::ERR) diff --git a/source/glsl/validate.cpp b/source/glsl/validate.cpp index 6d0f8e51..6f0869ea 100644 --- a/source/glsl/validate.cpp +++ b/source/glsl/validate.cpp @@ -112,6 +112,32 @@ void DeclarationValidator::visit(FunctionDeclaration &func) TraversingVisitor::visit(func); } + +void ReferenceValidator::visit(VariableReference &var) +{ + if(!var.declaration) + error(var, format("Use of undeclared variable '%s'", var.name)); + else if(stage->type!=Stage::VERTEX && var.declaration->interface=="in" && !var.declaration->linked_declaration) + error(var, format("Use of unlinked input variable '%s'", var.name)); +} + +void ReferenceValidator::visit(InterfaceBlockReference &iface) +{ + /* An interface block reference without a declaration should be impossible + since references are generated based on existing declarations. */ + if(!iface.declaration) + error(iface, format("Use of undeclared interface block '%s'", iface.name)); + else if(stage->type!=Stage::VERTEX && iface.declaration->interface=="in" && !iface.declaration->linked_block) + error(iface, format("Use of unlinked input block '%s'", iface.name)); +} + +void ReferenceValidator::visit(VariableDeclaration &var) +{ + if(!var.type_declaration) + error(var, format("Use of undeclared type '%s'", var.type)); + TraversingVisitor::visit(var); +} + } // namespace SL } // namespace GL } // namespace Msp diff --git a/source/glsl/validate.h b/source/glsl/validate.h index c723b995..bf2677e8 100644 --- a/source/glsl/validate.h +++ b/source/glsl/validate.h @@ -50,6 +50,17 @@ private: virtual void visit(FunctionDeclaration &); }; +class ReferenceValidator: private Validator +{ +public: + void apply(Stage &s) { stage = &s; s.content.visit(*this); } + +private: + virtual void visit(VariableReference &); + virtual void visit(InterfaceBlockReference &); + virtual void visit(VariableDeclaration &); +}; + } // namespace SL } // namespace GL } // namespace Msp diff --git a/tests/glsl/undeclared.glsl b/tests/glsl/undeclared.glsl new file mode 100644 index 00000000..da888cd3 --- /dev/null +++ b/tests/glsl/undeclared.glsl @@ -0,0 +1,15 @@ +uniform Transform +{ + mat4 mvp; +} transform; + +#pragma MSP stage(vertex) +void main() +{ + gl_Position = transform.model*position; +} + +/* Expected error: +:9: Use of undeclared member 'model' +:9: Use of undeclared variable 'position' +*/ diff --git a/tests/glsl/unlinked_interface.glsl b/tests/glsl/unlinked_interface.glsl new file mode 100644 index 00000000..bb90f0db --- /dev/null +++ b/tests/glsl/unlinked_interface.glsl @@ -0,0 +1,25 @@ +uniform sampler2D tex; + +#pragma MSP stage(vertex) +layout(location=0) in vec4 position; +void main() +{ + gl_Position = position; +} + +#pragma MSP stage(fragment) +in vec2 texcoord; +in VertexOut +{ + vec4 color; +} vs_out; +out vec4 frag_color; +void main() +{ + frag_color = texture(tex, texcoord)*vs_out.color; +} + +/* Expected error: +:19: Use of unlinked input variable 'texcoord' +:19: Use of unlinked input block 'vs_out' +*/ -- 2.43.0