diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/TypeTraitsTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/TypeTraitsTests.java index d5f86ac1d6d..703d0318beb 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/TypeTraitsTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/TypeTraitsTests.java @@ -13,6 +13,7 @@ package org.eclipse.cdt.core.parser.tests.ast2; import java.io.IOException; import org.eclipse.cdt.core.dom.ast.IType; +import org.eclipse.cdt.core.dom.ast.IVariable; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.TypeTraits; import org.eclipse.cdt.internal.core.parser.ParserException; @@ -292,4 +293,36 @@ public class TypeTraitsTests extends AST2TestBase { ICPPClassType classI = helper.assertNonProblemOnFirstIdentifier("I {"); assertFalse(TypeTraits.isTrivial(classI, null)); } + + // int a; + // char* const b; + // void* volatile c; + // char* const d[42]; + // enum E {} e; + // struct F { + // int x, y; + // F(); + // } f; + // struct G { + // int x, y; + // G(); + // G(const G&); + // } g; + public void testIsTriviallyCopyable() throws Exception { + BindingAssertionHelper helper = getAssertionHelper(); + IVariable a = helper.assertNonProblemOnFirstIdentifier("a;"); + assertTrue(TypeTraits.isTriviallyCopyable(a.getType(), null)); + IVariable b = helper.assertNonProblemOnFirstIdentifier("b;"); + assertTrue(TypeTraits.isTriviallyCopyable(b.getType(), null)); + IVariable c = helper.assertNonProblemOnFirstIdentifier("c;"); + assertFalse(TypeTraits.isTriviallyCopyable(c.getType(), null)); + IVariable d = helper.assertNonProblemOnFirstIdentifier("d["); + assertTrue(TypeTraits.isTriviallyCopyable(d.getType(), null)); + IVariable e = helper.assertNonProblemOnFirstIdentifier("e;"); + assertTrue(TypeTraits.isTriviallyCopyable(e.getType(), null)); + IVariable f = helper.assertNonProblemOnFirstIdentifier("f;"); + assertTrue(TypeTraits.isTriviallyCopyable(f.getType(), null)); + IVariable g = helper.assertNonProblemOnFirstIdentifier("g;"); + assertFalse(TypeTraits.isTriviallyCopyable(g.getType(), null)); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/Value.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/Value.java index ea6b05e58e8..148d97d9fcc 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/Value.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/Value.java @@ -352,7 +352,7 @@ public class Value implements IValue { return type instanceof ICPPClassType && TypeTraits.isTrivial((ICPPClassType) type, point) ? 1 : 0; case op_is_trivially_copyable: - break; // TODO: Implement + return TypeTraits.isTriviallyCopyable(type, point) ? 1 : 0; case op_is_union: return type instanceof ICompositeType && ((ICompositeType) type).getKey() == ICompositeType.k_union ? 1 : 0; 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 43d08a51c5c..504c3565a58 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,7 +15,10 @@ 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.IArrayType; import org.eclipse.cdt.core.dom.ast.IBasicType; +import org.eclipse.cdt.core.dom.ast.IEnumeration; +import org.eclipse.cdt.core.dom.ast.IPointerType; 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; @@ -58,11 +61,20 @@ public class TypeTraits { * C++11: 9-6 */ public static boolean isTrivial(ICPPClassType classType, IASTNode point) { + return isTrivialImpl(classType, point, true); + } + + private static boolean isTrivialImpl(ICPPClassType classType, IASTNode point, + boolean checkDefaultConstructors) { for (ICPPMethod method : ClassTypeHelper.getDeclaredMethods(classType, point)) { if (method.isVirtual()) return false; switch (ClassTypeHelper.getMethodKind(classType, method)) { case DEFAULT_CTOR: + if (checkDefaultConstructors) { + return false; + } + break; case COPY_CTOR: case MOVE_CTOR: case COPY_ASSIGNMENT_OP: @@ -432,4 +444,53 @@ public class TypeTraits { } return types[types.length - 1]; // Assume it fits into the largest type provided. } + + /** + * Returns true if 'type' is scalar, as defined in [basic.types] p9: + * + * "Arithmetic types, enumeration types, pointer types, pointer to member + * types, std::nullptr_t, and cv-qualified versions of these types are + * collectively called scalar types." + */ + private static boolean isScalar(IType type) { + type = SemanticUtil.getNestedType(type, SemanticUtil.ALLCVQ); + return type instanceof IBasicType || type instanceof IEnumeration || type instanceof IPointerType; + } + + /** + * Returns true if 'type' is a trivially copyable class, as defined in [class] p6: + * + * "A trivially copyable class is a class that: + * - has no non-trivial copy constructors, + * - has no non-trivial move constructors, + * - has no non-trivial copy assignment operators, + * - has no non-trivial move assignment operators, and + * - has a trivial destructor." + */ + private static boolean isTriviallyCopyableClass(ICPPClassType type, IASTNode point) { + return isTrivialImpl(type, point, false); + } + + /** + * Returns true if 'type' is trivially copyable, as defined in [basic.types] p9: + * + * "Cv-unqualified scalar types, trivially copyable class types, arrays + * of such types, and non-volatile const-qualified versions of these + * types are collectively called trivially copyable types." + */ + public static boolean isTriviallyCopyable(IType type, IASTNode point) { + type = SemanticUtil.getSimplifiedType(type); + CVQualifier qualifier = SemanticUtil.getCVQualifier(type); + if (qualifier.isVolatile()) { + return false; + } else if (qualifier.isConst()) { + return isTriviallyCopyable(SemanticUtil.getNestedType(type, SemanticUtil.ALLCVQ), point); + } else if (type instanceof IArrayType) { + return isTriviallyCopyable(((IArrayType) type).getType(), point); + } else if (type instanceof ICPPClassType) { + return isTriviallyCopyableClass((ICPPClassType) type, point); + } else { + return isScalar(type); + } + } }