From 86c47022e49776915684434ff8046a321cc837be Mon Sep 17 00:00:00 2001 From: "Igor V. Kovalenko" Date: Tue, 28 Mar 2023 23:27:57 +0300 Subject: [PATCH] Allow disambiguating class constructor definition followed by semicolon In this case member variable declaration would be longer (including trailing semicolon) but it is not valid since a class C shall not contain a non-static member of class C. --- .../parser/tests/ast2/AST2TemplateTests.java | 10 ++++++++++ .../dom/parser/AbstractGNUSourceCodeParser.java | 11 ++++++++++- .../core/dom/parser/c/GNUCSourceParser.java | 6 ++++++ .../core/dom/parser/cpp/GNUCPPSourceParser.java | 16 ++++++++++++++++ 4 files changed, 42 insertions(+), 1 deletion(-) diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java index 36503540caa..3ada7fabe19 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java @@ -11531,4 +11531,14 @@ public void testResolveFunctionTemplateInDeferredClassArg() throws Exception { public void testResolveFunctionTemplateInDeferredBaseArg() throws Exception { parseAndCheckBindings(); } + + // template + // struct S { + // S(T) {}; + // }; + // + // S s(1); + public void testRecognizeConstructorWithSemicolonAfterBody() throws Exception { + parseAndCheckImplicitNameBindings(); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/AbstractGNUSourceCodeParser.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/AbstractGNUSourceCodeParser.java index c346c8ca834..a781a7a0506 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/AbstractGNUSourceCodeParser.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/AbstractGNUSourceCodeParser.java @@ -1702,6 +1702,9 @@ protected boolean isAtStartOfStructuredBinding(IASTDeclSpecifier declSpecifier) && LTcatchEOF(expectedBracketOffset + 1) == IToken.tIDENTIFIER; } + protected abstract boolean maybeDeclaresNonStaticMemberOfSameClass(final DeclarationOptions option, + final IASTDeclSpecifier declSpec, final IASTDeclarator dtor); + /** * Parses for two alternatives of a declspec sequence followed by a initDeclarator. * A second alternative is accepted only, if it ends at the same point of the first alternative. Otherwise the @@ -1770,10 +1773,16 @@ protected Decl declSpecifierSequence_initDeclarator(final DeclarationOptions opt return result.set(declspec1, dtor1, dtorMark1); } + // [class.mem] "... In particluar, a class C shall not contain a non-static member of class C" + // If type name in first variant matches current class name, disambiguate it later too; + // this allows to handle the following case where constructor declaration is shorter + // than variable declaration with initializer list + // template class S { S(T){}; } final IToken end2 = mark(); - if (end1 == end2) { + if (end1 == end2 || maybeDeclaresNonStaticMemberOfSameClass(option, declspec1, dtor1)) { return result.set(declspec1, dtor1, declspec2, dtor2); } + if (end1.getEndOffset() > end2.getEndOffset()) { backup(end1); return result.set(declspec1, dtor1, dtorMark1); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/GNUCSourceParser.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/GNUCSourceParser.java index bd63a89dfab..742941c363f 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/GNUCSourceParser.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/GNUCSourceParser.java @@ -2224,4 +2224,10 @@ protected IASTAlignmentSpecifier createAmbiguousAlignmentSpecifier(IASTAlignment IASTAlignmentSpecifier typeId) { return new CASTAmbiguousAlignmentSpecifier(expression, typeId); } + + @Override + protected boolean maybeDeclaresNonStaticMemberOfSameClass(final DeclarationOptions option, + final IASTDeclSpecifier declSpec, final IASTDeclarator dtor) { + return false; + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java index 9db8b3b5988..7a33935b514 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java @@ -4256,6 +4256,22 @@ protected IASTDeclarator initDeclarator(IASTDeclSpecifier declspec, DeclarationO return dtor; } + @Override + protected boolean maybeDeclaresNonStaticMemberOfSameClass(final DeclarationOptions option, + final IASTDeclSpecifier declSpec, final IASTDeclarator dtor) { + if (option == DeclarationOptions.CPP_MEMBER && currentClassName != null + && declSpec.getStorageClass() != IASTDeclSpecifier.sc_static && dtor != null + && dtor.getPointerOperators().length == 0 + && declSpec instanceof ICPPASTNamedTypeSpecifier namedTypeSpec) { + IASTName name = namedTypeSpec.getName(); + if (CharArrayUtils.equals(name.getLookupKey(), currentClassName)) { + return true; + } + } + + return false; + } + /** * Tries to detect illegal versions of declarations */