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:
parent
66df5ff428
commit
c0d54f4f19
6 changed files with 40 additions and 23 deletions
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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};
|
||||||
|
|
|
@ -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)) {
|
||||||
|
|
|
@ -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.
|
||||||
*
|
*
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Add table
Reference in a new issue