]> git.tdb.fi Git - libs/gl.git/blob - source/glsl/validate.cpp
Record location information in all syntax nodes
[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(Node &node, Diagnostic::Severity severity, const string &message)
16 {
17         Diagnostic diag;
18         diag.severity = severity;
19         diag.source = node.source;
20         diag.line = node.line;
21         diag.message = message;
22         stage->diagnostics.push_back(diag);
23 }
24
25
26 DeclarationValidator::DeclarationValidator():
27         anonymous_block(false)
28 { }
29
30 void DeclarationValidator::multiple_definition(const string &name, Statement &statement, Statement &previous)
31 {
32         error(statement, format("Multiple definition of %s", name));
33         diagnose(previous, Diagnostic::INFO, "Previous definition is here");
34 }
35
36 Statement *DeclarationValidator::find_definition(const string &name)
37 {
38         BlockDeclarationMap *decls = &declarations[current_block];
39         BlockDeclarationMap::const_iterator i = decls->find(name);
40         if(i==decls->end() && anonymous_block)
41         {
42                 decls = &declarations[current_block->parent];
43                 i = decls->find(name);
44         }
45         return (i!=decls->end() ? i->second : 0);
46 }
47
48 void DeclarationValidator::check_definition(const string &name, Statement &statement)
49 {
50         if(Statement *previous = find_definition(name))
51                 multiple_definition(format("'%s'", name), statement, *previous);
52         else
53                 record_definition(name, statement);
54 }
55
56 void DeclarationValidator::record_definition(const string &name, Statement &statement)
57 {
58         declarations[current_block].insert(make_pair(name, &statement));
59         if(anonymous_block)
60                 declarations[current_block->parent].insert(make_pair(name, &statement));
61 }
62
63 void DeclarationValidator::visit(StructDeclaration &strct)
64 {
65         check_definition(strct.name, strct);
66         TraversingVisitor::visit(strct);
67 }
68
69 void DeclarationValidator::visit(VariableDeclaration &var)
70 {
71         check_definition(var.name, var);
72         TraversingVisitor::visit(var);
73 }
74
75 void DeclarationValidator::visit(InterfaceBlock &iface)
76 {
77         string key = iface.interface+iface.name;
78         map<string, InterfaceBlock *>::const_iterator i = interface_blocks.find(key);
79         if(i!=interface_blocks.end())
80                 multiple_definition(format("interface block '%s %s'", iface.interface, iface.name), iface, *i->second);
81         else
82                 interface_blocks.insert(make_pair(key, &iface));
83
84         if(Statement *previous = find_definition(iface.name))
85         {
86                 if(!dynamic_cast<InterfaceBlock *>(previous))
87                         multiple_definition(format("'%s'", iface.name), iface, *previous);
88         }
89         else
90                 record_definition(iface.name, iface);
91
92         if(!iface.instance_name.empty())
93                 check_definition(iface.instance_name, iface);
94
95         SetFlag set_anon(anonymous_block, iface.instance_name.empty());
96         TraversingVisitor::visit(iface);
97 }
98
99 void DeclarationValidator::visit(FunctionDeclaration &func)
100 {
101         if(Statement *previous = find_definition(func.name))
102                 if(!dynamic_cast<FunctionDeclaration *>(previous))
103                         multiple_definition(format("'%s'", func.name), func, *previous);
104
105         if(func.definition==&func)
106                 check_definition(func.name, func);
107         TraversingVisitor::visit(func);
108 }
109
110 } // namespace SL
111 } // namespace GL
112 } // namespace Msp