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:
parent
14afc9f4f4
commit
33c2e373d4
3 changed files with 48 additions and 22 deletions
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Add table
Reference in a new issue