mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-08-17 21:25:58 +02:00
Added few methods to ClassTypeHelper and tests for them.
This commit is contained in:
parent
94a3430cf2
commit
29762a2885
3 changed files with 277 additions and 31 deletions
|
@ -0,0 +1,123 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2010 Google, Inc 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:
|
||||||
|
* Sergey Prigogin (Google) - initial API and implementation
|
||||||
|
*******************************************************************************/
|
||||||
|
package org.eclipse.cdt.core.parser.tests.ast2;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import junit.framework.TestSuite;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
|
||||||
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.ClassTypeHelper;
|
||||||
|
import org.eclipse.cdt.internal.core.parser.ParserException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests for ClassTypeHelper class.
|
||||||
|
*/
|
||||||
|
public class ClassTypeHelperTests extends AST2BaseTest {
|
||||||
|
|
||||||
|
public ClassTypeHelperTests() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public ClassTypeHelperTests(String name) {
|
||||||
|
super(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TestSuite suite() {
|
||||||
|
return suite(ClassTypeHelperTests.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected BindingAssertionHelper getAssertionHelper() throws ParserException, IOException {
|
||||||
|
String code= getAboveComment();
|
||||||
|
return new BindingAssertionHelper(code, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// class A {
|
||||||
|
// public:
|
||||||
|
// A();
|
||||||
|
// int x;
|
||||||
|
// A* y;
|
||||||
|
// const A& z;
|
||||||
|
// };
|
||||||
|
public void testHasTrivialCopyCtor_1() throws Exception {
|
||||||
|
BindingAssertionHelper helper = getAssertionHelper();
|
||||||
|
ICPPClassType classType = helper.assertNonProblem("A {", 1, ICPPClassType.class);
|
||||||
|
assertTrue(ClassTypeHelper.hasTrivialCopyCtor(classType));
|
||||||
|
}
|
||||||
|
|
||||||
|
// struct A {
|
||||||
|
// A(const A& a);
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
// class B {
|
||||||
|
// public:
|
||||||
|
// A a;
|
||||||
|
// };
|
||||||
|
public void testHasTrivialCopyCtor_2() throws Exception {
|
||||||
|
BindingAssertionHelper helper = getAssertionHelper();
|
||||||
|
ICPPClassType classType = helper.assertNonProblem("B {", 1, ICPPClassType.class);
|
||||||
|
assertFalse(ClassTypeHelper.hasTrivialCopyCtor(classType));
|
||||||
|
}
|
||||||
|
|
||||||
|
// class A {
|
||||||
|
// public:
|
||||||
|
// A();
|
||||||
|
// A(const A& a);
|
||||||
|
// int x;
|
||||||
|
// A* y;
|
||||||
|
// const A& z;
|
||||||
|
// };
|
||||||
|
public void testHasTrivialDesctructor_1() throws Exception {
|
||||||
|
BindingAssertionHelper helper = getAssertionHelper();
|
||||||
|
ICPPClassType classType = helper.assertNonProblem("A {", 1, ICPPClassType.class);
|
||||||
|
assertTrue(ClassTypeHelper.hasTrivialDestructor(classType));
|
||||||
|
}
|
||||||
|
|
||||||
|
// struct A {
|
||||||
|
// ~A();
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
// class B {
|
||||||
|
// public:
|
||||||
|
// A a;
|
||||||
|
// };
|
||||||
|
public void testHasTrivialDesctructor_2() throws Exception {
|
||||||
|
BindingAssertionHelper helper = getAssertionHelper();
|
||||||
|
ICPPClassType classType = helper.assertNonProblem("B {", 1, ICPPClassType.class);
|
||||||
|
assertFalse(ClassTypeHelper.hasTrivialDestructor(classType));
|
||||||
|
}
|
||||||
|
|
||||||
|
// class A {
|
||||||
|
// public:
|
||||||
|
// A();
|
||||||
|
// A(const A& a);
|
||||||
|
// void m();
|
||||||
|
// int x;
|
||||||
|
// A* y;
|
||||||
|
// const A& z;
|
||||||
|
// };
|
||||||
|
public void testIsPolymorphic_1() throws Exception {
|
||||||
|
BindingAssertionHelper helper = getAssertionHelper();
|
||||||
|
ICPPClassType classType = helper.assertNonProblem("A {", 1, ICPPClassType.class);
|
||||||
|
assertFalse(ClassTypeHelper.isPolymorphic(classType));
|
||||||
|
}
|
||||||
|
|
||||||
|
// struct A {
|
||||||
|
// virtual void m();
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
// class B : public A {
|
||||||
|
// };
|
||||||
|
public void testIsPolymorphic_2() throws Exception {
|
||||||
|
BindingAssertionHelper helper = getAssertionHelper();
|
||||||
|
ICPPClassType classType = helper.assertNonProblem("B", 1, ICPPClassType.class);
|
||||||
|
assertTrue(ClassTypeHelper.isPolymorphic(classType));
|
||||||
|
}
|
||||||
|
}
|
|
@ -30,6 +30,7 @@ public class DOMParserTestSuite extends TestCase {
|
||||||
suite.addTest(ASTCPPSpecDefectTests.suite());
|
suite.addTest(ASTCPPSpecDefectTests.suite());
|
||||||
suite.addTest(AST2CPPImplicitNameTests.suite());
|
suite.addTest(AST2CPPImplicitNameTests.suite());
|
||||||
suite.addTest(AST2TemplateTests.suite());
|
suite.addTest(AST2TemplateTests.suite());
|
||||||
|
suite.addTest(ClassTypeHelperTests.suite());
|
||||||
suite.addTestSuite(QuickParser2Tests.class);
|
suite.addTestSuite(QuickParser2Tests.class);
|
||||||
suite.addTest(CompleteParser2Tests.suite());
|
suite.addTest(CompleteParser2Tests.suite());
|
||||||
suite.addTest(DOMLocationTests.suite());
|
suite.addTest(DOMLocationTests.suite());
|
||||||
|
|
|
@ -15,6 +15,10 @@
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.internal.core.dom.parser.cpp;
|
package org.eclipse.cdt.internal.core.dom.parser.cpp;
|
||||||
|
|
||||||
|
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.ARRAY;
|
||||||
|
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.CVTYPE;
|
||||||
|
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.TDEF;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
@ -180,7 +184,7 @@ public class ClassTypeHelper {
|
||||||
ICPPClassType backup= getBackupDefinition(host);
|
ICPPClassType backup= getBackupDefinition(host);
|
||||||
if (backup != null)
|
if (backup != null)
|
||||||
return backup.getBases();
|
return backup.getBases();
|
||||||
|
|
||||||
return ICPPBase.EMPTY_BASE_ARRAY;
|
return ICPPBase.EMPTY_BASE_ARRAY;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -203,7 +207,7 @@ public class ClassTypeHelper {
|
||||||
ICPPClassType backup= getBackupDefinition(host);
|
ICPPClassType backup= getBackupDefinition(host);
|
||||||
if (backup != null)
|
if (backup != null)
|
||||||
return backup.getDeclaredFields();
|
return backup.getDeclaredFields();
|
||||||
|
|
||||||
return ICPPField.EMPTY_CPPFIELD_ARRAY;
|
return ICPPField.EMPTY_CPPFIELD_ARRAY;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -235,7 +239,7 @@ public class ClassTypeHelper {
|
||||||
}
|
}
|
||||||
return (ICPPField[]) ArrayUtil.trim(ICPPField.class, result);
|
return (ICPPField[]) ArrayUtil.trim(ICPPField.class, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns all direct and indirect base classes.
|
* Returns all direct and indirect base classes.
|
||||||
* @param classType a class
|
* @param classType a class
|
||||||
|
@ -248,7 +252,7 @@ public class ClassTypeHelper {
|
||||||
result.remove(classType);
|
result.remove(classType);
|
||||||
return result.toArray(new ICPPClassType[result.size()]);
|
return result.toArray(new ICPPClassType[result.size()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void getAllBases(ICPPClassType classType, HashSet<ICPPClassType> result) {
|
private static void getAllBases(ICPPClassType classType, HashSet<ICPPClassType> result) {
|
||||||
ICPPBase[] bases= classType.getBases();
|
ICPPBase[] bases= classType.getBases();
|
||||||
for (ICPPBase base : bases) {
|
for (ICPPBase base : bases) {
|
||||||
|
@ -291,10 +295,10 @@ public class ClassTypeHelper {
|
||||||
}
|
}
|
||||||
return (ICPPMethod[]) ArrayUtil.trim(ICPPMethod.class, methods);
|
return (ICPPMethod[]) ArrayUtil.trim(ICPPMethod.class, methods);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ICPPMethod[] getMethods(ICPPClassType ct) {
|
public static ICPPMethod[] getMethods(ICPPClassType ct) {
|
||||||
ObjectSet<ICPPMethod> set = getOwnMethods(ct);
|
ObjectSet<ICPPMethod> set = getOwnMethods(ct);
|
||||||
|
|
||||||
ICPPClassType[] bases= getAllBases(ct);
|
ICPPClassType[] bases= getAllBases(ct);
|
||||||
for (ICPPClassType base : bases) {
|
for (ICPPClassType base : bases) {
|
||||||
set.addAll(base.getDeclaredMethods());
|
set.addAll(base.getDeclaredMethods());
|
||||||
|
@ -319,7 +323,7 @@ public class ClassTypeHelper {
|
||||||
}
|
}
|
||||||
return set;
|
return set;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ICPPMethod[] getDeclaredMethods(ICPPInternalClassTypeMixinHost host) {
|
public static ICPPMethod[] getDeclaredMethods(ICPPInternalClassTypeMixinHost host) {
|
||||||
if (host.getDefinition() == null) {
|
if (host.getDefinition() == null) {
|
||||||
host.checkForDefinition();
|
host.checkForDefinition();
|
||||||
|
@ -393,7 +397,7 @@ public class ClassTypeHelper {
|
||||||
ICPPClassType backup= getBackupDefinition(host);
|
ICPPClassType backup= getBackupDefinition(host);
|
||||||
if (backup != null)
|
if (backup != null)
|
||||||
return backup.getNestedClasses();
|
return backup.getNestedClasses();
|
||||||
|
|
||||||
return ICPPClassType.EMPTY_CLASS_ARRAY;
|
return ICPPClassType.EMPTY_CLASS_ARRAY;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -445,18 +449,17 @@ public class ClassTypeHelper {
|
||||||
}
|
}
|
||||||
return field;
|
return field;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether {@code method} is virtual. This is the case if it is declared to be virtual or
|
* Returns whether {@code method} is virtual. This is the case if it is declared to be virtual
|
||||||
* overrides another virtual method.
|
* or overrides another virtual method.
|
||||||
*/
|
*/
|
||||||
public static boolean isVirtual(ICPPMethod m) {
|
public static boolean isVirtual(ICPPMethod m) {
|
||||||
if (m instanceof ICPPConstructor)
|
if (m instanceof ICPPConstructor)
|
||||||
return false;
|
return false;
|
||||||
if (m.isVirtual())
|
if (m.isVirtual())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
final char[] mname= m.getNameCharArray();
|
final char[] mname= m.getNameCharArray();
|
||||||
final ICPPClassType mcl= m.getClassOwner();
|
final ICPPClassType mcl= m.getClassOwner();
|
||||||
if (mcl != null) {
|
if (mcl != null) {
|
||||||
|
@ -511,18 +514,18 @@ public class ClassTypeHelper {
|
||||||
return false;
|
return false;
|
||||||
if (!functionTypesAllowOverride(source.getType(), target.getType()))
|
if (!functionTypesAllowOverride(source.getType(), target.getType()))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
final ICPPClassType sourceClass= source.getClassOwner();
|
final ICPPClassType sourceClass= source.getClassOwner();
|
||||||
final ICPPClassType targetClass= target.getClassOwner();
|
final ICPPClassType targetClass= target.getClassOwner();
|
||||||
if (sourceClass == null || targetClass == null)
|
if (sourceClass == null || targetClass == null)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
ICPPClassType[] bases= getAllBases(sourceClass);
|
ICPPClassType[] bases= getAllBases(sourceClass);
|
||||||
for (ICPPClassType base : bases) {
|
for (ICPPClassType base : bases) {
|
||||||
if (base.isSameType(targetClass))
|
if (base.isSameType(targetClass))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -532,12 +535,12 @@ public class ClassTypeHelper {
|
||||||
public static ICPPMethod[] findOverridden(ICPPMethod method) {
|
public static ICPPMethod[] findOverridden(ICPPMethod method) {
|
||||||
if (method instanceof ICPPConstructor)
|
if (method instanceof ICPPConstructor)
|
||||||
return ICPPMethod.EMPTY_CPPMETHOD_ARRAY;
|
return ICPPMethod.EMPTY_CPPMETHOD_ARRAY;
|
||||||
|
|
||||||
final char[] mname= method.getNameCharArray();
|
final char[] mname= method.getNameCharArray();
|
||||||
final ICPPClassType mcl= method.getClassOwner();
|
final ICPPClassType mcl= method.getClassOwner();
|
||||||
if (mcl == null)
|
if (mcl == null)
|
||||||
return ICPPMethod.EMPTY_CPPMETHOD_ARRAY;
|
return ICPPMethod.EMPTY_CPPMETHOD_ARRAY;
|
||||||
|
|
||||||
final ArrayList<ICPPMethod> result= new ArrayList<ICPPMethod>();
|
final ArrayList<ICPPMethod> result= new ArrayList<ICPPMethod>();
|
||||||
final HashMap<ICPPClassType, Boolean> virtualInClass= new HashMap<ICPPClassType, Boolean>();
|
final HashMap<ICPPClassType, Boolean> virtualInClass= new HashMap<ICPPClassType, Boolean>();
|
||||||
final ICPPFunctionType mft= method.getType();
|
final ICPPFunctionType mft= method.getType();
|
||||||
|
@ -550,7 +553,7 @@ public class ClassTypeHelper {
|
||||||
findOverridden((ICPPClassType) b, mname, mft, virtualInClass, result);
|
findOverridden((ICPPClassType) b, mname, mft, virtualInClass, result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// list is filled from most derived up to here, reverse it
|
// list is filled from most derived up to here, reverse it
|
||||||
Collections.reverse(result);
|
Collections.reverse(result);
|
||||||
return result.toArray(new ICPPMethod[result.size()]);
|
return result.toArray(new ICPPMethod[result.size()]);
|
||||||
|
@ -567,7 +570,7 @@ public class ClassTypeHelper {
|
||||||
Boolean visitedBefore= virtualInClass.get(cl);
|
Boolean visitedBefore= virtualInClass.get(cl);
|
||||||
if (visitedBefore != null)
|
if (visitedBefore != null)
|
||||||
return visitedBefore;
|
return visitedBefore;
|
||||||
|
|
||||||
ICPPMethod[] methods= cl.getDeclaredMethods();
|
ICPPMethod[] methods= cl.getDeclaredMethods();
|
||||||
ICPPMethod candidate= null;
|
ICPPMethod candidate= null;
|
||||||
boolean hasOverridden= false;
|
boolean hasOverridden= false;
|
||||||
|
@ -578,7 +581,7 @@ public class ClassTypeHelper {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// prevent recursion
|
// prevent recursion
|
||||||
virtualInClass.put(cl, hasOverridden);
|
virtualInClass.put(cl, hasOverridden);
|
||||||
ICPPBase[] bases= cl.getBases();
|
ICPPBase[] bases= cl.getBases();
|
||||||
|
@ -610,7 +613,7 @@ public class ClassTypeHelper {
|
||||||
final ICPPClassType mcl= method.getClassOwner();
|
final ICPPClassType mcl= method.getClassOwner();
|
||||||
if (mcl == null)
|
if (mcl == null)
|
||||||
return ICPPMethod.EMPTY_CPPMETHOD_ARRAY;
|
return ICPPMethod.EMPTY_CPPMETHOD_ARRAY;
|
||||||
|
|
||||||
ICPPClassType[] subclasses= getSubClasses(index, mcl);
|
ICPPClassType[] subclasses= getSubClasses(index, mcl);
|
||||||
return findOverriders(subclasses, method);
|
return findOverriders(subclasses, method);
|
||||||
}
|
}
|
||||||
|
@ -645,7 +648,7 @@ public class ClassTypeHelper {
|
||||||
private static void getSubClasses(IIndex index, ICPPBinding classOrTypedef, List<ICPPBinding> result, HashSet<String> handled) throws CoreException {
|
private static void getSubClasses(IIndex index, ICPPBinding classOrTypedef, List<ICPPBinding> result, HashSet<String> handled) throws CoreException {
|
||||||
if (!(classOrTypedef instanceof IType))
|
if (!(classOrTypedef instanceof IType))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
final String key = ASTTypeUtil.getType((IType) classOrTypedef, true);
|
final String key = ASTTypeUtil.getType((IType) classOrTypedef, true);
|
||||||
if (!handled.add(key)) {
|
if (!handled.add(key)) {
|
||||||
return;
|
return;
|
||||||
|
@ -674,7 +677,7 @@ public class ClassTypeHelper {
|
||||||
private static final int KIND_ASSIGNMENT_OP= 2;
|
private static final int KIND_ASSIGNMENT_OP= 2;
|
||||||
private static final int KIND_DTOR= 3;
|
private static final int KIND_DTOR= 3;
|
||||||
private static final int KIND_OTHER= 4;
|
private static final int KIND_OTHER= 4;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For implicit methods the exception specification is inherited, search it
|
* For implicit methods the exception specification is inherited, search it
|
||||||
*/
|
*/
|
||||||
|
@ -688,7 +691,7 @@ public class ClassTypeHelper {
|
||||||
int kind= getImplicitMethodKind(owner, implicitMethod);
|
int kind= getImplicitMethodKind(owner, implicitMethod);
|
||||||
if (kind == KIND_OTHER)
|
if (kind == KIND_OTHER)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
List<IType> inheritedTypeids = new ArrayList<IType>();
|
List<IType> inheritedTypeids = new ArrayList<IType>();
|
||||||
ICPPClassType[] bases= getAllBases(owner);
|
ICPPClassType[] bases= getAllBases(owner);
|
||||||
for (ICPPClassType base : bases) {
|
for (ICPPClassType base : bases) {
|
||||||
|
@ -737,13 +740,13 @@ public class ClassTypeHelper {
|
||||||
}
|
}
|
||||||
return KIND_OTHER;
|
return KIND_OTHER;
|
||||||
}
|
}
|
||||||
return KIND_OTHER;
|
return KIND_OTHER;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isRefToConstClass(ICPPClassType ct, IType t) {
|
private static boolean isRefToConstClass(ICPPClassType ct, IType t) {
|
||||||
while (t instanceof ITypedef)
|
while (t instanceof ITypedef)
|
||||||
t= ((ITypedef) t).getType();
|
t= ((ITypedef) t).getType();
|
||||||
|
|
||||||
if (t instanceof ICPPReferenceType) {
|
if (t instanceof ICPPReferenceType) {
|
||||||
t= ((ICPPReferenceType) t).getType();
|
t= ((ICPPReferenceType) t).getType();
|
||||||
while (t instanceof ITypedef)
|
while (t instanceof ITypedef)
|
||||||
|
@ -809,6 +812,126 @@ public class ClassTypeHelper {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns <code>true</code> if and only if the given class has a trivial copy constructor.
|
||||||
|
* A copy constructor is trivial if:
|
||||||
|
* <ul>
|
||||||
|
* <li>it is implicitly defined by the compiler, and</li>
|
||||||
|
* <li><code>isPolymorphic(classTarget) == false</code>, and</li>
|
||||||
|
* <li>the class has no virtual base classes, and</li>
|
||||||
|
* <li>every direct base class has trivial copy constructor, and</li>
|
||||||
|
* <li>for every nonstatic data member that has class type or array of class type, that type
|
||||||
|
* has trivial copy constructor.</li>
|
||||||
|
* </ul>
|
||||||
|
* Similar to <code>std::tr1::has_trivial_copy</code>.
|
||||||
|
*
|
||||||
|
* @param classTarget the class to check
|
||||||
|
* @return <code>true</code> if the class has a trivial copy constructor
|
||||||
|
*/
|
||||||
|
public static boolean hasTrivialCopyCtor(ICPPClassType classTarget) {
|
||||||
|
if (getImplicitCopyCtor(classTarget) == null)
|
||||||
|
return false;
|
||||||
|
if (isPolymorphic(classTarget))
|
||||||
|
return false;
|
||||||
|
for (ICPPBase base : classTarget.getBases()) {
|
||||||
|
if (base.isVirtual())
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (ICPPClassType baseClass : getAllBases(classTarget)) {
|
||||||
|
if (!classTarget.isSameType(baseClass) && !hasTrivialCopyCtor(baseClass))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (ICPPField field : classTarget.getDeclaredFields()) {
|
||||||
|
if (!field.isStatic()) {
|
||||||
|
IType type = field.getType();
|
||||||
|
type = SemanticUtil.getNestedType(type, TDEF | CVTYPE | ARRAY);
|
||||||
|
if (type instanceof ICPPClassType && !classTarget.isSameType(type) &&
|
||||||
|
!hasTrivialCopyCtor((ICPPClassType) type)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the compiler-generated copy constructor for the given class, or <code>null</code>
|
||||||
|
* if the class doesn't have a compiler-generated copy constructor.
|
||||||
|
*
|
||||||
|
* @param classTarget the class to get the copy ctor for.
|
||||||
|
* @return the compiler-generated copy constructor, or <code>null</code> if the class doesn't
|
||||||
|
* have a compiler-generated copy constructor.
|
||||||
|
*/
|
||||||
|
private static ICPPConstructor getImplicitCopyCtor(ICPPClassType classTarget) {
|
||||||
|
for (ICPPConstructor ctor : classTarget.getConstructors()) {
|
||||||
|
if (ctor.isImplicit() && getImplicitMethodKind(classTarget, ctor) == KIND_COPY_CTOR)
|
||||||
|
return ctor;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns <code>true</code> if and only if the given class has a trivial destructor.
|
||||||
|
* A destructor is trivial if:
|
||||||
|
* <ul>
|
||||||
|
* <li>it is implicitly defined by the compiler, and</li>
|
||||||
|
* <li>every direct base class has trivial destructor, and</li>
|
||||||
|
* <li>for every nonstatic data member that has class type or array of class type, that type
|
||||||
|
* has trivial destructor.</li>
|
||||||
|
* </ul>
|
||||||
|
* Similar to <code>std::tr1::has_trivial_destructor</code>.
|
||||||
|
*
|
||||||
|
* @param classTarget the class to check
|
||||||
|
* @return <code>true</code> if the class has a trivial destructor
|
||||||
|
*/
|
||||||
|
public static boolean hasTrivialDestructor(ICPPClassType classTarget) {
|
||||||
|
for (ICPPMethod method : classTarget.getDeclaredMethods()) {
|
||||||
|
if (method.isDestructor())
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (ICPPClassType baseClass : getAllBases(classTarget)) {
|
||||||
|
if (!classTarget.isSameType(baseClass) && !hasTrivialDestructor(baseClass))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (ICPPField field : classTarget.getDeclaredFields()) {
|
||||||
|
if (!field.isStatic()) {
|
||||||
|
IType type = field.getType();
|
||||||
|
type = SemanticUtil.getNestedType(type, TDEF | CVTYPE | ARRAY);
|
||||||
|
if (type instanceof ICPPClassType && !classTarget.isSameType(type) &&
|
||||||
|
!hasTrivialDestructor((ICPPClassType) type)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns <code>true</code> if and only if the given class declares or inherits a virtual
|
||||||
|
* function. Similar to <code>std::tr1::is_polymorphic</code>.
|
||||||
|
*
|
||||||
|
* @param classTarget the class to check
|
||||||
|
* @return <code>true</code> if the class declares or inherits a virtual function.
|
||||||
|
*/
|
||||||
|
public static boolean isPolymorphic(ICPPClassType classTarget) {
|
||||||
|
if (hasDeclaredVirtualMethod(classTarget))
|
||||||
|
return true;
|
||||||
|
for (ICPPClassType baseClass : getAllBases(classTarget)) {
|
||||||
|
if (hasDeclaredVirtualMethod(baseClass))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean hasDeclaredVirtualMethod(ICPPClassType classTarget) {
|
||||||
|
for (ICPPMethod method : classTarget.getDeclaredMethods()) {
|
||||||
|
if (method.isVirtual()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks whether class is abstract, i.e. has pure virtual functions that were
|
* Checks whether class is abstract, i.e. has pure virtual functions that were
|
||||||
* not implemented in base after declaration.
|
* not implemented in base after declaration.
|
||||||
|
@ -820,7 +943,7 @@ public class ClassTypeHelper {
|
||||||
public static ICPPMethod[] getPureVirtualMethods(ICPPClassType classType) {
|
public static ICPPMethod[] getPureVirtualMethods(ICPPClassType classType) {
|
||||||
Map<String, List<ICPPMethod>> result= collectPureVirtualMethods(classType,
|
Map<String, List<ICPPMethod>> result= collectPureVirtualMethods(classType,
|
||||||
new HashMap<ICPPClassType, Map<String, List<ICPPMethod>>>());
|
new HashMap<ICPPClassType, Map<String, List<ICPPMethod>>>());
|
||||||
|
|
||||||
int resultArraySize = 0;
|
int resultArraySize = 0;
|
||||||
for (List<ICPPMethod> methods : result.values()) {
|
for (List<ICPPMethod> methods : result.values()) {
|
||||||
resultArraySize += methods.size();
|
resultArraySize += methods.size();
|
||||||
|
@ -837,14 +960,13 @@ public class ClassTypeHelper {
|
||||||
|
|
||||||
private static Map<String, List<ICPPMethod>> collectPureVirtualMethods(ICPPClassType classType,
|
private static Map<String, List<ICPPMethod>> collectPureVirtualMethods(ICPPClassType classType,
|
||||||
Map<ICPPClassType, Map<String, List<ICPPMethod>>> cache) {
|
Map<ICPPClassType, Map<String, List<ICPPMethod>>> cache) {
|
||||||
|
|
||||||
Map<String, List<ICPPMethod>> result = cache.get(classType);
|
Map<String, List<ICPPMethod>> result = cache.get(classType);
|
||||||
if (result != null)
|
if (result != null)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
result= new HashMap<String, List<ICPPMethod>>();
|
result= new HashMap<String, List<ICPPMethod>>();
|
||||||
cache.put(classType, result);
|
cache.put(classType, result);
|
||||||
|
|
||||||
// Look at the pure virtual methods of the base classes
|
// Look at the pure virtual methods of the base classes
|
||||||
Set<IBinding> handledBaseClasses= new HashSet<IBinding>();
|
Set<IBinding> handledBaseClasses= new HashSet<IBinding>();
|
||||||
for (ICPPBase base : classType.getBases()) {
|
for (ICPPBase base : classType.getBases()) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue