1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-06-06 01:06:01 +02:00

Bug 353360 - Bogus "type must implement the inherited pure virtual

method" error. Fix and test case.
This commit is contained in:
Sergey Prigogin 2011-07-30 22:59:14 -07:00
parent 14afc9f4f4
commit 33c2e373d4
3 changed files with 48 additions and 22 deletions

View file

@ -186,10 +186,8 @@ public class AbstractClassInstantiationChecker extends AbstractIndexAstChecker {
IType unwindedType = CxxAstUtils.getInstance().unwindTypedef(typeToCheck);
if (unwindedType instanceof ICPPClassType) {
ICPPClassType classType = (ICPPClassType) unwindedType;
ICPPMethod[] pureVirtualMethods;
if (pureVirtualMethodsCache.containsKey(classType)) {
pureVirtualMethods = pureVirtualMethodsCache.get(classType);
} else {
ICPPMethod[] pureVirtualMethods = pureVirtualMethodsCache.get(classType);
if (pureVirtualMethods == null) {
pureVirtualMethods = ClassTypeHelper.getPureVirtualMethods(classType);
pureVirtualMethodsCache.put(classType, pureVirtualMethods);
}

View file

@ -240,7 +240,21 @@ public class AbstractClassInstantiationCheckerTest extends CheckerTestCase {
// };
//
// B b;
public void testPureVirtualDestructorOverride() {
public void testPureVirtualDestructorOverride_1() {
loadCodeAndRun(getAboveComment());
checkNoErrors();
}
// class A {
// public:
// virtual ~A() = 0;
// };
//
// class B : public A {
// };
//
// B b;
public void testPureVirtualDestructorOverride_2() {
loadCodeAndRun(getAboveComment());
checkNoErrors();
}

View file

@ -76,10 +76,12 @@ import org.eclipse.core.runtime.CoreException;
* Holds common implementation of methods for ICPPClassType implementations that have
* a corresponding textual definition in the source code.
*
* @see CPPClassType
* @see CPPClassTemplate
* @see CPPClassType
* @see CPPClassTemplate
*/
public class ClassTypeHelper {
private static final String DESTRUCTOR_OVERRIDE_KEY = "~"; //$NON-NLS-1$
public static IBinding[] getFriends(ICPPInternalClassTypeMixinHost host) {
if (host.getDefinition() == null) {
host.checkForDefinition();
@ -292,10 +294,7 @@ public class ClassTypeHelper {
}
public static ICPPMethod[] getMethods(ICPPClassType ct) {
ObjectSet<ICPPMethod> set= new ObjectSet<ICPPMethod>(4);
set.addAll(ct.getDeclaredMethods());
ICPPClassScope scope= (ICPPClassScope) ct.getCompositeScope();
set.addAll(scope.getImplicitMethods());
ObjectSet<ICPPMethod> set = getOwnMethods(ct);
ICPPClassType[] bases= getAllBases(ct);
for (ICPPClassType base : bases) {
@ -307,6 +306,20 @@ public class ClassTypeHelper {
}
return set.keyArray(ICPPMethod.class);
}
/**
* Returns methods either declared by the given class or generated by the compiler. Does not
* include methods declared in base classes.
* @param classType
* @return
*/
private static ObjectSet<ICPPMethod> getOwnMethods(ICPPClassType classType) {
ObjectSet<ICPPMethod> set= new ObjectSet<ICPPMethod>(4);
set.addAll(classType.getDeclaredMethods());
ICPPClassScope scope= (ICPPClassScope) classType.getCompositeScope();
set.addAll(scope.getImplicitMethods());
return set;
}
public static ICPPMethod[] getDeclaredMethods(ICPPInternalClassTypeMixinHost host) {
if (host.getDefinition() == null) {
@ -745,7 +758,7 @@ public class ClassTypeHelper {
}
private static ICPPMethod getMethodInClass(ICPPClassType ct, int kind) {
switch(kind) {
switch (kind) {
case KIND_DEFAULT_CTOR:
case KIND_COPY_CTOR:
for (ICPPConstructor ctor : ct.getConstructors()) {
@ -805,8 +818,8 @@ public class ClassTypeHelper {
* but doesn't take into account base classes and methods dependent on unspecified
* template parameters.
*/
public static ICPPMethod[] getPureVirtualMethods(ICPPClassType classTarget) {
Collection<Set<ICPPMethod>> result = collectPureVirtualMethods(classTarget).values();
public static ICPPMethod[] getPureVirtualMethods(ICPPClassType classType) {
Collection<Set<ICPPMethod>> result = collectPureVirtualMethods(classType).values();
int resultArraySize = 0;
for (Set<ICPPMethod> set : result) {
resultArraySize += set.size();
@ -825,7 +838,7 @@ public class ClassTypeHelper {
private static String getMethodNameForOverrideKey(ICPPMethod method) {
if (method.isDestructor()) {
// Destructor's names may differ but they will override each other.
return "~"; //$NON-NLS-1$
return DESTRUCTOR_OVERRIDE_KEY;
} else {
return method.getName();
}
@ -834,13 +847,13 @@ public class ClassTypeHelper {
/**
* Returns pure virtual methods of the given class grouped by their names.
*
* @param classTarget The class to obtain the pure virtual method for.
* @param classType The class to obtain the pure virtual method for.
* @return pure virtual methods grouped by their names.
*/
private static Map<String, Set<ICPPMethod> > collectPureVirtualMethods(ICPPClassType classTarget) {
private static Map<String, Set<ICPPMethod> > collectPureVirtualMethods(ICPPClassType classType) {
// Collect pure virtual functions from base classes
Map<String, Set<ICPPMethod>> pureVirtualMethods = new HashMap<String, Set<ICPPMethod>>();
for (ICPPBase base : classTarget.getBases()) {
for (ICPPBase base : classType.getBases()) {
if (base.getBaseClass() instanceof ICPPClassType) {
ICPPClassType baseClass = (ICPPClassType) base.getBaseClass();
Map<String, Set<ICPPMethod> > derivedPureVirtualMethods = collectPureVirtualMethods(baseClass);
@ -849,15 +862,15 @@ public class ClassTypeHelper {
Set<ICPPMethod> methodsSet = pureVirtualMethods.get(currMethodEntry.getKey());
if (methodsSet == null) {
pureVirtualMethods.put(currMethodEntry.getKey(), currMethodEntry.getValue());
}
else {
} else {
methodsSet.addAll(currMethodEntry.getValue());
}
}
}
}
// Remove overridden methods (even if they are pure virtual)
for (ICPPMethod declaredMethod : classTarget.getDeclaredMethods()) {
for (ICPPMethod declaredMethod : getOwnMethods(classType).toList()) {
Set<ICPPMethod> methodsSet = pureVirtualMethods.get(getMethodNameForOverrideKey(declaredMethod));
if (methodsSet != null) {
for (Iterator<ICPPMethod> methodIt = methodsSet.iterator(); methodIt.hasNext();) {
@ -871,8 +884,9 @@ public class ClassTypeHelper {
}
}
}
// Add pure virtual methods of current class
for (ICPPMethod method : classTarget.getDeclaredMethods()) {
for (ICPPMethod method : classType.getDeclaredMethods()) {
if (method.isPureVirtual()) {
Set<ICPPMethod> methodsSet = pureVirtualMethods.get(getMethodNameForOverrideKey(method));
if (methodsSet == null) {