diff --git a/src/parser/cxx/binder.cc b/src/parser/cxx/binder.cc index d475ce70..7ec35e08 100644 --- a/src/parser/cxx/binder.cc +++ b/src/parser/cxx/binder.cc @@ -22,6 +22,7 @@ // cxx #include +#include #include #include #include @@ -551,6 +552,47 @@ void Binder::complete(LambdaExpressionAST* ast) { auto parentScope = ast->symbol->enclosingScope(); parentScope->addSymbol(ast->symbol); + + const Type* returnType = control()->getAutoType(); + std::vector parameterTypes; + bool isVariadic = false; + + if (auto params = ast->parameterDeclarationClause) { + for (auto it = params->parameterDeclarationList; it; it = it->next) { + auto paramType = it->value->type; + + if (control()->is_void(paramType)) { + continue; + } + + parameterTypes.push_back(paramType); + } + + isVariadic = params->isVariadic; + } + + bool isNoexcept = false; + + if (auto noexceptSpec = + ast_cast(ast->exceptionSpecifier)) { + if (!noexceptSpec->expression) { + isNoexcept = true; + } else { + ASTInterpreter sem{unit_}; + auto value = sem.evaluate(noexceptSpec->expression); + if (value.has_value()) { + isNoexcept = sem.toBool(*value).value_or(false); + } + } + } + + if (ast->trailingReturnType && ast->trailingReturnType->typeId) { + returnType = ast->trailingReturnType->typeId->type; + } + + auto type = control()->getFunctionType(returnType, std::move(parameterTypes), + isVariadic, {}, {}, isNoexcept); + ast->symbol->setType(type); } void Binder::bind(ParameterDeclarationClauseAST* ast) { @@ -600,14 +642,6 @@ auto Binder::declareFunction(DeclaratorAST* declarator, const Decl& decl) auto functionSymbol = control()->newFunctionSymbol(scope(), decl.location()); - // todo: scope chain fixup should be handled elsewhere, not here. - if (auto proto = getFunctionPrototype(declarator)) { - if (proto->parameterDeclarationClause) { - proto->parameterDeclarationClause->functionParametersSymbol->scope() - ->setParent(functionSymbol->scope()); - } - } - if (is_parsing_c()) { functionSymbol->setHasCxxLinkage(false); } diff --git a/src/parser/cxx/scope.cc b/src/parser/cxx/scope.cc index e22b6834..67a68a43 100644 --- a/src/parser/cxx/scope.cc +++ b/src/parser/cxx/scope.cc @@ -111,6 +111,13 @@ void Scope::addSymbol(Symbol* symbol) { } } + if (auto params = symbol_cast(symbol); + params && owner_) { + if (owner_->isFunction() || owner_->isLambda()) { + params->scope()->setParent(this); + } + } + symbol->setEnclosingScope(this); symbols_.push_back(symbol); diff --git a/src/parser/cxx/type_checker.cc b/src/parser/cxx/type_checker.cc index 4ba75023..9df595be 100644 --- a/src/parser/cxx/type_checker.cc +++ b/src/parser/cxx/type_checker.cc @@ -2264,18 +2264,13 @@ auto TypeChecker::Visitor::check_pseudo_destructor_access( void TypeChecker::checkReturnStatement(ReturnStatementAST* ast) { const Type* targetType = nullptr; for (auto current = scope_; current; current = current->parent()) { - if (auto function = symbol_cast(current->owner())) { - if (auto functionType = type_cast(function->type())) { - targetType = functionType->returnType(); - } - break; - } - - if (auto lambda = symbol_cast(current->owner())) { - if (auto functionType = type_cast(lambda->type())) { + auto owner = current->owner(); + if (!owner) continue; + if (owner->isFunction() || owner->isLambda()) { + if (auto functionType = type_cast(owner->type())) { targetType = functionType->returnType(); + break; } - break; } }