1
0
Fork 0
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:
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,
// 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);

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.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();

View file

@ -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),

View file

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

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) {
if (node instanceof IASTName)
while (node instanceof IASTName)
node = node.getParent();
if (node instanceof IASTDeclarator == false)
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.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) {

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.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))

View file

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