1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-23 14:42:11 +02:00

Correct argument deduction for function templates, bug 256113

This commit is contained in:
Markus Schorn 2008-11-26 16:20:43 +00:00
parent 941076063d
commit 5b9cd2b43e
15 changed files with 658 additions and 693 deletions

View file

@ -13,8 +13,6 @@ package org.eclipse.cdt.core.parser.tests.ast2;
import junit.framework.TestSuite;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionTemplate;
import org.eclipse.cdt.core.parser.ParserLanguage;
/**
@ -60,59 +58,7 @@ public class AST2CPPSpecFailingTest extends AST2SpecBaseTest {
public void _test7_3_3s12() throws Exception { // raised bug 161562 for that
parse(getAboveComment(), ParserLanguage.CPP, true, 0);
}
// template<class T> class task;
// template<class T> task<T>* preempt(task<T>*);
// template<class T> class task {
// // ...
// friend void next_time();
// friend void process(task<T>*);
// friend task<T>* preempt<T>(task<T>*);
// template<class C> friend int func(C);
// friend class task<int>;
// template<class P> friend class frd;
// // ...
// };
public void _test14_5_3s1() throws Exception { // TODO raised bug 90678
parse(getAboveComment(), ParserLanguage.CPP, true, 0);
}
// template <int I> class A;
// template <int I, int J> A<I+J> f/*1*/(A<I>, A<J>); // #1
// template <int K, int L> A<K+L> f/*2*/(A<K>, A<L>); // same as #1
// template <int I, int J> A<I-J> f/*3*/(A<I>, A<J>); // different from #1
public void _test14_5_5_1s5() throws Exception {
final String content= getAboveComment();
IASTTranslationUnit tu= parse(content, ParserLanguage.CPP, true, 0);
BindingAssertionHelper bh= new BindingAssertionHelper(content, true);
ICPPFunctionTemplate f1= bh.assertNonProblem("f/*1*/", 1);
ICPPFunctionTemplate f2= bh.assertNonProblem("f/*2*/", 1);
ICPPFunctionTemplate f3= bh.assertNonProblem("f/*3*/", 1);
assertSame(f1, f2);
assertNotSame(f1, f3);
}
// template <class T> void f(T t);
// template <class X> void g(const X x);
// template <class Z> void h(Z, Z*);
// int main()
// {
// // #1: function type is f(int), t is nonconst
// f<int>(1);
// // #2: function type is f(int), t is const
// f<const int>(1);
// // #3: function type is g(int), x is const
// g<int>(1);
// // #4: function type is g(int), x is const
// g<const int>(1);
// // #5: function type is h(int, const int*)
// h<const int>(1,0);
// }
public void _test14_8_2s3() throws Exception {
// mstodo this one must pass
parse(getAboveComment(), ParserLanguage.CPP, true, 0);
}
// template <class T> struct B { };
// template <class T> struct D : public B<T> {};
// struct D2 : public B<int> {};
@ -128,19 +74,6 @@ public class AST2CPPSpecFailingTest extends AST2SpecBaseTest {
parse(getAboveComment(), ParserLanguage.CPP, true, 0);
}
// template<class T> void f(T);
// class Complex {
// // ...
// Complex(double);
// };
// void g()
// {
// f<Complex>(1); // OK, means f<Complex>(Complex(1))
// }
public void _test14_8_1s4() throws Exception {
parse(getAboveComment(), ParserLanguage.CPP, true, 0);
}
// template<int i, typename T>
// T deduce(typename A<T>::X x, // T is not deduced here
// T t, // but T is deduced here
@ -155,17 +88,4 @@ public class AST2CPPSpecFailingTest extends AST2SpecBaseTest {
public void _test14_8_2_4s14() throws Exception {
parse(getAboveComment(), ParserLanguage.CPP, true, 0);
}
// template<class T> void f(T*,int); // #1
// template<class T> void f(T,char); // #2
// void h(int* pi, int i, char c)
// {
// f(pi,i); //#1: f<int>(pi,i)
// f(pi,c); //#2: f<int*>(pi,c)
// f(i,c); //#2: f<int>(i,c);
// f(i,i); //#2: f<int>(i,char(i))
// }
public void _test14_8_3s5() throws Exception {
parse(getAboveComment(), ParserLanguage.CPP, true, 0);
}
}

View file

@ -4604,6 +4604,22 @@ public class AST2CPPSpecTest extends AST2SpecBaseTest {
parse(getAboveComment(), ParserLanguage.CPP, true, 0);
}
// template<class T> class task;
// template<class T> task<T>* preempt(task<T>*);
// template<class T> class task {
// // ...
// friend void next_time();
// friend void process(task<T>*);
// friend task<T>* preempt<T>(task<T>*);
// template<class C> friend int func(C);
// friend class task<int>;
// template<class P> friend class frd;
// // ...
// };
public void test14_5_3s1() throws Exception {
parse(getAboveComment(), ParserLanguage.CPP, true, 0);
}
// namespace N {
// template <class T> void f(T);
// void g(int);
@ -5364,7 +5380,8 @@ public class AST2CPPSpecTest extends AST2SpecBaseTest {
// template <> void f<int>(int*); // OK
// template <> void f(int); // OK
public void test14_7_3s12() throws Exception {
parse(getAboveComment(), ParserLanguage.CPP, true, 1);
// gcc does not report the explicit instantiation as ambiguous, so we accept it as well.
parse(getAboveComment(), ParserLanguage.CPP, true, 0);
}
// template<class T> void f(T) { }
@ -5467,6 +5484,19 @@ public class AST2CPPSpecTest extends AST2SpecBaseTest {
parse(getAboveComment(), ParserLanguage.CPP, false, 0);
}
// template<class T> void f(T);
// class Complex {
// // ...
// Complex(double);
// };
// void g()
// {
// f<Complex>(1); // OK, means f<Complex>(Complex(1))
// }
public void test14_8_1s4() throws Exception {
parse(getAboveComment(), ParserLanguage.CPP, true, 0);
}
// namespace A {
// struct B { };
// template<int X> void f();
@ -5545,6 +5575,26 @@ public class AST2CPPSpecTest extends AST2SpecBaseTest {
parse(getAboveComment(), ParserLanguage.CPP, false, 1);
}
// template <class T> void f(T t);
// template <class X> void g(const X x);
// template <class Z> void h(Z, Z*);
// int main()
// {
// // #1: function type is f(int), t is nonconst
// f<int>(1);
// // #2: function type is f(int), t is const
// f<const int>(1);
// // #3: function type is g(int), x is const
// g<int>(1);
// // #4: function type is g(int), x is const
// g<const int>(1);
// // #5: function type is h(int, const int*)
// h<const int>(1,0);
// }
public void test14_8_2s3() throws Exception {
parse(getAboveComment(), ParserLanguage.CPP, true, 0);
}
// template <int> int f(int);
// template <signed char> int f(int);
// int i1 = f<1>(0); // ambiguous
@ -5707,6 +5757,19 @@ public class AST2CPPSpecTest extends AST2SpecBaseTest {
parse(getAboveComment(), ParserLanguage.CPP, true, 0);
}
// template<class T> void f(T*,int); // #1
// template<class T> void f(T,char); // #2
// void h(int* pi, int i, char c)
// {
// f(pi,i); //#1: f<int>(pi,i)
// f(pi,c); //#2: f<int*>(pi,c)
// f(i,c); //#2: f<int>(i,c);
// f(i,i); //#2: f<int>(i,char(i))
// }
public void test14_8_3s5() throws Exception {
parse(getAboveComment(), ParserLanguage.CPP, true, 0);
}
// template<class T> void f(T); // declaration
// void g() {
// f("Annemarie"); // call of f<const char*>
@ -6209,6 +6272,21 @@ public class AST2CPPSpecTest extends AST2SpecBaseTest {
parse(getAboveComment(), ParserLanguage.CPP, true, 0);
}
// template <int I> class A;
// template <int I, int J> A<I+J> f/*1*/(A<I>, A<J>); // #1
// template <int K, int L> A<K+L> f/*2*/(A<K>, A<L>); // same as #1
// template <int I, int J> A<I-J> f/*3*/(A<I>, A<J>); // different from #1
public void test14_5_5_1s5() throws Exception {
final String content= getAboveComment();
IASTTranslationUnit tu= parse(content, ParserLanguage.CPP, true, 0);
BindingAssertionHelper bh= new BindingAssertionHelper(content, true);
ICPPFunctionTemplate f1= bh.assertNonProblem("f/*1*/", 1);
ICPPFunctionTemplate f2= bh.assertNonProblem("f/*2*/", 1);
ICPPFunctionTemplate f3= bh.assertNonProblem("f/*3*/", 1);
assertSame(f1, f2);
assertNotSame(f1, f3);
}
// template <int I> class A;
// template <int I, int J> void f/*1*/(A<I+J>); // #1
// template <int K, int L> void f/*2*/(A<K+L>); // same as #1

View file

@ -2947,7 +2947,7 @@ public class AST2TemplateTests extends AST2BaseTest {
assertFalse(th1sCtor instanceof ICPPSpecialization);
ICPPTemplateNonTypeParameter np = ba.assertNonProblem("I>(I)", 1, ICPPTemplateNonTypeParameter.class);
ICPPClassType clazz= ba.assertNonProblem("That<I>(I)", 4, ICPPClassType.class);
ICPPConstructor clazz= ba.assertNonProblem("That<I>(I)", 4, ICPPConstructor.class);
ICPPConstructor ctor= ba.assertNonProblem("That<I>(I)", 7, ICPPConstructor.class);
ICPPTemplateNonTypeParameter np1 = ba.assertNonProblem("I)", 1, ICPPTemplateNonTypeParameter.class);
@ -2978,7 +2978,7 @@ public class AST2TemplateTests extends AST2BaseTest {
assertFalse(th1sCtor instanceof ICPPSpecialization);
ICPPTemplateTypeParameter np= ba.assertNonProblem("I>()", 1, ICPPTemplateTypeParameter.class);
ICPPClassType clazz= ba.assertNonProblem("That<I>()", 4, ICPPClassType.class);
ICPPConstructor clazz= ba.assertNonProblem("That<I>()", 4, ICPPConstructor.class);
ICPPConstructor ctor= ba.assertNonProblem("That<I>()", 7, ICPPConstructor.class);
}
@ -3294,4 +3294,50 @@ public class AST2TemplateTests extends AST2BaseTest {
public void testNewOfThisTemplate() throws Exception {
parseAndCheckBindings(getAboveComment(), ParserLanguage.CPP);
}
// template <class T> void f(T);
// class X {
// friend void f<>(int);
// };
public void testFunctionSpecializationAsFriend() throws Exception {
final String code = getAboveComment();
parseAndCheckBindings(code, ParserLanguage.CPP);
BindingAssertionHelper bh= new BindingAssertionHelper(code, true);
ICPPFunctionTemplate f= bh.assertNonProblem("f(T)", 1);
IFunction fref1= bh.assertNonProblem("f<>", 1);
assertSame(fref1, f);
IFunction fref2= bh.assertNonProblem("f<>", 3);
assertInstance(fref2, ICPPTemplateInstance.class);
assertSame(f, ((ICPPTemplateInstance) fref2).getSpecializedBinding());
}
// template <typename T> class XT {
// typedef int mytype1;
// mytype1 m1();
// };
// template <typename T> class XT<T*> {
// typedef int mytype2;
// mytype2 m2();
// };
// template <> class XT<int> {
// typedef int mytype3;
// mytype3 m3();
// };
// template <typename T> typename XT<T>::mytype1 XT<T>::m1() {}
// template <typename T> typename XT<T*>::mytype2 XT<T*>::m2() {}
// template <> typename XT<int>::mytype3 XT<int>::m3() {}
public void testMethodImplWithNonDeferredType() throws Exception {
final String code = getAboveComment();
parseAndCheckBindings(code, ParserLanguage.CPP);
BindingAssertionHelper bh= new BindingAssertionHelper(code, true);
ICPPMethod m1= bh.assertNonProblem("m1();", 2);
ICPPMethod m2= bh.assertNonProblem("m1() ", 2);
assertSame(m1, m2);
m1= bh.assertNonProblem("m2();", 2);
m2= bh.assertNonProblem("m2() ", 2);
assertSame(m1, m2);
m1= bh.assertNonProblem("m3();", 2);
m2= bh.assertNonProblem("m3() ", 2);
assertSame(m1, m2);
}
}

View file

@ -1419,7 +1419,7 @@ public class IndexCPPTemplateResolutionTest extends IndexBindingResolutionTestBa
*/
ICPPTemplateNonTypeParameter np= getBindingFromASTName("I>(I)", 1, ICPPTemplateNonTypeParameter.class);
ICPPClassType clazz= getBindingFromASTName("That<I>(I)", 4, ICPPClassType.class);
ICPPConstructor clazz= getBindingFromASTName("That<I>(I)", 4, ICPPConstructor.class);
ICPPConstructor ctor= getBindingFromASTName("That<I>(I)", 7, ICPPConstructor.class);
}
@ -1445,7 +1445,7 @@ public class IndexCPPTemplateResolutionTest extends IndexBindingResolutionTestBa
assertFalse(th1sCtor instanceof ICPPSpecialization);
ICPPTemplateTypeParameter np= getBindingFromASTName("I>()", 1, ICPPTemplateTypeParameter.class);
ICPPClassType clazz= getBindingFromASTName("That<I>()", 4, ICPPClassType.class);
ICPPConstructor clazz= getBindingFromASTName("That<I>()", 4, ICPPConstructor.class);
ICPPConstructor ctor= getBindingFromASTName("That<I>()", 7, ICPPConstructor.class);
}

View file

@ -28,6 +28,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespaceScope;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPReferenceType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPScope;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateArgument;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateInstance;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateScope;
import org.eclipse.cdt.core.dom.ast.gnu.cpp.IGPPBasicType;
@ -331,6 +332,10 @@ public class ASTTypeUtil {
} else {
result.append(getNameForAnonymous((ICompositeType) type));
}
if (type instanceof ICPPTemplateInstance) {
ICPPTemplateInstance inst = (ICPPTemplateInstance) type;
result.append(getArgumentListString(inst.getTemplateArguments(), normalize));
}
} else if (type instanceof ICPPReferenceType) {
result.append(Keywords.cpAMPER);
} else if (type instanceof IEnumeration) {

View file

@ -106,6 +106,6 @@ public class CPPDeferredClassInstance extends CPPUnknownClass implements ICPPDef
@Override
public String toString() {
return getName() + ASTTypeUtil.getArgumentListString(fArguments, true);
return ASTTypeUtil.getType(this, true);
}
}

View file

@ -6,13 +6,10 @@
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM - Initial API and implementation
* Andrew Niefer (IBM) - Initial API and implementation
* Markus Schorn (Wind River Systems)
* Sergey Prigogin (Google)
*******************************************************************************/
/*
* Created on Feb 11, 2005
*/
package org.eclipse.cdt.internal.core.dom.parser.cpp;
import org.eclipse.cdt.core.dom.ast.IASTName;
@ -28,7 +25,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPPointerToMemberType;
import org.eclipse.cdt.internal.core.index.IIndexType;
/**
* @author aniefer
* Models pointer to members.
*/
public class CPPPointerToMemberType extends CPPPointerType implements ICPPPointerToMemberType {
private ICPPASTPointerToMember operator;
@ -83,7 +80,7 @@ public class CPPPointerToMemberType extends CPPPointerType implements ICPPPointe
name = ns[ns.length - 1];
}
IBinding binding = name.resolveBinding();
IBinding binding = CPPASTNameBase.resolvePreBinding(name);
if (binding instanceof IType) {
classType = (IType) binding;
} else {

View file

@ -370,13 +370,13 @@ public class CPPSemantics {
}
if (binding != null && !(binding instanceof IProblemBinding)) {
if (data.forDefinition()) {
if (data.forFunctionDeclaration()) {
addDefinition(binding, data.astName);
}
}
// If we're still null...
if (binding == null) {
if (name instanceof ICPPASTQualifiedName && data.forDefinition())
if (name instanceof ICPPASTQualifiedName && data.forFunctionDeclaration())
binding = new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_MEMBER_DECLARATION_NOT_FOUND, data.name());
else
binding = new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_NAME_NOT_FOUND, data.name());
@ -1563,10 +1563,11 @@ public class CPPSemantics {
return null;
// specialization is selected during instantiation
if (candidate instanceof ICPPTemplateInstance && candidate instanceof IType)
if (candidate instanceof ICPPTemplateInstance)
candidate= ((ICPPTemplateInstance) candidate).getSpecializedBinding();
return candidate;
if (!(candidate instanceof ICPPFunctionTemplate))
return candidate;
}
}
@ -1736,6 +1737,12 @@ public class CPPSemantics {
items = (Object[]) data.foundItems;
continue;
} else if (temp instanceof IFunction) {
if (temp instanceof ICPPTemplateInstance) {
temp= ((ICPPTemplateInstance) temp).getSpecializedBinding();
if (!(temp instanceof IFunction))
continue;
}
IFunction function= (IFunction) temp;
if (function instanceof ICPPFunctionTemplate) {
if (templateFns == ObjectSet.EMPTY_SET)
@ -1811,7 +1818,8 @@ public class CPPSemantics {
int numTemplateFns = templateFns.size();
if (numTemplateFns > 0) {
if (data.functionParameters != null && !data.forDefinition()) {
if (data.functionParameters != null &&
(!data.forFunctionDeclaration() || data.forExplicitFunctionSpecialization())) {
IFunction[] fs = CPPTemplates.selectTemplateFunctions(templateFns, data.functionParameters, data.astName);
if (fs != null && fs.length > 0) {
if (fns == ObjectSet.EMPTY_SET)
@ -1853,19 +1861,6 @@ public class CPPSemantics {
return false;
}
static private boolean functionHasParameters(IFunction function, IASTParameterDeclaration[] params) throws DOMException{
IFunctionType ftype = function.getType();
if (params.length == 0) {
return ftype.getParameterTypes().length == 0;
}
IASTNode node = params[0].getParent();
if (node instanceof ICPPASTFunctionDeclarator) {
return isSameFunction(function, (IASTDeclarator) node);
}
return false;
}
static private void reduceToViable(LookupData data, IBinding[] functions) throws DOMException{
if (functions == null || functions.length == 0)
return;
@ -1873,7 +1868,7 @@ public class CPPSemantics {
Object[] fParams = data.functionParameters;
int numParameters = (fParams != null) ? fParams.length : 0;
int num;
boolean def = data.forDefinition();
boolean def = data.forFunctionDeclaration();
// Trim the list down to the set of viable functions
IFunction function = null;
int size = functions.length;
@ -1926,30 +1921,13 @@ public class CPPSemantics {
}
}
}
static private boolean isMatchingFunctionDeclaration(IFunction candidate, LookupData data) {
IASTName name = data.astName;
ICPPASTTemplateDeclaration decl = CPPTemplates.getTemplateDeclaration(name);
if (decl != null && !(candidate instanceof ICPPTemplateDefinition))
return false;
if (candidate instanceof ICPPTemplateDefinition && decl instanceof ICPPASTTemplateSpecialization) {
ICPPFunctionTemplate fn = CPPTemplates.resolveTemplateFunctions(new Object[] { candidate }, data.astName);
return (fn != null && !(fn instanceof IProblemBinding));
}
try {
IASTNode node = data.astName.getParent();
while (node instanceof IASTName)
node = node.getParent();
if (!(node instanceof ICPPASTFunctionDeclarator))
return false;
ICPPASTFunctionDeclarator dtor = (ICPPASTFunctionDeclarator) node;
ICPPFunctionType ftype = (ICPPFunctionType) candidate.getType();
if (dtor.isConst() != ftype.isConst() || dtor.isVolatile() != ftype.isVolatile())
return false;
return functionHasParameters(candidate, (IASTParameterDeclaration[]) data.functionParameters);
} catch (DOMException e) {
}
static private boolean isMatchingFunctionDeclaration(IFunction candidate, LookupData data) {
IASTNode node = data.astName.getParent();
while (node instanceof IASTName)
node = node.getParent();
if (node instanceof IASTDeclarator) {
return isSameFunction(candidate, (IASTDeclarator) node);
}
return false;
}
@ -2028,7 +2006,7 @@ public class CPPSemantics {
deferredOnly= false;
}
}
if (deferredOnly || data.forDefinition() || data.forExplicitInstantiation()) {
if (deferredOnly || data.forFunctionDeclaration()) {
for (IFunction fn : fns) {
if (fn != null) {
return fn;
@ -2147,6 +2125,7 @@ public class CPPSemantics {
// then this is an ambiguity (unless we find something better than both later).
ambiguous |= (hasWorse && hasBetter) || (!hasWorse && !hasBetter);
// mstodo if ambigous ??
if (!hasWorse) {
// If they are both template functions, we can order them that way
ICPPFunctionTemplate bestAsTemplate= asTemplate(bestFn);
@ -2336,10 +2315,10 @@ public class CPPSemantics {
break;
}
}
ICPPTemplateDefinition template = (ICPPTemplateDefinition) id.getTemplateName().resolveBinding();
if (template != null) {
IBinding template =id.getTemplateName().resolveBinding();
if (template instanceof ICPPTemplateDefinition) {
try {
ICPPTemplateParameter[] ps = template.getTemplateParameters();
ICPPTemplateParameter[] ps = ((ICPPTemplateDefinition)template).getTemplateParameters();
if (i < args.length && i < ps.length && ps[i] instanceof ICPPTemplateNonTypeParameter) {
return ((ICPPTemplateNonTypeParameter)ps[i]).getType();
}
@ -2668,20 +2647,24 @@ public class CPPSemantics {
}
public static boolean isSameFunction(IFunction function, IASTDeclarator declarator) {
IASTName name = declarator.getName();
IASTName name = CPPVisitor.findInnermostDeclarator(declarator).getName();
ICPPASTTemplateDeclaration templateDecl = CPPTemplates.getTemplateDeclaration(name);
boolean fnIsTemplate = (function instanceof ICPPFunctionTemplate);
boolean dtorIsTemplate = (templateDecl != null);
if (fnIsTemplate && dtorIsTemplate) {
return CPPTemplates.isSameTemplate((ICPPTemplateDefinition)function, name);
} else if (fnIsTemplate ^ dtorIsTemplate) {
return false;
if (templateDecl != null) {
if (templateDecl instanceof ICPPASTTemplateSpecialization) {
if (!(function instanceof ICPPTemplateInstance))
return false;
} else {
if (!(function instanceof ICPPTemplateDefinition))
return false;
}
}
IType type = null;
declarator= CPPVisitor.findTypeRelevantDeclarator(declarator);
try {
type = function.getType();
return type.isSameType(CPPVisitor.createType(declarator));
if (declarator instanceof ICPPASTFunctionDeclarator) {
IType type = function.getType();
return type.isSameType(CPPVisitor.createType(declarator));
}
} catch (DOMException e) {
}
return false;

View file

@ -44,7 +44,6 @@ import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.ITypedef;
import org.eclipse.cdt.core.dom.ast.IValue;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeclSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTElaboratedTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTExplicitTemplateInstantiation;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDeclarator;
@ -55,7 +54,6 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTSimpleTypeTemplateParameter;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateDeclaration;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateId;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateParameter;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateSpecialization;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplatedTypeTemplateParameter;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassSpecialization;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassTemplate;
@ -77,7 +75,6 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateInstance;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateNonTypeParameter;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateScope;
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;
@ -173,7 +170,7 @@ public class CPPTemplates {
return instance;
CPPTemplateParameterMap tpMap= new CPPTemplateParameterMap(args.length);
if (!CPPTemplates.deduceTemplateParameterMap(partialSpec.getTemplateArguments(), args, true, tpMap))
if (!CPPTemplates.deduceTemplateParameterMap(partialSpec.getTemplateArguments(), args, tpMap))
return null;
ICPPTemplateParameter[] params= partialSpec.getTemplateParameters();
@ -303,17 +300,22 @@ public class CPPTemplates {
* Instantiates the template for usage within its own body. May return <code>null</code>.
*/
public static IBinding instantiateWithinClassTemplate(ICPPClassTemplate template) throws DOMException {
ICPPTemplateParameter[] templateParameters = template.getTemplateParameters();
ICPPTemplateArgument[] args = new ICPPTemplateArgument[templateParameters.length];
for (int i = 0; i < templateParameters.length; i++) {
final ICPPTemplateParameter tp = templateParameters[i];
if (tp instanceof IType) {
args[i] = new CPPTemplateArgument((IType) tp);
} else if (tp instanceof ICPPTemplateNonTypeParameter) {
final ICPPTemplateNonTypeParameter nttp = (ICPPTemplateNonTypeParameter) tp;
args[i] = new CPPTemplateArgument(Value.create(nttp), nttp.getType());
} else {
assert false;
ICPPTemplateArgument[] args;
if (template instanceof ICPPClassTemplatePartialSpecialization) {
args= ((ICPPClassTemplatePartialSpecialization) template).getTemplateArguments();
} else {
ICPPTemplateParameter[] templateParameters = template.getTemplateParameters();
args = new ICPPTemplateArgument[templateParameters.length];
for (int i = 0; i < templateParameters.length; i++) {
final ICPPTemplateParameter tp = templateParameters[i];
if (tp instanceof IType) {
args[i] = new CPPTemplateArgument((IType) tp);
} else if (tp instanceof ICPPTemplateNonTypeParameter) {
final ICPPTemplateNonTypeParameter nttp = (ICPPTemplateNonTypeParameter) tp;
args[i] = new CPPTemplateArgument(Value.create(nttp), nttp.getType());
} else {
assert false;
}
}
}
return deferredInstance(template, args);
@ -425,388 +427,159 @@ public class CPPTemplates {
}
public static IBinding createBinding(ICPPASTTemplateId id) {
IASTNode parent = id.getParent();
boolean isLastName= true;
if (parent instanceof ICPPASTQualifiedName) {
isLastName= ((ICPPASTQualifiedName) parent).getLastName() == id;
parent = parent.getParent();
}
IASTNode decl= parent;
while (decl != null) {
if (decl instanceof IASTDeclaration) {
decl= decl.getParent();
break;
}
decl= decl.getParent();
}
try {
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);
if (parent instanceof ICPPASTFunctionDeclarator)
return createFunctionSpecialization(id);
}
if (!isLastName || isClassDecl || parent instanceof ICPPASTNamedTypeSpecifier ||
parent instanceof ICPPASTBaseSpecifier) {
// class template instance
IASTName templateName = id.getTemplateName();
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 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);
}
if (!isClassTemplate(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());
IBinding result= CPPVisitor.createBinding(id);
IASTName templateName = id.getTemplateName();
if (result instanceof ICPPTemplateInstance) {
templateName.setBinding(((ICPPTemplateInstance) result).getTemplateDefinition());
} else {
templateName.setBinding(result);
}
return template;
} catch (DOMException e) {
return e.getProblem();
}
}
protected static IBinding createExplicitClassInstantiation(ICPPASTElaboratedTypeSpecifier elabSpec) {
IASTName name = elabSpec.getName();
if (name instanceof ICPPASTQualifiedName) {
IASTName[] ns = ((ICPPASTQualifiedName) name).getNames();
name = ns[ns.length - 1];
}
ICPPASTTemplateId id = (ICPPASTTemplateId) name;
IBinding template = id.getTemplateName().resolveBinding();
try {
if (template instanceof ICPPClassTemplate) {
ICPPClassTemplate classTemplate = (ICPPClassTemplate) template;
ICPPTemplateArgument[] args= createTemplateArgumentArray(id);
IBinding binding= instantiate(classTemplate, args);
if (binding != null)
return binding;
}
} catch (DOMException e) {
return e.getProblem();
}
return new ProblemBinding(elabSpec, IProblemBinding.SEMANTIC_INVALID_TYPE, name.toCharArray());
}
/**
* Creates the binding for a partial or explicit class specialization.
* @throws DOMException
*/
protected static IBinding createExplicitClassSpecialization(ICPPASTDeclSpecifier compSpec) throws DOMException {
IASTName name = null;
if (compSpec instanceof ICPPASTElaboratedTypeSpecifier)
name = ((ICPPASTElaboratedTypeSpecifier) compSpec).getName();
else if (compSpec instanceof ICPPASTCompositeTypeSpecifier)
name = ((ICPPASTCompositeTypeSpecifier) compSpec).getName();
else
return null;
if (name instanceof ICPPASTQualifiedName) {
IASTName[] ns = ((ICPPASTQualifiedName) name).getNames();
name = ns[ns.length - 1];
}
ICPPASTTemplateId id = (ICPPASTTemplateId) name;
IBinding binding = id.getTemplateName().resolveBinding();
if (!(binding instanceof ICPPClassTemplate))
return null; //TODO: problem?
ICPPClassTemplate template = (ICPPClassTemplate) binding;
ICPPASTTemplateDeclaration templateDecl = getTemplateDeclaration(id);
if (templateDecl instanceof ICPPASTTemplateSpecialization) {
ICPPTemplateInstance inst = null;
ICPPTemplateParameter[] templateParams= template.getTemplateParameters();
ICPPTemplateArgument[] args= createTemplateArgumentArray(id);
CPPTemplateParameterMap tpMap = new CPPTemplateParameterMap(templateParams.length);
if (templateParams.length != args.length) {
return null; // mstodo problem or use default args?
}
args= SemanticUtil.getSimplifiedArguments(args);
for (int i = 0; i < templateParams.length; i++) {
tpMap.put(templateParams[i], args[i]);
}
inst= getInstance(template, args);
if (inst == null) {
IBinding owner= binding.getOwner();
inst= new CPPClassInstance(owner, template, tpMap, args);
addInstance(template, args, inst);
}
if (inst instanceof ICPPInternalBinding) {
IASTNode parent = id.getParent();
while (!(parent instanceof IASTDeclSpecifier))
parent = parent.getParent();
if (parent instanceof IASTElaboratedTypeSpecifier)
((ICPPInternalBinding) inst).addDeclaration(id);
else if (parent instanceof IASTCompositeTypeSpecifier)
((ICPPInternalBinding) inst).addDefinition(id);
}
return inst;
return result;
}
// 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);
return spec;
IASTNode parentOfName = id.getParent();
boolean isLastName= true;
if (parentOfName instanceof ICPPASTQualifiedName) {
isLastName= ((ICPPASTQualifiedName) parentOfName).getLastName() == id;
parentOfName = parentOfName.getParent();
}
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;
}
protected static IBinding createFunctionSpecialization(IASTName name) throws DOMException {
try {
LookupData data = new LookupData(name);
data.forceQualified = true;
ICPPScope scope = (ICPPScope) CPPVisitor.getContainingScope(name);
if (scope instanceof ICPPTemplateScope) {
scope = (ICPPScope) scope.getParent();
}
CPPSemantics.lookup(data, scope);
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)
return function;
if (name instanceof ICPPASTTemplateId) {
((ICPPASTTemplateId) name).getTemplateName().setBinding(function);
}
IASTNode parent = name.getParent();
while (parent instanceof IASTName)
parent = parent.getParent();
IASTParameterDeclaration[] ps = ((ICPPASTFunctionDeclarator) parent).getParameters();
final CPPTemplateParameterMap tpMap= new CPPTemplateParameterMap(ps.length);
ICPPTemplateArgument[] args= deduceTemplateFunctionArguments(function, ps, data.templateId, tpMap);
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());
boolean isDecl= false;
boolean isDef= false;
if (isLastName) {
if (parentOfName instanceof ICPPASTElaboratedTypeSpecifier) {
IASTNode parentOfDeclaration= parentOfName;
while (parentOfDeclaration != null) {
if (parentOfDeclaration instanceof IASTDeclaration) {
parentOfDeclaration= parentOfDeclaration.getParent();
break;
}
parentOfDeclaration= parentOfDeclaration.getParent();
}
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();
if (result instanceof ICPPInternalBinding) {
if (parent instanceof IASTSimpleDeclaration)
((ICPPInternalBinding) result).addDeclaration(name);
else if (parent instanceof IASTFunctionDefinition)
((ICPPInternalBinding) result).addDefinition(name);
}
return result;
isDecl= !(parentOfDeclaration instanceof ICPPASTExplicitTemplateInstantiation);
} else if (parentOfName instanceof ICPPASTCompositeTypeSpecifier) {
isDef= true;
}
}
try {
// class template instance
IBinding result= null;
IASTName templateName = id.getTemplateName();
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 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)) {
if (argsAreTrivial(classTemplate.getTemplateParameters(), args)) {
result= classTemplate;
} else {
ICPPClassTemplatePartialSpecialization partialSpec= findPartialSpecialization(classTemplate, args);
if (isDecl || isDef) {
if (partialSpec == null) {
partialSpec = new CPPClassTemplatePartialSpecialization(id);
// mstodo how to add partial specialization to class template from index?
if (template instanceof ICPPInternalClassTemplate)
((ICPPInternalClassTemplate) template).addPartialSpecialization(partialSpec);
return partialSpec;
}
}
if (partialSpec == null)
return new ProblemBinding(id, IProblemBinding.SEMANTIC_INVALID_TYPE, templateName.toCharArray());
result= partialSpec;
}
}
}
if (result == null) {
result= instantiate(classTemplate, args);
if (result instanceof ICPPInternalBinding) {
if (isDecl) {
((ICPPInternalBinding) result).addDeclaration(id);
} else if (isDef) {
((ICPPInternalBinding) result).addDefinition(id);
}
}
}
return CPPSemantics.postResolution(result, id);
} catch (DOMException e) {
return e.getProblem();
}
}
static protected ICPPFunctionTemplate resolveTemplateFunctions(Object[] items, IASTName name) {
if (items == null)
return null;
ICPPFunctionTemplate[] templates = null;
IBinding temp = null;
for (Object o : items) {
if (o instanceof IASTName) {
temp = ((IASTName) o).resolveBinding();
if (temp == null)
continue;
} else if (o instanceof IBinding) {
temp = (IBinding) o;
} else {
continue;
}
static boolean isClassTemplate(ICPPASTTemplateId id) {
IASTNode parentOfName = id.getParent();
if (temp instanceof ICPPTemplateInstance)
temp = ((ICPPTemplateInstance) temp).getTemplateDefinition();
if (temp instanceof ICPPFunctionTemplate)
templates = (ICPPFunctionTemplate[]) ArrayUtil.append(ICPPFunctionTemplate.class, templates, temp);
if (parentOfName instanceof ICPPASTQualifiedName) {
if (((ICPPASTQualifiedName) parentOfName).getLastName() != id)
return true;
parentOfName= parentOfName.getParent();
}
if (templates == null)
return null;
ICPPTemplateArgument[] templateArguments = null;
if (name instanceof ICPPASTTemplateId) {
try {
templateArguments= createTemplateArgumentArray((ICPPASTTemplateId) name);
} catch (DOMException e) {
return null;
IASTNode parentOfDeclaration= parentOfName;
while (parentOfDeclaration != null) {
if (parentOfDeclaration instanceof IASTDeclaration) {
parentOfDeclaration= parentOfDeclaration.getParent();
break;
}
}
int numArgs = (templateArguments != null) ? templateArguments.length : 0;
if (name.getParent() instanceof IASTName)
name = (IASTName) name.getParent();
IASTNode n = name.getParent();
if (n instanceof ICPPASTQualifiedName) {
n = n.getParent();
}
ICPPASTFunctionDeclarator fdtor = (ICPPASTFunctionDeclarator) n;
IType[] functionParameters = createTypeArray(fdtor.getParameters());
ICPPFunctionTemplate result = null;
outer: for (int i = 0; i < templates.length && templates[i] != null; i++) {
ICPPFunctionTemplate tmpl = templates[i];
CPPTemplateParameterMap map= new CPPTemplateParameterMap(functionParameters.length);
try {
if (!deduceTemplateParameterMapFromFunctionParameters(tmpl, functionParameters, map))
continue;
} catch (DOMException e) {
continue;
}
ICPPTemplateParameter[] params = null;
try {
params = tmpl.getTemplateParameters();
} catch (DOMException e) {
continue;
}
int numParams = params.length;
ICPPTemplateArgument arg = null;
for (int j = 0; j < numParams; j++) {
ICPPTemplateParameter param = params[j];
if (j < numArgs && templateArguments != null) {
arg = templateArguments[j];
} else {
arg = null;
}
ICPPTemplateArgument deducedArg= map.getArgument(param);
if (deducedArg != null) {
if (arg == null) {
map.put(param, deducedArg);
arg = deducedArg;
} else if (!deducedArg.isSameValue(arg)) {
continue outer;
}
}
arg= matchTemplateParameterAndArgument(param, arg, map);
if (arg == null) {
continue outer;
}
}
//made it this far, its a match
if (result != null) {
return new CPPFunctionTemplate.CPPFunctionTemplateProblem(name, IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP, name.toCharArray());
}
result = tmpl;
parentOfDeclaration= parentOfDeclaration.getParent();
}
return result;
return parentOfName instanceof ICPPASTElaboratedTypeSpecifier ||
parentOfName instanceof ICPPASTCompositeTypeSpecifier ||
parentOfName instanceof ICPPASTNamedTypeSpecifier ||
parentOfName instanceof ICPPASTBaseSpecifier;
}
/**
* Deduce arguments for a template function from the template id + the template function parameters.
*/
static protected ICPPTemplateArgument[] deduceTemplateFunctionArguments(ICPPFunctionTemplate primaryTemplate,
IASTParameterDeclaration[] ps, ICPPASTTemplateId id, CPPTemplateParameterMap map) throws DOMException {
ICPPTemplateParameter[] templateParameters = primaryTemplate.getTemplateParameters();
ICPPTemplateArgument[] arguments= createTemplateArgumentArray(id);
ICPPTemplateArgument[] result = new ICPPTemplateArgument[templateParameters.length];
arguments= SemanticUtil.getSimplifiedArguments(arguments);
if (arguments.length == result.length) {
for (int i = 0; i < templateParameters.length; i++) {
result[i] = arguments[i];
map.put(templateParameters[i], arguments[i]);
}
return result;
static private ICPPTemplateArgument[] deduceTemplateFunctionArguments(ICPPFunctionTemplate template,
ICPPTemplateArgument[] tmplArgs, IType[] fnArgs, CPPTemplateParameterMap map) throws DOMException {
final ICPPTemplateParameter[] tmplParams = template.getTemplateParameters();
final int length = tmplParams.length;
if (tmplArgs.length > length)
return null;
ICPPTemplateArgument[] result = new ICPPTemplateArgument[length];
tmplArgs= SemanticUtil.getSimplifiedArguments(tmplArgs);
for (int i = 0; i < tmplArgs.length; i++) {
ICPPTemplateArgument tmplArg= tmplArgs[i];
final ICPPTemplateParameter tmplParam= tmplParams[i];
tmplArg= matchTemplateParameterAndArgument(tmplParam, tmplArg, map);
if (tmplArg == null)
return null;
map.put(tmplParam, tmplArg);
result[i]= tmplArg;
}
//else need to deduce some arguments
IType[] paramTypes = createTypeArray(ps);
if (deduceTemplateParameterMapFromFunctionParameters(primaryTemplate, paramTypes, map)) {
for (int i = 0; i < templateParameters.length; i++) {
ICPPTemplateParameter param = templateParameters[i];
ICPPTemplateArgument arg = null;
if (i < arguments.length)
arg = arguments[i];
ICPPTemplateArgument deducedArg= map.getArgument(param);
if (deducedArg != null) {
if (arg == null) {
map.put(param, deducedArg);
arg = deducedArg;
} else if (!deducedArg.isSameValue(arg)) {
return null;
}
}
arg= matchTemplateParameterAndArgument(param, arg, map);
if (arg == null)
if (!deduceTemplateParameterMapFromFunctionParameters(template, fnArgs, map))
return null;
for (int i = 0; i < length; i++) {
if (result[i] == null) {
ICPPTemplateArgument deducedArg= map.getArgument(tmplParams[i]);
if (deducedArg == null)
return null;
result[i] = arg;
result[i]= deducedArg;
}
return result;
}
return null;
return result;
}
public static ICPPTemplateInstance createInstance(IBinding owner, ICPPTemplateDefinition template,
@ -868,7 +641,16 @@ public class CPPTemplates {
public static IValue instantiateValue(IValue value, ICPPTemplateParameterMap tpMap) {
if (value == null)
return null;
// mstodo- instantiate values
// mstodo- instantiate values correctly
int parPos= Value.isTemplateParameter(value);
if (parPos > 0) {
ICPPTemplateArgument arg = tpMap.getArgument(parPos);
if (arg != null) {
IValue mappedValue = arg.getNonTypeValue();
if (mappedValue != null)
return mappedValue;
}
}
return value;
}
@ -938,10 +720,12 @@ public class CPPTemplates {
ICPPPointerToMemberType ptm = (ICPPPointerToMemberType) type;
IType memberOfClass = ptm.getMemberOfClass();
IType newMemberOfClass = instantiateType(memberOfClass, tpMap, within);
if ((newNestedType != nestedType || newMemberOfClass != memberOfClass) &&
newMemberOfClass instanceof ICPPClassType) {
return new CPPPointerToMemberType(newNestedType, (ICPPClassType) newMemberOfClass,
if (newNestedType != nestedType || newMemberOfClass != memberOfClass) {
if (newMemberOfClass instanceof ICPPClassType) {
return new CPPPointerToMemberType(newNestedType, (ICPPClassType) newMemberOfClass,
ptm.isConst(), ptm.isVolatile());
}
return type;
}
}
if (newNestedType != nestedType) {
@ -1203,12 +987,8 @@ public class CPPTemplates {
ICPPClassTemplatePartialSpecialization spec = (ICPPClassTemplatePartialSpecialization) definition;
ICPPTemplateArgument[] args= createTemplateArgumentArray((ICPPASTTemplateId)name);
ICPPTemplateArgument[] specArgs = spec.getTemplateArguments();
if (args.length == specArgs.length) {
for (int i=0; i < args.length; i++) {
if (!specArgs[i].isSameValue(args[i]))
return false;
}
}
if (!areSameArguments(args, specArgs))
return false;
}
return true;
}
@ -1219,6 +999,16 @@ public class CPPTemplates {
}
return false;
}
public static boolean areSameArguments(ICPPTemplateArgument[] args, ICPPTemplateArgument[] specArgs) {
if (args.length == specArgs.length) {
for (int i=0; i < args.length; i++) {
if (!specArgs[i].isSameValue(args[i]))
return false;
}
}
return true;
}
/**
* @param id the template id containing the template arguments
@ -1285,62 +1075,31 @@ public class CPPTemplates {
if (templates == null || templates.size() == 0)
return null;
IFunction[] instances = null;
int size = templates.size();
int numTemplateArgs = 0;
ICPPTemplateArgument[] templateArguments = null;
if (name instanceof ICPPASTTemplateId) {
ICPPTemplateArgument[] templateArguments = ICPPTemplateArgument.EMPTY_ARGUMENTS;
if (name instanceof ICPPASTTemplateId) {
try {
templateArguments = createTemplateArgumentArray((ICPPASTTemplateId) name);
} catch (DOMException e) {
return new IFunction[0];
}
numTemplateArgs = templateArguments.length;
}
final IType[] fnArgs= createTypeArray(functionArguments);
IType[] fnArgs= createTypeArray(functionArguments);
outer: for (int idx = 0; idx < size; idx++) {
IFunction[] instances= null;
final int size = templates.size();
for (int idx = 0; idx < size; idx++) {
ICPPFunctionTemplate template = (ICPPFunctionTemplate) templates.keyAt(idx);
CPPTemplateParameterMap map= new CPPTemplateParameterMap(fnArgs.length);
try {
if (!deduceTemplateParameterMapFromFunctionParameters(template, fnArgs, map))
continue;
} catch (DOMException e) {
continue;
}
ICPPTemplateParameter[] templateParams = null;
try {
templateParams = template.getTemplateParameters();
} catch (DOMException e1) {
continue outer;
}
int numTemplateParams = templateParams.length;
ICPPTemplateArgument[] instanceArgs = null;
for (int i = 0; i < numTemplateParams; i++) {
ICPPTemplateArgument arg = (i < numTemplateArgs && templateArguments != null) ? templateArguments[i] : null;
ICPPTemplateArgument mapped = map.getArgument(templateParams[i]);
if (arg != null && mapped != null) {
if (arg.isSameValue(mapped))
instanceArgs = (ICPPTemplateArgument[]) ArrayUtil.append(ICPPTemplateArgument.class, instanceArgs, arg);
else
continue outer;
} else if (arg == null && mapped == null) {
continue outer;
} else {
instanceArgs = (ICPPTemplateArgument[]) ArrayUtil.append(ICPPTemplateArgument.class, instanceArgs, (arg != null) ? arg : mapped);
ICPPTemplateArgument[] args= deduceTemplateFunctionArguments(template, templateArguments, fnArgs, map);
if (args != null) {
IBinding temp= instantiate(template, args);
if (temp instanceof IFunction) {
instances = (IFunction[]) ArrayUtil.append(IFunction.class, instances, temp);
}
}
}
instanceArgs= (ICPPTemplateArgument[]) ArrayUtil.trim(ICPPTemplateArgument.class, instanceArgs);
IBinding temp= instantiate(template, instanceArgs);
if (temp instanceof IFunction) {
instances = (IFunction[]) ArrayUtil.append(IFunction.class, instances, temp);
} catch (DOMException e) {
// try next candidate
}
}
@ -1351,41 +1110,36 @@ public class CPPTemplates {
* Deduces the mapping for the template parameters from the function parameters,
* returns <code>false</code> if there is no mapping.
*/
private static boolean deduceTemplateParameterMapFromFunctionParameters(ICPPFunctionTemplate template, IType[] arguments, CPPTemplateParameterMap map) throws DOMException{
private static boolean deduceTemplateParameterMapFromFunctionParameters(ICPPFunctionTemplate template, IType[] fnArgs, CPPTemplateParameterMap map) throws DOMException{
ICPPFunction function = (ICPPFunction) template;
IType[] functionParameters = null;
try {
functionParameters = function.getType().getParameterTypes();
return deduceTemplateParameterMap(functionParameters, arguments, false, map);
IType[] fnPars = function.getType().getParameterTypes();
int len= Math.min(fnPars.length, fnArgs.length);
for (int j= 0; j < len; j++) {
IType par= fnPars[j];
par= instantiateType(par, map, null);
if (!isValidType(par))
return false;
par= SemanticUtil.adjustParameterType(par);
if (isDependentType(par) && !deduceTemplateParameterMap(par, fnArgs[j], map)) {
return false;
}
}
return true;
} catch (DOMException e) {
}
return false;
}
/**
* Deduces the template parameter mapping from pairs of types.
*/
public static boolean deduceTemplateParameterMap(final IType[] specArgs, final IType[] args, final boolean all, CPPTemplateParameterMap map) throws DOMException {
if (specArgs == null || (all && specArgs.length != args.length)) {
return false;
}
int len= all ? specArgs.length : Math.min(specArgs.length, args.length);
for (int j= 0; j < len; j++) {
if (!deduceTemplateParameterMap(specArgs[j], args[j], map)) {
return false;
}
}
return true;
}
/**
* Deduces the template parameter mapping from pairs of template arguments.
*/
public static boolean deduceTemplateParameterMap(final ICPPTemplateArgument[] p, final ICPPTemplateArgument[] a, final boolean all, CPPTemplateParameterMap map) throws DOMException {
if (p == null || (all && p.length != a.length)) {
public static boolean deduceTemplateParameterMap(final ICPPTemplateArgument[] p, final ICPPTemplateArgument[] a, CPPTemplateParameterMap map) throws DOMException {
final int len= a.length;
if (p == null || p.length != len) {
return false;
}
int len= Math.min(p.length, a.length);
for (int j=0; j<len; j++) {
if (!deduceTemplateParameterMap(p[j], a[j], map)) {
return false;
@ -1691,7 +1445,7 @@ public class CPPTemplates {
boolean bestMatchIsBest = true;
for (int i = 0; i < size; i++) {
spec = specializations[i];
if (deduceTemplateParameterMap(spec.getTemplateArguments(), args, true, new CPPTemplateParameterMap(args.length))) {
if (deduceTemplateParameterMap(spec.getTemplateArguments(), args, new CPPTemplateParameterMap(args.length))) {
int compare = orderSpecializations(bestMatch, spec);
if (compare == 0) {
bestMatchIsBest = false;
@ -1781,14 +1535,12 @@ public class CPPTemplates {
*/
static private ICPPFunctionTemplate classTemplateSpecializationToFunctionTemplate(ICPPClassTemplatePartialSpecialization specialization) {
try {
ICPPTemplateDefinition template = specialization;
ICPPTemplateArgument[] args= specialization.getTemplateArguments();
IType paramType = (IType) instantiate(template, args);
if (paramType == null)
// ICPPTemplateArgument[] args= specialization.getTemplateArguments();
IBinding paramType = instantiateWithinClassTemplate(specialization);
if (!(paramType instanceof IType))
return null;
IParameter[] functionParameters = new IParameter[] { new CPPParameter(paramType) };
IParameter[] functionParameters = new IParameter[] { new CPPParameter((IType) paramType) };
return new CPPImplicitFunctionTemplate(specialization.getTemplateParameters(), functionParameters);
} catch (DOMException e) {
@ -1796,8 +1548,7 @@ public class CPPTemplates {
}
}
static private boolean isValidArgument(ICPPTemplateParameter param, ICPPTemplateArgument argument) {
IType t= argument.getTypeValue();
static private boolean isValidType(IType t) {
try {
while (t instanceof ITypeContainer) {
t = ((ITypeContainer) t).getType();
@ -1810,7 +1561,7 @@ public class CPPTemplates {
static protected ICPPTemplateArgument matchTemplateParameterAndArgument(ICPPTemplateParameter param,
ICPPTemplateArgument arg, CPPTemplateParameterMap map) {
if (arg == null || !isValidArgument(param, arg)) {
if (arg == null || !isValidType(arg.getTypeValue())) {
return null;
}
if (param instanceof ICPPTemplateTypeParameter) {
@ -1904,7 +1655,7 @@ public class CPPTemplates {
return cost != null && cost.rank != Cost.NO_MATCH_RANK;
}
private static boolean argsAreTrivial(ICPPTemplateParameter[] pars, ICPPTemplateArgument[] args) {
static boolean argsAreTrivial(ICPPTemplateParameter[] pars, ICPPTemplateArgument[] args) {
if (pars.length != args.length) {
return false;
}
@ -1940,11 +1691,33 @@ public class CPPTemplates {
}
public static boolean isDependentType(IType t) {
// mstodo needs to be extended
if (t instanceof ICPPTemplateParameter)
return true;
t = SemanticUtil.getUltimateType(t, false);
return t instanceof ICPPUnknownBinding;
try {
while (true) {
if (t instanceof ICPPTemplateParameter || t instanceof ICPPUnknownBinding)
return true;
if (t instanceof ICPPFunctionType) {
final ICPPFunctionType ft = (ICPPFunctionType) t;
IType[] types= ft.getParameterTypes();
for (IType type : types) {
if (isDependentType(type))
return true;
}
t= ft.getReturnType();
} else if (t instanceof ICPPPointerToMemberType) {
ICPPPointerToMemberType ptmt= (ICPPPointerToMemberType) t;
if (isDependentType(ptmt.getMemberOfClass()))
return true;
t= ptmt.getType();
} else if (t instanceof ITypeContainer) {
t= ((ITypeContainer) t).getType();
} else {
return false;
}
}
} catch (DOMException e) {
// treat as non-dependent
return false;
}
}
public static boolean containsDependentArg(ObjectMap tpMap) {

View file

@ -93,6 +93,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTElaboratedTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTExplicitTemplateInstantiation;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFieldReference;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDeclarator;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDefinition;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTIfStatement;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTLinkageSpecification;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamedTypeSpecifier;
@ -120,6 +121,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPBasicType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPBlockScope;
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.ICPPFunction;
@ -131,6 +133,8 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPPointerToMemberType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPReferenceType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPScope;
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.ICPPTemplateInstance;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateNonTypeParameter;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateScope;
@ -176,6 +180,7 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPVariable;
import org.eclipse.cdt.internal.core.dom.parser.cpp.GPPBasicType;
import org.eclipse.cdt.internal.core.dom.parser.cpp.GPPPointerToMemberType;
import org.eclipse.cdt.internal.core.dom.parser.cpp.GPPPointerType;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPDeferredClassInstance;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPInternalBinding;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPInternalFunction;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownBinding;
@ -190,9 +195,6 @@ public class CPPVisitor extends ASTQueries {
public static final String STD = "std"; //$NON-NLS-1$
public static final String TYPE_INFO= "type_info"; //$NON-NLS-1$
/**
* @param name
*/
public static IBinding createBinding(IASTName name) {
IASTNode parent = name.getParent();
IBinding binding = null;
@ -200,8 +202,7 @@ public class CPPVisitor extends ASTQueries {
parent instanceof ICPPASTQualifiedName ||
parent instanceof ICPPASTBaseSpecifier ||
parent instanceof ICPPASTConstructorChainInitializer ||
name.getPropertyInParent() == ICPPASTNamespaceAlias.MAPPING_NAME ||
parent instanceof ICPPASTTemplateId) {
name.getPropertyInParent() == ICPPASTNamespaceAlias.MAPPING_NAME) {
binding = CPPSemantics.resolveBinding(name);
if (binding instanceof IProblemBinding && parent instanceof ICPPASTQualifiedName &&
!(parent.getParent() instanceof ICPPASTNamespaceAlias)) {
@ -225,7 +226,15 @@ public class CPPVisitor extends ASTQueries {
} else {
return binding;
}
}
} else if (parent instanceof ICPPASTTemplateId) {
final ICPPASTTemplateId id = (ICPPASTTemplateId) parent;
if (CPPTemplates.isClassTemplate(id))
return CPPSemantics.resolveBinding(name);
// function templates/instances/specializations must be resolved via the id
id.resolveBinding();
return name.getBinding();
}
if (parent instanceof IASTIdExpression) {
return resolveBinding(parent);
} else if (parent instanceof ICPPASTFieldReference) {
@ -425,7 +434,7 @@ public class CPPVisitor extends ASTQueries {
scope= (ICPPScope) scope.getParent();
}
if (name instanceof ICPPASTTemplateId) {
return CPPTemplates.createExplicitClassSpecialization(compType);
return CPPTemplates.createBinding((ICPPASTTemplateId) name);
}
if (name.toCharArray().length > 0 && scope != null) //can't lookup anonymous things
binding = scope.getBinding(name, false);
@ -522,24 +531,36 @@ public class CPPVisitor extends ASTQueries {
return candidate;
}
ASTNodeProperty prop = parent.getPropertyInParent();
if (parent instanceof IASTTypeId) {
// function type
if (parent instanceof IASTTypeId)
return CPPSemantics.resolveBinding(name);
} else if (prop == ICPPASTTemplateSpecialization.OWNED_DECLARATION ||
prop == ICPPASTExplicitTemplateInstantiation.OWNED_DECLARATION) {
try {
return CPPTemplates.createFunctionSpecialization(name);
} catch (DOMException e) {
return e.getProblem();
// explicit instantiations
ASTNodeProperty prop = parent.getPropertyInParent();
if (prop == ICPPASTExplicitTemplateInstantiation.OWNED_DECLARATION)
return CPPSemantics.resolveBinding(name);
// explicit specializations
if (prop == ICPPASTTemplateSpecialization.OWNED_DECLARATION) {
IBinding b= CPPSemantics.resolveBinding(name);
if (b instanceof ICPPInternalBinding) {
if (parent instanceof ICPPASTFunctionDefinition)
((ICPPInternalBinding) b).addDefinition(name);
else
((ICPPInternalBinding) b).addDeclaration(name);
}
} else if (prop == ICPPASTTemplateDeclaration.PARAMETER) {
return b;
}
// function type for non-type template parameter
if (prop == ICPPASTTemplateDeclaration.PARAMETER) {
return CPPTemplates.createBinding((ICPPASTTemplateParameter) parent);
}
// function declaration/defintion
IBinding binding;
ICPPScope scope = (ICPPScope) getContainingScope((IASTNode) name);
boolean template = false;
boolean template= false;
boolean isFriendDecl= false;
try {
while (scope instanceof ICPPTemplateScope) {
template = true;
@ -550,11 +571,13 @@ public class CPPVisitor extends ASTQueries {
if (declSpec.isFriend()) {
try {
scope = (ICPPScope) getParentScope(scope, name.getTranslationUnit());
isFriendDecl= true;
} catch (DOMException e1) {
}
}
}
binding = (scope != null) ? scope.getBinding(name, false) : null;
boolean forceResolve= isFriendDecl && name instanceof ICPPASTTemplateId;
binding = (scope != null) ? scope.getBinding(name, forceResolve) : null;
} catch (DOMException e) {
return e.getProblem();
}
@ -866,6 +889,20 @@ public class CPPVisitor extends ASTQueries {
inputNode.getRawSignature().toCharArray());
}
/**
* Searches for an enclosing function definition or declaration, returns
* the name of the function. If you pass the name of a function, it will be returned.
*/
public static ICPPASTFunctionDefinition findEnclosingFunctionDefinition(IASTNode node) {
while (node != null) {
if (node instanceof ICPPASTFunctionDefinition) {
return (ICPPASTFunctionDefinition) node;
}
node= node.getParent();
}
return null;
}
public static IScope getContainingScope(IASTName name) {
IScope scope= getContainingScopeOrNull(name);
if (scope == null) {
@ -910,7 +947,11 @@ public class CPPVisitor extends ASTQueries {
boolean done= true;
IScope scope= null;
if (binding instanceof ICPPClassType) {
scope= ((ICPPClassType)binding).getCompositeScope();
if (binding instanceof ICPPDeferredClassInstance) {
scope= checkForSpecializedScope((ICPPDeferredClassInstance) binding, qname);
}
if (scope == null)
scope= ((ICPPClassType)binding).getCompositeScope();
} else if (binding instanceof ICPPNamespace) {
scope= ((ICPPNamespace)binding).getNamespaceScope();
} else if (binding instanceof ICPPUnknownBinding) {
@ -956,6 +997,47 @@ public class CPPVisitor extends ASTQueries {
return getContainingScope(parent);
}
/**
* Checks whether the scope for a deferred instance should be a specialized variant of
* the class-template.
*/
private static IScope checkForSpecializedScope(ICPPDeferredClassInstance dcli, final ICPPASTQualifiedName qname)
throws DOMException {
ICPPClassTemplate ct = dcli.getClassTemplate();
ICPPTemplateArgument[] args = dcli.getTemplateArguments();
IASTName start= qname;
ICPPASTFunctionDefinition func= findEnclosingFunctionDefinition(qname);
if (func != null) {
start= findInnermostDeclarator(func.getDeclarator()).getName();
if (start == qname)
return null;
start= start.getLastName();
}
IScope lookupScope= getContainingNonTemplateScope(start);
while (lookupScope != null) {
if (lookupScope instanceof ICPPClassScope) {
ICPPClassScope clscope= (ICPPClassScope) lookupScope;
ICPPClassType ctype = clscope.getClassType();
if (ctype instanceof ICPPClassTemplatePartialSpecialization) {
ICPPTemplateArgument[] args1 = ((ICPPClassTemplatePartialSpecialization) ctype).getTemplateArguments();
if (CPPTemplates.areSameArguments(args, args1))
return lookupScope;
} else if (ctype instanceof ICPPTemplateInstance) {
ICPPTemplateArgument[] args1 = ((ICPPTemplateInstance) ctype).getTemplateArguments();
if (CPPTemplates.areSameArguments(args, args1))
return lookupScope;
} else if (ctype instanceof ICPPClassTemplate) {
if (ct.isSameType(ctype) &&
CPPTemplates.argsAreTrivial(ct.getTemplateParameters(), args)) {
return lookupScope;
}
}
}
lookupScope= lookupScope.getParent();
}
return null;
}
public static IScope getContainingScope(IASTStatement statement) {
IASTNode parent = statement.getParent();
IScope scope = null;
@ -1495,36 +1577,7 @@ public class CPPVisitor extends ASTQueries {
pt = createType(pDeclSpec);
pt = createType(pt, pDtor);
// bug 239975
IType noTypedef= SemanticUtil.getUltimateTypeViaTypedefs(pt);
//8.3.5-3
//Any cv-qualifier modifying a parameter type is deleted.
//so only create the base type from the declspec and not the qualifiers
try {
if (noTypedef instanceof IQualifierType) {
pt= ((IQualifierType) noTypedef).getType();
noTypedef= SemanticUtil.getUltimateTypeViaTypedefs(pt);
}
if (noTypedef instanceof CPPPointerType) {
pt= ((CPPPointerType) noTypedef).stripQualifiers();
noTypedef= SemanticUtil.getUltimateTypeViaTypedefs(pt);
}
//any parameter of type array of T is adjusted to be pointer to T
if (noTypedef instanceof IArrayType) {
IArrayType at = (IArrayType) noTypedef;
pt = new CPPPointerType(at.getType());
noTypedef= SemanticUtil.getUltimateTypeViaTypedefs(pt);
}
} catch (DOMException e) {
pt = e.getProblem();
}
//any parameter to type function returning T is adjusted to be pointer to function
if (noTypedef instanceof IFunctionType) {
pt = new CPPPointerType(pt);
}
pt = SemanticUtil.adjustParameterType(pt);
pTypes[i] = pt;
}

View file

@ -51,6 +51,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNewExpression;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateDeclaration;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateId;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateSpecialization;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTUnaryExpression;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTUsingDeclaration;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTUsingDirective;
@ -160,7 +161,7 @@ class LookupData {
return false;
}
public boolean forDefinition() {
public boolean forFunctionDeclaration() {
if (astName == null) return false;
if (astName.getPropertyInParent() == CPPSemantics.STRING_LOOKUP_PROPERTY) return false;
@ -169,39 +170,73 @@ class LookupData {
n = (IASTName) n.getParent();
IASTNode p1 = n.getParent();
if (p1 instanceof ICPPASTQualifiedName) {
IASTName[] ns = ((ICPPASTQualifiedName)p1).getNames();
if (ns[ns.length - 1] != n)
return false;
if (((ICPPASTQualifiedName) p1).getLastName() != n)
return false;
p1 = p1.getParent();
}
IASTNode p2 = p1.getParent();
if (p1 instanceof IASTDeclarator && p2 instanceof IASTSimpleDeclaration) {
return !(p2.getParent() instanceof ICPPASTExplicitTemplateInstantiation);
}
return (p1 instanceof IASTDeclarator && p2 instanceof IASTFunctionDefinition);
}
public boolean forExplicitInstantiation() {
if (astName == null) return false;
if (astName.getPropertyInParent() == CPPSemantics.STRING_LOOKUP_PROPERTY) return false;
IASTName n = astName;
if (n.getParent() instanceof ICPPASTTemplateId)
n = (IASTName) n.getParent();
IASTNode p1 = n.getParent();
if (p1 instanceof ICPPASTQualifiedName) {
IASTName[] ns = ((ICPPASTQualifiedName)p1).getNames();
if (ns[ns.length - 1] != n)
return false;
p1 = p1.getParent();
}
IASTNode p2 = p1.getParent();
if (p1 instanceof IASTDeclarator && p2 instanceof IASTSimpleDeclaration) {
return (p2.getParent() instanceof ICPPASTExplicitTemplateInstantiation);
if (p1 instanceof IASTDeclarator) {
IASTNode p2= CPPVisitor.findOutermostDeclarator((IASTDeclarator) p1).getParent();
if (p2 instanceof IASTSimpleDeclaration) {
if (p2.getParent() instanceof ICPPASTExplicitTemplateInstantiation)
return false;
if (astName instanceof ICPPASTTemplateId &&
((ICPPASTDeclSpecifier)((IASTSimpleDeclaration)p2).getDeclSpecifier()).isFriend())
return false;
return true;
}
return p2 instanceof IASTFunctionDefinition;
}
return false;
}
public boolean forExplicitFunctionSpecialization() {
if (astName == null) return false;
if (astName.getPropertyInParent() == CPPSemantics.STRING_LOOKUP_PROPERTY) return false;
IASTName n = astName;
if (n.getParent() instanceof ICPPASTTemplateId)
n = (IASTName) n.getParent();
IASTNode p1 = n.getParent();
if (p1 instanceof ICPPASTQualifiedName) {
if (((ICPPASTQualifiedName) p1).getLastName() != n)
return false;
p1 = p1.getParent();
}
if (p1 instanceof IASTDeclarator) {
IASTNode p2= CPPVisitor.findOutermostDeclarator((IASTDeclarator) p1).getParent();
if (p2 instanceof IASTSimpleDeclaration || p2 instanceof IASTFunctionDefinition) {
return p2.getParent() instanceof ICPPASTTemplateSpecialization;
}
}
return false;
}
public boolean forExplicitFunctionInstantiation() {
if (astName == null) return false;
if (astName.getPropertyInParent() == CPPSemantics.STRING_LOOKUP_PROPERTY) return false;
IASTName n = astName;
if (n.getParent() instanceof ICPPASTTemplateId)
n = (IASTName) n.getParent();
IASTNode p1 = n.getParent();
if (p1 instanceof ICPPASTQualifiedName) {
if (((ICPPASTQualifiedName) p1).getLastName() != n)
return false;
p1 = p1.getParent();
}
if (p1 instanceof IASTDeclarator) {
IASTNode p2= CPPVisitor.findOutermostDeclarator((IASTDeclarator) p1).getParent();
if (p2 instanceof IASTDeclaration) {
return p2.getParent() instanceof ICPPASTExplicitTemplateInstantiation;
}
}
return false;
}
private boolean considerConstructors() {
if (astName == null) return false;
if (astName.getPropertyInParent() == CPPSemantics.STRING_LOOKUP_PROPERTY) return false;
@ -351,6 +386,14 @@ class LookupData {
}
return implied;
}
if (prop == IASTDeclarator.DECLARATOR_NAME) {
if (forExplicitFunctionInstantiation()) {
IScope scope = CPPVisitor.getContainingScope(astName);
if (scope instanceof ICPPClassScope) {
return ((ICPPClassScope)scope).getClassType();
}
}
}
return null;
} catch (DOMException e) {
return e.getProblem();

View file

@ -14,6 +14,7 @@
package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics;
import org.eclipse.cdt.core.dom.ast.DOMException;
import org.eclipse.cdt.core.dom.ast.IArrayType;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IFunctionType;
import org.eclipse.cdt.core.dom.ast.IPointerType;
@ -35,6 +36,7 @@ import org.eclipse.cdt.core.parser.util.CharArrayUtils;
import org.eclipse.cdt.core.parser.util.ObjectSet;
import org.eclipse.cdt.internal.core.dom.parser.ITypeContainer;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPFunctionType;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPPointerType;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPTemplateArgument;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPDeferredClassInstance;
import org.eclipse.cdt.internal.core.dom.parser.cpp.OverloadableOperator;
@ -322,4 +324,41 @@ public class SemanticUtil {
}
return result;
}
/**
* Adjusts the parameter type according to 8.3.5-3:
* cv-qualifiers are deleted, arrays and function types are converted to pointers.
*/
public static IType adjustParameterType(IType pt) {
// bug 239975
IType noTypedef= SemanticUtil.getUltimateTypeViaTypedefs(pt);
//8.3.5-3
//Any cv-qualifier modifying a parameter type is deleted.
//so only create the base type from the declspec and not the qualifiers
try {
if (noTypedef instanceof IQualifierType) {
pt= ((IQualifierType) noTypedef).getType();
noTypedef= SemanticUtil.getUltimateTypeViaTypedefs(pt);
}
if (noTypedef instanceof CPPPointerType) {
pt= ((CPPPointerType) noTypedef).stripQualifiers();
noTypedef= SemanticUtil.getUltimateTypeViaTypedefs(pt);
}
//any parameter of type array of T is adjusted to be pointer to T
if (noTypedef instanceof IArrayType) {
IArrayType at = (IArrayType) noTypedef;
pt = new CPPPointerType(at.getType());
noTypedef= SemanticUtil.getUltimateTypeViaTypedefs(pt);
}
} catch (DOMException e) {
pt = e.getProblem();
}
//any parameter to type function returning T is adjusted to be pointer to function
if (noTypedef instanceof IFunctionType) {
pt = new CPPPointerType(pt);
}
return pt;
}
}

View file

@ -36,6 +36,7 @@ import org.eclipse.cdt.core.dom.ast.ICompositeType;
import org.eclipse.cdt.core.dom.ast.IEnumeration;
import org.eclipse.cdt.core.dom.ast.IProblemBinding;
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.ICPPASTUsingDirective;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassTemplate;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPDeferredTemplateInstance;
@ -240,7 +241,10 @@ abstract public class PDOMWriter {
Throwable th= null;
try {
final IBinding binding = name.resolveBinding();
if (binding instanceof IProblemBinding) {
if (name.getPropertyInParent() == ICPPASTTemplateId.TEMPLATE_NAME &&
((IASTName) name.getParent()).getBinding() == binding) {
na[0]= null;
} else if (binding instanceof IProblemBinding) {
fStatistics.fProblemBindingCount++;
if (fShowProblems) {
reportProblem((IProblemBinding) binding);

View file

@ -31,6 +31,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateInstance;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateNonTypeParameter;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateTemplateParameter;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateTypeParameter;
import org.eclipse.cdt.internal.core.dom.parser.ProblemBinding;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPInstanceCache;
import org.eclipse.cdt.internal.core.index.IIndexCPPBindingConstants;
@ -243,7 +244,17 @@ public class PDOMCPPClassTemplate extends PDOMCPPClassType
}
try {
PDOMNodeLinkedList list = new PDOMNodeLinkedList(pdom, record + PARAMETERS, getLinkageImpl());
return (ICPPTemplateParameter) list.getNodeAt(pos);
ICPPTemplateParameter result= (ICPPTemplateParameter) list.getNodeAt(pos);
if (param instanceof ICPPTemplateTypeParameter) {
if (result instanceof ICPPTemplateTypeParameter)
return result;
} else if (param instanceof ICPPTemplateNonTypeParameter) {
if (result instanceof ICPPTemplateNonTypeParameter)
return result;
} else if (param instanceof ICPPTemplateTemplateParameter) {
if (result instanceof ICPPTemplateTemplateParameter)
return result;
}
} catch (CoreException e) {
CCorePlugin.log(e);
}

View file

@ -24,7 +24,10 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionTemplate;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateArgument;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateInstance;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateNonTypeParameter;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateTemplateParameter;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateTypeParameter;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPInstanceCache;
import org.eclipse.cdt.internal.core.index.IIndexCPPBindingConstants;
import org.eclipse.cdt.internal.core.pdom.PDOM;
@ -131,7 +134,17 @@ class PDOMCPPFunctionTemplate extends PDOMCPPFunction
int pos = param.getParameterPosition();
try {
PDOMNodeLinkedList list = new PDOMNodeLinkedList(pdom, record + TEMPLATE_PARAMS, getLinkageImpl());
return (ICPPTemplateParameter) list.getNodeAt(pos);
ICPPTemplateParameter result= (ICPPTemplateParameter) list.getNodeAt(pos);
if (param instanceof ICPPTemplateTypeParameter) {
if (result instanceof ICPPTemplateTypeParameter)
return result;
} else if (param instanceof ICPPTemplateNonTypeParameter) {
if (result instanceof ICPPTemplateNonTypeParameter)
return result;
} else if (param instanceof ICPPTemplateTemplateParameter) {
if (result instanceof ICPPTemplateTemplateParameter)
return result;
}
} catch (CoreException e) {
CCorePlugin.log(e);
}