]> git.tdb.fi Git - libs/gl.git/blob - source/glsl/validate.cpp
Copy the location when moving output declarations out of functions
[libs/gl.git] / source / glsl / validate.cpp
1 #include <msp/core/raii.h>
2 #include <msp/strings/format.h>
3 #include "validate.h"
4
5 using namespace std;
6
7 namespace Msp {
8 namespace GL {
9 namespace SL {
10
11 Validator::Validator():
12         stage(0)
13 { }
14
15 void Validator::diagnose(Statement *statement, Diagnostic::Severity severity, const string &message)
16 {
17         Diagnostic diag;
18         diag.severity = severity;
19         if(statement)
20         {
21                 diag.source = statement->source;
22                 diag.line = statement->line;
23         }
24         diag.message = message;
25         stage->diagnostics.push_back(diag);
26 }
27
28
29 DeclarationValidator::DeclarationValidator():
30         anonymous_block(false)
31 { }
32
33 Statement *DeclarationValidator::find_definition(const string &name)
34 {
35         BlockDeclarationMap *decls = &declarations[current_block];
36         BlockDeclarationMap::const_iterator i = decls->find(name);
37         if(i==decls->end() && anonymous_block)
38         {
39                 decls = &declarations[current_block->parent];
40                 i = decls->find(name);
41         }
42         return (i!=decls->end() ? i->second : 0);
43 }
44
45 void DeclarationValidator::check_definition(const string &name, Statement &statement)
46 {
47         if(Statement *previous = find_definition(name))
48         {
49                 error(&statement, format("Multiple definition of '%s'", name));
50                 diagnose(previous, Diagnostic::INFO, "Previous definition is here");
51                 return;
52         }
53
54         declarations[current_block][name] = &statement;
55         if(anonymous_block)
56                 declarations[current_block->parent][name] = &statement;
57 }
58
59 void DeclarationValidator::visit(VariableDeclaration &var)
60 {
61         check_definition(var.name, var);
62         TraversingVisitor::visit(var);
63 }
64
65 void DeclarationValidator::visit(InterfaceBlock &iface)
66 {
67         check_definition(iface.name, iface);
68         if(!iface.instance_name.empty())
69                 check_definition(iface.instance_name, iface);
70         SetFlag set_anon(anonymous_block, iface.instance_name.empty());
71         TraversingVisitor::visit(iface);
72 }
73
74 void DeclarationValidator::visit(FunctionDeclaration &func)
75 {
76         if(func.definition==&func)
77                 check_definition(func.name, func);
78         TraversingVisitor::visit(func);
79 }
80
81 } // namespace SL
82 } // namespace GL
83 } // namespace Msp