TypeSpec ASTreturn_statement::typecheck (TypeSpec expected) { FunctionSymbol *myfunc = oslcompiler->current_function (); if (myfunc) { // If it's a user function (as opposed to a main shader body)... if (expr()) { // If we are returning a value, it must be assignable to the // kind of type the function actually returns. This check // will also catch returning a value from a void function. TypeSpec et = expr()->typecheck (myfunc->typespec()); if (! assignable (myfunc->typespec(), et)) { error ("Cannot return a '%s' from '%s %s()'", type_c_str(et), type_c_str(myfunc->typespec()), myfunc->name().c_str()); } } else { // If we are not returning a value, it must be a void function. if (! myfunc->typespec().is_void ()) error ("You must return a '%s' from function '%s'", type_c_str(myfunc->typespec()), myfunc->name().c_str()); } // If the function has other statements AFTER 'return', or if // the return statement is in a conditional, we'll need to // handle it specially when generating code. myfunc->complex_return (this->nextptr() != NULL || myfunc->nesting_level() > 0); } else { // We're not part of any user function, so this 'return' must // be from the main shader body. That's fine (it's equivalent // to calling exit()), but it can't return a value. if (expr()) error ("Cannot return a value from a shader body"); } return TypeSpec(); // TODO: what should be returned here? }
void SemanticAnalysis::visitNameProxy(NameProxy *proxy) { Symbol *binding = proxy->sym(); switch (binding->kind()) { case Symbol::kType: cc_.report(proxy->loc(), rmsg::cannot_use_type_as_value) << binding->asType()->type(); break; case Symbol::kConstant: { ConstantSymbol *sym = binding->toConstant(); proxy->setOutput(sym->type(), VK::rvalue); break; } case Symbol::kFunction: { FunctionSymbol *sym = binding->toFunction(); FunctionStatement *decl = sym->impl(); if (!decl) { cc_.report(proxy->loc(), rmsg::function_has_no_impl) << sym->name(); break; } if (!decl->type()) decl->setType(FunctionType::New(decl->signature())); // Function symbols are clvalues, since they are named. // :TODO: proxy->setOutput(decl->type(), VK::lvalue); break; } default: assert(false); } }