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 3a243584187..029f08a5b3d 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 @@ -10358,4 +10358,42 @@ public class AST2CPPTests extends AST2TestBase { public void testDecltypeInNameQualifier_bug380751() throws Exception { parseAndCheckBindings(); } + + // template + // struct underlying_type { + // typedef __underlying_type(T) type; + // }; + // + // enum class e_fixed_short1 : short; + // enum class e_fixed_short2 : short { a = 1, b = 2 }; + // + // enum class e_scoped { a = 1, b = 2 }; + // + // enum e_unsigned { a1 = 1, b1 = 2 }; + // enum e_int { a2 = -1, b2 = 1 }; + // enum e_ulong { a3 = 5000000000, b3 }; + // enum e_long { a4 = -5000000000, b4 = 5000000000 }; + // + // typedef underlying_type::type short1_type; + // typedef underlying_type::type short2_type; + // + // typedef underlying_type::type scoped_type; + // + // typedef underlying_type::type unsigned_type; + // typedef underlying_type::type int_type; + // typedef underlying_type::type ulong_type; + // typedef underlying_type::type loong_type; + public void testUnderlyingTypeBuiltin_bug411196() throws Exception { + BindingAssertionHelper helper = getAssertionHelper(); + + assertSameType((ITypedef) helper.assertNonProblem("short1_type"), CPPVisitor.SHORT_TYPE); + assertSameType((ITypedef) helper.assertNonProblem("short2_type"), CPPVisitor.SHORT_TYPE); + + assertSameType((ITypedef) helper.assertNonProblem("scoped_type"), CPPVisitor.INT_TYPE); + + assertSameType((ITypedef) helper.assertNonProblem("unsigned_type"), CPPVisitor.UNSIGNED_INT); + assertSameType((ITypedef) helper.assertNonProblem("int_type"), CPPVisitor.INT_TYPE); + assertSameType((ITypedef) helper.assertNonProblem("ulong_type"), CPPVisitor.UNSIGNED_LONG); + assertSameType((ITypedef) helper.assertNonProblem("loong_type"), CPPVisitor.LONG_TYPE); + } } 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 d8fdbd28f47..9d88bb2a088 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 @@ -62,6 +62,7 @@ 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; @@ -114,8 +115,8 @@ public class AST2TestBase extends BaseTestCase { private static Map getGnuMap() { Map map= new HashMap(); - map.put("__GNUC__", "4"); - map.put("__GNUC_MINOR__", "7"); + map.put("__GNUC__", Integer.toString(GPPLanguage.GNU_LATEST_VERSION_MAJOR)); + map.put("__GNUC_MINOR__", Integer.toString(GPPLanguage.GNU_LATEST_VERSION_MINOR)); 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/IndexBindingResolutionTestBase.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexBindingResolutionTestBase.java index b006fd6dc29..f8015f55c0a 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexBindingResolutionTestBase.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexBindingResolutionTestBase.java @@ -767,4 +767,10 @@ public abstract class IndexBindingResolutionTestBase extends BaseTestCase { fail("Artificially failing - see IndexBindingResolutionTestBase.fakeFailForReferenced()"); } } + + protected static void assertSameType(IType first, IType second){ + assertNotNull(first); + assertNotNull(second); + assertTrue("Expected types to be the same, but first was: '" + first.toString() + "' and second was: '" + second + "'", first.isSameType(second)); + } } \ No newline at end of file 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 new file mode 100644 index 00000000000..a642cdfb82b --- /dev/null +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexGPPBindingResolutionTest.java @@ -0,0 +1,120 @@ +/******************************************************************************* + * Copyright (c) 2013 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 implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.index.tests; + +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.semantics.CPPVisitor; + +import junit.framework.TestSuite; + +/** + * For testing resolution of bindings in C++ code with GNU extensions. + */ +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)); + } + + private static void gnuTearDown() { + TestScannerProvider.clear(); + } + + public class GPPReferencedProject extends ReferencedProject { + public GPPReferencedProject() { + super(true /* cpp */); + } + + @Override + public void setUp() throws Exception { + gnuSetUp(); + super.setUp(); + } + + @Override + public void tearDown() throws Exception { + super.tearDown(); + gnuTearDown(); + } + } + + public class GPPSinglePDOMTestStrategy extends SinglePDOMTestStrategy { + public GPPSinglePDOMTestStrategy() { + super(true /* cpp */); + } + + @Override + public void setUp() throws Exception { + gnuSetUp(); + super.setUp(); + } + + @Override + public void tearDown() throws Exception { + super.tearDown(); + gnuTearDown(); + } + } + + public static class SingleProject extends IndexGPPBindingResolutionTest { + public SingleProject() { setStrategy(new GPPSinglePDOMTestStrategy()); } + public static TestSuite suite() { return suite(SingleProject.class); } + } + + public static class ProjectWithDepProj extends IndexGPPBindingResolutionTest { + public ProjectWithDepProj() { setStrategy(new GPPReferencedProject()); } + public static TestSuite suite() { return suite(ProjectWithDepProj.class); } + } + + public static void addTests(TestSuite suite) { + suite.addTest(SingleProject.suite()); + suite.addTest(ProjectWithDepProj.suite()); + } + + // template + // struct underlying_type { + // typedef __underlying_type(T) type; + // }; + // + // enum class e_fixed_short1 : short; + // enum class e_fixed_short2 : short { a = 1, b = 2 }; + // + // enum class e_scoped { a = 1, b = 2 }; + // + // enum e_unsigned { a1 = 1, b1 = 2 }; + // enum e_int { a2 = -1, b2 = 1 }; + // enum e_ulong { a3 = 5000000000, b3 }; + // enum e_long { a4 = -5000000000, b4 = 5000000000 }; + + // typedef underlying_type::type short1_type; + // typedef underlying_type::type short2_type; + // + // typedef underlying_type::type scoped_type; + // + // typedef underlying_type::type unsigned_type; + // typedef underlying_type::type int_type; + // typedef underlying_type::type ulong_type; + // typedef underlying_type::type loong_type; + public void testUnderlyingTypeBuiltin_bug411196() throws Exception { + assertSameType((ITypedef) getBindingFromASTName("short1_type", 0), CPPVisitor.SHORT_TYPE); + assertSameType((ITypedef) getBindingFromASTName("short2_type", 0), CPPVisitor.SHORT_TYPE); + + assertSameType((ITypedef) getBindingFromASTName("scoped_type", 0), CPPVisitor.INT_TYPE); + + assertSameType((ITypedef) getBindingFromASTName("unsigned_type", 0), CPPVisitor.UNSIGNED_INT); + assertSameType((ITypedef) getBindingFromASTName("int_type", 0), CPPVisitor.INT_TYPE); + assertSameType((ITypedef) getBindingFromASTName("ulong_type", 0), CPPVisitor.UNSIGNED_LONG); + assertSameType((ITypedef) getBindingFromASTName("loong_type", 0), CPPVisitor.LONG_TYPE); + } +} diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexTests.java index 9ad58945e1c..4bba2249631 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexTests.java @@ -34,6 +34,7 @@ public class IndexTests extends TestSuite { IndexCPPBindingResolutionBugs.addTests(suite); IndexCPPBindingResolutionTest.addTests(suite); + IndexGPPBindingResolutionTest.addTests(suite); IndexCPPTemplateResolutionTest.addTests(suite); IndexCBindingResolutionBugs.addTests(suite); IndexCBindingResolutionTest.addTests(suite); diff --git a/core/org.eclipse.cdt.core.tests/suite/org/eclipse/cdt/core/testplugin/TestScannerInfo.java b/core/org.eclipse.cdt.core.tests/suite/org/eclipse/cdt/core/testplugin/TestScannerInfo.java index 6235fbc4b19..5732bf1ecb3 100644 --- a/core/org.eclipse.cdt.core.tests/suite/org/eclipse/cdt/core/testplugin/TestScannerInfo.java +++ b/core/org.eclipse.cdt.core.tests/suite/org/eclipse/cdt/core/testplugin/TestScannerInfo.java @@ -21,16 +21,19 @@ public class TestScannerInfo extends ExtendedScannerInfo { private String[] fIncludes; private String[] fIncludeFiles; private String[] fMacroFiles; + private Map fDefinedSymbols; - public TestScannerInfo(String[] includes, String[] macroFiles, String[] includeFiles) { + public TestScannerInfo(String[] includes, String[] macroFiles, String[] includeFiles, + Map definedSymbols) { fIncludes= includes; fIncludeFiles= includeFiles; fMacroFiles= macroFiles; + fDefinedSymbols= definedSymbols; } @Override public Map getDefinedSymbols() { - return Collections.emptyMap(); + return fDefinedSymbols == null ? Collections.emptyMap() : fDefinedSymbols; } @Override diff --git a/core/org.eclipse.cdt.core.tests/suite/org/eclipse/cdt/core/testplugin/TestScannerProvider.java b/core/org.eclipse.cdt.core.tests/suite/org/eclipse/cdt/core/testplugin/TestScannerProvider.java index 6fa5de23567..bc8f98a75da 100644 --- a/core/org.eclipse.cdt.core.tests/suite/org/eclipse/cdt/core/testplugin/TestScannerProvider.java +++ b/core/org.eclipse.cdt.core.tests/suite/org/eclipse/cdt/core/testplugin/TestScannerProvider.java @@ -11,6 +11,9 @@ *******************************************************************************/ package org.eclipse.cdt.core.testplugin; +import java.util.HashMap; +import java.util.Map; + import org.eclipse.cdt.core.AbstractCExtension; import org.eclipse.cdt.core.parser.IScannerInfo; import org.eclipse.cdt.core.parser.IScannerInfoChangeListener; @@ -21,15 +24,17 @@ public class TestScannerProvider extends AbstractCExtension implements IScannerI public static String[] sIncludes; public static String[] sIncludeFiles; public static String[] sMacroFiles; + public static Map sDefinedSymbols = new HashMap(); public final static String SCANNER_ID = CTestPlugin.PLUGIN_ID + ".TestScanner"; public static void clear() { sIncludes= sIncludeFiles= sMacroFiles= null; + sDefinedSymbols.clear(); } @Override public IScannerInfo getScannerInformation(IResource resource) { - return new TestScannerInfo(sIncludes, sMacroFiles, sIncludeFiles); + return new TestScannerInfo(sIncludes, sMacroFiles, sIncludeFiles, sDefinedSymbols); } @Override diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/ISemanticProblem.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/ISemanticProblem.java index ec7d620f069..9cb4d08d6df 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/ISemanticProblem.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/ISemanticProblem.java @@ -41,6 +41,10 @@ public interface ISemanticProblem { int TYPE_CANNOT_DEDUCE_AUTO_TYPE = 10003; int TYPE_UNKNOWN_FOR_EXPRESSION = 10004; int TYPE_NOT_PERSISTED = 10005; + /** + * @since 5.6 + */ + int TYPE_ENUMERATION_EXPECTED = 10006; /** * Returns the ID of the problem. diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTTypeTransformationSpecifier.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTTypeTransformationSpecifier.java new file mode 100644 index 00000000000..e3679383322 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTTypeTransformationSpecifier.java @@ -0,0 +1,41 @@ +/******************************************************************************* + * Copyright (c) 2013 IBM Corporation 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: + * Nathan Ridge - 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.cpp.ICPPUnaryTypeTransformation.Operator; + +/** + * A decl-specifier that represents the application of an intrinsic type + * transformation operator like __underlying_type(T). Intrinsic operators + * of this form take a type as input, and evaluate to a type. + * + * @noextend This interface is not intended to be extended by clients. + * @noimplement This interface is not intended to be implemented by clients. + * @since 5.6 + */ +public interface ICPPASTTypeTransformationSpecifier extends ICPPASTDeclSpecifier { + /** + * OPERAND represents the relationship between an ICPPASTTypeTransformationSpecifier and + * its nested IASTTypeId. + */ + public static final ASTNodeProperty OPERAND = new ASTNodeProperty("ICPPASTTypeTransformationSpecifier.OPERAND - type operand for ICPPASTTypeTransformationSpecifier"); //$NON-NLS-1$ + + /** + * Returns the type transformation operator being applied. + */ + Operator getOperator(); + + /** + * Returns the type-id to which the type transformation operator is being applied. + */ + ICPPASTTypeId getOperand(); +} 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 49db5b0839c..769e7aad5ea 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 @@ -28,6 +28,7 @@ import org.eclipse.cdt.core.dom.ast.IASTStatement; import org.eclipse.cdt.core.dom.ast.IASTTypeId; import org.eclipse.cdt.core.dom.ast.INodeFactory; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPUnaryTypeTransformation.Operator; import org.eclipse.cdt.core.parser.IScanner; /** @@ -345,6 +346,11 @@ public interface ICPPNodeFactory extends INodeFactory { @Deprecated public ICPPASTTypenameExpression newTypenameExpression(IASTName qualifiedName, IASTExpression expr, boolean isTemplate); + /** + * @since 5.6 + */ + public ICPPASTTypeTransformationSpecifier newTypeTransformationSpecifier(Operator kind, ICPPASTTypeId typeId); + @Override public ICPPASTUnaryExpression newUnaryExpression(int operator, IASTExpression operand); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPUnaryTypeTransformation.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPUnaryTypeTransformation.java new file mode 100644 index 00000000000..72804ec63b1 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPUnaryTypeTransformation.java @@ -0,0 +1,45 @@ +/******************************************************************************* + * Copyright (c) 2013 IBM Corporation 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: + * Nathan Ridge - Initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.core.dom.ast.cpp; + +import org.eclipse.cdt.core.dom.ast.IType; + +/** + * A type used to represent the result of applying an unary + * type transformation operator like __underlying_type(T). + * + * This representation is only used when T is dependent (and thus + * we cannot evaluate the type transformation yet). If T is not + * dependent, we simply use the result of evaluating the type + * transformation. + * + * @noextend This interface is not intended to be extended by clients. + * @noimplement This interface is not intended to be implemented by clients. + * @since 5.6 + */ +public interface ICPPUnaryTypeTransformation extends IType { + /** + * Identifies the type transformation operator being applied. + */ + public enum Operator { + underlying_type // the integer type underlying an enumeration type + } + + /** + * Returns the type transformation operator being applied. + */ + Operator getOperator(); + + /** + * Returns the type to which the type transformation operator is being applied. + */ + IType getOperand(); +} \ No newline at end of file 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 d4fbe2b8676..272ce3c9539 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 @@ -40,6 +40,12 @@ 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 + */ + public static final int GNU_LATEST_VERSION_MAJOR = 4, + GNU_LATEST_VERSION_MINOR = 7; + private static final GPPLanguage DEFAULT_INSTANCE = new GPPLanguage(); public static GPPLanguage getDefault() { 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 476a245dc5e..ee2fcc6cb17 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 @@ -34,7 +34,7 @@ public class GPPScannerExtensionConfiguration extends GNUScannerExtensionConfigu 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); - + public static GPPScannerExtensionConfiguration getInstance() { return CONFIG; } @@ -106,6 +106,8 @@ public class GPPScannerExtensionConfiguration extends GNUScannerExtensionConfigu if (version >= VERSION_4_7) { addKeyword(GCCKeywords.cp__float128, IGCCToken.t__float128); addKeyword(GCCKeywords.cp__int128, IGCCToken.t__int128); + + addKeyword(GCCKeywords.cp__underlying_type, IGCCToken.tTT_underlying_type); } } 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 88a057d544e..ee060670d96 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 @@ -79,4 +79,8 @@ public class GCCKeywords { cp__is_literal_type= "__is_literal_type".toCharArray(), cp__is_standard_layout= "__is_standard_layout".toCharArray(), cp__is_trivial= "__is_trivial".toCharArray(); + + /** @since 5.6 */ + public static final char[] + cp__underlying_type= "__underlying_type".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 a8a5d2498f9..d253176d97e 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 @@ -47,4 +47,6 @@ public interface IGCCToken extends IToken { /** @since 5.5 */ int t__int128= FIRST_RESERVED_IGCCToken + 25; /** @since 5.5 */ int t__float128= FIRST_RESERVED_IGCCToken + 26; + + /** @since 5.6 */ int tTT_underlying_type= FIRST_RESERVED_IGCCToken + 27; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ITypeMarshalBuffer.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ITypeMarshalBuffer.java index 3394c2ff227..d6f37f32af1 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ITypeMarshalBuffer.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ITypeMarshalBuffer.java @@ -38,6 +38,7 @@ public interface ITypeMarshalBuffer { final static byte UNKNOWN_MEMBER_CLASS_INSTANCE = 0x0D; final static byte DEFERRED_CLASS_INSTANCE = 0x0E; final static byte ALIAS_TEMPLATE = 0x0F; + final static byte TYPE_TRANSFORMATION = 0x10; // Can add more types up to 0x1C, after that it will collide with TypeMarshalBuffer.UNSTORABLE_TYPE. final static byte diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ProblemType.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ProblemType.java index 48d9b49696a..420d7309ce0 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ProblemType.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ProblemType.java @@ -23,6 +23,7 @@ import org.eclipse.core.runtime.CoreException; public class ProblemType implements IProblemType, ISerializableType { public static final IType UNRESOLVED_NAME = new ProblemType(TYPE_UNRESOLVED_NAME); public static final IType UNKNOWN_FOR_EXPRESSION = new ProblemType(ISemanticProblem.TYPE_UNKNOWN_FOR_EXPRESSION); + public static final IType ENUMERATION_EXPECTED = new ProblemType(ISemanticProblem.TYPE_ENUMERATION_EXPECTED); private final int fID; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTTypeTransformationSpecifier.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTTypeTransformationSpecifier.java new file mode 100644 index 00000000000..a7b9e4c3a57 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTTypeTransformationSpecifier.java @@ -0,0 +1,77 @@ +/******************************************************************************* + * Copyright (c) 2013 IBM Corporation 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: + * 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.cpp.ICPPASTDeclSpecifier; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTypeId; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTypeTransformationSpecifier; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPUnaryTypeTransformation.Operator; + +/** + * Implementation of ICPPASTTypeTransformationSpecifier. + */ +public class CPPASTTypeTransformationSpecifier extends CPPASTBaseDeclSpecifier implements ICPPASTTypeTransformationSpecifier { + private Operator fOperator; + private ICPPASTTypeId fOperand; + + public CPPASTTypeTransformationSpecifier(Operator operator, ICPPASTTypeId operand) { + fOperator = operator; + fOperand = operand; + fOperand.setParent(this); + fOperand.setPropertyInParent(OPERAND); + } + + @Override + public ICPPASTDeclSpecifier copy() { + return copy(CopyStyle.withoutLocations); + } + + @Override + public CPPASTTypeTransformationSpecifier copy(CopyStyle style) { + CPPASTTypeTransformationSpecifier copy = new CPPASTTypeTransformationSpecifier(fOperator, fOperand.copy(style)); + return super.copy(copy, style); + } + + @Override + public Operator getOperator() { + return fOperator; + } + + @Override + public ICPPASTTypeId getOperand() { + return fOperand; + } + + @Override + public boolean accept(ASTVisitor action) { + if (action.shouldVisitDeclSpecifiers) { + switch (action.visit(this)) { + case ASTVisitor.PROCESS_ABORT: return false; + case ASTVisitor.PROCESS_SKIP: return true; + default: break; + } + } + + if (!fOperand.accept(action)) + return false; + + if (action.shouldVisitDeclSpecifiers) { + switch (action.leave(this)) { + case ASTVisitor.PROCESS_ABORT: return false; + case ASTVisitor.PROCESS_SKIP: return true; + default: break; + } + } + + return true; + } +} 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 26a382a2794..ad83cf16922 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 @@ -14,7 +14,7 @@ package org.eclipse.cdt.internal.core.dom.parser.cpp; import org.eclipse.cdt.core.dom.ast.IASTASMDeclaration; import org.eclipse.cdt.core.dom.ast.IASTArrayModifier; import org.eclipse.cdt.core.dom.ast.IASTAttribute; -import org.eclipse.cdt.core.dom.ast.IASTBinaryTypeIdExpression.Operator; +import org.eclipse.cdt.core.dom.ast.IASTBinaryTypeIdExpression; import org.eclipse.cdt.core.dom.ast.IASTBreakStatement; import org.eclipse.cdt.core.dom.ast.IASTCaseStatement; import org.eclipse.cdt.core.dom.ast.IASTCompoundStatement; @@ -108,12 +108,14 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTranslationUnit; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTryBlockStatement; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTypeId; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTypeIdExpression; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTypeTransformationSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTUnaryExpression; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTUsingDeclaration; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTUsingDirective; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTVisibilityLabel; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTWhileStatement; import org.eclipse.cdt.core.dom.ast.cpp.ICPPNodeFactory; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPUnaryTypeTransformation; import org.eclipse.cdt.core.dom.ast.gnu.IGNUASTCompoundStatementExpression; import org.eclipse.cdt.core.parser.IScanner; import org.eclipse.cdt.internal.core.dom.parser.ASTToken; @@ -178,7 +180,7 @@ public class CPPNodeFactory extends NodeFactory implements ICPPNodeFactory { } @Override - public IASTExpression newBinaryTypeIdExpression(Operator op, IASTTypeId type1, IASTTypeId type2) { + public IASTExpression newBinaryTypeIdExpression(IASTBinaryTypeIdExpression.Operator op, IASTTypeId type1, IASTTypeId type2) { return new CPPASTBinaryTypeIdExpression(op, type1, type2); } @@ -721,6 +723,11 @@ public class CPPNodeFactory extends NodeFactory implements ICPPNodeFactory { return new CPPASTTypenameExpression(qualifiedName, expr); } + @Override + public ICPPASTTypeTransformationSpecifier newTypeTransformationSpecifier(ICPPUnaryTypeTransformation.Operator operator, ICPPASTTypeId operand) { + return new CPPASTTypeTransformationSpecifier(operator, operand); + } + @Override public ICPPASTUnaryExpression newUnaryExpression(int operator, IASTExpression operand) { return new CPPASTUnaryExpression(operator, operand); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPUnaryTypeTransformation.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPUnaryTypeTransformation.java new file mode 100644 index 00000000000..9e4287d96bf --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPUnaryTypeTransformation.java @@ -0,0 +1,73 @@ +/******************************************************************************* + * Copyright (c) 2013 IBM Corporation 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: + * Nathan Ridge - Initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.core.dom.parser.cpp; + +import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.core.dom.ast.IType; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPUnaryTypeTransformation; +import org.eclipse.cdt.internal.core.dom.parser.ISerializableType; +import org.eclipse.cdt.internal.core.dom.parser.ITypeMarshalBuffer; +import org.eclipse.core.runtime.CoreException; + +/** + * Implementation of ICPPUnaryTypeTransformation. + * + */ +public class CPPUnaryTypeTransformation implements ICPPUnaryTypeTransformation, ISerializableType { + Operator fOperator; + IType fOperand; + + public CPPUnaryTypeTransformation(Operator operator, IType operand) { + fOperator = operator; + fOperand = operand; + } + + @Override + public boolean isSameType(IType other) { + if (this == other) + return false; + if (!(other instanceof ICPPUnaryTypeTransformation)) + return false; + ICPPUnaryTypeTransformation otherType = (ICPPUnaryTypeTransformation) other; + return getOperator() == otherType.getOperator() + && getOperand().isSameType(otherType.getOperand()); + } + + @Override + public Operator getOperator() { + return fOperator; + } + + @Override + public IType getOperand() { + return fOperand; + } + + @Override + public CPPUnaryTypeTransformation clone() { + return new CPPUnaryTypeTransformation(fOperator, (IType) fOperand.clone()); + } + + @Override + public void marshal(ITypeMarshalBuffer buffer) throws CoreException { + buffer.putShort(ITypeMarshalBuffer.TYPE_TRANSFORMATION); + buffer.putByte((byte) getOperator().ordinal()); + buffer.marshalType(getOperand()); + } + + public static IType unmarshal(short firstBytes, ITypeMarshalBuffer buffer) throws CoreException { + int operator = buffer.getByte(); + if (operator >= Operator.values().length) + throw new CoreException(CCorePlugin.createStatus( + "Cannot unmarshal CPPUnaryTypeTransformation - unrecognized type transformation operator")); //$NON-NLS-1$ + return new CPPUnaryTypeTransformation(Operator.values()[operator], buffer.unmarshalType()); + } +} 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 694cb931f88..71d7c47e712 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 @@ -30,7 +30,6 @@ import org.eclipse.cdt.core.dom.ast.IASTArraySubscriptExpression; import org.eclipse.cdt.core.dom.ast.IASTAttribute; import org.eclipse.cdt.core.dom.ast.IASTBinaryExpression; import org.eclipse.cdt.core.dom.ast.IASTBinaryTypeIdExpression; -import org.eclipse.cdt.core.dom.ast.IASTBinaryTypeIdExpression.Operator; import org.eclipse.cdt.core.dom.ast.IASTCastExpression; import org.eclipse.cdt.core.dom.ast.IASTCompositeTypeSpecifier; import org.eclipse.cdt.core.dom.ast.IASTCompoundStatement; @@ -123,11 +122,13 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTranslationUnit; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTryBlockStatement; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTypeId; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTypeIdExpression; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTypeTransformationSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTUnaryExpression; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTUsingDeclaration; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTUsingDirective; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTVisibilityLabel; import org.eclipse.cdt.core.dom.ast.cpp.ICPPNodeFactory; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPUnaryTypeTransformation; import org.eclipse.cdt.core.dom.parser.IExtensionToken; import org.eclipse.cdt.core.dom.parser.cpp.ICPPParserExtensionConfiguration; import org.eclipse.cdt.core.index.IIndex; @@ -1382,7 +1383,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { return false; } - private Operator getBinaryTypeTraitOperator(IToken first) { + private IASTBinaryTypeIdExpression.Operator getBinaryTypeTraitOperator(IToken first) { switch (first.getType()) { case IGCCToken.tTT_is_base_of: return IASTBinaryTypeIdExpression.Operator.__is_base_of; @@ -3037,6 +3038,15 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { encounteredTypename= true; break; + + case IGCCToken.tTT_underlying_type: + if (encounteredRawType || encounteredTypename) + throwBacktrack(LA(1)); + + result= typeTransformationSpecifier(DeclarationOptions.TYPEID); + endOffset= calculateEndOffset(result); + encounteredTypename= true; + break; default: if (lt1 >= IExtensionToken.t__otherDeclSpecModifierFirst && lt1 <= IExtensionToken.t__otherDeclSpecModifierLast) { @@ -3229,6 +3239,18 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { IASTName name = qualifiedName(); return setRange(nodeFactory.newElaboratedTypeSpecifier(eck, name), offset, calculateEndOffset(name)); } + + /** + * Parse a type transformation specifier. + */ + protected ICPPASTTypeTransformationSpecifier typeTransformationSpecifier(DeclarationOptions options) + throws BacktrackException, EndOfFileException { + final int offset = consume(IGCCToken.tTT_underlying_type).getOffset(); + consume(IToken.tLPAREN); + ICPPASTTypeId operand = typeId(options); + final int endOffset = consumeOrEOC(IToken.tRPAREN).getEndOffset(); + return setRange(nodeFactory.newTypeTransformationSpecifier(ICPPUnaryTypeTransformation.Operator.underlying_type, operand), offset, endOffset); + } @Override protected IASTDeclarator initDeclarator(IASTDeclSpecifier declspec, DeclarationOptions option) diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPTemplates.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPTemplates.java index e5cf9c41887..4b404420fbc 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPTemplates.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPTemplates.java @@ -97,6 +97,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateTemplateParameter; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateTypeParameter; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPUnaryTypeTransformation; import org.eclipse.cdt.core.dom.ast.cpp.ICPPUsingDeclaration; import org.eclipse.cdt.core.index.IIndexBinding; import org.eclipse.cdt.core.parser.util.ArrayUtil; @@ -165,6 +166,7 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownType; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.Conversions.Context; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.Conversions.UDCMode; + /** * Collection of static methods to perform template instantiation, member specialization and * type instantiation. @@ -1355,6 +1357,15 @@ public class CPPTemplates { return typeContainer; } + if (type instanceof ICPPUnaryTypeTransformation) { + ICPPUnaryTypeTransformation typeTransformation = (ICPPUnaryTypeTransformation) type; + IType operand = instantiateType(typeTransformation.getOperand(), tpMap, packOffset, within, point); + switch (typeTransformation.getOperator()) { + case underlying_type: return TypeTraits.underlyingType(operand); + default: return null; // shouldn't happen + } + } + return type; } catch (DOMException e) { return e.getProblem(); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java index ac04f9e6af4..57a23396f58 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java @@ -137,6 +137,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateParameter; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateSpecialization; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplatedTypeTemplateParameter; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTypeId; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTypeTransformationSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTUsingDeclaration; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTUsingDirective; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTWhileStatement; @@ -206,6 +207,7 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPReferenceType; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPScope; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPTemplateParameterMap; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPTemplateTypeArgument; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPUnaryTypeTransformation; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPTypedef; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPUnknownTypeScope; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPVariable; @@ -219,9 +221,17 @@ import org.eclipse.cdt.internal.core.index.IIndexScope; * Collection of methods to extract information from a C++ translation unit. */ public class CPPVisitor extends ASTQueries { - private static final CPPBasicType INT_TYPE = new CPPBasicType(Kind.eInt, 0); - private static final CPPBasicType LONG_TYPE = new CPPBasicType(Kind.eInt, IBasicType.IS_LONG); - private static final CPPBasicType UNSIGNED_LONG = new CPPBasicType(Kind.eInt, IBasicType.IS_LONG | IBasicType.IS_UNSIGNED); + public static final CPPBasicType SHORT_TYPE = new CPPBasicType(Kind.eInt, IBasicType.IS_SHORT); + public static final CPPBasicType INT_TYPE = new CPPBasicType(Kind.eInt, 0); + public static final CPPBasicType LONG_TYPE = new CPPBasicType(Kind.eInt, IBasicType.IS_LONG); + public static final CPPBasicType LONG_LONG_TYPE = new CPPBasicType(Kind.eInt, IBasicType.IS_LONG_LONG); + public static final CPPBasicType INT128_TYPE = new CPPBasicType(Kind.eInt128, 0); + + public static final CPPBasicType UNSIGNED_SHORT = new CPPBasicType(Kind.eInt, IBasicType.IS_SHORT | IBasicType.IS_UNSIGNED); + public static final CPPBasicType UNSIGNED_INT = new CPPBasicType(Kind.eInt, IBasicType.IS_UNSIGNED); + public static final CPPBasicType UNSIGNED_LONG = new CPPBasicType(Kind.eInt, IBasicType.IS_LONG | IBasicType.IS_UNSIGNED); + public static final CPPBasicType UNSIGNED_LONG_LONG = new CPPBasicType(Kind.eInt, IBasicType.IS_LONG_LONG | IBasicType.IS_UNSIGNED); + public static final CPPBasicType UNSIGNED_INT128 = new CPPBasicType(Kind.eInt128, IBasicType.IS_UNSIGNED); public static final String BEGIN_STR = "begin"; //$NON-NLS-1$ public static final char[] BEGIN = BEGIN_STR.toCharArray(); @@ -2146,6 +2156,9 @@ public class CPPVisitor extends ASTQueries { name = ((ICPPASTElaboratedTypeSpecifier) declSpec).getName(); } else if (declSpec instanceof IASTEnumerationSpecifier) { name = ((IASTEnumerationSpecifier) declSpec).getName(); + } else if (declSpec instanceof ICPPASTTypeTransformationSpecifier) { + ICPPASTTypeTransformationSpecifier spec = (ICPPASTTypeTransformationSpecifier) declSpec; + return new CPPUnaryTypeTransformation(spec.getOperator(), createType(spec.getOperand())); } else if (declSpec instanceof ICPPASTSimpleDeclSpecifier) { ICPPASTSimpleDeclSpecifier spec = (ICPPASTSimpleDeclSpecifier) declSpec; // Check for decltype(expr) diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/TypeTraits.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/TypeTraits.java index d02dfdcd849..d5493bed5ed 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/TypeTraits.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/TypeTraits.java @@ -15,15 +15,22 @@ import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUti import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.TDEF; import org.eclipse.cdt.core.dom.ast.IASTNode; +import org.eclipse.cdt.core.dom.ast.IBasicType; import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPBase; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPBasicType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPEnumeration; import org.eclipse.cdt.core.dom.ast.cpp.ICPPField; import org.eclipse.cdt.core.dom.ast.cpp.ICPPMember; import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod; import org.eclipse.cdt.core.dom.ast.cpp.ICPPReferenceType; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPUnaryTypeTransformation.Operator; import org.eclipse.cdt.core.dom.ast.cpp.SemanticQueries; +import org.eclipse.cdt.internal.core.dom.parser.ArithmeticConversion; +import org.eclipse.cdt.internal.core.dom.parser.ProblemType; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPUnaryTypeTransformation; import org.eclipse.cdt.internal.core.dom.parser.cpp.ClassTypeHelper; import org.eclipse.cdt.internal.core.dom.parser.cpp.ClassTypeHelper.MethodKind; @@ -326,4 +333,60 @@ public class TypeTraits { } return false; } + + public static IType underlyingType(IType type) { + if (CPPTemplates.isDependentType(type)) { + return new CPPUnaryTypeTransformation(Operator.underlying_type, type); + } else if (!(type instanceof ICPPEnumeration)) { + return ProblemType.ENUMERATION_EXPECTED; + } else { + ICPPEnumeration enumeration = (ICPPEnumeration) type; + + // [dcl.enum] p5 + // "The underlying type can be explicitly specified using enum-base; + // if not explicitly specified, the underlying type of a scoped + // enumeration type is int." + IType fixedType = enumeration.getFixedType(); + if (fixedType != null) + return fixedType; + if (enumeration.isScoped()) + return CPPVisitor.INT_TYPE; + + // [dcl.enum] p6 + // "For an enumeration whose underlying type is not fixed, the + // underlying type is an integral type that can represent all + // the numerator values defined in the enumeration. ... It is + // implementation-defined which integral type is used as the + // underlying type except that the underlying type shall not be + // larger than int unless the value of an enumerator cannot fit + // in an int or unsigned int. If the enumerator-list is empty, + // the underlying type is as if the enumeration had a single + // enumerator with value 0." + if (enumeration.getEnumerators().length == 0) + return CPPVisitor.INT_TYPE; + if (enumeration.getMinValue() < 0 || enumeration.getMaxValue() < 0) { + return smallestFittingType(enumeration, + CPPVisitor.INT_TYPE, + CPPVisitor.LONG_TYPE, + CPPVisitor.LONG_LONG_TYPE, + CPPVisitor.INT128_TYPE); + } else { + return smallestFittingType(enumeration, + CPPVisitor.UNSIGNED_INT, + CPPVisitor.UNSIGNED_LONG, + CPPVisitor.UNSIGNED_LONG_LONG, + CPPVisitor.UNSIGNED_INT128); + } + } + } + + private static IBasicType smallestFittingType(ICPPEnumeration enumeration, ICPPBasicType... types) { + for (int i = 0; i < types.length - 1; ++i) { + if (ArithmeticConversion.fitsIntoType(types[i], enumeration.getMinValue()) + && ArithmeticConversion.fitsIntoType(types[i], enumeration.getMaxValue())) { + return types[i]; + } + } + return types[types.length - 1]; // assume it fits into the largest type provided + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CPPCompositesFactory.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CPPCompositesFactory.java index 95753c0b784..67e611bad20 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CPPCompositesFactory.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CPPCompositesFactory.java @@ -52,6 +52,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateNonTypeParameter; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateTemplateParameter; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateTypeParameter; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPUnaryTypeTransformation; import org.eclipse.cdt.core.dom.ast.cpp.ICPPUsingDeclaration; import org.eclipse.cdt.core.dom.ast.cpp.ICPPVariable; import org.eclipse.cdt.core.index.IIndex; @@ -65,6 +66,7 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPPointerToMemberType; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPPointerType; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPQualifierType; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPReferenceType; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPUnaryTypeTransformation; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPClassSpecializationScope; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPDeferredClassInstance; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation; @@ -223,6 +225,12 @@ public class CPPCompositesFactory extends AbstractCompositeFactory { return new TypeOfDependentExpression(e2); return tde; } + if (rtype instanceof ICPPUnaryTypeTransformation) { + ICPPUnaryTypeTransformation ttt= (ICPPUnaryTypeTransformation) rtype; + IType operand = ttt.getOperand(); + IType operand2 = getCompositeType(operand); + return new CPPUnaryTypeTransformation(ttt.getOperator(), operand2); + } if (rtype instanceof IBasicType || rtype == null || rtype instanceof ISemanticProblem) { return rtype; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPLinkage.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPLinkage.java index 716725a5a88..b0891405695 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPLinkage.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPLinkage.java @@ -93,6 +93,7 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPPointerToMemberType; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPPointerType; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPQualifierType; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPReferenceType; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPUnaryTypeTransformation; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPUnknownClassInstance; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPUnknownMember; import org.eclipse.cdt.internal.core.dom.parser.cpp.ClassTypeHelper; @@ -1197,6 +1198,8 @@ class PDOMCPPLinkage extends PDOMLinkage implements IIndexCPPBindingConstants { return CPPDeferredClassInstance.unmarshal(getPDOM(), firstBytes, buffer); case ITypeMarshalBuffer.ALIAS_TEMPLATE: return CPPAliasTemplateInstance.unmarshal(firstBytes, buffer); + case ITypeMarshalBuffer.TYPE_TRANSFORMATION: + return CPPUnaryTypeTransformation.unmarshal(firstBytes, buffer); } throw new CoreException(CCorePlugin.createStatus("Cannot unmarshal a type, first bytes=" + firstBytes)); //$NON-NLS-1$