1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-23 17:05:26 +02:00

Bug 539052 - Add support for __is_constructible type trait intrinsic

Change-Id: I582881808e19342bf55d62d6002365c3733ebf31
This commit is contained in:
Nathan Ridge 2018-09-15 14:14:04 -04:00
parent 9d84c30b5a
commit 7831931f3a
11 changed files with 53 additions and 9 deletions

View file

@ -12677,6 +12677,18 @@ public class AST2CPPTests extends AST2CPPTestBase {
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 {
// void foo();
// }

View file

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

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 enum Operator {
__is_trivially_constructible
__is_trivially_constructible,
/** @since 6.6 */ __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_7 = version(4, 7);
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_4_2= new GPPScannerExtensionConfiguration(VERSION_4_2);
private static GPPScannerExtensionConfiguration CONFIG_4_3= new GPPScannerExtensionConfiguration(VERSION_4_3);
private static GPPScannerExtensionConfiguration CONFIG_4_6= new GPPScannerExtensionConfiguration(VERSION_4_6);
private static GPPScannerExtensionConfiguration CONFIG_4_7= new GPPScannerExtensionConfiguration(VERSION_4_7);
private static GPPScannerExtensionConfiguration CONFIG_5_0= new GPPScannerExtensionConfiguration(VERSION_5_0);
private static GPPScannerExtensionConfiguration CONFIG_8_0= new GPPScannerExtensionConfiguration(VERSION_8_0);
private static GPPScannerExtensionConfiguration CONFIG_CLANG=
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 minor= Integer.valueOf(definedSymbols.get("__GNUC_MINOR__")); //$NON-NLS-1$
int version= version(major, minor);
if (version >= VERSION_8_0) {
return CONFIG_8_0;
}
if (version >= VERSION_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_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) {
// As documented at
// 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__is_trivially_constructible, IGCCToken.tTT_is_trivially_constructible);
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_constructible= "__is_trivially_constructible".toCharArray(),
cp__is_trivially_assignable= "__is_trivially_assignable".toCharArray();
/** @since 6.6 */
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_constructible= FIRST_RESERVED_IGCCToken + 33;
/** @since 6.0 */ int tTT_is_trivially_assignable= FIRST_RESERVED_IGCCToken + 34;
/** @since 6.6 */ int tTT_is_constructible= FIRST_RESERVED_IGCCToken + 35;
}

View file

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

View file

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

View file

@ -88,6 +88,7 @@ public class EvalNaryTypeId extends CPPDependentEvaluation {
public IType getType() {
switch (fOperator) {
case __is_trivially_constructible:
case __is_constructible:
return CPPBasicType.BOOLEAN;
}
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].
*
* If 'checkTrivial' is true, additionally checks if 'typeToConstruct'
* is trivially constructible from said argument types.
*/
public static boolean isTriviallyConstructible(IType typeToConstruct, IType[] argumentTypes,
IBinding pointOfDefinition) {
public static boolean isConstructible(IType typeToConstruct, IType[] argumentTypes,
IBinding pointOfDefinition, boolean checkTrivial) {
IType type = SemanticUtil.getSimplifiedType(typeToConstruct);
if (!(type instanceof ICPPClassType)) {
return true;
@ -586,7 +589,13 @@ public class TypeTraits {
}
EvalTypeId eval = new EvalTypeId(type, pointOfDefinition, false, false, arguments);
ICPPFunction constructor = eval.getConstructor();
if (!(constructor instanceof ICPPMethod)) {
return false;
}
// 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_base_of", GCCKeywords.cp__is_base_of);
addTypeTraitPrimitive("is_class", GCCKeywords.cp__is_class);
// missing: is_constructible
addTypeTraitPrimitive("is_constructible", GCCKeywords.cp__is_constructible);
// missing: is_convertible_to
// missing: is_destructible
addTypeTraitPrimitive("is_empty", GCCKeywords.cp__is_empty);