mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-08-16 20:55:44 +02:00
Definitions of members of partial specializations, bug 177418.
This commit is contained in:
parent
0dea0424ac
commit
8e55e2392f
6 changed files with 243 additions and 140 deletions
|
@ -1285,8 +1285,7 @@ public class AST2TemplateTests extends AST2BaseTest {
|
||||||
IBinding U2 = col.getName(10).resolveBinding();
|
IBinding U2 = col.getName(10).resolveBinding();
|
||||||
assertSame(U, U2);
|
assertSame(U, U2);
|
||||||
|
|
||||||
assertTrue(f2 instanceof ICPPSpecialization);
|
assertSame(f1, f2);
|
||||||
assertSame(((ICPPSpecialization)f2).getSpecializedBinding(), f1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// template<typename T>
|
// template<typename T>
|
||||||
|
@ -1792,9 +1791,10 @@ public class AST2TemplateTests extends AST2BaseTest {
|
||||||
ICPPClassTemplate B = (ICPPClassTemplate) col.getName(4).resolveBinding();
|
ICPPClassTemplate B = (ICPPClassTemplate) col.getName(4).resolveBinding();
|
||||||
|
|
||||||
assertSame(T, col.getName(5).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(T, col.getName(10).resolveBinding());
|
||||||
assertSame(T2, col.getName(14).resolveBinding());
|
assertSame(T2ofPartialSpec, col.getName(14).resolveBinding());
|
||||||
|
|
||||||
ICPPClassTemplatePartialSpecialization spec = (ICPPClassTemplatePartialSpecialization) col.getName(12).resolveBinding();
|
ICPPClassTemplatePartialSpecialization spec = (ICPPClassTemplatePartialSpecialization) col.getName(12).resolveBinding();
|
||||||
assertSame(spec.getPrimaryClassTemplate(), B);
|
assertSame(spec.getPrimaryClassTemplate(), B);
|
||||||
|
@ -3247,4 +3247,50 @@ public class AST2TemplateTests extends AST2BaseTest {
|
||||||
if (th[0] != null)
|
if (th[0] != null)
|
||||||
throw th[0];
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -187,4 +187,24 @@ public class PreprocessorBugsTests extends PreprocessorTestsBase {
|
||||||
validateProblem(0, IProblem.PREPROCESSOR_MISSING_RPAREN_PARMLIST, null);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.ICPPBasicType;
|
||||||
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.ICPPClassTemplate;
|
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.ICPPClassType;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor;
|
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.ICPPField;
|
||||||
|
@ -1490,7 +1491,6 @@ public class IndexCPPTemplateResolutionTest extends IndexBindingResolutionTestBa
|
||||||
assertSame(charInst1, charInst2);
|
assertSame(charInst1, charInst2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// template<typename T> class XT {
|
// template<typename T> class XT {
|
||||||
// public: void method() {};
|
// public: void method() {};
|
||||||
// };
|
// };
|
||||||
|
@ -1508,4 +1508,16 @@ public class IndexCPPTemplateResolutionTest extends IndexBindingResolutionTestBa
|
||||||
assertEquals(1, ms.length);
|
assertEquals(1, ms.length);
|
||||||
assertEquals(m, ms[0]);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -122,14 +122,11 @@ public class CPPFunctionTemplate extends CPPTemplateDefinition
|
||||||
super.addDeclaration(node);
|
super.addDeclaration(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private void updateFunctionParameterBindings(IASTName declName) {
|
||||||
* @param name
|
|
||||||
*/
|
|
||||||
private void updateFunctionParameterBindings(IASTName paramName) {
|
|
||||||
IASTName defName = definition != null ? definition : declarations[0];
|
IASTName defName = definition != null ? definition : declarations[0];
|
||||||
ICPPASTFunctionDeclarator orig = (ICPPASTFunctionDeclarator) defName.getParent();
|
ICPPASTFunctionDeclarator orig = getDeclaratorByName(defName);
|
||||||
IASTParameterDeclaration[] ops = orig.getParameters();
|
IASTParameterDeclaration[] ops = orig.getParameters();
|
||||||
IASTParameterDeclaration[] nps = ((ICPPASTFunctionDeclarator)paramName.getParent()).getParameters();
|
IASTParameterDeclaration[] nps = getDeclaratorByName(declName).getParameters();
|
||||||
CPPParameter temp = null;
|
CPPParameter temp = null;
|
||||||
for(int i = 0; i < nps.length; i++) {
|
for(int i = 0; i < nps.length; i++) {
|
||||||
temp = (CPPParameter) CPPVisitor.findInnermostDeclarator(ops[i].getDeclarator()).getName().getBinding();
|
temp = (CPPParameter) CPPVisitor.findInnermostDeclarator(ops[i].getDeclarator()).getName().getBinding();
|
||||||
|
|
|
@ -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.IQualifierType;
|
||||||
import org.eclipse.cdt.core.dom.ast.IScope;
|
import org.eclipse.cdt.core.dom.ast.IScope;
|
||||||
import org.eclipse.cdt.core.dom.ast.IType;
|
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.IVariable;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTEnumerationSpecifier.IASTEnumerator;
|
import org.eclipse.cdt.core.dom.ast.IASTEnumerationSpecifier.IASTEnumerator;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCatchHandler;
|
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.ASTNode;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.IASTInternalScope;
|
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.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.CPPASTFieldReference;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTIdExpression;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTIdExpression;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTName;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTName;
|
||||||
|
@ -220,12 +218,6 @@ public class CPPSemantics {
|
||||||
return postResolution(binding, data);
|
return postResolution(binding, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param binding
|
|
||||||
* @param data
|
|
||||||
* @param name
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
private static IBinding postResolution(IBinding binding, LookupData data) {
|
private static IBinding postResolution(IBinding binding, LookupData data) {
|
||||||
if (data.checkAssociatedScopes()) {
|
if (data.checkAssociatedScopes()) {
|
||||||
//3.4.2 argument dependent name lookup, aka Koenig lookup
|
//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;
|
IASTName name= data.astName;
|
||||||
if (name instanceof ICPPASTTemplateId) {
|
IASTNode nameParent= name.getParent();
|
||||||
if (binding instanceof ICPPDeferredTemplateInstance && CPPTemplates.getTemplateDeclaration(name) != null ) {
|
if (nameParent instanceof ICPPASTTemplateId) {
|
||||||
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) {
|
|
||||||
if (binding instanceof ICPPTemplateInstance) {
|
if (binding instanceof ICPPTemplateInstance) {
|
||||||
IBinding b = binding;
|
final ICPPTemplateInstance instance = (ICPPTemplateInstance)binding;
|
||||||
binding = ((ICPPTemplateInstance)binding).getSpecializedBinding();
|
binding = instance.getSpecializedBinding();
|
||||||
name.setBinding(binding);
|
name.setBinding(binding);
|
||||||
name = (IASTName) name.getParent();
|
((ICPPASTTemplateId) nameParent).setBinding(instance);
|
||||||
name.setBinding(b);
|
|
||||||
} else {
|
|
||||||
name = (IASTName) name.getParent();
|
|
||||||
}
|
}
|
||||||
|
name= (ICPPASTTemplateId) nameParent;
|
||||||
|
nameParent= name.getParent();
|
||||||
|
}
|
||||||
|
if (nameParent instanceof ICPPASTQualifiedName) {
|
||||||
|
if (name == ((ICPPASTQualifiedName) nameParent).getLastName()) {
|
||||||
|
name= (IASTName) nameParent;
|
||||||
|
nameParent= name.getParent();
|
||||||
}
|
}
|
||||||
if (name.getParent() instanceof ICPPASTQualifiedName) {
|
|
||||||
if (name == ((ICPPASTQualifiedName)name.getParent()).getLastName())
|
|
||||||
name = (IASTName) name.getParent();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// if the lookup in base-classes ran into a deferred instance, use the computed unknown binding.
|
// 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)
|
if (candidate instanceof ICPPClassTemplatePartialSpecialization)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
|
// specialization is selected during instantiation
|
||||||
|
// mstodo why not?
|
||||||
|
// if (candidate instanceof ICPPTemplateInstance && candidate instanceof IType)
|
||||||
|
// candidate= ((ICPPTemplateInstance) candidate).getSpecializedBinding();
|
||||||
|
|
||||||
return candidate;
|
return candidate;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1737,9 +1699,16 @@ public class CPPSemantics {
|
||||||
} else {
|
} else {
|
||||||
continue;
|
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.
|
// select among those bindings that have been created without problems.
|
||||||
if (temp instanceof IProblemBinding)
|
if (temp instanceof IProblemBinding)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!(temp instanceof ICPPMember) && !declaredBefore)
|
if (!(temp instanceof ICPPMember) && !declaredBefore)
|
||||||
continue;
|
continue;
|
||||||
if (temp instanceof ICPPUsingDeclaration) {
|
if (temp instanceof ICPPUsingDeclaration) {
|
||||||
|
|
|
@ -381,7 +381,7 @@ public class CPPTemplates {
|
||||||
if (element instanceof ICPPASTTemplateId) {
|
if (element instanceof ICPPASTTemplateId) {
|
||||||
++i;
|
++i;
|
||||||
if (i == idx) {
|
if (i == idx) {
|
||||||
binding = ((ICPPASTTemplateId) element).getTemplateName().resolveBinding();
|
binding = ((ICPPASTTemplateId) element).resolveBinding();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -426,10 +426,9 @@ public class CPPTemplates {
|
||||||
|
|
||||||
public static IBinding createBinding(ICPPASTTemplateId id) {
|
public static IBinding createBinding(ICPPASTTemplateId id) {
|
||||||
IASTNode parent = id.getParent();
|
IASTNode parent = id.getParent();
|
||||||
int segment = -1;
|
boolean isLastName= true;
|
||||||
if (parent instanceof ICPPASTQualifiedName) {
|
if (parent instanceof ICPPASTQualifiedName) {
|
||||||
IASTName[] ns = ((ICPPASTQualifiedName) parent).getNames();
|
isLastName= ((ICPPASTQualifiedName) parent).getLastName() == id;
|
||||||
segment = (ns[ns.length - 1] == id) ? 1 : 0;
|
|
||||||
parent = parent.getParent();
|
parent = parent.getParent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -443,51 +442,66 @@ public class CPPTemplates {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (decl instanceof ICPPASTExplicitTemplateInstantiation &&
|
final boolean isClassDecl= parent instanceof ICPPASTElaboratedTypeSpecifier;
|
||||||
parent instanceof ICPPASTElaboratedTypeSpecifier && segment != 0) {
|
final boolean isClassDef = parent instanceof ICPPASTCompositeTypeSpecifier;
|
||||||
|
|
||||||
|
if (isLastName) {
|
||||||
|
if (isClassDecl && decl instanceof ICPPASTExplicitTemplateInstantiation)
|
||||||
return createExplicitClassInstantiation((ICPPASTElaboratedTypeSpecifier) parent);
|
return createExplicitClassInstantiation((ICPPASTElaboratedTypeSpecifier) parent);
|
||||||
} else if (((parent instanceof ICPPASTElaboratedTypeSpecifier &&
|
|
||||||
decl instanceof ICPPASTTemplateDeclaration) ||
|
if (isClassDef || (isClassDecl && decl instanceof ICPPASTTemplateDeclaration))
|
||||||
parent instanceof ICPPASTCompositeTypeSpecifier) &&
|
|
||||||
segment != 0) {
|
|
||||||
return createExplicitClassSpecialization((ICPPASTDeclSpecifier) parent);
|
return createExplicitClassSpecialization((ICPPASTDeclSpecifier) parent);
|
||||||
} else if (parent instanceof ICPPASTFunctionDeclarator && segment != 0) {
|
|
||||||
|
if (parent instanceof ICPPASTFunctionDeclarator)
|
||||||
return createFunctionSpecialization(id);
|
return createFunctionSpecialization(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
//a reference: class or function template?
|
if (!isLastName || isClassDecl || parent instanceof ICPPASTNamedTypeSpecifier ||
|
||||||
IBinding template = null;
|
parent instanceof ICPPASTBaseSpecifier) {
|
||||||
if (parent instanceof ICPPASTNamedTypeSpecifier ||
|
// class template instance
|
||||||
parent instanceof ICPPASTElaboratedTypeSpecifier ||
|
|
||||||
parent instanceof ICPPASTBaseSpecifier ||
|
|
||||||
segment == 0) {
|
|
||||||
//class template
|
|
||||||
IASTName templateName = id.getTemplateName();
|
IASTName templateName = id.getTemplateName();
|
||||||
template = templateName.resolveBinding();
|
IBinding template = templateName.resolveBinding();
|
||||||
if (template instanceof ICPPClassTemplatePartialSpecialization) {
|
if (template instanceof ICPPUnknownClassInstance) {
|
||||||
//specializations are selected during the instantiation, start with the primary template
|
// mstodo we should not get here, rather than that an unknown class
|
||||||
try {
|
// should be made to an unknown class instance here
|
||||||
template = ((ICPPClassTemplatePartialSpecialization) template).getPrimaryClassTemplate();
|
return template;
|
||||||
} catch (DOMException e) {
|
|
||||||
return e.getProblem();
|
|
||||||
}
|
}
|
||||||
} else if (template instanceof ICPPSpecialization && !(template instanceof ICPPTemplateDefinition)) {
|
if (template instanceof ICPPConstructor) {
|
||||||
template = ((ICPPSpecialization) template).getSpecializedBinding();
|
template= template.getOwner();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (template instanceof ICPPTemplateDefinition) {
|
if (!(template instanceof ICPPClassTemplate) || template instanceof ICPPClassTemplatePartialSpecialization)
|
||||||
ICPPTemplateArgument[] args= CPPTemplates.createTemplateArgumentArray(id);
|
return new ProblemBinding(id, IProblemBinding.SEMANTIC_INVALID_TYPE, templateName.toCharArray());
|
||||||
IBinding instance= instantiate((ICPPTemplateDefinition) template, args);
|
|
||||||
|
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);
|
return CPPSemantics.postResolution(instance, id);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
//functions are instantiated as part of the resolution process
|
//functions are instantiated as part of the resolution process
|
||||||
template = CPPVisitor.createBinding(id);
|
IBinding template = CPPVisitor.createBinding(id);
|
||||||
if (template instanceof ICPPTemplateInstance) {
|
if (template instanceof ICPPTemplateInstance) {
|
||||||
IASTName templateName = id.getTemplateName();
|
IASTName templateName = id.getTemplateName();
|
||||||
templateName.setBinding(((ICPPTemplateInstance) template).getTemplateDefinition());
|
templateName.setBinding(((ICPPTemplateInstance) template).getTemplateDefinition());
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return template;
|
return template;
|
||||||
} catch (DOMException e) {
|
} catch (DOMException e) {
|
||||||
return e.getProblem();
|
return e.getProblem();
|
||||||
|
@ -571,22 +585,10 @@ public class CPPTemplates {
|
||||||
}
|
}
|
||||||
return inst;
|
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 != null) {
|
||||||
if (spec instanceof ICPPInternalBinding)
|
if (spec instanceof ICPPInternalBinding)
|
||||||
((ICPPInternalBinding) spec).addDefinition(id);
|
((ICPPInternalBinding) spec).addDefinition(id);
|
||||||
|
@ -594,6 +596,7 @@ public class CPPTemplates {
|
||||||
}
|
}
|
||||||
|
|
||||||
spec = new CPPClassTemplatePartialSpecialization(id);
|
spec = new CPPClassTemplatePartialSpecialization(id);
|
||||||
|
// mstodo how to add partial specialization to class template from index?
|
||||||
if (template instanceof ICPPInternalClassTemplate)
|
if (template instanceof ICPPInternalClassTemplate)
|
||||||
((ICPPInternalClassTemplate) template).addPartialSpecialization(spec);
|
((ICPPInternalClassTemplate) template).addPartialSpecialization(spec);
|
||||||
return spec;
|
return spec;
|
||||||
|
@ -628,22 +631,33 @@ public class CPPTemplates {
|
||||||
if (args == null)
|
if (args == null)
|
||||||
return new ProblemBinding(name, IProblemBinding.SEMANTIC_INVALID_TYPE, name.toCharArray());
|
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))
|
while (!(parent instanceof IASTDeclaration))
|
||||||
parent = parent.getParent();
|
parent = parent.getParent();
|
||||||
|
|
||||||
IBinding owner= function.getOwner();
|
if (result instanceof ICPPInternalBinding) {
|
||||||
ICPPTemplateInstance instance= getInstance(function, args);
|
|
||||||
if (instance == null) {
|
|
||||||
instance = createInstance(owner, function, tpMap, args);
|
|
||||||
addInstance(function, args, instance);
|
|
||||||
}
|
|
||||||
if (instance instanceof ICPPInternalBinding) {
|
|
||||||
if (parent instanceof IASTSimpleDeclaration)
|
if (parent instanceof IASTSimpleDeclaration)
|
||||||
((ICPPInternalBinding) instance).addDeclaration(name);
|
((ICPPInternalBinding) result).addDeclaration(name);
|
||||||
else if (parent instanceof IASTFunctionDefinition)
|
else if (parent instanceof IASTFunctionDefinition)
|
||||||
((ICPPInternalBinding) instance).addDefinition(name);
|
((ICPPInternalBinding) result).addDefinition(name);
|
||||||
}
|
}
|
||||||
return instance;
|
return result;
|
||||||
} catch (DOMException e) {
|
} catch (DOMException e) {
|
||||||
return e.getProblem();
|
return e.getProblem();
|
||||||
}
|
}
|
||||||
|
@ -1642,6 +1656,22 @@ public class CPPTemplates {
|
||||||
return d1 - d2;
|
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)
|
static public ICPPTemplateDefinition selectSpecialization(ICPPClassTemplate template, ICPPTemplateArgument[] args)
|
||||||
throws DOMException {
|
throws DOMException {
|
||||||
if (template == null) {
|
if (template == null) {
|
||||||
|
@ -1874,12 +1904,41 @@ public class CPPTemplates {
|
||||||
return cost != null && cost.rank != Cost.NO_MATCH_RANK;
|
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) {
|
public static boolean isDependentArgument(ICPPTemplateArgument arg) {
|
||||||
if (arg.isTypeValue())
|
if (arg.isTypeValue())
|
||||||
return isDependentType(arg.getTypeValue());
|
return isDependentType(arg.getTypeValue());
|
||||||
|
|
||||||
return Value.isDependentValue(arg.getNonTypeValue());
|
return Value.isDependentValue(arg.getNonTypeValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isDependentType(IType t) {
|
public static boolean isDependentType(IType t) {
|
||||||
// mstodo needs to be extended
|
// mstodo needs to be extended
|
||||||
if (t instanceof ICPPTemplateParameter)
|
if (t instanceof ICPPTemplateParameter)
|
||||||
|
|
Loading…
Add table
Reference in a new issue