1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-06-08 10:16:03 +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,20 +94,34 @@ 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;
} }
} }
@ -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,24 +1693,14 @@ 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) {
declSpec= e.altSpec;
dtor= e.altDeclarator;
} else {
declSpec = e.declSpec;
dtor= e.declarator;
}
backup( e.currToken );
} catch (FoundAggregateInitializer lie) { } catch (FoundAggregateInitializer lie) {
if (declSpec == null)
declSpec= lie.fDeclSpec; 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,18 +342,19 @@ 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:
return functionDefinition(firstOffset, declSpec, declarators);
case IToken.tSEMI:
endOffset= consume().getEndOffset();
break;
case IToken.tEOC: case IToken.tEOC:
endOffset= figureEndOffset(declSpec, declarators); endOffset= figureEndOffset(declSpec, declarators);
break; break;
case IToken.tSEMI:
endOffset= consume().getEndOffset();
break;
case IToken.tLBRACE:
return functionDefinition(firstOffset, declSpec, declarators);
default: default:
if (declOption != DeclarationOptions.LOCAL) { if (declOption != DeclarationOptions.LOCAL) {
insertSemi= true; insertSemi= true;
@ -413,7 +381,6 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
} }
throwBacktrack(LA(1)); throwBacktrack(LA(1));
} }
}
// no function body // no function body
IASTSimpleDeclaration simpleDeclaration = nodeFactory.newSimpleDeclaration(declSpec); IASTSimpleDeclaration simpleDeclaration = nodeFactory.newSimpleDeclaration(declSpec);
@ -421,8 +388,8 @@ 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);
} }
@ -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) {
declSpecifier= e.declSpec;
declarator= e.declarator;
backup(e.currToken);
} catch (FoundAggregateInitializer lie) { } catch (FoundAggregateInitializer lie) {
// type-ids have not compound initializers // type-ids have not compound initializers
return null; 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,24 +788,26 @@ 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;
IASTDeclSpecifier altResult= null;
try {
IASTName identifier= null;
IASTExpression typeofExpression= null; IASTExpression typeofExpression= null;
IASTProblem problem= null; IASTProblem problem= null;
boolean encounteredRawType= false; boolean encounteredRawType= false;
boolean encounteredTypename= false; boolean encounteredTypename= false;
final int offset= LA(1).getOffset();
int endOffset= offset;
declSpecifiers: for (;;) { declSpecifiers: for (;;) {
final int lt1= LTcatchEOF(1); final int lt1= LTcatchEOF(1);
switch (lt1) { switch (lt1) {
@ -980,37 +942,14 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
case IToken.tIDENTIFIER: case IToken.tIDENTIFIER:
case IToken.tCOMPLETION: case IToken.tCOMPLETION:
case IToken.tEOC: case IToken.tEOC:
if (encounteredTypename || encounteredRawType) { if (encounteredTypename || encounteredRawType)
break declSpecifiers; break declSpecifiers;
if ((endOffset != offset || declOption.fAllowEmptySpecifier) && LT(1) != IToken.tCOMPLETION) {
altResult= buildSimpleDeclSpec(storageClass, simpleType, options, isLong, typeofExpression, offset, endOffset);
returnToken= mark();
} }
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);
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(); identifier = identifier();
endOffset= calculateEndOffset(identifier); endOffset= calculateEndOffset(identifier);
encounteredTypename= true; encounteredTypename= true;
@ -1103,17 +1042,29 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
((CASTElaboratedTypeSpecifier) result).setRestrict(true); ((CASTElaboratedTypeSpecifier) result).setRestrict(true);
} }
} }
((ASTNode) result).setOffsetAndLength(offset, endOffset - offset); setRange(result, offset, endOffset);
if (problem != null) if (problem != null)
throwBacktrack(problem, result); throwBacktrack(problem, result);
} else if (identifier != null) {
return result; result= buildNamedTypeSpecifier(identifier, storageClass, options, offset, endOffset);
} else {
result= buildSimpleDeclSpec(storageClass, simpleType, options, isLong, typeofExpression, offset, endOffset);
} }
} catch (BacktrackException e) {
if (identifier != null) if (returnToken != null) {
return buildNamedTypeSpecifier(identifier, storageClass, options, offset, endOffset); backup(returnToken);
result= altResult;
return buildSimpleDeclSpec(storageClass, simpleType, options, isLong, typeofExpression, offset, endOffset); altResult= null;
returnToken= null;
} else {
throw e;
}
}
Decl target= new Decl();
target.fDeclSpec1= result;
target.fDeclSpec2= altResult;
target.fDtorToken1= returnToken;
return target;
} }
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

@ -32,7 +32,6 @@ import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTDeclaration; import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTDeclarator; import org.eclipse.cdt.core.dom.ast.IASTDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTElaboratedTypeSpecifier; 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.IASTExpression;
import org.eclipse.cdt.core.dom.ast.IASTFieldDeclarator; import org.eclipse.cdt.core.dom.ast.IASTFieldDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTFunctionCallExpression; import org.eclipse.cdt.core.dom.ast.IASTFunctionCallExpression;
@ -132,6 +131,7 @@ import org.eclipse.cdt.internal.core.dom.parser.BacktrackException;
import org.eclipse.cdt.internal.core.dom.parser.DeclarationOptions; import org.eclipse.cdt.internal.core.dom.parser.DeclarationOptions;
import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguousExpression; import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguousExpression;
import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguousStatement; import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguousStatement;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor;
/** /**
* This is our implementation of the IParser interface, serving as a parser for * This is our implementation of the IParser interface, serving as a parser for
@ -1674,61 +1674,27 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
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;
ICPPASTDeclSpecifier declSpec= null; IASTDeclSpecifier declSpec= null;
IASTDeclarator dtor= null; IASTDeclarator dtor= null;
IASTDeclSpecifier altDeclSpec= 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;
if (lt1 != IToken.tEOC && !validWithoutDtor(declOption, declSpec))
throwBacktrack(LA(1));
parseDtors= false;
insertSemi= lt1==0;
if (lt1 == IToken.tSEMI)
endOffset= consume().getEndOffset();
else
endOffset= calculateEndOffset(declSpec);
break;
case IToken.tCOMMA:
throwBacktrack(LA(1));
break;
default:
markBeforDtor= mark();
try {
dtor= initDeclarator(declSpec, declOption);
} catch (BacktrackException e) {
if (!validWithoutDtor(declOption, declSpec))
throw e;
backup(markBeforDtor);
} catch (EndOfFileException e) {
if (!validWithoutDtor(declOption, declSpec))
throw e;
backup(markBeforDtor);
}
break;
}
} catch (FoundAggregateInitializer lie) { } catch (FoundAggregateInitializer lie) {
if (declSpec == null) declSpec= lie.fDeclSpec;
declSpec= (ICPPASTDeclSpecifier) 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) {
declSpec= (ICPPASTDeclSpecifier) 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 ICPPASTDeclSpecifier && validWithoutDtor(declOption, (ICPPASTDeclSpecifier) node)) { if (node instanceof IASTDeclSpecifier && specifiesCompound((IASTDeclSpecifier) node)) {
IASTSimpleDeclaration d= nodeFactory.newSimpleDeclaration((IASTDeclSpecifier) node); IASTSimpleDeclaration d= nodeFactory.newSimpleDeclaration((IASTDeclSpecifier) node);
setRange(d, node); setRange(d, node);
throwBacktrack(e.getProblem(), d); throwBacktrack(e.getProblem(), d);
@ -1737,7 +1703,7 @@ public class GNUCPPSourceParser 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();
@ -1752,6 +1718,7 @@ public class GNUCPPSourceParser 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) {
@ -1768,14 +1735,12 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
default: default:
if (declOption != DeclarationOptions.LOCAL) { if (declOption != DeclarationOptions.LOCAL) {
insertSemi= true; insertSemi= true;
if (validWithoutDtor(declOption, declSpec)) { if (specifiesCompound(declSpec) && markBeforDtor != null && !isOnSameLine(calculateEndOffset(declSpec), markBeforDtor.getOffset())) {
if (markBeforDtor != null && !isOnSameLine(calculateEndOffset(declSpec), markBeforDtor.getOffset())) {
backup(markBeforDtor); backup(markBeforDtor);
declarators= IASTDeclarator.EMPTY_DECLARATOR_ARRAY; declarators= IASTDeclarator.EMPTY_DECLARATOR_ARRAY;
endOffset= calculateEndOffset(declSpec); endOffset= calculateEndOffset(declSpec);
break; break;
} }
}
endOffset= figureEndOffset(declSpec, declarators); endOffset= figureEndOffset(declSpec, declarators);
if (lt1 == 0 || !isOnSameLine(endOffset, LA(1).getOffset())) { if (lt1 == 0 || !isOnSameLine(endOffset, LA(1).getOffset())) {
break; break;
@ -1786,15 +1751,28 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
} }
throwBacktrack(LA(1)); throwBacktrack(LA(1));
} }
}
// no function body // no function body
IASTSimpleDeclaration simpleDeclaration= nodeFactory.newSimpleDeclaration(declSpec);
final boolean isAmbiguous= altDeclSpec != null && altDtor != null && declarators.length == 1;
IASTSimpleDeclaration simpleDeclaration;
if (isAmbiguous) {
// class C { C(T); }; // if T is a type this is a constructor, so
// prefer the empty declspec, it shall be used if both variants show no problems
simpleDeclaration= nodeFactory.newSimpleDeclaration(altDeclSpec);
simpleDeclaration.addDeclarator(altDtor);
} else {
simpleDeclaration= nodeFactory.newSimpleDeclaration(declSpec);
for (IASTDeclarator declarator : declarators) { for (IASTDeclarator declarator : declarators) {
simpleDeclaration.addDeclarator(declarator); simpleDeclaration.addDeclarator(declarator);
} }
}
((ASTNode) simpleDeclaration).setOffsetAndLength(firstOffset, endOffset-firstOffset); setRange(simpleDeclaration, firstOffset, endOffset);
if (isAmbiguous) {
simpleDeclaration = new CPPASTAmbiguousSimpleDeclaration(simpleDeclaration, declSpec, dtor);
setRange(simpleDeclaration, firstOffset, endOffset);
}
if (insertSemi) { if (insertSemi) {
IASTProblem problem= createProblem(IProblem.SYNTAX_ERROR, endOffset, 0); IASTProblem problem= createProblem(IProblem.SYNTAX_ERROR, endOffset, 0);
@ -1803,17 +1781,6 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
return simpleDeclaration; return simpleDeclaration;
} }
private boolean validWithoutDtor(DeclarationOptions option, ICPPASTDeclSpecifier declSpec) {
if (declSpec instanceof IASTCompositeTypeSpecifier)
return true;
if (declSpec instanceof IASTElaboratedTypeSpecifier)
return true;
if (declSpec instanceof IASTEnumerationSpecifier)
return true;
return option == DeclarationOptions.FUNCTION_STYLE_ASM;
}
private IASTDeclaration functionDefinition(final int firstOffset, IASTDeclSpecifier declSpec, private IASTDeclaration functionDefinition(final int firstOffset, IASTDeclSpecifier declSpec,
IASTDeclarator[] dtors) throws EndOfFileException, BacktrackException { IASTDeclarator[] dtors) throws EndOfFileException, BacktrackException {
@ -1939,21 +1906,17 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
IASTDeclSpecifier declSpec= null; IASTDeclSpecifier declSpec= null;
IASTDeclarator declarator; IASTDeclarator declarator;
try { try {
declSpec= declSpecifierSeq(DeclarationOptions.PARAMETER); Decl decl= declSpecifierSequence_initDeclarator(DeclarationOptions.PARAMETER, false);
declarator= initDeclarator(declSpec, DeclarationOptions.PARAMETER); declSpec= decl.fDeclSpec1;
} catch (FoundDeclaratorException e) { declarator= decl.fDtor1;
declSpec= e.declSpec;
declarator= e.declarator;
backup(e.currToken);
} catch (FoundAggregateInitializer lie) { } catch (FoundAggregateInitializer lie) {
if (declSpec == null)
declSpec= lie.fDeclSpec; declSpec= lie.fDeclSpec;
declarator= addInitializer(lie, DeclarationOptions.PARAMETER); declarator= addInitializer(lie, DeclarationOptions.PARAMETER);
} }
final ICPPASTParameterDeclaration parm = nodeFactory.newParameterDeclaration(declSpec, declarator); final ICPPASTParameterDeclaration parm = nodeFactory.newParameterDeclaration(declSpec, declarator);
final int endOffset = figureEndOffset(declSpec, declarator); final int endOffset = figureEndOffset(declSpec, declarator);
((ASTNode) parm).setOffsetAndLength(startOffset, endOffset - startOffset); setRange(parm, startOffset, endOffset);
return parm; return parm;
} }
@ -1961,6 +1924,8 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
private final static int INLINE=0x1, CONST=0x2, RESTRICT=0x4, VOLATILE=0x8, private final static int INLINE=0x1, CONST=0x2, RESTRICT=0x4, VOLATILE=0x8,
SHORT=0x10, UNSIGNED= 0x20, SIGNED=0x40, COMPLEX=0x80, IMAGINARY=0x100, SHORT=0x10, UNSIGNED= 0x20, SIGNED=0x40, COMPLEX=0x80, IMAGINARY=0x100,
VIRTUAL=0x200, EXPLICIT=0x400, FRIEND=0x800; VIRTUAL=0x200, EXPLICIT=0x400, FRIEND=0x800;
private static final int FORBID_IN_EMPTY_DECLSPEC =
CONST | RESTRICT | VOLATILE | SHORT | UNSIGNED | SIGNED | COMPLEX | IMAGINARY | FRIEND;
/** /**
@ -1976,18 +1941,19 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
* ("typename")? name | * ("typename")? name |
* { "class" | "struct" | "union" } classSpecifier | * { "class" | "struct" | "union" } classSpecifier |
* {"enum"} enumSpecifier * {"enum"} enumSpecifier
* @throws FoundAggregateInitializer
*/ */
@Override @Override
protected ICPPASTDeclSpecifier declSpecifierSeq(final DeclarationOptions option) protected Decl declSpecifierSeq(final DeclarationOptions option) throws BacktrackException, EndOfFileException {
throws BacktrackException, EndOfFileException, FoundDeclaratorException, FoundAggregateInitializer {
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;
ICPPASTDeclSpecifier result= null; ICPPASTDeclSpecifier result= null;
ICPPASTDeclSpecifier altResult= null;
try {
IASTName identifier= null;
IASTExpression typeofExpression= null; IASTExpression typeofExpression= null;
IASTProblem problem= null; IASTProblem problem= null;
@ -2163,18 +2129,10 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
if (encounteredRawType || encounteredTypename) if (encounteredRawType || encounteredTypename)
break declSpecifiers; break declSpecifiers;
try {
if (option.fAllowEmptySpecifier && LT(1) != IToken.tCOMPLETION) { if (option.fAllowEmptySpecifier && LT(1) != IToken.tCOMPLETION) {
lookAheadForDeclarator(option); if ((options & FORBID_IN_EMPTY_DECLSPEC) == 0 && storageClass == IASTDeclSpecifier.sc_unspecified) {
} altResult= buildSimpleDeclSpec(storageClass, simpleType, options, isLong, typeofExpression, offset, endOffset);
} catch (FoundAggregateInitializer e) { returnToken= mark();
e.fDeclSpec= buildSimpleDeclSpec(storageClass, simpleType, options, isLong, typeofExpression, offset, endOffset);
throw e;
}catch (FoundDeclaratorException e) {
if (e.currToken.getType() == IToken.tEOC || option == DeclarationOptions.FUNCTION_STYLE_ASM
|| canBeConstructorDestructorOrConversion(option, storageClass, options, e.declarator)) {
e.declSpec= buildSimpleDeclSpec(storageClass, simpleType, options, isLong, typeofExpression, offset, endOffset);
throw e;
} }
} }
@ -2268,49 +2226,31 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
// cannot store restrict in the cpp-nodes. // cannot store restrict in the cpp-nodes.
// if ((options & RESTRICT) != 0) { // if ((options & RESTRICT) != 0) {
// } // }
((ASTNode) result).setOffsetAndLength(offset, endOffset - offset); setRange(result, offset, endOffset);
if (problem != null) { if (problem != null) {
throwBacktrack(problem, result); throwBacktrack(problem, result);
} }
return result; } else if (identifier != null) {
result= buildNamedTypeSpecifier(identifier, isTypename, storageClass, options, offset, endOffset);
} else {
result= buildSimpleDeclSpec(storageClass, simpleType, options, isLong, typeofExpression, offset, endOffset);
} }
} catch (BacktrackException e) {
if (identifier != null) if (returnToken != null) {
return buildNamedTypeSpecifier(identifier, isTypename, storageClass, options, offset, endOffset); backup(returnToken);
result= altResult;
return buildSimpleDeclSpec(storageClass, simpleType, options, isLong, typeofExpression, offset, endOffset); altResult= null;
} returnToken= null;
} else {
private boolean canBeConstructorDestructorOrConversion(DeclarationOptions declOption, int storageClass, int options, IASTDeclarator dtor) { throw e;
final int forbid= CONST | RESTRICT | VOLATILE | SHORT | UNSIGNED | SIGNED | COMPLEX | IMAGINARY | FRIEND;
if (storageClass == IASTDeclSpecifier.sc_unspecified && (options & forbid) == 0) {
if (ASTQueries.findTypeRelevantDeclarator(dtor) instanceof IASTFunctionDeclarator) {
IASTName name= ASTQueries.findInnermostDeclarator(dtor).getName();
if (name instanceof ICPPASTQualifiedName) {
final ICPPASTQualifiedName qname = (ICPPASTQualifiedName) name;
final IASTName names[]= qname.getNames();
final int len = names.length;
final IASTName lastName = names[len-1];
if (len > 1 && CharArrayUtils.equals(names[len-2].getLookupKey(), lastName.getLookupKey()))
return true; // constructor
name= lastName;
}
if (name instanceof ICPPASTTemplateId)
name= ((ICPPASTTemplateId) name).getTemplateName();
if (name instanceof ICPPASTConversionName)
return true;
final char[] nchars= name.getLookupKey();
if (nchars.length > 0 && nchars[0] == '~')
return true; // destructor
if (declOption == DeclarationOptions.CPP_MEMBER && CharArrayUtils.equals(nchars, currentClassName))
return true;
} }
} }
return false;
Decl target= new Decl();
target.fDeclSpec1= result;
target.fDeclSpec2= altResult;
target.fDtorToken1= returnToken;
return target;
} }
private ICPPASTNamedTypeSpecifier buildNamedTypeSpecifier(IASTName name, boolean isTypename, private ICPPASTNamedTypeSpecifier buildNamedTypeSpecifier(IASTName name, boolean isTypename,
@ -2364,39 +2304,6 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
declSpec.setExplicit((options & EXPLICIT) != 0); declSpec.setExplicit((options & EXPLICIT) != 0);
} }
@Override
protected boolean verifyLookaheadDeclarator(DeclarationOptions option, IASTDeclarator dtor, IToken nextToken) {
switch (nextToken.getType()) {
case IToken.tCOMMA:
return true;
case IToken.tCOLON:
case IToken.t_try:
case IToken.t_catch:
case IToken.tLBRACE:
case IToken.t_const:
case IToken.t_volatile:
if (option == DeclarationOptions.GLOBAL || option == DeclarationOptions.CPP_MEMBER
|| option == DeclarationOptions.FUNCTION_STYLE_ASM) {
if (ASTQueries.findTypeRelevantDeclarator(dtor) instanceof IASTFunctionDeclarator) {
return true;
}
}
break;
case IToken.tSEMI:
return option == DeclarationOptions.GLOBAL || option == DeclarationOptions.CPP_MEMBER ||
option == DeclarationOptions.LOCAL;
case IToken.tRPAREN:
return option == DeclarationOptions.PARAMETER;
case IToken.tEOC:
return true;
}
return false;
}
/** /**
* Parse an elaborated type specifier. * Parse an elaborated type specifier.
* *
@ -2436,14 +2343,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
return elaboratedTypeSpec; return elaboratedTypeSpec;
} }
@Override @Override
protected IASTDeclarator initDeclarator(DeclarationOptions option)
throws EndOfFileException, BacktrackException, FoundAggregateInitializer {
// called from the lookahead, only.
return initDeclarator(DtorStrategy.PREFER_FUNCTION, option);
}
protected IASTDeclarator initDeclarator(IASTDeclSpecifier declspec, DeclarationOptions option) protected IASTDeclarator initDeclarator(IASTDeclSpecifier declspec, DeclarationOptions option)
throws EndOfFileException, BacktrackException, FoundAggregateInitializer { throws EndOfFileException, BacktrackException, FoundAggregateInitializer {
final IToken mark= mark(); final IToken mark= mark();
@ -2453,16 +2353,33 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
BacktrackException bt= null; BacktrackException bt= null;
try { try {
dtor1= initDeclarator(DtorStrategy.PREFER_FUNCTION, option); dtor1= initDeclarator(DtorStrategy.PREFER_FUNCTION, option);
if (dtor1 instanceof IASTFunctionDeclarator == false) verifyDtor(declspec, dtor1, option);
int lt1= LTcatchEOF(1);
switch(lt1) {
case 0:
return dtor1;
case IToken.tCOLON:
// a colon can be used after a type-id in a conditional expression
if (option != DeclarationOptions.CPP_MEMBER && option != DeclarationOptions.GLOBAL)
break;
//$FALL-THROUGH$
case IToken.tLBRACE:
case IToken.t_throw: case IToken.t_try:
case IToken.t_const: case IToken.t_volatile:
if (ASTQueries.findTypeRelevantDeclarator(dtor1) instanceof IASTFunctionDeclarator) {
return dtor1;
} else {
dtor1= null;
throwBacktrack(LA(1));
}
}
if (!(dtor1 instanceof IASTFunctionDeclarator))
return dtor1; return dtor1;
end1= LA(1); end1= LA(1);
switch(end1.getType()) {
case IToken.tLBRACE: case IToken.tCOLON:
case IToken.t_throw: case IToken.t_try:
case IToken.t_const: case IToken.t_volatile:
return dtor1;
}
} catch (BacktrackException e) { } catch (BacktrackException e) {
bt= e; bt= e;
} }
@ -2502,6 +2419,45 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
return dtor; return dtor;
} }
/**
* Tries to detect illegal versions of declarations
*/
private void verifyDtor(IASTDeclSpecifier declspec, IASTDeclarator dtor, DeclarationOptions opt) throws BacktrackException {
if (CPPVisitor.doesNotSpecifyType(declspec)) {
if (ASTQueries.findTypeRelevantDeclarator(dtor) instanceof IASTFunctionDeclarator) {
boolean isQualified= false;
IASTName name= ASTQueries.findInnermostDeclarator(dtor).getName();
if (name instanceof ICPPASTQualifiedName) {
isQualified= true;
name= name.getLastName();
}
if (name instanceof ICPPASTTemplateId)
name= ((ICPPASTTemplateId) name).getTemplateName();
// accept conversion operator
if (name instanceof ICPPASTConversionName)
return;
// accept destructor
final char[] nchars= name.getLookupKey();
if (nchars.length > 0 && nchars[0] == '~')
return;
if (opt == DeclarationOptions.CPP_MEMBER) {
// accept constructor within class body
if (CharArrayUtils.equals(nchars, currentClassName))
return;
} else if (isQualified) {
// accept qualified constructor outside of class body
return;
}
}
ASTNode node= (ASTNode) dtor;
throwBacktrack(node.getOffset(), node.getLength());
}
}
private boolean canHaveConstructorInitializer(IASTDeclSpecifier declspec, IASTDeclarator dtor) { private boolean canHaveConstructorInitializer(IASTDeclSpecifier declspec, IASTDeclarator dtor) {
if (declspec instanceof ICPPASTDeclSpecifier) { if (declspec instanceof ICPPASTDeclSpecifier) {
ICPPASTDeclSpecifier cppspec= (ICPPASTDeclSpecifier) declspec; ICPPASTDeclSpecifier cppspec= (ICPPASTDeclSpecifier) declspec;
@ -2686,19 +2642,15 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
if (!canBeTypeSpecifier()) { if (!canBeTypeSpecifier()) {
return null; return null;
} }
int startingOffset = mark().getOffset(); final int offset = mark().getOffset();
IASTDeclSpecifier declSpecifier = null; IASTDeclSpecifier declSpecifier = null;
IASTDeclarator declarator = null; IASTDeclarator declarator = null;
rejectLogicalOperatorInTemplateID++; rejectLogicalOperatorInTemplateID++;
try { try {
declSpecifier = declSpecifierSeq(option); Decl decl= declSpecifierSequence_initDeclarator(option, false);
if (LT(1) != IToken.tEOC) { declSpecifier= decl.fDeclSpec1;
declarator= declarator(DtorStrategy.PREFER_FUNCTION, option); declarator= decl.fDtor1;
}
} catch (FoundDeclaratorException e) {
declSpecifier= e.declSpec;
declarator= e.declarator;
backup(e.currToken);
} catch (FoundAggregateInitializer lie) { } catch (FoundAggregateInitializer lie) {
// type-ids have no initializers // type-ids have no initializers
return null; return null;
@ -2708,7 +2660,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
rejectLogicalOperatorInTemplateID--; rejectLogicalOperatorInTemplateID--;
} }
IASTTypeId result = nodeFactory.newTypeId(declSpecifier, declarator); IASTTypeId result = nodeFactory.newTypeId(declSpecifier, declarator);
((ASTNode) result).setOffsetAndLength(startingOffset, figureEndOffset(declSpecifier, declarator) - startingOffset); setRange(result, offset, figureEndOffset(declSpecifier, declarator));
return result; return result;
} }
@ -3343,27 +3295,23 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
private IASTSimpleDeclaration simpleSingleDeclaration(DeclarationOptions options) throws BacktrackException, EndOfFileException { private IASTSimpleDeclaration simpleSingleDeclaration(DeclarationOptions options) throws BacktrackException, EndOfFileException {
final int startOffset= LA(1).getOffset(); final int startOffset= LA(1).getOffset();
IASTDeclSpecifier declSpec= null; IASTDeclSpecifier declSpec;
IASTDeclarator declarator; IASTDeclarator declarator;
try { try {
declSpec= declSpecifierSeq(options); Decl decl= declSpecifierSequence_initDeclarator(options, true);
declarator= initDeclarator(declSpec, options); declSpec= decl.fDeclSpec1;
} catch (FoundDeclaratorException e) { declarator= decl.fDtor1;
declSpec= e.declSpec;
declarator= e.declarator;
backup(e.currToken);
} catch (FoundAggregateInitializer lie) { } catch (FoundAggregateInitializer lie) {
if (declSpec == null)
declSpec= lie.fDeclSpec; declSpec= lie.fDeclSpec;
declarator= addInitializer(lie, options); declarator= addInitializer(lie, options);
} }
final int endOffset = figureEndOffset(declSpec, declarator); final int endOffset = figureEndOffset(declSpec, declarator);
final IASTSimpleDeclaration decl= nodeFactory.newSimpleDeclaration(declSpec); final IASTSimpleDeclaration decl= nodeFactory.newSimpleDeclaration(declSpec);
if (declarator != null)
decl.addDeclarator(declarator); decl.addDeclarator(declarator);
((ASTNode) decl).setOffsetAndLength(startOffset, endOffset - startOffset); ((ASTNode) decl).setOffsetAndLength(startOffset, endOffset - startOffset);
return decl; return decl;
} }

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,6 +479,35 @@ public class CPPSemantics {
return binding; 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 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) { 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;
}
} }