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

Cleanup: unify isSameType for index and ast, create AST bindings for definitions of specializations.

This commit is contained in:
Markus Schorn 2009-10-28 12:01:51 +00:00
parent 21cda7ff60
commit 5e934ed6a5
11 changed files with 162 additions and 91 deletions

View file

@ -1526,11 +1526,11 @@ public class IndexCPPTemplateResolutionTest extends IndexBindingResolutionTestBa
ICPPTemplateInstance inst= (ICPPTemplateInstance) t1;
final ICPPClassTemplate tmplDef = (ICPPClassTemplate) inst.getTemplateDefinition();
IBinding inst2= CPPTemplates.instantiate(tmplDef, inst.getTemplateArguments());
IBinding inst2= CPPTemplates.instantiate(tmplDef, inst.getTemplateArguments(), false);
assertSame(inst, inst2);
IBinding charInst1= CPPTemplates.instantiate(tmplDef, new ICPPTemplateArgument[] {new CPPTemplateArgument(new CPPBasicType(Kind.eChar, 0))});
IBinding charInst2= CPPTemplates.instantiate(tmplDef, new ICPPTemplateArgument[] {new CPPTemplateArgument(new CPPBasicType(Kind.eChar, 0))});
IBinding charInst1= CPPTemplates.instantiate(tmplDef, new ICPPTemplateArgument[] {new CPPTemplateArgument(new CPPBasicType(Kind.eChar, 0))}, false);
IBinding charInst2= CPPTemplates.instantiate(tmplDef, new ICPPTemplateArgument[] {new CPPTemplateArgument(new CPPBasicType(Kind.eChar, 0))}, false);
assertSame(charInst1, charInst2);
}

View file

@ -16,12 +16,16 @@ package org.eclipse.cdt.internal.core.dom.parser.cpp;
import org.eclipse.cdt.core.dom.ast.ASTTypeUtil;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IProblemBinding;
import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.ITypedef;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassSpecialization;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateArgument;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateDefinition;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateInstance;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPTemplates;
import org.eclipse.cdt.internal.core.index.IIndexType;
/**
* The result of instantiating a class template.
@ -59,4 +63,32 @@ public class CPPClassInstance extends CPPClassSpecialization implements ICPPTemp
public boolean equals(Object obj) {
return obj instanceof ICPPClassType && isSameType((ICPPClassType) obj);
}
@Override
public boolean isSameType(IType type) {
if (type == this)
return true;
if (type instanceof ITypedef || type instanceof IIndexType)
return type.isSameType(this);
return isSameClassInstance(this, type);
}
public static boolean isSameClassInstance(ICPPClassSpecialization classInstance, IType type) {
assert classInstance instanceof ICPPTemplateInstance;
// require a class instance
if (!(type instanceof ICPPClassSpecialization) || !(type instanceof ICPPTemplateInstance) ||
type instanceof IProblemBinding) {
return false;
}
final ICPPClassSpecialization classSpec2 = (ICPPClassSpecialization) type;
final ICPPClassType orig1= classInstance.getSpecializedBinding();
final ICPPClassType orig2= classSpec2.getSpecializedBinding();
if (!orig1.isSameType(orig2))
return false;
return CPPTemplates.haveSameArguments((ICPPTemplateInstance) classInstance, (ICPPTemplateInstance) type);
}
}

View file

@ -22,6 +22,7 @@ import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IField;
import org.eclipse.cdt.core.dom.ast.IProblemBinding;
import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.ITypedef;
import org.eclipse.cdt.core.dom.ast.cpp.CPPASTVisitor;
@ -37,6 +38,8 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPField;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPSpecialization;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateDefinition;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateInstance;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap;
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
import org.eclipse.cdt.core.parser.util.ObjectMap;
@ -277,11 +280,15 @@ public class CPPClassSpecialization extends CPPSpecialization
/* (non-Javadoc)
* @see org.eclipse.cdt.core.dom.ast.IType#isSameType(org.eclipse.cdt.core.dom.ast.IType)
*/
public final boolean isSameType(IType type) {
if( type == this )
public boolean isSameType(IType type) {
if (type == this)
return true;
if( type instanceof ITypedef || type instanceof IIndexType )
return type.isSameType( this );
if (type instanceof ITypedef || type instanceof IIndexType)
return type.isSameType(this);
if (type instanceof ICPPClassSpecialization) {
return isSameClassSpecialization(this, (ICPPClassSpecialization) type);
}
return false;
}
@ -308,4 +315,34 @@ public class CPPClassSpecialization extends CPPSpecialization
}
return false;
}
public static boolean isSameClassSpecialization(ICPPClassSpecialization t1, ICPPClassSpecialization t2) {
// exclude class template specialization or class instance
if (t2 instanceof ICPPTemplateInstance || t2 instanceof ICPPTemplateDefinition ||
t2 instanceof IProblemBinding)
return false;
try {
if (t1.getKey() != t2.getKey())
return false;
if (!CharArrayUtils.equals(t1.getNameCharArray(), t2.getNameCharArray()))
return false;
// the argument map is not significant for comparing specializations, the map is
// determined by the owner of the specialization. This is different for instances,
// which have a separate implementation for isSameType().
final IBinding owner1= t1.getOwner();
final IBinding owner2= t2.getOwner();
// for a specialization that is not an instance the owner has to be a class-type
if (owner1 instanceof ICPPClassType == false || owner2 instanceof ICPPClassType == false)
return false;
return ((ICPPClassType) owner1).isSameType((ICPPClassType) owner2);
} catch (DOMException e) {
return false;
}
}
}

View file

@ -15,14 +15,17 @@ import org.eclipse.cdt.core.dom.ast.ASTTypeUtil;
import org.eclipse.cdt.core.dom.ast.DOMException;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.ITypedef;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateId;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassTemplate;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassTemplatePartialSpecialization;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPSpecialization;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateArgument;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap;
import org.eclipse.cdt.core.parser.util.ObjectMap;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPTemplates;
import org.eclipse.cdt.internal.core.index.IIndexType;
/**
* A partial class template specialization.
@ -86,4 +89,44 @@ public class CPPClassTemplatePartialSpecialization extends CPPClassTemplate
public IType[] getArguments() throws DOMException {
return CPPTemplates.getArguments(getTemplateArguments());
}
/* (non-Javadoc)
* @see org.eclipse.cdt.core.dom.ast.IType#isSameType(org.eclipse.cdt.core.dom.ast.IType)
*/
@Override
public boolean isSameType(IType type) {
if (type == this)
return true;
if (type instanceof ITypedef || type instanceof IIndexType)
return type.isSameType(this);
if (type instanceof ICPPClassTemplatePartialSpecialization) {
return isSamePartialClassSpecialization(this, (ICPPClassTemplatePartialSpecialization) type);
}
return false;
}
public static boolean isSamePartialClassSpecialization(
ICPPClassTemplatePartialSpecialization lhs,
ICPPClassTemplatePartialSpecialization rhs) {
try {
ICPPClassType ct1= lhs.getPrimaryClassTemplate();
ICPPClassType ct2= rhs.getPrimaryClassTemplate();
if(!ct1.isSameType(ct2))
return false;
ICPPTemplateArgument[] args1= lhs.getTemplateArguments();
ICPPTemplateArgument[] args2= rhs.getTemplateArguments();
if (args1.length != args2.length)
return false;
for (int i = 0; i < args2.length; i++) {
if (args1[i].isSameValue(args2[i]))
return false;
}
} catch (DOMException e) {
return false;
}
return true;
}
}

View file

@ -295,7 +295,7 @@ public class CPPScopeMapper {
if (template instanceof IIndexBinding && template instanceof ICPPClassType) {
IBinding mapped= mapToAST((ICPPClassType) template);
if (mapped != template && mapped instanceof ICPPClassType) {
mapped= CPPTemplates.instantiate((ICPPClassTemplate) mapped, inst.getTemplateArguments());
mapped= CPPTemplates.instantiate((ICPPClassTemplate) mapped, inst.getTemplateArguments(), false);
if (mapped instanceof ICPPClassType)
return (ICPPClassType) mapped;
}

View file

@ -367,7 +367,7 @@ public class CPPSemantics {
if (data.tu != null) {
ICPPASTTemplateId id = (ICPPASTTemplateId) data.astName;
ICPPTemplateArgument[] args = CPPTemplates.createTemplateArgumentArray(id);
IBinding inst= CPPTemplates.instantiate((ICPPClassTemplate) cls, args);
IBinding inst= CPPTemplates.instantiate((ICPPClassTemplate) cls, args, false);
if (inst instanceof ICPPClassType) {
cls= (ICPPClassType) inst;
}

View file

@ -84,6 +84,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateTemplateParameter;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateTypeParameter;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier;
import org.eclipse.cdt.core.index.IIndexBinding;
import org.eclipse.cdt.core.parser.util.ArrayUtil;
import org.eclipse.cdt.core.parser.util.CharArraySet;
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
@ -149,7 +150,7 @@ public class CPPTemplates {
/**
* Instantiates a class template with the given arguments. May return <code>null</code>.
*/
public static IBinding instantiate(ICPPClassTemplate template, ICPPTemplateArgument[] arguments) {
public static IBinding instantiate(ICPPClassTemplate template, ICPPTemplateArgument[] arguments, boolean isDef) {
try {
arguments= SemanticUtil.getSimplifiedArguments(arguments);
if (template instanceof ICPPTemplateTemplateParameter || hasDependentArgument(arguments)) {
@ -157,7 +158,7 @@ public class CPPTemplates {
}
if (template instanceof ICPPClassTemplatePartialSpecialization) {
return instantiatePartialSpecialization((ICPPClassTemplatePartialSpecialization) template, arguments);
return instantiatePartialSpecialization((ICPPClassTemplatePartialSpecialization) template, arguments, isDef);
}
// check whether we need to use default arguments
@ -209,10 +210,10 @@ public class CPPTemplates {
return tdef;
if (tdef instanceof ICPPClassTemplatePartialSpecialization) {
return instantiatePartialSpecialization((ICPPClassTemplatePartialSpecialization) tdef, completeArgs);
return instantiatePartialSpecialization((ICPPClassTemplatePartialSpecialization) tdef, completeArgs, isDef);
}
return instantiatePrimaryTemplate(template, completeArgs, map);
return instantiatePrimaryTemplate(template, completeArgs, map, isDef);
} catch (DOMException e) {
return e.getProblem();
}
@ -269,8 +270,8 @@ public class CPPTemplates {
/**
* Instantiates a partial class template specialization.
*/
private static IBinding instantiatePartialSpecialization(ICPPClassTemplatePartialSpecialization partialSpec, ICPPTemplateArgument[] args) throws DOMException {
ICPPTemplateInstance instance= getInstance(partialSpec, args);
private static IBinding instantiatePartialSpecialization(ICPPClassTemplatePartialSpecialization partialSpec, ICPPTemplateArgument[] args, boolean isDef) throws DOMException {
ICPPTemplateInstance instance= getInstance(partialSpec, args, isDef);
if (instance != null)
return instance;
@ -296,10 +297,10 @@ public class CPPTemplates {
* @param map
*/
private static IBinding instantiatePrimaryTemplate(ICPPClassTemplate template, ICPPTemplateArgument[] arguments,
CPPTemplateParameterMap map) throws DOMException {
CPPTemplateParameterMap map, boolean isDef) throws DOMException {
assert !(template instanceof ICPPClassTemplatePartialSpecialization);
ICPPTemplateInstance instance= getInstance(template, arguments);
ICPPTemplateInstance instance= getInstance(template, arguments, isDef);
if (instance != null) {
return instance;
}
@ -312,7 +313,7 @@ public class CPPTemplates {
private static IBinding instantiateFunctionTemplate(ICPPFunctionTemplate template, ICPPTemplateArgument[] arguments)
throws DOMException {
ICPPTemplateInstance instance= getInstance(template, arguments);
ICPPTemplateInstance instance= getInstance(template, arguments, false);
if (instance != null) {
return instance;
}
@ -336,9 +337,12 @@ public class CPPTemplates {
/**
* Obtains a cached instance from the template.
*/
private static ICPPTemplateInstance getInstance(ICPPTemplateDefinition template, ICPPTemplateArgument[] args) {
private static ICPPTemplateInstance getInstance(ICPPTemplateDefinition template, ICPPTemplateArgument[] args, boolean forDefinition) {
if (template instanceof ICPPInstanceCache) {
return ((ICPPInstanceCache) template).getInstance(args);
ICPPTemplateInstance result = ((ICPPInstanceCache) template).getInstance(args);
if (forDefinition && result instanceof IIndexBinding)
return null;
return result;
}
return null;
}
@ -353,7 +357,7 @@ public class CPPTemplates {
}
private static IBinding deferredInstance(ICPPClassTemplate template, ICPPTemplateArgument[] arguments) throws DOMException {
ICPPTemplateInstance instance= getInstance(template, arguments);
ICPPTemplateInstance instance= getInstance(template, arguments, false);
if (instance != null)
return instance;
@ -590,7 +594,7 @@ public class CPPTemplates {
}
}
if (result == null) {
result= instantiate(classTemplate, args);
result= instantiate(classTemplate, args, isDef);
if (result instanceof ICPPInternalBinding) {
if (isDecl) {
ASTInternal.addDeclaration(result, id);
@ -2211,7 +2215,7 @@ public class CPPTemplates {
ICPPTemplateArgument[] newArgs = CPPTemplates.instantiateArguments(
((ICPPUnknownClassInstance) unknown).getArguments(), tpMap, within);
if (result instanceof ICPPClassTemplate) {
result = instantiate((ICPPClassTemplate) result, newArgs);
result = instantiate((ICPPClassTemplate) result, newArgs, false);
}
}
}
@ -2235,7 +2239,7 @@ public class CPPTemplates {
}
if (changed) {
IBinding inst= instantiate(classTemplate, newArgs);
IBinding inst= instantiate(classTemplate, newArgs, false);
if (inst != null)
return inst;
}

View file

@ -13,14 +13,13 @@
package org.eclipse.cdt.internal.core.pdom.dom.cpp;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.dom.ast.IProblemBinding;
import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.ITypedef;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassSpecialization;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateArgument;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateDefinition;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateInstance;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPClassInstance;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPTemplates;
import org.eclipse.cdt.internal.core.index.IIndexCPPBindingConstants;
import org.eclipse.cdt.internal.core.pdom.dom.PDOMBinding;
@ -90,19 +89,7 @@ class PDOMCPPClassInstance extends PDOMCPPClassSpecialization implements ICPPTem
}
}
// require a class instance
if (!(type instanceof ICPPClassSpecialization) || !(type instanceof ICPPTemplateInstance) ||
type instanceof IProblemBinding) {
return false;
}
final ICPPClassSpecialization classSpec2 = (ICPPClassSpecialization) type;
final ICPPClassType orig1= getSpecializedBinding();
final ICPPClassType orig2= classSpec2.getSpecializedBinding();
if (!orig1.isSameType(orig2))
return false;
return CPPTemplates.haveSameArguments(this, (ICPPTemplateInstance) type);
return CPPClassInstance.isSameClassInstance(this, type);
}
@Deprecated

View file

@ -21,7 +21,6 @@ import org.eclipse.cdt.core.dom.IPDOMVisitor;
import org.eclipse.cdt.core.dom.ast.DOMException;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IField;
import org.eclipse.cdt.core.dom.ast.IProblemBinding;
import org.eclipse.cdt.core.dom.ast.IScope;
import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.ITypedef;
@ -33,10 +32,8 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPField;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPSpecialization;
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.CharArrayUtils;
import org.eclipse.cdt.core.parser.util.ObjectMap;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPClassSpecialization;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ClassTypeHelper;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPClassSpecializationScope;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPTemplates;
@ -310,35 +307,10 @@ class PDOMCPPClassSpecialization extends PDOMCPPSpecialization implements
}
// require a class specialization
if (type instanceof ICPPSpecialization == false || type instanceof IProblemBinding)
if (!(type instanceof ICPPClassSpecialization))
return false;
// exclude class template specialization or class instance
if (type instanceof ICPPTemplateInstance || type instanceof ICPPTemplateDefinition)
return false;
final ICPPClassSpecialization classSpec2 = (ICPPClassSpecialization) type;
try {
if (getKey() != classSpec2.getKey())
return false;
if (!CharArrayUtils.equals(getNameCharArray(), classSpec2.getNameCharArray()))
return false;
// the argument map is not significant for comparing specializations, the map is
// determined by the owner of the specialization. This is different for instances,
// which have a separate implementation for isSameType().
final IBinding owner1= getOwner();
final IBinding owner2= classSpec2.getOwner();
// for a specialization that is not an instance the owner has to be a class-type
if (owner1 instanceof ICPPClassType == false || owner2 instanceof ICPPClassType == false)
return false;
return ((ICPPClassType) owner1).isSameType((ICPPClassType) owner2);
} catch (DOMException e) {
return false;
}
return CPPClassSpecialization.isSameClassSpecialization(this, (ICPPClassSpecialization) type);
}
@Override

View file

@ -17,8 +17,8 @@ import org.eclipse.cdt.core.dom.ast.ITypedef;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassTemplate;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassTemplatePartialSpecialization;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassTemplatePartialSpecializationSpecialization;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateArgument;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPClassTemplatePartialSpecialization;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPTemplates;
import org.eclipse.cdt.internal.core.index.IIndexCPPBindingConstants;
import org.eclipse.cdt.internal.core.pdom.db.Database;
@ -100,25 +100,7 @@ class PDOMCPPClassTemplatePartialSpecializationSpecialization extends PDOMCPPCla
}
final ICPPClassTemplatePartialSpecialization rhs = (ICPPClassTemplatePartialSpecialization)type;
try {
ICPPClassType ct1= getPrimaryClassTemplate();
ICPPClassType ct2= rhs.getPrimaryClassTemplate();
if(!ct1.isSameType(ct2))
return false;
ICPPTemplateArgument[] args1= getTemplateArguments();
ICPPTemplateArgument[] args2= rhs.getTemplateArguments();
if (args1.length != args2.length)
return false;
for (int i = 0; i < args2.length; i++) {
if (args1[i].isSameValue(args2[i]))
return false;
}
} catch (DOMException e) {
return false;
}
return true;
return CPPClassTemplatePartialSpecialization.isSamePartialClassSpecialization(this, rhs);
}
public ICPPClassTemplate getPrimaryClassTemplate() {

View file

@ -310,9 +310,23 @@ class OpenDeclarationsJob extends Job implements ASTRunnable {
declNames.addAll(Arrays.asList(ast.getDefinitionsInAST(binding)));
for (Iterator<IASTName> i = declNames.iterator(); i.hasNext();) {
IASTName name= i.next();
if (name.resolveBinding() instanceof ICPPUsingDeclaration) {
final IBinding b2 = name.resolveBinding();
if (b2 instanceof ICPPUsingDeclaration) {
i.remove();
}
if (binding != b2 && binding instanceof ICPPSpecialization) {
// make sure binding specializes b2 so that for instance we do not navigate from
// one partial specialization to another.
IBinding spec= binding;
while (spec instanceof ICPPSpecialization) {
spec= ((ICPPSpecialization) spec).getSpecializedBinding();
if (spec == b2)
break;
}
if (!(spec instanceof ICPPSpecialization)) {
i.remove();
}
}
}
if (!declNames.isEmpty()) {
return declNames.toArray(new IASTName[declNames.size()]);