1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-21 21:52:10 +02:00

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.
This commit is contained in:
Igor V. Kovalenko 2023-03-28 23:27:57 +03:00 committed by Jonah Graham
parent f768aed976
commit 6cf3e03c35
4 changed files with 42 additions and 1 deletions

View file

@ -11559,4 +11559,14 @@ public class AST2TemplateTests extends AST2CPPTestBase {
public void testResolveFunctionTemplateInDeferredBaseArg() throws Exception {
parseAndCheckBindings();
}
// template<typename T>
// struct S {
// S(T) {};
// };
//
// S<int> s(1);
public void testRecognizeConstructorWithSemicolonAfterBody() throws Exception {
parseAndCheckImplicitNameBindings();
}
}

View file

@ -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<typename T> 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);

View file

@ -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;
}
}

View file

@ -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
*/