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

Bug 411196 - Type traits that evaluate to a type

Change-Id: Ic0772e5b6e27aade06f4100b1ce92f671f6ea4d5
Signed-off-by: Nathan Ridge <zeratul976@hotmail.com>
Reviewed-on: https://git.eclipse.org/r/15873
Reviewed-by: Sergey Prigogin <eclipse.sprigogin@gmail.com>
IP-Clean: Sergey Prigogin <eclipse.sprigogin@gmail.com>
Tested-by: Sergey Prigogin <eclipse.sprigogin@gmail.com>
This commit is contained in:
Nathan Ridge 2013-08-27 02:01:52 -04:00 committed by Sergey Prigogin
parent afecac9ccd
commit 9d1233f05a
26 changed files with 576 additions and 13 deletions

View file

@ -10358,4 +10358,42 @@ public class AST2CPPTests extends AST2TestBase {
public void testDecltypeInNameQualifier_bug380751() throws Exception {
parseAndCheckBindings();
}
// template <typename T>
// 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<e_fixed_short1>::type short1_type;
// typedef underlying_type<e_fixed_short2>::type short2_type;
//
// typedef underlying_type<e_scoped>::type scoped_type;
//
// typedef underlying_type<e_unsigned>::type unsigned_type;
// typedef underlying_type<e_int>::type int_type;
// typedef underlying_type<e_ulong>::type ulong_type;
// typedef underlying_type<e_long>::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);
}
}

View file

@ -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<String, String> getGnuMap() {
Map<String, String> map= new HashMap<String, String>();
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");

View file

@ -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));
}
}

View file

@ -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 <typename T>
// 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<e_fixed_short1>::type short1_type;
// typedef underlying_type<e_fixed_short2>::type short2_type;
//
// typedef underlying_type<e_scoped>::type scoped_type;
//
// typedef underlying_type<e_unsigned>::type unsigned_type;
// typedef underlying_type<e_int>::type int_type;
// typedef underlying_type<e_ulong>::type ulong_type;
// typedef underlying_type<e_long>::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);
}
}

View file

@ -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);

View file

@ -21,16 +21,19 @@ public class TestScannerInfo extends ExtendedScannerInfo {
private String[] fIncludes;
private String[] fIncludeFiles;
private String[] fMacroFiles;
private Map<String, String> fDefinedSymbols;
public TestScannerInfo(String[] includes, String[] macroFiles, String[] includeFiles) {
public TestScannerInfo(String[] includes, String[] macroFiles, String[] includeFiles,
Map<String, String> definedSymbols) {
fIncludes= includes;
fIncludeFiles= includeFiles;
fMacroFiles= macroFiles;
fDefinedSymbols= definedSymbols;
}
@Override
public Map getDefinedSymbols() {
return Collections.emptyMap();
return fDefinedSymbols == null ? Collections.emptyMap() : fDefinedSymbols;
}
@Override

View file

@ -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<String, String> sDefinedSymbols = new HashMap<String, String>();
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

View file

@ -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.

View file

@ -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 {
/**
* <code>OPERAND</code> represents the relationship between an <code>ICPPASTTypeTransformationSpecifier</code> and
* its nested <code>IASTTypeId</code>.
*/
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();
}

View file

@ -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);

View file

@ -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();
}

View file

@ -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() {

View file

@ -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);
}
}

View file

@ -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();
}

View file

@ -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;
}

View file

@ -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

View file

@ -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;

View file

@ -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;
}
}

View file

@ -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);

View file

@ -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());
}
}

View file

@ -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)

View file

@ -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();

View file

@ -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)

View file

@ -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
}
}

View file

@ -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;
}

View file

@ -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$