diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/c/CLanguage.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/c/CLanguage.java index 053e52d12ca..c352f4ac047 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/c/CLanguage.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/c/CLanguage.java @@ -3,6 +3,7 @@ import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.dom.ILinkage; import org.eclipse.cdt.core.dom.parser.AbstractCLikeLanguage; +import org.eclipse.cdt.core.dom.parser.IExactCLanguage; import org.eclipse.cdt.core.dom.parser.IScannerExtensionConfiguration; import org.eclipse.cdt.core.dom.parser.ISourceCodeParser; import org.eclipse.cdt.core.dom.parser.c.ANSICParserExtensionConfiguration; @@ -18,7 +19,7 @@ /** * ILanguage implementation for the DOM no-dialect, pure C Parser. */ -public class CLanguage extends AbstractCLikeLanguage implements IActualCLanguage { +public class CLanguage extends AbstractCLikeLanguage implements IExactCLanguage { public static final ANSICParserExtensionConfiguration C_PARSER_EXTENSION = new ANSICParserExtensionConfiguration(); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/CPPLanguage.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/CPPLanguage.java index 2064b2e163c..bf735453b36 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/CPPLanguage.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/CPPLanguage.java @@ -3,6 +3,7 @@ import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.dom.ILinkage; import org.eclipse.cdt.core.dom.parser.AbstractCLikeLanguage; +import org.eclipse.cdt.core.dom.parser.IExactCLanguage; import org.eclipse.cdt.core.dom.parser.IScannerExtensionConfiguration; import org.eclipse.cdt.core.dom.parser.ISourceCodeParser; import org.eclipse.cdt.core.dom.parser.cpp.ANSICPPParserExtensionConfiguration; @@ -18,7 +19,7 @@ /** * ILanguage implementation for the DOM no-dialect, pure C++ Parser. */ -public class CPPLanguage extends AbstractCLikeLanguage implements IActualCPPLanguage { +public class CPPLanguage extends AbstractCLikeLanguage implements IExactCLanguage { public static final ANSICPPParserExtensionConfiguration CPP_PARSER_EXTENSION = new ANSICPPParserExtensionConfiguration(); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/IActualCPPLanguage.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/IActualCPPLanguage.java deleted file mode 100644 index fcc9aacca7d..00000000000 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/IActualCPPLanguage.java +++ /dev/null @@ -1,13 +0,0 @@ -package org.eclipse.cdt.core.dom.ast.cpp; - -/** - * This interface is used by Eclipse to mark the core language implementation that - * comes as one of the built-in languages as the true C++ Language. - * This should not be implemented by any dialects! - * - * @noextend This interface is not intended to be extended by clients. - * @noimplement This interface is not intended to be implemented by clients. - */ -interface IActualCPPLanguage { - -} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/c/IActualCLanguage.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/parser/IExactCLanguage.java similarity index 66% rename from core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/c/IActualCLanguage.java rename to core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/parser/IExactCLanguage.java index 7cd2dbb0706..9424c21178f 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/c/IActualCLanguage.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/parser/IExactCLanguage.java @@ -1,13 +1,13 @@ -package org.eclipse.cdt.core.dom.ast.c; +package org.eclipse.cdt.core.dom.parser; /** * This interface is used by Eclipse to mark the core language implementation that - * comes as one of the built-in languages as the true C Language. + * comes as one of the built-in languages as the true C or C++ Languages. * This should not be implemented by any dialects! * * @noextend This interface is not intended to be extended by clients. * @noimplement This interface is not intended to be implemented by clients. */ -interface IActualCLanguage { +public interface IExactCLanguage { } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/AbstractSourceCodeParser.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/AbstractSourceCodeParser.java index 72c81682736..591c3712882 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/AbstractSourceCodeParser.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/AbstractSourceCodeParser.java @@ -1,8 +1,14 @@ package org.eclipse.cdt.internal.core.dom.parser; +import java.util.ArrayList; +import java.util.List; + import org.eclipse.cdt.core.dom.ast.ASTCompletionNode; import org.eclipse.cdt.core.dom.ast.ASTGenericVisitor; import org.eclipse.cdt.core.dom.ast.IASTASMDeclaration; +import org.eclipse.cdt.core.dom.ast.IASTAlignmentSpecifier; +import org.eclipse.cdt.core.dom.ast.IASTAttributeOwner; +import org.eclipse.cdt.core.dom.ast.IASTAttributeSpecifier; import org.eclipse.cdt.core.dom.ast.IASTBinaryExpression; import org.eclipse.cdt.core.dom.ast.IASTCastExpression; import org.eclipse.cdt.core.dom.ast.IASTCompletionNode; @@ -15,6 +21,7 @@ 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.IASTEnumerationSpecifier.IASTEnumerator; import org.eclipse.cdt.core.dom.ast.IASTExpression; import org.eclipse.cdt.core.dom.ast.IASTExpressionList; import org.eclipse.cdt.core.dom.ast.IASTFileLocation; @@ -62,7 +69,6 @@ public abstract class AbstractSourceCodeParser implements ISourceCodeParser { protected final ParserMode mode; protected final INodeFactory nodeFactory; protected final IBuiltinBindingsProvider builtinBindingsProvider; - protected final boolean supportKnRC; protected boolean passing = true; protected boolean cancelled = false; @@ -76,12 +82,11 @@ public abstract class AbstractSourceCodeParser implements ISourceCodeParser { private boolean activeCode = true; public AbstractSourceCodeParser(IScanner scanner, ParserMode parserMode, IParserLogService logService, - INodeFactory factory, boolean supportKnRC, IBuiltinBindingsProvider provider) { + INodeFactory factory, IBuiltinBindingsProvider provider) { this.scanner = scanner; this.nodeFactory = factory; this.log = wrapLogService(logService); this.mode = parserMode; - this.supportKnRC = supportKnRC; this.builtinBindingsProvider = provider; } @@ -181,6 +186,16 @@ protected abstract IASTAmbiguousExpression createAmbiguousCastVsMethodCallExpres protected abstract IASTTypeId typeID(DeclarationOptions option) throws EndOfFileException, BacktrackException; + // Methods for parsing a type-id and an expression with an optional trailing ellipsis. + // The optional trailing ellipsis can only appear in C++ code, and only the C++ parser + // allows it, but being able to invoke this from here allows reusing more productions + // between C and C++, such as alignmentSpecifier(). + protected abstract IASTExpression expressionWithOptionalTrailingEllipsis() + throws BacktrackException, EndOfFileException; + + protected abstract IASTTypeId typeIDWithOptionalTrailingEllipsis(DeclarationOptions option) + throws EndOfFileException, BacktrackException; + /** * 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. @@ -199,6 +214,59 @@ protected Decl declSpecifierSeq(DeclarationOptions option) throws BacktrackExcep */ protected abstract IASTName identifier() throws EndOfFileException, BacktrackException; + protected abstract IASTAlignmentSpecifier createAmbiguousAlignmentSpecifier(IASTAlignmentSpecifier expression, + IASTAlignmentSpecifier typeId); + + protected boolean canBeTypeSpecifier() throws EndOfFileException { + final int type = lookaheadType(1); + switch (type) { + // simple type specifiers: + case IToken.tIDENTIFIER: + case IToken.tCOLONCOLON: + case IToken.t_void: + case IToken.t_char: + case IToken.t_char16_t: + case IToken.t_char32_t: + case IToken.t_wchar_t: + case IToken.t_bool: + case IToken.t_short: + case IToken.t_int: + case IToken.t_long: + case IToken.t_float: + case IToken.t_double: + case IToken.t__Bool: + case IToken.t__Complex: + case IToken.t__Imaginary: + case IToken.t_signed: + case IToken.t_unsigned: + case IToken.t_decltype: + case IToken.t_auto: + + // class-specifier: + case IToken.t_class: + case IToken.t_struct: + case IToken.t_union: + + // enum-specifier: + case IToken.t_enum: + + // elaborated type specifier: (together with class, struct, union, enum) + case IToken.t_typename: + + // cq-qualifiers + case IToken.t_const: + case IToken.t_volatile: + case IToken.t_restrict: + + // content assist + case IToken.tCOMPLETION: + return true; + + default: + return false; + } + } + protected void processCompilationUnit() { try { createCompilationUnit(); @@ -246,6 +314,160 @@ protected ASTCompletionNode createCompletionNode(IToken token) { return completionNode; } + protected IASTAlignmentSpecifier alignmentSpecifier() throws BacktrackException, EndOfFileException { + int startOffset = consume(IToken.t_alignas, IToken.t__Alignas).getOffset(); + + consume(IToken.tLPAREN); + + IASTTypeId typeId = null; + IASTExpression expression = null; + + // Try parsing a type-id. + IToken beginning = mark(); + IToken typeIdEnd = null; + try { + typeId = typeIDWithOptionalTrailingEllipsis(DeclarationOptions.TYPEID); + typeIdEnd = mark(); + } catch (BacktrackException exception) { + } + + // Back up and try parsing an expression. + backup(beginning); + try { + expression = expressionWithOptionalTrailingEllipsis(); + } catch (BacktrackException exception) { + // If neither parses successfully, throw. + if (typeId == null) { + throw exception; + } + } + + IASTAlignmentSpecifier result; + if (typeId == null) { + // No type id - use the expression. + result = nodeFactory.newAlignmentSpecifier(expression); + } else if (expression == null) { + // No expression - use the type id. + backup(typeIdEnd); + result = nodeFactory.newAlignmentSpecifier(typeId); + } else if (expression.contains(typeId)) { // otherwise, pick the longer one + if (typeId.contains(expression)) { + // They are both the same length - ambiguous. + int endOffset = consume(IToken.tRPAREN).getEndOffset(); + IASTAlignmentSpecifier expressionAlternative = nodeFactory.newAlignmentSpecifier(expression); + IASTAlignmentSpecifier typeIdAlternative = nodeFactory.newAlignmentSpecifier(typeId); + setRange(expressionAlternative, startOffset, endOffset); + setRange(typeIdAlternative, startOffset, endOffset); + return createAmbiguousAlignmentSpecifier(expressionAlternative, typeIdAlternative); + } else { + // Expression is longer - use it. + result = nodeFactory.newAlignmentSpecifier(expression); + } + } else { + // Type-id is longer - use it. + backup(typeIdEnd); + result = nodeFactory.newAlignmentSpecifier(typeId); + } + + int endOffset = consume(IToken.tRPAREN).getEndOffset(); + + setRange(result, startOffset, endOffset); + return result; + } + + /** + * Parse an enumeration specifier, as according to the ANSI specs in C & + * C++. enumSpecifier: "enum" (name)? "{" (enumerator-list) "}" + * enumerator-list: enumerator-definition enumerator-list , + * enumerator-definition enumerator-definition: enumerator enumerator = + * constant-expression enumerator: identifier + * + * @throws BacktrackException request a backtrack + */ + protected IASTEnumerationSpecifier enumSpecifier() throws BacktrackException, EndOfFileException { + final IToken mark = mark(); + final int offset = consume().getOffset(); + + IASTName name; + if (lookaheadType(1) == IToken.tIDENTIFIER) { + name = identifier(); + } else { + name = nodeFactory.newName(); + } + + if (lookaheadType(1) != IToken.tLBRACE) { + backup(mark); + throwBacktrack(mark); + } + + final IASTEnumerationSpecifier result = nodeFactory.newEnumerationSpecifier(name); + + int endOffset = enumBody(result); + return setRange(result, offset, endOffset); + } + + protected int enumBody(final IASTEnumerationSpecifier result) throws EndOfFileException, BacktrackException { + boolean needComma = false; + int endOffset = consume(IToken.tLBRACE).getEndOffset(); // IToken.tLBRACE + int problemOffset = endOffset; + try { + loop: while (true) { + switch (lookaheadTypeWithEndOfFile(1)) { + case 0: // eof + endOffset = getEndOffset(); + break loop; + case IToken.tRBRACE: + endOffset = consume().getEndOffset(); + break loop; + case IToken.tEOC: + break loop; + case IToken.tCOMMA: + if (!needComma) { + problemOffset = lookahead(1).getOffset(); + throw backtrack; + } + endOffset = consume().getEndOffset(); + needComma = false; + continue loop; + case IToken.tIDENTIFIER: + case IToken.tCOMPLETION: + problemOffset = lookahead(1).getOffset(); + if (needComma) + throw backtrack; + + final IASTName etorName = identifier(); + final IASTEnumerator enumerator = nodeFactory.newEnumerator(etorName, null); + + // WIP C23 + List attributes = new ArrayList<>(); + addAttributeSpecifiers(attributes, enumerator); + endOffset = attributesEndOffset(calculateEndOffset(etorName), attributes); + setRange(enumerator, problemOffset, endOffset); + + result.addEnumerator(enumerator); + if (lookaheadTypeWithEndOfFile(1) == IToken.tASSIGN) { + problemOffset = consume().getOffset(); + final IASTExpression value = constantExpression(); + enumerator.setValue(value); + adjustLength(enumerator, value); + endOffset = calculateEndOffset(value); + } + needComma = true; + continue loop; + default: + problemOffset = lookahead(1).getOffset(); + throw backtrack; + } + } + } catch (EndOfFileException eof) { + throwBacktrack(createProblem(IProblem.SYNTAX_ERROR, problemOffset, getEndOffset() - problemOffset), result); + } catch (BacktrackException bt) { + IASTProblem problem = skipProblemEnumerator(problemOffset); + throwBacktrack(problem, result); + } + return endOffset; + } + protected IASTProblemDeclaration skipProblemDeclaration(int offset) { return skipProblemDeclaration(offset, null); } @@ -411,7 +633,7 @@ protected IASTStatement handleMethodBody() throws BacktrackException, EndOfFileE } /** - * Parses a function body. + * Parses a method body. * * @return the compound statement representing the function body. * @throws BacktrackException @@ -571,7 +793,7 @@ protected boolean isLegalWithoutDtor(IASTDeclSpecifier specifier) { * The type of token that you are expecting. * @return the token that was consumed and removed from our buffer. * @throws BacktrackException - * if LT(1) != type + * if lookaheadType(1) != type */ protected IToken consumeOrEndOfCompletion(int type) throws EndOfFileException, BacktrackException { final IToken token = lookahead(1); @@ -940,6 +1162,45 @@ protected final void skipBrackets(int left, int right, int terminator) } } + protected final void declarationListInBraces(final IASTDeclarationListOwner owner, int offset, + DeclarationOptions options) throws EndOfFileException, BacktrackException { + // consume brace, if requested + int codeBranchNesting = getCodeBranchNesting(); + consume(IToken.tLBRACE); + declarationList(owner, options, true, codeBranchNesting); + + final int type = lookaheadTypeWithEndOfFile(1); + if (type == IToken.tRBRACE) { + int endOffset = consume().getEndOffset(); + setRange(owner, offset, endOffset); + return; + } + + final int endOffset = getEndOffset(); + setRange(owner, offset, endOffset); + if (type == IToken.tEOC || (type == 0 && owner instanceof IASTCompositeTypeSpecifier)) { + return; + } + throwBacktrack(createProblem(IProblem.SYNTAX_ERROR, endOffset, 0), owner); + } + + protected final void addAttributeSpecifiers(List specifiers, IASTAttributeOwner owner) { + assert owner != null; + if (specifiers != null) { + for (IASTAttributeSpecifier specifier : specifiers) { + owner.addAttributeSpecifier(specifier); + } + } + } + + protected final int attributesEndOffset(int endOffset, List specifiers) { + if (specifiers == null || specifiers.isEmpty()) { + return endOffset; + } + ASTNode lastSpecifier = (ASTNode) specifiers.get(specifiers.size() - 1); + return Math.max(endOffset, calculateEndOffset(lastSpecifier)); + } + protected final void throwBacktrack(IASTProblem problem, IASTNode node) throws BacktrackException { ++backtrackCount; backtrack.initialize(problem, node); @@ -956,6 +1217,17 @@ protected final void throwBacktrack(IToken token) throws BacktrackException { throwBacktrack(token.getOffset(), token.getLength()); } + protected final void throwBacktrack(IASTProblem problem) throws BacktrackException { + ++backtrackCount; + backtrack.initialize(problem); + throw backtrack; + } + + protected final void throwBacktrack(IASTNode inode) throws BacktrackException { + final ASTNode node = (ASTNode) inode; + throwBacktrack(node.getOffset(), node.getLength()); + } + /** * Roll back to a previous point, reseting the queue of tokens. * @param mark a token previously obtained via {@link #mark()}. @@ -1077,6 +1349,19 @@ protected final IToken consume(int type) throws EndOfFileException, BacktrackExc return result; } + /** + * The next token is consumed. Afterwards its type is checked and a {@link BacktrackException} + * is thrown if the type neither matches type1 nor type2. + */ + protected final IToken consume(int first, int second) throws EndOfFileException, BacktrackException { + final IToken result = consume(); + final int type = result.getType(); + if (type != first && type != second) { + throwBacktrack(result); + } + return result; + } + protected final boolean acceptInactiveCodeBoundary(int nesting) { try { while (true) { @@ -1537,6 +1822,12 @@ private IASTExpression createCastVsBinaryExpressionAmbiguity(IASTBinaryExpressio return result; } + private IASTProblem skipProblemEnumerator(int offset) { + passing = false; + final int endOffset = skipToSemiOrClosingBrace(offset, true); + return createProblem(IProblem.SYNTAX_ERROR, offset, endOffset - offset); + } + protected static final class ASTMarkInactiveVisitor extends ASTGenericVisitor { public ASTMarkInactiveVisitor() { super(true); @@ -1571,6 +1862,9 @@ protected static class Decl { public boolean isAtStartOfStructuredBinding = false; + public Decl() { + } + public Decl set(IASTDeclSpecifier declspec, IASTDeclarator dtor, IToken dtorToken) { fDeclSpec1 = declspec; fDtor1 = dtor; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CSourceParser.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CSourceParser.java index adcbcb7db37..bcb406d5911 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CSourceParser.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CSourceParser.java @@ -4,16 +4,19 @@ import java.util.List; import org.eclipse.cdt.core.dom.ast.ASTCompletionNode; +import org.eclipse.cdt.core.dom.ast.IASTAlignmentSpecifier; import org.eclipse.cdt.core.dom.ast.IASTArrayDeclarator; import org.eclipse.cdt.core.dom.ast.IASTArrayModifier; import org.eclipse.cdt.core.dom.ast.IASTArraySubscriptExpression; import org.eclipse.cdt.core.dom.ast.IASTAttributeSpecifier; import org.eclipse.cdt.core.dom.ast.IASTBinaryExpression; import org.eclipse.cdt.core.dom.ast.IASTCastExpression; +import org.eclipse.cdt.core.dom.ast.IASTCompositeTypeSpecifier; import org.eclipse.cdt.core.dom.ast.IASTCompoundStatement; 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.IASTEqualsInitializer; import org.eclipse.cdt.core.dom.ast.IASTExpression; import org.eclipse.cdt.core.dom.ast.IASTFieldDeclarator; @@ -21,15 +24,17 @@ import org.eclipse.cdt.core.dom.ast.IASTFunctionCallExpression; import org.eclipse.cdt.core.dom.ast.IASTFunctionDeclarator; import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition; +import org.eclipse.cdt.core.dom.ast.IASTIdExpression; import org.eclipse.cdt.core.dom.ast.IASTInitializer; import org.eclipse.cdt.core.dom.ast.IASTInitializerClause; import org.eclipse.cdt.core.dom.ast.IASTInitializerList; +import org.eclipse.cdt.core.dom.ast.IASTLiteralExpression; import org.eclipse.cdt.core.dom.ast.IASTName; import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.IASTParameterDeclaration; import org.eclipse.cdt.core.dom.ast.IASTPointerOperator; import org.eclipse.cdt.core.dom.ast.IASTProblem; -import org.eclipse.cdt.core.dom.ast.IASTProblemDeclaration; +import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclSpecifier; import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration; import org.eclipse.cdt.core.dom.ast.IASTStandardFunctionDeclarator; import org.eclipse.cdt.core.dom.ast.IASTStatement; @@ -39,12 +44,17 @@ import org.eclipse.cdt.core.dom.ast.IASTUnaryExpression; import org.eclipse.cdt.core.dom.ast.c.ICASTArrayDesignator; import org.eclipse.cdt.core.dom.ast.c.ICASTArrayModifier; +import org.eclipse.cdt.core.dom.ast.c.ICASTCompositeTypeSpecifier; +import org.eclipse.cdt.core.dom.ast.c.ICASTDeclSpecifier; import org.eclipse.cdt.core.dom.ast.c.ICASTDesignatedInitializer; import org.eclipse.cdt.core.dom.ast.c.ICASTDesignator; +import org.eclipse.cdt.core.dom.ast.c.ICASTElaboratedTypeSpecifier; +import org.eclipse.cdt.core.dom.ast.c.ICASTEnumerationSpecifier; import org.eclipse.cdt.core.dom.ast.c.ICASTFieldDesignator; import org.eclipse.cdt.core.dom.ast.c.ICASTPointer; +import org.eclipse.cdt.core.dom.ast.c.ICASTSimpleDeclSpecifier; +import org.eclipse.cdt.core.dom.ast.c.ICASTTypedefNameSpecifier; import org.eclipse.cdt.core.dom.ast.c.ICNodeFactory; -import org.eclipse.cdt.core.dom.ast.gnu.c.ICASTKnRFunctionDeclarator; import org.eclipse.cdt.core.dom.parser.c.ICParserExtensionConfiguration; import org.eclipse.cdt.core.index.IIndex; import org.eclipse.cdt.core.parser.EndOfFileException; @@ -54,7 +64,6 @@ import org.eclipse.cdt.core.parser.IToken; import org.eclipse.cdt.core.parser.ParserMode; import org.eclipse.cdt.core.parser.util.ArrayUtil; -import org.eclipse.cdt.core.parser.util.CharArrayUtils; import org.eclipse.cdt.internal.core.dom.parser.ASTNode; import org.eclipse.cdt.internal.core.dom.parser.ASTQueries; import org.eclipse.cdt.internal.core.dom.parser.ASTTranslationUnit; @@ -70,12 +79,13 @@ public class CSourceParser extends AbstractSourceCodeParser { private IASTTranslationUnit compilationUnit; private IIndex index; - private int fPreventKnrCheck = 0; + + public static final int INLINE = 0x01, CONST = 0x02, RESTRICT = 0x04, VOLATILE = 0x08, SHORT = 0x10, + UNSIGNED = 0x20, SIGNED = 0x40, COMPLEX = 0x80, IMAGINARY = 0x100; public CSourceParser(IScanner scanner, ParserMode parserMode, IParserLogService logService, ICParserExtensionConfiguration config, IIndex index) { - super(scanner, parserMode, logService, CNodeFactory.getDefault(), config.supportKnRC(), - config.getBuiltinBindingsProvider()); + super(scanner, parserMode, logService, CNodeFactory.getDefault(), config.getBuiltinBindingsProvider()); this.index = index; } @@ -140,8 +150,10 @@ protected IASTDeclarator initDeclarator(IASTDeclSpecifier declspec, final Declar @Override protected IASTDeclaration declaration(DeclarationOptions option) throws BacktrackException, EndOfFileException { switch (lookaheadType(1)) { + /* asm is technically not part of C case IToken.t_asm: return asmDeclaration(); + */ case IToken.tSEMI: IToken semi = consume(); IASTDeclSpecifier specifier = nodeFactory.newSimpleDeclSpecifier(); @@ -224,17 +236,135 @@ protected IASTExpression unaryExpression(CastExprCtx ctx, ITemplateIdStrategy st } } + @Override + protected IASTExpression expressionWithOptionalTrailingEllipsis() throws BacktrackException, EndOfFileException { + return expression(); + } + + @Override + protected IASTTypeId typeIDWithOptionalTrailingEllipsis(DeclarationOptions option) + throws EndOfFileException, BacktrackException { + return typeID(option); + } + + @Override + protected IASTAlignmentSpecifier createAmbiguousAlignmentSpecifier(IASTAlignmentSpecifier expression, + IASTAlignmentSpecifier typeId) { + return new CASTAmbiguousAlignmentSpecifier(expression, typeId); + } + @Override protected IASTExpression primaryExpression(CastExprCtx ctx, ITemplateIdStrategy strat) throws BacktrackException, EndOfFileException { - // TODO Auto-generated method stub - return null; + IToken token = null; + IASTLiteralExpression literalExpression = null; + switch (lookaheadType(1)) { + // TO DO: we need more literals... + case IToken.tINTEGER: + token = consume(); + literalExpression = nodeFactory.newLiteralExpression(IASTLiteralExpression.lk_integer_constant, + token.getImage()); + ((ASTNode) literalExpression).setOffsetAndLength(token.getOffset(), + token.getEndOffset() - token.getOffset()); + return literalExpression; + case IToken.tFLOATINGPT: + token = consume(); + literalExpression = nodeFactory.newLiteralExpression(IASTLiteralExpression.lk_float_constant, + token.getImage()); + ((ASTNode) literalExpression).setOffsetAndLength(token.getOffset(), + token.getEndOffset() - token.getOffset()); + return literalExpression; + case IToken.tSTRING: + case IToken.tLSTRING: + case IToken.tUTF16STRING: + case IToken.tUTF32STRING: + token = consume(); + literalExpression = nodeFactory.newLiteralExpression(IASTLiteralExpression.lk_string_literal, + token.getImage()); + ((ASTNode) literalExpression).setOffsetAndLength(token.getOffset(), + token.getEndOffset() - token.getOffset()); + return literalExpression; + case IToken.tCHAR: + case IToken.tLCHAR: + case IToken.tUTF16CHAR: + case IToken.tUTF32CHAR: + token = consume(); + literalExpression = nodeFactory.newLiteralExpression(IASTLiteralExpression.lk_char_constant, + token.getImage()); + ((ASTNode) literalExpression).setOffsetAndLength(token.getOffset(), token.getLength()); + return literalExpression; + case IToken.tLPAREN: + token = consume(); + IASTExpression lhs = expression(ExprKind.eExpression); // instead of expression(), to keep the stack smaller + int finalOffset = 0; + switch (lookaheadType(1)) { + case IToken.tRPAREN: + case IToken.tEOC: + finalOffset = consume().getEndOffset(); + break; + default: + throwBacktrack(lookahead(1)); + } + return buildUnaryExpression(IASTUnaryExpression.op_bracketedPrimary, lhs, token.getOffset(), finalOffset); + case IToken.tIDENTIFIER: + case IToken.tCOMPLETION: + case IToken.tEOC: + int startingOffset = lookahead(1).getOffset(); + IASTName name = identifier(); + IASTIdExpression idExpression = nodeFactory.newIdExpression(name); + ((ASTNode) idExpression).setOffsetAndLength((ASTNode) name); + return idExpression; + default: + IToken lookahead = lookahead(1); + startingOffset = lookahead.getOffset(); + throwBacktrack(startingOffset, lookahead.getLength()); + return null; + } } @Override protected IASTStatement statement() throws EndOfFileException, BacktrackException { - // TODO Auto-generated method stub - return null; + switch (lookaheadType(1)) { + // labeled statements + case IToken.t_case: + return parseCaseStatement(); + case IToken.t_default: + return parseDefaultStatement(); + // compound statement + case IToken.tLBRACE: + return parseCompoundStatement(); + // selection statement + case IToken.t_if: + return parseIfStatement(); + case IToken.t_switch: + return parseSwitchStatement(); + // iteration statements + case IToken.t_while: + return parseWhileStatement(); + case IToken.t_do: + return parseDoStatement(); + case IToken.t_for: + return parseForStatement(); + // jump statement + case IToken.t_break: + return parseBreakStatement(); + case IToken.t_continue: + return parseContinueStatement(); + case IToken.t_return: + return parseReturnStatement(); + case IToken.t_goto: + return parseGotoStatement(); + case IToken.tSEMI: + return parseNullStatement(); + default: + // can be many things: + // label + if (lookaheadType(1) == IToken.tIDENTIFIER && lookaheadType(2) == IToken.tCOLON) { + return parseLabelStatement(); + } + + return parseDeclarationOrExpressionStatement(); + } } @Override @@ -265,15 +395,368 @@ protected IASTAmbiguousExpression createAmbiguousCastVsMethodCallExpression(IAST @Override protected IASTTypeId typeID(DeclarationOptions option) throws EndOfFileException, BacktrackException { - // TODO Auto-generated method stub - return null; + if (!canBeTypeSpecifier()) { + return null; + } + final int offset = mark().getOffset(); + IASTDeclSpecifier declSpecifier = null; + IASTDeclarator declarator = null; + + try { + Decl decl = initDeclSpecifierSequenceDeclarator(option, false); + declSpecifier = decl.fDeclSpec1; + declarator = decl.fDtor1; + } catch (FoundAggregateInitializer lie) { + // type-ids have not compound initializers + throwBacktrack(lie.fDeclarator); + } + + IASTTypeId result = nodeFactory.newTypeId(declSpecifier, declarator); + setRange(result, offset, figureEndOffset(declSpecifier, declarator)); + return result; } @Override protected Decl declSpecifierSeq(DeclarationOptions option, ITemplateIdStrategy strat) throws BacktrackException, EndOfFileException { - // TODO Auto-generated method stub - return null; + int storageClass = IASTDeclSpecifier.sc_unspecified; + int simpleType = IASTSimpleDeclSpecifier.t_unspecified; + int options = 0; + int isLong = 0; + + IToken returnToken = null; + ICASTDeclSpecifier result = null; + ICASTDeclSpecifier altResult = null; + IASTAlignmentSpecifier[] alignmentSpecifiers = IASTAlignmentSpecifier.EMPTY_ALIGNMENT_SPECIFIER_ARRAY; + List attributes = null; + try { + IASTName identifier = null; + IASTExpression typeofExpression = null; + IASTProblem problem = null; + + boolean encounteredRawType = false; + boolean encounteredTypename = false; + + final int offset = lookahead(1).getOffset(); + int endOffset = offset; + + declSpecifiers: for (;;) { + final int type = lookaheadTypeWithEndOfFile(1); + switch (type) { + 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; + + // Method Specifier + case IToken.t_inline: + options |= INLINE; + 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; + + // 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 = IASTSimpleDeclSpecifier.t_bool; + encounteredRawType = true; + endOffset = consume().getEndOffset(); + break; + case IToken.t__Complex: + if (encounteredTypename) + break declSpecifiers; + options |= COMPLEX; + endOffset = consume().getEndOffset(); + break; + case IToken.t__Imaginary: + if (encounteredTypename) + break declSpecifiers; + options |= IMAGINARY; + endOffset = consume().getEndOffset(); + break; + + case IToken.tIDENTIFIER: + case IToken.tCOMPLETION: + case IToken.tEOC: + if (encounteredTypename || encounteredRawType) + break declSpecifiers; + + if ((endOffset != offset || option.fAllowEmptySpecifier) + && lookaheadType(1) != IToken.tCOMPLETION) { + altResult = buildSimpleDeclSpec(storageClass, simpleType, options, isLong, typeofExpression, + offset, endOffset); + returnToken = mark(); + } + + 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 exception) { + result = elaboratedTypeSpecifier(); + } + endOffset = calculateEndOffset(result); + encounteredTypename = true; + break; + case IToken.t_enum: + if (encounteredTypename || encounteredRawType) + break declSpecifiers; + try { + result = (ICASTEnumerationSpecifier) enumSpecifier(); + } catch (BacktrackException exception) { + if (exception.getNodeBeforeProblem() instanceof ICASTDeclSpecifier) { + result = (ICASTDeclSpecifier) exception.getNodeBeforeProblem(); + problem = exception.getProblem(); + break declSpecifiers; + } else { + result = elaboratedTypeSpecifier(); + } + } + endOffset = calculateEndOffset(result); + encounteredTypename = true; + break; + + case IToken.t__Alignas: + alignmentSpecifiers = ArrayUtil.append(alignmentSpecifiers, alignmentSpecifier()); + break; + + default: + break declSpecifiers; + } + + if (encounteredRawType && encounteredTypename) + throwBacktrack(lookahead(1)); + } + + // check for empty specification + if (!encounteredRawType && !encounteredTypename && lookaheadType(1) != IToken.tEOC + && !option.fAllowEmptySpecifier) { + if (offset == endOffset) { + throwBacktrack(lookahead(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); + } + result.setAlignmentSpecifiers(ArrayUtil.trim(alignmentSpecifiers)); + addAttributeSpecifiers(attributes, result); + endOffset = attributesEndOffset(endOffset, attributes); + setRange(result, offset, endOffset); + } catch (BacktrackException exception) { + if (returnToken != null) { + backup(returnToken); + result = altResult; + altResult = null; + returnToken = null; + } else { + throw exception; + } + } + Decl target = new Decl(); + target.fDeclSpec1 = result; + target.fDeclSpec2 = altResult; + target.fDtorToken1 = returnToken; + return target; + } + + /** + * Parse a class/struct/union definition. + * + * classSpecifier : classKey name (baseClause)? "{" (memberSpecification)* + * "}" + * + * @throws BacktrackException to request a backtrack + */ + protected ICASTCompositeTypeSpecifier structOrUnionSpecifier() throws BacktrackException, EndOfFileException { + int classKind = 0; + IToken mark = mark(); + final int offset = mark.getOffset(); + + // class key + switch (lookaheadType(1)) { + case IToken.t_struct: + consume(); + classKind = IASTCompositeTypeSpecifier.k_struct; + break; + case IToken.t_union: + consume(); + classKind = IASTCompositeTypeSpecifier.k_union; + break; + default: + throwBacktrack(lookahead(1)); + return null; // line never reached, hint for the parser. + } + + // WIP C23 + List attributes = new ArrayList<>(); + + // class name + IASTName name = null; + if (lookaheadType(1) == IToken.tIDENTIFIER) { + name = identifier(); + } + + if (lookaheadType(1) != IToken.tLBRACE) { + IToken errorPoint = lookahead(1); + backup(mark); + throwBacktrack(errorPoint); + } + + if (name == null) { + name = nodeFactory.newName(); + } + ICASTCompositeTypeSpecifier result = (ICASTCompositeTypeSpecifier) nodeFactory + .newCompositeTypeSpecifier(classKind, name); + declarationListInBraces(result, offset, DeclarationOptions.C_MEMBER); + addAttributeSpecifiers(attributes, result); + return result; + } + + protected ICASTElaboratedTypeSpecifier elaboratedTypeSpecifier() throws BacktrackException, EndOfFileException { + // this is an elaborated class specifier + IToken token = consume(); + int kind = 0; + + switch (token.getType()) { + case IToken.t_struct: + kind = IASTElaboratedTypeSpecifier.k_struct; + break; + case IToken.t_union: + kind = IASTElaboratedTypeSpecifier.k_union; + break; + case IToken.t_enum: + kind = IASTElaboratedTypeSpecifier.k_enum; + break; + default: + backup(token); + throwBacktrack(token.getOffset(), token.getLength()); + } + + IASTName name = identifier(); + ICASTElaboratedTypeSpecifier result = (ICASTElaboratedTypeSpecifier) nodeFactory + .newElaboratedTypeSpecifier(kind, name); + ((ASTNode) result).setOffsetAndLength(token.getOffset(), calculateEndOffset(name) - token.getOffset()); + return result; } private IASTDeclarator declarator(IASTDeclSpecifier declSpec, DeclarationOptions option) @@ -395,10 +878,12 @@ private IASTDeclarator declarator(final List pointerOps, endOffset = calculateEndOffset(result); } + /* if (type != 0 && lookaheadType(1) == IToken.t_asm) { // asm labels bug 226121 consume(); endOffset = asmExpression(null).getEndOffset(); } + */ for (IASTPointerOperator operator : pointerOps) { result.addPointerOperator(operator); @@ -551,70 +1036,6 @@ private IASTDeclarator methodDeclarator(DeclarationOptions paramOption) IToken last = consume(IToken.tLPAREN); int startOffset = last.getOffset(); - // check for K&R C parameters (0 means it's not K&R C) - if (fPreventKnrCheck == 0 && supportKnRC) { - fPreventKnrCheck++; - try { - final int numKnRCParms = countKnRCParms(); - if (numKnRCParms > 0) { // KnR C parameters were found - IASTName[] parmNames = new IASTName[numKnRCParms]; - IASTDeclaration[] parmDeclarations = new IASTDeclaration[numKnRCParms]; - - boolean seenParameter = false; - for (int i = 0; i <= parmNames.length; i++) { - switch (lookaheadType(1)) { - case IToken.tCOMMA: - last = consume(); - parmNames[i] = identifier(); - seenParameter = true; - break; - case IToken.tIDENTIFIER: - if (seenParameter) - throwBacktrack(startOffset, last.getEndOffset() - startOffset); - - parmNames[i] = identifier(); - seenParameter = true; - break; - case IToken.tRPAREN: - last = consume(); - break; - default: - break; - } - } - - // now that the parameter names are parsed, parse the parameter declarations - // count for parameter declarations <= count for parameter names. - int endOffset = last.getEndOffset(); - for (int i = 0; i < numKnRCParms && lookaheadType(1) != IToken.tLBRACE; i++) { - try { - IASTDeclaration decl = simpleDeclaration(DeclarationOptions.LOCAL); - IASTSimpleDeclaration ok = checkKnrParameterDeclaration(decl, parmNames); - if (ok != null) { - parmDeclarations[i] = ok; - endOffset = calculateEndOffset(ok); - } else { - final ASTNode node = (ASTNode) decl; - parmDeclarations[i] = createKnRCProblemDeclaration(node.getOffset(), node.getLength()); - endOffset = calculateEndOffset(node); - } - } catch (BacktrackException b) { - parmDeclarations[i] = createKnRCProblemDeclaration(b.getOffset(), b.getLength()); - endOffset = b.getOffset() + b.getLength(); - } - } - - parmDeclarations = ArrayUtil.removeNulls(IASTDeclaration.class, parmDeclarations); - ICASTKnRFunctionDeclarator functionDecltor = ((ICNodeFactory) nodeFactory) - .newKnRFunctionDeclarator(parmNames, parmDeclarations); - ((ASTNode) functionDecltor).setOffsetAndLength(startOffset, endOffset - startOffset); - return functionDecltor; - } - } finally { - fPreventKnrCheck--; - } - } - boolean seenParameter = false; boolean encounteredVarArgs = false; List parameters = null; @@ -1065,7 +1486,6 @@ private final IASTParameterDeclaration parameterDeclaration(DeclarationOptions o IASTDeclarator altDeclarator = null; try { - fPreventKnrCheck++; Decl decl = initDeclSpecifierSequenceDeclarator(option, false); declSpec = decl.fDeclSpec1; declarator = decl.fDtor1; @@ -1074,8 +1494,6 @@ private final IASTParameterDeclaration parameterDeclaration(DeclarationOptions o } catch (FoundAggregateInitializer lie) { declSpec = lie.fDeclSpec; declarator = lie.fDeclarator; - } finally { - fPreventKnrCheck--; } final int length = figureEndOffset(declSpec, declarator) - startingOffset; @@ -1091,127 +1509,43 @@ private final IASTParameterDeclaration parameterDeclaration(DeclarationOptions o return result; } - @Deprecated - private int countKnRCParms() { - IToken mark = null; - int parmCount = 0; - boolean previousWasIdentifier = false; - - try { - mark = mark(); - - // starts at the beginning of the parameter list - for (;;) { - if (lookaheadType(1) == IToken.tCOMMA) { - consume(); - previousWasIdentifier = false; - } else if (lookaheadType(1) == IToken.tIDENTIFIER) { - consume(); - if (previousWasIdentifier) { - backup(mark); - return 0; // i.e. KnR C won't have int f(typedef x) - // char - // x; {} - } - previousWasIdentifier = true; - parmCount++; - } else if (lookaheadType(1) == IToken.tRPAREN) { - if (!previousWasIdentifier) { - // if the first token encountered is tRPAREN then it's not K&R C - // the first token when counting K&R C parms is always an identifier - backup(mark); - return 0; - } - consume(); - break; - } else { - backup(mark); - return 0; // i.e. KnR C won't have int f(char) char x; {} - } - } - - // if the next token is a tSEMI then the declaration was a regular - // declaration statement i.e. int f(type_def); - final int type = lookaheadType(1); - if (type == IToken.tSEMI || type == IToken.tLBRACE) { - backup(mark); - return 0; - } - - // look ahead for the start of the function body, if end of file is - // found then return 0 parameters found (implies not KnR C) - int previous = -1; - while (lookaheadType(1) != IToken.tLBRACE) { - // fix for 100104: check if the parameter declaration is a valid one - try { - simpleDeclaration(DeclarationOptions.LOCAL); - } catch (BacktrackException e) { - backup(mark); - return 0; - } - - final IToken token = lookahead(1); - if (token.getType() == IToken.tEOC) - break; - - final int next = token.hashCode(); - if (next == previous) { // infinite loop detected - break; - } - previous = next; - } - - backup(mark); - return parmCount; - } catch (EndOfFileException exception) { - if (mark != null) - backup(mark); - - return 0; - } - } - - @Deprecated - private IASTProblemDeclaration createKnRCProblemDeclaration(int offset, int length) throws EndOfFileException { - IASTProblem problem = createProblem(IProblem.SYNTAX_ERROR, offset, length); - IASTProblemDeclaration declaration = nodeFactory.newProblemDeclaration(problem); - ((ASTNode) declaration).setOffsetAndLength((ASTNode) problem); - - // consume until LBRACE is found (to leave off at the function body and - // continue from there) - IToken previous = null; - IToken next = null; - while (lookaheadType(1) != IToken.tLBRACE) { - next = consume(); - if (next == previous || next.getType() == IToken.tEOC) { // infinite loop detected - break; - } - previous = next; + private ICASTSimpleDeclSpecifier buildSimpleDeclSpec(int storageClass, int simpleType, int options, int isLong, + IASTExpression typeofExpression, int offset, int endOffset) { + ICASTSimpleDeclSpecifier declSpec = (ICASTSimpleDeclSpecifier) nodeFactory.newSimpleDeclSpecifier(); + + configureDeclSpec(declSpec, storageClass, options); + declSpec.setType(simpleType); + declSpec.setLong(isLong == 1); + declSpec.setLongLong(isLong > 1); + declSpec.setRestrict((options & RESTRICT) != 0); + declSpec.setUnsigned((options & UNSIGNED) != 0); + declSpec.setSigned((options & SIGNED) != 0); + declSpec.setShort((options & SHORT) != 0); + declSpec.setComplex((options & COMPLEX) != 0); + declSpec.setImaginary((options & IMAGINARY) != 0); + if (typeofExpression != null) { + declSpec.setDeclTypeExpression(typeofExpression); + typeofExpression.setParent(declSpec); } - return declaration; + ((ASTNode) declSpec).setOffsetAndLength(offset, endOffset - offset); + return declSpec; } - @Deprecated - private IASTSimpleDeclaration checkKnrParameterDeclaration(IASTDeclaration decl, final IASTName[] paramNames) { - if (!(decl instanceof IASTSimpleDeclaration)) - return null; + private void configureDeclSpec(IASTDeclSpecifier specifier, int storageClass, int options) { + specifier.setStorageClass(storageClass); + specifier.setConst((options & CONST) != 0); + specifier.setVolatile((options & VOLATILE) != 0); + specifier.setInline((options & INLINE) != 0); + } - IASTSimpleDeclaration declaration = ((IASTSimpleDeclaration) decl); - IASTDeclarator[] decltors = declaration.getDeclarators(); - for (IASTDeclarator decltor : decltors) { - boolean decltorOk = false; - final char[] nchars = ASTQueries.findInnermostDeclarator(decltor).getName().toCharArray(); - for (IASTName parmName : paramNames) { - if (CharArrayUtils.equals(nchars, parmName.toCharArray())) { - decltorOk = true; - break; - } - } - if (!decltorOk) - return null; - } - return declaration; + private ICASTTypedefNameSpecifier buildNamedTypeSpecifier(IASTName name, int storageClass, int options, int offset, + int endOffset) { + ICASTTypedefNameSpecifier declSpec = (ICASTTypedefNameSpecifier) nodeFactory.newTypedefNameSpecifier(name); + configureDeclSpec(declSpec, storageClass, options); + declSpec.setRestrict((options & RESTRICT) != 0); + ((ASTNode) declSpec).setOffsetAndLength(offset, endOffset - offset); + return declSpec; } private IASTExpression postfixExpression(CastExprCtx ctx, ITemplateIdStrategy strat) @@ -1346,4 +1680,5 @@ private IASTExpression postfixExpression(CastExprCtx ctx, ITemplateIdStrategy st } } } + }