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 70682f4527c..6fd9a850378 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 @@ -11559,4 +11559,14 @@ public class AST2TemplateTests extends AST2CPPTestBase { 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 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser { && 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 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser { 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 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser { 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 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { 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 */