1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-22 14:12:10 +02:00

Bug 535269: Allow attributes on enumerators

C++17 feature.
Implementation and tests.

Change-Id: Idafe4ca41058e8387aeae9a27f028677c62245c0
Signed-off-by: Hansruedi Patzen <hansruedi.patzen@hsr.ch>
Signed-off-by: Thomas Corbat <tcorbat@hsr.ch>
This commit is contained in:
Hansruedi Patzen 2018-05-29 14:09:53 +02:00 committed by Thomas Corbat
parent 66df5ff428
commit c0d54f4f19
6 changed files with 40 additions and 23 deletions

View file

@ -15,8 +15,6 @@ package org.eclipse.cdt.core.parser.tests.ast2;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import junit.framework.TestSuite;
import org.eclipse.cdt.core.dom.ast.ASTVisitor; import org.eclipse.cdt.core.dom.ast.ASTVisitor;
import org.eclipse.cdt.core.dom.ast.IASTArrayModifier; import org.eclipse.cdt.core.dom.ast.IASTArrayModifier;
import org.eclipse.cdt.core.dom.ast.IASTAttribute; import org.eclipse.cdt.core.dom.ast.IASTAttribute;
@ -26,6 +24,7 @@ import org.eclipse.cdt.core.dom.ast.IASTCaseStatement;
import org.eclipse.cdt.core.dom.ast.IASTCompoundStatement; import org.eclipse.cdt.core.dom.ast.IASTCompoundStatement;
import org.eclipse.cdt.core.dom.ast.IASTDeclarator; import org.eclipse.cdt.core.dom.ast.IASTDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTDefaultStatement; import org.eclipse.cdt.core.dom.ast.IASTDefaultStatement;
import org.eclipse.cdt.core.dom.ast.IASTEnumerationSpecifier.IASTEnumerator;
import org.eclipse.cdt.core.dom.ast.IASTExpressionStatement; import org.eclipse.cdt.core.dom.ast.IASTExpressionStatement;
import org.eclipse.cdt.core.dom.ast.IASTFunctionDeclarator; import org.eclipse.cdt.core.dom.ast.IASTFunctionDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTLabelStatement; import org.eclipse.cdt.core.dom.ast.IASTLabelStatement;
@ -55,6 +54,8 @@ import org.eclipse.cdt.core.parser.ParserLanguage;
import org.eclipse.cdt.internal.core.dom.parser.ASTNode; import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
import org.eclipse.cdt.internal.core.dom.parser.ASTTokenList; import org.eclipse.cdt.internal.core.dom.parser.ASTTokenList;
import junit.framework.TestSuite;
public class AST2CPPAttributeTests extends AST2TestBase { public class AST2CPPAttributeTests extends AST2TestBase {
public AST2CPPAttributeTests() { public AST2CPPAttributeTests() {
@ -519,4 +520,13 @@ public class AST2CPPAttributeTests extends AST2TestBase {
IASTTranslationUnit tu = parseAndCheckBindings(getAboveComment(), ParserLanguage.CPP, true); IASTTranslationUnit tu = parseAndCheckBindings(getAboveComment(), ParserLanguage.CPP, true);
checkAttributeRelations(getAttributeSpecifiers(tu), ICPPASTFunctionDeclarator.class); checkAttributeRelations(getAttributeSpecifiers(tu), ICPPASTFunctionDeclarator.class);
} }
// enum E {
// value1 [[attr1]], value2 [[attr2]] = 1
// };
public void testAttributedEnumerator_Bug535269() throws Exception {
IASTTranslationUnit tu = parseAndCheckBindings(getAboveComment(), ParserLanguage.CPP, true);
checkAttributeRelations(getAttributeSpecifiers(tu), IASTEnumerator.class, IASTEnumerator.class);
}
} }

View file

@ -359,3 +359,7 @@ char*__attribute__((aligned(8)))* f;
//%CPP GNU //%CPP GNU
void __attribute__((noreturn)) foo(); void __attribute__((noreturn)) foo();
void (__attribute__((__stdcall__))*foo1)(int); void (__attribute__((__stdcall__))*foo1)(int);
//!Attributed Enumerator
//%CPP
enum E{ value1 [[attr1]], value2 [[attr2]] = 1};

View file

@ -89,6 +89,7 @@ public abstract class ASTEnumerator extends ASTAttributeOwner implements IASTEnu
} }
} }
if (name != null && !name.accept(action)) return false; if (name != null && !name.accept(action)) return false;
if (!acceptByAttributeSpecifiers(action)) return false;
if (value != null && !value.accept(action)) return false; if (value != null && !value.accept(action)) return false;
if (action.shouldVisitEnumerators) { if (action.shouldVisitEnumerators) {
switch (action.leave(this)) { switch (action.leave(this)) {

View file

@ -1574,7 +1574,7 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
final IASTEnumerator enumerator= nodeFactory.newEnumerator(etorName, null); final IASTEnumerator enumerator= nodeFactory.newEnumerator(etorName, null);
endOffset= calculateEndOffset(etorName); endOffset= calculateEndOffset(etorName);
List<IASTAttributeSpecifier> attributes = __attribute_decl_seq(supportAttributeSpecifiers, supportDeclspecSpecifiers); List<IASTAttributeSpecifier> attributes = anyAttributes(supportAttributeSpecifiers, supportDeclspecSpecifiers);
addAttributeSpecifiers(attributes, enumerator); addAttributeSpecifiers(attributes, enumerator);
endOffset = attributesEndOffset(endOffset, attributes); endOffset = attributesEndOffset(endOffset, attributes);
setRange(enumerator, problemOffset, endOffset); setRange(enumerator, problemOffset, endOffset);
@ -2395,6 +2395,10 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
} }
} }
protected List<IASTAttributeSpecifier> anyAttributes(boolean allowAttrib, boolean allowDeclspec) throws BacktrackException, EndOfFileException {
return __attribute_decl_seq(allowAttrib, allowDeclspec);
}
/** /**
* Accepts a sequence of __attribute__ or __declspec. * Accepts a sequence of __attribute__ or __declspec.
* *

View file

@ -2753,6 +2753,14 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
return null; return null;
} }
@Override
protected List<IASTAttributeSpecifier> anyAttributes(boolean allowAttrib, boolean allowDeclspec)
throws BacktrackException, EndOfFileException {
List<IASTAttributeSpecifier> attributes = super.anyAttributes(allowAttrib, allowDeclspec);
attributes = CollectionUtils.merge(attributes, attributeSpecifierSeq());
return attributes;
}
protected List<IASTAttributeSpecifier> attributeSpecifierSeq() throws EndOfFileException, protected List<IASTAttributeSpecifier> attributeSpecifierSeq() throws EndOfFileException,
BacktrackException { BacktrackException {
List<IASTAttributeSpecifier> specifiers = null; List<IASTAttributeSpecifier> specifiers = null;
@ -3630,8 +3638,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
consume(); consume();
} }
// if __attribute__ or __declspec occurs after struct/union/class and before the identifier // if __attribute__ or __declspec occurs after struct/union/class and before the identifier
attributes = __attribute_decl_seq(supportAttributeSpecifiers, supportDeclspecSpecifiers); attributes = anyAttributes(supportAttributeSpecifiers, supportDeclspecSpecifiers);
attributes = CollectionUtils.merge(attributes, attributeSpecifierSeq());
if (isScoped || LT(1) == IToken.tIDENTIFIER) { if (isScoped || LT(1) == IToken.tIDENTIFIER) {
// A qualified-name can appear here if an enumeration declared at class scope is // A qualified-name can appear here if an enumeration declared at class scope is
@ -3709,8 +3716,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
final int offset= consume().getOffset(); final int offset= consume().getOffset();
// if __attribute__ or __declspec occurs after struct/union/class and before the identifier // if __attribute__ or __declspec occurs after struct/union/class and before the identifier
List<IASTAttributeSpecifier> attributes = __attribute_decl_seq(supportAttributeSpecifiers, supportDeclspecSpecifiers); List<IASTAttributeSpecifier> attributes = anyAttributes(supportAttributeSpecifiers, supportDeclspecSpecifiers);
attributes = CollectionUtils.merge(attributes, attributeSpecifierSeq());
IASTName name = qualifiedName(); IASTName name = qualifiedName();
ICPPASTElaboratedTypeSpecifier elaboratedTypeSpecifier = getNodeFactory().newElaboratedTypeSpecifier(eck, name); ICPPASTElaboratedTypeSpecifier elaboratedTypeSpecifier = getNodeFactory().newElaboratedTypeSpecifier(eck, name);
@ -4838,8 +4844,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
} }
// if __attribute__ or __declspec occurs after struct/union/class and before the identifier // if __attribute__ or __declspec occurs after struct/union/class and before the identifier
List<IASTAttributeSpecifier> attributes = __attribute_decl_seq(supportAttributeSpecifiers, supportDeclspecSpecifiers); List<IASTAttributeSpecifier> attributes = anyAttributes(supportAttributeSpecifiers, supportDeclspecSpecifiers);
attributes = CollectionUtils.merge(attributes, attributeSpecifierSeq());
// class name // class name
IASTName name = null; IASTName name = null;

View file

@ -15,7 +15,6 @@ package org.eclipse.cdt.internal.core.dom.rewrite.astwriter;
import java.util.EnumSet; import java.util.EnumSet;
import org.eclipse.cdt.core.dom.ast.IASTAttributeOwner;
import org.eclipse.cdt.core.dom.ast.IASTCompositeTypeSpecifier; import org.eclipse.cdt.core.dom.ast.IASTCompositeTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier; import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTDeclaration; import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
@ -171,9 +170,7 @@ public class DeclSpecWriter extends NodeWriter {
private void writeElaboratedTypeSec(IASTElaboratedTypeSpecifier elabType) { private void writeElaboratedTypeSec(IASTElaboratedTypeSpecifier elabType) {
scribe.printStringSpace(getElabTypeString(elabType.getKind())); scribe.printStringSpace(getElabTypeString(elabType.getKind()));
if (elabType instanceof IASTAttributeOwner) { writeAttributes(elabType, EnumSet.of(SpaceLocation.AFTER));
writeAttributes((IASTAttributeOwner) elabType, EnumSet.of(SpaceLocation.AFTER));
}
elabType.getName().accept(visitor); elabType.getName().accept(visitor);
} }
@ -228,9 +225,7 @@ public class DeclSpecWriter extends NodeWriter {
private void writeEnumSpec(IASTEnumerationSpecifier enumSpec) { private void writeEnumSpec(IASTEnumerationSpecifier enumSpec) {
scribe.printStringSpace(Keywords.ENUM); scribe.printStringSpace(Keywords.ENUM);
if (enumSpec instanceof IASTAttributeOwner) { writeAttributes(enumSpec, EnumSet.of(SpaceLocation.AFTER));
writeAttributes((IASTAttributeOwner) enumSpec, EnumSet.of(SpaceLocation.AFTER));
}
enumSpec.getName().accept(visitor); enumSpec.getName().accept(visitor);
scribe.print('{'); scribe.print('{');
scribe.printSpace(); scribe.printSpace();
@ -246,7 +241,7 @@ public class DeclSpecWriter extends NodeWriter {
private void writeEnumerator(IASTEnumerator enumerator) { private void writeEnumerator(IASTEnumerator enumerator) {
enumerator.getName().accept(visitor); enumerator.getName().accept(visitor);
writeAttributes(enumerator, EnumSet.of(SpaceLocation.BEFORE));
IASTExpression value = enumerator.getValue(); IASTExpression value = enumerator.getValue();
if (value != null) { if (value != null) {
scribe.print(EQUALS); scribe.print(EQUALS);
@ -257,9 +252,7 @@ public class DeclSpecWriter extends NodeWriter {
private void writeCompositeTypeSpecifier(IASTCompositeTypeSpecifier compDeclSpec) { private void writeCompositeTypeSpecifier(IASTCompositeTypeSpecifier compDeclSpec) {
boolean hasTrailingComments = hasTrailingComments(compDeclSpec.getName()); boolean hasTrailingComments = hasTrailingComments(compDeclSpec.getName());
scribe.printStringSpace(getCPPCompositeTypeString(compDeclSpec.getKey())); scribe.printStringSpace(getCPPCompositeTypeString(compDeclSpec.getKey()));
if (compDeclSpec instanceof IASTAttributeOwner) { writeAttributes(compDeclSpec, EnumSet.of(SpaceLocation.AFTER));
writeAttributes((IASTAttributeOwner) compDeclSpec, EnumSet.of(SpaceLocation.AFTER));
}
compDeclSpec.getName().accept(visitor); compDeclSpec.getName().accept(visitor);
if (compDeclSpec instanceof ICPPASTCompositeTypeSpecifier) { if (compDeclSpec instanceof ICPPASTCompositeTypeSpecifier) {
ICPPASTCompositeTypeSpecifier cppComp = (ICPPASTCompositeTypeSpecifier) compDeclSpec; ICPPASTCompositeTypeSpecifier cppComp = (ICPPASTCompositeTypeSpecifier) compDeclSpec;