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 e8e4d45eb79..854f30caf77 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 @@ -11082,4 +11082,26 @@ public class AST2CPPTests extends AST2TestBase { public void testTemplateIdInsideCastOperator_460080() throws Exception { parseAndCheckBindings(); } + + // alignas(8) int x; + // alignas(int) char y; + // alignas(16) struct { int x; int y; }; + // alignas(8) enum { A, B, C }; + // struct S { + // alignas(long long) int x; + // alignas(decltype(x)) int y; + // }; + // alignas(32) S s; + // template + // struct U { + // alignas(S) int x; + // alignas(T...) char y; + // }; + // template + // struct Y { + // alignas(N...) char x; + // }; + public void testAlignas_451082() throws Exception { + parseAndCheckBindings(); + } } diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2Tests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2Tests.java index 418d8a5b4c1..dc1c57f363b 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2Tests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2Tests.java @@ -7595,4 +7595,18 @@ public class AST2Tests extends AST2TestBase { public void testVoidPointerInTernaryOperator_460741() throws Exception { parseAndCheckBindings(getAboveComment(), C); } + + // _Alignas(8) int x; + // _Alignas(int) char y; + // _Alignas(16) struct { int x; int y; }; + // _Alignas(8) enum { A, B, C }; + // struct S { + // int x; + // _Alignas(8) int y; + // }; + // _Alignas(32) struct S s; + // _Alignas(struct S) int t; + public void testAlignas_451082() throws Exception { + parseAndCheckBindings(getAboveComment(), C); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTAlignmentSpecifier.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTAlignmentSpecifier.java new file mode 100644 index 00000000000..20d9b4be30c --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTAlignmentSpecifier.java @@ -0,0 +1,55 @@ +/******************************************************************************* + * Copyright (c) 2015 Nathan Ridge. + * 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: + * Nathan Ridge - Initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.core.dom.ast; + +/** + * Represents an alignment specifier. + * + * Grammatically, this is a decl-specifier. + * + * Possible forms are: + * C++: + * alignas() + * alignas() + * C: + * _Alignas() + * _Alignas() + * @noimplement This interface is not intended to be implemented by clients. + * @noextend This interface is not intended to be extended by clients. + * @since 5.10 + */ +public interface IASTAlignmentSpecifier extends IASTNode { + public static final IASTAlignmentSpecifier[] EMPTY_ALIGNMENT_SPECIFIER_ARRAY = {}; + + public static final ASTNodeProperty ALIGNMENT_EXPRESSION = new ASTNodeProperty( + "IASTAlignmentSpecifier.ALIGNMENT_EXPRESSION - Expression in alignment specifier"); //$NON-NLS-1$ + + public static final ASTNodeProperty ALIGNMENT_TYPEID = new ASTNodeProperty( + "IASTAlignmentSpecifier.ALIGNMENT_TYPEID - Type-id in alignment specifier"); //$NON-NLS-1$ + + /** + * If the specifier is of the form 'alignas()' or '_Alignas()', + * returns the enclosed expression. Otherwise, returns null. + */ + IASTExpression getExpression(); + + /** + * If the specifier is of the form 'alignas()' or '_Alignas()', + * returns the enclosed type-id. Otherwise, returns null. + */ + IASTTypeId getTypeId(); + + @Override + public IASTAlignmentSpecifier copy(); + + @Override + public IASTAlignmentSpecifier copy(CopyStyle style); +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTDeclSpecifier.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTDeclSpecifier.java index 46d36600b60..49e59dbb477 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTDeclSpecifier.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTDeclSpecifier.java @@ -30,6 +30,10 @@ public interface IASTDeclSpecifier extends IASTNode { /** @since 5.2 */ public static final int sc_mutable = 6; + /** @since 5.10 */ + public static final ASTNodeProperty ALIGNMENT_SPECIFIER = new ASTNodeProperty( + "IASTDeclSpecifier.ALIGNMENT_SPECIFIER - Alignment specifier"); //$NON-NLS-1$ + /** * Returns the storage class, which is one of the constants sc_... */ @@ -47,6 +51,12 @@ public interface IASTDeclSpecifier extends IASTNode { // Function specifier public boolean isInline(); + /** + * Get any alignment-specifiers in this decl-specifier sequence. + * @since 5.10 + */ + public IASTAlignmentSpecifier[] getAlignmentSpecifiers(); + /** * @since 5.1 */ @@ -85,6 +95,12 @@ public interface IASTDeclSpecifier extends IASTNode { */ public void setInline(boolean value); + /** + * Not allowed on frozen ast. + * @since 5.10 + */ + public void setAlignmentSpecifiers(IASTAlignmentSpecifier[] alignmentSpecifiers); + /** * @deprecated All constants must be defined in this interface. */ diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/INodeFactory.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/INodeFactory.java index d24f40150d5..4c72cb15a98 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/INodeFactory.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/INodeFactory.java @@ -42,7 +42,13 @@ import org.eclipse.cdt.core.parser.IToken; * @noimplement This interface is not intended to be implemented by clients. */ public interface INodeFactory { - + + /** @since 5.10 */ + public IASTAlignmentSpecifier newAlignmentSpecifier(IASTExpression expression); + + /** @since 5.10 */ + public IASTAlignmentSpecifier newAlignmentSpecifier(IASTTypeId typeId); + public IASTArrayDeclarator newArrayDeclarator(IASTName name); public IASTArrayModifier newArrayModifier(IASTExpression expr); 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 0924eacc4dc..df63b03c61f 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 @@ -23,6 +23,7 @@ import org.eclipse.cdt.core.dom.ast.ASTCompletionNode; import org.eclipse.cdt.core.dom.ast.ASTGenericVisitor; import org.eclipse.cdt.core.dom.ast.ASTVisitor; import org.eclipse.cdt.core.dom.ast.IASTASMDeclaration; +import org.eclipse.cdt.core.dom.ast.IASTAlignmentSpecifier; import org.eclipse.cdt.core.dom.ast.IASTAttribute; import org.eclipse.cdt.core.dom.ast.IASTAttributeOwner; import org.eclipse.cdt.core.dom.ast.IASTAttributeSpecifier; @@ -1153,6 +1154,13 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser { protected abstract IASTExpression unaryExpression(CastExprCtx ctx, ITemplateIdStrategy strat) throws BacktrackException, EndOfFileException; protected abstract IASTExpression primaryExpression(CastExprCtx ctx, ITemplateIdStrategy strat) throws BacktrackException, EndOfFileException; 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; private final static class CastAmbiguityMarker extends ASTNode implements IASTExpression { private IASTExpression fExpression; @@ -2669,4 +2677,68 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser { } } } + + protected abstract IASTAlignmentSpecifier createAmbiguousAlignmentSpecifier(IASTAlignmentSpecifier expression, + IASTAlignmentSpecifier typeId); + + 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 e) { + } + + // Back up and try parsing an expression. + backup(beginning); + try { + expression = expressionWithOptionalTrailingEllipsis(); + } catch (BacktrackException e) { + // If neither parses successfully, throw. + if (typeId == null) { + throw e; + } + } + + 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; + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTAlignmentSpecifier.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTAlignmentSpecifier.java new file mode 100644 index 00000000000..94ccdb9b15d --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTAlignmentSpecifier.java @@ -0,0 +1,69 @@ +/******************************************************************************* + * Copyright (c) 2015 Nathan Ridge. + * 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: + * Nathan Ridge - Initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.core.dom.parser.c; + +import org.eclipse.cdt.core.dom.ast.ASTVisitor; +import org.eclipse.cdt.core.dom.ast.IASTAlignmentSpecifier; +import org.eclipse.cdt.core.dom.ast.IASTExpression; +import org.eclipse.cdt.core.dom.ast.IASTTypeId; +import org.eclipse.cdt.internal.core.dom.parser.ASTNode; + +public class CASTAlignmentSpecifier extends ASTNode implements IASTAlignmentSpecifier { + // Precisely one of these is null. + private IASTExpression fExpression; + private IASTTypeId fTypeId; + + CASTAlignmentSpecifier(IASTExpression expression) { + fExpression = expression; + fExpression.setParent(this); + fExpression.setPropertyInParent(ALIGNMENT_EXPRESSION); + } + + CASTAlignmentSpecifier(IASTTypeId typeId) { + fTypeId = typeId; + fTypeId.setParent(this); + fTypeId.setPropertyInParent(ALIGNMENT_TYPEID); + } + + @Override + public IASTExpression getExpression() { + return fExpression; + } + + @Override + public IASTTypeId getTypeId() { + return fTypeId; + } + + @Override + public IASTAlignmentSpecifier copy() { + return copy(CopyStyle.withoutLocations); + } + + @Override + public IASTAlignmentSpecifier copy(CopyStyle style) { + CASTAlignmentSpecifier copy; + if (fExpression != null) { + copy = new CASTAlignmentSpecifier(fExpression.copy(style)); + } else { + copy = new CASTAlignmentSpecifier(fTypeId.copy(style)); + } + return copy(copy, style); + } + + @Override + public boolean accept(ASTVisitor visitor) { + if (fExpression != null) { + return fExpression.accept(visitor); + } + return fTypeId.accept(visitor); + } +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTAmbiguousAlignmentSpecifier.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTAmbiguousAlignmentSpecifier.java new file mode 100644 index 00000000000..938523275e6 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTAmbiguousAlignmentSpecifier.java @@ -0,0 +1,52 @@ +/******************************************************************************* + * Copyright (c) 2015 Nathan Ridge. + * 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: + * Nathan Ridge - Initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.core.dom.parser.c; + +import org.eclipse.cdt.core.dom.ast.IASTAlignmentSpecifier; +import org.eclipse.cdt.core.dom.ast.IASTExpression; +import org.eclipse.cdt.core.dom.ast.IASTNode; +import org.eclipse.cdt.core.dom.ast.IASTTypeId; +import org.eclipse.cdt.internal.core.dom.parser.ASTAmbiguousNode; + +public class CASTAmbiguousAlignmentSpecifier extends ASTAmbiguousNode implements IASTAlignmentSpecifier { + IASTAlignmentSpecifier fExpression; + IASTAlignmentSpecifier fTypeId; + + CASTAmbiguousAlignmentSpecifier(IASTAlignmentSpecifier expression, IASTAlignmentSpecifier typeId) { + fExpression = expression; + fTypeId = typeId; + } + + @Override + public IASTExpression getExpression() { + return fExpression.getExpression(); + } + + @Override + public IASTTypeId getTypeId() { + return fTypeId.getTypeId(); + } + + @Override + public IASTAlignmentSpecifier copy() { + throw new UnsupportedOperationException(); + } + + @Override + public IASTAlignmentSpecifier copy(CopyStyle style) { + throw new UnsupportedOperationException(); + } + + @Override + public IASTNode[] getNodes() { + return new IASTNode[] { fExpression, fTypeId }; + } +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTBaseDeclSpecifier.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTBaseDeclSpecifier.java index d8f002bd023..3ec08d483c2 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTBaseDeclSpecifier.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTBaseDeclSpecifier.java @@ -10,21 +10,27 @@ *******************************************************************************/ package org.eclipse.cdt.internal.core.dom.parser.c; +import org.eclipse.cdt.core.dom.ast.ASTVisitor; +import org.eclipse.cdt.core.dom.ast.IASTAlignmentSpecifier; +import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.c.ICASTDeclSpecifier; import org.eclipse.cdt.internal.core.dom.parser.ASTNode; +import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguityParent; /** * @author jcamelon */ -public abstract class CASTBaseDeclSpecifier extends ASTNode implements ICASTDeclSpecifier { +public abstract class CASTBaseDeclSpecifier extends ASTNode + implements ICASTDeclSpecifier, IASTAmbiguityParent { protected int storageClass; protected boolean isConst; protected boolean isVolatile; protected boolean isRestrict; protected boolean isInline; - + protected IASTAlignmentSpecifier[] alignmentSpecifiers = + IASTAlignmentSpecifier.EMPTY_ALIGNMENT_SPECIFIER_ARRAY; @Override public boolean isRestrict() { @@ -51,6 +57,11 @@ public abstract class CASTBaseDeclSpecifier extends ASTNode implements ICASTDecl return isInline; } + @Override + public IASTAlignmentSpecifier[] getAlignmentSpecifiers() { + return alignmentSpecifiers; + } + @Override public void setStorageClass(int storageClass) { assertNotFrozen(); @@ -81,12 +92,50 @@ public abstract class CASTBaseDeclSpecifier extends ASTNode implements ICASTDecl this.isInline = value; } + @Override + public void setAlignmentSpecifiers(IASTAlignmentSpecifier[] alignmentSpecifiers) { + assertNotFrozen(); + for (IASTAlignmentSpecifier specifier : alignmentSpecifiers) { + specifier.setParent(this); + specifier.setPropertyInParent(ALIGNMENT_SPECIFIER); + } + this.alignmentSpecifiers = alignmentSpecifiers; + } + protected T copy(T copy, CopyStyle style) { copy.storageClass = storageClass; copy.isConst = isConst; copy.isVolatile = isVolatile; copy.isRestrict = isRestrict; copy.isInline = isInline; + copy.alignmentSpecifiers = new IASTAlignmentSpecifier[alignmentSpecifiers.length]; + for (int i = 0; i < alignmentSpecifiers.length; ++i) { + copy.alignmentSpecifiers[i] = alignmentSpecifiers[i].copy(style); + copy.alignmentSpecifiers[i].setParent(copy); + } return super.copy(copy, style); } + + protected boolean visitAlignmentSpecifiers(ASTVisitor visitor) { + for (IASTAlignmentSpecifier specifier : alignmentSpecifiers) { + if (!specifier.accept(visitor)) { + return false; + } + } + return true; + } + + @Override + public void replace(IASTNode child, IASTNode other) { + if (child instanceof IASTAlignmentSpecifier && other instanceof IASTAlignmentSpecifier) { + for (int i = 0; i < alignmentSpecifiers.length; ++i) { + if (alignmentSpecifiers[i] == child) { + alignmentSpecifiers[i] = (IASTAlignmentSpecifier) other; + other.setParent(child.getParent()); + other.setPropertyInParent(child.getPropertyInParent()); + return; + } + } + } + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTCompositeTypeSpecifier.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTCompositeTypeSpecifier.java index 8647b1832d8..63f9f8f84d2 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTCompositeTypeSpecifier.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTCompositeTypeSpecifier.java @@ -20,13 +20,12 @@ import org.eclipse.cdt.core.dom.ast.IScope; import org.eclipse.cdt.core.dom.ast.c.ICASTCompositeTypeSpecifier; import org.eclipse.cdt.core.parser.util.ArrayUtil; import org.eclipse.cdt.internal.core.dom.parser.ASTQueries; -import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguityParent; /** * Implementation for C composite specifiers. */ public class CASTCompositeTypeSpecifier extends CASTBaseDeclSpecifier implements - ICASTCompositeTypeSpecifier, IASTAmbiguityParent { + ICASTCompositeTypeSpecifier { private int fKey; private IASTName fName; private IASTDeclaration[] fActiveDeclarations; @@ -141,6 +140,10 @@ public class CASTCompositeTypeSpecifier extends CASTBaseDeclSpecifier implements default: break; } } + if (!visitAlignmentSpecifiers(action)) { + return false; + } + if (fName != null && !fName.accept(action)) return false; @@ -149,7 +152,7 @@ public class CASTCompositeTypeSpecifier extends CASTBaseDeclSpecifier implements if (!decls[i].accept(action)) return false; } - + if (action.shouldVisitDeclSpecifiers) { switch (action.leave(this)) { case ASTVisitor.PROCESS_ABORT: return false; @@ -179,5 +182,6 @@ public class CASTCompositeTypeSpecifier extends CASTBaseDeclSpecifier implements return; } } + super.replace(child, other); } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTElaboratedTypeSpecifier.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTElaboratedTypeSpecifier.java index 786da820f8a..6f40bf8c1d0 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTElaboratedTypeSpecifier.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTElaboratedTypeSpecifier.java @@ -90,6 +90,9 @@ public class CASTElaboratedTypeSpecifier extends CASTBaseDeclSpecifier implement default : break; } } + if (!visitAlignmentSpecifiers(action)) { + return false; + } if( name != null ) if( !name.accept( action ) ) return false; if( action.shouldVisitDeclSpecifiers ){ switch( action.leave( this ) ){ diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTEnumerationSpecifier.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTEnumerationSpecifier.java index c4590f8180a..0f7c325e155 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTEnumerationSpecifier.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTEnumerationSpecifier.java @@ -114,6 +114,9 @@ public class CASTEnumerationSpecifier extends CASTBaseDeclSpecifier default: break; } } + if (!visitAlignmentSpecifiers(action)) { + return false; + } if (fName != null && !fName.accept(action)) return false; IASTEnumerator[] etors = getEnumerators(); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTSimpleDeclSpecifier.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTSimpleDeclSpecifier.java index bedaed5fb89..2c79ac1a182 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTSimpleDeclSpecifier.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTSimpleDeclSpecifier.java @@ -17,10 +17,8 @@ import org.eclipse.cdt.core.dom.ast.IASTExpression; import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.IBasicType.Kind; import org.eclipse.cdt.core.dom.ast.c.ICASTSimpleDeclSpecifier; -import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguityParent; -public class CASTSimpleDeclSpecifier extends CASTBaseDeclSpecifier - implements ICASTSimpleDeclSpecifier, IASTAmbiguityParent { +public class CASTSimpleDeclSpecifier extends CASTBaseDeclSpecifier implements ICASTSimpleDeclSpecifier { private int simpleType; private boolean isSigned; private boolean isUnsigned; @@ -167,10 +165,14 @@ public class CASTSimpleDeclSpecifier extends CASTBaseDeclSpecifier default : break; } } + + if (!visitAlignmentSpecifiers(action)) { + return false; + } if (fDeclTypeExpression != null && !fDeclTypeExpression.accept(action)) return false; - + if( action.shouldVisitDeclSpecifiers ){ switch( action.leave( this ) ){ case ASTVisitor.PROCESS_ABORT : return false; @@ -224,6 +226,8 @@ public class CASTSimpleDeclSpecifier extends CASTBaseDeclSpecifier other.setPropertyInParent(child.getPropertyInParent()); other.setParent(child.getParent()); fDeclTypeExpression= (IASTExpression) other; + return; } + super.replace(child, other); } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTTypedefNameSpecifier.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTTypedefNameSpecifier.java index 5585c7537e9..418ff77e1e0 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTTypedefNameSpecifier.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTTypedefNameSpecifier.java @@ -72,6 +72,9 @@ public class CASTTypedefNameSpecifier extends CASTBaseDeclSpecifier implements default : break; } } + if (!visitAlignmentSpecifiers(action)) { + return false; + } if( name != null ) if( !name.accept( action ) ) return false; if( action.shouldVisitDeclSpecifiers ){ switch( action.leave( this ) ){ diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CNodeFactory.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CNodeFactory.java index 57e88259ec7..f4f35db2f56 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CNodeFactory.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CNodeFactory.java @@ -14,6 +14,7 @@ package org.eclipse.cdt.internal.core.dom.parser.c; import org.eclipse.cdt.core.dom.ast.IASTASMDeclaration; +import org.eclipse.cdt.core.dom.ast.IASTAlignmentSpecifier; import org.eclipse.cdt.core.dom.ast.IASTArrayDeclarator; import org.eclipse.cdt.core.dom.ast.IASTArraySubscriptExpression; import org.eclipse.cdt.core.dom.ast.IASTAttribute; @@ -103,6 +104,16 @@ public class CNodeFactory extends NodeFactory implements ICNodeFactory { return DEFAULT_INSTANCE; } + @Override + public IASTAlignmentSpecifier newAlignmentSpecifier(IASTExpression expression) { + return new CASTAlignmentSpecifier(expression); + } + + @Override + public IASTAlignmentSpecifier newAlignmentSpecifier(IASTTypeId typeId) { + return new CASTAlignmentSpecifier(typeId); + } + @Override public IASTArrayDeclarator newArrayDeclarator(IASTName name) { return new CASTArrayDeclarator(name); 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 31f21b9ec11..00754d9978b 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 @@ -22,6 +22,7 @@ import java.util.List; import org.eclipse.cdt.core.dom.ast.ASTVisitor; import org.eclipse.cdt.core.dom.ast.DOMException; +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; @@ -918,6 +919,7 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser { IToken returnToken= null; IASTDeclSpecifier result= null; IASTDeclSpecifier altResult= null; + IASTAlignmentSpecifier[] alignmentSpecifiers = IASTAlignmentSpecifier.EMPTY_ALIGNMENT_SPECIFIER_ARRAY; try { IASTName identifier= null; IASTExpression typeofExpression= null; @@ -1119,6 +1121,10 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser { encounteredTypename= true; break; + case IToken.t__Alignas: + alignmentSpecifiers = ArrayUtil.append(alignmentSpecifiers, alignmentSpecifier()); + break; + case IGCCToken.t__attribute__: // if __attribute__ is after the declSpec if (!supportAttributeSpecifiers) throwBacktrack(LA(1)); @@ -1182,6 +1188,7 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser { } else { result= buildSimpleDeclSpec(storageClass, simpleType, options, isLong, typeofExpression, offset, endOffset); } + result.setAlignmentSpecifiers(ArrayUtil.trim(alignmentSpecifiers)); } catch (BacktrackException e) { if (returnToken != null) { backup(returnToken); @@ -2157,4 +2164,24 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser { } return for_statement; } + + @Override + protected IASTExpression expressionWithOptionalTrailingEllipsis() throws BacktrackException, + EndOfFileException { + // No pack expansions in C. + return expression(); + } + + @Override + protected IASTTypeId typeIdWithOptionalTrailingEllipsis(DeclarationOptions option) + throws EndOfFileException, BacktrackException { + // No pack expansions in C. + return typeId(option); + } + + @Override + protected IASTAlignmentSpecifier createAmbiguousAlignmentSpecifier(IASTAlignmentSpecifier expression, + IASTAlignmentSpecifier typeId) { + return new CASTAmbiguousAlignmentSpecifier(expression, typeId); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTAlignmentSpecifier.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTAlignmentSpecifier.java new file mode 100644 index 00000000000..3572b97cd0c --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTAlignmentSpecifier.java @@ -0,0 +1,69 @@ +/******************************************************************************* + * Copyright (c) 2015 Nathan Ridge. + * 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: + * Nathan Ridge - 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.IASTAlignmentSpecifier; +import org.eclipse.cdt.core.dom.ast.IASTExpression; +import org.eclipse.cdt.core.dom.ast.IASTTypeId; +import org.eclipse.cdt.internal.core.dom.parser.ASTNode; + +public class CPPASTAlignmentSpecifier extends ASTNode implements IASTAlignmentSpecifier { + // Precisely one of these is null. + private IASTExpression fExpression; + private IASTTypeId fTypeId; + + CPPASTAlignmentSpecifier(IASTExpression expression) { + fExpression = expression; + fExpression.setParent(this); + fExpression.setPropertyInParent(ALIGNMENT_EXPRESSION); + } + + CPPASTAlignmentSpecifier(IASTTypeId typeId) { + fTypeId = typeId; + fTypeId.setParent(this); + fTypeId.setPropertyInParent(ALIGNMENT_TYPEID); + } + + @Override + public IASTExpression getExpression() { + return fExpression; + } + + @Override + public IASTTypeId getTypeId() { + return fTypeId; + } + + @Override + public IASTAlignmentSpecifier copy() { + return copy(CopyStyle.withoutLocations); + } + + @Override + public IASTAlignmentSpecifier copy(CopyStyle style) { + CPPASTAlignmentSpecifier copy; + if (fExpression != null) { + copy = new CPPASTAlignmentSpecifier(fExpression.copy(style)); + } else { + copy = new CPPASTAlignmentSpecifier(fTypeId.copy(style)); + } + return copy(copy, style); + } + + @Override + public boolean accept(ASTVisitor visitor) { + if (fExpression != null) { + return fExpression.accept(visitor); + } + return fTypeId.accept(visitor); + } +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTAmbiguousAlignmentSpecifier.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTAmbiguousAlignmentSpecifier.java new file mode 100644 index 00000000000..47f2ff54ce6 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTAmbiguousAlignmentSpecifier.java @@ -0,0 +1,52 @@ +/******************************************************************************* + * Copyright (c) 2015 Nathan Ridge. + * 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: + * Nathan Ridge - Initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.core.dom.parser.cpp; + +import org.eclipse.cdt.core.dom.ast.IASTAlignmentSpecifier; +import org.eclipse.cdt.core.dom.ast.IASTExpression; +import org.eclipse.cdt.core.dom.ast.IASTNode; +import org.eclipse.cdt.core.dom.ast.IASTTypeId; +import org.eclipse.cdt.internal.core.dom.parser.ASTAmbiguousNode; + +public class CPPASTAmbiguousAlignmentSpecifier extends ASTAmbiguousNode implements IASTAlignmentSpecifier { + IASTAlignmentSpecifier fExpression; + IASTAlignmentSpecifier fTypeId; + + CPPASTAmbiguousAlignmentSpecifier(IASTAlignmentSpecifier expression, IASTAlignmentSpecifier typeId) { + fExpression = expression; + fTypeId = typeId; + } + + @Override + public IASTExpression getExpression() { + return fExpression.getExpression(); + } + + @Override + public IASTTypeId getTypeId() { + return fTypeId.getTypeId(); + } + + @Override + public IASTAlignmentSpecifier copy() { + throw new UnsupportedOperationException(); + } + + @Override + public IASTAlignmentSpecifier copy(CopyStyle style) { + throw new UnsupportedOperationException(); + } + + @Override + public IASTNode[] getNodes() { + return new IASTNode[] { fExpression, fTypeId }; + } +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTBaseDeclSpecifier.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTBaseDeclSpecifier.java index 9f9eeff4e16..e311d9f27c9 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTBaseDeclSpecifier.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTBaseDeclSpecifier.java @@ -11,14 +11,19 @@ *******************************************************************************/ package org.eclipse.cdt.internal.core.dom.parser.cpp; +import org.eclipse.cdt.core.dom.ast.ASTVisitor; +import org.eclipse.cdt.core.dom.ast.IASTAlignmentSpecifier; +import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeclSpecifier; import org.eclipse.cdt.internal.core.dom.parser.ASTAttributeOwner; +import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguityParent; import org.eclipse.cdt.internal.core.model.ASTStringUtil; /** * Base for all c++ declaration specifiers. */ -public abstract class CPPASTBaseDeclSpecifier extends ASTAttributeOwner implements ICPPASTDeclSpecifier { +public abstract class CPPASTBaseDeclSpecifier extends ASTAttributeOwner + implements ICPPASTDeclSpecifier, IASTAmbiguityParent { private boolean explicit; private boolean friend; private boolean inline; @@ -29,6 +34,8 @@ public abstract class CPPASTBaseDeclSpecifier extends ASTAttributeOwner implemen private boolean isVolatile; private int sc; private boolean virtual; + private IASTAlignmentSpecifier[] alignmentSpecifiers = + IASTAlignmentSpecifier.EMPTY_ALIGNMENT_SPECIFIER_ARRAY; @Override public boolean isFriend() { @@ -139,7 +146,22 @@ public abstract class CPPASTBaseDeclSpecifier extends ASTAttributeOwner implemen assertNotFrozen(); this.explicit = value; } - + + @Override + public IASTAlignmentSpecifier[] getAlignmentSpecifiers() { + return alignmentSpecifiers; + } + + @Override + public void setAlignmentSpecifiers(IASTAlignmentSpecifier[] alignmentSpecifiers) { + assertNotFrozen(); + for (IASTAlignmentSpecifier specifier : alignmentSpecifiers) { + specifier.setParent(this); + specifier.setPropertyInParent(ALIGNMENT_SPECIFIER); + } + this.alignmentSpecifiers = alignmentSpecifiers; + } + protected T copy(T copy, CopyStyle style) { CPPASTBaseDeclSpecifier target = copy; target.explicit = explicit; @@ -152,6 +174,11 @@ public abstract class CPPASTBaseDeclSpecifier extends ASTAttributeOwner implemen target.isVolatile = isVolatile; target.sc = sc; target.virtual = virtual; + target.alignmentSpecifiers = new IASTAlignmentSpecifier[alignmentSpecifiers.length]; + for (int i = 0; i < alignmentSpecifiers.length; ++i) { + target.alignmentSpecifiers[i] = alignmentSpecifiers[i].copy(style); + target.alignmentSpecifiers[i].setParent(target); + } return super.copy(copy, style); } @@ -162,4 +189,27 @@ public abstract class CPPASTBaseDeclSpecifier extends ASTAttributeOwner implemen public String toString() { return ASTStringUtil.getSignatureString(this, null); } + + protected boolean visitAlignmentSpecifiers(ASTVisitor visitor) { + for (IASTAlignmentSpecifier specifier : alignmentSpecifiers) { + if (!specifier.accept(visitor)) { + return false; + } + } + return true; + } + + @Override + public void replace(IASTNode child, IASTNode other) { + if (child instanceof IASTAlignmentSpecifier && other instanceof IASTAlignmentSpecifier) { + for (int i = 0; i < alignmentSpecifiers.length; ++i) { + if (alignmentSpecifiers[i] == child) { + alignmentSpecifiers[i] = (IASTAlignmentSpecifier) other; + other.setParent(child.getParent()); + other.setPropertyInParent(child.getPropertyInParent()); + return; + } + } + } + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTCompositeTypeSpecifier.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTCompositeTypeSpecifier.java index 733e58cd9e8..ae5aeb0f94e 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTCompositeTypeSpecifier.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTCompositeTypeSpecifier.java @@ -22,13 +22,12 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTVisibilityLabel; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassScope; import org.eclipse.cdt.core.parser.util.ArrayUtil; import org.eclipse.cdt.internal.core.dom.parser.ASTQueries; -import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguityParent; /** * c++ specific composite type specifier */ public class CPPASTCompositeTypeSpecifier extends CPPASTBaseDeclSpecifier - implements ICPPASTCompositeTypeSpecifier, IASTAmbiguityParent { + implements ICPPASTCompositeTypeSpecifier { private int fKey; private IASTName fName; private CPPClassScope fScope; @@ -182,6 +181,10 @@ public class CPPASTCompositeTypeSpecifier extends CPPASTBaseDeclSpecifier if (!acceptByAttributeSpecifiers(action)) return false; + + if (!visitAlignmentSpecifiers(action)) { + return false; + } if (fName != null && !fName.accept(action)) return false; @@ -223,8 +226,10 @@ public class CPPASTCompositeTypeSpecifier extends CPPASTBaseDeclSpecifier other.setPropertyInParent(child.getPropertyInParent()); fAllDeclarations[i] = (IASTDeclaration) other; fActiveDeclarations= null; + return; } } + super.replace(child, other); } @Override diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTElaboratedTypeSpecifier.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTElaboratedTypeSpecifier.java index 1af08592879..3b0c55c4f66 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTElaboratedTypeSpecifier.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTElaboratedTypeSpecifier.java @@ -90,6 +90,10 @@ public class CPPASTElaboratedTypeSpecifier extends CPPASTBaseDeclSpecifier if (!acceptByAttributeSpecifiers(action)) return false; + if (!visitAlignmentSpecifiers(action)) { + return false; + } + if (name != null) if (!name.accept(action)) return false; if (action.shouldVisitDeclSpecifiers) { switch (action.leave(this)) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTEnumerationSpecifier.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTEnumerationSpecifier.java index 2793df0597e..7279b8c03c0 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTEnumerationSpecifier.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTEnumerationSpecifier.java @@ -135,6 +135,10 @@ public class CPPASTEnumerationSpecifier extends CPPASTBaseDeclSpecifier if (!acceptByAttributeSpecifiers(action)) return false; + if (!visitAlignmentSpecifiers(action)) { + return false; + } + for (IASTEnumerator e : getEnumerators()) { if (!e.accept(action)) return false; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTNamedTypeSpecifier.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTNamedTypeSpecifier.java index bbfc9cd0b12..898ee71ea3f 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTNamedTypeSpecifier.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTNamedTypeSpecifier.java @@ -89,6 +89,11 @@ public class CPPASTNamedTypeSpecifier extends CPPASTBaseDeclSpecifier break; } } + + if (!visitAlignmentSpecifiers(action)) { + return false; + } + if (name != null && !name.accept(action)) return false; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTSimpleDeclSpecifier.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTSimpleDeclSpecifier.java index 608e3dfd649..aa8794d9d77 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTSimpleDeclSpecifier.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTSimpleDeclSpecifier.java @@ -17,10 +17,9 @@ import org.eclipse.cdt.core.dom.ast.IASTExpression; import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.IBasicType.Kind; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTSimpleDeclSpecifier; -import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguityParent; public class CPPASTSimpleDeclSpecifier extends CPPASTBaseDeclSpecifier - implements ICPPASTSimpleDeclSpecifier, IASTAmbiguityParent { + implements ICPPASTSimpleDeclSpecifier { private int type; private boolean isSigned; private boolean isUnsigned; @@ -217,6 +216,10 @@ public class CPPASTSimpleDeclSpecifier extends CPPASTBaseDeclSpecifier if (!acceptByAttributeSpecifiers(action)) return false; + if (!visitAlignmentSpecifiers(action)) { + return false; + } + if (action.shouldVisitDeclSpecifiers) { switch (action.leave(this)) { case ASTVisitor.PROCESS_ABORT: return false; @@ -233,6 +236,8 @@ public class CPPASTSimpleDeclSpecifier extends CPPASTBaseDeclSpecifier other.setPropertyInParent(child.getPropertyInParent()); other.setParent(child.getParent()); fDeclTypeExpression= (IASTExpression) other; + return; } + super.replace(child, other); } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTTypeTransformationSpecifier.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTTypeTransformationSpecifier.java index a7b9e4c3a57..74a9def5ff7 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTTypeTransformationSpecifier.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTTypeTransformationSpecifier.java @@ -60,7 +60,11 @@ public class CPPASTTypeTransformationSpecifier extends CPPASTBaseDeclSpecifier i default: break; } } - + + if (!visitAlignmentSpecifiers(action)) { + return false; + } + if (!fOperand.accept(action)) return false; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPNodeFactory.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPNodeFactory.java index 84b57374c1b..1c70b6c7f9f 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPNodeFactory.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPNodeFactory.java @@ -14,6 +14,7 @@ package org.eclipse.cdt.internal.core.dom.parser.cpp; import org.eclipse.cdt.core.dom.ast.IASTASMDeclaration; +import org.eclipse.cdt.core.dom.ast.IASTAlignmentSpecifier; import org.eclipse.cdt.core.dom.ast.IASTArrayModifier; import org.eclipse.cdt.core.dom.ast.IASTBinaryTypeIdExpression; import org.eclipse.cdt.core.dom.ast.IASTBreakStatement; @@ -143,6 +144,16 @@ public class CPPNodeFactory extends NodeFactory implements ICPPNodeFactory { return DEFAULT_INSTANCE; } + @Override + public IASTAlignmentSpecifier newAlignmentSpecifier(IASTExpression expression) { + return new CPPASTAlignmentSpecifier(expression); + } + + @Override + public IASTAlignmentSpecifier newAlignmentSpecifier(IASTTypeId typeId) { + return new CPPASTAlignmentSpecifier(typeId); + } + @Override public ICPPASTArrayDeclarator newArrayDeclarator(IASTName name) { return new CPPASTArrayDeclarator(name); 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 85a9cf7b274..b0f89a7c55b 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 @@ -27,6 +27,7 @@ import java.util.Map; import org.eclipse.cdt.core.dom.ast.ASTVisitor; import org.eclipse.cdt.core.dom.ast.DOMException; +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; @@ -2897,6 +2898,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { ICPPASTDeclSpecifier result= null; ICPPASTDeclSpecifier altResult= null; List attributes = null; + IASTAlignmentSpecifier[] alignmentSpecifiers = IASTAlignmentSpecifier.EMPTY_ALIGNMENT_SPECIFIER_ARRAY; try { IASTName identifier= null; IASTExpression typeofExpression= null; @@ -3163,6 +3165,10 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { endOffset= calculateEndOffset(result); encounteredTypename= true; break; + + case IToken.t_alignas: + alignmentSpecifiers = ArrayUtil.append(alignmentSpecifiers, alignmentSpecifier()); + break; case IGCCToken.t__attribute__: // if __attribute__ is after the declSpec if (!supportAttributeSpecifiers) @@ -3263,6 +3269,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { result= buildSimpleDeclSpec(storageClass, simpleType, options, isLong, typeofExpression, offset, endOffset); } addAttributeSpecifiers(attributes, result); + result.setAlignmentSpecifiers(ArrayUtil.trim(alignmentSpecifiers)); } catch (BacktrackException e) { if (returnToken != null) { backup(returnToken); @@ -5120,4 +5127,30 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { return setRange(nodeFactory.newReturnStatement(expr), offset, endOffset); } + + @Override + protected IASTExpression expressionWithOptionalTrailingEllipsis() throws BacktrackException, + EndOfFileException { + IASTExpression result = expression(); + if (LT(1) == IToken.tELLIPSIS) { + result = addPackExpansion(result, consume()); + } + return result; + } + + @Override + protected IASTTypeId typeIdWithOptionalTrailingEllipsis(DeclarationOptions option) + throws EndOfFileException, BacktrackException { + ICPPASTTypeId result = typeId(option); + if (LT(1) == IToken.tELLIPSIS) { + addPackExpansion(result, consume()); + } + return result; + } + + @Override + protected IASTAlignmentSpecifier createAmbiguousAlignmentSpecifier(IASTAlignmentSpecifier expression, + IASTAlignmentSpecifier typeId) { + return new CPPASTAmbiguousAlignmentSpecifier(expression, typeId); + } } diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/SemanticHighlightingTest.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/SemanticHighlightingTest.java index a21dbe66ed6..e5774f29d49 100644 --- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/SemanticHighlightingTest.java +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/SemanticHighlightingTest.java @@ -151,7 +151,7 @@ public class SemanticHighlightingTest extends TestCase { BaseTestCase.waitForIndexer(fCProject); fEditor= (CEditor) EditorTestHelper.openInEditor(ResourceTestHelper.findFile("/SHTest/" + sourceFileName), true); fSourceViewer= EditorTestHelper.getSourceViewer(fEditor); - assertTrue(EditorTestHelper.joinReconciler(fSourceViewer, 0, 10000, 100)); + assertTrue(EditorTestHelper.joinReconciler(fSourceViewer, 0, 1000000, 1000)); EditorTestHelper.joinBackgroundActivities(); fIndex = CCorePlugin.getIndexManager().getIndex(fCProject); @@ -434,4 +434,10 @@ public class SemanticHighlightingTest extends TestCase { public void testNPE_458317() throws Exception { makeAssertions(); } + + // struct S { }; //$class + // alignas(S) int x; //$class,globalVariable + public void testHighlightingInsideAlignmentSpecifier_451082() throws Exception { + makeAssertions(); + } }