From cbea1acd8539b5b5bc80b4c9f7c6846e11c537ff Mon Sep 17 00:00:00 2001 From: Hansruedi Patzen Date: Tue, 29 May 2018 15:27:30 +0200 Subject: [PATCH] Bug 535257: __declspec lost on AST rewrite Implemented new IASTMSDeclspec nodes. Change-Id: I2fbc0c2124a8158a457bae0e3cf95aa20ac8ac00 Signed-off-by: Hansruedi Patzen Signed-off-by: Thomas Corbat --- .../rewrite/ASTWriterAttributeTestSource.awts | 14 ++++ .../org.eclipse.cdt.core/META-INF/MANIFEST.MF | 1 + .../cdt/core/dom/ast/INodeFactory.java | 6 ++ .../core/dom/ast/ms/IMSASTDeclspecList.java | 28 ++++++++ .../parser/AbstractGNUSourceCodeParser.java | 67 +++++++++++-------- .../core/dom/parser/MSASTDeclspecList.java | 29 ++++++++ .../internal/core/dom/parser/NodeFactory.java | 6 ++ .../dom/parser/cpp/GNUCPPSourceParser.java | 4 +- .../rewrite/astwriter/AttributeWriter.java | 21 +++++- 9 files changed, 145 insertions(+), 31 deletions(-) create mode 100644 core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/ms/IMSASTDeclspecList.java create mode 100644 core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/MSASTDeclspecList.java diff --git a/core/org.eclipse.cdt.core.tests/resources/rewrite/ASTWriterAttributeTestSource.awts b/core/org.eclipse.cdt.core.tests/resources/rewrite/ASTWriterAttributeTestSource.awts index bb6e749a6c7..64a636b5309 100644 --- a/core/org.eclipse.cdt.core.tests/resources/rewrite/ASTWriterAttributeTestSource.awts +++ b/core/org.eclipse.cdt.core.tests/resources/rewrite/ASTWriterAttributeTestSource.awts @@ -363,3 +363,17 @@ void (__attribute__((__stdcall__))*foo1)(int); //!Attributed Enumerator //%CPP 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; \ No newline at end of file diff --git a/core/org.eclipse.cdt.core/META-INF/MANIFEST.MF b/core/org.eclipse.cdt.core/META-INF/MANIFEST.MF index b03657253bd..4c97838c066 100644 --- a/core/org.eclipse.cdt.core/META-INF/MANIFEST.MF +++ b/core/org.eclipse.cdt.core/META-INF/MANIFEST.MF @@ -17,6 +17,7 @@ Export-Package: org.eclipse.cdt.core, org.eclipse.cdt.core.dom.ast.gnu, org.eclipse.cdt.core.dom.ast.gnu.c, 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.parser, org.eclipse.cdt.core.dom.parser.c, 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 b19af914f6a..a9cb2d62c30 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 @@ -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.gnu.IGCCASTAttributeList; 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.IToken; import org.eclipse.cdt.internal.core.dom.parser.IASTInactiveCompletionName; @@ -121,6 +122,11 @@ public interface INodeFactory { */ public IGCCASTAttributeList newGCCAttributeList(); + /** + * @since 6.5 + */ + public IMSASTDeclspecList newMSDeclspecList(); + public IGNUASTCompoundStatementExpression newGNUCompoundStatementExpression(IASTCompoundStatement compoundStatement); public IASTGotoStatement newGotoStatement(IASTName name); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/ms/IMSASTDeclspecList.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/ms/IMSASTDeclspecList.java new file mode 100644 index 00000000000..768a70366f8 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/ms/IMSASTDeclspecList.java @@ -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 TYPE_FILTER = + new InstanceOfPredicate<>(IMSASTDeclspecList.class); +} 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 1b5fa011750..4313e5f5afc 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 @@ -1572,11 +1572,10 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser { final IASTName etorName= identifier(); final IASTEnumerator enumerator= nodeFactory.newEnumerator(etorName, null); - endOffset= calculateEndOffset(etorName); List attributes = anyAttributes(supportAttributeSpecifiers, supportDeclspecSpecifiers); addAttributeSpecifiers(attributes, enumerator); - endOffset = attributesEndOffset(endOffset, attributes); + endOffset = attributesEndOffset(calculateEndOffset(etorName), attributes); setRange(enumerator, problemOffset, endOffset); result.addEnumerator(enumerator); @@ -2419,7 +2418,10 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser { } result.add(__attribute__()); } else if (allowDeclspec && (lt == IGCCToken.t__declspec)) { - __declspec(); + if (result == null) { + result = new ArrayList(); + } + result.add(__declspec()); } else { break; } @@ -2445,21 +2447,7 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser { consume(); consume(IToken.tLPAREN); - for (;;) { - 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(); - } + addAttributesOrDeclspecs(result); consumeOrEOC(IToken.tRPAREN); endOffset = consumeOrEOC(IToken.tRPAREN).getEndOffset(); @@ -2582,15 +2570,40 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser { return token; } - protected void __declspec() throws BacktrackException, EndOfFileException { - IToken token = LA(1); - if (token.getType() == IGCCToken.t__declspec) { - consume(); - if (LT(1) == IToken.tLPAREN) { - skipBrackets(IToken.tLPAREN, IToken.tRPAREN, 0); - } - } - } + protected void addAttributesOrDeclspecs(IASTAttributeList result) throws EndOfFileException, BacktrackException { + int lt1 = LT(1); + do { + // Allow empty attribute + if (lt1 != IToken.tCOMMA) { + result.addAttribute(singleAttribute()); + } + + // Continue on comma + if (LT(1) != IToken.tCOMMA) { + return; + } + 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) { + consume(); + addAttributesOrDeclspecs(result); + final int endOffset = consumeOrEOC(IToken.tRPAREN).getEndOffset(); + setRange(result, startOffset, endOffset); + } + return result; + } /** * Hook method to support (skip) additional declspec modifiers. diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/MSASTDeclspecList.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/MSASTDeclspecList.java new file mode 100644 index 00000000000..ad757f8c0b8 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/MSASTDeclspecList.java @@ -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); + } +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/NodeFactory.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/NodeFactory.java index 688893a15f6..bba32d8b82c 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/NodeFactory.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/NodeFactory.java @@ -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.INodeFactory; import org.eclipse.cdt.core.dom.ast.gnu.IGCCASTAttributeList; +import org.eclipse.cdt.core.dom.ast.ms.IMSASTDeclspecList; /** * Abstract base class for node factories. @@ -46,4 +47,9 @@ public abstract class NodeFactory implements INodeFactory { public IGCCASTAttributeList newGCCAttributeList() { return new GCCASTAttributeList(); } + + @Override + public IMSASTDeclspecList newMSDeclspecList() { + return new MSASTDeclspecList(); + } } 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 77552c119af..c3c193cdea5 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 @@ -2594,6 +2594,8 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { @Override protected IASTDeclaration declaration(DeclarationOptions option) throws EndOfFileException, BacktrackException { List attributes = attributeSpecifierSeq(); + attributes = CollectionUtils.merge(attributes, __attribute_decl_seq(supportAttributeSpecifiers, supportDeclspecSpecifiers)); + switch (LT(1)) { case IToken.t_asm: return asmDeclaration(); @@ -3466,7 +3468,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { case IGCCToken.t__declspec: // __declspec precedes the identifier if (identifier != null || !supportDeclspecSpecifiers) throwBacktrack(LA(1)); - __attribute_decl_seq(false, true); + attributes = CollectionUtils.merge(attributes, __attribute_decl_seq(false, true)); break; case IGCCToken.t_typeof: diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/rewrite/astwriter/AttributeWriter.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/rewrite/astwriter/AttributeWriter.java index 2689dd200f3..1245f27d1d3 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/rewrite/astwriter/AttributeWriter.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/rewrite/astwriter/AttributeWriter.java @@ -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.IASTAttribute; +import org.eclipse.cdt.core.dom.ast.IASTAttributeList; import org.eclipse.cdt.core.dom.ast.IASTAttributeSpecifier; import org.eclipse.cdt.core.dom.ast.IASTToken; 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.ICPPASTAttributeList; 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.Keywords; import org.eclipse.cdt.internal.core.dom.rewrite.commenthandler.NodeCommentMap; @@ -41,6 +43,8 @@ public class AttributeWriter extends NodeWriter { writeAttributeSpecifier((ICPPASTAttributeList) attribute); } else if (attribute instanceof IGCCASTAttributeList) { writeGCCAttributeSpecifier((IGCCASTAttributeList) attribute); + } else if (attribute instanceof IMSASTDeclspecList) { + writeMSDeclspecSpecifier((IMSASTDeclspecList) attribute); } else if (attribute instanceof IASTAlignmentSpecifier) { writeAlignmentSpecifier((IASTAlignmentSpecifier) attribute); } @@ -61,7 +65,20 @@ public class AttributeWriter extends NodeWriter { scribe.print(GCCKeywords.__ATTRIBUTE__); 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++) { IASTAttribute innerAttribute = innerAttributes[i]; if (innerAttribute instanceof ICPPASTAttribute) { @@ -74,8 +91,6 @@ public class AttributeWriter extends NodeWriter { scribe.printSpace(); } } - scribe.print(CLOSING_PARENTHESIS); - scribe.print(CLOSING_PARENTHESIS); } private void writeAttributeSpecifier(ICPPASTAttributeList specifier) {