X-Git-Url: http://git.tdb.fi/?p=libs%2Fgl.git;a=blobdiff_plain;f=source%2Fglsl%2Fvalidate.cpp;h=91d1de991515dc74dbb359d0385a0429ef855803;hp=c4e0a9bda8aa6b21d80fca7e92a5b393217d4a53;hb=7d66c70e15b84cbaf6b1973db07629f5bd3e5cdf;hpb=f526938b407e061c7424adedc34af4d1ff687f90 diff --git a/source/glsl/validate.cpp b/source/glsl/validate.cpp index c4e0a9bd..91d1de99 100644 --- a/source/glsl/validate.cpp +++ b/source/glsl/validate.cpp @@ -11,17 +11,29 @@ namespace GL { namespace SL { Validator::Validator(): - stage(0) + stage(0), + last_provoker(0) { } -void Validator::diagnose(Node &node, Diagnostic::Severity severity, const string &message) +void Validator::diagnose(Node &node, Node &provoking_node, Diagnostic::Severity severity, const string &message) { Diagnostic diag; diag.severity = severity; diag.source = node.source; diag.line = node.line; + diag.provoking_source = provoking_node.source; + diag.provoking_line = provoking_node.line; diag.message = message; stage->diagnostics.push_back(diag); + + last_provoker = &provoking_node; +} + +void Validator::add_info(Node &node, const string &message) +{ + if(!last_provoker) + throw logic_error("Tried to add info without a previous provoker"); + diagnose(node, *last_provoker, Diagnostic::INFO, message); } @@ -83,7 +95,7 @@ DeclarationValidator::DeclarationValidator(): void DeclarationValidator::multiple_definition(const string &name, Statement &statement, Statement &previous) { error(statement, format("Multiple definition of %s", name)); - diagnose(previous, Diagnostic::INFO, "Previous definition is here"); + add_info(previous, "Previous definition is here"); } Statement *DeclarationValidator::find_definition(const string &name) @@ -161,17 +173,28 @@ void DeclarationValidator::visit(InterfaceBlock &iface) void DeclarationValidator::visit(FunctionDeclaration &func) { + string key = func.name+func.signature; + map::const_iterator i = overloaded_functions.find(key); + if(i==overloaded_functions.end()) + overloaded_functions.insert(make_pair(key, &func)); + else if(func.return_type_declaration && i->second->return_type_declaration!=func.return_type_declaration) + { + error(func, format("Conflicting return type '%s' for function '%s'", func.return_type_declaration->name, func.name)); + if(i->second->return_type_declaration) + add_info(*i->second, format("Previously declared as returning '%s'", i->second->return_type_declaration->name)); + } + if(Statement *previous = find_definition(func.name)) { - FunctionDeclaration *prev_func = dynamic_cast(previous); - if(prev_func && prev_func->definition==&func) - declarations[current_block][func.name] = &func; - else + if(!dynamic_cast(previous)) multiple_definition(format("'%s'", func.name), func, *previous); } else record_definition(func.name, func); + if(func.definition==&func) + check_definition(func.name+func.signature, func); + TraversingVisitor::visit(func); } @@ -196,6 +219,13 @@ void ReferenceValidator::visit(VariableReference &var) error(var, format("Use of unlinked input variable '%s'", var.name)); } +void ReferenceValidator::visit(MemberAccess &memacc) +{ + if(memacc.left->type && !memacc.declaration) + error(memacc, format("Use of undeclared member '%s'", memacc.member)); + TraversingVisitor::visit(memacc); +} + void ReferenceValidator::visit(InterfaceBlockReference &iface) { /* An interface block reference without a declaration should be impossible