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

Definitions of members of partial specializations, bug 177418.

This commit is contained in:
Markus Schorn 2008-11-14 09:31:43 +00:00
parent 0dea0424ac
commit 8e55e2392f
6 changed files with 243 additions and 140 deletions

View file

@ -1285,8 +1285,7 @@ public class AST2TemplateTests extends AST2BaseTest {
IBinding U2 = col.getName(10).resolveBinding();
assertSame(U, U2);
assertTrue(f2 instanceof ICPPSpecialization);
assertSame(((ICPPSpecialization)f2).getSpecializedBinding(), f1);
assertSame(f1, f2);
}
// template<typename T>
@ -1792,9 +1791,10 @@ public class AST2TemplateTests extends AST2BaseTest {
ICPPClassTemplate B = (ICPPClassTemplate) col.getName(4).resolveBinding();
assertSame(T, col.getName(5).resolveBinding());
assertSame(T2, col.getName(6).resolveBinding());
final IBinding T2ofPartialSpec = col.getName(6).resolveBinding();
assertNotSame(T2, T2ofPartialSpec); // partial spec has its own template params
assertSame(T, col.getName(10).resolveBinding());
assertSame(T2, col.getName(14).resolveBinding());
assertSame(T2ofPartialSpec, col.getName(14).resolveBinding());
ICPPClassTemplatePartialSpecialization spec = (ICPPClassTemplatePartialSpecialization) col.getName(12).resolveBinding();
assertSame(spec.getPrimaryClassTemplate(), B);
@ -3234,7 +3234,7 @@ public class AST2TemplateTests extends AST2BaseTest {
@Override
public void run() {
try {
parseAndCheckBindings(getAboveComment(), ParserLanguage.CPP);
parseAndCheckBindings(getAboveComment(), ParserLanguage.CPP);
} catch (Throwable e) {
th[0]= e;
}
@ -3247,4 +3247,50 @@ public class AST2TemplateTests extends AST2BaseTest {
if (th[0] != null)
throw th[0];
}
// template<class T, class U> class A {};
// template<class T> class A<T, int> {
// void foo(T t);
// };
// template<class T> void A<T, int>::foo(T t) {}
public void testBug177418() throws Exception {
IASTTranslationUnit tu = parse(getAboveComment(), ParserLanguage.CPP, true, true );
CPPNameCollector col = new CPPNameCollector();
tu.accept( col );
ICPPTemplateParameter T1 = (ICPPTemplateParameter) col.getName(0).resolveBinding();
ICPPTemplateParameter U = (ICPPTemplateParameter) col.getName(1).resolveBinding();
ICPPClassTemplate A = (ICPPClassTemplate) col.getName(2).resolveBinding();
ICPPTemplateParameter T2 = (ICPPTemplateParameter) col.getName(3).resolveBinding();
assertNotSame(T1, T2);
ICPPClassTemplatePartialSpecialization A2 = (ICPPClassTemplatePartialSpecialization) col.getName(4).resolveBinding();
assertSame(A2.getPrimaryClassTemplate(), A);
assertSame(A, col.getName(5).resolveBinding());
assertSame(T2, col.getName(6).resolveBinding());
ICPPMethod foo = (ICPPMethod) col.getName(7).resolveBinding();
assertSame(T2, col.getName(8).resolveBinding());
assertSame(T2, col.getName(10).resolveBinding());
ICPPParameter t = (ICPPParameter) col.getName(9).resolveBinding();
assertSame(A2, col.getName(12).resolveBinding());
assertSame(A, col.getName(13).resolveBinding());
assertSame(T2, col.getName(14).resolveBinding());
assertSame(foo, col.getName(15).resolveBinding());
assertSame(T2, col.getName(16).resolveBinding());
assertSame(t, col.getName(17).resolveBinding());
}
// template <typename T, typename U> class CT {
// T* instance(void);
// };
// template <class T, class U> T * CT<T, U>::instance (void) {
// return new CT<T, U>;
// }
public void testNewOfThisTemplate() throws Exception {
parseAndCheckBindings(getAboveComment(), ParserLanguage.CPP);
}
}

View file

@ -187,4 +187,24 @@ public class PreprocessorBugsTests extends PreprocessorTestsBase {
validateProblem(0, IProblem.PREPROCESSOR_MISSING_RPAREN_PARMLIST, null);
}
// #ifdef 0
// /**/ #else
// OK1
// #endif
// #ifdef 0
// a /*
// */ #else
// OK2
// #endif
// #ifdef 0
// a /**/ #else
// NOTOK
// #endif
public void testCommentBeforeDirective_Bug255318() throws Exception {
initializeScanner();
validateIdentifier("OK1");
validateIdentifier("OK2");
validateEOF();
validateProblemCount(0);
}
}

View file

@ -31,6 +31,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPBase;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPBasicType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassScope;
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.ICPPConstructor;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPField;
@ -1490,7 +1491,6 @@ public class IndexCPPTemplateResolutionTest extends IndexBindingResolutionTestBa
assertSame(charInst1, charInst2);
}
// template<typename T> class XT {
// public: void method() {};
// };
@ -1508,4 +1508,16 @@ public class IndexCPPTemplateResolutionTest extends IndexBindingResolutionTestBa
assertEquals(1, ms.length);
assertEquals(m, ms[0]);
}
// template<class T, class U> class A {};
// template<class T> class A<T, int> {
// void foo(T t);
// };
// template<class T> void A<T, int>::foo(T t) {}
public void testBug177418() throws Exception {
ICPPMethod m= getBindingFromASTName("foo", 3, ICPPMethod.class);
ICPPClassType owner= m.getClassOwner();
assertInstance(owner, ICPPClassTemplatePartialSpecialization.class);
}
}

View file

@ -122,14 +122,11 @@ public class CPPFunctionTemplate extends CPPTemplateDefinition
super.addDeclaration(node);
}
/**
* @param name
*/
private void updateFunctionParameterBindings(IASTName paramName) {
private void updateFunctionParameterBindings(IASTName declName) {
IASTName defName = definition != null ? definition : declarations[0];
ICPPASTFunctionDeclarator orig = (ICPPASTFunctionDeclarator) defName.getParent();
ICPPASTFunctionDeclarator orig = getDeclaratorByName(defName);
IASTParameterDeclaration[] ops = orig.getParameters();
IASTParameterDeclaration[] nps = ((ICPPASTFunctionDeclarator)paramName.getParent()).getParameters();
IASTParameterDeclaration[] nps = getDeclaratorByName(declName).getParameters();
CPPParameter temp = null;
for(int i = 0; i < nps.length; i++) {
temp = (CPPParameter) CPPVisitor.findInnermostDeclarator(ops[i].getDeclarator()).getName().getBinding();

View file

@ -67,7 +67,6 @@ import org.eclipse.cdt.core.dom.ast.IProblemBinding;
import org.eclipse.cdt.core.dom.ast.IQualifierType;
import org.eclipse.cdt.core.dom.ast.IScope;
import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.IValue;
import org.eclipse.cdt.core.dom.ast.IVariable;
import org.eclipse.cdt.core.dom.ast.IASTEnumerationSpecifier.IASTEnumerator;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCatchHandler;
@ -132,7 +131,6 @@ import org.eclipse.cdt.internal.core.dom.parser.ASTInternal;
import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
import org.eclipse.cdt.internal.core.dom.parser.IASTInternalScope;
import org.eclipse.cdt.internal.core.dom.parser.ProblemBinding;
import org.eclipse.cdt.internal.core.dom.parser.Value;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTFieldReference;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTIdExpression;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTName;
@ -220,12 +218,6 @@ public class CPPSemantics {
return postResolution(binding, data);
}
/**
* @param binding
* @param data
* @param name
* @return
*/
private static IBinding postResolution(IBinding binding, LookupData data) {
if (data.checkAssociatedScopes()) {
//3.4.2 argument dependent name lookup, aka Koenig lookup
@ -321,58 +313,23 @@ public class CPPSemantics {
}
}
// mstodo this looks like a hack?
// in template declarations the template-ids get instantiated to deferred instances, revert that.
IASTName name = data.astName;
if (name instanceof ICPPASTTemplateId) {
if (binding instanceof ICPPDeferredTemplateInstance && CPPTemplates.getTemplateDeclaration(name) != null ) {
ICPPDeferredTemplateInstance deferred= (ICPPDeferredTemplateInstance) binding;
IBinding spec= deferred.getSpecializedBinding();
if (spec instanceof ICPPTemplateDefinition) {
try {
ICPPTemplateArgument[] args= deferred.getTemplateArguments();
ICPPTemplateParameter[] pars= ((ICPPTemplateDefinition) spec).getTemplateParameters();
if (args.length == pars.length) {
boolean useOriginal= true;
for (int i = 0; useOriginal && i < pars.length; i++) {
ICPPTemplateParameter par= pars[i];
if (par instanceof ICPPTemplateNonTypeParameter) {
IValue val= args[i].getNonTypeValue();
if (val == null || par.getParameterPosition() != Value.isTemplateParameter(val)) {
useOriginal= false;
}
} else {
IType other= args[i].getTypeValue();
if (!(other instanceof ICPPTemplateParameter)) {
useOriginal= false;
} else if (par.getParameterPosition() != ((ICPPTemplateParameter) other).getParameterPosition()) {
useOriginal= false;
}
}
}
if (useOriginal) {
binding= spec;
}
}
} catch (DOMException e) {
}
}
}
}
if (name.getParent() instanceof ICPPASTTemplateId) {
IASTName name= data.astName;
IASTNode nameParent= name.getParent();
if (nameParent instanceof ICPPASTTemplateId) {
if (binding instanceof ICPPTemplateInstance) {
IBinding b = binding;
binding = ((ICPPTemplateInstance)binding).getSpecializedBinding();
final ICPPTemplateInstance instance = (ICPPTemplateInstance)binding;
binding = instance.getSpecializedBinding();
name.setBinding(binding);
name = (IASTName) name.getParent();
name.setBinding(b);
} else {
name = (IASTName) name.getParent();
}
((ICPPASTTemplateId) nameParent).setBinding(instance);
}
name= (ICPPASTTemplateId) nameParent;
nameParent= name.getParent();
}
if (name.getParent() instanceof ICPPASTQualifiedName) {
if (name == ((ICPPASTQualifiedName)name.getParent()).getLastName())
name = (IASTName) name.getParent();
if (nameParent instanceof ICPPASTQualifiedName) {
if (name == ((ICPPASTQualifiedName) nameParent).getLastName()) {
name= (IASTName) nameParent;
nameParent= name.getParent();
}
}
// if the lookup in base-classes ran into a deferred instance, use the computed unknown binding.
@ -1585,6 +1542,11 @@ public class CPPSemantics {
if (candidate instanceof ICPPClassTemplatePartialSpecialization)
return null;
// specialization is selected during instantiation
// mstodo why not?
// if (candidate instanceof ICPPTemplateInstance && candidate instanceof IType)
// candidate= ((ICPPTemplateInstance) candidate).getSpecializedBinding();
return candidate;
}
}
@ -1737,9 +1699,16 @@ public class CPPSemantics {
} else {
continue;
}
// specialization is selected during instantiation
// mstodo why not?
// if (temp instanceof ICPPTemplateInstance && temp instanceof IType)
// temp= ((ICPPTemplateInstance) temp).getSpecializedBinding();
// select among those bindings that have been created without problems.
if (temp instanceof IProblemBinding)
if (temp instanceof IProblemBinding)
continue;
if (!(temp instanceof ICPPMember) && !declaredBefore)
continue;
if (temp instanceof ICPPUsingDeclaration) {

View file

@ -381,7 +381,7 @@ public class CPPTemplates {
if (element instanceof ICPPASTTemplateId) {
++i;
if (i == idx) {
binding = ((ICPPASTTemplateId) element).getTemplateName().resolveBinding();
binding = ((ICPPASTTemplateId) element).resolveBinding();
break;
}
}
@ -426,10 +426,9 @@ public class CPPTemplates {
public static IBinding createBinding(ICPPASTTemplateId id) {
IASTNode parent = id.getParent();
int segment = -1;
boolean isLastName= true;
if (parent instanceof ICPPASTQualifiedName) {
IASTName[] ns = ((ICPPASTQualifiedName) parent).getNames();
segment = (ns[ns.length - 1] == id) ? 1 : 0;
isLastName= ((ICPPASTQualifiedName) parent).getLastName() == id;
parent = parent.getParent();
}
@ -443,50 +442,65 @@ public class CPPTemplates {
}
try {
if (decl instanceof ICPPASTExplicitTemplateInstantiation &&
parent instanceof ICPPASTElaboratedTypeSpecifier && segment != 0) {
return createExplicitClassInstantiation((ICPPASTElaboratedTypeSpecifier) parent);
} else if (((parent instanceof ICPPASTElaboratedTypeSpecifier &&
decl instanceof ICPPASTTemplateDeclaration) ||
parent instanceof ICPPASTCompositeTypeSpecifier) &&
segment != 0) {
return createExplicitClassSpecialization((ICPPASTDeclSpecifier) parent);
} else if (parent instanceof ICPPASTFunctionDeclarator && segment != 0) {
return createFunctionSpecialization(id);
}
final boolean isClassDecl= parent instanceof ICPPASTElaboratedTypeSpecifier;
final boolean isClassDef = parent instanceof ICPPASTCompositeTypeSpecifier;
if (isLastName) {
if (isClassDecl && decl instanceof ICPPASTExplicitTemplateInstantiation)
return createExplicitClassInstantiation((ICPPASTElaboratedTypeSpecifier) parent);
if (isClassDef || (isClassDecl && decl instanceof ICPPASTTemplateDeclaration))
return createExplicitClassSpecialization((ICPPASTDeclSpecifier) parent);
//a reference: class or function template?
IBinding template = null;
if (parent instanceof ICPPASTNamedTypeSpecifier ||
parent instanceof ICPPASTElaboratedTypeSpecifier ||
parent instanceof ICPPASTBaseSpecifier ||
segment == 0) {
//class template
if (parent instanceof ICPPASTFunctionDeclarator)
return createFunctionSpecialization(id);
}
if (!isLastName || isClassDecl || parent instanceof ICPPASTNamedTypeSpecifier ||
parent instanceof ICPPASTBaseSpecifier) {
// class template instance
IASTName templateName = id.getTemplateName();
template = templateName.resolveBinding();
if (template instanceof ICPPClassTemplatePartialSpecialization) {
//specializations are selected during the instantiation, start with the primary template
try {
template = ((ICPPClassTemplatePartialSpecialization) template).getPrimaryClassTemplate();
} catch (DOMException e) {
return e.getProblem();
}
} else if (template instanceof ICPPSpecialization && !(template instanceof ICPPTemplateDefinition)) {
template = ((ICPPSpecialization) template).getSpecializedBinding();
IBinding template = templateName.resolveBinding();
if (template instanceof ICPPUnknownClassInstance) {
// mstodo we should not get here, rather than that an unknown class
// should be made to an unknown class instance here
return template;
}
if (template instanceof ICPPConstructor) {
template= template.getOwner();
}
if (template instanceof ICPPTemplateDefinition) {
ICPPTemplateArgument[] args= CPPTemplates.createTemplateArgumentArray(id);
IBinding instance= instantiate((ICPPTemplateDefinition) template, args);
return CPPSemantics.postResolution(instance, id);
}
} else {
//functions are instantiated as part of the resolution process
template = CPPVisitor.createBinding(id);
if (template instanceof ICPPTemplateInstance) {
IASTName templateName = id.getTemplateName();
templateName.setBinding(((ICPPTemplateInstance) template).getTemplateDefinition());
if (!(template instanceof ICPPClassTemplate) || template instanceof ICPPClassTemplatePartialSpecialization)
return new ProblemBinding(id, IProblemBinding.SEMANTIC_INVALID_TYPE, templateName.toCharArray());
final ICPPClassTemplate classTemplate = (ICPPClassTemplate) template;
ICPPTemplateArgument[] args= createTemplateArgumentArray(id);
ICPPASTTemplateDeclaration tdecl= getTemplateDeclaration(id);
if (tdecl != null) {
if (hasDependentArgument(args)) {
IBinding result= null;
if (argsAreTrivial(classTemplate.getTemplateParameters(), args)) {
result= classTemplate;
} else {
ICPPClassTemplatePartialSpecialization partialSpec= findPartialSpecialization(classTemplate, args);
if (partialSpec == null)
return new ProblemBinding(id, IProblemBinding.SEMANTIC_INVALID_TYPE, templateName.toCharArray());
result= partialSpec;
}
if (isClassDecl && result instanceof ICPPInternalBinding)
((ICPPInternalBinding) result).addDeclaration(id);
return result;
}
}
IBinding instance= instantiate(classTemplate, args);
return CPPSemantics.postResolution(instance, id);
}
//functions are instantiated as part of the resolution process
IBinding template = CPPVisitor.createBinding(id);
if (template instanceof ICPPTemplateInstance) {
IASTName templateName = id.getTemplateName();
templateName.setBinding(((ICPPTemplateInstance) template).getTemplateDefinition());
}
return template;
} catch (DOMException e) {
@ -571,22 +585,10 @@ public class CPPTemplates {
}
return inst;
}
//else partial specialization
//CPPClassTemplate template = (CPPClassTemplate) binding;
ICPPClassTemplatePartialSpecialization spec= null;
try {
ICPPClassTemplatePartialSpecialization[] specs = template.getPartialSpecializations();
if (specs != null) {
for (ICPPClassTemplatePartialSpecialization specialization : specs) {
if (isSameTemplate(specialization, id)) {
spec = specialization;
break;
}
}
}
} catch (DOMException e) {
}
// we have a partial specialization
ICPPTemplateArgument[] args= createTemplateArgumentArray(id);
ICPPClassTemplatePartialSpecialization spec= findPartialSpecialization(template, args);
if (spec != null) {
if (spec instanceof ICPPInternalBinding)
((ICPPInternalBinding) spec).addDefinition(id);
@ -594,6 +596,7 @@ public class CPPTemplates {
}
spec = new CPPClassTemplatePartialSpecialization(id);
// mstodo how to add partial specialization to class template from index?
if (template instanceof ICPPInternalClassTemplate)
((ICPPInternalClassTemplate) template).addPartialSpecialization(spec);
return spec;
@ -609,7 +612,7 @@ public class CPPTemplates {
}
CPPSemantics.lookup(data, scope);
ICPPFunctionTemplate function = resolveTemplateFunctions((Object[]) data.foundItems, name);
ICPPFunctionTemplate function= resolveTemplateFunctions((Object[]) data.foundItems, name);
if (function == null)
return new ProblemBinding(name, IProblemBinding.SEMANTIC_NAME_NOT_FOUND, name.toCharArray());
if (function instanceof IProblemBinding)
@ -628,22 +631,33 @@ public class CPPTemplates {
if (args == null)
return new ProblemBinding(name, IProblemBinding.SEMANTIC_INVALID_TYPE, name.toCharArray());
IBinding result= null;
if (hasDependentArgument(args)) {
// we are looking at a definition for a function-template.
final ICPPTemplateParameter[] pars= function.getTemplateParameters();
if (!argsAreTrivial(pars, args)) {
return new ProblemBinding(name, IProblemBinding.SEMANTIC_DEFINITION_NOT_FOUND, name.toCharArray());
}
result= function;
} else {
result= getInstance(function, args);
if (result == null) {
IBinding owner= function.getOwner();
ICPPTemplateInstance instance= createInstance(owner, function, tpMap, args);
addInstance(function, args, instance);
result= instance;
}
}
while (!(parent instanceof IASTDeclaration))
parent = parent.getParent();
IBinding owner= function.getOwner();
ICPPTemplateInstance instance= getInstance(function, args);
if (instance == null) {
instance = createInstance(owner, function, tpMap, args);
addInstance(function, args, instance);
}
if (instance instanceof ICPPInternalBinding) {
if (result instanceof ICPPInternalBinding) {
if (parent instanceof IASTSimpleDeclaration)
((ICPPInternalBinding) instance).addDeclaration(name);
((ICPPInternalBinding) result).addDeclaration(name);
else if (parent instanceof IASTFunctionDefinition)
((ICPPInternalBinding) instance).addDefinition(name);
((ICPPInternalBinding) result).addDefinition(name);
}
return instance;
return result;
} catch (DOMException e) {
return e.getProblem();
}
@ -1642,6 +1656,22 @@ public class CPPTemplates {
return d1 - d2;
}
private static ICPPClassTemplatePartialSpecialization findPartialSpecialization(ICPPClassTemplate ct, ICPPTemplateArgument[] args) throws DOMException {
ICPPClassTemplatePartialSpecialization[] pspecs = ct.getPartialSpecializations();
if (pspecs != null && pspecs.length > 0) {
final String argStr= ASTTypeUtil.getArgumentListString(args, true);
for (ICPPClassTemplatePartialSpecialization pspec : pspecs) {
try {
if (argStr.equals(ASTTypeUtil.getArgumentListString(pspec.getTemplateArguments(), true)))
return pspec;
} catch (DOMException e) {
// ignore partial specializations with problems
}
}
}
return null;
}
static public ICPPTemplateDefinition selectSpecialization(ICPPClassTemplate template, ICPPTemplateArgument[] args)
throws DOMException {
if (template == null) {
@ -1874,12 +1904,41 @@ public class CPPTemplates {
return cost != null && cost.rank != Cost.NO_MATCH_RANK;
}
private static boolean argsAreTrivial(ICPPTemplateParameter[] pars, ICPPTemplateArgument[] args) {
if (pars.length != args.length) {
return false;
}
for (int i = 0; i < args.length; i++) {
ICPPTemplateParameter par= pars[i];
ICPPTemplateArgument arg = args[i];
if (par instanceof IType) {
IType argType= arg.getTypeValue();
if (argType == null || !argType.isSameType((IType) par))
return false;
} else {
int parpos= Value.isTemplateParameter(arg.getNonTypeValue());
if (parpos != par.getParameterPosition())
return false;
}
}
return true;
}
public static boolean hasDependentArgument(ICPPTemplateArgument[] args) {
for (ICPPTemplateArgument arg : args) {
if (isDependentArgument(arg))
return true;
}
return false;
}
public static boolean isDependentArgument(ICPPTemplateArgument arg) {
if (arg.isTypeValue())
return isDependentType(arg.getTypeValue());
return Value.isDependentValue(arg.getNonTypeValue());
}
public static boolean isDependentType(IType t) {
// mstodo needs to be extended
if (t instanceof ICPPTemplateParameter)