1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-23 22:52:11 +02:00

Bug 535257: __declspec lost on AST rewrite

Implemented new IASTMSDeclspec nodes.

Change-Id: I2fbc0c2124a8158a457bae0e3cf95aa20ac8ac00
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 15:27:30 +02:00 committed by Thomas Corbat
parent 512b73075f
commit cbea1acd85
9 changed files with 145 additions and 31 deletions

View file

@ -363,3 +363,17 @@ void (__attribute__((__stdcall__))*foo1)(int);
//!Attributed Enumerator //!Attributed Enumerator
//%CPP //%CPP
enum E{ value1 [[attr1]], value2 [[attr2]] = 1}; enum E{ value1 [[attr1]], value2 [[attr2]] = 1};
//!MS declspec attribute on class
//%CPP GNU
__declspec(dllimport) class X
{
} varX;
//!MS declspec attribute on declarator
//%CPP GNU
int __declspec(selectany)* pi2 = 0;
//!MS declspec attribute on simple declaration
//%CPP GNU
__declspec(thread) int tls_i = 1;

View file

@ -17,6 +17,7 @@ Export-Package: org.eclipse.cdt.core,
org.eclipse.cdt.core.dom.ast.gnu, org.eclipse.cdt.core.dom.ast.gnu,
org.eclipse.cdt.core.dom.ast.gnu.c, org.eclipse.cdt.core.dom.ast.gnu.c,
org.eclipse.cdt.core.dom.ast.gnu.cpp, org.eclipse.cdt.core.dom.ast.gnu.cpp,
org.eclipse.cdt.core.dom.ast.ms,
org.eclipse.cdt.core.dom.ast.tag, org.eclipse.cdt.core.dom.ast.tag,
org.eclipse.cdt.core.dom.parser, org.eclipse.cdt.core.dom.parser,
org.eclipse.cdt.core.dom.parser.c, org.eclipse.cdt.core.dom.parser.c,

View file

@ -17,6 +17,7 @@ package org.eclipse.cdt.core.dom.ast;
import org.eclipse.cdt.core.dom.ast.IASTEnumerationSpecifier.IASTEnumerator; import org.eclipse.cdt.core.dom.ast.IASTEnumerationSpecifier.IASTEnumerator;
import org.eclipse.cdt.core.dom.ast.gnu.IGCCASTAttributeList; import org.eclipse.cdt.core.dom.ast.gnu.IGCCASTAttributeList;
import org.eclipse.cdt.core.dom.ast.gnu.IGNUASTCompoundStatementExpression; import org.eclipse.cdt.core.dom.ast.gnu.IGNUASTCompoundStatementExpression;
import org.eclipse.cdt.core.dom.ast.ms.IMSASTDeclspecList;
import org.eclipse.cdt.core.parser.IScanner; import org.eclipse.cdt.core.parser.IScanner;
import org.eclipse.cdt.core.parser.IToken; import org.eclipse.cdt.core.parser.IToken;
import org.eclipse.cdt.internal.core.dom.parser.IASTInactiveCompletionName; import org.eclipse.cdt.internal.core.dom.parser.IASTInactiveCompletionName;
@ -121,6 +122,11 @@ public interface INodeFactory {
*/ */
public IGCCASTAttributeList newGCCAttributeList(); public IGCCASTAttributeList newGCCAttributeList();
/**
* @since 6.5
*/
public IMSASTDeclspecList newMSDeclspecList();
public IGNUASTCompoundStatementExpression newGNUCompoundStatementExpression(IASTCompoundStatement compoundStatement); public IGNUASTCompoundStatementExpression newGNUCompoundStatementExpression(IASTCompoundStatement compoundStatement);
public IASTGotoStatement newGotoStatement(IASTName name); public IASTGotoStatement newGotoStatement(IASTName name);

View file

@ -0,0 +1,28 @@
/*******************************************************************************
* Copyright (c) 2018 Institute for Software, HSR Hochschule fuer Technik
* Rapperswil, University of applied sciences.
* 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:
* Hansruedi Patzen (IFS) - Initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.core.dom.ast.ms;
import org.eclipse.cdt.core.dom.ast.IASTAttributeList;
import org.eclipse.cdt.core.dom.ast.IASTAttributeSpecifier;
import org.eclipse.cdt.core.parser.util.InstanceOfPredicate;
/**
* Represents a Microsoft attribute specifier, introduced by __declspec.
*
* @since 6.5
* @noextend This interface is not intended to be extended by clients.
* @noimplement This interface is not intended to be implemented by clients.
*/
public interface IMSASTDeclspecList extends IASTAttributeList {
public static InstanceOfPredicate<IASTAttributeSpecifier> TYPE_FILTER =
new InstanceOfPredicate<>(IMSASTDeclspecList.class);
}

View file

@ -1572,11 +1572,10 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
final IASTName etorName= identifier(); final IASTName etorName= identifier();
final IASTEnumerator enumerator= nodeFactory.newEnumerator(etorName, null); final IASTEnumerator enumerator= nodeFactory.newEnumerator(etorName, null);
endOffset= calculateEndOffset(etorName);
List<IASTAttributeSpecifier> attributes = anyAttributes(supportAttributeSpecifiers, supportDeclspecSpecifiers); List<IASTAttributeSpecifier> attributes = anyAttributes(supportAttributeSpecifiers, supportDeclspecSpecifiers);
addAttributeSpecifiers(attributes, enumerator); addAttributeSpecifiers(attributes, enumerator);
endOffset = attributesEndOffset(endOffset, attributes); endOffset = attributesEndOffset(calculateEndOffset(etorName), attributes);
setRange(enumerator, problemOffset, endOffset); setRange(enumerator, problemOffset, endOffset);
result.addEnumerator(enumerator); result.addEnumerator(enumerator);
@ -2419,7 +2418,10 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
} }
result.add(__attribute__()); result.add(__attribute__());
} else if (allowDeclspec && (lt == IGCCToken.t__declspec)) { } else if (allowDeclspec && (lt == IGCCToken.t__declspec)) {
__declspec(); if (result == null) {
result = new ArrayList<IASTAttributeSpecifier>();
}
result.add(__declspec());
} else { } else {
break; break;
} }
@ -2445,21 +2447,7 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
consume(); consume();
consume(IToken.tLPAREN); consume(IToken.tLPAREN);
for (;;) { addAttributesOrDeclspecs(result);
final int lt1= LT(1);
if (lt1 == IToken.tRPAREN || lt1 == IToken.tEOC)
break;
// Allow empty attribute
if (lt1 != IToken.tCOMMA) {
result.addAttribute(singleAttribute());
}
// Require comma
if (LT(1) != IToken.tCOMMA)
break;
consume();
}
consumeOrEOC(IToken.tRPAREN); consumeOrEOC(IToken.tRPAREN);
endOffset = consumeOrEOC(IToken.tRPAREN).getEndOffset(); endOffset = consumeOrEOC(IToken.tRPAREN).getEndOffset();
@ -2582,14 +2570,39 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
return token; return token;
} }
protected void __declspec() throws BacktrackException, EndOfFileException { protected void addAttributesOrDeclspecs(IASTAttributeList result) throws EndOfFileException, BacktrackException {
IToken token = LA(1); int lt1 = LT(1);
if (token.getType() == IGCCToken.t__declspec) { do {
// Allow empty attribute
if (lt1 != IToken.tCOMMA) {
result.addAttribute(singleAttribute());
}
// Continue on comma
if (LT(1) != IToken.tCOMMA) {
return;
}
consume(); consume();
lt1 = LT(1);
} while(lt1 != IToken.tRPAREN && lt1 != IToken.tEOC);
}
/**
* Parses an __declspec clause.
* @return the list of __declspec attributes
* @throws BacktrackException
* @throws EndOfFileException
*/
protected IASTAttributeList __declspec() throws BacktrackException, EndOfFileException {
IASTAttributeList result = nodeFactory.newMSDeclspecList();
final int startOffset = consume(IGCCToken.t__declspec).getOffset();
if (LT(1) == IToken.tLPAREN) { if (LT(1) == IToken.tLPAREN) {
skipBrackets(IToken.tLPAREN, IToken.tRPAREN, 0); consume();
} addAttributesOrDeclspecs(result);
final int endOffset = consumeOrEOC(IToken.tRPAREN).getEndOffset();
setRange(result, startOffset, endOffset);
} }
return result;
} }
/** /**

View file

@ -0,0 +1,29 @@
/*******************************************************************************
* Copyright (c) 2018 Institute for Software, HSR Hochschule fuer Technik
* Rapperswil, University of applied sciences.
* 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:
* Hansruedi Patzen (IFS) - Initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser;
import org.eclipse.cdt.core.dom.ast.ms.IMSASTDeclspecList;
/**
* Represents a __declspec list.
*/
public class MSASTDeclspecList extends ASTAttributeList implements IMSASTDeclspecList {
@Override
public MSASTDeclspecList copy(CopyStyle style) {
return copy(new MSASTDeclspecList(), style);
}
@Override
public MSASTDeclspecList copy() {
return copy(CopyStyle.withoutLocations);
}
}

View file

@ -13,6 +13,7 @@ package org.eclipse.cdt.internal.core.dom.parser;
import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.INodeFactory; import org.eclipse.cdt.core.dom.ast.INodeFactory;
import org.eclipse.cdt.core.dom.ast.gnu.IGCCASTAttributeList; import org.eclipse.cdt.core.dom.ast.gnu.IGCCASTAttributeList;
import org.eclipse.cdt.core.dom.ast.ms.IMSASTDeclspecList;
/** /**
* Abstract base class for node factories. * Abstract base class for node factories.
@ -46,4 +47,9 @@ public abstract class NodeFactory implements INodeFactory {
public IGCCASTAttributeList newGCCAttributeList() { public IGCCASTAttributeList newGCCAttributeList() {
return new GCCASTAttributeList(); return new GCCASTAttributeList();
} }
@Override
public IMSASTDeclspecList newMSDeclspecList() {
return new MSASTDeclspecList();
}
} }

View file

@ -2594,6 +2594,8 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
@Override @Override
protected IASTDeclaration declaration(DeclarationOptions option) throws EndOfFileException, BacktrackException { protected IASTDeclaration declaration(DeclarationOptions option) throws EndOfFileException, BacktrackException {
List<IASTAttributeSpecifier> attributes = attributeSpecifierSeq(); List<IASTAttributeSpecifier> attributes = attributeSpecifierSeq();
attributes = CollectionUtils.merge(attributes, __attribute_decl_seq(supportAttributeSpecifiers, supportDeclspecSpecifiers));
switch (LT(1)) { switch (LT(1)) {
case IToken.t_asm: case IToken.t_asm:
return asmDeclaration(); return asmDeclaration();
@ -3466,7 +3468,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
case IGCCToken.t__declspec: // __declspec precedes the identifier case IGCCToken.t__declspec: // __declspec precedes the identifier
if (identifier != null || !supportDeclspecSpecifiers) if (identifier != null || !supportDeclspecSpecifiers)
throwBacktrack(LA(1)); throwBacktrack(LA(1));
__attribute_decl_seq(false, true); attributes = CollectionUtils.merge(attributes, __attribute_decl_seq(false, true));
break; break;
case IGCCToken.t_typeof: case IGCCToken.t_typeof:

View file

@ -13,12 +13,14 @@ package org.eclipse.cdt.internal.core.dom.rewrite.astwriter;
import org.eclipse.cdt.core.dom.ast.IASTAlignmentSpecifier; import org.eclipse.cdt.core.dom.ast.IASTAlignmentSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTAttribute; import org.eclipse.cdt.core.dom.ast.IASTAttribute;
import org.eclipse.cdt.core.dom.ast.IASTAttributeList;
import org.eclipse.cdt.core.dom.ast.IASTAttributeSpecifier; import org.eclipse.cdt.core.dom.ast.IASTAttributeSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTToken; import org.eclipse.cdt.core.dom.ast.IASTToken;
import org.eclipse.cdt.core.dom.ast.IASTTokenList; import org.eclipse.cdt.core.dom.ast.IASTTokenList;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTAttribute; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTAttribute;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTAttributeList; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTAttributeList;
import org.eclipse.cdt.core.dom.ast.gnu.IGCCASTAttributeList; import org.eclipse.cdt.core.dom.ast.gnu.IGCCASTAttributeList;
import org.eclipse.cdt.core.dom.ast.ms.IMSASTDeclspecList;
import org.eclipse.cdt.core.parser.GCCKeywords; import org.eclipse.cdt.core.parser.GCCKeywords;
import org.eclipse.cdt.core.parser.Keywords; import org.eclipse.cdt.core.parser.Keywords;
import org.eclipse.cdt.internal.core.dom.rewrite.commenthandler.NodeCommentMap; import org.eclipse.cdt.internal.core.dom.rewrite.commenthandler.NodeCommentMap;
@ -41,6 +43,8 @@ public class AttributeWriter extends NodeWriter {
writeAttributeSpecifier((ICPPASTAttributeList) attribute); writeAttributeSpecifier((ICPPASTAttributeList) attribute);
} else if (attribute instanceof IGCCASTAttributeList) { } else if (attribute instanceof IGCCASTAttributeList) {
writeGCCAttributeSpecifier((IGCCASTAttributeList) attribute); writeGCCAttributeSpecifier((IGCCASTAttributeList) attribute);
} else if (attribute instanceof IMSASTDeclspecList) {
writeMSDeclspecSpecifier((IMSASTDeclspecList) attribute);
} else if (attribute instanceof IASTAlignmentSpecifier) { } else if (attribute instanceof IASTAlignmentSpecifier) {
writeAlignmentSpecifier((IASTAlignmentSpecifier) attribute); writeAlignmentSpecifier((IASTAlignmentSpecifier) attribute);
} }
@ -61,7 +65,20 @@ public class AttributeWriter extends NodeWriter {
scribe.print(GCCKeywords.__ATTRIBUTE__); scribe.print(GCCKeywords.__ATTRIBUTE__);
scribe.print(OPENING_PARENTHESIS); scribe.print(OPENING_PARENTHESIS);
scribe.print(OPENING_PARENTHESIS); scribe.print(OPENING_PARENTHESIS);
IASTAttribute[] innerAttributes = specifier.getAttributes(); writeAttributeOrDeclspec(specifier);
scribe.print(CLOSING_PARENTHESIS);
scribe.print(CLOSING_PARENTHESIS);
}
private void writeMSDeclspecSpecifier(IMSASTDeclspecList specifier) {
scribe.print(GCCKeywords.__DECLSPEC);
scribe.print(OPENING_PARENTHESIS);
writeAttributeOrDeclspec(specifier);
scribe.print(CLOSING_PARENTHESIS);
}
private void writeAttributeOrDeclspec(IASTAttributeList attributeList) {
IASTAttribute[] innerAttributes = attributeList.getAttributes();
for (int i = 0; i < innerAttributes.length; i++) { for (int i = 0; i < innerAttributes.length; i++) {
IASTAttribute innerAttribute = innerAttributes[i]; IASTAttribute innerAttribute = innerAttributes[i];
if (innerAttribute instanceof ICPPASTAttribute) { if (innerAttribute instanceof ICPPASTAttribute) {
@ -74,8 +91,6 @@ public class AttributeWriter extends NodeWriter {
scribe.printSpace(); scribe.printSpace();
} }
} }
scribe.print(CLOSING_PARENTHESIS);
scribe.print(CLOSING_PARENTHESIS);
} }
private void writeAttributeSpecifier(ICPPASTAttributeList specifier) { private void writeAttributeSpecifier(ICPPASTAttributeList specifier) {