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 Statement *DeclarationValidator::find_definition(const string &name)
35 BlockDeclarationMap *decls = &declarations[current_block];
36 BlockDeclarationMap::const_iterator i = decls->find(name);
37 if(i==decls->end() && anonymous_block)
39 decls = &declarations[current_block->parent];
40 i = decls->find(name);
42 return (i!=decls->end() ? i->second : 0);
45 void DeclarationValidator::check_definition(const string &name, Statement &statement)
47 if(Statement *previous = find_definition(name))
49 error(&statement, format("Multiple definition of '%s'", name));
50 diagnose(previous, Diagnostic::INFO, "Previous definition is here");
54 declarations[current_block][name] = &statement;
56 declarations[current_block->parent][name] = &statement;
59 void DeclarationValidator::visit(VariableDeclaration &var)
61 check_definition(var.name, var);
62 TraversingVisitor::visit(var);
65 void DeclarationValidator::visit(InterfaceBlock &iface)
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);
74 void DeclarationValidator::visit(FunctionDeclaration &func)
76 if(func.definition==&func)
77 check_definition(func.name, func);
78 TraversingVisitor::visit(func);