1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-19 06:55:23 +02:00

Bug 451082 - Parser support for alignment-specifiers

Change-Id: Ib4321fc036970c1819cb4e66611d1ddbda607e28
Signed-off-by: Nathan Ridge <zeratul976@hotmail.com>
This commit is contained in:
Nathan Ridge 2015-03-13 02:51:33 -04:00 committed by Sergey Prigogin
parent a7b52f139b
commit a4859c33e3
28 changed files with 676 additions and 18 deletions

View file

@ -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 <typename... T>
// struct U {
// alignas(S) int x;
// alignas(T...) char y;
// };
// template <int... N>
// struct Y {
// alignas(N...) char x;
// };
public void testAlignas_451082() throws Exception {
parseAndCheckBindings();
}
}

View file

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

View file

@ -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(<type-id>)
* alignas(<expression>)
* C:
* _Alignas(<type-id>)
* _Alignas(<expression>)
* @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(<expression>)' or '_Alignas(<expression>)',
* returns the enclosed expression. Otherwise, returns null.
*/
IASTExpression getExpression();
/**
* If the specifier is of the form 'alignas(<type-id>)' or '_Alignas(<type-id>)',
* returns the enclosed type-id. Otherwise, returns null.
*/
IASTTypeId getTypeId();
@Override
public IASTAlignmentSpecifier copy();
@Override
public IASTAlignmentSpecifier copy(CopyStyle style);
}

View file

@ -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.
*/

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -89,6 +89,11 @@ public class CPPASTNamedTypeSpecifier extends CPPASTBaseDeclSpecifier
break;
}
}
if (!visitAlignmentSpecifiers(action)) {
return false;
}
if (name != null && !name.accept(action))
return false;

View file

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

View file

@ -60,7 +60,11 @@ public class CPPASTTypeTransformationSpecifier extends CPPASTBaseDeclSpecifier i
default: break;
}
}
if (!visitAlignmentSpecifiers(action)) {
return false;
}
if (!fOperand.accept(action))
return false;

View file

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

View file

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

View file

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