]> git.tdb.fi Git - libs/gl.git/blobdiff - source/glsl/validate.cpp
Validate GLSL flow control
[libs/gl.git] / source / glsl / validate.cpp
index 62f997bb5c29ad6d8a507620c3d78745118fc80f..86afebedb1611871d5ecfa5e3b34fb2cbd59957a 100644 (file)
@@ -699,6 +699,52 @@ void ExpressionValidator::visit(Return &ret)
 }
 
 
+FlowControlValidator::FlowControlValidator():
+       reachable(true)
+{ }
+
+void FlowControlValidator::visit(Block &block)
+{
+       for(NodeList<Statement>::const_iterator i=block.body.begin(); i!=block.body.end(); ++i)
+       {
+               if(!reachable)
+               {
+                       diagnose(**i, Diagnostic::WARN, "Unreachable code detected");
+                       break;
+               }
+               (*i)->visit(*this);
+       }
+}
+
+void FlowControlValidator::visit(FunctionDeclaration &func)
+{
+       func.body.visit(*this);
+
+       if(func.definition==&func && func.return_type_declaration)
+       {
+               const BasicTypeDeclaration *basic_ret = dynamic_cast<const BasicTypeDeclaration *>(func.return_type_declaration);
+               if(reachable && (!basic_ret || basic_ret->kind!=BasicTypeDeclaration::VOID))
+                       error(func, "Missing return statement at the end of a function not returning 'void'");
+       }
+       reachable = true;
+}
+
+void FlowControlValidator::visit(Conditional &cond)
+{
+       cond.body.visit(*this);
+       bool reachable_if_true = reachable;
+       reachable = true;
+       cond.else_body.visit(*this);
+       reachable |= reachable_if_true;
+}
+
+void FlowControlValidator::visit(Iteration &iter)
+{
+       iter.body.visit(*this);
+       reachable = true;
+}
+
+
 int StageInterfaceValidator::get_location(const Layout &layout)
 {
        for(vector<Layout::Qualifier>::const_iterator i=layout.qualifiers.begin(); i!=layout.qualifiers.end(); ++i)