1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-23 08:55:25 +02:00

Bug 326900: Update for template argument deduction.

This commit is contained in:
Markus Schorn 2010-10-06 13:24:38 +00:00
parent 1fff26625d
commit a0add23230
17 changed files with 493 additions and 267 deletions

View file

@ -19,6 +19,7 @@ import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTExpression;
import org.eclipse.cdt.core.dom.ast.IASTExpressionList;
import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition;
import org.eclipse.cdt.core.dom.ast.IASTImplicitName;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTProblemDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
@ -35,6 +36,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateId;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTUsingDeclaration;
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.ICPPSpecialization;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateInstance;
import org.eclipse.cdt.core.parser.ParserLanguage;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownBinding;
@ -4246,7 +4248,8 @@ public class AST2CPPSpecTest extends AST2SpecBaseTest {
// b.f(); //Calls X::f()
// }
public void test13_3_3_2s3b() throws Exception {
parse(getAboveComment(), ParserLanguage.CPP, true, 0);
String[] problems= {"g"};
parse(getAboveComment(), ParserLanguage.CPP, problems);
}
// struct A {
@ -4670,7 +4673,7 @@ public class AST2CPPSpecTest extends AST2SpecBaseTest {
// template<class P> friend class frd;
// // ...
// };
public void test14_5_3s1() throws Exception {
public void test14_5_4s1() throws Exception {
parse(getAboveComment(), ParserLanguage.CPP, true, 0);
}
@ -4689,7 +4692,7 @@ public class AST2CPPSpecTest extends AST2SpecBaseTest {
// };
// }
// }
public void test14_5_3s2() throws Exception {
public void test14_5_4s2() throws Exception {
parse(getAboveComment(), ParserLanguage.CPP, false, 0);
}
@ -4697,7 +4700,7 @@ public class AST2CPPSpecTest extends AST2SpecBaseTest {
// template<class T> friend class B; // OK
// template<class T> friend void f(T){ } // OK
// };
public void test14_5_3s3() throws Exception {
public void test14_5_4s3() throws Exception {
parse(getAboveComment(), ParserLanguage.CPP, true, 0);
}
@ -4707,7 +4710,7 @@ public class AST2CPPSpecTest extends AST2SpecBaseTest {
// };
// template<class T> struct A { X::Y ab; }; // OK
// template<class T> struct A<T*> { X::Y ab; }; // OK
public void test14_5_3s4() throws Exception {
public void test14_5_4s4() throws Exception {
parse(getAboveComment(), ParserLanguage.CPP, true, 0);
}
@ -4719,7 +4722,7 @@ public class AST2CPPSpecTest extends AST2SpecBaseTest {
// template<class T> friend struct A<T>::B;
// template<class T> friend void A<T>::f();
// };
public void test14_5_3s6() throws Exception {
public void test14_5_4s6() throws Exception {
parse(getAboveComment(), ParserLanguage.CPP, true, 0);
}
@ -4731,7 +4734,7 @@ public class AST2CPPSpecTest extends AST2SpecBaseTest {
// A<char>::B<int*> abcip; // uses #2
// A<short>::B<int*> absip; // uses #3
// A<char>::B<int> abci; // uses #1
public void test14_5_4_3s2() throws Exception {
public void test14_5_5_3s2() throws Exception {
parse(getAboveComment(), ParserLanguage.CPP, true, 0);
}
@ -4740,13 +4743,13 @@ public class AST2CPPSpecTest extends AST2SpecBaseTest {
// template<class T1, class T2, int I> class A<T1*, T2, I> { }; // #3
// template<class T> class A<int, T*, 5> { }; // #4
// template<class T1, class T2, int I> class A<T1, T2*, I> { }; // #5
public void test14_5_4s4() throws Exception {
public void test14_5_5s4() throws Exception {
parse(getAboveComment(), ParserLanguage.CPP, true, 0);
}
// template <int I, int J> struct B {};
// template <int I> struct B<I, I> {}; // OK
public void test14_5_4s9b() throws Exception {
public void test14_5_5s9b() throws Exception {
parse(getAboveComment(), ParserLanguage.CPP, true, 0);
}
@ -4759,7 +4762,7 @@ public class AST2CPPSpecTest extends AST2SpecBaseTest {
// A<int, int*, 1> a2; // uses #2, T is int, I is 1
// A<int, char*, 5> a3; // uses #4, T is char
// A<int, char*, 1> a4; // uses #5, T1 is int, T2 is char, I is 1
public void test14_5_4_1s2a() throws Exception {
public void test14_5_5_1s2a() throws Exception {
parse(getAboveComment(), ParserLanguage.CPP, true, 0);
}
@ -4769,7 +4772,7 @@ public class AST2CPPSpecTest extends AST2SpecBaseTest {
// template<class T> class A<int, T*, 5> { }; // #4
// template<class T1, class T2, int I> class A<T1, T2*, I> { }; // #5
// A<int*, int*, 2> a5; // ambiguous: matches #3 and #5 : expect problem
public void test14_5_4_1s2b() throws Exception {
public void test14_5_5_1s2b() throws Exception {
parse(getAboveComment(), ParserLanguage.CPP, true, 1);
}
@ -4778,7 +4781,7 @@ public class AST2CPPSpecTest extends AST2SpecBaseTest {
// template<int I> class X<I, I, int> { }; // #2
// template<int I, int J> void f(X<I, J, int>); // #A
// template<int I> void f(X<I, I, int>); // #B
public void test14_5_4_2s2() throws Exception {
public void test14_5_5_2s2() throws Exception {
parse(getAboveComment(), ParserLanguage.CPP, true, 0);
}
@ -4809,13 +4812,13 @@ public class AST2CPPSpecTest extends AST2SpecBaseTest {
// a2.f(); //illformed, no definition of f for A<T,2>
// // the primary template is not used here
// }
public void test14_5_4_3s1() throws Exception {
public void test14_5_5_3s1() throws Exception {
parse(getAboveComment(), ParserLanguage.CPP, false, 0);
}
// template<class T> class Array { };
// template<class T> void sort(Array<T>&);
public void test14_5_5s1() throws Exception {
public void test14_5_6s1() throws Exception {
parse(getAboveComment(), ParserLanguage.CPP, true, 0);
}
@ -4826,7 +4829,7 @@ public class AST2CPPSpecTest extends AST2SpecBaseTest {
// f(p); // call
// // f<int>(int*)
// }
public void test14_5_5_1s1a() throws Exception {
public void test14_5_6_1s1a() throws Exception {
parse(getAboveComment(), ParserLanguage.CPP, true, 0);
}
// // file2.c
@ -4836,7 +4839,7 @@ public class AST2CPPSpecTest extends AST2SpecBaseTest {
// f(p); // call
// // f<int*>(int*)
// }
public void test14_5_5_1s1b() throws Exception {
public void test14_5_6_1s1b() throws Exception {
parse(getAboveComment(), ParserLanguage.CPP, true, 0);
}
@ -4846,7 +4849,7 @@ public class AST2CPPSpecTest extends AST2SpecBaseTest {
// template <int I> void f/*2*/(A<I>, A<I+10>);
// // Guaranteed to be different
// template <int I> void f/*3*/(A<I>, A<I+11>);
public void test14_5_5_1s8a() throws Exception {
public void test14_5_6_1s8a() throws Exception {
final String content= getAboveComment();
IASTTranslationUnit tu= parse(content, ParserLanguage.CPP, true, 0);
BindingAssertionHelper bh= new BindingAssertionHelper(content, true);
@ -4860,11 +4863,33 @@ public class AST2CPPSpecTest extends AST2SpecBaseTest {
// // Illformed, no diagnostic required
// template <int I> void f(A<I>, A<I+10>);
// template <int I> void f(A<I>, A<I+1+2+3+4>);
public void test14_5_5_1s8b() throws Exception {
public void test14_5_6_1s8b() throws Exception {
//test is only for syntax, semantics are not checked here.
parse(getAboveComment(), ParserLanguage.CPP, false, 0);
}
// struct A { };
// template<class T> struct B {
// template<class R> int operator*(R&); // #1
// };
// template<class T, class R> int operator*(T&, R&); // #2
// // The declaration of B::operator* is transformed into the equivalent of
// // template<class R> int operator*(B<A>&, R&); // #1a
// int main() {
// A a;
// B<A> b;
// b * a; // calls #1a
// }
public void test14_5_6_2s3() throws Exception {
String code= getAboveComment();
BindingAssertionHelper bh= new BindingAssertionHelper(code, true);
IBinding op1= bh.assertNonProblem("operator*(R&)", -4);
IASTImplicitName name= bh.assertImplicitName("* a", 1, ICPPFunction.class);
ICPPTemplateInstance inst= (ICPPTemplateInstance) name.resolveBinding();
ICPPSpecialization templateSpecialization = (ICPPSpecialization) inst.getTemplateDefinition();
assertSame(op1, templateSpecialization.getSpecializedBinding());
}
// template<class T> struct A { A(); };
// template<class T> void f(T);
// template<class T> void f(T*);
@ -4883,7 +4908,7 @@ public class AST2CPPSpecTest extends AST2SpecBaseTest {
// const A<int> z2;
// h(z2); // h(const T&) is called because h(A<T>&) is not callable
// }
public void test14_5_5_2s5() throws Exception {
public void test14_5_6_2s5() throws Exception {
parse(getAboveComment(), ParserLanguage.CPP, false, 0);
}
@ -4896,7 +4921,7 @@ public class AST2CPPSpecTest extends AST2SpecBaseTest {
// f(ip); //calls #2
// g(ip); //calls #4
// }
public void test14_5_5_2s6() throws Exception {
public void test14_5_6_2s6() throws Exception {
parse(getAboveComment(), ParserLanguage.CPP, true, 0);
}
@ -5657,7 +5682,7 @@ public class AST2CPPSpecTest extends AST2SpecBaseTest {
// template <class T> int f(T[5]);
// int I = f<int>(0);
// int j = f<void>(0); // invalid array
// int j = f<void>(0); // invalid array // also no error with gcc
public void _test14_8_2s8b() throws Exception {
final String content= getAboveComment();
BindingAssertionHelper bh= new BindingAssertionHelper(content, true);
@ -5829,7 +5854,7 @@ public class AST2CPPSpecTest extends AST2SpecBaseTest {
// char g(char);
// template <class T> T g(T);
// int i = f(1, g); // calls f(int, int (*)(int))
public void _test14_8_2_1s9() throws Exception {
public void test14_8_2_1s9() throws Exception {
final String code= getAboveComment();
BindingAssertionHelper bh= new BindingAssertionHelper(code, true);
ICPPTemplateInstance inst;
@ -5962,13 +5987,13 @@ public class AST2CPPSpecTest extends AST2SpecBaseTest {
// f(i); // calls f<int&>(int&), i.e., #1
// f(0); // calls f<int>(int&&), i.e., #2
// }
public void _test14_8_2_5s10() throws Exception {
public void test14_8_2_5s10() throws Exception {
final String code= getAboveComment();
BindingAssertionHelper bh= new BindingAssertionHelper(code, true);
ICPPTemplateInstance inst;
inst= bh.assertNonProblem("f(i)", 1);
assertEquals("<int &>", ASTTypeUtil.getArgumentListString(inst.getTemplateArguments(), true));
inst= bh.assertNonProblem("f(i)", 1);
inst= bh.assertNonProblem("f(0)", 1);
assertEquals("<int>", ASTTypeUtil.getArgumentListString(inst.getTemplateArguments(), true));
}
@ -6021,7 +6046,7 @@ public class AST2CPPSpecTest extends AST2SpecBaseTest {
// g<0>(a1); // OK
// f(a1, a2); // OK
// }
public void _test14_8_2_5s16a() throws Exception {
public void test14_8_2_5s16a() throws Exception {
final String code= getAboveComment();
BindingAssertionHelper bh= new BindingAssertionHelper(code, true);
ICPPTemplateInstance inst;
@ -6069,7 +6094,7 @@ public class AST2CPPSpecTest extends AST2SpecBaseTest {
// B<1> b;
// g(b); // OK: cv-qualifiers are ignored on template parameter types
// }
public void _test14_8_2_5s17() throws Exception {
public void test14_8_2_5s17() throws Exception {
final String code= getAboveComment();
BindingAssertionHelper bh= new BindingAssertionHelper(code, true);
ICPPTemplateInstance inst;
@ -6684,7 +6709,7 @@ public class AST2CPPSpecTest extends AST2SpecBaseTest {
}
// template<class T1, class T2, int I> class A<T1, T2, I> { }; // error
public void test14_5_4s5() throws Exception {
public void test14_5_5s5() throws Exception {
parse(getAboveComment(), ParserLanguage.CPP, false, 0);
}
@ -6697,7 +6722,7 @@ public class AST2CPPSpecTest extends AST2SpecBaseTest {
// template<class T> template<class T2>
// struct A<T>::C::B<T2*> { };
// A<short>::C::B<int*> absip; // uses partial specialization
public void test14_5_4s6() throws Exception {
public void test14_5_5s6() throws Exception {
parse(getAboveComment(), ParserLanguage.CPP, true, 0);
}
@ -6710,14 +6735,14 @@ public class AST2CPPSpecTest extends AST2SpecBaseTest {
// }
// A<int,int*> a; // uses the partial specialization, which is found through
// // the using declaration which refers to the primary template
public void test14_5_4s7() throws Exception {
public void test14_5_5s7() throws Exception {
parse(getAboveComment(), ParserLanguage.CPP, true, 0);
}
// template<class T> void f();
// template<int I> void f(); // OK: overloads the first template
// // distinguishable with an explicit template argument list
public void test14_5_5_1s4() throws Exception {
public void test14_5_6_1s4() throws Exception {
parse(getAboveComment(), ParserLanguage.CPP, true, 0);
}
@ -6725,7 +6750,7 @@ public class AST2CPPSpecTest extends AST2SpecBaseTest {
// 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 {
public void test14_5_6_1s5() throws Exception {
final String content= getAboveComment();
IASTTranslationUnit tu= parse(content, ParserLanguage.CPP, true, 0);
BindingAssertionHelper bh= new BindingAssertionHelper(content, true);
@ -6739,7 +6764,7 @@ public class AST2CPPSpecTest extends AST2SpecBaseTest {
// 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
public void test14_5_5_1s6() throws Exception {
public void test14_5_6_1s6() throws Exception {
final String content= getAboveComment();
IASTTranslationUnit tu= parse(content, ParserLanguage.CPP, true, 0);
BindingAssertionHelper bh= new BindingAssertionHelper(content, true);

View file

@ -4896,6 +4896,55 @@ public class AST2CPPTests extends AST2BaseTest {
assertSame( col.getName(2).resolveBinding(), col.getName(5).resolveBinding() );
}
// void f(const int&);
// void f(int&);
// void g(const int&);
// void g(int);
// void h(const int * const&);
// void h(int *);
// void i(int * const &);
// void i(const int *);
// void test() {
// const int ca= 1; int a;
// f(ca); // f(const int&)
// f(a); // f(int &)
// g(ca); // ambiguous
// g(a); // ambiguous
// h(&ca); // h(const int * const&)
// h(&a); // void h(int *)
// i(&ca); // i(const int *)
// i(&a); // i(int * const &)
// }
public void testRankingQualificationConversions_c() throws Exception {
String code= getAboveComment();
BindingAssertionHelper bh= new BindingAssertionHelper(code, true);
ICPPFunction f1= bh.assertNonProblem("f(const int&)", 1);
ICPPFunction f2= bh.assertNonProblem("f(int&)", 1);
ICPPFunction g1= bh.assertNonProblem("g(const int&)", 1);
ICPPFunction g2= bh.assertNonProblem("g(int)", 1);
ICPPFunction h1= bh.assertNonProblem("h(const int * const&)", 1);
ICPPFunction h2= bh.assertNonProblem("h(int *)", 1);
ICPPFunction i1= bh.assertNonProblem("i(int * const &)", 1);
ICPPFunction i2= bh.assertNonProblem("i(const int *)", 1);
ICPPFunction ref;
ref= bh.assertNonProblem("f(ca)", 1);
assertSame(f1, ref);
ref= bh.assertNonProblem("f(a)", 1);
assertSame(f2, ref);
bh.assertProblem("g(ca)", 1);
bh.assertProblem("g(a)", 1);
ref= bh.assertNonProblem("h(&ca)", 1);
assertSame(h1, ref);
ref= bh.assertNonProblem("h(&a)", 1);
assertSame(h2, ref);
ref= bh.assertNonProblem("i(&ca)", 1);
assertSame(i2, ref);
ref= bh.assertNonProblem("i(&a)", 1);
assertSame(i1, ref);
}
// namespace n {
// namespace m {
// class A;

View file

@ -64,7 +64,7 @@ public class ASTCPPSpecDefectTests extends AST2BaseTest {
// void test() {
// fp(f0);
// }
public void testADLForOverloadSet_324842() throws Exception {
public void test33_ADLForOverloadSet_324842() throws Exception {
parseAndCheckBindings();
}
@ -73,7 +73,15 @@ public class ASTCPPSpecDefectTests extends AST2BaseTest {
// struct A {
// friend A operator + <>(A&);
// };
public void testTemplateArgForOperator() throws Exception {
public void test38_templateArgForOperator() throws Exception {
parseAndCheckBindings();
}
// template <class T1, class ...Z> class S; // #1
// template <class T1, class ...Z> class S<T1, const Z&...> {}; // #2
// template <class T1, class T2> class S<T1, const T2&> {};; // #3
// S<int, const int&> s; // both #2 and #3 match; #3 is more specialized
public void test692_partialOrdering() throws Exception {
parseAndCheckBindings();
}

View file

@ -416,6 +416,8 @@ public class ASTTypeUtil {
needSpace= appendCVQ(result, needSpace, qt.isConst(), qt.isVolatile());
} else if (type instanceof ITypedef) {
result.append(((ITypedef) type).getNameCharArray());
} else if (type != null) {
result.append('@').append(type.hashCode());
}
return result.toString();

View file

@ -446,7 +446,7 @@ public class Value implements IValue {
unknownSigs.put(sig, idx);
unknowns.add(unknown);
}
return REFERENCE_CHAR + idx.toString();
return "" + REFERENCE_CHAR + idx.toString(); //$NON-NLS-1$
}
private static Object evaluateValue(IValue cv, Map<String, Integer> unknownSigs, List<ICPPUnknownBinding> unknowns) throws UnknownValueException {
@ -536,7 +536,7 @@ public class Value implements IValue {
case IASTUnaryExpression.op_minus:
case IASTUnaryExpression.op_tilde:
case IASTUnaryExpression.op_not:
return UNARY_OP_CHAR + unaryOp + SEPARATOR + value.toString();
return "" + UNARY_OP_CHAR + unaryOp + SEPARATOR + value.toString(); //$NON-NLS-1$
}
throw UNKNOWN_EX;
}
@ -634,7 +634,7 @@ public class Value implements IValue {
throw UNKNOWN_EX;
}
return BINARY_OP_CHAR + op + SEPARATOR + o1.toString() + SEPARATOR + o2.toString();
return "" + BINARY_OP_CHAR + op + SEPARATOR + o1.toString() + SEPARATOR + o2.toString(); //$NON-NLS-1$
}
public static IValue reevaluate(IValue val, int packOffset, IBinding[] resolvedUnknowns, ICPPTemplateParameterMap map, int maxdepth) {
@ -699,7 +699,7 @@ public class Value implements IValue {
}
return po;
}
return CONDITIONAL_CHAR + SEPARATOR + cond.toString() + SEPARATOR + po.toString() + SEPARATOR + neg.toString();
return "" + CONDITIONAL_CHAR + SEPARATOR + cond.toString() + SEPARATOR + po.toString() + SEPARATOR + neg.toString(); //$NON-NLS-1$
case REFERENCE_CHAR:
int num= parseNonNegative(buf, idx+1);
final IBinding[] resolvedUnknowns= reeval.fResolvedUnknown;

View file

@ -27,6 +27,7 @@ import org.eclipse.core.runtime.CoreException;
* Integral c++ type.
*/
public class CPPBasicType implements ICPPBasicType, ISerializableType {
// mstodo replace with problem type
public static int UNIQUE_TYPE_QUALIFIER= -1;
private final Kind fKind;
private final int fModifiers;

View file

@ -31,6 +31,10 @@ public class CPPTemplateParameterMap implements ICPPTemplateParameterMap {
fMap= new ObjectMap(initialSize);
}
public CPPTemplateParameterMap(CPPTemplateParameterMap other) {
fMap= (ObjectMap) other.fMap.clone();
}
/**
* Returns whether the map contains the given parameter
*/

View file

@ -2294,7 +2294,7 @@ public class CPPSemantics {
return resolveFunctionDeclaration(data, fns);
// Reduce our set of candidate functions to only those who have the right number of parameters
final IType[] argTypes = data.getFunctionArgumentTypes();
final IType[] argTypes = data.getFunctionArgumentTypes();
ICPPFunction[] tmp= selectByArgumentCount(data, fns);
tmp= CPPTemplates.instantiateForFunctionCall(data.astName, tmp,
Arrays.asList(argTypes),
@ -2820,7 +2820,7 @@ public class CPPSemantics {
if (inst != null) {
int cmp= -1;
if (result != null) {
cmp= CPPTemplates.orderTemplateFunctions(resultTemplate, template);
cmp= CPPTemplates.orderFunctionTemplates(resultTemplate, template);
if (cmp == 0)
cmp= compareByRelevance(tu, resultTemplate, template);
}

View file

@ -14,14 +14,11 @@
package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics;
import static org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory.LVALUE;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.addQualifiers;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.eclipse.cdt.core.dom.IName;
import org.eclipse.cdt.core.dom.ast.ASTTypeUtil;
@ -41,8 +38,6 @@ import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration;
import org.eclipse.cdt.core.dom.ast.IArrayType;
import org.eclipse.cdt.core.dom.ast.IBasicType;
import org.eclipse.cdt.core.dom.ast.IBasicType.Kind;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IEnumeration;
import org.eclipse.cdt.core.dom.ast.IEnumerator;
@ -104,7 +99,6 @@ 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.CPPASTName;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPArrayType;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPBasicType;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPClassInstance;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPClassSpecialization;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPClassTemplatePartialSpecialization;
@ -125,6 +119,7 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPMethodTemplateSpecializat
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPParameterPackType;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPPointerToMemberType;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPPointerType;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPReferenceType;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPTemplateArgument;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPTemplateDefinition;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPTemplateNonTypeParameter;
@ -157,7 +152,7 @@ public class CPPTemplates {
private static final int PACK_SIZE_FAIL = -2;
private static final int PACK_SIZE_NOT_FOUND = Integer.MAX_VALUE;
private static final ICPPFunction[] NO_FUNCTIONS = {};
/**
* Instantiates a class template with the given arguments. May return <code>null</code>.
*/
@ -1111,10 +1106,9 @@ public class CPPTemplates {
ICPPPointerToMemberType ptm = (ICPPPointerToMemberType) typeContainer;
IType memberOfClass = ptm.getMemberOfClass();
IType newMemberOfClass = instantiateType(memberOfClass, tpMap, packOffset, within);
if (!(newMemberOfClass instanceof ICPPClassType) &&
!(newMemberOfClass instanceof IBasicType && ((IBasicType) newMemberOfClass).getModifiers() == CPPBasicType.UNIQUE_TYPE_QUALIFIER) &&
!(newMemberOfClass instanceof ICPPUnknownBinding)) {
newMemberOfClass= memberOfClass;
if (!(newMemberOfClass instanceof ICPPClassType || newMemberOfClass instanceof UniqueType
|| newMemberOfClass instanceof ICPPUnknownBinding)) {
newMemberOfClass = memberOfClass;
}
if (newNestedType != nestedType || newMemberOfClass != memberOfClass) {
return new CPPPointerToMemberType(newNestedType, newMemberOfClass,
@ -1580,16 +1574,13 @@ public class CPPTemplates {
return fns;
final List<ICPPFunction> result= new ArrayList<ICPPFunction>(fns.length);
final List<List<IType>> crossProduct= expandOverloadedSets(fnArgs);
for (ICPPFunction fn : fns) {
if (fn != null) {
if (fn instanceof ICPPFunctionTemplate) {
ICPPFunctionTemplate fnTmpl= (ICPPFunctionTemplate) fn;
for (List<IType> args : crossProduct) {
ICPPFunction inst = instantiateForFunctionCall(fnTmpl, tmplArgs, args, argCats, withImpliedObjectArg);
if (inst != null)
result.add(inst);
}
ICPPFunction inst = instantiateForFunctionCall(fnTmpl, tmplArgs, fnArgs, argCats, withImpliedObjectArg);
if (inst != null)
result.add(inst);
} else if (!requireTemplate || fn instanceof ICPPUnknownBinding) {
result.add(fn);
}
@ -1598,47 +1589,6 @@ public class CPPTemplates {
return result.toArray(new ICPPFunction[result.size()]);
}
private static List<List<IType>> expandOverloadedSets(List<IType> fnArgs) {
List<List<IType>> result= Collections.singletonList(fnArgs);
int i= 0;
for (IType arg : fnArgs) {
if (arg instanceof FunctionSetType) {
Collection<ICPPFunctionType> targetTypes= getFunctionTypes((FunctionSetType) arg);
if (targetTypes.isEmpty())
return Collections.emptyList();
List<List<IType>> expanded= new ArrayList<List<IType>>(targetTypes.size() * result.size());
for (IType targetType : targetTypes) {
for (List<IType> orig : result) {
ArrayList<IType> copy = new ArrayList<IType>(orig);
copy.set(i, new CPPPointerType(targetType));
expanded.add(copy);
}
}
result= expanded;
}
i++;
}
return result;
}
private static Collection<ICPPFunctionType> getFunctionTypes(FunctionSetType fst) {
final ICPPFunction[] functionSet = fst.getFunctionSet();
Set<String> handled= new HashSet<String>();
Collection<ICPPFunctionType> result= new ArrayList<ICPPFunctionType>(functionSet.length);
for (ICPPFunction f : functionSet) {
if (! (f instanceof ICPPFunctionTemplate)) {
try {
ICPPFunctionType t= f.getType();
if (handled.add(ASTTypeUtil.getType(t, true)))
result.add(t);
} catch (DOMException e) {
}
}
}
return result;
}
private static ICPPFunction instantiateForFunctionCall(ICPPFunctionTemplate template,
ICPPTemplateArgument[] tmplArgs, List<IType> fnArgs, List<ValueCategory> argCats,
boolean withImpliedObjectArg) {
@ -1732,90 +1682,92 @@ public class CPPTemplates {
return null;
}
/**
* Transforms a function template for use in partial ordering, as described in the
* spec 14.5.5.2-3
* @param template
* @return
* -for each type template parameter, synthesize a unique type and substitute that for each
* occurrence of that parameter in the function parameter list
* -for each non-type template parameter, synthesize a unique value of the appropriate type and
* substitute that for each occurrence of that parameter in the function parameter list
* for each template template parameter, synthesize a unique class template and substitute that
* for each occurrence of that parameter in the function parameter list
* @throws DOMException
*/
static private ICPPTemplateArgument[] createArgsForFunctionTemplateOrdering(ICPPTemplateParameter[] paramList)
throws DOMException{
int size = paramList.length;
ICPPTemplateArgument[] args = new ICPPTemplateArgument[size];
for (int i = 0; i < size; i++) {
ICPPTemplateParameter param = paramList[i];
if (param instanceof ICPPTemplateNonTypeParameter) {
args[i]= new CPPTemplateArgument(Value.unique(), ((ICPPTemplateNonTypeParameter) param).getType());
} else {
args[i] = new CPPTemplateArgument(new CPPBasicType(Kind.eUnspecified, CPPBasicType.UNIQUE_TYPE_QUALIFIER));
}
}
return args;
}
static int orderTemplateFunctions(ICPPFunctionTemplate f1, ICPPFunctionTemplate f2)
// 14.5.6.2 Partial ordering of function templates
static int orderFunctionTemplates(ICPPFunctionTemplate f1, ICPPFunctionTemplate f2)
throws DOMException {
// 14.5.5.2
// A template is more specialized than another if and only if it is at least as specialized as the
// other template and that template is not at least as specialized as the first.
boolean f1IsAtLeastAsSpecializedAsF2 = isAtLeastAsSpecializedAs(f1, f2);
boolean f2IsAtLeastAsSpecializedAsF1 = isAtLeastAsSpecializedAs(f2, f1);
if (f1IsAtLeastAsSpecializedAsF2 == f2IsAtLeastAsSpecializedAsF1)
int s1 = compareSpecialization(f1, f2);
int s2 = compareSpecialization(f2, f1);
if (s1 == s2)
return 0;
if (f1IsAtLeastAsSpecializedAsF2)
return 1;
return -1;
if (s1 < 0 || s2 > 0)
return -1;
assert s2 < 0 || s1 > 0;
return 1;
}
private static boolean isAtLeastAsSpecializedAs(ICPPFunctionTemplate f1, ICPPFunctionTemplate f2) throws DOMException {
// mstodo use function-type, parameter-types or return type.
// mstodo perform transformations (references, cv-qualifiers)
// mstodo if equal, use differences in cv-qualifiers
// mstodo special rule for parameter packs.
// 14.5.5.2
// Using the transformed parameter list, perform argument deduction against the other
// function template
// The transformed template is at least as specialized as the other if and only if the deduction
// succeeds and the deduced parameter types are an exact match.
private static ICPPFunction transferFunctionTemplate(ICPPFunctionTemplate f) throws DOMException {
final ICPPTemplateParameter[] tpars = f.getTemplateParameters();
final int argLen = tpars.length;
// Check for parameter packs
final ICPPTemplateParameter[] tmplParams1 = f1.getTemplateParameters();
ICPPTemplateArgument[] transferArgs = createArgsForFunctionTemplateOrdering(tmplParams1);
final int length = transferArgs.length;
CPPTemplateParameterMap map = new CPPTemplateParameterMap(length);
for (int i = 0; i < length; i++) {
map.put(tmplParams1[i], transferArgs[i]);
}
IBinding transferredTemplate = instantiateFunctionTemplate(f1, transferArgs, map);
if (!(transferredTemplate instanceof ICPPFunction))
return false;
map= new CPPTemplateParameterMap(2);
final IType[] transferredParameterTypes = ((ICPPFunction) transferredTemplate).getType().getParameterTypes();
if (!TemplateArgumentDeduction.deduceFromFunctionArgs(f2, Arrays.asList(transferredParameterTypes), null, map, true))
return false;
final int last = tmplParams1.length -1;
if (last >= 0 && tmplParams1[last].isParameterPack()) {
final ICPPTemplateParameter[] tmplParams2 = f2.getTemplateParameters();
if (last < tmplParams2.length && !tmplParams2[last].isParameterPack()) {
return false;
// Create arguments and map
ICPPTemplateArgument[] args = new ICPPTemplateArgument[argLen];
CPPTemplateParameterMap map = new CPPTemplateParameterMap(argLen);
for (int i = 0; i < argLen; i++) {
final ICPPTemplateParameter tpar = tpars[i];
final CPPTemplateArgument arg = uniqueArg(tpar);
args[i]= arg;
if (tpar.isParameterPack()) {
map.put(tpar, new ICPPTemplateArgument[] {arg});
} else {
map.put(tpar, arg);
}
}
return true;
IBinding result = instantiateFunctionTemplate(f, args, map);
if (result instanceof ICPPFunction)
return (ICPPFunction) result;
return null;
}
private static CPPTemplateArgument uniqueArg(final ICPPTemplateParameter tpar) throws DOMException {
final CPPTemplateArgument arg;
if (tpar instanceof ICPPTemplateNonTypeParameter) {
arg = new CPPTemplateArgument(Value.unique(), ((ICPPTemplateNonTypeParameter) tpar).getType());
} else {
arg = new CPPTemplateArgument(new UniqueType(tpar.isParameterPack()));
}
return arg;
}
private static int compareSpecialization(ICPPFunctionTemplate f1, ICPPFunctionTemplate f2) throws DOMException {
ICPPFunction transF1 = transferFunctionTemplate(f1);
if (transF1 == null)
return -1;
// mstodo use function-type, parameter-types or return type.
IType[] pars= f2.getType().getParameterTypes();
IType[] args = transF1.getType().getParameterTypes();
boolean nonStaticMember1= isNonStaticMember(f1);
boolean nonStaticMember2= isNonStaticMember(f2);
if (nonStaticMember1 != nonStaticMember2) {
if (nonStaticMember1) {
args= addImplicitObjectType(args, (ICPPMethod) f1);
} else {
pars= addImplicitObjectType(pars, (ICPPMethod) f2);
}
}
return TemplateArgumentDeduction.deduceForPartialOrdering(f2.getTemplateParameters(), pars, args);
}
private static boolean isNonStaticMember(ICPPFunctionTemplate f) {
return (f instanceof ICPPMethod) && !((ICPPMethod) f).isStatic();
}
private static IType[] addImplicitObjectType(IType[] types, ICPPMethod f1) {
ICPPClassType ct = f1.getClassOwner();
if (ct != null) {
try {
ICPPFunctionType ft = f1.getType();
IType[] result= new IType[types.length+1];
result[0]= new CPPReferenceType(addQualifiers(ct, ft.isConst(), ft.isVolatile()), false);
System.arraycopy(types, 0, result, 1, types.length);
return result;
} catch (DOMException e) {
}
}
return types;
}
private static ICPPClassTemplatePartialSpecialization findPartialSpecialization(ICPPClassTemplate ct,
@ -1918,21 +1870,25 @@ public class CPPTemplates {
final ICPPTemplateArgument[] targs2 = f2.getTemplateArguments();
if (targs1.length != targs2.length)
return false;
// transfer arguments of specialization 1
final ICPPTemplateArgument[] helperArgs = createArgsForFunctionTemplateOrdering(tpars1);
final CPPTemplateParameterMap transferMap= new CPPTemplateParameterMap(5);
for (int i = 0; i < tpars1.length; i++) {
transferMap.put(tpars1[i], helperArgs[i]);
// Transfer arguments of specialization 1
final int tpars1Len = tpars1.length;
ICPPTemplateArgument[] args = new ICPPTemplateArgument[tpars1Len];
final CPPTemplateParameterMap transferMap= new CPPTemplateParameterMap(tpars1Len);
for (int i = 0; i < tpars1Len; i++) {
final ICPPTemplateParameter param = tpars1[i];
final CPPTemplateArgument arg = uniqueArg(param);
args[i]= arg;
transferMap.put(param, arg);
}
final ICPPTemplateArgument[] transferredArgs1 = instantiateArguments(targs1, transferMap, -1, null);
// deduce arguments for specialization 2
// Deduce arguments for specialization 2
final CPPTemplateParameterMap deductionMap= new CPPTemplateParameterMap(2);
if (!TemplateArgumentDeduction.fromTemplateArguments(tpars2, targs2, transferredArgs1, deductionMap))
return false;
// compare
// Compare
for (int i = 0; i < targs2.length; i++) {
ICPPTemplateArgument transferredArg2= instantiateArgument(targs2[i], deductionMap, -1, null);
if (!transferredArg2.isSameValue(transferredArgs1[i]))

View file

@ -1821,7 +1821,7 @@ public class CPPVisitor extends ASTQueries {
ICPPFunctionTemplate template = new AutoTypeResolver(type);
CPPTemplateParameterMap paramMap = new CPPTemplateParameterMap(1);
TemplateArgumentDeduction.deduceFromFunctionArgs(template, Collections.singletonList(initType),
Collections.singletonList(valueCat), paramMap, false);
Collections.singletonList(valueCat), paramMap);
ICPPTemplateArgument argument = paramMap.getArgument(0, 0);
if (argument == null) {
return null;

View file

@ -35,6 +35,10 @@ public enum CVQualifier {
return other == _ || this == other || this == cv;
}
public boolean isMoreQualifiedThan(CVQualifier other) {
return this != other && (other == _ || this == cv);
}
public CVQualifier remove(CVQualifier arg) {
if (this == arg)
return _;

View file

@ -95,8 +95,8 @@ public class Conversions {
final IType cv1T1= getNestedType(target, TDEF | REF);
final IType T1= getNestedType(cv1T1, TDEF | REF | ALLCVQ);
ReferenceBinding refBindingType= ReferenceBinding.OTHER;
if (target instanceof ICPPReferenceType) {
ReferenceBinding refBindingType= ReferenceBinding.OTHER_REF;
// [8.5.3-5] initialization of a reference
final boolean isLValueRef= !((ICPPReferenceType) target).isRValueReference();
final IType cv2T2= exprType;
@ -239,8 +239,8 @@ public class Conversions {
if (!isImpliedObject && ctx != Context.REQUIRE_DIRECT_BINDING) {
if (isReferenceRelated(T1, T2) < 0 || compareQualifications(cv1T1, cv2T2) >= 0) {
Cost cost= nonReferenceConversion(valueCat, cv2T2, T1, udc, false);
if (!isImplicitWithoutRefQualifier && cost.converts()) {
cost.setReferenceBinding(isLValueRef ? ReferenceBinding.LVALUE_REF : ReferenceBinding.RVALUE_REF_BINDS_RVALUE);
if (cost.converts()) {
cost.setReferenceBinding(refBindingType);
}
return cost;
}
@ -249,11 +249,7 @@ public class Conversions {
}
// Non-reference binding
Cost cost= nonReferenceConversion(valueCat, exprType, T1, udc, isImpliedObject);
if (cost.converts()) {
cost.setReferenceBinding(refBindingType);
}
return cost;
return nonReferenceConversion(valueCat, exprType, T1, udc, isImpliedObject);
}
/**
@ -279,6 +275,8 @@ public class Conversions {
IType implicitParameterType= CPPSemantics.getImplicitParameterType(op, ft.isConst(), ft.isVolatile());
Cost udcCost= isReferenceCompatible(getNestedType(implicitParameterType, TDEF | REF), cv2T2, true); // expression type to implicit object type
if (udcCost != null) {
// Make sure top-level cv-qualifiers are compared
udcCost.setReferenceBinding(ReferenceBinding.LVALUE_REF);
FunctionCost udcFuncCost= new FunctionCost(op, udcCost);
int cmp= udcFuncCost.compareTo(null, bestUdcCost);
if (cmp <= 0) {
@ -729,6 +727,8 @@ public class Conversions {
IType implicitType= CPPSemantics.getImplicitParameterType(op, ft.isConst(), ft.isVolatile());
final Cost udcCost = isReferenceCompatible(getNestedType(implicitType, TDEF | REF), source, true);
if (udcCost != null) {
// Make sure top-level cv-qualifiers are compared
udcCost.setReferenceBinding(ReferenceBinding.LVALUE_REF);
FunctionCost c1= new FunctionCost(op, udcCost);
int cmp= c1.compareTo(null, cost1);
if (cmp <= 0) {
@ -783,6 +783,8 @@ public class Conversions {
IType implicitType= CPPSemantics.getImplicitParameterType(op, ftype.isConst(), ftype.isVolatile());
final Cost udcCost = isReferenceCompatible(getNestedType(implicitType, TDEF | REF), source, true);
if (udcCost != null) {
// Make sure top-level cv-qualifiers are compared
udcCost.setReferenceBinding(ReferenceBinding.LVALUE_REF);
FunctionCost c1= new FunctionCost(op, udcCost);
int cmp= c1.compareTo(null, cost1);
if (cmp <= 0) {
@ -868,7 +870,7 @@ public class Conversions {
IASTLiteralExpression lit= (IASTLiteralExpression) val;
if (lit.getKind() == IASTLiteralExpression.lk_string_literal) {
source= new CPPPointerType(srcTarget, false, false);
cost.setQualificationAdjustment(getCVQualifier(targetPtrTgt).isVolatile() ? 2 : 1);
cost.setQualificationAdjustment((getCVQualifier(targetPtrTgt).isVolatile() ? 2 : 1) << 2);
}
}
}
@ -886,11 +888,11 @@ public class Conversions {
boolean constInEveryCV2k = true;
boolean firstPointer= true;
int adjustments= 0;
int shift=0;
while (true) {
s= getNestedType(s, TDEF | REF);
t= getNestedType(t, TDEF | REF);
if (s instanceof IPointerType && t instanceof IPointerType) {
adjustments <<= 2;
final int cmp= compareQualifications(t, s); // is t more qualified than s?
if (cmp < 0 || (cmp > 0 && !constInEveryCV2k)) {
return false;
@ -904,19 +906,19 @@ public class Conversions {
s= sPtr.getType();
t= tPtr.getType();
firstPointer= false;
adjustments |= cmp;
adjustments |= (cmp << shift);
shift+= 2;
} else {
break;
}
}
adjustments <<= 2;
int cmp= compareQualifications(t, s); // is t more qualified than s?
if (cmp < 0 || (cmp > 0 && !constInEveryCV2k)) {
return false;
}
adjustments |= cmp;
adjustments |= (cmp << shift);
s= getNestedType(s, ALLCVQ | TDEF | REF);
t= getNestedType(t, ALLCVQ | TDEF | REF);

View file

@ -38,7 +38,7 @@ public class Cost {
USER_DEFINED_CONVERSION, ELLIPSIS_CONVERSION, NO_MATCH
}
enum ReferenceBinding {
RVALUE_REF_BINDS_RVALUE, LVALUE_REF, OTHER
RVALUE_REF_BINDS_RVALUE, LVALUE_REF, OTHER_REF, NO_REF
}
public static final Cost NO_CONVERSION = new Cost(null, null, Rank.NO_MATCH) {
@ -99,7 +99,7 @@ public class Cost {
source = s;
target = t;
fRank= rank;
fReferenceBinding= ReferenceBinding.OTHER;
fReferenceBinding= ReferenceBinding.NO_REF;
}
public final Rank getRank() {
@ -207,7 +207,11 @@ public class Cost {
return -1;
}
// Top level cv-qualifiers are compared only for reference bindings.
int qdiff= fQualificationAdjustments ^ other.fQualificationAdjustments;
if (fReferenceBinding == ReferenceBinding.NO_REF || other.fReferenceBinding == ReferenceBinding.NO_REF)
qdiff &= ~3;
if (qdiff != 0) {
if ((fQualificationAdjustments & qdiff) == 0)
return -1;

View file

@ -155,7 +155,7 @@ class FunctionCost {
} else if (!isTemplate && otherIsTemplate) {
haveBetter = true;
} else if (isTemplate && otherIsTemplate) {
int order = CPPTemplates.orderTemplateFunctions(otherAsTemplate, asTemplate);
int order = CPPTemplates.orderFunctionTemplates(otherAsTemplate, asTemplate);
if (order < 0) {
haveBetter= true;
} else if (order > 0) {

View file

@ -38,6 +38,7 @@ 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.ICPPSpecialization;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateArgument;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateInstance;
import org.eclipse.cdt.core.index.IIndexBinding;
import org.eclipse.cdt.core.parser.Keywords;
import org.eclipse.cdt.core.parser.util.ArrayUtil;
@ -577,4 +578,50 @@ public class SemanticUtil {
return -1;
}
public static boolean containsUniqueTypeForParameterPack(IType type) {
if (type instanceof ICPPFunctionType) {
final ICPPFunctionType ft = (ICPPFunctionType) type;
if (containsUniqueTypeForParameterPack(ft.getReturnType()))
return true;
for (IType pt : ft.getParameterTypes()) {
if (containsUniqueTypeForParameterPack(pt))
return true;
}
return false;
}
if (type instanceof ICPPPointerToMemberType) {
if (containsUniqueTypeForParameterPack(((ICPPPointerToMemberType) type).getMemberOfClass()))
return true;
}
if (type instanceof IBinding) {
IBinding owner = ((IBinding) type).getOwner();
if (owner instanceof IType) {
if (containsUniqueTypeForParameterPack((IType) owner))
return true;
}
}
if (type instanceof ICPPTemplateInstance) {
ICPPTemplateArgument[] args = ((ICPPTemplateInstance) type).getTemplateArguments();
for (ICPPTemplateArgument arg : args) {
if (containsUniqueTypeForParameterPack(arg.getTypeValue()))
return true;
}
}
if (type instanceof ITypeContainer) {
final ITypeContainer tc = (ITypeContainer) type;
final IType nestedType= tc.getType();
return containsUniqueTypeForParameterPack(nestedType);
}
if (type instanceof UniqueType) {
return ((UniqueType) type).isForParameterPack();
}
return false;
}
}

View file

@ -19,6 +19,7 @@ import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.eclipse.cdt.core.dom.ast.ASTTypeUtil;
import org.eclipse.cdt.core.dom.ast.DOMException;
import org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory;
import org.eclipse.cdt.core.dom.ast.IArrayType;
@ -35,6 +36,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPBasicType;
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.ICPPFunction;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionTemplate;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPParameterPackType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPPointerToMemberType;
@ -97,7 +99,7 @@ public class TemplateArgumentDeduction {
map.put(tmplParam, pack);
}
if (!deduceFromFunctionArgs(template, fnArgs, argIsLValue, map, false))
if (!deduceFromFunctionArgs(template, fnArgs, argIsLValue, map))
return null;
List<ICPPTemplateArgument> result= new ArrayList<ICPPTemplateArgument>(numTmplParams);
@ -236,7 +238,7 @@ public class TemplateArgumentDeduction {
* returns <code>false</code> if there is no mapping.
*/
static boolean deduceFromFunctionArgs(ICPPFunctionTemplate template, List<IType> fnArgs, List<ValueCategory> argCats,
CPPTemplateParameterMap map, boolean checkExactMatch) {
CPPTemplateParameterMap map) {
try {
IType[] fnPars = template.getType().getParameterTypes();
final int fnParCount = fnPars.length;
@ -246,7 +248,7 @@ public class TemplateArgumentDeduction {
final ICPPTemplateParameter[] tmplPars = template.getTemplateParameters();
TemplateArgumentDeduction deduct= new TemplateArgumentDeduction(tmplPars, map, new CPPTemplateParameterMap(fnParCount), 0);
IType fnParPack= null;
for (int j= 0; j < fnArgs.size(); j++) {
argLoop: for (int j= 0; j < fnArgs.size(); j++) {
IType par;
if (fnParPack != null) {
par= fnParPack;
@ -255,7 +257,7 @@ public class TemplateArgumentDeduction {
par= fnPars[j];
if (par instanceof ICPPParameterPackType) {
if (j != fnParCount - 1)
continue; // non-deduced context
continue argLoop; // Non-deduced context
par= fnParPack= ((ICPPParameterPackType) par).getType();
deduct= new TemplateArgumentDeduction(deduct, fnArgs.size() - j);
@ -268,14 +270,12 @@ public class TemplateArgumentDeduction {
if (!CPPTemplates.isValidType(par))
return false;
boolean isDependentPar= CPPTemplates.isDependentType(par);
if (checkExactMatch || isDependentPar) {
if (CPPTemplates.isDependentType(par)) {
IType arg = fnArgs.get(j);
par= SemanticUtil.getNestedType(par, SemanticUtil.TDEF); // adjustParameterType preserves typedefs
// C++0x: 14.9.2.1-1
if (arg instanceof InitializerListType) {
assert !checkExactMatch;
par= SemanticUtil.getNestedType(par, TDEF | REF | CVTYPE);
// Check if this is a deduced context
@ -285,23 +285,44 @@ public class TemplateArgumentDeduction {
IType[] types = initListType.getExpressionTypes();
ValueCategory[] valueCats = initListType.getValueCategories();
for (int i = 0; i < types.length; i++) {
if (!deduceFromFunctionArg(inner, types[i], valueCats[i], checkExactMatch, isDependentPar, deduct))
if (!deduceFromFunctionArg(inner, types[i], valueCats[i], deduct))
return false;
}
}
continue;
}
// 14.8.2.1-2
ValueCategory cat= argCats != null ? argCats.get(j) : LVALUE;
if (!deduceFromFunctionArg(par, arg, cat, checkExactMatch, isDependentPar, deduct)) {
return false;
} else if (arg instanceof FunctionSetType) {
// 14.8.2.1-6 Handling of overloaded function sets
ICPPFunction[] fs= ((FunctionSetType) arg).getFunctionSet();
for (ICPPFunction f : fs) {
if (f instanceof ICPPFunctionTemplate)
continue argLoop; // Non-deduced context
}
// Do trial deduction
CPPTemplateParameterMap success= null;
Set<String> handled= new HashSet<String>();
for (ICPPFunction f : fs) {
arg= f.getType();
if (handled.add(ASTTypeUtil.getType(arg, true))) {
final CPPTemplateParameterMap state = deduct.saveState();
if (deduceFromFunctionArg(par, arg, argCats.get(j), deduct)) {
if (success != null) {
deduct.restoreState(state);
continue argLoop; // Non-deduced context
}
success= deduct.saveState();
}
deduct.restoreState(state);
}
}
if (success == null)
return false;
deduct.restoreState(success);
} else {
if (!deduceFromFunctionArg(par, arg, argCats.get(j), deduct))
return false;
}
}
}
// Bug 309564: For partial ordering not all arguments need to be deduced
if (checkExactMatch)
return true;
if (!deduct.fExplicitArgs.mergeToExplicit(deduct.fDeducedArgs))
return false;
@ -312,7 +333,7 @@ public class TemplateArgumentDeduction {
return false;
}
private static boolean deduceFromFunctionArg(IType par, IType arg, ValueCategory valueCat, boolean checkExactMatch, boolean isDependentPar, TemplateArgumentDeduction deduct) throws DOMException {
private static boolean deduceFromFunctionArg(IType par, IType arg, ValueCategory valueCat, TemplateArgumentDeduction deduct) throws DOMException {
boolean isReferenceTypeParameter= false;
if (par instanceof ICPPReferenceType) {
// If P is an rvalue reference to a cv-unqualified template parameter and the argument is an
@ -330,61 +351,113 @@ public class TemplateArgumentDeduction {
arg= getArgumentTypeForDeduction(arg, false);
}
if (!checkExactMatch) {
// 14.8.2.1-3
CVQualifier cvPar= SemanticUtil.getCVQualifier(par);
CVQualifier cvArg= SemanticUtil.getCVQualifier(arg);
if (cvPar == cvArg || (isReferenceTypeParameter && cvPar.isAtLeastAsQualifiedAs(cvArg))) {
IType pcheck= SemanticUtil.getNestedType(par, CVTYPE);
if (!(pcheck instanceof ICPPTemplateParameter)) {
par= pcheck;
arg= SemanticUtil.getNestedType(arg, CVTYPE);
IType argcheck= arg;
if (par instanceof IPointerType && arg instanceof IPointerType) {
pcheck= ((IPointerType) par).getType();
argcheck= ((IPointerType) arg).getType();
if (pcheck instanceof ICPPTemplateParameter) {
pcheck= null;
// 14.8.2.1-3
CVQualifier cvPar= SemanticUtil.getCVQualifier(par);
CVQualifier cvArg= SemanticUtil.getCVQualifier(arg);
if (cvPar == cvArg || (isReferenceTypeParameter && cvPar.isAtLeastAsQualifiedAs(cvArg))) {
IType pcheck= SemanticUtil.getNestedType(par, CVTYPE);
if (!(pcheck instanceof ICPPTemplateParameter)) {
par= pcheck;
arg= SemanticUtil.getNestedType(arg, CVTYPE);
IType argcheck= arg;
if (par instanceof IPointerType && arg instanceof IPointerType) {
pcheck= ((IPointerType) par).getType();
argcheck= ((IPointerType) arg).getType();
if (pcheck instanceof ICPPTemplateParameter) {
pcheck= null;
} else {
cvPar= SemanticUtil.getCVQualifier(pcheck);
cvArg= SemanticUtil.getCVQualifier(argcheck);
if (cvPar.isAtLeastAsQualifiedAs(cvArg)) {
pcheck= SemanticUtil.getNestedType(pcheck, CVTYPE);
argcheck= SemanticUtil.getNestedType(argcheck, CVTYPE);
} else {
cvPar= SemanticUtil.getCVQualifier(pcheck);
cvArg= SemanticUtil.getCVQualifier(argcheck);
if (cvPar.isAtLeastAsQualifiedAs(cvArg)) {
pcheck= SemanticUtil.getNestedType(pcheck, CVTYPE);
argcheck= SemanticUtil.getNestedType(argcheck, CVTYPE);
} else {
pcheck= null;
}
pcheck= null;
}
}
if (pcheck instanceof ICPPTemplateInstance && argcheck instanceof ICPPClassType) {
ICPPTemplateInstance pInst = (ICPPTemplateInstance) pcheck;
ICPPClassTemplate pTemplate= getPrimaryTemplate(pInst);
if (pTemplate != null) {
ICPPClassType aInst= findBaseInstance((ICPPClassType) argcheck, pTemplate, CPPSemantics.MAX_INHERITANCE_DEPTH);
if (aInst != null && aInst != argcheck) {
par= pcheck;
arg= aInst;
}
}
if (pcheck instanceof ICPPTemplateInstance && argcheck instanceof ICPPClassType) {
ICPPTemplateInstance pInst = (ICPPTemplateInstance) pcheck;
ICPPClassTemplate pTemplate= getPrimaryTemplate(pInst);
if (pTemplate != null) {
ICPPClassType aInst= findBaseInstance((ICPPClassType) argcheck, pTemplate, CPPSemantics.MAX_INHERITANCE_DEPTH);
if (aInst != null && aInst != argcheck) {
par= pcheck;
arg= aInst;
}
}
}
}
}
if (isDependentPar && !deduct.fromType(par, arg, true)) {
return false;
return deduct.fromType(par, arg, true);
}
/**
* Deduces the mapping for the template parameters from the function parameters,
* returns <code>false</code> if there is no mapping.
*/
static int deduceForPartialOrdering(ICPPTemplateParameter[] tmplPars, IType[] fnPars, IType[] fnArgs) {
try {
final int fnParCount = fnPars.length;
final int fnArgCount = fnArgs.length;
int result= 0;
TemplateArgumentDeduction deduct= new TemplateArgumentDeduction(tmplPars, new CPPTemplateParameterMap(0), new CPPTemplateParameterMap(fnParCount), 0);
IType fnParPack= null;
for (int j= 0; j < fnArgCount; j++) {
IType par;
if (fnParPack != null) {
par= fnParPack;
deduct.incPackOffset();
} else {
if (j >= fnParCount)
return result;
par= fnPars[j];
if (par instanceof ICPPParameterPackType) {
if (j != fnParCount - 1)
continue; // non-deduced context
par= fnParPack= ((ICPPParameterPackType) par).getType();
deduct= new TemplateArgumentDeduction(deduct, fnArgs.length - j);
}
}
IType arg = fnArgs[j];
int cmpSpecialized= deduceForPartialOrdering(par, arg, deduct);
if (cmpSpecialized < 0)
return cmpSpecialized;
if (cmpSpecialized > 0)
result= cmpSpecialized;
}
return result;
} catch (DOMException e) {
}
if (checkExactMatch) {
IType instantiated= CPPTemplates.instantiateType(par, deduct.fDeducedArgs, deduct.fPackOffset, null);
if (!instantiated.isSameType(arg))
return false;
return -1;
}
private static int deduceForPartialOrdering(IType par, IType arg, TemplateArgumentDeduction deduct) throws DOMException {
par= getNestedType(par, TDEF);
arg= getNestedType(arg, TDEF);
boolean isMoreCVQualified= false;
if (par instanceof ICPPReferenceType && arg instanceof ICPPReferenceType) {
par= getNestedType(par, REF | TDEF);
arg= getNestedType(arg, REF | TDEF);
CVQualifier cvp= getCVQualifier(par);
CVQualifier cva= getCVQualifier(arg);
isMoreCVQualified= cva.isMoreQualifiedThan(cvp);
}
return true;
par= getNestedType(par, TDEF | REF | ALLCVQ);
arg= getNestedType(arg, TDEF | REF | ALLCVQ);
if (!deduct.fromType(par, arg, false))
return -1;
return isMoreCVQualified ? 1 : 0;
}
/**
* 14.8.2.1.3 If P is a class and has the form template-id, then A can be a derived class of the deduced A.
* @throws DOMException
*/
private static ICPPClassType findBaseInstance(ICPPClassType a, ICPPClassTemplate pTemplate, int maxdepth) throws DOMException {
if (a instanceof ICPPTemplateInstance) {
@ -519,6 +592,14 @@ public class TemplateArgumentDeduction {
fPackSize= packSize;
fPackOffset= packSize > 0 ? 0 : -1;
}
private CPPTemplateParameterMap saveState() {
return new CPPTemplateParameterMap(fDeducedArgs);
}
private void restoreState(CPPTemplateParameterMap saved) {
fDeducedArgs= saved;
}
private void incPackOffset() {
fPackOffset++;
@ -535,15 +616,21 @@ public class TemplateArgumentDeduction {
if (p.isNonTypeValue()) {
IValue tval= p.getNonTypeValue();
int parId= Value.isTemplateParameter(tval);
if (parId >= 0) {
ICPPTemplateArgument old= fDeducedArgs.getArgument(parId, fPackOffset);
if (old == null) {
return deduce(parId, a);
if (Value.referencesTemplateParameter(tval)) {
int parId= Value.isTemplateParameter(tval);
if (parId >= 0) {
if (!p.getTypeOfNonTypeValue().isSameType(a.getTypeOfNonTypeValue()))
return false;
ICPPTemplateArgument old= fDeducedArgs.getArgument(parId, fPackOffset);
if (old == null) {
return deduce(parId, a);
}
return old.isSameValue(a);
} else {
// Non-deduced context
return true;
}
return old.isSameValue(a);
}
IValue sval= a.getNonTypeValue();
return tval.equals(sval);
}
@ -758,6 +845,8 @@ public class TemplateArgumentDeduction {
return false;
return fDeducedArgs.putPackElement(parID, fPackOffset, arg, fPackSize);
}
if (SemanticUtil.containsUniqueTypeForParameterPack(arg.getTypeValue()))
return false;
fDeducedArgs.put(parID, arg);
return true;
}

View file

@ -0,0 +1,35 @@
/*
* UniqueType.java
* Created on 04.10.2010
*
* Copyright 2010 Wind River Systems, Inc. All rights reserved.
*/
package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics;
import org.eclipse.cdt.core.dom.ast.IType;
/**
* Used for computing the partial ordering of function templates.
*/
class UniqueType implements IType {
private boolean fForParameterPack;
public UniqueType(boolean forParameterPack) {
fForParameterPack= forParameterPack;
}
public boolean isSameType(IType type) {
return type == this;
}
public boolean isForParameterPack() {
return fForParameterPack;
}
@Override
public Object clone() {
throw new UnsupportedOperationException();
}
}