1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-08-14 03:35:37 +02:00

Bug 539052 - Add support for __is_constructible type trait intrinsic

Backport to the 9.5 branch, including adding an API filter to allow
adding a new keyword and token type.

Change-Id: I9789268dee320ab95aee60c30d8e1867bd0dda53
This commit is contained in:
Nathan Ridge 2018-09-15 14:14:04 -04:00
parent de428d3703
commit 87f1208c77
12 changed files with 61 additions and 9 deletions

View file

@ -12660,6 +12660,18 @@ public class AST2CPPTests extends AST2CPPTestBase {
helper.assertVariableValue("waldo5", 0); helper.assertVariableValue("waldo5", 0);
} }
// template <typename T, typename U>
// struct pair {
// pair();
// pair(T, U);
// };
//
// constexpr bool waldo = __is_constructible(pair<const int>, pair<int, int>&&);
public void testIsConstructible_539052() throws Exception {
BindingAssertionHelper helper = getAssertionHelper();
helper.assertVariableValue("waldo", 1);
}
// namespace x { // namespace x {
// void foo(); // void foo();
// } // }

View file

@ -70,7 +70,7 @@ public class BaseTestCase extends TestCase {
* The GCC version to emulate when running tests. * The GCC version to emulate when running tests.
* We emulate the latest version whose extensions we support. * We emulate the latest version whose extensions we support.
*/ */
protected static final int GCC_MAJOR_VERSION_FOR_TESTS = 5; protected static final int GCC_MAJOR_VERSION_FOR_TESTS = 8;
protected static final int GCC_MINOR_VERSION_FOR_TESTS = 1; protected static final int GCC_MINOR_VERSION_FOR_TESTS = 1;
/** /**

View file

@ -1,5 +1,13 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<component id="org.eclipse.cdt.core" version="2"> <component id="org.eclipse.cdt.core" version="2">
<resource path="META-INF/MANIFEST.MF">
<filter comment="To allow bug 539052 to be backported to the 9.5 branch" id="924844039">
<message_arguments>
<message_argument value="6.5.0"/>
<message_argument value="6.5.0"/>
</message_arguments>
</filter>
</resource>
<resource path="src/org/eclipse/cdt/core/build/ICBuildConfiguration.java" type="org.eclipse.cdt.core.build.ICBuildConfiguration"> <resource path="src/org/eclipse/cdt/core/build/ICBuildConfiguration.java" type="org.eclipse.cdt.core.build.ICBuildConfiguration">
<filter id="403767336"> <filter id="403767336">
<message_arguments> <message_arguments>

View file

@ -24,7 +24,8 @@ public interface ICPPASTNaryTypeIdExpression extends ICPPASTExpression {
public static final ASTNodeProperty OPERAND = new ASTNodeProperty("ICPPASTNaryTypeIdExpression.OPERAND [IASTTypeId]"); //$NON-NLS-1$ public static final ASTNodeProperty OPERAND = new ASTNodeProperty("ICPPASTNaryTypeIdExpression.OPERAND [IASTTypeId]"); //$NON-NLS-1$
public static enum Operator { public static enum Operator {
__is_trivially_constructible __is_trivially_constructible,
/** @since 6.5 */ __is_constructible
} }
/** /**

View file

@ -34,12 +34,14 @@ public class GPPScannerExtensionConfiguration extends GNUScannerExtensionConfigu
private static final int VERSION_4_6 = version(4, 6); 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_4_7 = version(4, 7);
private static final int VERSION_5_0 = version(5, 0); private static final int VERSION_5_0 = version(5, 0);
private static final int VERSION_8_0 = version(8, 0);
private static GPPScannerExtensionConfiguration CONFIG= new GPPScannerExtensionConfiguration(); private static GPPScannerExtensionConfiguration CONFIG= new GPPScannerExtensionConfiguration();
private static GPPScannerExtensionConfiguration CONFIG_4_2= new GPPScannerExtensionConfiguration(VERSION_4_2); 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_3= new GPPScannerExtensionConfiguration(VERSION_4_3);
private static GPPScannerExtensionConfiguration CONFIG_4_6= new GPPScannerExtensionConfiguration(VERSION_4_6); 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_4_7= new GPPScannerExtensionConfiguration(VERSION_4_7);
private static GPPScannerExtensionConfiguration CONFIG_5_0= new GPPScannerExtensionConfiguration(VERSION_5_0); private static GPPScannerExtensionConfiguration CONFIG_5_0= new GPPScannerExtensionConfiguration(VERSION_5_0);
private static GPPScannerExtensionConfiguration CONFIG_8_0= new GPPScannerExtensionConfiguration(VERSION_8_0);
private static GPPScannerExtensionConfiguration CONFIG_CLANG= private static GPPScannerExtensionConfiguration CONFIG_CLANG=
new GPPScannerExtensionConfiguration(CompilerType.Clang, 0 /* version is ignored for now */); new GPPScannerExtensionConfiguration(CompilerType.Clang, 0 /* version is ignored for now */);
@ -65,6 +67,9 @@ public class GPPScannerExtensionConfiguration extends GNUScannerExtensionConfigu
int major= Integer.valueOf(definedSymbols.get("__GNUC__")); //$NON-NLS-1$ int major= Integer.valueOf(definedSymbols.get("__GNUC__")); //$NON-NLS-1$
int minor= Integer.valueOf(definedSymbols.get("__GNUC_MINOR__")); //$NON-NLS-1$ int minor= Integer.valueOf(definedSymbols.get("__GNUC_MINOR__")); //$NON-NLS-1$
int version= version(major, minor); int version= version(major, minor);
if (version >= VERSION_8_0) {
return CONFIG_8_0;
}
if (version >= VERSION_5_0) { if (version >= VERSION_5_0) {
return CONFIG_5_0; return CONFIG_5_0;
} }
@ -149,6 +154,9 @@ public class GPPScannerExtensionConfiguration extends GNUScannerExtensionConfigu
addKeyword(GCCKeywords.cp__is_trivially_constructible, IGCCToken.tTT_is_trivially_constructible); addKeyword(GCCKeywords.cp__is_trivially_constructible, IGCCToken.tTT_is_trivially_constructible);
addKeyword(GCCKeywords.cp__is_trivially_assignable, IGCCToken.tTT_is_trivially_assignable); addKeyword(GCCKeywords.cp__is_trivially_assignable, IGCCToken.tTT_is_trivially_assignable);
} }
if (version >= VERSION_8_0) {
addKeyword(GCCKeywords.cp__is_constructible, IGCCToken.tTT_is_constructible);
}
} else if (compiler == CompilerType.Clang) { } else if (compiler == CompilerType.Clang) {
// As documented at // As documented at
// http://clang.llvm.org/docs/LanguageExtensions.html#checks-for-type-trait-primitives. // http://clang.llvm.org/docs/LanguageExtensions.html#checks-for-type-trait-primitives.
@ -173,6 +181,7 @@ public class GPPScannerExtensionConfiguration extends GNUScannerExtensionConfigu
addKeyword(GCCKeywords.cp__underlying_type, IGCCToken.tTT_underlying_type); addKeyword(GCCKeywords.cp__underlying_type, IGCCToken.tTT_underlying_type);
addKeyword(GCCKeywords.cp__is_trivially_constructible, IGCCToken.tTT_is_trivially_constructible); addKeyword(GCCKeywords.cp__is_trivially_constructible, IGCCToken.tTT_is_trivially_constructible);
addKeyword(GCCKeywords.cp__is_trivially_assignable, IGCCToken.tTT_is_trivially_assignable); addKeyword(GCCKeywords.cp__is_trivially_assignable, IGCCToken.tTT_is_trivially_assignable);
addKeyword(GCCKeywords.cp__is_constructible, IGCCToken.tTT_is_constructible);
} }
} }

View file

@ -108,4 +108,8 @@ public class GCCKeywords {
cp__is_trivially_copyable= "__is_trivially_copyable".toCharArray(), cp__is_trivially_copyable= "__is_trivially_copyable".toCharArray(),
cp__is_trivially_constructible= "__is_trivially_constructible".toCharArray(), cp__is_trivially_constructible= "__is_trivially_constructible".toCharArray(),
cp__is_trivially_assignable= "__is_trivially_assignable".toCharArray(); cp__is_trivially_assignable= "__is_trivially_assignable".toCharArray();
/** @since 6.5 */
public static final char[]
cp__is_constructible= "__is_constructible".toCharArray();
} }

View file

@ -58,4 +58,6 @@ public interface IGCCToken extends IToken {
/** @since 6.0 */ int tTT_is_trivially_copyable= FIRST_RESERVED_IGCCToken + 32; /** @since 6.0 */ int tTT_is_trivially_copyable= FIRST_RESERVED_IGCCToken + 32;
/** @since 6.0 */ int tTT_is_trivially_constructible= FIRST_RESERVED_IGCCToken + 33; /** @since 6.0 */ int tTT_is_trivially_constructible= FIRST_RESERVED_IGCCToken + 33;
/** @since 6.0 */ int tTT_is_trivially_assignable= FIRST_RESERVED_IGCCToken + 34; /** @since 6.0 */ int tTT_is_trivially_assignable= FIRST_RESERVED_IGCCToken + 34;
/** @since 6.5 */ int tTT_is_constructible= FIRST_RESERVED_IGCCToken + 35;
} }

View file

@ -611,14 +611,16 @@ public class ValueFactory {
private static IValue applyNaryTypeIdOperator(ICPPASTNaryTypeIdExpression.Operator operator, private static IValue applyNaryTypeIdOperator(ICPPASTNaryTypeIdExpression.Operator operator,
IType[] operands, IBinding pointOfDefinition) { IType[] operands, IBinding pointOfDefinition) {
switch (operator) { switch (operator) {
case __is_constructible:
case __is_trivially_constructible: case __is_trivially_constructible:
if (operands.length == 0) { if (operands.length == 0) {
return IntegralValue.UNKNOWN; return IntegralValue.UNKNOWN;
} }
boolean checkTrivial = (operator == Operator.__is_trivially_constructible);
IType typeToConstruct = operands[0]; IType typeToConstruct = operands[0];
IType[] argumentTypes = Arrays.copyOfRange(operands, 1, operands.length); IType[] argumentTypes = Arrays.copyOfRange(operands, 1, operands.length);
return IntegralValue.create(TypeTraits.isTriviallyConstructible(typeToConstruct, argumentTypes, return IntegralValue.create(TypeTraits.isConstructible(typeToConstruct, argumentTypes,
pointOfDefinition) ? 1 : 0); pointOfDefinition, checkTrivial) ? 1 : 0);
} }
return IntegralValue.UNKNOWN; return IntegralValue.UNKNOWN;
} }

View file

@ -1542,6 +1542,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
case IGCCToken.tTT_is_trivially_copyable: case IGCCToken.tTT_is_trivially_copyable:
case IGCCToken.tTT_is_trivially_constructible: case IGCCToken.tTT_is_trivially_constructible:
case IGCCToken.tTT_is_trivially_assignable: case IGCCToken.tTT_is_trivially_assignable:
case IGCCToken.tTT_is_constructible:
return parseTypeTrait(); return parseTypeTrait();
default: default:
@ -1601,6 +1602,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
private boolean isNaryTrait(IToken operatorToken) { private boolean isNaryTrait(IToken operatorToken) {
switch (operatorToken.getType()) { switch (operatorToken.getType()) {
case IGCCToken.tTT_is_trivially_constructible: case IGCCToken.tTT_is_trivially_constructible:
case IGCCToken.tTT_is_constructible:
return true; return true;
} }
return false; return false;
@ -1622,6 +1624,8 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
switch (operatorToken.getType()) { switch (operatorToken.getType()) {
case IGCCToken.tTT_is_trivially_constructible: case IGCCToken.tTT_is_trivially_constructible:
return ICPPASTNaryTypeIdExpression.Operator.__is_trivially_constructible; return ICPPASTNaryTypeIdExpression.Operator.__is_trivially_constructible;
case IGCCToken.tTT_is_constructible:
return ICPPASTNaryTypeIdExpression.Operator.__is_constructible;
} }
assert false; assert false;

View file

@ -88,6 +88,7 @@ public class EvalNaryTypeId extends CPPDependentEvaluation {
public IType getType() { public IType getType() {
switch (fOperator) { switch (fOperator) {
case __is_trivially_constructible: case __is_trivially_constructible:
case __is_constructible:
return CPPBasicType.BOOLEAN; return CPPBasicType.BOOLEAN;
} }
return ProblemType.UNKNOWN_FOR_EXPRESSION; return ProblemType.UNKNOWN_FOR_EXPRESSION;

View file

@ -566,11 +566,14 @@ public class TypeTraits {
} }
/** /**
* Returns true if 'typeToConstruct' is trivially constructible from arguments * Returns true if 'typeToConstruct' is constructible from arguments
* of type 'argumentTypes', as defined in [meta.unary.prop]. * of type 'argumentTypes', as defined in [meta.unary.prop].
*
* If 'checkTrivial' is true, additionally checks if 'typeToConstruct'
* is trivially constructible from said argument types.
*/ */
public static boolean isTriviallyConstructible(IType typeToConstruct, IType[] argumentTypes, public static boolean isConstructible(IType typeToConstruct, IType[] argumentTypes,
IBinding pointOfDefinition) { IBinding pointOfDefinition, boolean checkTrivial) {
IType type = SemanticUtil.getSimplifiedType(typeToConstruct); IType type = SemanticUtil.getSimplifiedType(typeToConstruct);
if (!(type instanceof ICPPClassType)) { if (!(type instanceof ICPPClassType)) {
return true; return true;
@ -586,7 +589,13 @@ public class TypeTraits {
} }
EvalTypeId eval = new EvalTypeId(type, pointOfDefinition, false, false, arguments); EvalTypeId eval = new EvalTypeId(type, pointOfDefinition, false, false, arguments);
ICPPFunction constructor = eval.getConstructor(); ICPPFunction constructor = eval.getConstructor();
if (!(constructor instanceof ICPPMethod)) {
return false;
}
// TODO check that conversions are trivial as well // TODO check that conversions are trivial as well
return constructor instanceof ICPPMethod && ((ICPPMethod) constructor).isImplicit(); if (checkTrivial && !((ICPPMethod) constructor).isImplicit()) {
return false;
}
return true;
} }
} }

View file

@ -2206,7 +2206,7 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
addTypeTraitPrimitive("is_abstract", GCCKeywords.cp__is_abstract); addTypeTraitPrimitive("is_abstract", GCCKeywords.cp__is_abstract);
addTypeTraitPrimitive("is_base_of", GCCKeywords.cp__is_base_of); addTypeTraitPrimitive("is_base_of", GCCKeywords.cp__is_base_of);
addTypeTraitPrimitive("is_class", GCCKeywords.cp__is_class); addTypeTraitPrimitive("is_class", GCCKeywords.cp__is_class);
// missing: is_constructible addTypeTraitPrimitive("is_constructible", GCCKeywords.cp__is_constructible);
// missing: is_convertible_to // missing: is_convertible_to
// missing: is_destructible // missing: is_destructible
addTypeTraitPrimitive("is_empty", GCCKeywords.cp__is_empty); addTypeTraitPrimitive("is_empty", GCCKeywords.cp__is_empty);