1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-08-05 07:15:39 +02:00

Bug 383502 - Injected-class-names of different instances of the same

template found in different base classes

Change-Id: I4eed0443e95ca388a771f158ba16ec27298f7afb
Signed-off-by: Nathan Ridge <zeratul976@hotmail.com>
This commit is contained in:
Nathan Ridge 2015-12-29 19:56:57 -05:00
parent 6b58a751bb
commit 2308f972e2
2 changed files with 69 additions and 3 deletions

View file

@ -7825,6 +7825,23 @@ public class AST2CPPTests extends AST2TestBase {
parseAndCheckBindings(); parseAndCheckBindings();
} }
// template<class>
// struct ContainerOf {
// int numParts;
// };
//
// struct HumanPart;
// struct RobotPart;
//
// struct BionicMan : ContainerOf<HumanPart>, ContainerOf<RobotPart> {
// int numRoboParts() {
// return ContainerOf<RobotPart>::numParts;
// }
// };
public void testInheritanceFromMultipleInstancesOfSameTemplate_383502() throws Exception {
parseAndCheckBindings();
}
// int v1; // int v1;
// static int v2; // static int v2;
// extern int v3; // extern int v3;

View file

@ -28,10 +28,13 @@ import org.eclipse.cdt.core.dom.ast.IProblemBinding;
import org.eclipse.cdt.core.dom.ast.IScope; import org.eclipse.cdt.core.dom.ast.IScope;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNameSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNameSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateId;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPBase; import org.eclipse.cdt.core.dom.ast.cpp.ICPPBase;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassScope; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassScope;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMember; import org.eclipse.cdt.core.dom.ast.cpp.ICPPMember;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateDefinition;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateInstance;
import org.eclipse.cdt.core.parser.util.ArrayUtil; import org.eclipse.cdt.core.parser.util.ArrayUtil;
import org.eclipse.cdt.core.parser.util.CharArrayObjectMap; import org.eclipse.cdt.core.parser.util.CharArrayObjectMap;
import org.eclipse.cdt.internal.core.dom.parser.ProblemBinding; import org.eclipse.cdt.internal.core.dom.parser.ProblemBinding;
@ -384,16 +387,62 @@ class BaseClassLookup {
} }
if (numBindingsToAdd < fBindings.length) if (numBindingsToAdd < fBindings.length)
fBindings[numBindingsToAdd] = null; fBindings[numBindingsToAdd] = null;
boolean possibleAmbiguity = false;
if (result.length > 0 && numBindingsToAdd > 0 && data.problem == null) { if (result.length > 0 && numBindingsToAdd > 0 && data.problem == null) {
// Matches are found in more than one base class - this is an indication of ambiguity. // Matches are found in more than one base class - this is usually
data.problem= new ProblemBinding(data.getLookupName(), // an indication of ambiguity (but see below).
IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP, result); possibleAmbiguity = true;
} }
result= ArrayUtil.addAll(result, fBindings); result= ArrayUtil.addAll(result, fBindings);
if (possibleAmbiguity) {
// [temp.local] p4:
// A lookup that finds an injected-class-name can result in an
// ambiguity in certain cases (for example, if it is found in
// more than one base class). If all of the injected-class-names
// that are found refer to specializations of the same class
// template, and if the name is used as a template-name, the
// reference refers to the class template itself and not a
// specialization thereof, and is not ambiguous.
result = collapseInjectedClassNames(data, result);
if (result.length > 1) {
data.problem= new ProblemBinding(data.getLookupName(),
IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP, result);
}
}
for (int i= 0; i < fChildren.size(); i++) { for (int i= 0; i < fChildren.size(); i++) {
BaseClassLookup child = fChildren.get(i); BaseClassLookup child = fChildren.get(i);
result= child.collectResult(data, fVirtual.get(i), result); result= child.collectResult(data, fVirtual.get(i), result);
} }
return result; return result;
} }
// If all bindings in 'result' are instances of the same class template,
// collapse them to the class template itself. Only applies if the lookup
// is for a name used as a template-name.
private IBinding[] collapseInjectedClassNames(LookupData data, IBinding[] result) {
IASTName lookupName = data.getLookupName();
if (lookupName == null || lookupName.getPropertyInParent() != ICPPASTTemplateId.TEMPLATE_NAME) {
// Name not used as a template-name.
return result;
}
ICPPTemplateDefinition template = null;
for (IBinding binding : result) {
if (binding instanceof ICPPClassType && binding instanceof ICPPTemplateInstance) {
ICPPTemplateDefinition specialized =
(ICPPTemplateDefinition) ((ICPPTemplateInstance) binding).getSpecializedBinding();
if (template == null) {
template = specialized;
continue;
}
if (template == specialized) {
continue;
}
}
return result;
}
if (template != null) {
return new IBinding[] { template };
}
return result;
}
} }