]> git.tdb.fi Git - libs/gl.git/blob - source/glsl/validate.cpp
Check for function declaration conflicting with something else
[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 void DeclarationValidator::multiple_definition(const string &name, Statement &statement, Statement &previous)
34 {
35         error(&statement, format("Multiple definition of %s", name));
36         diagnose(&previous, Diagnostic::INFO, "Previous definition is here");
37 }
38
39 Statement *DeclarationValidator::find_definition(const string &name)
40 {
41         BlockDeclarationMap *decls = &declarations[current_block];
42         BlockDeclarationMap::const_iterator i = decls->find(name);
43         if(i==decls->end() && anonymous_block)
44         {
45                 decls = &declarations[current_block->parent];
46                 i = decls->find(name);
47         }
48         return (i!=decls->end() ? i->second : 0);
49 }
50
51 void DeclarationValidator::check_definition(const string &name, Statement &statement)
52 {
53         if(Statement *previous = find_definition(name))
54                 multiple_definition(format("'%s'", name), statement, *previous);
55         else
56                 record_definition(name, statement);
57 }
58
59 void DeclarationValidator::record_definition(const string &name, Statement &statement)
60 {
61         declarations[current_block].insert(make_pair(name, &statement));
62         if(anonymous_block)
63                 declarations[current_block->parent].insert(make_pair(name, &statement));
64 }
65
66 void DeclarationValidator::visit(VariableDeclaration &var)
67 {
68         check_definition(var.name, var);
69         TraversingVisitor::visit(var);
70 }
71
72 void DeclarationValidator::visit(InterfaceBlock &iface)
73 {
74         string key = iface.interface+iface.name;
75         map<string, InterfaceBlock *>::const_iterator i = interface_blocks.find(key);
76         if(i!=interface_blocks.end())
77                 multiple_definition(format("interface block '%s %s'", iface.interface, iface.name), iface, *i->second);
78         else
79                 interface_blocks.insert(make_pair(key, &iface));
80
81         if(Statement *previous = find_definition(iface.name))
82         {
83                 if(!dynamic_cast<InterfaceBlock *>(previous))
84                         multiple_definition(format("'%s'", iface.name), iface, *previous);
85         }
86         else
87                 record_definition(iface.name, iface);
88
89         if(!iface.instance_name.empty())
90                 check_definition(iface.instance_name, iface);
91
92         SetFlag set_anon(anonymous_block, iface.instance_name.empty());
93         TraversingVisitor::visit(iface);
94 }
95
96 void DeclarationValidator::visit(FunctionDeclaration &func)
97 {
98         if(Statement *previous = find_definition(func.name))
99                 if(!dynamic_cast<FunctionDeclaration *>(previous))
100                         multiple_definition(format("'%s'", func.name), func, *previous);
101
102         if(func.definition==&func)
103                 check_definition(func.name, func);
104         TraversingVisitor::visit(func);
105 }
106
107 } // namespace SL
108 } // namespace GL
109 } // namespace Msp