From a5348a47baa78876f734a361f957ad89bed20485 Mon Sep 17 00:00:00 2001 From: Nathan Ridge Date: Tue, 12 Jan 2016 23:00:45 -0500 Subject: [PATCH] Bug 485713 - Parser support for new type trait intrinsics in GCC 5 Change-Id: I1c0d41c01c921f701c58b2eee342c63de607d1d7 Signed-off-by: Nathan Ridge --- .../core/parser/tests/ast2/AST2CPPTests.java | 13 +++ .../core/parser/tests/ast2/AST2TestBase.java | 5 +- .../tests/IndexGPPBindingResolutionTest.java | 5 +- .../core/testplugin/util/BaseTestCase.java | 7 ++ .../dom/ast/IASTBinaryTypeIdExpression.java | 8 +- .../core/dom/ast/IASTTypeIdExpression.java | 6 + .../ast/cpp/ICPPASTNaryTypeIdExpression.java | 45 ++++++++ .../cdt/core/dom/ast/cpp/ICPPNodeFactory.java | 6 + .../cdt/core/dom/ast/gnu/cpp/GPPLanguage.java | 12 +- .../cpp/GPPScannerExtensionConfiguration.java | 10 ++ .../eclipse/cdt/core/parser/GCCKeywords.java | 6 + .../eclipse/cdt/core/parser/IGCCToken.java | 4 + .../cdt/internal/core/dom/parser/Value.java | 5 + .../cpp/CPPASTNaryTypeIdExpression.java | 109 ++++++++++++++++++ .../core/dom/parser/cpp/CPPNodeFactory.java | 7 ++ .../dom/parser/cpp/GNUCPPSourceParser.java | 56 ++++++++- .../cpp/semantics/EvalBinaryTypeId.java | 1 + .../parser/cpp/semantics/EvalUnaryTypeID.java | 3 + 18 files changed, 292 insertions(+), 16 deletions(-) create mode 100644 core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTNaryTypeIdExpression.java create mode 100644 core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTNaryTypeIdExpression.java 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 8ae09344df7..d2ead7296a2 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 @@ -10582,6 +10582,19 @@ public class AST2CPPTests extends AST2TestBase { ICPPMethod foo = bh.assertNonProblem("foo"); assertTrue(foo.isFinal()); } + + // struct S {}; + // bool b1 = __is_trivially_copyable(S); + // bool b2 = __is_trivially_assignable(S, S&); + // bool b3 = __is_trivially_constructible(S, int, char*); + // // Test that __is_trivially_constructible can take parameter packs + // template + // struct U { + // static const bool value = __is_trivially_constructible(S, Args...); + // }; + public void testParsingOfGcc5TypeTraitIntrinsics_485713() throws Exception { + parseAndCheckBindings(getAboveComment(), CPP, true /* use GNU extensions */); + } // struct S1 {}; // S1 s1; diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TestBase.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TestBase.java index 538ca6f1de8..ebb747e91d6 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TestBase.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TestBase.java @@ -66,7 +66,6 @@ import org.eclipse.cdt.core.dom.ast.IVariable; import org.eclipse.cdt.core.dom.ast.c.ICASTTypeIdInitializerExpression; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTLinkageSpecification; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamespaceDefinition; -import org.eclipse.cdt.core.dom.ast.gnu.cpp.GPPLanguage; import org.eclipse.cdt.core.dom.parser.IScannerExtensionConfiguration; import org.eclipse.cdt.core.dom.parser.c.ANSICParserExtensionConfiguration; import org.eclipse.cdt.core.dom.parser.c.GCCParserExtensionConfiguration; @@ -147,8 +146,8 @@ public class AST2TestBase extends BaseTestCase { private static Map getGnuMap() { Map map= new HashMap<>(); - map.put("__GNUC__", Integer.toString(GPPLanguage.GNU_LATEST_VERSION_MAJOR)); - map.put("__GNUC_MINOR__", Integer.toString(GPPLanguage.GNU_LATEST_VERSION_MINOR)); + map.put("__GNUC__", Integer.toString(GCC_MAJOR_VERSION_FOR_TESTS)); + map.put("__GNUC_MINOR__", Integer.toString(GCC_MINOR_VERSION_FOR_TESTS)); map.put("__SIZEOF_SHORT__", "2"); map.put("__SIZEOF_INT__", "4"); map.put("__SIZEOF_LONG__", "8"); diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexGPPBindingResolutionTest.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexGPPBindingResolutionTest.java index 621bcdf0726..af838a28bc8 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexGPPBindingResolutionTest.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexGPPBindingResolutionTest.java @@ -12,7 +12,6 @@ package org.eclipse.cdt.internal.index.tests; import org.eclipse.cdt.core.dom.ast.IField; import org.eclipse.cdt.core.dom.ast.ITypedef; -import org.eclipse.cdt.core.dom.ast.gnu.cpp.GPPLanguage; import org.eclipse.cdt.core.testplugin.TestScannerProvider; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPBasicType; @@ -24,8 +23,8 @@ import junit.framework.TestSuite; public abstract class IndexGPPBindingResolutionTest extends IndexBindingResolutionTestBase { private static void gnuSetUp() { - TestScannerProvider.sDefinedSymbols.put("__GNUC__", Integer.toString(GPPLanguage.GNU_LATEST_VERSION_MAJOR)); - TestScannerProvider.sDefinedSymbols.put("__GNUC_MINOR__", Integer.toString(GPPLanguage.GNU_LATEST_VERSION_MINOR)); + TestScannerProvider.sDefinedSymbols.put("__GNUC__", Integer.toString(GCC_MAJOR_VERSION_FOR_TESTS)); + TestScannerProvider.sDefinedSymbols.put("__GNUC_MINOR__", Integer.toString(GCC_MINOR_VERSION_FOR_TESTS)); } private static void gnuTearDown() { diff --git a/core/org.eclipse.cdt.core.tests/suite/org/eclipse/cdt/core/testplugin/util/BaseTestCase.java b/core/org.eclipse.cdt.core.tests/suite/org/eclipse/cdt/core/testplugin/util/BaseTestCase.java index 67dbfb78fe0..a2560d556e7 100644 --- a/core/org.eclipse.cdt.core.tests/suite/org/eclipse/cdt/core/testplugin/util/BaseTestCase.java +++ b/core/org.eclipse.cdt.core.tests/suite/org/eclipse/cdt/core/testplugin/util/BaseTestCase.java @@ -64,6 +64,13 @@ public class BaseTestCase extends TestCase { Integer.parseInt(System.getProperty(INDEXER_TIMEOUT_PROPERTY, DEFAULT_INDEXER_TIMEOUT_SEC)); protected static final int INDEXER_TIMEOUT_MILLISEC= INDEXER_TIMEOUT_SEC * 1000; + /** + * The GCC version to emulate when running tests. + * We emulate the latest version whose extensions we support. + */ + protected static final int GCC_MAJOR_VERSION_FOR_TESTS = 5; + protected static final int GCC_MINOR_VERSION_FOR_TESTS = 1; + private boolean fExpectFailure; private int fBugNumber; private int fExpectedLoggedNonOK; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTBinaryTypeIdExpression.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTBinaryTypeIdExpression.java index 69d296aee47..a1939148cab 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTBinaryTypeIdExpression.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTBinaryTypeIdExpression.java @@ -20,9 +20,13 @@ public interface IASTBinaryTypeIdExpression extends IASTExpression { public static final ASTNodeProperty OPERAND2 = new ASTNodeProperty("IASTBinaryTypeIdExpression.OPERAND2 [IASTTypeId]"); //$NON-NLS-1$ /** - * Built-in type trait of g++. + * Built-in type traits of g++. */ - public static enum Operator {__is_base_of} + public static enum Operator { + __is_base_of, + /** @since 5.12 */ + __is_trivially_assignable + } /** * Returns the operator for the expression. diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTTypeIdExpression.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTTypeIdExpression.java index 4e8bc6fc0ec..c88c276d73c 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTTypeIdExpression.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTTypeIdExpression.java @@ -158,6 +158,12 @@ public interface IASTTypeIdExpression extends IASTExpression { */ public static final int op_is_final= 23; + /** + * Built-in type trait of g++. + * @since 5.12 + */ + public static final int op_is_trivially_copyable = 24; + /** * @deprecated constants should be declared here, to avoid using the same constant in different * interfaces. diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTNaryTypeIdExpression.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTNaryTypeIdExpression.java new file mode 100644 index 00000000000..9feca44b2de --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTNaryTypeIdExpression.java @@ -0,0 +1,45 @@ +/******************************************************************************* + * Copyright (c) 2016 Nathan Ridge. + * 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: + * Nathan Ridge - Initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.core.dom.ast.cpp; + +import org.eclipse.cdt.core.dom.ast.ASTNodeProperty; + +/** + * A type-id expression with any number of arguments. + * Example: __is_trivially_constructible(MyClass, int, float) + * + * @noextend This interface is not intended to be extended by clients. + * @noimplement This interface is not intended to be implemented by clients. + * @since 5.12 + */ +public interface ICPPASTNaryTypeIdExpression extends ICPPASTExpression { + public static final ASTNodeProperty OPERAND = new ASTNodeProperty("ICPPASTNaryTypeIdExpression.OPERAND [IASTTypeId]"); //$NON-NLS-1$ + + public static enum Operator { + __is_trivially_constructible + } + + /** + * Returns the operator of the expression. + */ + public Operator getOperator(); + + /** + * Returns the operands of the expression. + */ + public ICPPASTTypeId[] getOperands(); + + @Override + public ICPPASTNaryTypeIdExpression copy(); + + @Override + public ICPPASTNaryTypeIdExpression copy(CopyStyle style); +} 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 e408e3f39ed..156b8e25cfb 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 @@ -261,6 +261,12 @@ public interface ICPPNodeFactory extends INodeFactory { public ICPPASTNamespaceAlias newNamespaceAlias(IASTName alias, IASTName qualifiedName); public ICPPASTNamespaceDefinition newNamespaceDefinition(IASTName name); + + /** + * @since 5.12 + */ + public ICPPASTNaryTypeIdExpression newNaryTypeIdExpression(ICPPASTNaryTypeIdExpression.Operator operator, + ICPPASTTypeId[] operands); /** * @deprecated Replaced by {@link #newNewExpression(IASTInitializerClause[], IASTInitializer, IASTTypeId)} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/gnu/cpp/GPPLanguage.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/gnu/cpp/GPPLanguage.java index 5b82121de6e..6f73214b5f4 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/gnu/cpp/GPPLanguage.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/gnu/cpp/GPPLanguage.java @@ -41,9 +41,17 @@ public class GPPLanguage extends AbstractCLikeLanguage { protected static final GPPParserExtensionConfiguration CPP_GNU_PARSER_EXTENSION= GPPParserExtensionConfiguration.getInstance(); public static final String ID = CCorePlugin.PLUGIN_ID + ".g++"; //$NON-NLS-1$ - /** @since 5.6 */ + /** + * @since 5.6 + * @deprecated This was meant for internal use only. + */ + @Deprecated public static final int GNU_LATEST_VERSION_MAJOR = 4; - /** @since 5.6 */ + /** + * @since 5.6 + * @deprecated This was meant for internal use only. + */ + @Deprecated public static final int GNU_LATEST_VERSION_MINOR = 7; private static final GPPLanguage DEFAULT_INSTANCE = new GPPLanguage(); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/parser/cpp/GPPScannerExtensionConfiguration.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/parser/cpp/GPPScannerExtensionConfiguration.java index e4c9baf100c..fa6b36febfc 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/parser/cpp/GPPScannerExtensionConfiguration.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/parser/cpp/GPPScannerExtensionConfiguration.java @@ -32,11 +32,13 @@ public class GPPScannerExtensionConfiguration extends GNUScannerExtensionConfigu private static final int VERSION_4_3 = version(4, 3); private static final int VERSION_4_6 = version(4, 6); private static final int VERSION_4_7 = version(4, 7); + private static final int VERSION_5_0 = version(5, 0); private static GPPScannerExtensionConfiguration CONFIG= new GPPScannerExtensionConfiguration(); private static GPPScannerExtensionConfiguration CONFIG_4_2= new GPPScannerExtensionConfiguration(VERSION_4_2); private static GPPScannerExtensionConfiguration CONFIG_4_3= new GPPScannerExtensionConfiguration(VERSION_4_3); private static GPPScannerExtensionConfiguration CONFIG_4_6= new GPPScannerExtensionConfiguration(VERSION_4_6); private static GPPScannerExtensionConfiguration CONFIG_4_7= new GPPScannerExtensionConfiguration(VERSION_4_7); + private static GPPScannerExtensionConfiguration CONFIG_5_0= new GPPScannerExtensionConfiguration(VERSION_5_0); public static GPPScannerExtensionConfiguration getInstance() { return CONFIG; @@ -52,6 +54,9 @@ public class GPPScannerExtensionConfiguration extends GNUScannerExtensionConfigu int major= Integer.valueOf(definedSymbols.get("__GNUC__")); //$NON-NLS-1$ int minor= Integer.valueOf(definedSymbols.get("__GNUC_MINOR__")); //$NON-NLS-1$ int version= version(major, minor); + if (version >= VERSION_5_0) { + return CONFIG_5_0; + } if (version >= VERSION_4_7) { return CONFIG_4_7; } @@ -120,6 +125,11 @@ public class GPPScannerExtensionConfiguration extends GNUScannerExtensionConfigu addKeyword(GCCKeywords.cp__is_final, IGCCToken.tTT_is_final); addKeyword(GCCKeywords.cp__underlying_type, IGCCToken.tTT_underlying_type); } + if (version >= VERSION_5_0) { + addKeyword(GCCKeywords.cp__is_trivially_copyable, IGCCToken.tTT_is_trivially_copyable); + addKeyword(GCCKeywords.cp__is_trivially_constructible, IGCCToken.tTT_is_trivially_constructible); + addKeyword(GCCKeywords.cp__is_trivially_assignable, IGCCToken.tTT_is_trivially_assignable); + } } @Override diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/GCCKeywords.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/GCCKeywords.java index b120258240f..2c9b35318ed 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/GCCKeywords.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/GCCKeywords.java @@ -102,4 +102,10 @@ public class GCCKeywords { cp_decimal32= _DECIMAL32.toCharArray(), cp_decimal64= _DECIMAL64.toCharArray(), cp_decimal128= _DECIMAL128.toCharArray(); + + /** @since 5.12 */ + public static final char[] + cp__is_trivially_copyable= "__is_trivially_copyable".toCharArray(), + cp__is_trivially_constructible= "__is_trivially_constructible".toCharArray(), + cp__is_trivially_assignable= "__is_trivially_assignable".toCharArray(); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/IGCCToken.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/IGCCToken.java index 673baa3e5fd..a5fa7752181 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/IGCCToken.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/IGCCToken.java @@ -54,4 +54,8 @@ public interface IGCCToken extends IToken { /** @since 5.10 */ int t_decimal32= FIRST_RESERVED_IGCCToken + 29; /** @since 5.10 */ int t_decimal64= FIRST_RESERVED_IGCCToken + 30; /** @since 5.10 */ int t_decimal128= FIRST_RESERVED_IGCCToken + 31; + + /** @since 5.12 */ int tTT_is_trivially_copyable= FIRST_RESERVED_IGCCToken + 32; + /** @since 5.12 */ int tTT_is_trivially_constructible= FIRST_RESERVED_IGCCToken + 33; + /** @since 5.12 */ int tTT_is_trivially_assignable= FIRST_RESERVED_IGCCToken + 34; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/Value.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/Value.java index 81daab7eef4..ea6b05e58e8 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/Value.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/Value.java @@ -29,6 +29,7 @@ import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_is_pod; import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_is_polymorphic; import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_is_standard_layout; import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_is_trivial; +import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_is_trivially_copyable; import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_is_union; import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_sizeof; import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_typeid; @@ -350,6 +351,8 @@ public class Value implements IValue { case op_is_trivial: return type instanceof ICPPClassType && TypeTraits.isTrivial((ICPPClassType) type, point) ? 1 : 0; + case op_is_trivially_copyable: + break; // TODO: Implement case op_is_union: return type instanceof ICompositeType && ((ICompositeType) type).getKey() == ICompositeType.k_union ? 1 : 0; @@ -371,6 +374,8 @@ public class Value implements IValue { return 1; } return 0; + case __is_trivially_assignable: + return VALUE_CANNOT_BE_DETERMINED; // TODO: Implement. } return VALUE_CANNOT_BE_DETERMINED; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTNaryTypeIdExpression.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTNaryTypeIdExpression.java new file mode 100644 index 00000000000..bf71ff981ae --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTNaryTypeIdExpression.java @@ -0,0 +1,109 @@ +/******************************************************************************* + * Copyright (c) 2016 Nathan Ridge. + * 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: + * Nathan Ridge - 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.IASTImplicitDestructorName; +import org.eclipse.cdt.core.dom.ast.IType; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNaryTypeIdExpression; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTypeId; +import org.eclipse.cdt.internal.core.dom.parser.ASTNode; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalFixed; + +public class CPPASTNaryTypeIdExpression extends ASTNode implements ICPPASTNaryTypeIdExpression { + private Operator fOperator; + private ICPPASTTypeId[] fOperands; + + public CPPASTNaryTypeIdExpression(Operator operator, ICPPASTTypeId[] operands) { + fOperator = operator; + fOperands = operands; + for (ICPPASTTypeId operand : fOperands) { + operand.setParent(this); + operand.setPropertyInParent(OPERAND); + } + } + + @Override + public ICPPASTNaryTypeIdExpression copy() { + return copy(CopyStyle.withoutLocations); + } + + @Override + public ICPPASTNaryTypeIdExpression copy(CopyStyle style) { + ICPPASTTypeId[] operands = new ICPPASTTypeId[fOperands.length]; + for (int i = 0; i < fOperands.length; ++i) { + operands[i] = fOperands[i].copy(style); + } + CPPASTNaryTypeIdExpression copy = new CPPASTNaryTypeIdExpression(fOperator, operands); + return copy(copy, style); + } + + @Override + public Operator getOperator() { + return fOperator; + } + + @Override + public ICPPASTTypeId[] getOperands() { + return fOperands; + } + + @Override + public boolean accept(ASTVisitor action) { + if (action.shouldVisitExpressions) { + switch (action.visit(this)) { + case ASTVisitor.PROCESS_ABORT: return false; + case ASTVisitor.PROCESS_SKIP: return true; + default: break; + } + } + + for (ICPPASTTypeId operand : fOperands) { + if (!operand.accept(action)) { + return false; + } + } + + if (action.shouldVisitExpressions && action.leave(this) == ASTVisitor.PROCESS_ABORT) { + return false; + } + + return true; + } + + @Override + public ICPPEvaluation getEvaluation() { + // TODO: Implement. This will need a new evaluation type, EvalNaryTypeId. + return EvalFixed.INCOMPLETE; + } + + @Override + public IType getExpressionType() { + // TODO: When getEvaluation() is implemented, delegate to getEvaluation().getType(). + return CPPBasicType.BOOLEAN; + } + + @Override + public boolean isLValue() { + return false; + } + + @Override + public ValueCategory getValueCategory() { + return ValueCategory.PRVALUE; + } + + @Override + public IASTImplicitDestructorName[] getImplicitDestructorNames() { + // N-ary type-id expressions don't call destructors. + return IASTImplicitDestructorName.EMPTY_NAME_ARRAY; + } +} 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 ed8d623858e..3d564d76ee9 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 @@ -99,6 +99,8 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNameSpecifier; 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; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNaryTypeIdExpression; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNaryTypeIdExpression.Operator; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNewExpression; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTOperatorName; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTPackExpansionExpression; @@ -570,6 +572,11 @@ public class CPPNodeFactory extends NodeFactory implements ICPPNodeFactory { return new CPPASTNamespaceDefinition(name); } + @Override + public ICPPASTNaryTypeIdExpression newNaryTypeIdExpression(Operator operator, ICPPASTTypeId[] operands) { + return new CPPASTNaryTypeIdExpression(operator, operands); + } + @Override @Deprecated public ICPPASTNewExpression newNewExpression(IASTExpression placement, IASTExpression initializer, IASTTypeId typeId) { 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 bf86c426abf..d57affd9aaf 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 @@ -118,6 +118,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNameSpecifier; 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; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNaryTypeIdExpression; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNewExpression; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTOperatorName; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTPackExpandable; @@ -1488,6 +1489,9 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { case IGCCToken.tTT_is_standard_layout: case IGCCToken.tTT_is_trivial: case IGCCToken.tTT_is_union: + case IGCCToken.tTT_is_trivially_copyable: + case IGCCToken.tTT_is_trivially_constructible: + case IGCCToken.tTT_is_trivially_assignable: return parseTypeTrait(); default: @@ -1498,22 +1502,39 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { private IASTExpression parseTypeTrait() throws EndOfFileException, BacktrackException { IToken first= consume(); final boolean isBinary= isBinaryTrait(first); + final boolean isNary = isNaryTrait(first); consume(IToken.tLPAREN); - IASTTypeId typeId= typeId(DeclarationOptions.TYPEID); - IASTTypeId secondTypeId= null; + ICPPASTTypeId[] operands = new ICPPASTTypeId[isBinary ? 2 : 1]; + operands[0] = typeId(DeclarationOptions.TYPEID); if (isBinary) { consumeOrEOC(IToken.tCOMMA); if (LT(1) != IToken.tEOC) { - secondTypeId= typeId(DeclarationOptions.TYPEID); + operands[1] = typeId(DeclarationOptions.TYPEID); } + } else if (isNary) { + while (LTcatchEOF(1) == IToken.tCOMMA) { + consume(); + if (LT(1) != IToken.tEOC) { + ICPPASTTypeId operand = typeId(DeclarationOptions.TYPEID); + // n-ary type traits can contain pack expansions + if (LT(1) == IToken.tELLIPSIS) { + addPackExpansion(operand, consume()); + } + operands = ArrayUtil.append(operands, operand); + } + } + operands = ArrayUtil.removeNulls(operands); } int endOffset= consumeOrEOC(IToken.tRPAREN).getEndOffset(); IASTExpression result; - if (isBinary) { - result= getNodeFactory().newBinaryTypeIdExpression(getBinaryTypeTraitOperator(first), typeId, secondTypeId); + if (isNary) { + result= getNodeFactory().newNaryTypeIdExpression(getNaryTypeTraitOperator(first), operands); + } else if (isBinary) { + result= getNodeFactory().newBinaryTypeIdExpression(getBinaryTypeTraitOperator(first), operands[0], + operands[1]); } else { - result= getNodeFactory().newTypeIdExpression(getUnaryTypeTraitOperator(first), typeId); + result= getNodeFactory().newTypeIdExpression(getUnaryTypeTraitOperator(first), operands[0]); } return setRange(result, first.getOffset(), endOffset); } @@ -1521,6 +1542,15 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { private boolean isBinaryTrait(IToken first) { switch (first.getType()) { case IGCCToken.tTT_is_base_of: + case IGCCToken.tTT_is_trivially_assignable: + return true; + } + return false; + } + + private boolean isNaryTrait(IToken operatorToken) { + switch (operatorToken.getType()) { + case IGCCToken.tTT_is_trivially_constructible: return true; } return false; @@ -1530,11 +1560,23 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { switch (first.getType()) { case IGCCToken.tTT_is_base_of: return IASTBinaryTypeIdExpression.Operator.__is_base_of; + case IGCCToken.tTT_is_trivially_assignable: + return IASTBinaryTypeIdExpression.Operator.__is_trivially_assignable; } assert false; return null; } + + private ICPPASTNaryTypeIdExpression.Operator getNaryTypeTraitOperator(IToken operatorToken) { + switch (operatorToken.getType()) { + case IGCCToken.tTT_is_trivially_constructible: + return ICPPASTNaryTypeIdExpression.Operator.__is_trivially_constructible; + } + + assert false; + return null; + } private int getUnaryTypeTraitOperator(IToken first) { switch (first.getType()) { @@ -1576,6 +1618,8 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { return IASTTypeIdExpression.op_is_trivial; case IGCCToken.tTT_is_union: return IASTTypeIdExpression.op_is_union; + case IGCCToken.tTT_is_trivially_copyable: + return IASTTypeIdExpression.op_is_trivially_copyable; } assert false; return 0; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalBinaryTypeId.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalBinaryTypeId.java index c6a657de323..f20f9a425cf 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalBinaryTypeId.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalBinaryTypeId.java @@ -76,6 +76,7 @@ public class EvalBinaryTypeId extends CPPDependentEvaluation { public IType getType(IASTNode point) { switch (fOperator) { case __is_base_of: + case __is_trivially_assignable: return CPPBasicType.BOOLEAN; } return ProblemType.UNKNOWN_FOR_EXPRESSION; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalUnaryTypeID.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalUnaryTypeID.java index d2737c5ae7d..31acd14ef2f 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalUnaryTypeID.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalUnaryTypeID.java @@ -31,6 +31,7 @@ import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_is_pod; import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_is_polymorphic; import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_is_standard_layout; import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_is_trivial; +import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_is_trivially_copyable; import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_is_union; import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_sizeof; import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_sizeofParameterPack; @@ -116,6 +117,7 @@ public class EvalUnaryTypeID extends CPPDependentEvaluation { case op_is_polymorphic: case op_is_standard_layout: case op_is_trivial: + case op_is_trivially_copyable: case op_is_union: return CPPTemplates.isDependentType(fOrigType); @@ -163,6 +165,7 @@ public class EvalUnaryTypeID extends CPPDependentEvaluation { case op_is_polymorphic: case op_is_standard_layout: case op_is_trivial: + case op_is_trivially_copyable: case op_is_union: return CPPBasicType.BOOLEAN; case op_typeof: