diff --git a/source/parsing/Parser_members.cpp b/source/parsing/Parser_members.cpp index e5a0457a7..59b8f7fe6 100644 --- a/source/parsing/Parser_members.cpp +++ b/source/parsing/Parser_members.cpp @@ -682,8 +682,8 @@ FunctionPrototypeSyntax& Parser::parseFunctionPrototype(SyntaxKind parentKind, else keyword = expect(TokenKind::FunctionKeyword); - auto specifiers = parseClassSpecifierList( - options.has(FunctionOptions::AllowOverrideSpecifiers)); + const bool allowSpecifiers = options.has(FunctionOptions::AllowOverrideSpecifiers); + auto specifiers = parseClassSpecifierList(allowSpecifiers); auto lifetime = parseLifetime(); if (lifetime && options.has(FunctionOptions::IsPrototype)) @@ -728,15 +728,20 @@ FunctionPrototypeSyntax& Parser::parseFunctionPrototype(SyntaxKind parentKind, else if (constructor) addDiag(diag::TaskConstructor, keyword.location()) << name.sourceRange(); } - else if (constructor && returnType->kind != SyntaxKind::ImplicitType) { - addDiag(diag::ConstructorReturnType, name.getFirstToken().location()) - << returnType->sourceRange(); - } - else if (constructor && name.kind != SyntaxKind::ScopedName && - parentKind != SyntaxKind::ClassDeclaration) { - addDiag(diag::ConstructorOutsideClass, keyword.location()) << name.sourceRange(); + else if (constructor) { + if (returnType->kind != SyntaxKind::ImplicitType) { + addDiag(diag::ConstructorReturnType, name.getFirstToken().location()) + << returnType->sourceRange(); + } + else if (name.kind != SyntaxKind::ScopedName && + parentKind != SyntaxKind::ClassDeclaration) { + addDiag(diag::ConstructorOutsideClass, keyword.location()) << name.sourceRange(); + } + else if (allowSpecifiers && !specifiers.empty()) { + addDiag(diag::SpecifiersNotAllowed, specifiers[0]->sourceRange()) << name.sourceRange(); + } } - else if (!constructor && !options.has(FunctionOptions::AllowImplicitReturn) && + else if (!options.has(FunctionOptions::AllowImplicitReturn) && returnType->kind == SyntaxKind::ImplicitType) { addDiag(diag::ImplicitNotAllowed, name.getFirstToken().location()); } diff --git a/tests/unittests/parsing/MemberParsingTests.cpp b/tests/unittests/parsing/MemberParsingTests.cpp index e08ce7628..7e7c539cf 100644 --- a/tests/unittests/parsing/MemberParsingTests.cpp +++ b/tests/unittests/parsing/MemberParsingTests.cpp @@ -1508,3 +1508,17 @@ program A ; final randcase 0 : matches A = # 0 0 ; endcase endprogram REQUIRE(diagnostics.size() == 16); } + +TEST_CASE("Override specifiers on class constructor") { + auto& text = R"( +class cls; + function :initial :final new(); + endfunction +endclass +)"; + + parseCompilationUnit(text, LanguageVersion::v1800_2023); + + REQUIRE(diagnostics.size() == 1); + CHECK(diagnostics[0].code == diag::SpecifiersNotAllowed); +}