mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-29 19:45:01 +02:00
Declarator ambiguity with initializer, bug 267184.
This commit is contained in:
parent
e0124cd03d
commit
935de12ddc
8 changed files with 111 additions and 32 deletions
|
@ -102,6 +102,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPMember;
|
|||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespace;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespaceAlias;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPParameter;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPPointerToMemberType;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPReferenceType;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPUsingDeclaration;
|
||||
|
@ -6943,4 +6944,44 @@ public class AST2CPPTests extends AST2BaseTest {
|
|||
final String code = getAboveComment();
|
||||
parseAndCheckBindings(code, ParserLanguage.CPP);
|
||||
}
|
||||
|
||||
// void f(char *(names[2])= 0);
|
||||
// void f2(const char *(n[])) {
|
||||
// if (n && 1){}
|
||||
// }
|
||||
public void testPointerToArrayWithDefaultVal_267184() throws Exception {
|
||||
final String code = getAboveComment();
|
||||
BindingAssertionHelper ba= new BindingAssertionHelper(code, true);
|
||||
ICPPParameter p= ba.assertNonProblem("names", 5);
|
||||
assertTrue(p.hasDefaultValue());
|
||||
IType t= p.getType();
|
||||
assertInstance(t, IPointerType.class); // parameter of type array is converted to pointer
|
||||
t= ((IPointerType) t).getType();
|
||||
assertInstance(t, IPointerType.class);
|
||||
t= ((IPointerType) t).getType();
|
||||
assertInstance(t, IBasicType.class);
|
||||
|
||||
parseAndCheckBindings(code, ParserLanguage.CPP);
|
||||
}
|
||||
|
||||
// class X {
|
||||
// virtual void pv() = 0;
|
||||
// void (*ptrToFunc) ()= 0;
|
||||
// };
|
||||
public void testPureVirtualVsInitDeclarator_267184() throws Exception {
|
||||
final String code = getAboveComment();
|
||||
IASTTranslationUnit tu= parseAndCheckBindings(code, ParserLanguage.CPP);
|
||||
ICPPASTCompositeTypeSpecifier ct= getCompositeType(tu, 0);
|
||||
IASTSimpleDeclaration sdecl= getDeclaration(ct, 0);
|
||||
ICPPASTFunctionDeclarator dtor= (ICPPASTFunctionDeclarator) sdecl.getDeclarators()[0];
|
||||
assertTrue(dtor.isPureVirtual());
|
||||
assertNull(dtor.getInitializer());
|
||||
|
||||
sdecl= getDeclaration(ct, 1);
|
||||
dtor= (ICPPASTFunctionDeclarator) sdecl.getDeclarators()[0];
|
||||
assertFalse(dtor.isPureVirtual());
|
||||
assertNotNull(dtor.getInitializer());
|
||||
|
||||
parseAndCheckBindings(code, ParserLanguage.CPP);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -65,6 +65,9 @@ public abstract class ASTAmbiguousNode extends ASTNode {
|
|||
protected void beforeResolution() {
|
||||
}
|
||||
|
||||
protected void afterResolution(ASTVisitor resolver, IASTNode best) {
|
||||
}
|
||||
|
||||
public IASTNode resolveAmbiguity(ASTVisitor resolver) {
|
||||
beforeResolution();
|
||||
final IASTAmbiguityParent owner= (IASTAmbiguityParent) getParent();
|
||||
|
@ -127,6 +130,7 @@ public abstract class ASTAmbiguousNode extends ASTNode {
|
|||
if (nodeToReplace != bestAlternative) {
|
||||
owner.replace(nodeToReplace, bestAlternative);
|
||||
}
|
||||
afterResolution(resolver, bestAlternative);
|
||||
return bestAlternative;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -488,10 +488,14 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
|||
|
||||
protected final void adjustLength(IASTNode n, IASTNode endNode) {
|
||||
final int endOffset= calculateEndOffset(endNode);
|
||||
final ASTNode node = (ASTNode) n;
|
||||
node.setLength(endOffset-node.getOffset());
|
||||
adjustEndOffset(n, endOffset);
|
||||
}
|
||||
|
||||
protected final void adjustEndOffset(IASTNode n, final int endOffset) {
|
||||
final ASTNode node = (ASTNode) n;
|
||||
node.setLength(endOffset-node.getOffset());
|
||||
}
|
||||
|
||||
protected final int getEndOffset() {
|
||||
if (lastTokenFromScanner == null)
|
||||
return 0;
|
||||
|
@ -1628,7 +1632,7 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
|||
} catch (FoundAggregateInitializer lie) {
|
||||
if (declSpec == null)
|
||||
declSpec= lie.fDeclSpec;
|
||||
dtor= addInitializer(lie);
|
||||
dtor= addInitializer(lie, DeclarationOptions.FUNCTION_STYLE_ASM);
|
||||
}
|
||||
|
||||
if (LT(1) != IToken.tLBRACE)
|
||||
|
@ -1649,7 +1653,7 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
|||
return funcDefinition;
|
||||
}
|
||||
|
||||
protected abstract IASTDeclarator addInitializer(FoundAggregateInitializer lie) throws EndOfFileException;
|
||||
protected abstract IASTDeclarator addInitializer(FoundAggregateInitializer lie, DeclarationOptions option) throws EndOfFileException;
|
||||
|
||||
protected IToken asmExpression(StringBuilder content) throws EndOfFileException, BacktrackException {
|
||||
IToken t= consume(IToken.tLPAREN);
|
||||
|
|
|
@ -29,7 +29,7 @@ public class DeclarationOptions {
|
|||
GLOBAL= new DeclarationOptions(ALLOW_EMPTY_SPECIFIER | ALLOW_CONSTRUCTOR_INITIALIZER),
|
||||
FUNCTION_STYLE_ASM= new DeclarationOptions(ALLOW_EMPTY_SPECIFIER | NO_INITIALIZER),
|
||||
C_MEMBER= new DeclarationOptions(ALLOW_BITFIELD | ALLOW_ABSTRACT),
|
||||
CPP_MEMBER= new DeclarationOptions(ALLOW_EMPTY_SPECIFIER | ALLOW_BITFIELD | ALLOW_CONSTRUCTOR_INITIALIZER),
|
||||
CPP_MEMBER= new DeclarationOptions(ALLOW_EMPTY_SPECIFIER | ALLOW_BITFIELD),
|
||||
LOCAL= new DeclarationOptions(ALLOW_CONSTRUCTOR_INITIALIZER),
|
||||
PARAMETER= new DeclarationOptions(ALLOW_ABSTRACT),
|
||||
TYPEID= new DeclarationOptions(REQUIRE_ABSTRACT | NO_INITIALIZER),
|
||||
|
|
|
@ -338,7 +338,7 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
|
|||
// scalability: don't keep references to tokens, initializer may be large
|
||||
declarationMark= null;
|
||||
markBeforDtor= null;
|
||||
dtor= addInitializer(lie);
|
||||
dtor= addInitializer(lie, declOption);
|
||||
} catch (FoundDeclaratorException e) {
|
||||
if (e.altSpec != null) {
|
||||
declSpec= e.altSpec;
|
||||
|
@ -371,7 +371,7 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
|
|||
// scalability: don't keep references to tokens, initializer may be large
|
||||
declarationMark= null;
|
||||
markBeforDtor= null;
|
||||
dtor= addInitializer(e);
|
||||
dtor= addInitializer(e, declOption);
|
||||
}
|
||||
declarators= (IASTDeclarator[]) ArrayUtil.append( IASTDeclarator.class, declarators, dtor);
|
||||
}
|
||||
|
@ -1274,7 +1274,7 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected IASTDeclarator addInitializer(FoundAggregateInitializer e) throws EndOfFileException {
|
||||
protected IASTDeclarator addInitializer(FoundAggregateInitializer e, DeclarationOptions options) throws EndOfFileException {
|
||||
final IASTDeclarator d = e.fDeclarator;
|
||||
try {
|
||||
IASTInitializer i = optionalCInitializer();
|
||||
|
|
|
@ -24,6 +24,7 @@ import org.eclipse.cdt.core.dom.ast.IASTExpression;
|
|||
import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTInitializer;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTParameterDeclaration;
|
||||
import org.eclipse.cdt.core.dom.ast.IScope;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.ASTAmbiguousNode;
|
||||
|
@ -70,6 +71,10 @@ final class CPPASTAmbiguityResolver extends ASTVisitor {
|
|||
fRepopulate.add((IASTDeclaration) node);
|
||||
break;
|
||||
}
|
||||
if (node instanceof IASTParameterDeclaration) {
|
||||
repopulateScope((IASTParameterDeclaration) node);
|
||||
break;
|
||||
}
|
||||
if (node instanceof IASTExpression) {
|
||||
break;
|
||||
}
|
||||
|
@ -172,6 +177,12 @@ final class CPPASTAmbiguityResolver extends ASTVisitor {
|
|||
CPPSemantics.populateCache((ICPPASTInternalScope) scope, declaration);
|
||||
}
|
||||
}
|
||||
private void repopulateScope(IASTParameterDeclaration declaration) {
|
||||
IScope scope= CPPVisitor.getContainingNonTemplateScope(declaration);
|
||||
if (scope instanceof ICPPASTInternalScope) {
|
||||
CPPSemantics.populateCache((ICPPASTInternalScope) scope, declaration);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int visit(IASTInitializer initializer) {
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.cdt.internal.core.dom.parser.cpp;
|
||||
|
||||
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTDeclarator;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTInitializer;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTName;
|
||||
|
@ -31,6 +32,7 @@ public class CPPASTAmbiguousDeclarator extends ASTAmbiguousNode implements IASTA
|
|||
|
||||
private IASTDeclarator[] dtors = new IASTDeclarator[2];
|
||||
private int dtorPos=-1;
|
||||
private IASTInitializer fInitializer;
|
||||
|
||||
|
||||
public CPPASTAmbiguousDeclarator(IASTDeclarator... decls) {
|
||||
|
@ -49,8 +51,18 @@ public class CPPASTAmbiguousDeclarator extends ASTAmbiguousNode implements IASTA
|
|||
((ICPPASTInternalScope) scope).populateCache();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void afterResolution(ASTVisitor resolver, IASTNode best) {
|
||||
// if we have an initializer it needs to be added to the chosen alternative.
|
||||
// we also need to resolve ambiguities in the initializer.
|
||||
if (fInitializer != null) {
|
||||
((IASTDeclarator) best).setInitializer(fInitializer);
|
||||
fInitializer.accept(resolver);
|
||||
}
|
||||
}
|
||||
|
||||
public IASTDeclarator copy() {
|
||||
public IASTDeclarator copy() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
|
@ -74,7 +86,7 @@ public class CPPASTAmbiguousDeclarator extends ASTAmbiguousNode implements IASTA
|
|||
}
|
||||
|
||||
public IASTInitializer getInitializer() {
|
||||
return dtors[0].getInitializer();
|
||||
return fInitializer;
|
||||
}
|
||||
|
||||
public IASTName getName() {
|
||||
|
@ -99,8 +111,8 @@ public class CPPASTAmbiguousDeclarator extends ASTAmbiguousNode implements IASTA
|
|||
}
|
||||
|
||||
public void setInitializer(IASTInitializer initializer) {
|
||||
assertNotFrozen();
|
||||
Assert.isLegal(false);
|
||||
// store the initializer until the ambiguity is resolved
|
||||
fInitializer= initializer;
|
||||
}
|
||||
|
||||
public void setName(IASTName name) {
|
||||
|
|
|
@ -1717,7 +1717,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
// scalability: don't keep references to tokens, initializer may be large
|
||||
declarationMark= null;
|
||||
markBeforDtor= null;
|
||||
dtor= addInitializer(lie);
|
||||
dtor= addInitializer(lie, declOption);
|
||||
} catch (FoundDeclaratorException e) {
|
||||
declSpec= (ICPPASTDeclSpecifier) e.declSpec;
|
||||
dtor= e.declarator;
|
||||
|
@ -1743,7 +1743,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
// scalability: don't keep references to tokens, initializer may be large
|
||||
declarationMark= null;
|
||||
markBeforDtor= null;
|
||||
dtor= addInitializer(e);
|
||||
dtor= addInitializer(e, declOption);
|
||||
}
|
||||
declarators = (IASTDeclarator[]) ArrayUtil.append(IASTDeclarator.class, declarators, dtor);
|
||||
}
|
||||
|
@ -1944,7 +1944,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
} catch (FoundAggregateInitializer lie) {
|
||||
if (declSpec == null)
|
||||
declSpec= lie.fDeclSpec;
|
||||
declarator= addInitializer(lie);
|
||||
declarator= addInitializer(lie, DeclarationOptions.PARAMETER);
|
||||
}
|
||||
|
||||
final ICPPASTParameterDeclaration parm = nodeFactory.newParameterDeclaration(declSpec, declarator);
|
||||
|
@ -2555,7 +2555,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
if (LTcatchEOF(1) == IToken.tASSIGN && LTcatchEOF(2) == IToken.tLBRACE)
|
||||
throw new FoundAggregateInitializer(dtor);
|
||||
|
||||
IASTInitializer initializer= optionalCPPInitializer(dtor);
|
||||
IASTInitializer initializer= optionalCPPInitializer(dtor, option);
|
||||
if (initializer != null) {
|
||||
dtor.setInitializer(initializer);
|
||||
adjustLength(dtor, initializer);
|
||||
|
@ -2565,10 +2565,10 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected IASTDeclarator addInitializer(FoundAggregateInitializer e) throws EndOfFileException {
|
||||
protected IASTDeclarator addInitializer(FoundAggregateInitializer e, DeclarationOptions option) throws EndOfFileException {
|
||||
final IASTDeclarator d = e.fDeclarator;
|
||||
try {
|
||||
IASTInitializer i = optionalCPPInitializer(e.fDeclarator);
|
||||
IASTInitializer i = optionalCPPInitializer(e.fDeclarator, option);
|
||||
if (i != null) {
|
||||
d.setInitializer(i);
|
||||
((ASTNode) d).setLength(calculateEndOffset(i) - ((ASTNode) d).getOffset());
|
||||
|
@ -2579,18 +2579,35 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
return d;
|
||||
}
|
||||
|
||||
protected IASTInitializer optionalCPPInitializer(IASTDeclarator d) throws EndOfFileException, BacktrackException {
|
||||
protected IASTInitializer optionalCPPInitializer(IASTDeclarator d, DeclarationOptions option) throws EndOfFileException, BacktrackException {
|
||||
// handle initializer
|
||||
final int lt1= LTcatchEOF(1);
|
||||
if (lt1 == IToken.tASSIGN) {
|
||||
consume();
|
||||
// for member functions we need to consider pure-virtual syntax
|
||||
if (option == DeclarationOptions.CPP_MEMBER && LTcatchEOF(1) == IToken.tINTEGER) {
|
||||
IASTDeclarator relDtor = ASTQueries.findTypeRelevantDeclarator(d);
|
||||
// note the declarator for a member function cannot be ambiguous because it cannot be abstract
|
||||
if (relDtor instanceof ICPPASTFunctionDeclarator) {
|
||||
// check for pure virtual
|
||||
IToken t = consume();
|
||||
char[] image = t.getCharImage();
|
||||
if (image.length != 1 || image[0] != '0') {
|
||||
throwBacktrack(t);
|
||||
}
|
||||
|
||||
((ICPPASTFunctionDeclarator) relDtor).setPureVirtual(true);
|
||||
adjustEndOffset(d, t.getEndOffset()); // we can only adjust the offset of the outermost dtor.
|
||||
return null;
|
||||
}
|
||||
}
|
||||
try {
|
||||
return initializerClause(false);
|
||||
} catch (EndOfFileException eof) {
|
||||
failParse();
|
||||
throw eof;
|
||||
}
|
||||
} else if (lt1 == IToken.tLPAREN) {
|
||||
} else if (option.fAllowConstructorInitializer && lt1 == IToken.tLPAREN) {
|
||||
if (d instanceof IASTFunctionDeclarator && d.getNestedDeclarator() == null) {
|
||||
// constructor initializer doesn't make sense for a function
|
||||
// declarator,
|
||||
|
@ -3080,17 +3097,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
__attribute_decl_seq(supportAttributeSpecifiers, false);
|
||||
}
|
||||
|
||||
// pure virtual
|
||||
if (LT(1) == IToken.tASSIGN && LT(2) == IToken.tINTEGER) {
|
||||
char[] image = LA(2).getCharImage();
|
||||
if (image.length == 1 && image[0] == '0') {
|
||||
consume(); // tASSIGN
|
||||
endOffset= consume().getEndOffset(); // tINTEGER
|
||||
fc.setPureVirtual(true);
|
||||
}
|
||||
}
|
||||
|
||||
((ASTNode) fc).setOffsetAndLength(startOffset, endOffset-startOffset);
|
||||
setRange(fc, startOffset, endOffset);
|
||||
return fc;
|
||||
}
|
||||
|
||||
|
@ -3345,7 +3352,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
} catch (FoundAggregateInitializer lie) {
|
||||
if (declSpec == null)
|
||||
declSpec= lie.fDeclSpec;
|
||||
declarator= addInitializer(lie);
|
||||
declarator= addInitializer(lie, options);
|
||||
}
|
||||
|
||||
final int endOffset = figureEndOffset(declSpec, declarator);
|
||||
|
|
Loading…
Add table
Reference in a new issue