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

Fix for AST2TemplateTests.testNestedClassTypeSpecializations, generalizes fix for 213861.

This commit is contained in:
Markus Schorn 2008-05-14 07:11:00 +00:00
parent 1c28b186cf
commit e836c2d3f5
9 changed files with 165 additions and 110 deletions

View file

@ -1166,7 +1166,7 @@ public class AST2TemplateTests extends AST2BaseTest {
// A<int> a;
// a.b.t;
// }
public void _testNestedClassTypeSpecializations() throws Exception {
public void testNestedClassTypeSpecializations() throws Exception {
IASTTranslationUnit tu = parse(getAboveComment(), ParserLanguage.CPP);
CPPNameCollector col = new CPPNameCollector();
tu.accept(col);

View file

@ -1191,4 +1191,22 @@ public class IndexCPPTemplateResolutionTest extends IndexBindingResolutionTestBa
assertInstance(args.keyAt(0), ICPPTemplateNonTypeParameter.class);
assertEquals(1, args.size());
}
// template <class T> class A {
// class B { T t; };
// B b;
// };
// void f() {
// A<int> a;
// a.b.t;
// }
public void testNestedClassTypeSpecializations() throws Exception {
ICPPField t2 = getBindingFromASTName("t;", 1, ICPPField.class);
assertTrue(t2 instanceof ICPPSpecialization);
final IType type = t2.getType();
assertTrue(type instanceof IBasicType);
assertEquals(((IBasicType)type).getType(), IBasicType.t_int);
}
}

View file

@ -39,7 +39,7 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor;
/**
* @author aniefer
*/
public class CPPClassSpecializationScope implements ICPPClassScope, IASTInternalScope {
public class CPPClassSpecializationScope implements ICPPClassSpecializationScope, IASTInternalScope {
private ObjectMap instanceMap = ObjectMap.EMPTY_MAP;
final private ICPPSpecialization specialization;
@ -47,11 +47,11 @@ public class CPPClassSpecializationScope implements ICPPClassScope, IASTInternal
this.specialization = specialization;
}
protected ICPPClassType getOriginalClass() {
public ICPPClassType getOriginalClassType() {
return (ICPPClassType) specialization.getSpecializedBinding();
}
private IBinding getInstance(IBinding binding) {
public IBinding getInstance(IBinding binding) {
if (instanceMap.containsKey(binding)) {
return (IBinding) instanceMap.get(binding);
} else if (!(binding instanceof ICPPClassTemplatePartialSpecialization)) {
@ -162,7 +162,7 @@ public class CPPClassSpecializationScope implements ICPPClassScope, IASTInternal
}
public IScope getParent() throws DOMException {
ICPPClassType cls = getOriginalClass();
ICPPClassType cls = getOriginalClassType();
ICPPClassScope scope = (ICPPClassScope)cls.getCompositeScope();
if (scope != null)
return scope.getParent();
@ -179,7 +179,7 @@ public class CPPClassSpecializationScope implements ICPPClassScope, IASTInternal
}
public boolean isFullyCached() throws DOMException {
ICPPScope origScope = (ICPPScope) getOriginalClass().getCompositeScope();
ICPPScope origScope = (ICPPScope) getOriginalClassType().getCompositeScope();
if (!ASTInternal.isFullyCached(origScope)) {
try {
CPPSemantics.lookupInScope(null, origScope, null);

View file

@ -0,0 +1,27 @@
/*******************************************************************************
* Copyright (c) 2008 Wind River Systems, 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:
* Markus Schorn - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassScope;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
/**
* mstodo
*
* @since 5.0
*/
public interface ICPPClassSpecializationScope extends ICPPClassScope {
ICPPClassType getOriginalClassType();
IBinding getInstance(IBinding original);
}

View file

@ -13,6 +13,8 @@
*******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics;
import java.util.LinkedList;
import org.eclipse.cdt.core.dom.ast.DOMException;
import org.eclipse.cdt.core.dom.ast.IASTCompositeTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier;
@ -108,6 +110,7 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPPointerType;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPTemplateDefinition;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPTemplateTemplateParameter;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPTypedefSpecialization;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPClassSpecializationScope;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPInternalBase;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPInternalBinding;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPInternalClassTemplate;
@ -701,43 +704,6 @@ public class CPPTemplates {
((ICPPFunctionType) type).isVolatile());
}
if (type instanceof ITypedef) {
// Typedef requires special treatment (bug 213861).
final ITypedef typedef = (ITypedef) type;
try {
final IScope scopeOfTypedef= typedef.getScope();
if (scopeOfTypedef instanceof ICPPClassScope) {
if (instantiationScope instanceof ICPPClassScope) {
ICPPClassType owner= ((ICPPClassScope) scopeOfTypedef).getClassType();
IBinding instance= ((ICPPClassScope) instantiationScope).getClassType();
if (instance instanceof ICPPSpecialization) {
instance= ((ICPPSpecialization) instance).getSpecializedBinding();
if (instance instanceof IType && owner.isSameType((IType) instance)) {
return new CPPTypedefSpecialization(typedef, (ICPPScope) instantiationScope, argMap);
}
}
}
// we cannot instantiate a typedef contained in a class without knowing the scope of instantiation.
return type;
}
} catch (DOMException e) {
}
}
if (type instanceof ITypeContainer) {
try {
IType temp = ((ITypeContainer) type).getType();
IType newType = instantiateType(temp, argMap, instantiationScope);
if (newType != temp) {
temp = (IType) type.clone();
((ITypeContainer) temp).setType(newType);
return temp;
}
} catch (DOMException e) {
}
return type;
}
if (type instanceof ICPPTemplateParameter) {
IType t = (IType) argMap.get(type);
if (t != null) {
@ -765,9 +731,73 @@ public class CPPTemplates {
return type;
}
if (type instanceof IBinding &&
(type instanceof ITypedef || type instanceof ICPPClassType)) {
if (instantiationScope instanceof ICPPClassSpecializationScope) {
try {
IBinding instance= instantiateBinding((IBinding) type, (ICPPClassSpecializationScope) instantiationScope);
if (instance instanceof IType) {
return (IType) instance;
}
} catch (DOMException e) {
}
}
return type;
}
if (type instanceof ITypeContainer) {
try {
IType temp = ((ITypeContainer) type).getType();
IType newType = instantiateType(temp, argMap, instantiationScope);
if (newType != temp) {
temp = (IType) type.clone();
((ITypeContainer) temp).setType(newType);
return temp;
}
} catch (DOMException e) {
}
return type;
}
return type;
}
/**
* Instantiates a binding representing a scope by means of the given class specialization scope.
* @throws DOMException
*/
private static IBinding instantiateBinding(final IBinding originalBinding, ICPPClassSpecializationScope instantiationScope) throws DOMException {
ICPPClassType originalClassType= instantiationScope.getOriginalClassType();
IScope scope= originalBinding.getScope();
boolean found= false;
LinkedList<ICPPClassType> classTypes= new LinkedList<ICPPClassType>();
while (scope instanceof ICPPClassScope) {
ICPPClassType ct= ((ICPPClassScope) scope).getClassType();
if (ct.isSameType(originalClassType)) {
found= true;
break;
}
classTypes.add(ct);
scope= scope.getParent();
}
if (!found) {
return originalBinding;
}
while(!classTypes.isEmpty()) {
ICPPClassType ct= classTypes.removeLast();
final IBinding binding= instantiationScope.getInstance(ct);
scope= binding.getScope();
if (scope instanceof ICPPClassSpecializationScope == false) {
return originalBinding;
}
instantiationScope= (ICPPClassSpecializationScope) scope;
}
return instantiationScope.getInstance(originalBinding);
}
/**
* Instantiates types contained in an array.
* @param types an array of types

View file

@ -23,12 +23,13 @@ import org.eclipse.cdt.core.parser.util.ArrayUtil;
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
import org.eclipse.cdt.core.parser.util.ObjectMap;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPClassScope;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPClassSpecializationScope;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPTemplates;
import org.eclipse.cdt.internal.core.index.IIndexFragmentBinding;
import org.eclipse.cdt.internal.core.index.composite.ICompositesFactory;
public class CompositeCPPClassSpecializationScope extends CompositeCPPClassScope {
public class CompositeCPPClassSpecializationScope extends CompositeCPPClassScope implements ICPPClassSpecializationScope {
private ObjectMap instanceMap = ObjectMap.EMPTY_MAP;
public CompositeCPPClassSpecializationScope(ICompositesFactory cf, IIndexFragmentBinding rbinding) {
@ -38,6 +39,11 @@ public class CompositeCPPClassSpecializationScope extends CompositeCPPClassScope
private ICPPSpecialization specialization() {
return (ICPPSpecialization) cf.getCompositeBinding(rbinding);
}
public ICPPClassType getOriginalClassType() {
return (ICPPClassType) specialization().getSpecializedBinding();
}
@Override
public ICPPMethod[] getImplicitMethods() {
@ -67,8 +73,8 @@ public class CompositeCPPClassSpecializationScope extends CompositeCPPClassScope
return null;
IBinding[] specs = new IBinding[0];
for (int i = 0; i < bindings.length; i++) {
specs = (IBinding[]) ArrayUtil.append(IBinding.class, specs, getInstance(bindings[i]));
for (IBinding binding : bindings) {
specs = (IBinding[]) ArrayUtil.append(IBinding.class, specs, getInstance(binding));
}
specs = (IBinding[]) ArrayUtil.trim(IBinding.class, specs);
return CPPSemantics.resolveAmbiguities(name, specs);
@ -91,15 +97,15 @@ public class CompositeCPPClassSpecializationScope extends CompositeCPPClassScope
classScope.getBindings(name, forceResolve, prefixLookup, fileSet) : null;
if (bindings != null) {
for (int i = 0; i < bindings.length; i++) {
result = (IBinding[]) ArrayUtil.append(IBinding.class, result, getInstance(bindings[i]));
for (IBinding binding : bindings) {
result = (IBinding[]) ArrayUtil.append(IBinding.class, result, getInstance(binding));
}
}
return (IBinding[]) ArrayUtil.trim(IBinding.class, result);
}
private IBinding getInstance(IBinding binding) {
public IBinding getInstance(IBinding binding) {
if (instanceMap.containsKey(binding)) {
return (IBinding) instanceMap.get(binding);
} else if (!(binding instanceof ICPPClassTemplatePartialSpecialization)) {

View file

@ -30,7 +30,6 @@ import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.ITypedef;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPBase;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPBinding;
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.ICPPConstructor;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPField;
@ -42,6 +41,7 @@ import org.eclipse.cdt.core.index.IIndexFileSet;
import org.eclipse.cdt.core.parser.util.ArrayUtil;
import org.eclipse.cdt.core.parser.util.ObjectMap;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPClassScope;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPClassSpecializationScope;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPDeferredClassInstance;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPTemplates;
@ -59,7 +59,7 @@ import org.eclipse.core.runtime.CoreException;
* @author Bryan Wilkinson
*/
class PDOMCPPClassInstance extends PDOMCPPInstance implements
ICPPClassType, ICPPClassScope, IPDOMMemberOwner, IIndexType, IIndexScope {
ICPPClassType, ICPPClassSpecializationScope, IPDOMMemberOwner, IIndexType, IIndexScope {
private static final int MEMBERLIST = PDOMCPPInstance.RECORD_SIZE + 0;
@ -88,6 +88,10 @@ class PDOMCPPClassInstance extends PDOMCPPInstance implements
return IIndexCPPBindingConstants.CPP_CLASS_INSTANCE;
}
public ICPPClassType getOriginalClassType() {
return (ICPPClassType) getSpecializedBinding();
}
public ICPPBase[] getBases() throws DOMException {
return CPPTemplates.getBases(this);
}
@ -279,6 +283,18 @@ class PDOMCPPClassInstance extends PDOMCPPInstance implements
return (IBinding[]) ArrayUtil.trim(IBinding.class, result);
}
public IBinding getInstance(IBinding original) {
SpecializationFinder visitor = new SpecializationFinder(new IBinding[] {original});
try {
accept(visitor);
return visitor.getSpecializations()[0];
} catch (CoreException e) {
CCorePlugin.log(e);
}
return original;
}
//ICPPClassScope unimplemented
public ICPPMethod[] getImplicitMethods() { fail(); return null; }

View file

@ -26,7 +26,6 @@ import org.eclipse.cdt.core.dom.ast.IScope;
import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.ITypedef;
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.ICPPClassType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPField;
@ -38,6 +37,7 @@ import org.eclipse.cdt.core.index.IIndexFileSet;
import org.eclipse.cdt.core.parser.util.ArrayUtil;
import org.eclipse.cdt.core.parser.util.ObjectMap;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPClassScope;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPClassSpecializationScope;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPInternalBase;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPTemplates;
@ -59,7 +59,7 @@ import org.eclipse.core.runtime.CoreException;
*
*/
class PDOMCPPClassSpecialization extends PDOMCPPSpecialization implements
ICPPClassType, ICPPClassScope, IPDOMMemberOwner, IIndexType, IIndexScope {
ICPPClassType, ICPPClassSpecializationScope, IPDOMMemberOwner, IIndexType, IIndexScope {
private static final int FIRSTBASE = PDOMCPPSpecialization.RECORD_SIZE + 0;
private static final int MEMBERLIST = PDOMCPPSpecialization.RECORD_SIZE + 4;
@ -94,6 +94,10 @@ class PDOMCPPClassSpecialization extends PDOMCPPSpecialization implements
return IIndexCPPBindingConstants.CPP_CLASS_SPECIALIZATION;
}
public ICPPClassType getOriginalClassType() {
return (ICPPClassType) getSpecializedBinding();
}
public PDOMCPPBase getFirstBase() throws CoreException {
int rec = pdom.getDB().getInt(record + FIRSTBASE);
return rec != 0 ? new PDOMCPPBase(pdom, rec) : null;
@ -353,6 +357,17 @@ class PDOMCPPClassSpecialization extends PDOMCPPSpecialization implements
return null;
}
public IBinding getInstance(IBinding original) {
SpecializationFinder visitor = new SpecializationFinder(new IBinding[] {original});
try {
accept(visitor);
return visitor.getSpecializations()[0];
} catch (CoreException e) {
CCorePlugin.log(e);
}
return original;
}
public ICPPMethod[] getImplicitMethods() {
try {
PDOMClassUtil.MethodCollector methods = new PDOMClassUtil.MethodCollector(true, false);

View file

@ -1,57 +0,0 @@
/*******************************************************************************
* Copyright (c) 2008 Wind River Systems, 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:
* Markus Schorn - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.core.pdom.dom.cpp;
import org.eclipse.cdt.core.dom.ast.DOMException;
import org.eclipse.cdt.core.dom.ast.IScope;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
import org.eclipse.cdt.core.index.IIndexBinding;
import org.eclipse.cdt.core.index.IIndexName;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPClassSpecializationScope;
import org.eclipse.cdt.internal.core.index.IIndexScope;
/**
* @since 5.0
*/
public class PDOMCPPClassSpecializationScope extends CPPClassSpecializationScope implements IIndexScope {
private final PDOMCPPDeferredClassInstance fBinding;
public PDOMCPPClassSpecializationScope(PDOMCPPDeferredClassInstance specialization) {
super(specialization);
fBinding= specialization;
}
public IIndexBinding getScopeBinding() {
return fBinding;
}
@Override
public IIndexName getScopeName() {
return null;
}
@Override
public IIndexScope getParent() {
ICPPClassType cls = getOriginalClass();
try {
IScope scope = cls.getCompositeScope();
if (scope != null) {
scope= scope.getParent();
if (scope instanceof IIndexScope) {
return (IIndexScope) scope;
}
}
} catch (DOMException e) {
}
return null;
}
}