diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPSpecTest.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPSpecTest.java index 3564afcc35a..3b5d701095a 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPSpecTest.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPSpecTest.java @@ -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); diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java index 5feb51138a5..d6365da103e 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java @@ -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 Compare { + // Compare(); + // ~Compare(); + // bool check; + // }; + // typedef Compare MY_COMPARE; + // template<> MY_COMPARE::Compare() {} + public void testTemplateCTorWithTypedef_Bug269953() throws Exception { + final String code = getAboveComment(); + parseAndCheckBindings(code, ParserLanguage.CPP); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/AbstractGNUSourceCodeParser.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/AbstractGNUSourceCodeParser.java index 236462c657a..5d872a4de79 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/AbstractGNUSourceCodeParser.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/AbstractGNUSourceCodeParser.java @@ -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(); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/DeclarationOptions.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/DeclarationOptions.java index 908ac9fc722..c4f3435dec0 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/DeclarationOptions.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/DeclarationOptions.java @@ -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), diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/GNUCSourceParser.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/GNUCSourceParser.java index 4c45087853c..35e5b9a08bc 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/GNUCSourceParser.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/GNUCSourceParser.java @@ -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; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTAmbiguousSimpleDeclaration.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTAmbiguousSimpleDeclaration.java new file mode 100644 index 00000000000..57e19cef7bb --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTAmbiguousSimpleDeclaration.java @@ -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. + *
+ * 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; + } +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFunction.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFunction.java index e22f981751e..894a4969147 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFunction.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFunction.java @@ -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; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFunctionSpecialization.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFunctionSpecialization.java index 46e9f8a966a..9f755ab3c5a 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFunctionSpecialization.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFunctionSpecialization.java @@ -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) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java index 60d1da36c40..f0618f83784 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java @@ -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.IASTDeclarator; 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.IASTFieldDeclarator; 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.IASTAmbiguousExpression; 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 @@ -1674,61 +1674,27 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { final int firstOffset= LA(1).getOffset(); int endOffset= firstOffset; boolean insertSemi= false; - boolean parseDtors= true; - ICPPASTDeclSpecifier declSpec= null; + IASTDeclSpecifier declSpec= null; IASTDeclarator dtor= null; + IASTDeclSpecifier altDeclSpec= 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: - 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; - } + 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= (ICPPASTDeclSpecifier) 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) { - declSpec= (ICPPASTDeclSpecifier) e.declSpec; - dtor= e.declarator; - backup(e.currToken); } catch (BacktrackException e) { 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); setRange(d, node); throwBacktrack(e.getProblem(), d); @@ -1737,7 +1703,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { } IASTDeclarator[] declarators= IASTDeclarator.EMPTY_DECLARATOR_ARRAY; - if (parseDtors) { + if (dtor != null) { declarators= new IASTDeclarator[]{dtor}; while (LTcatchEOF(1) == IToken.tCOMMA) { consume(); @@ -1752,50 +1718,62 @@ public class GNUCPPSourceParser 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.t_try: - case IToken.tCOLON: - case IToken.tLBRACE: - return functionDefinition(firstOffset, declSpec, declarators); - default: - if (declOption != DeclarationOptions.LOCAL) { - insertSemi= true; - if (validWithoutDtor(declOption, declSpec)) { - if (markBeforDtor != null && !isOnSameLine(calculateEndOffset(declSpec), markBeforDtor.getOffset())) { - backup(markBeforDtor); - declarators= IASTDeclarator.EMPTY_DECLARATOR_ARRAY; - endOffset= calculateEndOffset(declSpec); - break; - } - } - endOffset= figureEndOffset(declSpec, declarators); - if (lt1 == 0 || !isOnSameLine(endOffset, LA(1).getOffset())) { - break; - } - if (declarators.length == 1 && declarators[0] instanceof IASTFunctionDeclarator) { - break; - } - } - throwBacktrack(LA(1)); - } } - // no function body - IASTSimpleDeclaration simpleDeclaration= nodeFactory.newSimpleDeclaration(declSpec); - for (IASTDeclarator declarator : declarators) { - simpleDeclaration.addDeclarator(declarator); + final int lt1= LTcatchEOF(1); + switch (lt1) { + case IToken.tEOC: + endOffset= figureEndOffset(declSpec, declarators); + break; + case IToken.tSEMI: + endOffset= consume().getEndOffset(); + break; + case IToken.t_try: + case IToken.tCOLON: + case IToken.tLBRACE: + return functionDefinition(firstOffset, declSpec, declarators); + default: + if (declOption != DeclarationOptions.LOCAL) { + insertSemi= true; + if (specifiesCompound(declSpec) && markBeforDtor != null && !isOnSameLine(calculateEndOffset(declSpec), markBeforDtor.getOffset())) { + backup(markBeforDtor); + declarators= IASTDeclarator.EMPTY_DECLARATOR_ARRAY; + endOffset= calculateEndOffset(declSpec); + break; + } + endOffset= figureEndOffset(declSpec, declarators); + if (lt1 == 0 || !isOnSameLine(endOffset, LA(1).getOffset())) { + break; + } + if (declarators.length == 1 && declarators[0] instanceof IASTFunctionDeclarator) { + break; + } + } + throwBacktrack(LA(1)); } - ((ASTNode) simpleDeclaration).setOffsetAndLength(firstOffset, endOffset-firstOffset); + // no function body + 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) { + simpleDeclaration.addDeclarator(declarator); + } + } + + setRange(simpleDeclaration, firstOffset, endOffset); + if (isAmbiguous) { + simpleDeclaration = new CPPASTAmbiguousSimpleDeclaration(simpleDeclaration, declSpec, dtor); + setRange(simpleDeclaration, firstOffset, endOffset); + } + if (insertSemi) { IASTProblem problem= createProblem(IProblem.SYNTAX_ERROR, endOffset, 0); throwBacktrack(problem, simpleDeclaration); @@ -1803,17 +1781,6 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { 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, IASTDeclarator[] dtors) throws EndOfFileException, BacktrackException { @@ -1939,28 +1906,26 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { IASTDeclSpecifier declSpec= null; IASTDeclarator declarator; try { - declSpec= declSpecifierSeq(DeclarationOptions.PARAMETER); - declarator= initDeclarator(declSpec, DeclarationOptions.PARAMETER); - } catch (FoundDeclaratorException e) { - declSpec= e.declSpec; - declarator= e.declarator; - backup(e.currToken); + Decl decl= declSpecifierSequence_initDeclarator(DeclarationOptions.PARAMETER, false); + declSpec= decl.fDeclSpec1; + declarator= decl.fDtor1; } catch (FoundAggregateInitializer lie) { - if (declSpec == null) - declSpec= lie.fDeclSpec; + declSpec= lie.fDeclSpec; declarator= addInitializer(lie, DeclarationOptions.PARAMETER); } final ICPPASTParameterDeclaration parm = nodeFactory.newParameterDeclaration(declSpec, declarator); final int endOffset = figureEndOffset(declSpec, declarator); - ((ASTNode) parm).setOffsetAndLength(startOffset, endOffset - startOffset); + setRange(parm, startOffset, endOffset); return parm; } private final static int INLINE=0x1, CONST=0x2, RESTRICT=0x4, VOLATILE=0x8, - SHORT=0x10, UNSIGNED= 0x20, SIGNED=0x40, COMPLEX=0x80, IMAGINARY=0x100, - VIRTUAL=0x200, EXPLICIT=0x400, FRIEND=0x800; + SHORT=0x10, UNSIGNED= 0x20, SIGNED=0x40, COMPLEX=0x80, IMAGINARY=0x100, + VIRTUAL=0x200, EXPLICIT=0x400, FRIEND=0x800; + private static final int FORBID_IN_EMPTY_DECLSPEC = + CONST | RESTRICT | VOLATILE | SHORT | UNSIGNED | SIGNED | COMPLEX | IMAGINARY | FRIEND; /** @@ -1976,343 +1941,318 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { * ("typename")? name | * { "class" | "struct" | "union" } classSpecifier | * {"enum"} enumSpecifier - * @throws FoundAggregateInitializer */ @Override - protected ICPPASTDeclSpecifier declSpecifierSeq(final DeclarationOptions option) - throws BacktrackException, EndOfFileException, FoundDeclaratorException, FoundAggregateInitializer { - int storageClass = IASTDeclSpecifier.sc_unspecified; + protected Decl declSpecifierSeq(final DeclarationOptions option) throws BacktrackException, EndOfFileException { + int storageClass = IASTDeclSpecifier.sc_unspecified; int simpleType = IASTSimpleDeclSpecifier.t_unspecified; int options= 0; int isLong= 0; - IASTName identifier= null; - ICPPASTDeclSpecifier result= null; - IASTExpression typeofExpression= null; - IASTProblem problem= null; + IToken returnToken= null; + ICPPASTDeclSpecifier result= null; + ICPPASTDeclSpecifier altResult= null; + try { + IASTName identifier= null; + IASTExpression typeofExpression= null; + IASTProblem problem= null; - boolean isTypename = false; - boolean encounteredRawType= false; - boolean encounteredTypename= false; + boolean isTypename = false; + boolean encounteredRawType= false; + boolean encounteredTypename= false; - final int offset = LA(1).getOffset(); - int endOffset= offset; + final int offset = LA(1).getOffset(); + int endOffset= offset; - declSpecifiers: for (;;) { - final int lt1= LTcatchEOF(1); - switch (lt1) { - case 0: // encountered 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_mutable: - storageClass = ICPPASTDeclSpecifier.sc_mutable; - endOffset= consume().getEndOffset(); - break; - case IToken.t_typedef: - storageClass = IASTDeclSpecifier.sc_typedef; - endOffset= consume().getEndOffset(); - break; - // function specifiers - case IToken.t_inline: - options |= INLINE; - endOffset= consume().getEndOffset(); - break; - case IToken.t_virtual: - options |= VIRTUAL; - endOffset= consume().getEndOffset(); - break; - case IToken.t_explicit: - options |= EXPLICIT; - endOffset= consume().getEndOffset(); - break; - case IToken.t_friend: - options |= FRIEND; - endOffset= consume().getEndOffset(); - break; - // type specifier - 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.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_short: - if (encounteredTypename) - break declSpecifiers; - options |= SHORT; - encounteredRawType= true; - endOffset= consume().getEndOffset(); - break; - case IToken.t_long: - if (encounteredTypename) - break declSpecifiers; - isLong++; - encounteredRawType= true; - endOffset= consume().getEndOffset(); - break; - case IToken.t__Complex: - if (encounteredTypename) - break declSpecifiers; - options |= COMPLEX; - endOffset= consume().getEndOffset(); - break; - case IToken.t__Imaginary: - if (encounteredTypename) - break declSpecifiers; - options |= IMAGINARY; - endOffset= consume().getEndOffset(); - break; - case IToken.t_char: - if (encounteredTypename) - break declSpecifiers; - simpleType = IASTSimpleDeclSpecifier.t_char; - encounteredRawType= true; - endOffset= consume().getEndOffset(); - break; - case IToken.t_wchar_t: - if (encounteredTypename) - break declSpecifiers; - simpleType = ICPPASTSimpleDeclSpecifier.t_wchar_t; - encounteredRawType= true; - endOffset= consume().getEndOffset(); - break; - case IToken.t_bool: - if (encounteredTypename) - break declSpecifiers; - simpleType = ICPPASTSimpleDeclSpecifier.t_bool; - 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_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_void: - if (encounteredTypename) - break declSpecifiers; - simpleType = IASTSimpleDeclSpecifier.t_void; - encounteredRawType= true; - endOffset= consume().getEndOffset(); - break; - case IToken.t_typename: - if (encounteredTypename || encounteredRawType) - break declSpecifiers; - consume(); - identifier= qualifiedName(); - endOffset= calculateEndOffset(identifier); - isTypename = true; - encounteredTypename= true; - break; - case IToken.tBITCOMPLEMENT: - case IToken.tCOLONCOLON: - case IToken.tIDENTIFIER: - case IToken.tCOMPLETION: - if (encounteredRawType || encounteredTypename) - break declSpecifiers; + declSpecifiers: for (;;) { + final int lt1= LTcatchEOF(1); + switch (lt1) { + case 0: // encountered 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_mutable: + storageClass = ICPPASTDeclSpecifier.sc_mutable; + endOffset= consume().getEndOffset(); + break; + case IToken.t_typedef: + storageClass = IASTDeclSpecifier.sc_typedef; + endOffset= consume().getEndOffset(); + break; + // function specifiers + case IToken.t_inline: + options |= INLINE; + endOffset= consume().getEndOffset(); + break; + case IToken.t_virtual: + options |= VIRTUAL; + endOffset= consume().getEndOffset(); + break; + case IToken.t_explicit: + options |= EXPLICIT; + endOffset= consume().getEndOffset(); + break; + case IToken.t_friend: + options |= FRIEND; + endOffset= consume().getEndOffset(); + break; + // type specifier + 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.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_short: + if (encounteredTypename) + break declSpecifiers; + options |= SHORT; + encounteredRawType= true; + endOffset= consume().getEndOffset(); + break; + case IToken.t_long: + if (encounteredTypename) + break declSpecifiers; + isLong++; + encounteredRawType= true; + endOffset= consume().getEndOffset(); + break; + case IToken.t__Complex: + if (encounteredTypename) + break declSpecifiers; + options |= COMPLEX; + endOffset= consume().getEndOffset(); + break; + case IToken.t__Imaginary: + if (encounteredTypename) + break declSpecifiers; + options |= IMAGINARY; + endOffset= consume().getEndOffset(); + break; + case IToken.t_char: + if (encounteredTypename) + break declSpecifiers; + simpleType = IASTSimpleDeclSpecifier.t_char; + encounteredRawType= true; + endOffset= consume().getEndOffset(); + break; + case IToken.t_wchar_t: + if (encounteredTypename) + break declSpecifiers; + simpleType = ICPPASTSimpleDeclSpecifier.t_wchar_t; + encounteredRawType= true; + endOffset= consume().getEndOffset(); + break; + case IToken.t_bool: + if (encounteredTypename) + break declSpecifiers; + simpleType = ICPPASTSimpleDeclSpecifier.t_bool; + 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_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_void: + if (encounteredTypename) + break declSpecifiers; + simpleType = IASTSimpleDeclSpecifier.t_void; + encounteredRawType= true; + endOffset= consume().getEndOffset(); + break; + case IToken.t_typename: + if (encounteredTypename || encounteredRawType) + break declSpecifiers; + consume(); + identifier= qualifiedName(); + endOffset= calculateEndOffset(identifier); + isTypename = true; + encounteredTypename= true; + break; + case IToken.tBITCOMPLEMENT: + case IToken.tCOLONCOLON: + case IToken.tIDENTIFIER: + case IToken.tCOMPLETION: + if (encounteredRawType || encounteredTypename) + break declSpecifiers; - try { - if (option.fAllowEmptySpecifier && LT(1) != IToken.tCOMPLETION) { - lookAheadForDeclarator(option); - } - } catch (FoundAggregateInitializer e) { - 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; - } - } + if (option.fAllowEmptySpecifier && LT(1) != IToken.tCOMPLETION) { + if ((options & FORBID_IN_EMPTY_DECLSPEC) == 0 && storageClass == IASTDeclSpecifier.sc_unspecified) { + altResult= buildSimpleDeclSpec(storageClass, simpleType, options, isLong, typeofExpression, offset, endOffset); + returnToken= mark(); + } + } - identifier= qualifiedName(); - if (identifier.getLookupKey().length == 0 && LT(1) != IToken.tEOC) - throwBacktrack(LA(1)); - - endOffset= calculateEndOffset(identifier); - encounteredTypename= true; - break; - case IToken.t_class: - case IToken.t_struct: - case IToken.t_union: - if (encounteredTypename || encounteredRawType) - break declSpecifiers; - try { - result= classSpecifier(); - } catch (BacktrackException bt) { - result= elaboratedTypeSpecifier(); - } - endOffset= calculateEndOffset(result); - encounteredTypename= true; - break; + identifier= qualifiedName(); + if (identifier.getLookupKey().length == 0 && LT(1) != IToken.tEOC) + throwBacktrack(LA(1)); - case IToken.t_enum: - if (encounteredTypename || encounteredRawType) - break declSpecifiers; - try { - result= (ICPPASTDeclSpecifier) enumSpecifier(); - } catch (BacktrackException bt) { - if (bt.getNodeBeforeProblem() instanceof ICPPASTDeclSpecifier) { - result= (ICPPASTDeclSpecifier) bt.getNodeBeforeProblem(); - problem= bt.getProblem(); - break declSpecifiers; - } else { - result= elaboratedTypeSpecifier(); - } - } - endOffset= calculateEndOffset(result); - encounteredTypename= true; - break; + endOffset= calculateEndOffset(identifier); + encounteredTypename= true; + break; + case IToken.t_class: + case IToken.t_struct: + case IToken.t_union: + if (encounteredTypename || encounteredRawType) + break declSpecifiers; + try { + result= classSpecifier(); + } catch (BacktrackException bt) { + 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 IGCCToken.t_typeof: - if (encounteredRawType || encounteredTypename) - throwBacktrack(LA(1)); + case IToken.t_enum: + if (encounteredTypename || encounteredRawType) + break declSpecifiers; + try { + result= (ICPPASTDeclSpecifier) enumSpecifier(); + } catch (BacktrackException bt) { + if (bt.getNodeBeforeProblem() instanceof ICPPASTDeclSpecifier) { + result= (ICPPASTDeclSpecifier) bt.getNodeBeforeProblem(); + problem= bt.getProblem(); + break declSpecifiers; + } else { + result= elaboratedTypeSpecifier(); + } + } + endOffset= calculateEndOffset(result); + encounteredTypename= true; + break; - final boolean wasInBinary= inBinaryExpression; - try { - inBinaryExpression= false; - typeofExpression= parseTypeidInParenthesisOrUnaryExpression(false, consume().getOffset(), - IGNUASTTypeIdExpression.op_typeof, IGNUASTUnaryExpression.op_typeof); - } finally { - inBinaryExpression= wasInBinary; - } + 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; - encounteredTypename= true; - endOffset= calculateEndOffset(typeofExpression); - break; + case IGCCToken.t_typeof: + if (encounteredRawType || encounteredTypename) + throwBacktrack(LA(1)); - default: - if (lt1 >= IExtensionToken.t__otherDeclSpecModifierFirst && lt1 <= IExtensionToken.t__otherDeclSpecModifierLast) { - handleOtherDeclSpecModifier(); - endOffset= LA(1).getOffset(); - break; - } - break declSpecifiers; - } - - 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; + } - // check for empty specification - if (!encounteredRawType && !encounteredTypename && LT(1) != IToken.tEOC && !option.fAllowEmptySpecifier) { - throwBacktrack(LA(1)); + 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)); + } + + // check for empty specification + if (!encounteredRawType && !encounteredTypename && LT(1) != IToken.tEOC && !option.fAllowEmptySpecifier) { + throwBacktrack(LA(1)); + } + + if (result != null) { + configureDeclSpec(result, storageClass, options); + // cannot store restrict in the cpp-nodes. + // if ((options & RESTRICT) != 0) { + // } + setRange(result, offset, endOffset); + if (problem != null) { + throwBacktrack(problem, 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 (returnToken != null) { + backup(returnToken); + result= altResult; + altResult= null; + returnToken= null; + } else { + throw e; + } } - if (result != null) { - configureDeclSpec(result, storageClass, options); - // cannot store restrict in the cpp-nodes. - // if ((options & RESTRICT) != 0) { - // } - ((ASTNode) result).setOffsetAndLength(offset, endOffset - offset); - if (problem != null) { - throwBacktrack(problem, result); - } - return result; - } - - if (identifier != null) - return buildNamedTypeSpecifier(identifier, isTypename, 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 boolean canBeConstructorDestructorOrConversion(DeclarationOptions declOption, int storageClass, int options, IASTDeclarator dtor) { - 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; - } - private ICPPASTNamedTypeSpecifier buildNamedTypeSpecifier(IASTName name, boolean isTypename, int storageClass, int options, int offset, int endOffset) { ICPPASTNamedTypeSpecifier declSpec = nodeFactory.newTypedefNameSpecifier(name); @@ -2364,39 +2304,6 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { 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. * @@ -2435,15 +2342,8 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { ((ASTNode) elaboratedTypeSpec).setOffsetAndLength(t.getOffset(), calculateEndOffset(name) - t.getOffset()); return elaboratedTypeSpec; } - - - @Override - protected IASTDeclarator initDeclarator(DeclarationOptions option) - throws EndOfFileException, BacktrackException, FoundAggregateInitializer { - // called from the lookahead, only. - return initDeclarator(DtorStrategy.PREFER_FUNCTION, option); - } + @Override protected IASTDeclarator initDeclarator(IASTDeclSpecifier declspec, DeclarationOptions option) throws EndOfFileException, BacktrackException, FoundAggregateInitializer { final IToken mark= mark(); @@ -2453,16 +2353,33 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { BacktrackException bt= null; try { 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; 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) { bt= e; } @@ -2502,6 +2419,45 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { 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) { if (declspec instanceof ICPPASTDeclSpecifier) { ICPPASTDeclSpecifier cppspec= (ICPPASTDeclSpecifier) declspec; @@ -2686,19 +2642,15 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { if (!canBeTypeSpecifier()) { return null; } - int startingOffset = mark().getOffset(); + final int offset = mark().getOffset(); IASTDeclSpecifier declSpecifier = null; IASTDeclarator declarator = null; + rejectLogicalOperatorInTemplateID++; try { - declSpecifier = declSpecifierSeq(option); - if (LT(1) != IToken.tEOC) { - declarator= declarator(DtorStrategy.PREFER_FUNCTION, option); - } - } catch (FoundDeclaratorException e) { - declSpecifier= e.declSpec; - declarator= e.declarator; - backup(e.currToken); + Decl decl= declSpecifierSequence_initDeclarator(option, false); + declSpecifier= decl.fDeclSpec1; + declarator= decl.fDtor1; } catch (FoundAggregateInitializer lie) { // type-ids have no initializers return null; @@ -2708,7 +2660,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { rejectLogicalOperatorInTemplateID--; } IASTTypeId result = nodeFactory.newTypeId(declSpecifier, declarator); - ((ASTNode) result).setOffsetAndLength(startingOffset, figureEndOffset(declSpecifier, declarator) - startingOffset); + setRange(result, offset, figureEndOffset(declSpecifier, declarator)); return result; } @@ -3343,27 +3295,23 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { private IASTSimpleDeclaration simpleSingleDeclaration(DeclarationOptions options) throws BacktrackException, EndOfFileException { final int startOffset= LA(1).getOffset(); - IASTDeclSpecifier declSpec= null; + IASTDeclSpecifier declSpec; IASTDeclarator declarator; try { - declSpec= declSpecifierSeq(options); - declarator= initDeclarator(declSpec, options); - } catch (FoundDeclaratorException e) { - declSpec= e.declSpec; - declarator= e.declarator; - backup(e.currToken); + Decl decl= declSpecifierSequence_initDeclarator(options, true); + declSpec= decl.fDeclSpec1; + declarator= decl.fDtor1; } catch (FoundAggregateInitializer lie) { - if (declSpec == null) - declSpec= lie.fDeclSpec; + declSpec= lie.fDeclSpec; declarator= addInitializer(lie, options); } final int endOffset = figureEndOffset(declSpec, declarator); final IASTSimpleDeclaration decl= nodeFactory.newSimpleDeclaration(declSpec); - decl.addDeclarator(declarator); + if (declarator != null) + decl.addDeclarator(declarator); ((ASTNode) decl).setOffsetAndLength(startOffset, endOffset - startOffset); - return decl; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java index 630862c6fb3..9fa98ca9271 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java @@ -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)) diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java index bea77da5047..cf981f192cd 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java @@ -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; + } }