]> git.tdb.fi Git - libs/gl.git/blob - source/glsl/validate.cpp
Resolve the return types 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(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 TypeValidator::TypeValidator():
27         in_struct(false)
28 { }
29
30 void TypeValidator::visit(BasicTypeDeclaration &type)
31 {
32         if(type.kind==BasicTypeDeclaration::VECTOR)
33         {
34                 BasicTypeDeclaration::Kind base_kind = BasicTypeDeclaration::VOID;
35                 if(BasicTypeDeclaration *basic_base = dynamic_cast<BasicTypeDeclaration *>(type.base_type))
36                         base_kind = basic_base->kind;
37                 if(base_kind!=BasicTypeDeclaration::BOOL && base_kind!=BasicTypeDeclaration::INT && base_kind!=BasicTypeDeclaration::FLOAT)
38                         error(type, format("Invalid base type '%s' for vector type '%s'", type.base, type.name));
39         }
40         else if(type.kind==BasicTypeDeclaration::ARRAY)
41         {
42                 if(BasicTypeDeclaration *basic_base = dynamic_cast<BasicTypeDeclaration *>(type.base_type))
43                         if(basic_base->kind==BasicTypeDeclaration::VOID)
44                                 error(type, format("Invalid base type '%s' for array type '%s'", type.base, type.name));
45         }
46 }
47
48 void TypeValidator::visit(ImageTypeDeclaration &type)
49 {
50         BasicTypeDeclaration::Kind base_kind = BasicTypeDeclaration::VOID;
51         if(BasicTypeDeclaration *basic_base = dynamic_cast<BasicTypeDeclaration *>(type.base_type))
52                 base_kind = basic_base->kind;
53         if(base_kind!=BasicTypeDeclaration::INT && base_kind!=BasicTypeDeclaration::FLOAT)
54                 error(type, format("Invalid base type '%s' for image type '%s'", type.base, type.name));
55 }
56
57 void TypeValidator::visit(StructDeclaration &strct)
58 {
59         SetFlag set_struct(in_struct);
60         TraversingVisitor::visit(strct);
61 }
62
63 void TypeValidator::visit(VariableDeclaration &var)
64 {
65         if(in_struct)
66         {
67                 if(var.layout)
68                         error(var, "Struct members can't have layouts");
69                 if(var.init_expression)
70                         error(var, "Struct members can't have initializers");
71         }
72
73         TraversingVisitor::visit(var);
74 }
75
76
77 DeclarationValidator::DeclarationValidator():
78         anonymous_block(false)
79 { }
80
81 void DeclarationValidator::multiple_definition(const string &name, Statement &statement, Statement &previous)
82 {
83         error(statement, format("Multiple definition of %s", name));
84         diagnose(previous, Diagnostic::INFO, "Previous definition is here");
85 }
86
87 Statement *DeclarationValidator::find_definition(const string &name)
88 {
89         BlockDeclarationMap *decls = &declarations[current_block];
90         BlockDeclarationMap::const_iterator i = decls->find(name);
91         if(i==decls->end() && anonymous_block)
92         {
93                 decls = &declarations[current_block->parent];
94                 i = decls->find(name);
95         }
96         return (i!=decls->end() ? i->second : 0);
97 }
98
99 void DeclarationValidator::check_definition(const string &name, Statement &statement)
100 {
101         if(Statement *previous = find_definition(name))
102                 multiple_definition(format("'%s'", name), statement, *previous);
103         else
104                 record_definition(name, statement);
105 }
106
107 void DeclarationValidator::record_definition(const string &name, Statement &statement)
108 {
109         declarations[current_block].insert(make_pair(name, &statement));
110         if(anonymous_block)
111                 declarations[current_block->parent].insert(make_pair(name, &statement));
112 }
113
114 void DeclarationValidator::visit(TypeDeclaration &type)
115 {
116         check_definition(type.name, type);
117 }
118
119 void DeclarationValidator::visit(StructDeclaration &strct)
120 {
121         check_definition(strct.name, strct);
122         TraversingVisitor::visit(strct);
123 }
124
125 void DeclarationValidator::visit(VariableDeclaration &var)
126 {
127         check_definition(var.name, var);
128         TraversingVisitor::visit(var);
129 }
130
131 void DeclarationValidator::visit(InterfaceBlock &iface)
132 {
133         string key = iface.interface+iface.name;
134         map<string, InterfaceBlock *>::const_iterator i = interface_blocks.find(key);
135         if(i!=interface_blocks.end())
136                 multiple_definition(format("interface block '%s %s'", iface.interface, iface.name), iface, *i->second);
137         else
138                 interface_blocks.insert(make_pair(key, &iface));
139
140         if(Statement *previous = find_definition(iface.name))
141         {
142                 if(!dynamic_cast<InterfaceBlock *>(previous))
143                         multiple_definition(format("'%s'", iface.name), iface, *previous);
144         }
145         else
146                 record_definition(iface.name, iface);
147
148         if(!iface.instance_name.empty())
149                 check_definition(iface.instance_name, iface);
150
151         SetFlag set_anon(anonymous_block, iface.instance_name.empty());
152         TraversingVisitor::visit(iface);
153 }
154
155 void DeclarationValidator::visit(FunctionDeclaration &func)
156 {
157         if(Statement *previous = find_definition(func.name))
158                 if(!dynamic_cast<FunctionDeclaration *>(previous))
159                         multiple_definition(format("'%s'", func.name), func, *previous);
160
161         if(func.definition==&func)
162                 check_definition(func.name, func);
163         TraversingVisitor::visit(func);
164 }
165
166
167 void ReferenceValidator::visit(BasicTypeDeclaration &type)
168 {
169         if(!type.base.empty() && !type.base_type)
170                 error(type, format("Use of undeclared type '%s'", type.base));
171 }
172
173 void ReferenceValidator::visit(ImageTypeDeclaration &type)
174 {
175         if(!type.base.empty() && !type.base_type)
176                 error(type, format("Use of undeclared type '%s'", type.base));
177 }
178
179 void ReferenceValidator::visit(VariableReference &var)
180 {
181         if(!var.declaration)
182                 error(var, format("Use of undeclared variable '%s'", var.name));
183         else if(stage->type!=Stage::VERTEX && var.declaration->interface=="in" && !var.declaration->linked_declaration)
184                 error(var, format("Use of unlinked input variable '%s'", var.name));
185 }
186
187 void ReferenceValidator::visit(InterfaceBlockReference &iface)
188 {
189         /* An interface block reference without a declaration should be impossible
190         since references are generated based on existing declarations. */
191         if(!iface.declaration)
192                 error(iface, format("Use of undeclared interface block '%s'", iface.name));
193         else if(stage->type!=Stage::VERTEX && iface.declaration->interface=="in" && !iface.declaration->linked_block)
194                 error(iface, format("Use of unlinked input block '%s'", iface.name));
195 }
196
197 void ReferenceValidator::visit(VariableDeclaration &var)
198 {
199         if(!var.type_declaration)
200                 error(var, format("Use of undeclared type '%s'", var.type));
201         TraversingVisitor::visit(var);
202 }
203
204 void ReferenceValidator::visit(FunctionDeclaration &func)
205 {
206         if(!func.return_type_declaration)
207                 error(func, format("Use of undeclared type '%s'", func.return_type));
208         TraversingVisitor::visit(func);
209 }
210
211 } // namespace SL
212 } // namespace GL
213 } // namespace Msp