1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-06-07 17:56: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); IType unwindedType = CxxAstUtils.getInstance().unwindTypedef(typeToCheck);
if (unwindedType instanceof ICPPClassType) { if (unwindedType instanceof ICPPClassType) {
ICPPClassType classType = (ICPPClassType) unwindedType; ICPPClassType classType = (ICPPClassType) unwindedType;
ICPPMethod[] pureVirtualMethods; ICPPMethod[] pureVirtualMethods = pureVirtualMethodsCache.get(classType);
if (pureVirtualMethodsCache.containsKey(classType)) { if (pureVirtualMethods == null) {
pureVirtualMethods = pureVirtualMethodsCache.get(classType);
} else {
pureVirtualMethods = ClassTypeHelper.getPureVirtualMethods(classType); pureVirtualMethods = ClassTypeHelper.getPureVirtualMethods(classType);
pureVirtualMethodsCache.put(classType, pureVirtualMethods); pureVirtualMethodsCache.put(classType, pureVirtualMethods);
} }

View file

@ -240,7 +240,21 @@ public class AbstractClassInstantiationCheckerTest extends CheckerTestCase {
// }; // };
// //
// B b; // 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()); loadCodeAndRun(getAboveComment());
checkNoErrors(); checkNoErrors();
} }

View file

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