1 #include <msp/core/raii.h>
2 #include <msp/strings/format.h>
11 Validator::Validator():
15 void Validator::diagnose(Statement *statement, Diagnostic::Severity severity, const string &message)
18 diag.severity = severity;
21 diag.source = statement->source;
22 diag.line = statement->line;
24 diag.message = message;
25 stage->diagnostics.push_back(diag);
29 DeclarationValidator::DeclarationValidator():
30 anonymous_block(false)
33 void DeclarationValidator::multiple_definition(const string &name, Statement &statement, Statement &previous)
35 error(&statement, format("Multiple definition of %s", name));
36 diagnose(&previous, Diagnostic::INFO, "Previous definition is here");
39 Statement *DeclarationValidator::find_definition(const string &name)
41 BlockDeclarationMap *decls = &declarations[current_block];
42 BlockDeclarationMap::const_iterator i = decls->find(name);
43 if(i==decls->end() && anonymous_block)
45 decls = &declarations[current_block->parent];
46 i = decls->find(name);
48 return (i!=decls->end() ? i->second : 0);
51 void DeclarationValidator::check_definition(const string &name, Statement &statement)
53 if(Statement *previous = find_definition(name))
54 multiple_definition(format("'%s'", name), statement, *previous);
56 record_definition(name, statement);
59 void DeclarationValidator::record_definition(const string &name, Statement &statement)
61 declarations[current_block].insert(make_pair(name, &statement));
63 declarations[current_block->parent].insert(make_pair(name, &statement));
66 void DeclarationValidator::visit(VariableDeclaration &var)
68 check_definition(var.name, var);
69 TraversingVisitor::visit(var);
72 void DeclarationValidator::visit(InterfaceBlock &iface)
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);
79 interface_blocks.insert(make_pair(key, &iface));
81 if(Statement *previous = find_definition(iface.name))
83 if(!dynamic_cast<InterfaceBlock *>(previous))
84 multiple_definition(format("'%s'", iface.name), iface, *previous);
87 record_definition(iface.name, iface);
89 if(!iface.instance_name.empty())
90 check_definition(iface.instance_name, iface);
92 SetFlag set_anon(anonymous_block, iface.instance_name.empty());
93 TraversingVisitor::visit(iface);
96 void DeclarationValidator::visit(FunctionDeclaration &func)
98 if(func.definition==&func)
99 check_definition(func.name, func);
100 TraversingVisitor::visit(func);