diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java index e74b28ab3ed..cfdd619ff64 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java @@ -7733,5 +7733,22 @@ public class AST2CPPTests extends AST2BaseTest { parseAndCheckBindings(code, ParserLanguage.CPP); } + // const unsigned int EIGHT= 8; + // static_assert(sizeof(long) >= EIGHT, "no 64-bit support"); + // namespace ns { + // static_assert(sizeof(long) >= 4, "no 32-bit support"); + // } + // template class basic_string { + // static_assert(T::value, "bla"); + // }; + // void do_something() { + // struct VMPage { + // }; + // static_assert(sizeof(VMPage) == 1, "bla"); + // } + public void testStaticAssertions_294730() throws Exception { + final String code= getAboveComment(); + parseAndCheckBindings(code, ParserLanguage.CPP); + } } diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CModelBuilder2.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CModelBuilder2.java index 379ee5f15d4..6756dda3e51 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CModelBuilder2.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CModelBuilder2.java @@ -57,6 +57,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTLinkageSpecification; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamespaceAlias; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamespaceDefinition; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTStaticAssertDeclaration; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateDeclaration; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateId; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateSpecialization; @@ -332,6 +333,8 @@ public class CModelBuilder2 implements IContributedModelBuilder { // TODO [cmodel] asm declaration? } else if (declaration instanceof IASTProblemDeclaration) { // TODO [cmodel] problem declaration? + } else if (declaration instanceof ICPPASTStaticAssertDeclaration) { + // ignore } else { assert false : "TODO: " + declaration.getClass().getName(); //$NON-NLS-1$ } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTStaticAssertDeclaration.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTStaticAssertDeclaration.java new file mode 100644 index 00000000000..a7e44084b91 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTStaticAssertDeclaration.java @@ -0,0 +1,39 @@ +/******************************************************************************* + * Copyright (c) 2009 Wind River Systems, Inc. and others. + * 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: + * Markus Schorn - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.core.dom.ast.cpp; + +import org.eclipse.cdt.core.dom.ast.ASTNodeProperty; +import org.eclipse.cdt.core.dom.ast.IASTDeclaration; +import org.eclipse.cdt.core.dom.ast.IASTExpression; + +/** + * Models static assertions: static_assert(false, "message"); + * + * @since 5.2 + * @noextend This interface is not intended to be extended by clients. + * @noimplement This interface is not intended to be implemented by clients. + */ +public interface ICPPASTStaticAssertDeclaration extends IASTDeclaration { + public static final ASTNodeProperty CONDITION = new ASTNodeProperty( + "ICPPASTStaticAssertDeclaration.CONDITION [IASTExpression]"); //$NON-NLS-1$ + public static final ASTNodeProperty MESSAGE = new ASTNodeProperty( + "ICPPASTStaticAssertDeclaration.MESSAGE [ICPPASTLiteralExpression]"); //$NON-NLS-1$ + + /** + * Returns the condition of the assertion + */ + IASTExpression getCondition(); + + /** + * Returns the message of the assertion, or potentially null when using content assist. + */ + ICPPASTLiteralExpression getMessage(); +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPNodeFactory.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPNodeFactory.java index 9e9b1213aa7..694ec43a854 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPNodeFactory.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPNodeFactory.java @@ -7,6 +7,7 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.core.dom.ast.cpp; @@ -175,5 +176,11 @@ public interface ICPPNodeFactory extends INodeFactory { public ICPPASTArraySubscriptExpression newArraySubscriptExpression(IASTExpression arrayExpr, IASTExpression subscript); public ICPPASTFunctionCallExpression newFunctionCallExpression(IASTExpression idExpr, IASTExpression argList); + + /** + * Creates a new static assertion declaration with the given condition and message. + * @since 5.2 + */ + public ICPPASTStaticAssertDeclaration newStaticAssertion(IASTExpression condition, ICPPASTLiteralExpression message); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/IToken.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/IToken.java index 5c90dcad839..1add0589502 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/IToken.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/IToken.java @@ -30,11 +30,6 @@ public interface IToken { public void setNext(IToken t); public void setType(int i); - /** - * @noreference This method is not intended to be referenced by clients. - */ - @Deprecated - public boolean isOperator(); // Token types int FIRST_RESERVED_PREPROCESSOR= -200; @@ -99,6 +94,7 @@ public interface IToken { * @since 5.2 */ int tGT_in_SHIFTR= 53; + /** @deprecated use {@link #tAND} */ @Deprecated int t_and = 54; /** @deprecated use {@link #tAMPERASSIGN} */ @Deprecated int t_and_eq = 55; int t_asm = 56; @@ -153,6 +149,7 @@ public interface IToken { int t_short = 104; int t_sizeof = 105; int t_static = 106; + /** @since 5.2 */ int t_static_assert = 5010; int t_static_cast = 107; int t_signed = 108; int t_struct = 109; @@ -210,4 +207,9 @@ public interface IToken { int LAST_RESERVED_IExtensionToken = 299; + /** + * @noreference This method is not intended to be referenced by clients. + */ + @Deprecated + public boolean isOperator(); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/Keywords.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/Keywords.java index cb2c126c0ad..7411c46bf0f 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/Keywords.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/Keywords.java @@ -82,6 +82,8 @@ public class Keywords { public static final String SIGNED = "signed"; //$NON-NLS-1$ public static final String SIZEOF = "sizeof"; //$NON-NLS-1$ public static final String STATIC = "static"; //$NON-NLS-1$ + /** @since 5.2 */ + public static final String STATIC_ASSERT = "static_assert"; //$NON-NLS-1$ public static final String STATIC_CAST = "static_cast"; //$NON-NLS-1$ public static final String STRUCT = "struct"; //$NON-NLS-1$ public static final String SWITCH = "switch"; //$NON-NLS-1$ @@ -162,6 +164,8 @@ public class Keywords { public static final char[] cSIGNED = "signed".toCharArray(); //$NON-NLS-1$ public static final char[] cSIZEOF = "sizeof".toCharArray(); //$NON-NLS-1$ public static final char[] cSTATIC = "static".toCharArray(); //$NON-NLS-1$ + /** @since 5.2 */ + public static final char[] cSTATIC_ASSERT = "static_assert".toCharArray(); //$NON-NLS-1$ public static final char[] cSTATIC_CAST = "static_cast".toCharArray(); //$NON-NLS-1$ public static final char[] cSTRUCT = "struct".toCharArray(); //$NON-NLS-1$ public static final char[] cSWITCH = "switch".toCharArray(); //$NON-NLS-1$ @@ -339,6 +343,7 @@ public class Keywords { cppkeywords.put(Keywords.cPROTECTED, IToken.t_protected); cppkeywords.put(Keywords.cPUBLIC, IToken.t_public); cppkeywords.put(Keywords.cREINTERPRET_CAST, IToken.t_reinterpret_cast); + cppkeywords.put(Keywords.cSTATIC_ASSERT, IToken.t_static_assert); cppkeywords.put(Keywords.cSTATIC_CAST, IToken.t_static_cast); cppkeywords.put(Keywords.cTEMPLATE, IToken.t_template); cppkeywords.put(Keywords.cTHIS, IToken.t_this); 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 ab17c905e69..0211c0fe93c 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 @@ -509,12 +509,14 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser { return node.getOffset() + node.getLength(); } - protected final void setRange(IASTNode n, IASTNode from) { + protected final T setRange(T n, IASTNode from) { ((ASTNode) n).setOffsetAndLength((ASTNode) from); + return n; } - protected final void setRange(IASTNode n, int offset, int endOffset) { + protected final T setRange(T n, int offset, int endOffset) { ((ASTNode) n).setOffsetAndLength(offset, endOffset-offset); + return n; } protected final void adjustLength(IASTNode n, IASTNode endNode) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTStaticAssertionDeclaration.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTStaticAssertionDeclaration.java new file mode 100644 index 00000000000..a49bacda4ef --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTStaticAssertionDeclaration.java @@ -0,0 +1,82 @@ +/******************************************************************************* + * Copyright (c) 2009 Wind River Systems, Inc. and others. + * 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: + * Markus Schorn - 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.IASTExpression; +import org.eclipse.cdt.core.dom.ast.IASTNode; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTLiteralExpression; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTStaticAssertDeclaration; +import org.eclipse.cdt.internal.core.dom.parser.ASTNode; +import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguityParent; + +public class CPPASTStaticAssertionDeclaration extends ASTNode implements ICPPASTStaticAssertDeclaration, IASTAmbiguityParent { + + private IASTExpression fCondition; + private final ICPPASTLiteralExpression fMessage; + + public CPPASTStaticAssertionDeclaration(IASTExpression condition, ICPPASTLiteralExpression message) { + fCondition= condition; + fMessage= message; + if (condition != null) { + condition.setParent(this); + condition.setPropertyInParent(CONDITION); + } + if (message != null) { + message.setParent(this); + message.setPropertyInParent(MESSAGE); + } + } + + public IASTExpression getCondition() { + return fCondition; + } + + public ICPPASTLiteralExpression getMessage() { + return fMessage; + } + + + public CPPASTStaticAssertionDeclaration copy() { + final IASTExpression condCopy = fCondition == null ? null : fCondition.copy(); + final ICPPASTLiteralExpression msgCopy = fMessage == null ? null : fMessage.copy(); + CPPASTStaticAssertionDeclaration copy = new CPPASTStaticAssertionDeclaration(condCopy, msgCopy); + copy.setOffsetAndLength(this); + return copy; + } + + @Override + public boolean accept( ASTVisitor action ){ + if (action.shouldVisitDeclarations) { + switch (action.visit(this)) { + case ASTVisitor.PROCESS_ABORT : return false; + case ASTVisitor.PROCESS_SKIP : return true; + } + } + + if (fCondition != null && !fCondition.accept(action)) + return false; + if (fMessage != null && !fMessage.accept(action)) + return false; + + if (action.shouldVisitDeclarations && action.leave(this) == ASTVisitor.PROCESS_ABORT) + return false; + return true; + } + + public void replace(IASTNode child, IASTNode other) { + if (child == fCondition) { + fCondition= (IASTExpression) other; + other.setParent(child.getParent()); + other.setPropertyInParent(child.getPropertyInParent()); + } + } +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPNodeFactory.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPNodeFactory.java index 367c2467411..71990c1ecab 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPNodeFactory.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPNodeFactory.java @@ -83,6 +83,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTReferenceOperator; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTSimpleDeclSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTSimpleTypeConstructorExpression; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTSimpleTypeTemplateParameter; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTStaticAssertDeclaration; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTSwitchStatement; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateDeclaration; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateId; @@ -513,4 +514,8 @@ public class CPPNodeFactory extends NodeFactory implements ICPPNodeFactory { return new CPPASTProblemTypeId(problem); } + public ICPPASTStaticAssertDeclaration newStaticAssertion(IASTExpression condition, + ICPPASTLiteralExpression message) { + return new CPPASTStaticAssertionDeclaration(condition, message); + } } 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 65245d5acf4..ff50c2c4dab 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 @@ -77,6 +77,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDefinition; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionWithTryBlock; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTIfStatement; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTLinkageSpecification; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTLiteralExpression; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamedTypeSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamespaceAlias; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamespaceDefinition; @@ -88,6 +89,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTReferenceOperator; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTSimpleDeclSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTSimpleTypeConstructorExpression; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTSimpleTypeTemplateParameter; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTStaticAssertDeclaration; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTSwitchStatement; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateDeclaration; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateId; @@ -1293,10 +1295,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { case IToken.tLSTRING: case IToken.tUTF16STRING: case IToken.tUTF32STRING: - t = consume(); - literalExpression = nodeFactory.newLiteralExpression(IASTLiteralExpression.lk_string_literal, t.getImage()); - ((ASTNode) literalExpression).setOffsetAndLength(t.getOffset(), t.getEndOffset() - t.getOffset()); - return literalExpression; + return stringLiteral(); case IToken.tCHAR: case IToken.tLCHAR: case IToken.tUTF16CHAR: @@ -1357,6 +1356,22 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { } + private ICPPASTLiteralExpression stringLiteral() throws EndOfFileException, BacktrackException { + switch(LT(1)) { + case IToken.tSTRING: + case IToken.tLSTRING: + case IToken.tUTF16STRING: + case IToken.tUTF32STRING: + break; + default: + throwBacktrack(LA(1)); + } + IToken t= consume(); + ICPPASTLiteralExpression r= nodeFactory.newLiteralExpression(IASTLiteralExpression.lk_string_literal, t.getImage()); + setRange(r, t.getOffset(), t.getEndOffset()); + return r; + } + protected IASTExpression specialCastExpression(int kind) throws EndOfFileException, BacktrackException { final int offset = LA(1).getOffset(); final int optype= consume().getType(); @@ -1458,6 +1473,25 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { } + /** + * static_assert-declaration: + static_assert ( constant-expression , string-literal ) ; + */ + private ICPPASTStaticAssertDeclaration staticAssertDeclaration() throws EndOfFileException, BacktrackException { + int offset= consume(IToken.t_static_assert).getOffset(); + consume(IToken.tLPAREN); + IASTExpression e= constantExpression(); + int endOffset= calculateEndOffset(e); + ICPPASTLiteralExpression lit= null; + if (LT(1) != IToken.tEOC) { + consume(IToken.tCOMMA); + lit= stringLiteral(); + consume(IToken.tRPAREN); + endOffset= consume(IToken.tSEMI).getEndOffset(); + } + ICPPASTStaticAssertDeclaration assertion = nodeFactory.newStaticAssertion(e, lit); + return setRange(assertion, offset, endOffset); + } /** * Implements Linkage specification in the ANSI C++ grammar. @@ -1690,6 +1724,8 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { return namespaceDefinitionOrAlias(); case IToken.t_using: return usingClause(); + case IToken.t_static_assert: + return staticAssertDeclaration(); case IToken.t_export: case IToken.t_template: return templateDeclaration(option); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/token/KeywordSets.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/token/KeywordSets.java index d04aa2f57c1..09843f630f4 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/token/KeywordSets.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/token/KeywordSets.java @@ -151,6 +151,7 @@ public class KeywordSets { DECLARATION_CPP.add( Keywords.USING ); DECLARATION_CPP.add( Keywords.NAMESPACE ); DECLARATION_CPP.add( Keywords.EXPORT ); + DECLARATION_CPP.add( Keywords.STATIC_ASSERT ); } private static final Set DECLARATION_C; @@ -453,6 +454,7 @@ public class KeywordSets { ALL_CPP.add( Keywords.SIGNED); ALL_CPP.add( Keywords.SIZEOF); ALL_CPP.add( Keywords.STATIC); + ALL_CPP.add( Keywords.STATIC_ASSERT); ALL_CPP.add( Keywords.STATIC_CAST); ALL_CPP.add( Keywords.STRUCT); ALL_CPP.add( Keywords.SWITCH); @@ -534,6 +536,7 @@ public class KeywordSets { KEYWORDS_CPP.add( Keywords.RETURN ); KEYWORDS_CPP.add( Keywords.SIZEOF ); KEYWORDS_CPP.add( Keywords.STATIC ); + KEYWORDS_CPP.add( Keywords.STATIC_ASSERT ); KEYWORDS_CPP.add( Keywords.STATIC_CAST ); KEYWORDS_CPP.add( Keywords.STRUCT ); KEYWORDS_CPP.add( Keywords.SWITCH );