mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-23 14:42:11 +02:00
Ambiguity between constructor and field declaration, bug 269953.
This commit is contained in:
parent
ba7561b70a
commit
fc1bd1306d
11 changed files with 1163 additions and 980 deletions
|
@ -2054,7 +2054,7 @@ public class AST2CPPSpecTest extends AST2SpecBaseTest {
|
|||
// *pi,
|
||||
// f(),
|
||||
// *fpi(int),
|
||||
// (*pif)(const char*, const char*);
|
||||
// (*pif)(const char*, const char*),
|
||||
// (*fpif(int))(int);
|
||||
public void test8_3_5s9a() throws Exception {
|
||||
parse(getAboveComment(), ParserLanguage.CPP, true, 0);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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.IASTDefaultStatement;
|
||||
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.IASTExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTExpressionList;
|
||||
|
@ -93,21 +94,35 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
|||
fDeclarator= d;
|
||||
}
|
||||
}
|
||||
protected static class FoundDeclaratorException extends Exception {
|
||||
private static final long serialVersionUID = 0;
|
||||
|
||||
protected static class Decl extends Exception {
|
||||
public Decl() {
|
||||
}
|
||||
|
||||
public IASTDeclSpecifier declSpec;
|
||||
public IASTDeclarator declarator;
|
||||
public IASTDeclSpecifier fDeclSpec1;
|
||||
public IASTDeclSpecifier fDeclSpec2;
|
||||
|
||||
public IASTDeclSpecifier altSpec;
|
||||
public IASTDeclarator altDeclarator;
|
||||
|
||||
public IToken currToken;
|
||||
public IASTDeclarator fDtor1;
|
||||
public IASTDeclarator fDtor2;
|
||||
public IToken fDtorToken1;
|
||||
|
||||
public FoundDeclaratorException(IASTDeclarator d, IToken t) {
|
||||
this.declarator = d;
|
||||
this.currToken =t;
|
||||
}
|
||||
public Decl set(IASTDeclSpecifier declspec, IASTDeclarator dtor, IToken dtorToken) {
|
||||
fDeclSpec1= declspec;
|
||||
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) {
|
||||
|
@ -1384,36 +1399,9 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
|||
return compoundStatement();
|
||||
}
|
||||
|
||||
protected abstract IASTDeclarator initDeclarator(DeclarationOptions option)
|
||||
protected abstract IASTDeclarator initDeclarator(IASTDeclSpecifier declSpec, DeclarationOptions option)
|
||||
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 &
|
||||
|
@ -1530,7 +1518,98 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
|||
|
||||
|
||||
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) {
|
||||
failParse();
|
||||
|
@ -1614,25 +1693,15 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
|||
|
||||
|
||||
protected IASTDeclaration functionStyleAsmDeclaration() throws BacktrackException, EndOfFileException {
|
||||
|
||||
final int offset= LA(1).getOffset();
|
||||
IASTDeclSpecifier declSpec= null;
|
||||
IASTDeclSpecifier declSpec;
|
||||
IASTDeclarator dtor;
|
||||
try {
|
||||
declSpec = declSpecifierSeq(DeclarationOptions.FUNCTION_STYLE_ASM);
|
||||
dtor = initDeclarator(DeclarationOptions.FUNCTION_STYLE_ASM);
|
||||
} catch (FoundDeclaratorException e) {
|
||||
if (e.altSpec != null) {
|
||||
declSpec= e.altSpec;
|
||||
dtor= e.altDeclarator;
|
||||
} else {
|
||||
declSpec = e.declSpec;
|
||||
dtor= e.declarator;
|
||||
}
|
||||
backup( e.currToken );
|
||||
} catch (FoundAggregateInitializer lie) {
|
||||
if (declSpec == null)
|
||||
declSpec= lie.fDeclSpec;
|
||||
Decl decl= declSpecifierSequence_initDeclarator(DeclarationOptions.FUNCTION_STYLE_ASM, false);
|
||||
declSpec= decl.fDeclSpec1;
|
||||
dtor= decl.fDtor1;
|
||||
} catch (FoundAggregateInitializer lie) {
|
||||
declSpec= lie.fDeclSpec;
|
||||
dtor= addInitializer(lie, DeclarationOptions.FUNCTION_STYLE_ASM);
|
||||
}
|
||||
|
||||
|
@ -1640,7 +1709,7 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
|||
throwBacktrack(LA(1));
|
||||
|
||||
final IASTDeclarator fdtor= ASTQueries.findTypeRelevantDeclarator(dtor);
|
||||
if (dtor instanceof IASTFunctionDeclarator == false)
|
||||
if (!(fdtor instanceof IASTFunctionDeclarator))
|
||||
throwBacktrack(offset, LA(1).getEndOffset() - offset);
|
||||
|
||||
final int compoundOffset= LA(1).getOffset();
|
||||
|
|
|
@ -27,7 +27,7 @@ public class DeclarationOptions {
|
|||
|
||||
public static final DeclarationOptions
|
||||
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),
|
||||
CPP_MEMBER= new DeclarationOptions(ALLOW_EMPTY_SPECIFIER | ALLOW_BITFIELD),
|
||||
LOCAL= new DeclarationOptions(ALLOW_CONSTRUCTOR_INITIALIZER),
|
||||
|
|
|
@ -291,64 +291,31 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
|
|||
return simpleDeclaration(declOption);
|
||||
}
|
||||
|
||||
private IASTDeclaration simpleDeclaration(final DeclarationOptions declOption)
|
||||
throws BacktrackException, EndOfFileException {
|
||||
private IASTDeclaration simpleDeclaration(final DeclarationOptions declOption) throws BacktrackException, EndOfFileException {
|
||||
if (LT(1) == IToken.tLBRACE)
|
||||
throwBacktrack(LA(1));
|
||||
|
||||
final int firstOffset= LA(1).getOffset();
|
||||
int endOffset= firstOffset;
|
||||
boolean insertSemi= false;
|
||||
boolean parseDtors= true;
|
||||
|
||||
IASTDeclSpecifier declSpec= null;
|
||||
IASTDeclarator dtor= null;
|
||||
IASTDeclSpecifier altDeclSpec= null;
|
||||
IASTDeclarator altDeclarator= null;
|
||||
IASTDeclarator altDtor= null;
|
||||
IToken markBeforDtor= null;
|
||||
try {
|
||||
declSpec = declSpecifierSeq(declOption);
|
||||
final int lt1= LTcatchEOF(1);
|
||||
switch(lt1) {
|
||||
case 0: // eof
|
||||
case IToken.tEOC:
|
||||
case IToken.tSEMI:
|
||||
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);
|
||||
}
|
||||
}
|
||||
Decl decl= declSpecifierSequence_initDeclarator(declOption, true);
|
||||
markBeforDtor= decl.fDtorToken1;
|
||||
declSpec= decl.fDeclSpec1;
|
||||
dtor= decl.fDtor1;
|
||||
altDeclSpec= decl.fDeclSpec2;
|
||||
altDtor= decl.fDtor2;
|
||||
} catch (FoundAggregateInitializer lie) {
|
||||
if (declSpec == null)
|
||||
declSpec= lie.fDeclSpec;
|
||||
declSpec= lie.fDeclSpec;
|
||||
// scalability: don't keep references to tokens, initializer may be large
|
||||
declarationMark= null;
|
||||
markBeforDtor= null;
|
||||
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) {
|
||||
IASTNode node= e.getNodeBeforeProblem();
|
||||
if (node instanceof IASTDeclSpecifier) {
|
||||
|
@ -360,12 +327,12 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
|
|||
}
|
||||
|
||||
IASTDeclarator[] declarators= IASTDeclarator.EMPTY_DECLARATOR_ARRAY;
|
||||
if (parseDtors) {
|
||||
if (dtor != null) {
|
||||
declarators= new IASTDeclarator[]{dtor};
|
||||
while (LTcatchEOF(1) == IToken.tCOMMA) {
|
||||
consume();
|
||||
try {
|
||||
dtor= initDeclarator(declOption);
|
||||
dtor= initDeclarator(declSpec, declOption);
|
||||
} catch (FoundAggregateInitializer e) {
|
||||
// scalability: don't keep references to tokens, initializer may be large
|
||||
declarationMark= null;
|
||||
|
@ -375,44 +342,44 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
|
|||
declarators= (IASTDeclarator[]) ArrayUtil.append( IASTDeclarator.class, declarators, dtor);
|
||||
}
|
||||
declarators= (IASTDeclarator[]) ArrayUtil.removeNulls( IASTDeclarator.class, declarators );
|
||||
}
|
||||
|
||||
final int lt1= LTcatchEOF(1);
|
||||
switch (lt1) {
|
||||
case IToken.tEOC:
|
||||
endOffset= figureEndOffset(declSpec, declarators);
|
||||
break;
|
||||
case IToken.tSEMI:
|
||||
endOffset= consume().getEndOffset();
|
||||
break;
|
||||
case IToken.tLBRACE:
|
||||
return functionDefinition(firstOffset, declSpec, declarators);
|
||||
|
||||
final int lt1= LTcatchEOF(1);
|
||||
switch (lt1) {
|
||||
case IToken.tLBRACE:
|
||||
return functionDefinition(firstOffset, declSpec, declarators);
|
||||
|
||||
case IToken.tSEMI:
|
||||
endOffset= consume().getEndOffset();
|
||||
break;
|
||||
case IToken.tEOC:
|
||||
endOffset= figureEndOffset(declSpec, declarators);
|
||||
break;
|
||||
default:
|
||||
if (declOption != DeclarationOptions.LOCAL) {
|
||||
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) {
|
||||
default:
|
||||
if (declOption != DeclarationOptions.LOCAL) {
|
||||
insertSemi= true;
|
||||
if (markBeforDtor != null) {
|
||||
endOffset= calculateEndOffset(declSpec);
|
||||
if (firstOffset != endOffset && !isOnSameLine(endOffset, markBeforDtor.getOffset())) {
|
||||
backup(markBeforDtor);
|
||||
declarators= IASTDeclarator.EMPTY_DECLARATOR_ARRAY;
|
||||
break;
|
||||
}
|
||||
if (firstOffset != endOffset) {
|
||||
if (!isOnSameLine(endOffset, LA(1).getOffset())) {
|
||||
break;
|
||||
}
|
||||
if (declarators.length == 1 && declarators[0] instanceof IASTFunctionDeclarator) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
endOffset= figureEndOffset(declSpec, declarators);
|
||||
if (lt1 == 0) {
|
||||
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
|
||||
|
@ -421,10 +388,10 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
|
|||
simpleDeclaration.addDeclarator(declarator);
|
||||
|
||||
setRange(simpleDeclaration, firstOffset, endOffset);
|
||||
if ( altDeclSpec != null && altDeclarator != null) {
|
||||
simpleDeclaration= new CASTAmbiguousSimpleDeclaration(simpleDeclaration, altDeclSpec, altDeclarator);
|
||||
setRange(simpleDeclaration, firstOffset, endOffset);
|
||||
}
|
||||
if (altDeclSpec != null && altDtor != null) {
|
||||
simpleDeclaration = new CASTAmbiguousSimpleDeclaration(simpleDeclaration, altDeclSpec, altDtor);
|
||||
setRange(simpleDeclaration, firstOffset, endOffset);
|
||||
}
|
||||
|
||||
if (insertSemi) {
|
||||
IASTProblem problem= createProblem(IProblem.SYNTAX_ERROR, endOffset, 0);
|
||||
|
@ -737,24 +704,18 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
|
|||
if (!canBeTypeSpecifier()) {
|
||||
return null;
|
||||
}
|
||||
IToken mark = mark();
|
||||
int startingOffset = mark.getOffset();
|
||||
final int offset = mark().getOffset();
|
||||
IASTDeclSpecifier declSpecifier = null;
|
||||
IASTDeclarator declarator = null;
|
||||
|
||||
fPreventKnrCheck++;
|
||||
try {
|
||||
try {
|
||||
declSpecifier= declSpecifierSeq(option);
|
||||
declarator= declarator(option);
|
||||
} catch (FoundDeclaratorException e) {
|
||||
declSpecifier= e.declSpec;
|
||||
declarator= e.declarator;
|
||||
backup(e.currToken);
|
||||
} catch (FoundAggregateInitializer lie) {
|
||||
// type-ids have not compound initializers
|
||||
return null;
|
||||
}
|
||||
Decl decl= declSpecifierSequence_initDeclarator(option, false);
|
||||
declSpecifier= decl.fDeclSpec1;
|
||||
declarator= decl.fDtor1;
|
||||
} catch (FoundAggregateInitializer lie) {
|
||||
// type-ids have not compound initializers
|
||||
return null;
|
||||
} catch (BacktrackException bt) {
|
||||
return null;
|
||||
} finally {
|
||||
|
@ -762,8 +723,7 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
|
|||
}
|
||||
|
||||
IASTTypeId result = nodeFactory.newTypeId(declSpecifier, declarator);
|
||||
((ASTNode) result).setOffsetAndLength(startingOffset, figureEndOffset(
|
||||
declSpecifier, declarator) - startingOffset);
|
||||
setRange(result, offset, figureEndOffset(declSpecifier, declarator));
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -828,292 +788,283 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
|
|||
SHORT=0x10, UNSIGNED= 0x20, SIGNED=0x40, COMPLEX=0x80, IMAGINARY=0x100;
|
||||
|
||||
@Override
|
||||
protected IASTDeclSpecifier declSpecifierSeq(final DeclarationOptions declOption)
|
||||
throws BacktrackException, EndOfFileException, FoundDeclaratorException, FoundAggregateInitializer {
|
||||
|
||||
final int offset= LA(1).getOffset();
|
||||
int endOffset= offset;
|
||||
protected Decl declSpecifierSeq(final DeclarationOptions declOption) throws BacktrackException, EndOfFileException {
|
||||
int storageClass= IASTDeclSpecifier.sc_unspecified;
|
||||
int simpleType= IASTSimpleDeclSpecifier.t_unspecified;
|
||||
int options= 0;
|
||||
int isLong= 0;
|
||||
|
||||
IASTName identifier= null;
|
||||
IASTDeclSpecifier result= null;
|
||||
IASTExpression typeofExpression= null;
|
||||
IASTProblem problem= null;
|
||||
IToken returnToken= null;
|
||||
IASTDeclSpecifier result= null;
|
||||
IASTDeclSpecifier altResult= null;
|
||||
try {
|
||||
IASTName identifier= null;
|
||||
IASTExpression typeofExpression= null;
|
||||
IASTProblem problem= null;
|
||||
|
||||
boolean encounteredRawType= false;
|
||||
boolean encounteredTypename= false;
|
||||
boolean encounteredRawType= false;
|
||||
boolean encounteredTypename= false;
|
||||
|
||||
declSpecifiers: for (;;) {
|
||||
final int lt1= LTcatchEOF(1);
|
||||
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;
|
||||
final int offset= LA(1).getOffset();
|
||||
int endOffset= offset;
|
||||
|
||||
// Function Specifier
|
||||
case IToken.t_inline:
|
||||
options |= INLINE;
|
||||
endOffset= consume().getEndOffset();
|
||||
break;
|
||||
declSpecifiers: for (;;) {
|
||||
final int lt1= LTcatchEOF(1);
|
||||
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;
|
||||
|
||||
// Type Qualifiers
|
||||
case IToken.t_const:
|
||||
options |= CONST;
|
||||
endOffset= consume().getEndOffset();
|
||||
break;
|
||||
case IToken.t_volatile:
|
||||
options |= VOLATILE;
|
||||
endOffset= consume().getEndOffset();
|
||||
break;
|
||||
case IToken.t_restrict:
|
||||
options |= RESTRICT;
|
||||
endOffset= consume().getEndOffset();
|
||||
break;
|
||||
// Function Specifier
|
||||
case IToken.t_inline:
|
||||
options |= INLINE;
|
||||
endOffset= consume().getEndOffset();
|
||||
break;
|
||||
|
||||
// Type Specifiers
|
||||
case IToken.t_void:
|
||||
if (encounteredTypename)
|
||||
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;
|
||||
// Type Qualifiers
|
||||
case IToken.t_const:
|
||||
options |= CONST;
|
||||
endOffset= consume().getEndOffset();
|
||||
break;
|
||||
case IToken.t_volatile:
|
||||
options |= VOLATILE;
|
||||
endOffset= consume().getEndOffset();
|
||||
break;
|
||||
case IToken.t_restrict:
|
||||
options |= RESTRICT;
|
||||
endOffset= consume().getEndOffset();
|
||||
break;
|
||||
|
||||
case IToken.tIDENTIFIER:
|
||||
case IToken.tCOMPLETION:
|
||||
case IToken.tEOC:
|
||||
if (encounteredTypename || encounteredRawType) {
|
||||
break declSpecifiers;
|
||||
}
|
||||
|
||||
try {
|
||||
if (endOffset != offset || declOption.fAllowEmptySpecifier) {
|
||||
lookAheadForDeclarator(declOption);
|
||||
}
|
||||
} catch (FoundAggregateInitializer e) {
|
||||
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);
|
||||
// Type Specifiers
|
||||
case IToken.t_void:
|
||||
if (encounteredTypename)
|
||||
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;
|
||||
|
||||
IToken mark= mark();
|
||||
try {
|
||||
final IASTName id= identifier(); // for the specifier
|
||||
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
|
||||
if (!supportAttributeSpecifiers)
|
||||
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;
|
||||
case IToken.tIDENTIFIER:
|
||||
case IToken.tCOMPLETION:
|
||||
case IToken.tEOC:
|
||||
if (encounteredTypename || encounteredRawType)
|
||||
break declSpecifiers;
|
||||
|
||||
case IGCCToken.t_typeof:
|
||||
if (encounteredRawType || encounteredTypename)
|
||||
throwBacktrack(LA(1));
|
||||
if ((endOffset != offset || declOption.fAllowEmptySpecifier) && LT(1) != IToken.tCOMPLETION) {
|
||||
altResult= buildSimpleDeclSpec(storageClass, simpleType, options, isLong, typeofExpression, offset, endOffset);
|
||||
returnToken= mark();
|
||||
}
|
||||
|
||||
final boolean wasInBinary= inBinaryExpression;
|
||||
try {
|
||||
inBinaryExpression= false;
|
||||
typeofExpression = parseTypeidInParenthesisOrUnaryExpression(false, consume().getOffset(),
|
||||
IGNUASTTypeIdExpression.op_typeof, IGNUASTUnaryExpression.op_typeof);
|
||||
} finally {
|
||||
inBinaryExpression= wasInBinary;
|
||||
}
|
||||
encounteredTypename= true;
|
||||
endOffset= calculateEndOffset(typeofExpression);
|
||||
break;
|
||||
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;
|
||||
|
||||
default:
|
||||
if (lt1 >= IExtensionToken.t__otherDeclSpecModifierFirst && lt1 <= IExtensionToken.t__otherDeclSpecModifierLast) {
|
||||
handleOtherDeclSpecModifier();
|
||||
endOffset= LA(1).getOffset();
|
||||
break;
|
||||
}
|
||||
break declSpecifiers;
|
||||
}
|
||||
case IGCCToken.t__attribute__: // if __attribute__ is after the declSpec
|
||||
if (!supportAttributeSpecifiers)
|
||||
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;
|
||||
|
||||
case IGCCToken.t_typeof:
|
||||
if (encounteredRawType || encounteredTypename)
|
||||
throwBacktrack(LA(1));
|
||||
|
||||
final boolean wasInBinary= inBinaryExpression;
|
||||
try {
|
||||
inBinaryExpression= false;
|
||||
typeofExpression = parseTypeidInParenthesisOrUnaryExpression(false, consume().getOffset(),
|
||||
IGNUASTTypeIdExpression.op_typeof, IGNUASTUnaryExpression.op_typeof);
|
||||
} finally {
|
||||
inBinaryExpression= wasInBinary;
|
||||
}
|
||||
encounteredTypename= true;
|
||||
endOffset= calculateEndOffset(typeofExpression);
|
||||
break;
|
||||
|
||||
default:
|
||||
if (lt1 >= IExtensionToken.t__otherDeclSpecModifierFirst && lt1 <= IExtensionToken.t__otherDeclSpecModifierLast) {
|
||||
handleOtherDeclSpecModifier();
|
||||
endOffset= LA(1).getOffset();
|
||||
break;
|
||||
}
|
||||
break declSpecifiers;
|
||||
}
|
||||
|
||||
if (encounteredRawType && encounteredTypename)
|
||||
throwBacktrack(LA(1));
|
||||
}
|
||||
if (encounteredRawType && encounteredTypename)
|
||||
throwBacktrack(LA(1));
|
||||
}
|
||||
|
||||
// check for empty specification
|
||||
if (!encounteredRawType && !encounteredTypename && LT(1) != IToken.tEOC && !declOption.fAllowEmptySpecifier) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
((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);
|
||||
Decl target= new Decl();
|
||||
target.fDeclSpec1= result;
|
||||
target.fDeclSpec2= altResult;
|
||||
target.fDtorToken1= returnToken;
|
||||
return target;
|
||||
}
|
||||
|
||||
private ICASTTypedefNameSpecifier buildNamedTypeSpecifier(IASTName name, int storageClass,
|
||||
|
@ -1155,31 +1106,6 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
|
|||
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.
|
||||
*
|
||||
|
@ -1266,11 +1192,18 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
|
|||
|
||||
|
||||
@Override
|
||||
protected IASTDeclarator initDeclarator(final DeclarationOptions option)
|
||||
protected IASTDeclarator initDeclarator(IASTDeclSpecifier declspec, final DeclarationOptions option)
|
||||
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);
|
||||
|
||||
IASTInitializer i = optionalCInitializer();
|
||||
|
@ -1296,7 +1229,7 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
|
|||
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();
|
||||
int endOffset = startingOffset;
|
||||
|
||||
|
@ -1342,7 +1275,7 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
|
|||
if (LT(1) == IToken.tRPAREN)
|
||||
throwBacktrack(LA(1));
|
||||
|
||||
final IASTDeclarator nested= declarator(option);
|
||||
final IASTDeclarator nested= declarator(declSpec, option);
|
||||
endOffset= consume(IToken.tRPAREN).getEndOffset();
|
||||
final IASTDeclarator cand2= declarator(pointerOps, null, nested, startingOffset, endOffset, option);
|
||||
if (cand1 == null || cand1End == null)
|
||||
|
@ -1734,14 +1667,11 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
|
|||
|
||||
try {
|
||||
fPreventKnrCheck++;
|
||||
declSpec= declSpecifierSeq(option);
|
||||
declarator = declarator(option);
|
||||
} catch(FoundDeclaratorException fd) {
|
||||
declSpec= fd.declSpec;
|
||||
declarator= fd.declarator;
|
||||
altDeclSpec= fd.altSpec;
|
||||
altDeclarator= fd.altDeclarator;
|
||||
backup(fd.currToken);
|
||||
Decl decl= declSpecifierSequence_initDeclarator(option, false);
|
||||
declSpec= decl.fDeclSpec1;
|
||||
declarator= decl.fDtor1;
|
||||
altDeclSpec= decl.fDeclSpec2;
|
||||
altDeclarator= decl.fDtor2;
|
||||
} catch (FoundAggregateInitializer lie) {
|
||||
declSpec= lie.fDeclSpec;
|
||||
declarator= lie.fDeclarator;
|
||||
|
@ -1755,8 +1685,8 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
|
|||
if (altDeclarator != null && altDeclSpec != null) {
|
||||
IASTParameterDeclaration alt = nodeFactory.newParameterDeclaration(altDeclSpec, altDeclarator);
|
||||
((ASTNode) alt).setOffsetAndLength(startingOffset, length);
|
||||
// order is important, prefer alternative over the declarator found via the lookahead.
|
||||
result= new CASTAmbiguousParameterDeclaration(alt, result);
|
||||
// order is important, prefer variant with declspec over the one without
|
||||
result= new CASTAmbiguousParameterDeclaration(result, alt);
|
||||
((ASTNode) result).setOffsetAndLength((ASTNode) alt);
|
||||
}
|
||||
return result;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -194,7 +194,7 @@ public class CPPFunction extends PlatformObject implements ICPPFunction, ICPPInt
|
|||
}
|
||||
|
||||
private ICPPASTFunctionDeclarator extractFunctionDtor(IASTNode node) {
|
||||
if (node instanceof IASTName)
|
||||
while (node instanceof IASTName)
|
||||
node = node.getParent();
|
||||
if (node instanceof IASTDeclarator == false)
|
||||
return null;
|
||||
|
|
|
@ -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.index.IIndexBinding;
|
||||
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;
|
||||
|
||||
/**
|
||||
|
@ -192,26 +193,34 @@ public class CPPFunctionSpecialization extends CPPSpecialization implements ICPP
|
|||
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
|
||||
public void addDefinition(IASTNode node) {
|
||||
IASTNode n = node;
|
||||
while (n instanceof IASTName)
|
||||
n = n.getParent();
|
||||
if (!(n instanceof ICPPASTFunctionDeclarator))
|
||||
return;
|
||||
updateParameterBindings((ICPPASTFunctionDeclarator) n);
|
||||
super.addDefinition(n);
|
||||
ICPPASTFunctionDeclarator dtor = extractFunctionDtor(node);
|
||||
if (dtor != null) {
|
||||
updateParameterBindings(dtor);
|
||||
super.addDefinition(dtor);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addDeclaration(IASTNode node) {
|
||||
IASTNode n = node;
|
||||
while (n instanceof IASTName)
|
||||
n = n.getParent();
|
||||
if (!(n instanceof ICPPASTFunctionDeclarator))
|
||||
return;
|
||||
updateParameterBindings((ICPPASTFunctionDeclarator) n);
|
||||
super.addDeclaration(n);
|
||||
ICPPASTFunctionDeclarator dtor = extractFunctionDtor(node);
|
||||
if (dtor != null) {
|
||||
updateParameterBindings(dtor);
|
||||
super.addDeclaration(dtor);
|
||||
}
|
||||
}
|
||||
|
||||
protected void updateParameterBindings(ICPPASTFunctionDeclarator fdtor) {
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -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.ICPPASTForStatement;
|
||||
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.ICPPASTLinkageSpecification;
|
||||
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.DebugUtil;
|
||||
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.ASTNode;
|
||||
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 (data.forFunctionDeclaration()) {
|
||||
IASTNode node = data.astName.getParent();
|
||||
if (node instanceof ICPPASTQualifiedName)
|
||||
node = node.getParent();
|
||||
if (node instanceof ICPPASTFunctionDeclarator
|
||||
&& node.getParent() instanceof IASTFunctionDefinition) {
|
||||
ASTInternal.addDefinition(binding, node);
|
||||
IASTNode declaration= data.astName;
|
||||
while (declaration instanceof IASTName)
|
||||
declaration= declaration.getParent();
|
||||
while (declaration instanceof IASTDeclarator)
|
||||
declaration= declaration.getParent();
|
||||
|
||||
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 (binding == null) {
|
||||
if (name instanceof ICPPASTQualifiedName && data.forFunctionDeclaration()) {
|
||||
|
@ -468,8 +478,37 @@ public class CPPSemantics {
|
|||
}
|
||||
return binding;
|
||||
}
|
||||
|
||||
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 LookupData createLookupData(IASTName name, boolean considerAssociatedScopes) {
|
||||
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);
|
||||
IASTNode parent = name.getParent();
|
||||
|
||||
|
@ -1466,9 +1505,10 @@ public class CPPSemantics {
|
|||
ASTInternal.addName(scope, name);
|
||||
return;
|
||||
}
|
||||
if (declaration == null)
|
||||
if (declaration == null || declaration instanceof ASTAmbiguousNode) {
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
if (declaration instanceof IASTSimpleDeclaration) {
|
||||
IASTSimpleDeclaration simpleDeclaration = (IASTSimpleDeclaration) declaration;
|
||||
ICPPASTDeclSpecifier declSpec = (ICPPASTDeclSpecifier) simpleDeclaration.getDeclSpecifier();
|
||||
|
@ -3056,7 +3096,7 @@ public class CPPSemantics {
|
|||
ICPPASTTemplateDeclaration templateDecl = CPPTemplates.getTemplateDeclaration(name);
|
||||
if (templateDecl != null) {
|
||||
if (templateDecl instanceof ICPPASTTemplateSpecialization) {
|
||||
if (!(function instanceof ICPPTemplateInstance))
|
||||
if (!(function instanceof ICPPSpecialization))
|
||||
return false;
|
||||
} else {
|
||||
if (!(function instanceof ICPPTemplateDefinition))
|
||||
|
|
|
@ -646,6 +646,10 @@ public class CPPVisitor extends ASTQueries {
|
|||
if (binding instanceof ICPPInternalBinding && binding instanceof IFunction && name.isActive()) {
|
||||
IFunction function = (IFunction) binding;
|
||||
if (CPPSemantics.isSameFunction(function, funcDeclarator)) {
|
||||
binding= CPPSemantics.checkDeclSpecifier(binding, name, parent);
|
||||
if (binding instanceof IProblemBinding)
|
||||
return binding;
|
||||
|
||||
ICPPInternalBinding internal = (ICPPInternalBinding) function;
|
||||
if (parent instanceof IASTSimpleDeclaration) {
|
||||
ASTInternal.addDeclaration(internal, name);
|
||||
|
@ -676,6 +680,7 @@ public class CPPVisitor extends ASTQueries {
|
|||
binding = template ? (ICPPFunction) new CPPFunctionTemplate(name)
|
||||
: new CPPFunction((ICPPASTFunctionDeclarator) funcDeclarator);
|
||||
}
|
||||
binding= CPPSemantics.checkDeclSpecifier(binding, name, parent);
|
||||
} else if (simpleDecl != null) {
|
||||
IType t1 = null, t2 = null;
|
||||
if (binding != null && binding instanceof IVariable && !(binding instanceof IIndexBinding)) {
|
||||
|
@ -2098,4 +2103,22 @@ public class CPPVisitor extends ASTQueries {
|
|||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue