1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-06-08 02:06:01 +02:00

Ambiguity between constructor and field declaration, bug 269953.

This commit is contained in:
Markus Schorn 2009-07-14 15:22:46 +00:00
parent ba7561b70a
commit fc1bd1306d
11 changed files with 1163 additions and 980 deletions

View file

@ -2054,7 +2054,7 @@ public class AST2CPPSpecTest extends AST2SpecBaseTest {
// *pi, // *pi,
// f(), // f(),
// *fpi(int), // *fpi(int),
// (*pif)(const char*, const char*); // (*pif)(const char*, const char*),
// (*fpif(int))(int); // (*fpif(int))(int);
public void test8_3_5s9a() throws Exception { public void test8_3_5s9a() throws Exception {
parse(getAboveComment(), ParserLanguage.CPP, true, 0); parse(getAboveComment(), ParserLanguage.CPP, true, 0);

View file

@ -7195,4 +7195,46 @@ public class AST2CPPTests extends AST2BaseTest {
} }
// typedef int T;
// class C {
// C(T); // ctor
// C(s); // instance s;
// };
public void testDeclarationAmbiguity_Bug269953() throws Exception {
final String code = getAboveComment();
IASTTranslationUnit tu= parseAndCheckBindings(code, ParserLanguage.CPP);
ICPPASTCompositeTypeSpecifier ct= getCompositeType(tu, 1);
ICPPClassType c= (ICPPClassType) ct.getName().resolveBinding();
ICPPMethod[] methods= c.getDeclaredMethods();
assertEquals(1, methods.length);
assertEquals("C", methods[0].getName());
ICPPField[] fields= c.getDeclaredFields();
assertEquals(1, fields.length);
assertEquals("s", fields[0].getName());
}
// class C3 {
// C3(int);
// };
// typedef C3 T3;
// T3::C3(int) {
// }
public void testCTorWithTypedef_Bug269953() throws Exception {
final String code = getAboveComment();
parseAndCheckBindings(code, ParserLanguage.CPP);
}
// template<class T> class Compare {
// Compare();
// ~Compare();
// bool check;
// };
// typedef Compare<int> MY_COMPARE;
// template<> MY_COMPARE::Compare() {}
public void testTemplateCTorWithTypedef_Bug269953() throws Exception {
final String code = getAboveComment();
parseAndCheckBindings(code, ParserLanguage.CPP);
}
} }

View file

@ -33,6 +33,7 @@ import org.eclipse.cdt.core.dom.ast.IASTDeclarationStatement;
import org.eclipse.cdt.core.dom.ast.IASTDeclarator; import org.eclipse.cdt.core.dom.ast.IASTDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTDefaultStatement; import org.eclipse.cdt.core.dom.ast.IASTDefaultStatement;
import org.eclipse.cdt.core.dom.ast.IASTDoStatement; import org.eclipse.cdt.core.dom.ast.IASTDoStatement;
import org.eclipse.cdt.core.dom.ast.IASTElaboratedTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTEnumerationSpecifier; import org.eclipse.cdt.core.dom.ast.IASTEnumerationSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTExpression; import org.eclipse.cdt.core.dom.ast.IASTExpression;
import org.eclipse.cdt.core.dom.ast.IASTExpressionList; import org.eclipse.cdt.core.dom.ast.IASTExpressionList;
@ -93,21 +94,35 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
fDeclarator= d; fDeclarator= d;
} }
} }
protected static class FoundDeclaratorException extends Exception {
private static final long serialVersionUID = 0;
public IASTDeclSpecifier declSpec; protected static class Decl extends Exception {
public IASTDeclarator declarator; public Decl() {
}
public IASTDeclSpecifier altSpec; public IASTDeclSpecifier fDeclSpec1;
public IASTDeclarator altDeclarator; public IASTDeclSpecifier fDeclSpec2;
public IToken currToken; public IASTDeclarator fDtor1;
public IASTDeclarator fDtor2;
public IToken fDtorToken1;
public FoundDeclaratorException(IASTDeclarator d, IToken t) { public Decl set(IASTDeclSpecifier declspec, IASTDeclarator dtor, IToken dtorToken) {
this.declarator = d; fDeclSpec1= declspec;
this.currToken =t; fDtor1= dtor;
} fDtorToken1= dtorToken;
fDeclSpec2= null;
fDtor2= null;
return this;
}
public Decl set(IASTDeclSpecifier declspec1, IASTDeclarator dtor1, IASTDeclSpecifier declspec2, IASTDeclarator dtor2) {
fDeclSpec1= declspec1;
fDtor1= dtor1;
fDtorToken1= null;
fDeclSpec2= declspec2;
fDtor2= dtor2;
return this;
}
} }
private static final ASTVisitor MARK_INACTIVE = new ASTGenericVisitor(true) { private static final ASTVisitor MARK_INACTIVE = new ASTGenericVisitor(true) {
@ -1384,36 +1399,9 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
return compoundStatement(); return compoundStatement();
} }
protected abstract IASTDeclarator initDeclarator(DeclarationOptions option) protected abstract IASTDeclarator initDeclarator(IASTDeclSpecifier declSpec, DeclarationOptions option)
throws EndOfFileException, BacktrackException, FoundAggregateInitializer; throws EndOfFileException, BacktrackException, FoundAggregateInitializer;
/**
* @param option the options with which to parse the declaration
* @throws FoundDeclaratorException encountered EOF while looking ahead
* @throws FoundAggregateInitializer found aggregate initializer, needs special treatment
* because of scalability.
*/
protected void lookAheadForDeclarator(final DeclarationOptions option)
throws FoundDeclaratorException, FoundAggregateInitializer {
IToken mark = null;
try {
mark = mark();
final IASTDeclarator dtor= initDeclarator(option);
final IToken la = LA(1);
if (la == null || la == mark)
return;
if (verifyLookaheadDeclarator(option, dtor, la))
throw new FoundDeclaratorException(dtor, la);
} catch (BacktrackException bte) {
} catch (EndOfFileException e) {
} finally {
if (mark != null)
backup(mark);
}
}
protected abstract boolean verifyLookaheadDeclarator(DeclarationOptions option, IASTDeclarator d, IToken nextToken);
/** /**
* Parse an enumeration specifier, as according to the ANSI specs in C & * Parse an enumeration specifier, as according to the ANSI specs in C &
@ -1530,7 +1518,98 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
protected abstract IASTDeclaration declaration(DeclarationOptions option) throws BacktrackException, EndOfFileException; protected abstract IASTDeclaration declaration(DeclarationOptions option) throws BacktrackException, EndOfFileException;
protected abstract IASTDeclSpecifier declSpecifierSeq(DeclarationOptions option) throws BacktrackException, EndOfFileException, FoundDeclaratorException, FoundAggregateInitializer;
/**
* Parses for two alternatives of a declspec sequence. If there is a second alternative the token after the second alternative
* is returned, such that the parser can continue after both variants.
*/
protected abstract Decl declSpecifierSeq(DeclarationOptions option) throws BacktrackException, EndOfFileException;
/**
* 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
* longer alternative is selected.
*/
protected Decl declSpecifierSequence_initDeclarator(final DeclarationOptions option, boolean acceptCompoundWithoutDtor) throws EndOfFileException, FoundAggregateInitializer, BacktrackException {
Decl result= declSpecifierSeq(option);
final int lt1 = LTcatchEOF(1);
if (lt1 == IToken.tEOC)
return result;
// support simple declarations without declarators
final boolean acceptEmpty = acceptCompoundWithoutDtor && specifiesCompound(result.fDeclSpec1);
if (acceptEmpty) {
switch(lt1) {
case 0:
case IToken.tEOC:
case IToken.tSEMI:
return result;
}
}
final IToken dtorMark1= mark();
final IToken dtorMark2= result.fDtorToken1;
final IASTDeclSpecifier declspec1= result.fDeclSpec1;
final IASTDeclSpecifier declspec2= result.fDeclSpec2;
IASTDeclarator dtor1, dtor2;
try {
// declarator for first variant
dtor1= initDeclarator(declspec1, option);
} catch (FoundAggregateInitializer e) {
e.fDeclSpec= declspec1;
throw e;
} catch (BacktrackException e) {
if (acceptEmpty) {
backup(dtorMark1);
return result.set(declspec1, null, null);
}
// try second variant, if possible
if (dtorMark2 == null)
throw e;
backup(dtorMark2);
dtor2= initDeclarator(declspec2, option);
return result.set(declspec2, dtor2, dtorMark2);
}
// first variant was a success. If possible, try second one.
if (dtorMark2 == null) {
return result.set(declspec1, dtor1, dtorMark1);
}
final IToken end1= mark();
backup(dtorMark2);
try {
dtor2= initDeclarator(declspec2, option);
} catch (BacktrackException e) {
backup(end1);
return result.set(declspec1, dtor1, dtorMark1);
}
final IToken end2= mark();
if (end1 == end2) {
return result.set(declspec1, dtor1, declspec2, dtor2);
}
if (end1.getEndOffset() > end2.getEndOffset()) {
backup(end1);
return result.set(declspec1, dtor1, dtorMark1);
}
return result.set(declspec2, dtor2, dtorMark2);
}
protected boolean specifiesCompound(IASTDeclSpecifier declSpec) {
if (declSpec instanceof IASTCompositeTypeSpecifier)
return true;
if (declSpec instanceof IASTElaboratedTypeSpecifier)
return true;
if (declSpec instanceof IASTEnumerationSpecifier)
return true;
return false;
}
protected IASTDeclaration[] problemDeclaration(int offset, BacktrackException bt, DeclarationOptions option) { protected IASTDeclaration[] problemDeclaration(int offset, BacktrackException bt, DeclarationOptions option) {
failParse(); failParse();
@ -1614,25 +1693,15 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
protected IASTDeclaration functionStyleAsmDeclaration() throws BacktrackException, EndOfFileException { protected IASTDeclaration functionStyleAsmDeclaration() throws BacktrackException, EndOfFileException {
final int offset= LA(1).getOffset(); final int offset= LA(1).getOffset();
IASTDeclSpecifier declSpec= null; IASTDeclSpecifier declSpec;
IASTDeclarator dtor; IASTDeclarator dtor;
try { try {
declSpec = declSpecifierSeq(DeclarationOptions.FUNCTION_STYLE_ASM); Decl decl= declSpecifierSequence_initDeclarator(DeclarationOptions.FUNCTION_STYLE_ASM, false);
dtor = initDeclarator(DeclarationOptions.FUNCTION_STYLE_ASM); declSpec= decl.fDeclSpec1;
} catch (FoundDeclaratorException e) { dtor= decl.fDtor1;
if (e.altSpec != null) { } catch (FoundAggregateInitializer lie) {
declSpec= e.altSpec; declSpec= lie.fDeclSpec;
dtor= e.altDeclarator;
} else {
declSpec = e.declSpec;
dtor= e.declarator;
}
backup( e.currToken );
} catch (FoundAggregateInitializer lie) {
if (declSpec == null)
declSpec= lie.fDeclSpec;
dtor= addInitializer(lie, DeclarationOptions.FUNCTION_STYLE_ASM); dtor= addInitializer(lie, DeclarationOptions.FUNCTION_STYLE_ASM);
} }
@ -1640,7 +1709,7 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
throwBacktrack(LA(1)); throwBacktrack(LA(1));
final IASTDeclarator fdtor= ASTQueries.findTypeRelevantDeclarator(dtor); final IASTDeclarator fdtor= ASTQueries.findTypeRelevantDeclarator(dtor);
if (dtor instanceof IASTFunctionDeclarator == false) if (!(fdtor instanceof IASTFunctionDeclarator))
throwBacktrack(offset, LA(1).getEndOffset() - offset); throwBacktrack(offset, LA(1).getEndOffset() - offset);
final int compoundOffset= LA(1).getOffset(); final int compoundOffset= LA(1).getOffset();

View file

@ -27,7 +27,7 @@ public class DeclarationOptions {
public static final DeclarationOptions public static final DeclarationOptions
GLOBAL= new DeclarationOptions(ALLOW_EMPTY_SPECIFIER | ALLOW_CONSTRUCTOR_INITIALIZER), GLOBAL= new DeclarationOptions(ALLOW_EMPTY_SPECIFIER | ALLOW_CONSTRUCTOR_INITIALIZER),
FUNCTION_STYLE_ASM= new DeclarationOptions(ALLOW_EMPTY_SPECIFIER | NO_INITIALIZER), FUNCTION_STYLE_ASM= new DeclarationOptions(ALLOW_EMPTY_SPECIFIER | NO_INITIALIZER | ALLOW_ABSTRACT),
C_MEMBER= new DeclarationOptions(ALLOW_BITFIELD | ALLOW_ABSTRACT), C_MEMBER= new DeclarationOptions(ALLOW_BITFIELD | ALLOW_ABSTRACT),
CPP_MEMBER= new DeclarationOptions(ALLOW_EMPTY_SPECIFIER | ALLOW_BITFIELD), CPP_MEMBER= new DeclarationOptions(ALLOW_EMPTY_SPECIFIER | ALLOW_BITFIELD),
LOCAL= new DeclarationOptions(ALLOW_CONSTRUCTOR_INITIALIZER), LOCAL= new DeclarationOptions(ALLOW_CONSTRUCTOR_INITIALIZER),

View file

@ -291,64 +291,31 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
return simpleDeclaration(declOption); return simpleDeclaration(declOption);
} }
private IASTDeclaration simpleDeclaration(final DeclarationOptions declOption) private IASTDeclaration simpleDeclaration(final DeclarationOptions declOption) throws BacktrackException, EndOfFileException {
throws BacktrackException, EndOfFileException {
if (LT(1) == IToken.tLBRACE) if (LT(1) == IToken.tLBRACE)
throwBacktrack(LA(1)); throwBacktrack(LA(1));
final int firstOffset= LA(1).getOffset(); final int firstOffset= LA(1).getOffset();
int endOffset= firstOffset; int endOffset= firstOffset;
boolean insertSemi= false; boolean insertSemi= false;
boolean parseDtors= true;
IASTDeclSpecifier declSpec= null; IASTDeclSpecifier declSpec= null;
IASTDeclarator dtor= null; IASTDeclarator dtor= null;
IASTDeclSpecifier altDeclSpec= null; IASTDeclSpecifier altDeclSpec= null;
IASTDeclarator altDeclarator= null; IASTDeclarator altDtor= null;
IToken markBeforDtor= null; IToken markBeforDtor= null;
try { try {
declSpec = declSpecifierSeq(declOption); Decl decl= declSpecifierSequence_initDeclarator(declOption, true);
final int lt1= LTcatchEOF(1); markBeforDtor= decl.fDtorToken1;
switch(lt1) { declSpec= decl.fDeclSpec1;
case 0: // eof dtor= decl.fDtor1;
case IToken.tEOC: altDeclSpec= decl.fDeclSpec2;
case IToken.tSEMI: altDtor= decl.fDtor2;
parseDtors= false;
insertSemi= lt1==0;
if (lt1 == IToken.tSEMI)
endOffset= consume().getEndOffset();
else
endOffset= calculateEndOffset(declSpec);
break;
default:
markBeforDtor= mark();
try {
dtor= initDeclarator(declOption);
} catch (BacktrackException e) {
backup(markBeforDtor);
} catch (EndOfFileException e) {
backup(markBeforDtor);
}
}
} catch (FoundAggregateInitializer lie) { } catch (FoundAggregateInitializer lie) {
if (declSpec == null) declSpec= lie.fDeclSpec;
declSpec= lie.fDeclSpec;
// scalability: don't keep references to tokens, initializer may be large // scalability: don't keep references to tokens, initializer may be large
declarationMark= null; declarationMark= null;
markBeforDtor= null;
dtor= addInitializer(lie, declOption); dtor= addInitializer(lie, declOption);
} catch (FoundDeclaratorException e) {
if (e.altSpec != null) {
declSpec= e.altSpec;
dtor= e.altDeclarator;
altDeclSpec= e.declSpec;
altDeclarator= e.declarator;
} else {
declSpec = e.declSpec;
dtor= e.declarator;
}
backup( e.currToken );
} catch (BacktrackException e) { } catch (BacktrackException e) {
IASTNode node= e.getNodeBeforeProblem(); IASTNode node= e.getNodeBeforeProblem();
if (node instanceof IASTDeclSpecifier) { if (node instanceof IASTDeclSpecifier) {
@ -360,12 +327,12 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
} }
IASTDeclarator[] declarators= IASTDeclarator.EMPTY_DECLARATOR_ARRAY; IASTDeclarator[] declarators= IASTDeclarator.EMPTY_DECLARATOR_ARRAY;
if (parseDtors) { if (dtor != null) {
declarators= new IASTDeclarator[]{dtor}; declarators= new IASTDeclarator[]{dtor};
while (LTcatchEOF(1) == IToken.tCOMMA) { while (LTcatchEOF(1) == IToken.tCOMMA) {
consume(); consume();
try { try {
dtor= initDeclarator(declOption); dtor= initDeclarator(declSpec, declOption);
} catch (FoundAggregateInitializer e) { } catch (FoundAggregateInitializer e) {
// scalability: don't keep references to tokens, initializer may be large // scalability: don't keep references to tokens, initializer may be large
declarationMark= null; declarationMark= null;
@ -375,44 +342,44 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
declarators= (IASTDeclarator[]) ArrayUtil.append( IASTDeclarator.class, declarators, dtor); declarators= (IASTDeclarator[]) ArrayUtil.append( IASTDeclarator.class, declarators, dtor);
} }
declarators= (IASTDeclarator[]) ArrayUtil.removeNulls( IASTDeclarator.class, declarators ); declarators= (IASTDeclarator[]) ArrayUtil.removeNulls( IASTDeclarator.class, declarators );
}
final int lt1= LTcatchEOF(1); final int lt1= LTcatchEOF(1);
switch (lt1) { switch (lt1) {
case IToken.tLBRACE: case IToken.tEOC:
return functionDefinition(firstOffset, declSpec, declarators); endOffset= figureEndOffset(declSpec, declarators);
break;
case IToken.tSEMI:
endOffset= consume().getEndOffset();
break;
case IToken.tLBRACE:
return functionDefinition(firstOffset, declSpec, declarators);
case IToken.tSEMI: default:
endOffset= consume().getEndOffset(); if (declOption != DeclarationOptions.LOCAL) {
break; insertSemi= true;
case IToken.tEOC: if (markBeforDtor != null) {
endOffset= figureEndOffset(declSpec, declarators); endOffset= calculateEndOffset(declSpec);
break; if (firstOffset != endOffset && !isOnSameLine(endOffset, markBeforDtor.getOffset())) {
default: backup(markBeforDtor);
if (declOption != DeclarationOptions.LOCAL) { declarators= IASTDeclarator.EMPTY_DECLARATOR_ARRAY;
insertSemi= true;
if (markBeforDtor != null) {
endOffset= calculateEndOffset(declSpec);
if (firstOffset != endOffset && !isOnSameLine(endOffset, markBeforDtor.getOffset())) {
backup(markBeforDtor);
declarators= IASTDeclarator.EMPTY_DECLARATOR_ARRAY;
break;
}
}
endOffset= figureEndOffset(declSpec, declarators);
if (lt1 == 0) {
break; break;
} }
if (firstOffset != endOffset) { }
if (!isOnSameLine(endOffset, LA(1).getOffset())) { endOffset= figureEndOffset(declSpec, declarators);
break; if (lt1 == 0) {
} break;
if (declarators.length == 1 && declarators[0] instanceof IASTFunctionDeclarator) { }
break; if (firstOffset != endOffset) {
} if (!isOnSameLine(endOffset, LA(1).getOffset())) {
break;
}
if (declarators.length == 1 && declarators[0] instanceof IASTFunctionDeclarator) {
break;
} }
} }
throwBacktrack(LA(1));
} }
throwBacktrack(LA(1));
} }
// no function body // no function body
@ -421,10 +388,10 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
simpleDeclaration.addDeclarator(declarator); simpleDeclaration.addDeclarator(declarator);
setRange(simpleDeclaration, firstOffset, endOffset); setRange(simpleDeclaration, firstOffset, endOffset);
if ( altDeclSpec != null && altDeclarator != null) { if (altDeclSpec != null && altDtor != null) {
simpleDeclaration= new CASTAmbiguousSimpleDeclaration(simpleDeclaration, altDeclSpec, altDeclarator); simpleDeclaration = new CASTAmbiguousSimpleDeclaration(simpleDeclaration, altDeclSpec, altDtor);
setRange(simpleDeclaration, firstOffset, endOffset); setRange(simpleDeclaration, firstOffset, endOffset);
} }
if (insertSemi) { if (insertSemi) {
IASTProblem problem= createProblem(IProblem.SYNTAX_ERROR, endOffset, 0); IASTProblem problem= createProblem(IProblem.SYNTAX_ERROR, endOffset, 0);
@ -737,24 +704,18 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
if (!canBeTypeSpecifier()) { if (!canBeTypeSpecifier()) {
return null; return null;
} }
IToken mark = mark(); final int offset = mark().getOffset();
int startingOffset = mark.getOffset();
IASTDeclSpecifier declSpecifier = null; IASTDeclSpecifier declSpecifier = null;
IASTDeclarator declarator = null; IASTDeclarator declarator = null;
fPreventKnrCheck++; fPreventKnrCheck++;
try { try {
try { Decl decl= declSpecifierSequence_initDeclarator(option, false);
declSpecifier= declSpecifierSeq(option); declSpecifier= decl.fDeclSpec1;
declarator= declarator(option); declarator= decl.fDtor1;
} catch (FoundDeclaratorException e) { } catch (FoundAggregateInitializer lie) {
declSpecifier= e.declSpec; // type-ids have not compound initializers
declarator= e.declarator; return null;
backup(e.currToken);
} catch (FoundAggregateInitializer lie) {
// type-ids have not compound initializers
return null;
}
} catch (BacktrackException bt) { } catch (BacktrackException bt) {
return null; return null;
} finally { } finally {
@ -762,8 +723,7 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
} }
IASTTypeId result = nodeFactory.newTypeId(declSpecifier, declarator); IASTTypeId result = nodeFactory.newTypeId(declSpecifier, declarator);
((ASTNode) result).setOffsetAndLength(startingOffset, figureEndOffset( setRange(result, offset, figureEndOffset(declSpecifier, declarator));
declSpecifier, declarator) - startingOffset);
return result; return result;
} }
@ -828,292 +788,283 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
SHORT=0x10, UNSIGNED= 0x20, SIGNED=0x40, COMPLEX=0x80, IMAGINARY=0x100; SHORT=0x10, UNSIGNED= 0x20, SIGNED=0x40, COMPLEX=0x80, IMAGINARY=0x100;
@Override @Override
protected IASTDeclSpecifier declSpecifierSeq(final DeclarationOptions declOption) protected Decl declSpecifierSeq(final DeclarationOptions declOption) throws BacktrackException, EndOfFileException {
throws BacktrackException, EndOfFileException, FoundDeclaratorException, FoundAggregateInitializer {
final int offset= LA(1).getOffset();
int endOffset= offset;
int storageClass= IASTDeclSpecifier.sc_unspecified; int storageClass= IASTDeclSpecifier.sc_unspecified;
int simpleType= IASTSimpleDeclSpecifier.t_unspecified; int simpleType= IASTSimpleDeclSpecifier.t_unspecified;
int options= 0; int options= 0;
int isLong= 0; int isLong= 0;
IASTName identifier= null; IToken returnToken= null;
IASTDeclSpecifier result= null; IASTDeclSpecifier result= null;
IASTExpression typeofExpression= null; IASTDeclSpecifier altResult= null;
IASTProblem problem= null; try {
IASTName identifier= null;
IASTExpression typeofExpression= null;
IASTProblem problem= null;
boolean encounteredRawType= false; boolean encounteredRawType= false;
boolean encounteredTypename= false; boolean encounteredTypename= false;
declSpecifiers: for (;;) { final int offset= LA(1).getOffset();
final int lt1= LTcatchEOF(1); int endOffset= offset;
switch (lt1) {
case 0: // eof
break declSpecifiers;
// storage class specifiers
case IToken.t_auto:
storageClass = IASTDeclSpecifier.sc_auto;
endOffset= consume().getEndOffset();
break;
case IToken.t_register:
storageClass = IASTDeclSpecifier.sc_register;
endOffset= consume().getEndOffset();
break;
case IToken.t_static:
storageClass = IASTDeclSpecifier.sc_static;
endOffset= consume().getEndOffset();
break;
case IToken.t_extern:
storageClass = IASTDeclSpecifier.sc_extern;
endOffset= consume().getEndOffset();
break;
case IToken.t_typedef:
storageClass = IASTDeclSpecifier.sc_typedef;
endOffset= consume().getEndOffset();
break;
// Function Specifier declSpecifiers: for (;;) {
case IToken.t_inline: final int lt1= LTcatchEOF(1);
options |= INLINE; switch (lt1) {
endOffset= consume().getEndOffset(); case 0: // eof
break; break declSpecifiers;
// storage class specifiers
case IToken.t_auto:
storageClass = IASTDeclSpecifier.sc_auto;
endOffset= consume().getEndOffset();
break;
case IToken.t_register:
storageClass = IASTDeclSpecifier.sc_register;
endOffset= consume().getEndOffset();
break;
case IToken.t_static:
storageClass = IASTDeclSpecifier.sc_static;
endOffset= consume().getEndOffset();
break;
case IToken.t_extern:
storageClass = IASTDeclSpecifier.sc_extern;
endOffset= consume().getEndOffset();
break;
case IToken.t_typedef:
storageClass = IASTDeclSpecifier.sc_typedef;
endOffset= consume().getEndOffset();
break;
// Type Qualifiers // Function Specifier
case IToken.t_const: case IToken.t_inline:
options |= CONST; options |= INLINE;
endOffset= consume().getEndOffset(); endOffset= consume().getEndOffset();
break; break;
case IToken.t_volatile:
options |= VOLATILE;
endOffset= consume().getEndOffset();
break;
case IToken.t_restrict:
options |= RESTRICT;
endOffset= consume().getEndOffset();
break;
// Type Specifiers // Type Qualifiers
case IToken.t_void: case IToken.t_const:
if (encounteredTypename) options |= CONST;
break declSpecifiers; endOffset= consume().getEndOffset();
simpleType = IASTSimpleDeclSpecifier.t_void; break;
encounteredRawType= true; case IToken.t_volatile:
endOffset= consume().getEndOffset(); options |= VOLATILE;
break; endOffset= consume().getEndOffset();
case IToken.t_char: break;
if (encounteredTypename) case IToken.t_restrict:
break declSpecifiers; options |= RESTRICT;
simpleType = IASTSimpleDeclSpecifier.t_char; endOffset= consume().getEndOffset();
encounteredRawType= true; break;
endOffset= consume().getEndOffset();
break;
case IToken.t_short:
if (encounteredTypename)
break declSpecifiers;
options |= SHORT;
encounteredRawType= true;
endOffset= consume().getEndOffset();
break;
case IToken.t_int:
if (encounteredTypename)
break declSpecifiers;
simpleType = IASTSimpleDeclSpecifier.t_int;
encounteredRawType= true;
endOffset= consume().getEndOffset();
break;
case IToken.t_long:
if (encounteredTypename)
break declSpecifiers;
isLong++;
encounteredRawType= true;
endOffset= consume().getEndOffset();
break;
case IToken.t_float:
if (encounteredTypename)
break declSpecifiers;
simpleType = IASTSimpleDeclSpecifier.t_float;
encounteredRawType= true;
endOffset= consume().getEndOffset();
break;
case IToken.t_double:
if (encounteredTypename)
break declSpecifiers;
simpleType = IASTSimpleDeclSpecifier.t_double;
encounteredRawType= true;
endOffset= consume().getEndOffset();
break;
case IToken.t_signed:
if (encounteredTypename)
break declSpecifiers;
options |= SIGNED;
encounteredRawType= true;
endOffset= consume().getEndOffset();
break;
case IToken.t_unsigned:
if (encounteredTypename)
break declSpecifiers;
options |= UNSIGNED;
encounteredRawType= true;
endOffset= consume().getEndOffset();
break;
case IToken.t__Bool:
if (encounteredTypename)
break declSpecifiers;
simpleType = ICASTSimpleDeclSpecifier.t_Bool;
encounteredRawType= true;
endOffset= consume().getEndOffset();
break;
case IToken.t__Complex:
if (encounteredTypename)
break declSpecifiers;
options |= COMPLEX;
endOffset= consume().getEndOffset();
break;
case IToken.t__Imaginary:
if (encounteredTypename)
break declSpecifiers;
options |= IMAGINARY;
endOffset= consume().getEndOffset();
break;
case IToken.tIDENTIFIER: // Type Specifiers
case IToken.tCOMPLETION: case IToken.t_void:
case IToken.tEOC: if (encounteredTypename)
if (encounteredTypename || encounteredRawType) { break declSpecifiers;
break declSpecifiers; simpleType = IASTSimpleDeclSpecifier.t_void;
} encounteredRawType= true;
endOffset= consume().getEndOffset();
break;
case IToken.t_char:
if (encounteredTypename)
break declSpecifiers;
simpleType = IASTSimpleDeclSpecifier.t_char;
encounteredRawType= true;
endOffset= consume().getEndOffset();
break;
case IToken.t_short:
if (encounteredTypename)
break declSpecifiers;
options |= SHORT;
encounteredRawType= true;
endOffset= consume().getEndOffset();
break;
case IToken.t_int:
if (encounteredTypename)
break declSpecifiers;
simpleType = IASTSimpleDeclSpecifier.t_int;
encounteredRawType= true;
endOffset= consume().getEndOffset();
break;
case IToken.t_long:
if (encounteredTypename)
break declSpecifiers;
isLong++;
encounteredRawType= true;
endOffset= consume().getEndOffset();
break;
case IToken.t_float:
if (encounteredTypename)
break declSpecifiers;
simpleType = IASTSimpleDeclSpecifier.t_float;
encounteredRawType= true;
endOffset= consume().getEndOffset();
break;
case IToken.t_double:
if (encounteredTypename)
break declSpecifiers;
simpleType = IASTSimpleDeclSpecifier.t_double;
encounteredRawType= true;
endOffset= consume().getEndOffset();
break;
case IToken.t_signed:
if (encounteredTypename)
break declSpecifiers;
options |= SIGNED;
encounteredRawType= true;
endOffset= consume().getEndOffset();
break;
case IToken.t_unsigned:
if (encounteredTypename)
break declSpecifiers;
options |= UNSIGNED;
encounteredRawType= true;
endOffset= consume().getEndOffset();
break;
case IToken.t__Bool:
if (encounteredTypename)
break declSpecifiers;
simpleType = ICASTSimpleDeclSpecifier.t_Bool;
encounteredRawType= true;
endOffset= consume().getEndOffset();
break;
case IToken.t__Complex:
if (encounteredTypename)
break declSpecifiers;
options |= COMPLEX;
endOffset= consume().getEndOffset();
break;
case IToken.t__Imaginary:
if (encounteredTypename)
break declSpecifiers;
options |= IMAGINARY;
endOffset= consume().getEndOffset();
break;
try { case IToken.tIDENTIFIER:
if (endOffset != offset || declOption.fAllowEmptySpecifier) { case IToken.tCOMPLETION:
lookAheadForDeclarator(declOption); case IToken.tEOC:
} if (encounteredTypename || encounteredRawType)
} catch (FoundAggregateInitializer e) { break declSpecifiers;
e.fDeclSpec= buildSimpleDeclSpec(storageClass, simpleType, options, isLong, typeofExpression, offset, endOffset);
throw e;
} catch (FoundDeclaratorException e) {
e.declSpec= buildSimpleDeclSpec(storageClass, simpleType, options, isLong, typeofExpression, offset, endOffset);
IToken mark= mark(); if ((endOffset != offset || declOption.fAllowEmptySpecifier) && LT(1) != IToken.tCOMPLETION) {
try { altResult= buildSimpleDeclSpec(storageClass, simpleType, options, isLong, typeofExpression, offset, endOffset);
final IASTName id= identifier(); // for the specifier returnToken= mark();
final IASTDeclarator altDtor = initDeclarator(declOption); }
if (LA(1) == e.currToken) {
e.altDeclarator= altDtor;
e.altSpec= buildNamedTypeSpecifier(id, storageClass, options, offset, calculateEndOffset(id));
}
} catch (FoundAggregateInitializer lie) {
lie.fDeclSpec= e.declSpec;
throw lie;
} catch (BacktrackException bt) {
} finally {
backup(mark);
}
throw e;
}
identifier = identifier();
endOffset= calculateEndOffset(identifier);
encounteredTypename= true;
break;
case IToken.t_struct:
case IToken.t_union:
if (encounteredTypename || encounteredRawType)
break declSpecifiers;
try {
result= structOrUnionSpecifier();
} catch (BacktrackException bt) {
result= elaboratedTypeSpecifier();
}
endOffset= calculateEndOffset(result);
encounteredTypename= true;
break;
case IToken.t_enum:
if (encounteredTypename || encounteredRawType)
break declSpecifiers;
try {
result= enumSpecifier();
} catch (BacktrackException bt) {
if (bt.getNodeBeforeProblem() instanceof IASTDeclSpecifier) {
result= (IASTDeclSpecifier) bt.getNodeBeforeProblem();
problem = bt.getProblem();
break declSpecifiers;
} else {
result= elaboratedTypeSpecifier();
}
}
endOffset= calculateEndOffset(result);
encounteredTypename= true;
break;
case IGCCToken.t__attribute__: // if __attribute__ is after the declSpec identifier = identifier();
if (!supportAttributeSpecifiers) endOffset= calculateEndOffset(identifier);
throwBacktrack(LA(1)); encounteredTypename= true;
__attribute_decl_seq(true, false); break;
break; case IToken.t_struct:
case IGCCToken.t__declspec: // __declspec precedes the identifier case IToken.t_union:
if (identifier != null || !supportDeclspecSpecifiers) if (encounteredTypename || encounteredRawType)
throwBacktrack(LA(1)); break declSpecifiers;
__attribute_decl_seq(false, true); try {
break; result= structOrUnionSpecifier();
} catch (BacktrackException bt) {
result= elaboratedTypeSpecifier();
}
endOffset= calculateEndOffset(result);
encounteredTypename= true;
break;
case IToken.t_enum:
if (encounteredTypename || encounteredRawType)
break declSpecifiers;
try {
result= enumSpecifier();
} catch (BacktrackException bt) {
if (bt.getNodeBeforeProblem() instanceof IASTDeclSpecifier) {
result= (IASTDeclSpecifier) bt.getNodeBeforeProblem();
problem = bt.getProblem();
break declSpecifiers;
} else {
result= elaboratedTypeSpecifier();
}
}
endOffset= calculateEndOffset(result);
encounteredTypename= true;
break;
case IGCCToken.t_typeof: case IGCCToken.t__attribute__: // if __attribute__ is after the declSpec
if (encounteredRawType || encounteredTypename) if (!supportAttributeSpecifiers)
throwBacktrack(LA(1)); throwBacktrack(LA(1));
__attribute_decl_seq(true, false);
break;
case IGCCToken.t__declspec: // __declspec precedes the identifier
if (identifier != null || !supportDeclspecSpecifiers)
throwBacktrack(LA(1));
__attribute_decl_seq(false, true);
break;
final boolean wasInBinary= inBinaryExpression; case IGCCToken.t_typeof:
try { if (encounteredRawType || encounteredTypename)
inBinaryExpression= false; throwBacktrack(LA(1));
typeofExpression = parseTypeidInParenthesisOrUnaryExpression(false, consume().getOffset(),
IGNUASTTypeIdExpression.op_typeof, IGNUASTUnaryExpression.op_typeof);
} finally {
inBinaryExpression= wasInBinary;
}
encounteredTypename= true;
endOffset= calculateEndOffset(typeofExpression);
break;
default: final boolean wasInBinary= inBinaryExpression;
if (lt1 >= IExtensionToken.t__otherDeclSpecModifierFirst && lt1 <= IExtensionToken.t__otherDeclSpecModifierLast) { try {
handleOtherDeclSpecModifier(); inBinaryExpression= false;
endOffset= LA(1).getOffset(); typeofExpression = parseTypeidInParenthesisOrUnaryExpression(false, consume().getOffset(),
break; IGNUASTTypeIdExpression.op_typeof, IGNUASTUnaryExpression.op_typeof);
} } finally {
break declSpecifiers; inBinaryExpression= wasInBinary;
} }
encounteredTypename= true;
endOffset= calculateEndOffset(typeofExpression);
break;
if (encounteredRawType && encounteredTypename) default:
throwBacktrack(LA(1)); if (lt1 >= IExtensionToken.t__otherDeclSpecModifierFirst && lt1 <= IExtensionToken.t__otherDeclSpecModifierLast) {
} handleOtherDeclSpecModifier();
endOffset= LA(1).getOffset();
break;
}
break declSpecifiers;
}
// check for empty specification if (encounteredRawType && encounteredTypename)
if (!encounteredRawType && !encounteredTypename && LT(1) != IToken.tEOC && !declOption.fAllowEmptySpecifier) { throwBacktrack(LA(1));
if (offset == endOffset) { }
throwBacktrack(LA(1));
// check for empty specification
if (!encounteredRawType && !encounteredTypename && LT(1) != IToken.tEOC && !declOption.fAllowEmptySpecifier) {
if (offset == endOffset) {
throwBacktrack(LA(1));
}
}
if (result != null) {
configureDeclSpec(result, storageClass, options);
if ((options & RESTRICT) != 0) {
if (result instanceof ICASTCompositeTypeSpecifier) {
((ICASTCompositeTypeSpecifier) result).setRestrict(true);
} else if (result instanceof CASTEnumerationSpecifier) {
((CASTEnumerationSpecifier) result).setRestrict(true);
} else if (result instanceof CASTElaboratedTypeSpecifier) {
((CASTElaboratedTypeSpecifier) result).setRestrict(true);
}
}
setRange(result, offset, endOffset);
if (problem != null)
throwBacktrack(problem, result);
} else if (identifier != null) {
result= buildNamedTypeSpecifier(identifier, storageClass, options, offset, endOffset);
} else {
result= buildSimpleDeclSpec(storageClass, simpleType, options, isLong, typeofExpression, offset, endOffset);
}
} catch (BacktrackException e) {
if (returnToken != null) {
backup(returnToken);
result= altResult;
altResult= null;
returnToken= null;
} else {
throw e;
} }
} }
Decl target= new Decl();
if (result != null) { target.fDeclSpec1= result;
configureDeclSpec(result, storageClass, options); target.fDeclSpec2= altResult;
if ((options & RESTRICT) != 0) { target.fDtorToken1= returnToken;
if (result instanceof ICASTCompositeTypeSpecifier) { return target;
((ICASTCompositeTypeSpecifier) result).setRestrict(true);
} else if (result instanceof CASTEnumerationSpecifier) {
((CASTEnumerationSpecifier) result).setRestrict(true);
} else if (result instanceof CASTElaboratedTypeSpecifier) {
((CASTElaboratedTypeSpecifier) result).setRestrict(true);
}
}
((ASTNode) result).setOffsetAndLength(offset, endOffset - offset);
if (problem != null)
throwBacktrack(problem, result);
return result;
}
if (identifier != null)
return buildNamedTypeSpecifier(identifier, storageClass, options, offset, endOffset);
return buildSimpleDeclSpec(storageClass, simpleType, options, isLong, typeofExpression, offset, endOffset);
} }
private ICASTTypedefNameSpecifier buildNamedTypeSpecifier(IASTName name, int storageClass, private ICASTTypedefNameSpecifier buildNamedTypeSpecifier(IASTName name, int storageClass,
@ -1155,31 +1106,6 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
declSpec.setInline((options & INLINE) != 0); declSpec.setInline((options & INLINE) != 0);
} }
@Override
protected boolean verifyLookaheadDeclarator(DeclarationOptions option, IASTDeclarator dtor, IToken nextToken) {
switch (nextToken.getType()) {
case IToken.tCOMMA:
return true;
case IToken.tLBRACE:
if (option == DeclarationOptions.GLOBAL || option == DeclarationOptions.C_MEMBER
|| option == DeclarationOptions.FUNCTION_STYLE_ASM) {
if (ASTQueries.findTypeRelevantDeclarator(dtor) instanceof IASTFunctionDeclarator) {
return true;
}
}
break;
case IToken.tSEMI:
return option == DeclarationOptions.GLOBAL || option == DeclarationOptions.C_MEMBER ||
option == DeclarationOptions.LOCAL;
case IToken.tRPAREN:
return option == DeclarationOptions.PARAMETER
|| option == DeclarationOptions.C_PARAMETER_NON_ABSTRACT;
}
return false;
}
/** /**
* Parse a class/struct/union definition. * Parse a class/struct/union definition.
* *
@ -1266,11 +1192,18 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
@Override @Override
protected IASTDeclarator initDeclarator(final DeclarationOptions option) protected IASTDeclarator initDeclarator(IASTDeclSpecifier declspec, final DeclarationOptions option)
throws EndOfFileException, BacktrackException, FoundAggregateInitializer { throws EndOfFileException, BacktrackException, FoundAggregateInitializer {
IASTDeclarator d = declarator(option); IASTDeclarator d = declarator(declspec, option);
if (LTcatchEOF(1) == IToken.tASSIGN && LT(2) == IToken.tLBRACE) final int lt1= LTcatchEOF(1);
if (lt1 == IToken.tLBRACE) {
if (!(ASTQueries.findTypeRelevantDeclarator(d) instanceof IASTFunctionDeclarator)) {
throwBacktrack(LA(1));
}
}
if (lt1 == IToken.tASSIGN && LT(2) == IToken.tLBRACE)
throw new FoundAggregateInitializer(d); throw new FoundAggregateInitializer(d);
IASTInitializer i = optionalCInitializer(); IASTInitializer i = optionalCInitializer();
@ -1296,7 +1229,7 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
return d; return d;
} }
protected IASTDeclarator declarator(DeclarationOptions option) throws EndOfFileException, BacktrackException { protected IASTDeclarator declarator(IASTDeclSpecifier declSpec, DeclarationOptions option) throws EndOfFileException, BacktrackException {
final int startingOffset = LA(1).getOffset(); final int startingOffset = LA(1).getOffset();
int endOffset = startingOffset; int endOffset = startingOffset;
@ -1342,7 +1275,7 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
if (LT(1) == IToken.tRPAREN) if (LT(1) == IToken.tRPAREN)
throwBacktrack(LA(1)); throwBacktrack(LA(1));
final IASTDeclarator nested= declarator(option); final IASTDeclarator nested= declarator(declSpec, option);
endOffset= consume(IToken.tRPAREN).getEndOffset(); endOffset= consume(IToken.tRPAREN).getEndOffset();
final IASTDeclarator cand2= declarator(pointerOps, null, nested, startingOffset, endOffset, option); final IASTDeclarator cand2= declarator(pointerOps, null, nested, startingOffset, endOffset, option);
if (cand1 == null || cand1End == null) if (cand1 == null || cand1End == null)
@ -1734,14 +1667,11 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
try { try {
fPreventKnrCheck++; fPreventKnrCheck++;
declSpec= declSpecifierSeq(option); Decl decl= declSpecifierSequence_initDeclarator(option, false);
declarator = declarator(option); declSpec= decl.fDeclSpec1;
} catch(FoundDeclaratorException fd) { declarator= decl.fDtor1;
declSpec= fd.declSpec; altDeclSpec= decl.fDeclSpec2;
declarator= fd.declarator; altDeclarator= decl.fDtor2;
altDeclSpec= fd.altSpec;
altDeclarator= fd.altDeclarator;
backup(fd.currToken);
} catch (FoundAggregateInitializer lie) { } catch (FoundAggregateInitializer lie) {
declSpec= lie.fDeclSpec; declSpec= lie.fDeclSpec;
declarator= lie.fDeclarator; declarator= lie.fDeclarator;
@ -1755,8 +1685,8 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
if (altDeclarator != null && altDeclSpec != null) { if (altDeclarator != null && altDeclSpec != null) {
IASTParameterDeclaration alt = nodeFactory.newParameterDeclaration(altDeclSpec, altDeclarator); IASTParameterDeclaration alt = nodeFactory.newParameterDeclaration(altDeclSpec, altDeclarator);
((ASTNode) alt).setOffsetAndLength(startingOffset, length); ((ASTNode) alt).setOffsetAndLength(startingOffset, length);
// order is important, prefer alternative over the declarator found via the lookahead. // order is important, prefer variant with declspec over the one without
result= new CASTAmbiguousParameterDeclaration(alt, result); result= new CASTAmbiguousParameterDeclaration(result, alt);
((ASTNode) result).setOffsetAndLength((ASTNode) alt); ((ASTNode) result).setOffsetAndLength((ASTNode) alt);
} }
return result; return result;

View file

@ -0,0 +1,122 @@
/*******************************************************************************
* Copyright (c) 2009 IBM Wind River Systems, Inc. and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Markus Schorn - Initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp;
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IProblemBinding;
import org.eclipse.cdt.core.dom.ast.IScope;
import org.eclipse.cdt.internal.core.dom.parser.ASTAmbiguousNode;
import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguityParent;
import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguousSimpleDeclaration;
import org.eclipse.cdt.internal.core.dom.parser.IASTInternalScope;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor;
/**
* Handles ambiguities for simple declarations.
* <br>
* class C {
* C(D); // if D a type we have a constructor, otherwise this declares the field D.
* };
*/
public class CPPASTAmbiguousSimpleDeclaration extends ASTAmbiguousNode implements IASTAmbiguousSimpleDeclaration {
private IASTSimpleDeclaration fSimpleDecl;
private IASTDeclSpecifier fAltDeclSpec;
private IASTDeclarator fAltDtor;
public CPPASTAmbiguousSimpleDeclaration(IASTSimpleDeclaration decl, IASTDeclSpecifier declSpec, IASTDeclarator dtor) {
fSimpleDecl= decl;
fAltDeclSpec= declSpec;
fAltDtor= dtor;
}
@Override
protected void beforeResolution() {
// populate containing scope, so that it will not be affected by the alternative branches.
IScope scope= CPPVisitor.getContainingScope(this);
if (scope instanceof IASTInternalScope) {
((IASTInternalScope) scope).populateCache();
}
}
@Override
public IASTNode[] getNodes() {
return new IASTNode[] {fSimpleDecl, fAltDeclSpec, fAltDtor};
}
public IASTSimpleDeclaration copy() {
throw new UnsupportedOperationException();
}
public void addDeclarator(IASTDeclarator declarator) {
fSimpleDecl.addDeclarator(declarator);
}
public IASTDeclSpecifier getDeclSpecifier() {
return fSimpleDecl.getDeclSpecifier();
}
public IASTDeclarator[] getDeclarators() {
return fSimpleDecl.getDeclarators();
}
public void setDeclSpecifier(IASTDeclSpecifier declSpec) {
fSimpleDecl.setDeclSpecifier(declSpec);
}
@Override
public final IASTNode resolveAmbiguity(ASTVisitor visitor) {
final IASTAmbiguityParent owner= (IASTAmbiguityParent) getParent();
IASTNode nodeToReplace= this;
// handle nested ambiguities first
owner.replace(nodeToReplace, fSimpleDecl);
IASTDeclarator dtor= fSimpleDecl.getDeclarators()[0];
dtor.accept(visitor);
// find nested names
final NameCollector nameCollector= new NameCollector();
dtor.accept(nameCollector);
final IASTName[] names= nameCollector.getNames();
// resolve names
boolean hasIssue= false;
for (IASTName name : names) {
try {
IBinding b = name.resolveBinding();
if (b instanceof IProblemBinding) {
hasIssue= true;
break;
}
} catch (Exception t) {
hasIssue= true;
break;
}
}
if (hasIssue) {
// use the alternate version
final IASTAmbiguityParent parent = (IASTAmbiguityParent) fSimpleDecl;
parent.replace(fSimpleDecl.getDeclSpecifier(), fAltDeclSpec);
parent.replace(dtor, fAltDtor);
}
// resolve further nested ambiguities
fSimpleDecl.accept(visitor);
return fSimpleDecl;
}
}

View file

@ -194,7 +194,7 @@ public class CPPFunction extends PlatformObject implements ICPPFunction, ICPPInt
} }
private ICPPASTFunctionDeclarator extractFunctionDtor(IASTNode node) { private ICPPASTFunctionDeclarator extractFunctionDtor(IASTNode node) {
if (node instanceof IASTName) while (node instanceof IASTName)
node = node.getParent(); node = node.getParent();
if (node instanceof IASTDeclarator == false) if (node instanceof IASTDeclarator == false)
return null; return null;

View file

@ -32,6 +32,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPParameter;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap;
import org.eclipse.cdt.core.index.IIndexBinding; import org.eclipse.cdt.core.index.IIndexBinding;
import org.eclipse.cdt.internal.core.dom.parser.ASTInternal; import org.eclipse.cdt.internal.core.dom.parser.ASTInternal;
import org.eclipse.cdt.internal.core.dom.parser.ASTQueries;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor;
/** /**
@ -192,26 +193,34 @@ public class CPPFunctionSpecialization extends CPPSpecialization implements ICPP
return null; return null;
} }
private ICPPASTFunctionDeclarator extractFunctionDtor(IASTNode node) {
if (node instanceof IASTName)
node = node.getParent();
if (node instanceof IASTDeclarator == false)
return null;
node= ASTQueries.findTypeRelevantDeclarator((IASTDeclarator) node);
if (node instanceof ICPPASTFunctionDeclarator == false)
return null;
return (ICPPASTFunctionDeclarator) node;
}
@Override @Override
public void addDefinition(IASTNode node) { public void addDefinition(IASTNode node) {
IASTNode n = node; ICPPASTFunctionDeclarator dtor = extractFunctionDtor(node);
while (n instanceof IASTName) if (dtor != null) {
n = n.getParent(); updateParameterBindings(dtor);
if (!(n instanceof ICPPASTFunctionDeclarator)) super.addDefinition(dtor);
return; }
updateParameterBindings((ICPPASTFunctionDeclarator) n);
super.addDefinition(n);
} }
@Override @Override
public void addDeclaration(IASTNode node) { public void addDeclaration(IASTNode node) {
IASTNode n = node; ICPPASTFunctionDeclarator dtor = extractFunctionDtor(node);
while (n instanceof IASTName) if (dtor != null) {
n = n.getParent(); updateParameterBindings(dtor);
if (!(n instanceof ICPPASTFunctionDeclarator)) super.addDeclaration(dtor);
return; }
updateParameterBindings((ICPPASTFunctionDeclarator) n);
super.addDeclaration(n);
} }
protected void updateParameterBindings(ICPPASTFunctionDeclarator fdtor) { protected void updateParameterBindings(ICPPASTFunctionDeclarator fdtor) {

View file

@ -87,6 +87,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeleteExpression;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFieldReference; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFieldReference;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTForStatement; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTForStatement;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDeclarator; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDeclarator;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDefinition;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTIfStatement; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTIfStatement;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTLinkageSpecification; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTLinkageSpecification;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamedTypeSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamedTypeSpecifier;
@ -141,6 +142,7 @@ import org.eclipse.cdt.core.parser.util.CharArrayObjectMap;
import org.eclipse.cdt.core.parser.util.CharArrayUtils; import org.eclipse.cdt.core.parser.util.CharArrayUtils;
import org.eclipse.cdt.core.parser.util.DebugUtil; import org.eclipse.cdt.core.parser.util.DebugUtil;
import org.eclipse.cdt.core.parser.util.ObjectSet; import org.eclipse.cdt.core.parser.util.ObjectSet;
import org.eclipse.cdt.internal.core.dom.parser.ASTAmbiguousNode;
import org.eclipse.cdt.internal.core.dom.parser.ASTInternal; import org.eclipse.cdt.internal.core.dom.parser.ASTInternal;
import org.eclipse.cdt.internal.core.dom.parser.ASTNode; import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
import org.eclipse.cdt.internal.core.dom.parser.ASTQueries; import org.eclipse.cdt.internal.core.dom.parser.ASTQueries;
@ -445,17 +447,25 @@ public class CPPSemantics {
} }
} }
// explicit function specializations are found via name resolution, need to
// add name as definition and check the declaration specifier.
if (binding instanceof IFunction && !(binding instanceof IProblemBinding)) { if (binding instanceof IFunction && !(binding instanceof IProblemBinding)) {
if (data.forFunctionDeclaration()) { if (data.forFunctionDeclaration()) {
IASTNode node = data.astName.getParent(); IASTNode declaration= data.astName;
if (node instanceof ICPPASTQualifiedName) while (declaration instanceof IASTName)
node = node.getParent(); declaration= declaration.getParent();
if (node instanceof ICPPASTFunctionDeclarator while (declaration instanceof IASTDeclarator)
&& node.getParent() instanceof IASTFunctionDefinition) { declaration= declaration.getParent();
ASTInternal.addDefinition(binding, node);
binding= checkDeclSpecifier(binding, data.astName, declaration);
if (!(binding instanceof IProblemBinding)) {
if (declaration instanceof ICPPASTFunctionDefinition) {
ASTInternal.addDefinition(binding, data.astName);
}
} }
} }
} }
// If we're still null... // If we're still null...
if (binding == null) { if (binding == null) {
if (name instanceof ICPPASTQualifiedName && data.forFunctionDeclaration()) { if (name instanceof ICPPASTQualifiedName && data.forFunctionDeclaration()) {
@ -469,7 +479,36 @@ public class CPPSemantics {
return binding; return binding;
} }
private static LookupData createLookupData(IASTName name, boolean considerAssociatedScopes) { static IBinding checkDeclSpecifier(IBinding binding, IASTName name, IASTNode decl) {
// check for empty declaration specifiers
if (!isCTorOrConversionOperator(binding)) {
IASTDeclSpecifier declspec= null;
if (decl instanceof IASTSimpleDeclaration) {
declspec= ((IASTSimpleDeclaration) decl).getDeclSpecifier();
} else if (decl instanceof IASTFunctionDefinition) {
declspec= ((IASTFunctionDefinition) decl).getDeclSpecifier();
}
if (declspec != null && CPPVisitor.doesNotSpecifyType(declspec)) {
binding= new ProblemBinding(name, IProblemBinding.SEMANTIC_INVALID_TYPE);
}
}
return binding;
}
private static boolean isCTorOrConversionOperator(IBinding binding) {
if (binding instanceof ICPPConstructor)
return true;
if (binding instanceof ICPPMethod) {
ICPPMethod m= (ICPPMethod) binding;
if (m.isDestructor())
return true;
return isConversionOperator(m);
}
return false;
}
private static LookupData createLookupData(IASTName name, boolean considerAssociatedScopes) {
LookupData data = new LookupData(name); LookupData data = new LookupData(name);
IASTNode parent = name.getParent(); IASTNode parent = name.getParent();
@ -1466,8 +1505,9 @@ public class CPPSemantics {
ASTInternal.addName(scope, name); ASTInternal.addName(scope, name);
return; return;
} }
if (declaration == null) if (declaration == null || declaration instanceof ASTAmbiguousNode) {
return; return;
}
if (declaration instanceof IASTSimpleDeclaration) { if (declaration instanceof IASTSimpleDeclaration) {
IASTSimpleDeclaration simpleDeclaration = (IASTSimpleDeclaration) declaration; IASTSimpleDeclaration simpleDeclaration = (IASTSimpleDeclaration) declaration;
@ -3056,7 +3096,7 @@ public class CPPSemantics {
ICPPASTTemplateDeclaration templateDecl = CPPTemplates.getTemplateDeclaration(name); ICPPASTTemplateDeclaration templateDecl = CPPTemplates.getTemplateDeclaration(name);
if (templateDecl != null) { if (templateDecl != null) {
if (templateDecl instanceof ICPPASTTemplateSpecialization) { if (templateDecl instanceof ICPPASTTemplateSpecialization) {
if (!(function instanceof ICPPTemplateInstance)) if (!(function instanceof ICPPSpecialization))
return false; return false;
} else { } else {
if (!(function instanceof ICPPTemplateDefinition)) if (!(function instanceof ICPPTemplateDefinition))

View file

@ -646,6 +646,10 @@ public class CPPVisitor extends ASTQueries {
if (binding instanceof ICPPInternalBinding && binding instanceof IFunction && name.isActive()) { if (binding instanceof ICPPInternalBinding && binding instanceof IFunction && name.isActive()) {
IFunction function = (IFunction) binding; IFunction function = (IFunction) binding;
if (CPPSemantics.isSameFunction(function, funcDeclarator)) { if (CPPSemantics.isSameFunction(function, funcDeclarator)) {
binding= CPPSemantics.checkDeclSpecifier(binding, name, parent);
if (binding instanceof IProblemBinding)
return binding;
ICPPInternalBinding internal = (ICPPInternalBinding) function; ICPPInternalBinding internal = (ICPPInternalBinding) function;
if (parent instanceof IASTSimpleDeclaration) { if (parent instanceof IASTSimpleDeclaration) {
ASTInternal.addDeclaration(internal, name); ASTInternal.addDeclaration(internal, name);
@ -676,6 +680,7 @@ public class CPPVisitor extends ASTQueries {
binding = template ? (ICPPFunction) new CPPFunctionTemplate(name) binding = template ? (ICPPFunction) new CPPFunctionTemplate(name)
: new CPPFunction((ICPPASTFunctionDeclarator) funcDeclarator); : new CPPFunction((ICPPASTFunctionDeclarator) funcDeclarator);
} }
binding= CPPSemantics.checkDeclSpecifier(binding, name, parent);
} else if (simpleDecl != null) { } else if (simpleDecl != null) {
IType t1 = null, t2 = null; IType t1 = null, t2 = null;
if (binding != null && binding instanceof IVariable && !(binding instanceof IIndexBinding)) { if (binding != null && binding instanceof IVariable && !(binding instanceof IIndexBinding)) {
@ -2098,4 +2103,22 @@ public class CPPVisitor extends ASTQueries {
} }
return false; return false;
} }
public static boolean doesNotSpecifyType(IASTDeclSpecifier declspec) {
if (declspec instanceof ICPPASTSimpleDeclSpecifier) {
ICPPASTSimpleDeclSpecifier ds= (ICPPASTSimpleDeclSpecifier) declspec;
if (ds.getType() == IASTSimpleDeclSpecifier.t_unspecified) {
if (ds instanceof IGPPASTSimpleDeclSpecifier) {
final IGPPASTSimpleDeclSpecifier gds = (IGPPASTSimpleDeclSpecifier) ds;
if (gds.isLongLong() || gds.getTypeofExpression() != null)
return false;
}
if (ds.isShort() || ds.isLong() || ds.isSigned() || ds.isUnsigned())
return false;
return true;
}
}
return false;
}
} }