mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-29 19:45:01 +02:00
Bug 280909: Type deduction and instantiation for variadic templates.
This commit is contained in:
parent
54f917f440
commit
0ef32519a1
24 changed files with 1666 additions and 838 deletions
|
@ -14,6 +14,8 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.cdt.core.parser.tests.ast2;
|
||||
|
||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.TDEF;
|
||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.getNestedType;
|
||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.getUltimateType;
|
||||
import junit.framework.TestSuite;
|
||||
|
||||
|
@ -4365,7 +4367,7 @@ public class AST2TemplateTests extends AST2BaseTest {
|
|||
assertEquals("void (#0 (* ...)())", ASTTypeUtil.getType(f.getType(), true));
|
||||
assertTrue(f.getParameters()[0].isParameterPack());
|
||||
f= bh.assertNonProblem("f4", 2);
|
||||
assertEquals("void (int (& ...)[#0])", ASTTypeUtil.getType(f.getType(), true));
|
||||
assertEquals("void (int (& ...)[`0])", ASTTypeUtil.getType(f.getType(), true));
|
||||
assertTrue(f.getParameters()[0].isParameterPack());
|
||||
f= bh.assertNonProblem("f5", 2);
|
||||
assertEquals("void (#0 ...)", ASTTypeUtil.getType(f.getType(), true));
|
||||
|
@ -4397,6 +4399,32 @@ public class AST2TemplateTests extends AST2BaseTest {
|
|||
assertTrue(tp.isParameterPack());
|
||||
}
|
||||
|
||||
// template <typename... Pack> class CT : public Pack... {
|
||||
// void mem() throw(Pack...);
|
||||
// };
|
||||
// struct A {int a;};
|
||||
// struct B {int b;};
|
||||
//
|
||||
// void test() {
|
||||
// CT<A,B> c;
|
||||
// c.a= 1;
|
||||
// c.b= 1;
|
||||
// c.mem();
|
||||
// }
|
||||
public void testParameterPackExpansions_280909() throws Exception {
|
||||
final String code= getAboveComment();
|
||||
parseAndCheckBindings(code, ParserLanguage.CPP);
|
||||
BindingAssertionHelper bh= new BindingAssertionHelper(code, true);
|
||||
ICPPField field= bh.assertNonProblem("a= 1", 1);
|
||||
field= bh.assertNonProblem("b= 1", 1);
|
||||
|
||||
ICPPMethod meth= bh.assertNonProblem("mem();", 3);
|
||||
IType[] spec= meth.getExceptionSpecification();
|
||||
assertEquals(2, spec.length);
|
||||
assertEquals("A", ASTTypeUtil.getType(spec[0]));
|
||||
assertEquals("B", ASTTypeUtil.getType(spec[1]));
|
||||
}
|
||||
|
||||
// template<typename... T> void f1(T*...);
|
||||
// template<typename T> void f2(T*...);
|
||||
public void testTemplateParameterPacksAmbiguity_280909() throws Exception {
|
||||
|
@ -4426,7 +4454,7 @@ public class AST2TemplateTests extends AST2BaseTest {
|
|||
// void g() {
|
||||
// f(add, subtract);
|
||||
// }
|
||||
public void _testVariadicTemplateExamples_280909b() throws Exception {
|
||||
public void testVariadicTemplateExamples_280909b() throws Exception {
|
||||
final String code= getAboveComment();
|
||||
parseAndCheckBindings(code, ParserLanguage.CPP);
|
||||
}
|
||||
|
@ -4474,7 +4502,7 @@ public class AST2TemplateTests extends AST2BaseTest {
|
|||
// Y<A> ya; // ill-formed: a template parameter pack does not match a template parameter
|
||||
// Y<B> yb; // ill-formed: a template parameter pack does not match a template parameter
|
||||
// Y<C> yc; // okay
|
||||
public void _testVariadicTemplateExamples_280909f() throws Exception {
|
||||
public void testVariadicTemplateExamples_280909f() throws Exception {
|
||||
final String code= getAboveComment();
|
||||
BindingAssertionHelper bh= new BindingAssertionHelper(code, true);
|
||||
bh.assertNonProblem("X<A>", 4);
|
||||
|
@ -4539,13 +4567,13 @@ public class AST2TemplateTests extends AST2BaseTest {
|
|||
// f("aa",3.0); // error: X cannot be deduced
|
||||
// f2<char, short, int, long>(); // okay
|
||||
// }
|
||||
public void _testVariadicTemplateExamples_280909i() throws Exception {
|
||||
public void testVariadicTemplateExamples_280909i() throws Exception {
|
||||
final String code= getAboveComment();
|
||||
BindingAssertionHelper bh= new BindingAssertionHelper(code, true);
|
||||
bh.assertNonProblem("f<int,char*,double>", 0);
|
||||
bh.assertNonProblem("f<int,char*>", 0);
|
||||
bh.assertProblem("f<int>", 0);
|
||||
bh.assertNonProblem("f(", 1);
|
||||
bh.assertNonProblem("f<int>", 0);
|
||||
bh.assertProblem("f(\"aa\",3.0)", 1);
|
||||
bh.assertNonProblem("f2<char, short, int, long>", 0);
|
||||
}
|
||||
|
||||
|
@ -4553,19 +4581,19 @@ public class AST2TemplateTests extends AST2BaseTest {
|
|||
// void g() {
|
||||
// f<int*, float*>(0, 0, 0); // Types is the sequence int*, float*, int
|
||||
// }
|
||||
public void _testVariadicTemplateExamples_280909j() throws Exception {
|
||||
public void testVariadicTemplateExamples_280909j() throws Exception {
|
||||
final String code= getAboveComment();
|
||||
parseAndCheckBindings(code, ParserLanguage.CPP);
|
||||
}
|
||||
|
||||
// template<class... Types> void f(Types&...);
|
||||
// template<class T, class... Types> void g(T1, Types...);
|
||||
// template<class T1, class... Types> void g(T1, Types...);
|
||||
// void h(int x, float& y) {
|
||||
// const int z = x;
|
||||
// f(x, y, z); // Types is deduced to int, float, const int
|
||||
// g(x, y, z); // T1 is deduced to int, Types is deduced to float, int
|
||||
// }
|
||||
public void _testVariadicTemplateExamples_280909k() throws Exception {
|
||||
public void testVariadicTemplateExamples_280909k() throws Exception {
|
||||
final String code= getAboveComment();
|
||||
parseAndCheckBindings(code, ParserLanguage.CPP);
|
||||
}
|
||||
|
@ -4574,11 +4602,13 @@ public class AST2TemplateTests extends AST2BaseTest {
|
|||
// template<typename... Types> void g(Tuple<Types...>); // #1
|
||||
// template<typename T1, typename... Types> void g(Tuple<T1, Types...>); // #2
|
||||
// template<typename T1, typename... Types> void g(Tuple<T1, Types&...>); // #3
|
||||
// void test() {
|
||||
// g(Tuple<>()); // calls #1
|
||||
// g(Tuple<int, float>()); // calls #2
|
||||
// g(Tuple<int, float&>()); // calls #3
|
||||
// g(Tuple<int>()); // calls #3
|
||||
public void _testVariadicTemplateExamples_280909m() throws Exception {
|
||||
// }
|
||||
public void testVariadicTemplateExamples_280909m() throws Exception {
|
||||
final String code= getAboveComment();
|
||||
parseAndCheckBindings(code, ParserLanguage.CPP);
|
||||
BindingAssertionHelper bh= new BindingAssertionHelper(code, true);
|
||||
|
@ -4586,21 +4616,21 @@ public class AST2TemplateTests extends AST2BaseTest {
|
|||
ICPPFunction g2= bh.assertNonProblem("g(Tuple<T1, Types...>)", 1);
|
||||
ICPPFunction g3= bh.assertNonProblem("g(Tuple<T1, Types&...>)", 1);
|
||||
|
||||
ICPPFunction x= bh.assertNonProblem("g(Tuple<>())", 1);
|
||||
assertSame(g1, x);
|
||||
ICPPTemplateInstance x= bh.assertNonProblem("g(Tuple<>())", 1);
|
||||
assertSame(g1, x.getTemplateDefinition());
|
||||
x= bh.assertNonProblem("g(Tuple<int, float>())", 1);
|
||||
assertSame(g2, x);
|
||||
assertSame(g2, x.getTemplateDefinition());
|
||||
x= bh.assertNonProblem("g(Tuple<int, float&>())", 1);
|
||||
assertSame(g3, x);
|
||||
assertSame(g3, x.getTemplateDefinition());
|
||||
x= bh.assertNonProblem("g(Tuple<int>())", 1);
|
||||
assertSame(g3, x);
|
||||
assertSame(g3, x.getTemplateDefinition());
|
||||
}
|
||||
|
||||
// template<class> struct X { };
|
||||
// template<class R, class... ArgTypes> struct X<R(int, ArgTypes...)> { };
|
||||
// template<class... Types> struct Y { };
|
||||
// template<class T, class... Types> struct Y<T, Types&...> { };
|
||||
// template <class... Types> int f (void ()(Types...));
|
||||
// template <class... Types> int f (void (*)(Types...));
|
||||
// void g(int, float);
|
||||
// X<int> x1; // uses primary template
|
||||
// X<int(int, float, double)> x2; // uses partial specialization, ArgTypes contains float, double
|
||||
|
@ -4609,7 +4639,7 @@ public class AST2TemplateTests extends AST2BaseTest {
|
|||
// Y<int&, float&, double&> y2; // uses partial specialization. T is int&, Types contains float, double
|
||||
// Y<int, float, double> y3; // uses primary template, Types contains int, float, double
|
||||
// int fv = f(g); // okay, Types contains int, float
|
||||
public void _testVariadicTemplateExamples_280909n() throws Exception {
|
||||
public void testVariadicTemplateExamples_280909n() throws Exception {
|
||||
final String code= getAboveComment();
|
||||
parseAndCheckBindings(code, ParserLanguage.CPP);
|
||||
}
|
||||
|
@ -4622,7 +4652,7 @@ public class AST2TemplateTests extends AST2BaseTest {
|
|||
// f(1, 2, 3); // calls #2
|
||||
// f(1, 2); // calls #3; non-variadic template #3 is
|
||||
// } // more specialized than the variadic templates #1 and #2
|
||||
public void _testVariadicTemplateExamples_280909o() throws Exception {
|
||||
public void testVariadicTemplateExamples_280909o() throws Exception {
|
||||
final String code= getAboveComment();
|
||||
parseAndCheckBindings(code, ParserLanguage.CPP);
|
||||
BindingAssertionHelper bh= new BindingAssertionHelper(code, true);
|
||||
|
@ -4630,12 +4660,12 @@ public class AST2TemplateTests extends AST2BaseTest {
|
|||
ICPPFunction f2= bh.assertNonProblem("f(T1 a1, Args... args)", 1);
|
||||
ICPPFunction f3= bh.assertNonProblem("f(T1 a2, T2 a2)", 1);
|
||||
|
||||
ICPPFunction x= bh.assertNonProblem("f()", 1);
|
||||
assertSame(f1, x);
|
||||
ICPPTemplateInstance x= bh.assertNonProblem("f()", 1);
|
||||
assertSame(f1, x.getTemplateDefinition());
|
||||
x= bh.assertNonProblem("f(1, 2, 3)", 1);
|
||||
assertSame(f2, x);
|
||||
assertSame(f2, x.getTemplateDefinition());
|
||||
x= bh.assertNonProblem("f(1, 2)", 1);
|
||||
assertSame(f3, x);
|
||||
assertSame(f3, x.getTemplateDefinition());
|
||||
}
|
||||
|
||||
// template<typename... Types> struct Tuple { };
|
||||
|
@ -4645,7 +4675,7 @@ public class AST2TemplateTests extends AST2BaseTest {
|
|||
// Tuple<int, float> t2; // Types contains two arguments: int and float
|
||||
// Tuple<0> error; // Error: 0 is not a type
|
||||
// }
|
||||
public void _testVariadicTemplateExamples_280909p() throws Exception {
|
||||
public void testVariadicTemplateExamples_280909p() throws Exception {
|
||||
final String code= getAboveComment();
|
||||
BindingAssertionHelper bh= new BindingAssertionHelper(code, true);
|
||||
bh.assertNonProblem("Tuple<>", 0);
|
||||
|
@ -4660,7 +4690,7 @@ public class AST2TemplateTests extends AST2BaseTest {
|
|||
// f(1); // okay: args contains one int argument
|
||||
// f(2, 1.0); // okay: args contains two arguments, an int and a double
|
||||
// }
|
||||
public void _testVariadicTemplateExamples_280909q() throws Exception {
|
||||
public void testVariadicTemplateExamples_280909q() throws Exception {
|
||||
final String code= getAboveComment();
|
||||
parseAndCheckBindings(code, ParserLanguage.CPP);
|
||||
}
|
||||
|
@ -4686,21 +4716,28 @@ public class AST2TemplateTests extends AST2BaseTest {
|
|||
// typedef zip<short>::with<unsigned short, unsigned>::type T2;
|
||||
// // error: different number of arguments specified
|
||||
// // for Args1 and Args2
|
||||
// template<typename... Args> void f(Args... args) {}
|
||||
// template<typename... Args> void h(Args... args) {}
|
||||
// template<typename... Args> void g(Args... args) {
|
||||
// f(const cast<const Args*>(&args)...); // okay: ‘‘Args’’ and ‘‘args’’ are expanded
|
||||
// f(const_cast<const Args*>(&args)...); // okay: ‘‘Args’’ and ‘‘args’’ are expanded
|
||||
// f(5 ...); // error: pattern does not contain any parameter packs
|
||||
// f(args); // error: parameter pack ”args” is not expanded
|
||||
// f(h(args...) + args...); // okay: first ‘‘args’’ expanded within h, second ‘‘args’’ expanded within f.
|
||||
// }
|
||||
public void _testVariadicTemplateExamples_280909s() throws Exception {
|
||||
public void testVariadicTemplateExamples_280909s() throws Exception {
|
||||
final String code= getAboveComment();
|
||||
BindingAssertionHelper bh= new BindingAssertionHelper(code, true);
|
||||
ITypedef td= bh.assertNonProblem("T1;", 2);
|
||||
assertEquals("Tuple<Pair<short, unsigned short>, Pair<int, unsigned> >", ASTTypeUtil.getType(td, true));
|
||||
bh.assertProblem("zip<short>::with<unsigned short, unsigned>::type", 0);
|
||||
bh.assertNonProblem("f(const cast<const Args*>(&args)...)", 1);
|
||||
bh.assertProblem("f(5 ...)", 1);
|
||||
bh.assertProblem("f(args)", 1);
|
||||
bh.assertNonProblem("f(h(args...) + args...)", 1);
|
||||
IType type = getNestedType(td, TDEF);
|
||||
assertEquals("Tuple<Pair<short int,unsigned short int>,Pair<int,unsigned int>>", ASTTypeUtil.getType(type, false));
|
||||
td= bh.assertNonProblem("zip<short>::with<unsigned short, unsigned>::type", 0);
|
||||
type = getNestedType(td, TDEF);
|
||||
assertTrue(type instanceof IProblemBinding);
|
||||
|
||||
ICPPUnknownBinding ub;
|
||||
ub= bh.assertNonProblem("f(const_cast<const Args*>(&args)...)", 1);
|
||||
ub= bh.assertNonProblem("f(5 ...)", 1); // no diagnostics in CDT, treated as unknown function.
|
||||
ub= bh.assertNonProblem("f(args)", 1); // no diagnostics in CDT
|
||||
ub= bh.assertNonProblem("f(h(args...) + args...)", 1);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,9 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.cdt.internal.core.model.ext;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.cdt.core.dom.ast.ASTTypeUtil;
|
||||
import org.eclipse.cdt.core.dom.ast.DOMException;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassSpecialization;
|
||||
|
@ -55,13 +58,21 @@ public class StructureTemplateHandle extends StructureHandle implements IStructu
|
|||
fTemplate= new Template(classBinding.getName());
|
||||
ICPPTemplateParameterMap map = classBinding.getTemplateParameterMap();
|
||||
ICPPTemplateParameter[] tpars = ct.getTemplateParameters();
|
||||
String[] args= new String[tpars.length];
|
||||
for (int i = 0; i < tpars.length; i++) {
|
||||
ICPPTemplateParameter par = tpars[i];
|
||||
ICPPTemplateArgument arg = map.getArgument(par);
|
||||
args[i]= arg == null ? par.getName() : ASTTypeUtil.getArgumentString(arg, false);
|
||||
List<String> args= new ArrayList<String>(tpars.length);
|
||||
for (ICPPTemplateParameter par : tpars) {
|
||||
if (par.isParameterPack()) {
|
||||
ICPPTemplateArgument[] pack= map.getPackExpansion(par);
|
||||
if (pack != null) {
|
||||
for (ICPPTemplateArgument p : pack) {
|
||||
args.add(ASTTypeUtil.getArgumentString(p, false));
|
||||
}
|
||||
fTemplate.setTemplateInfo(null, args);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
ICPPTemplateArgument arg = map.getArgument(par);
|
||||
args.add(arg == null ? par.getName() : ASTTypeUtil.getArgumentString(arg, false));
|
||||
}
|
||||
fTemplate.setTemplateInfo(null, args.toArray(new String[args.size()]));
|
||||
}
|
||||
|
||||
public int getNumberOfTemplateParameters() {
|
||||
|
|
|
@ -60,4 +60,16 @@ public interface ICPPTemplateArgument {
|
|||
* Checks whether two arguments denote the same value.
|
||||
*/
|
||||
boolean isSameValue(ICPPTemplateArgument arg);
|
||||
|
||||
/**
|
||||
* Returns whether this template argument is a pack expansion or not.
|
||||
* @since 5.2
|
||||
*/
|
||||
boolean isPackExpansion();
|
||||
|
||||
/**
|
||||
* Returns the expansion pattern, if this is a pack expansion, or <code>null</code> otherwise.
|
||||
* @since 5.2
|
||||
*/
|
||||
ICPPTemplateArgument getExpansionPattern();
|
||||
}
|
||||
|
|
|
@ -12,7 +12,8 @@ package org.eclipse.cdt.core.dom.ast.cpp;
|
|||
|
||||
|
||||
/**
|
||||
* Models the mapping of template parameters to values.
|
||||
* Models the mapping of template parameters to values, or pack-expansions.
|
||||
*
|
||||
* @since 5.1
|
||||
* @noextend This interface is not intended to be extended by clients.
|
||||
* @noimplement This interface is not intended to be implemented by clients.
|
||||
|
@ -27,10 +28,25 @@ public interface ICPPTemplateParameterMap {
|
|||
|
||||
/**
|
||||
* Returns the value for the template parameter in the map, or <code>null</code> if
|
||||
* the parameter is not mapped.
|
||||
* the parameter is not mapped or the parameter is a parameter pack.
|
||||
*/
|
||||
public ICPPTemplateArgument getArgument(ICPPTemplateParameter param);
|
||||
|
||||
|
||||
/**
|
||||
* Returns the values for the template parameter pack with the given id in the map,
|
||||
* or <code>null</code> if the parameter is not mapped or is not a parameter pack.
|
||||
* @since 5.2
|
||||
*/
|
||||
public ICPPTemplateArgument[] getPackExpansion(int paramID);
|
||||
|
||||
/**
|
||||
* Returns the values for the template parameter pack in the map, or <code>null</code> if the
|
||||
* parameter is not mapped or is no parameter pack.
|
||||
* @since 5.2
|
||||
*/
|
||||
public ICPPTemplateArgument[] getPackExpansion(ICPPTemplateParameter param);
|
||||
|
||||
/**
|
||||
* Returns the array of template parameter positions, for which a mapping exists.
|
||||
*/
|
||||
|
|
|
@ -46,10 +46,12 @@ public class Value implements IValue {
|
|||
public static final int MAX_RECURSION_DEPTH = 25;
|
||||
public final static IValue UNKNOWN= new Value("<unknown>".toCharArray(), ICPPUnknownBinding.EMPTY_UNKNOWN_BINDING_ARRAY); //$NON-NLS-1$
|
||||
public final static IValue NOT_INITIALIZED= new Value("<__>".toCharArray(), ICPPUnknownBinding.EMPTY_UNKNOWN_BINDING_ARRAY); //$NON-NLS-1$
|
||||
private static final int[] NO_INT = {};
|
||||
|
||||
private static final String SCOPE_OP = "::"; //$NON-NLS-1$
|
||||
private static final char UNIQUE_CHAR = '_';
|
||||
private static final char TEMPLATE_PARAM_CHAR = '#';
|
||||
private static final char TEMPLATE_PARAM_PACK_CHAR = '`';
|
||||
private static final char REFERENCE_CHAR = '&';
|
||||
private static final char UNARY_OP_CHAR = '$';
|
||||
private static final char BINARY_OP_CHAR = '@';
|
||||
|
@ -69,13 +71,17 @@ public class Value implements IValue {
|
|||
|
||||
private static class Reevaluation {
|
||||
public final char[] fExpression;
|
||||
private int fPackOffset;
|
||||
public int pos=0;
|
||||
public final Map<String, Integer> fUnknownSigs;
|
||||
public final List<ICPPUnknownBinding> fUnknowns;
|
||||
public final IBinding[] fResolvedUnknown;
|
||||
public final ICPPTemplateParameterMap fMap;
|
||||
public Reevaluation(char[] expr, Map<String, Integer> unknownSigs, List<ICPPUnknownBinding> unknowns, IBinding[] resolvedUnknowns, ICPPTemplateParameterMap map) {
|
||||
|
||||
public Reevaluation(char[] expr, int packOffset, Map<String, Integer> unknownSigs,
|
||||
List<ICPPUnknownBinding> unknowns, IBinding[] resolvedUnknowns, ICPPTemplateParameterMap map) {
|
||||
fExpression= expr;
|
||||
fPackOffset= packOffset;
|
||||
fUnknownSigs= unknownSigs;
|
||||
fUnknowns= unknowns;
|
||||
fResolvedUnknown= resolvedUnknowns;
|
||||
|
@ -189,25 +195,26 @@ public class Value implements IValue {
|
|||
* Creates a value representing the given template parameter.
|
||||
*/
|
||||
public static IValue create(ICPPTemplateNonTypeParameter tntp) {
|
||||
final String expr = createTemplateParamExpression(tntp.getParameterID());
|
||||
final String expr = createTemplateParamExpression(tntp.getParameterID(), tntp.isParameterPack());
|
||||
return new Value(expr.toCharArray(), ICPPUnknownBinding.EMPTY_UNKNOWN_BINDING_ARRAY);
|
||||
}
|
||||
|
||||
private static String createTemplateParamExpression(int id) {
|
||||
private static String createTemplateParamExpression(int id, boolean isPack) {
|
||||
StringBuilder buf= new StringBuilder();
|
||||
buf.append(TEMPLATE_PARAM_CHAR);
|
||||
buf.append(isPack ? TEMPLATE_PARAM_PACK_CHAR : TEMPLATE_PARAM_CHAR);
|
||||
buf.append(Integer.toHexString(id));
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether the value is a template parameter, returns the parameter id of the
|
||||
* parameter, or <code>-1</code> if it is not a template parameter.
|
||||
* Tests whether the value is a template parameter (or parameter pack),
|
||||
* returns the parameter id of the parameter, or <code>-1</code> if it is not a template parameter.
|
||||
*/
|
||||
public static int isTemplateParameter(IValue tval) {
|
||||
final char[] rep= tval.getInternalExpression();
|
||||
if (rep.length > 0) {
|
||||
if (rep[0] == TEMPLATE_PARAM_CHAR) {
|
||||
final char c = rep[0];
|
||||
if (c == TEMPLATE_PARAM_CHAR || c == TEMPLATE_PARAM_PACK_CHAR) {
|
||||
for (int i = 1; i < rep.length; i++) {
|
||||
if (rep[i] == SEPARATOR)
|
||||
return -1;
|
||||
|
@ -227,7 +234,7 @@ public class Value implements IValue {
|
|||
public static boolean referencesTemplateParameter(IValue tval) {
|
||||
final char[] rep= tval.getInternalExpression();
|
||||
for (char element : rep) {
|
||||
if (element == TEMPLATE_PARAM_CHAR)
|
||||
if (element == TEMPLATE_PARAM_CHAR || element == TEMPLATE_PARAM_PACK_CHAR)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -239,12 +246,50 @@ public class Value implements IValue {
|
|||
public static boolean isDependentValue(IValue nonTypeValue) {
|
||||
final char[] rep= nonTypeValue.getInternalExpression();
|
||||
for (final char c : rep) {
|
||||
if (c == REFERENCE_CHAR || c == TEMPLATE_PARAM_CHAR)
|
||||
if (c == REFERENCE_CHAR || c == TEMPLATE_PARAM_CHAR || c == TEMPLATE_PARAM_PACK_CHAR)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Collects all references to parameter packs.
|
||||
*/
|
||||
public static int[] getParameterPackReferences(IValue value) {
|
||||
final char[] rep= value.getInternalExpression();
|
||||
int result= -1;
|
||||
List<Integer> array= null;
|
||||
for (int i=0; i<rep.length-1; i++) {
|
||||
if (rep[i] == TEMPLATE_PARAM_PACK_CHAR) {
|
||||
int ref;
|
||||
try {
|
||||
ref = parseHex(rep, i + 1);
|
||||
if (result < 0) {
|
||||
result = ref;
|
||||
} else {
|
||||
if (array == null) {
|
||||
array = new ArrayList<Integer>(2);
|
||||
array.add(result);
|
||||
}
|
||||
array.add(ref);
|
||||
}
|
||||
} catch (UnknownValueException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (array != null) {
|
||||
int[] ra= new int[array.size()];
|
||||
for (int i = 0; i < ra.length; i++) {
|
||||
ra[i]= array.get(i);
|
||||
}
|
||||
return ra;
|
||||
}
|
||||
if (result != -1)
|
||||
return new int[] {result};
|
||||
|
||||
return NO_INT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the value for an expression.
|
||||
*/
|
||||
|
@ -371,8 +416,10 @@ public class Value implements IValue {
|
|||
if (b instanceof IType) {
|
||||
throw UNKNOWN_EX;
|
||||
}
|
||||
if (b instanceof ICPPTemplateNonTypeParameter)
|
||||
return createTemplateParamExpression(((ICPPTemplateNonTypeParameter) b).getParameterID());
|
||||
if (b instanceof ICPPTemplateNonTypeParameter) {
|
||||
final ICPPTemplateNonTypeParameter tp = (ICPPTemplateNonTypeParameter) b;
|
||||
return createTemplateParamExpression(tp.getParameterID(), tp.isParameterPack());
|
||||
}
|
||||
|
||||
if (b instanceof ICPPUnknownBinding) {
|
||||
return createReference((ICPPUnknownBinding) b, unknownSigs, unknowns);
|
||||
|
@ -591,11 +638,11 @@ public class Value implements IValue {
|
|||
return BINARY_OP_CHAR + op + SEPARATOR + o1.toString() + SEPARATOR + o2.toString();
|
||||
}
|
||||
|
||||
public static IValue reevaluate(IValue val, IBinding[] resolvedUnknowns, ICPPTemplateParameterMap map, int maxdepth) {
|
||||
public static IValue reevaluate(IValue val, int packOffset, IBinding[] resolvedUnknowns, ICPPTemplateParameterMap map, int maxdepth) {
|
||||
try {
|
||||
Map<String, Integer> unknownSigs= new HashMap<String, Integer>();
|
||||
List<ICPPUnknownBinding> unknown= new ArrayList<ICPPUnknownBinding>();
|
||||
Reevaluation reeval= new Reevaluation(val.getInternalExpression(),
|
||||
Reevaluation reeval= new Reevaluation(val.getInternalExpression(), packOffset,
|
||||
unknownSigs, unknown,
|
||||
resolvedUnknowns, map);
|
||||
Object obj= reevaluate(reeval, maxdepth);
|
||||
|
@ -672,7 +719,25 @@ public class Value implements IValue {
|
|||
throw UNKNOWN_EX;
|
||||
return evaluateValue(val, reeval.fUnknownSigs, reeval.fUnknowns);
|
||||
}
|
||||
return createTemplateParamExpression(num);
|
||||
return createTemplateParamExpression(num, false);
|
||||
|
||||
case TEMPLATE_PARAM_PACK_CHAR:
|
||||
num= parseHex(buf, idx+1);
|
||||
reeval.nextSeperator();
|
||||
arg= null;
|
||||
if (reeval.fPackOffset >= 0) {
|
||||
ICPPTemplateArgument[] args= reeval.fMap.getPackExpansion(num);
|
||||
if (args != null && reeval.fPackOffset < args.length) {
|
||||
arg= args[reeval.fPackOffset];
|
||||
}
|
||||
}
|
||||
if (arg != null) {
|
||||
IValue val= arg.getNonTypeValue();
|
||||
if (val == null)
|
||||
throw UNKNOWN_EX;
|
||||
return evaluateValue(val, reeval.fUnknownSigs, reeval.fUnknowns);
|
||||
}
|
||||
return createTemplateParamExpression(num, true);
|
||||
|
||||
default:
|
||||
reeval.nextSeperator();
|
||||
|
|
|
@ -29,6 +29,8 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor;
|
|||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPField;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespace;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPParameterPackType;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap;
|
||||
import org.eclipse.cdt.core.index.IIndexFileSet;
|
||||
import org.eclipse.cdt.core.parser.util.ArrayUtil;
|
||||
|
@ -125,10 +127,26 @@ public class AbstractCPPClassSpecializationScope implements ICPPClassSpecializat
|
|||
} else {
|
||||
final ICPPTemplateParameterMap tpmap = specialClass.getTemplateParameterMap();
|
||||
for (ICPPBase base : bases) {
|
||||
ICPPBase specBase = base.clone();
|
||||
IBinding origClass = base.getBaseClass();
|
||||
if (origClass instanceof ICPPTemplateParameter && ((ICPPTemplateParameter) origClass).isParameterPack()) {
|
||||
IType[] specClasses= CPPTemplates.instantiateTypes(new IType[]{new CPPParameterPackType((IType) origClass)}, tpmap, -1, specialClass);
|
||||
if (specClasses.length == 1 && specClasses[0] instanceof ICPPParameterPackType) {
|
||||
result= (ICPPBase[]) ArrayUtil.append(ICPPBase.class, result, base);
|
||||
} else {
|
||||
for (IType specClass : specClasses) {
|
||||
ICPPBase specBase = base.clone();
|
||||
specClass = SemanticUtil.getUltimateType(specClass, false);
|
||||
if (specClass instanceof IBinding && !(specClass instanceof IProblemBinding)) {
|
||||
specBase.setBaseClass((IBinding) specClass);
|
||||
result = (ICPPBase[]) ArrayUtil.append(ICPPBase.class, result, specBase);
|
||||
}
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (origClass instanceof IType) {
|
||||
IType specClass= CPPTemplates.instantiateType((IType) origClass, tpmap, specialClass);
|
||||
ICPPBase specBase = base.clone();
|
||||
IType specClass= CPPTemplates.instantiateType((IType) origClass, tpmap, -1, specialClass);
|
||||
specClass = SemanticUtil.getUltimateType(specClass, false);
|
||||
if (specClass instanceof IBinding && !(specClass instanceof IProblemBinding)) {
|
||||
specBase.setBaseClass((IBinding) specClass);
|
||||
|
|
|
@ -25,8 +25,8 @@ import org.eclipse.cdt.internal.core.dom.parser.ASTAmbiguousNode;
|
|||
import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguityParent;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguousParameterDeclaration;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPTemplates;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil;
|
||||
import org.eclipse.core.runtime.Assert;
|
||||
|
||||
/**
|
||||
|
@ -57,7 +57,7 @@ public class CPPASTAmbiguousParameterDeclaration extends ASTAmbiguousNode implem
|
|||
|
||||
IType t= CPPVisitor.createParameterType(fParameterDecl, true);
|
||||
if (!(t instanceof ICPPParameterPackType) ||
|
||||
!SemanticUtil.containsParameterPack(((ICPPParameterPackType) t).getType())) {
|
||||
!CPPTemplates.containsParameterPack(((ICPPParameterPackType) t).getType())) {
|
||||
final ICPPASTDeclarator dtor = fParameterDecl.getDeclarator();
|
||||
dtor.setDeclaresParameterPack(false);
|
||||
adjustOffsets(dtor);
|
||||
|
|
|
@ -13,10 +13,12 @@ package org.eclipse.cdt.internal.core.dom.parser.cpp;
|
|||
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
||||
import org.eclipse.cdt.core.dom.ast.IProblemBinding;
|
||||
import org.eclipse.cdt.core.dom.ast.IType;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTPackExpansionExpression;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguityParent;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.ProblemBinding;
|
||||
|
||||
/**
|
||||
* Implementation of pack expansion expression.
|
||||
|
@ -51,7 +53,11 @@ public class CPPASTPackExpansionExpression extends ASTNode implements ICPPASTPac
|
|||
}
|
||||
|
||||
public IType getExpressionType() {
|
||||
return new CPPParameterPackType(fPattern.getExpressionType());
|
||||
final IType type = fPattern.getExpressionType();
|
||||
if (type == null)
|
||||
return new ProblemBinding(this, IProblemBinding.SEMANTIC_INVALID_TYPE, getRawSignatureChars());
|
||||
|
||||
return new CPPParameterPackType(type);
|
||||
}
|
||||
|
||||
public boolean isLValue() {
|
||||
|
|
|
@ -91,9 +91,9 @@ public class CPPClassTemplatePartialSpecializationSpecialization extends CPPClas
|
|||
ICPPTemplateArgument[] args = ((ICPPClassTemplatePartialSpecialization) getSpecializedBinding()).getTemplateArguments();
|
||||
final IBinding owner = getOwner();
|
||||
if (owner instanceof ICPPClassSpecialization) {
|
||||
return CPPTemplates.instantiateArguments(args, getTemplateParameterMap(), (ICPPClassSpecialization) owner);
|
||||
return CPPTemplates.instantiateArguments(args, getTemplateParameterMap(), -1, (ICPPClassSpecialization) owner);
|
||||
}
|
||||
return CPPTemplates.instantiateArguments(args, getTemplateParameterMap(), null);
|
||||
return CPPTemplates.instantiateArguments(args, getTemplateParameterMap(), -1, null);
|
||||
}
|
||||
|
||||
public void addPartialSpecialization(ICPPClassTemplatePartialSpecialization spec) {
|
||||
|
|
|
@ -53,6 +53,8 @@ public class CPPClassTemplateSpecialization extends CPPClassSpecialization
|
|||
}
|
||||
|
||||
public ICPPTemplateParameter[] getTemplateParameters() throws DOMException {
|
||||
// mstodo if we specialize the template parameters (because of its default values), it will
|
||||
// be less error prone to use the defaults.
|
||||
ICPPClassTemplate template = (ICPPClassTemplate) getSpecializedBinding();
|
||||
return template.getTemplateParameters();
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDeclarator;
|
|||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionType;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPParameter;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPParameterPackType;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap;
|
||||
import org.eclipse.cdt.core.index.IIndexBinding;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.ASTInternal;
|
||||
|
@ -288,8 +289,24 @@ public class CPPFunctionSpecialization extends CPPSpecialization implements ICPP
|
|||
IType[] types = function.getExceptionSpecification();
|
||||
if (types != null) {
|
||||
IType[] specializedTypeList = new IType[types.length];
|
||||
for (int i=0; i<types.length; ++i)
|
||||
specializedTypeList[i] = specializeType(types[i]);
|
||||
int j=0;
|
||||
for (int i=0; i<types.length; ++i) {
|
||||
final IType origType = types[i];
|
||||
if (origType instanceof ICPPParameterPackType) {
|
||||
IType[] specialized= specializeTypePack((ICPPParameterPackType) origType);
|
||||
if (specialized.length != 1) {
|
||||
IType[] x= new IType[specializedTypeList.length + specialized.length-1];
|
||||
System.arraycopy(specializedTypeList, 0, x, 0, j);
|
||||
specializedTypeList= x;
|
||||
}
|
||||
for (IType iType : specialized) {
|
||||
specializedTypeList[j++] = iType;
|
||||
}
|
||||
} else {
|
||||
specializedTypeList[j++] = specializeType(origType);
|
||||
}
|
||||
}
|
||||
specializedExceptionSpec= specializedTypeList;
|
||||
}
|
||||
}
|
||||
return specializedExceptionSpec;
|
||||
|
|
|
@ -11,12 +11,14 @@
|
|||
package org.eclipse.cdt.internal.core.dom.parser.cpp;
|
||||
|
||||
import org.eclipse.cdt.core.dom.ast.ASTTypeUtil;
|
||||
import org.eclipse.cdt.core.dom.ast.IProblemBinding;
|
||||
import org.eclipse.cdt.core.dom.ast.IType;
|
||||
import org.eclipse.cdt.core.dom.ast.ITypedef;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPParameterPackType;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.ISerializableType;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.ITypeContainer;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.ITypeMarshalBuffer;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.ProblemBinding;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
|
||||
public class CPPParameterPackType implements ICPPParameterPackType, ITypeContainer, ISerializableType {
|
||||
|
@ -72,6 +74,9 @@ public class CPPParameterPackType implements ICPPParameterPackType, ITypeContain
|
|||
|
||||
public static IType unmarshal(int firstByte, ITypeMarshalBuffer buffer) throws CoreException {
|
||||
IType nested= buffer.unmarshalType();
|
||||
if (nested == null)
|
||||
return new ProblemBinding(null, IProblemBinding.SEMANTIC_INVALID_TYPE);
|
||||
|
||||
return new CPPParameterPackType(nested);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassSpecialization;
|
|||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespace;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPParameterPackType;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPSpecialization;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap;
|
||||
import org.eclipse.cdt.core.parser.util.ArrayUtil;
|
||||
|
@ -53,17 +54,25 @@ public abstract class CPPSpecialization extends PlatformObject implements ICPPSp
|
|||
|
||||
public IType specializeType(IType type) {
|
||||
if (owner instanceof ICPPClassSpecialization) {
|
||||
return CPPTemplates.instantiateType(type, getTemplateParameterMap(), (ICPPClassSpecialization) owner);
|
||||
return CPPTemplates.instantiateType(type, getTemplateParameterMap(), -1, (ICPPClassSpecialization) owner);
|
||||
} else {
|
||||
return CPPTemplates.instantiateType(type, getTemplateParameterMap(), null);
|
||||
return CPPTemplates.instantiateType(type, getTemplateParameterMap(), -1, null);
|
||||
}
|
||||
}
|
||||
|
||||
public IType[] specializeTypePack(ICPPParameterPackType type) {
|
||||
if (owner instanceof ICPPClassSpecialization) {
|
||||
return CPPTemplates.instantiateTypes(new IType[]{type}, getTemplateParameterMap(), -1, (ICPPClassSpecialization) owner);
|
||||
} else {
|
||||
return CPPTemplates.instantiateTypes(new IType[]{type}, getTemplateParameterMap(), -1, null);
|
||||
}
|
||||
}
|
||||
|
||||
public IValue specializeValue(IValue value, int maxdepth) {
|
||||
if (owner instanceof ICPPClassSpecialization) {
|
||||
return CPPTemplates.instantiateValue(value, getTemplateParameterMap(), (ICPPClassSpecialization) owner, maxdepth);
|
||||
return CPPTemplates.instantiateValue(value, getTemplateParameterMap(), -1, (ICPPClassSpecialization) owner, maxdepth);
|
||||
} else {
|
||||
return CPPTemplates.instantiateValue(value, getTemplateParameterMap(), null, maxdepth);
|
||||
return CPPTemplates.instantiateValue(value, getTemplateParameterMap(), -1, null, maxdepth);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2008 Wind River Systems, Inc. and others.
|
||||
* Copyright (c) 2008, 2009 Wind River Systems, Inc. and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
|
@ -12,6 +12,7 @@ package org.eclipse.cdt.internal.core.dom.parser.cpp;
|
|||
|
||||
import org.eclipse.cdt.core.dom.ast.IType;
|
||||
import org.eclipse.cdt.core.dom.ast.IValue;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPParameterPackType;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateArgument;
|
||||
import org.eclipse.core.runtime.Assert;
|
||||
|
||||
|
@ -54,6 +55,23 @@ public class CPPTemplateArgument implements ICPPTemplateArgument {
|
|||
return isNonTypeValue() ? fType : null;
|
||||
}
|
||||
|
||||
public boolean isPackExpansion() {
|
||||
return fType instanceof ICPPParameterPackType;
|
||||
}
|
||||
|
||||
public ICPPTemplateArgument getExpansionPattern() {
|
||||
if (fType instanceof ICPPParameterPackType) {
|
||||
IType t= ((ICPPParameterPackType) fType).getType();
|
||||
if (t != null) {
|
||||
if (fValue != null) {
|
||||
return new CPPTemplateArgument(fValue, t);
|
||||
}
|
||||
return new CPPTemplateArgument(t);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean isSameValue(ICPPTemplateArgument arg) {
|
||||
if (fValue != null) {
|
||||
return fValue.equals(arg.getNonTypeValue());
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2008 Wind River Systems, Inc. and others.
|
||||
* Copyright (c) 2008, 2009 Wind River Systems, Inc. and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
|
@ -39,26 +39,40 @@ public class CPPTemplateParameterMap implements ICPPTemplateParameterMap {
|
|||
}
|
||||
|
||||
/**
|
||||
* Adds the mapping to the map.
|
||||
* Adds the mapping.
|
||||
*/
|
||||
public void put(ICPPTemplateParameter param, ICPPTemplateArgument value) {
|
||||
fMap.put(param.getParameterID(), value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the mapping to the map.
|
||||
* Adds the mapping.
|
||||
*/
|
||||
public void put(int parameterID, ICPPTemplateArgument value) {
|
||||
fMap.put(parameterID, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the mapping.
|
||||
*/
|
||||
public void put(ICPPTemplateParameter param, ICPPTemplateArgument[] packExpansion) {
|
||||
fMap.put(param.getParameterID(), packExpansion);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the mapping.
|
||||
*/
|
||||
public void put(int parameterID, ICPPTemplateArgument[] packExpansion) {
|
||||
fMap.put(parameterID, packExpansion);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value for the given parameter.
|
||||
*/
|
||||
public ICPPTemplateArgument getArgument(ICPPTemplateParameter param) {
|
||||
if (param == null)
|
||||
return null;
|
||||
return (ICPPTemplateArgument) fMap.get(param.getParameterID());
|
||||
return getArgument(param.getParameterID());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -66,14 +80,75 @@ public class CPPTemplateParameterMap implements ICPPTemplateParameterMap {
|
|||
* @see ICPPTemplateParameter#getParameterID()
|
||||
*/
|
||||
public ICPPTemplateArgument getArgument(int paramID) {
|
||||
return (ICPPTemplateArgument) fMap.get(paramID);
|
||||
final Object object = fMap.get(paramID);
|
||||
if (object instanceof ICPPTemplateArgument) {
|
||||
return (ICPPTemplateArgument) object;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the values for the given template parameter pack.
|
||||
*/
|
||||
public ICPPTemplateArgument[] getPackExpansion(ICPPTemplateParameter tpar) {
|
||||
return getPackExpansion(tpar.getParameterID());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the values for the template parameter pack with the given id.
|
||||
* @see ICPPTemplateParameter#getParameterID()
|
||||
*/
|
||||
public ICPPTemplateArgument[] getPackExpansion(int paramID) {
|
||||
final Object object = fMap.get(paramID);
|
||||
if (object instanceof ICPPTemplateArgument[]) {
|
||||
return (ICPPTemplateArgument[]) object;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public ICPPTemplateArgument getArgument(ICPPTemplateParameter tpar, int packOffset) {
|
||||
return getArgument(tpar.getParameterID(), packOffset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the argument at the given position
|
||||
*/
|
||||
public ICPPTemplateArgument getArgument(int paramID, int packOffset) {
|
||||
final Object object = fMap.get(paramID);
|
||||
if (object instanceof ICPPTemplateArgument)
|
||||
return (ICPPTemplateArgument) object;
|
||||
if (object instanceof ICPPTemplateArgument[]) {
|
||||
ICPPTemplateArgument[] args = (ICPPTemplateArgument[]) object;
|
||||
if (packOffset < args.length && packOffset >= 0)
|
||||
return args[packOffset];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the argument at the given position
|
||||
*/
|
||||
public boolean putPackElement(Integer paramID, int packOffset, ICPPTemplateArgument arg, int packSize) {
|
||||
ICPPTemplateArgument[] args;
|
||||
final Object object = fMap.get(paramID);
|
||||
if (object instanceof ICPPTemplateArgument[]) {
|
||||
args = (ICPPTemplateArgument[]) object;
|
||||
if (packSize != args.length)
|
||||
return false;
|
||||
} else if (object == null) {
|
||||
args= new ICPPTemplateArgument[packSize];
|
||||
fMap.put(paramID, args);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
args[packOffset]= arg;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts all mappings from the supplied map into this map.
|
||||
*/
|
||||
public void putAll(ICPPTemplateParameterMap map) {
|
||||
|
||||
if (map instanceof CPPTemplateParameterMap) {
|
||||
final ObjectMap omap= ((CPPTemplateParameterMap) map).fMap;
|
||||
for (int i = 0; i < omap.size(); i++) {
|
||||
|
@ -84,12 +159,35 @@ public class CPPTemplateParameterMap implements ICPPTemplateParameterMap {
|
|||
}
|
||||
}
|
||||
|
||||
public ICPPTemplateArgument[] values() {
|
||||
ICPPTemplateArgument[] result= new ICPPTemplateArgument[fMap.size()];
|
||||
for (int i = 0; i < result.length; i++) {
|
||||
result[i]= (ICPPTemplateArgument) fMap.getAt(i);
|
||||
public boolean mergeToExplicit(CPPTemplateParameterMap deducedMap) {
|
||||
Integer[] keys= deducedMap.getAllParameterPositions();
|
||||
for (Integer key : keys) {
|
||||
Object explicit= fMap.get(key);
|
||||
Object deduced= deducedMap.fMap.get(key);
|
||||
if (explicit == null) {
|
||||
if (deduced instanceof ICPPTemplateArgument[]) {
|
||||
for (ICPPTemplateArgument arg : (ICPPTemplateArgument[]) deduced) {
|
||||
if (arg == null)
|
||||
return false;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
fMap.put(key, deduced);
|
||||
} else if (explicit instanceof ICPPTemplateArgument[] && deduced instanceof ICPPTemplateArgument[]) {
|
||||
ICPPTemplateArgument[] explicitPack= (ICPPTemplateArgument[]) explicit;
|
||||
ICPPTemplateArgument[] deducedPack= (ICPPTemplateArgument[]) deduced;
|
||||
if (deducedPack.length < explicitPack.length)
|
||||
return false;
|
||||
System.arraycopy(explicitPack, 0, deducedPack, 0, explicitPack.length);
|
||||
for (ICPPTemplateArgument arg : deducedPack) {
|
||||
if (arg == null)
|
||||
return false;
|
||||
}
|
||||
fMap.put(key, deducedPack);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -111,7 +209,22 @@ public class CPPTemplateParameterMap implements ICPPTemplateParameterMap {
|
|||
if (sb.length() > 1) {
|
||||
sb.append(", "); //$NON-NLS-1$
|
||||
}
|
||||
ICPPTemplateArgument value = (ICPPTemplateArgument) fMap.getAt(i);
|
||||
|
||||
final Object obj = fMap.getAt(i);
|
||||
if (obj instanceof ICPPTemplateArgument) {
|
||||
appendArg(sb, key, (ICPPTemplateArgument) obj);
|
||||
} else if (obj instanceof ICPPTemplateArgument[]) {
|
||||
for (ICPPTemplateArgument arg : (ICPPTemplateArgument[]) obj) {
|
||||
appendArg(sb, key, arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
sb.append("}"); //$NON-NLS-1$
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private void appendArg(StringBuilder sb, Integer key, ICPPTemplateArgument value) {
|
||||
sb.append('#');
|
||||
sb.append(key >> 16);
|
||||
sb.append(',');
|
||||
|
@ -119,8 +232,4 @@ public class CPPTemplateParameterMap implements ICPPTemplateParameterMap {
|
|||
sb.append(": "); //$NON-NLS-1$
|
||||
sb.append(ASTTypeUtil.getArgumentString(value, true));
|
||||
}
|
||||
}
|
||||
sb.append("}"); //$NON-NLS-1$
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1588,7 +1588,7 @@ public class CPPVisitor extends ASTQueries {
|
|||
pt = createType(pt, pDtor);
|
||||
pt= adjustParameterType(pt, forFuncType);
|
||||
|
||||
if (CPPVisitor.findInnermostDeclarator(pDtor).declaresParameterPack()) {
|
||||
if (pt != null && CPPVisitor.findInnermostDeclarator(pDtor).declaresParameterPack()) {
|
||||
pt= new CPPParameterPackType(pt);
|
||||
}
|
||||
return pt;
|
||||
|
@ -1714,7 +1714,7 @@ public class CPPVisitor extends ASTQueries {
|
|||
}
|
||||
}
|
||||
}
|
||||
if (isPackExpansion) {
|
||||
if (type != null && isPackExpansion) {
|
||||
type= new CPPParameterPackType(type);
|
||||
}
|
||||
return type;
|
||||
|
|
|
@ -34,11 +34,9 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
|
|||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionType;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespace;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPParameterPackType;
|
||||
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.ICPPTemplateArgument;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter;
|
||||
import org.eclipse.cdt.core.index.IIndexBinding;
|
||||
import org.eclipse.cdt.core.parser.Keywords;
|
||||
import org.eclipse.cdt.core.parser.util.ArrayUtil;
|
||||
|
@ -53,7 +51,6 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPPointerType;
|
|||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPQualifierType;
|
||||
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.ICPPUnknownBinding;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.OverloadableOperator;
|
||||
|
||||
/**
|
||||
|
@ -377,50 +374,6 @@ public class SemanticUtil {
|
|||
return type;
|
||||
}
|
||||
|
||||
public static boolean containsParameterPack(IType type) {
|
||||
while (true) {
|
||||
if (type instanceof ICPPTemplateParameter) {
|
||||
return ((ICPPTemplateParameter) type).isParameterPack();
|
||||
} else if (type instanceof ICPPDeferredClassInstance) {
|
||||
// mstodo check the deferred arguments.
|
||||
return false;
|
||||
} else if (type instanceof ICPPUnknownBinding) {
|
||||
try {
|
||||
IBinding owner= ((ICPPUnknownBinding) type).getOwner();
|
||||
if (owner instanceof IType) {
|
||||
type= (IType) owner;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} catch (DOMException e) {
|
||||
return false;
|
||||
}
|
||||
} else if (type instanceof IFunctionType) {
|
||||
final ICPPFunctionType ft = (ICPPFunctionType) type;
|
||||
final IType r = ft.getReturnType();
|
||||
if (containsParameterPack(r))
|
||||
return true;
|
||||
final IType[] ps = ft.getParameterTypes();
|
||||
for (IType p : ps) {
|
||||
if (containsParameterPack(p))
|
||||
return true;
|
||||
}
|
||||
|
||||
} else if (type instanceof ICPPParameterPackType) {
|
||||
// A pack expansion expands all packs.
|
||||
return false;
|
||||
} else if (type instanceof IArrayType) {
|
||||
final IArrayType atype= (IArrayType) type;
|
||||
// mstodo check array size
|
||||
type= atype.getType();
|
||||
} else if (type instanceof ITypeContainer) {
|
||||
type= ((ITypeContainer) type).getType();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static IType mapToAST(IType type, IASTNode node) {
|
||||
if (type instanceof IFunctionType) {
|
||||
final ICPPFunctionType ft = (ICPPFunctionType) type;
|
||||
|
|
|
@ -0,0 +1,629 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2009 Wind River Systems, Inc. and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* Markus Schorn - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics;
|
||||
|
||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.BitSet;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.eclipse.cdt.core.dom.ast.DOMException;
|
||||
import org.eclipse.cdt.core.dom.ast.IArrayType;
|
||||
import org.eclipse.cdt.core.dom.ast.IBasicType;
|
||||
import org.eclipse.cdt.core.dom.ast.IBinding;
|
||||
import org.eclipse.cdt.core.dom.ast.IFunctionType;
|
||||
import org.eclipse.cdt.core.dom.ast.IPointerType;
|
||||
import org.eclipse.cdt.core.dom.ast.IQualifierType;
|
||||
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.ICPPBase;
|
||||
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.ICPPFunctionTemplate;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPParameterPackType;
|
||||
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.ICPPTemplateArgument;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateDefinition;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateInstance;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.Value;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPBasicType;
|
||||
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.CPPTemplateParameterMap;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownBinding;
|
||||
|
||||
/**
|
||||
* Algorithms for deducing template arguments in various contexts.
|
||||
*/
|
||||
public class TemplateArgumentDeduction {
|
||||
/**
|
||||
* Deduce arguments for a template function from the template id + the template function parameters.
|
||||
* 14.8.2.1
|
||||
*/
|
||||
static ICPPTemplateArgument[] deduceForFunctionCall(ICPPFunctionTemplate template,
|
||||
ICPPTemplateArgument[] tmplArgs, IType[] fnArgs, BitSet argIsLValue, CPPTemplateParameterMap map)
|
||||
throws DOMException {
|
||||
final ICPPTemplateParameter[] tmplParams = template.getTemplateParameters();
|
||||
final int numTmplParams = tmplParams.length;
|
||||
final int numTmplArgs = tmplArgs.length;
|
||||
|
||||
tmplArgs= SemanticUtil.getSimplifiedArguments(tmplArgs);
|
||||
ICPPTemplateParameter tmplParam= null;
|
||||
int packOffset= -1;
|
||||
for (int i = 0; i < numTmplArgs; i++) {
|
||||
if (packOffset < 0 || tmplParam == null) {
|
||||
if (i >= numTmplParams)
|
||||
return null;
|
||||
|
||||
tmplParam= tmplParams[i];
|
||||
if (tmplParam.isParameterPack()) {
|
||||
packOffset= i;
|
||||
}
|
||||
}
|
||||
ICPPTemplateArgument tmplArg= tmplArgs[i];
|
||||
tmplArg= CPPTemplates.matchTemplateParameterAndArgument(tmplParam, tmplArg, map);
|
||||
if (tmplArg == null)
|
||||
return null;
|
||||
|
||||
if (packOffset < 0) {
|
||||
map.put(tmplParam, tmplArg);
|
||||
}
|
||||
}
|
||||
|
||||
if (packOffset >= 0) {
|
||||
final int packSize= tmplArgs.length- packOffset;
|
||||
ICPPTemplateArgument[] pack= new ICPPTemplateArgument[packSize];
|
||||
System.arraycopy(tmplArgs, packOffset, pack, 0, packSize);
|
||||
map.put(tmplParam, pack);
|
||||
}
|
||||
|
||||
if (!deduceFromFunctionArgs(template, fnArgs, argIsLValue, map, false))
|
||||
return null;
|
||||
|
||||
List<ICPPTemplateArgument> result= new ArrayList<ICPPTemplateArgument>(numTmplParams);
|
||||
for (ICPPTemplateParameter tpar : tmplParams) {
|
||||
if (tpar.isParameterPack()) {
|
||||
ICPPTemplateArgument[] deducedArgs= map.getPackExpansion(tpar);
|
||||
if (deducedArgs == null)
|
||||
return null;
|
||||
result.addAll(Arrays.asList(deducedArgs));
|
||||
} else {
|
||||
ICPPTemplateArgument deducedArg= map.getArgument(tpar);
|
||||
if (deducedArg == null)
|
||||
return null;
|
||||
|
||||
result.add(deducedArg);
|
||||
}
|
||||
}
|
||||
return result.toArray(new ICPPTemplateArgument[result.size()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deduce arguments for a user defined conversion template
|
||||
* 14.8.2.3
|
||||
*/
|
||||
static ICPPTemplateArgument[] deduceForConversion(ICPPFunctionTemplate template,
|
||||
IType conversionType, CPPTemplateParameterMap map) throws DOMException {
|
||||
final ICPPTemplateParameter[] tmplParams = template.getTemplateParameters();
|
||||
final int length = tmplParams.length;
|
||||
|
||||
ICPPTemplateArgument[] result = new ICPPTemplateArgument[length];
|
||||
IType a= SemanticUtil.getSimplifiedType(conversionType);
|
||||
IType p= template.getType().getReturnType();
|
||||
p= getArgumentTypeForDeduction(p, a instanceof ICPPReferenceType);
|
||||
a= SemanticUtil.getNestedType(a, SemanticUtil.REF | SemanticUtil.TDEF);
|
||||
TemplateArgumentDeduction deduct= new TemplateArgumentDeduction(tmplParams, null, map, 0);
|
||||
if (!deduct.fromType(p, a)) {
|
||||
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]= deducedArg;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deduces the mapping for the template parameters from the function parameters,
|
||||
* returns <code>false</code> if there is no mapping.
|
||||
*/
|
||||
static boolean deduceFromFunctionArgs(ICPPFunctionTemplate template, IType[] fnArgs, BitSet argIsLValue,
|
||||
CPPTemplateParameterMap map, boolean checkExactMatch) {
|
||||
try {
|
||||
IType[] fnPars = template.getType().getParameterTypes();
|
||||
final int fnParCount = fnPars.length;
|
||||
if (fnParCount == 0)
|
||||
return true;
|
||||
|
||||
final ICPPTemplateParameter[] tmplPars = template.getTemplateParameters();
|
||||
TemplateArgumentDeduction deduct= new TemplateArgumentDeduction(tmplPars, map, new CPPTemplateParameterMap(fnParCount), 0);
|
||||
IType fnParPack= null;
|
||||
for (int j= 0; j < fnArgs.length; j++) {
|
||||
IType par;
|
||||
if (fnParPack != null) {
|
||||
par= fnParPack;
|
||||
deduct.incPackOffset();
|
||||
} else if (j < fnParCount) {
|
||||
par= fnPars[j];
|
||||
if (par instanceof ICPPParameterPackType) {
|
||||
// must be the last parameter.
|
||||
if (j != fnParCount-1)
|
||||
return false;
|
||||
|
||||
par= fnParPack= ((ICPPParameterPackType) par).getType();
|
||||
deduct= new TemplateArgumentDeduction(deduct, fnArgs.length-j);
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
||||
par= CPPTemplates.instantiateType(par, map, -1, null);
|
||||
if (!CPPTemplates.isValidType(par))
|
||||
return false;
|
||||
|
||||
boolean isDependentPar= CPPTemplates.isDependentType(par);
|
||||
if (checkExactMatch || isDependentPar) {
|
||||
boolean isReferenceTypeParameter= false;
|
||||
IType arg = fnArgs[j];
|
||||
par= SemanticUtil.getNestedType(par, SemanticUtil.TDEF); // adjustParameterType preserves typedefs
|
||||
// 14.8.2.1-2
|
||||
if (par instanceof ICPPReferenceType) {
|
||||
// If P is an rvalue reference to a cv-unqualified template parameter and the argument is an
|
||||
// lvalue, the type A& “lvalue reference to A” is used in place of A for type deduction.
|
||||
isReferenceTypeParameter= true;
|
||||
final ICPPReferenceType refPar = (ICPPReferenceType) par;
|
||||
if (refPar.isRValueReference() && refPar.getType() instanceof ICPPTemplateParameter && argIsLValue.get(j)) {
|
||||
arg= new CPPReferenceType(getSimplifiedType(arg), false);
|
||||
} else {
|
||||
arg= getArgumentTypeForDeduction(arg, true);
|
||||
}
|
||||
par= SemanticUtil.getNestedType(par, SemanticUtil.REF | SemanticUtil.TDEF);
|
||||
} else {
|
||||
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;
|
||||
} 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
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)) {
|
||||
return false;
|
||||
}
|
||||
if (checkExactMatch) {
|
||||
IType instantiated= CPPTemplates.instantiateType(par, deduct.fDeducedArgs, deduct.fPackOffset, null);
|
||||
if (!instantiated.isSameType(arg))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!deduct.fExplicitArgs.mergeToExplicit(deduct.fDeducedArgs))
|
||||
return false;
|
||||
|
||||
return verifyDeduction(tmplPars, map, true);
|
||||
} catch (DOMException e) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
final ICPPTemplateInstance inst = (ICPPTemplateInstance) a;
|
||||
ICPPClassTemplate tmpl= getPrimaryTemplate(inst);
|
||||
if (pTemplate.isSameType(tmpl))
|
||||
return a;
|
||||
}
|
||||
if (maxdepth-- > 0) {
|
||||
for (ICPPBase cppBase : a.getBases()) {
|
||||
IBinding base= cppBase.getBaseClass();
|
||||
if (base instanceof ICPPClassType) {
|
||||
final ICPPClassType inst= findBaseInstance((ICPPClassType) base, pTemplate, maxdepth);
|
||||
if (inst != null)
|
||||
return inst;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
private static ICPPClassTemplate getPrimaryTemplate(ICPPTemplateInstance inst) throws DOMException {
|
||||
ICPPTemplateDefinition template= inst.getTemplateDefinition();
|
||||
if (template instanceof ICPPClassTemplatePartialSpecialization) {
|
||||
return ((ICPPClassTemplatePartialSpecialization) template).getPrimaryClassTemplate();
|
||||
} else if (template instanceof ICPPClassTemplate) {
|
||||
return (ICPPClassTemplate) template;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 14.8.2.1-2
|
||||
* if P is not a reference type
|
||||
* - If A is an array type, the pointer type produced by the array-to-pointer conversion is used instead
|
||||
* - If A is a function type, the pointer type produced by the function-to-pointer conversion is used instead
|
||||
* - If A is a cv-qualified type, the top level cv-qualifiers are ignored for type deduction
|
||||
*
|
||||
* Also 14.8.2.3-2 where the same logics is used in reverse.
|
||||
*/
|
||||
private static IType getArgumentTypeForDeduction(IType type, boolean parameterIsAReferenceType) {
|
||||
type = SemanticUtil.getSimplifiedType(type);
|
||||
if (type instanceof ICPPReferenceType) {
|
||||
type = ((ICPPReferenceType) type).getType();
|
||||
}
|
||||
IType result = type;
|
||||
if (!parameterIsAReferenceType) {
|
||||
if (type instanceof IArrayType) {
|
||||
result = new CPPPointerType(((IArrayType) type).getType());
|
||||
} else if (type instanceof IFunctionType) {
|
||||
result = new CPPPointerType(type);
|
||||
} else {
|
||||
result = SemanticUtil.getNestedType(type, TDEF | ALLCVQ );
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Deduces the template parameter mapping from pairs of template arguments.
|
||||
*/
|
||||
public static boolean fromTemplateArguments(final ICPPTemplateParameter[] pars, final ICPPTemplateArgument[] p, final ICPPTemplateArgument[] a, CPPTemplateParameterMap map) throws DOMException {
|
||||
TemplateArgumentDeduction deduct= new TemplateArgumentDeduction(pars, null, map, 0);
|
||||
final int len= a.length;
|
||||
if (p == null || p.length != len) {
|
||||
return false;
|
||||
}
|
||||
for (int j=0; j<len; j++) {
|
||||
if (!deduct.fromTemplateArgument(p[j], a[j])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return verifyDeduction(pars, map, false);
|
||||
}
|
||||
|
||||
|
||||
private static boolean verifyDeduction(ICPPTemplateParameter[] pars, CPPTemplateParameterMap tpMap, boolean useDefaults) {
|
||||
for (ICPPTemplateParameter tpar : pars) {
|
||||
if (tpar.isParameterPack()) {
|
||||
ICPPTemplateArgument[] deducedArgs= tpMap.getPackExpansion(tpar);
|
||||
if (deducedArgs == null) {
|
||||
tpMap.put(tpar, ICPPTemplateArgument.EMPTY_ARGUMENTS);
|
||||
} else {
|
||||
for (ICPPTemplateArgument arg : deducedArgs) {
|
||||
if (arg == null)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ICPPTemplateArgument deducedArg= tpMap.getArgument(tpar);
|
||||
if (deducedArg == null && useDefaults) {
|
||||
deducedArg= tpar.getDefaultValue();
|
||||
if (deducedArg != null) {
|
||||
deducedArg= CPPTemplates.instantiateArgument(deducedArg, tpMap, -1, null);
|
||||
}
|
||||
}
|
||||
if (deducedArg == null)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
private CPPTemplateParameterMap fExplicitArgs;
|
||||
private CPPTemplateParameterMap fDeducedArgs;
|
||||
private Set<Integer> fTemplateParameterPacks;
|
||||
private int fPackOffset;
|
||||
private final int fPackSize;
|
||||
|
||||
private TemplateArgumentDeduction(ICPPTemplateParameter[] tpars, CPPTemplateParameterMap explicit, CPPTemplateParameterMap result, int packSize) {
|
||||
fExplicitArgs= explicit;
|
||||
fDeducedArgs= result;
|
||||
fPackSize= packSize;
|
||||
fPackOffset= packSize > 0 ? 0 : -1;
|
||||
for (ICPPTemplateParameter tpar : tpars) {
|
||||
if (tpar.isParameterPack()) {
|
||||
if (fTemplateParameterPacks == null) {
|
||||
fTemplateParameterPacks= new HashSet<Integer>();
|
||||
}
|
||||
fTemplateParameterPacks.add(tpar.getParameterID());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private TemplateArgumentDeduction(TemplateArgumentDeduction base, int packSize) {
|
||||
fExplicitArgs= base.fExplicitArgs;
|
||||
fDeducedArgs= base.fDeducedArgs;
|
||||
fTemplateParameterPacks= base.fTemplateParameterPacks;
|
||||
fPackSize= packSize;
|
||||
fPackOffset= packSize > 0 ? 0 : -1;
|
||||
}
|
||||
|
||||
|
||||
private void incPackOffset() {
|
||||
fPackOffset++;
|
||||
assert fPackOffset < fPackSize;
|
||||
}
|
||||
/**
|
||||
* Deduces the template parameter mapping from one pair of template arguments.
|
||||
*/
|
||||
private boolean fromTemplateArgument(ICPPTemplateArgument p, ICPPTemplateArgument a) throws DOMException {
|
||||
if (p.isNonTypeValue() != a.isNonTypeValue())
|
||||
return false;
|
||||
|
||||
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);
|
||||
}
|
||||
return old.isSameValue(a);
|
||||
}
|
||||
|
||||
IValue sval= a.getNonTypeValue();
|
||||
return tval.equals(sval);
|
||||
}
|
||||
|
||||
return fromType(p.getTypeValue(), a.getTypeValue());
|
||||
}
|
||||
|
||||
|
||||
private boolean fromType(IType p, IType a) throws DOMException {
|
||||
while (p != null) {
|
||||
while (a instanceof ITypedef)
|
||||
a = ((ITypedef) a).getType();
|
||||
if (p instanceof IBasicType) {
|
||||
return p.isSameType(a);
|
||||
} else if (p instanceof ICPPPointerToMemberType) {
|
||||
if (!(a instanceof ICPPPointerToMemberType))
|
||||
return false;
|
||||
if (!fromType(((ICPPPointerToMemberType) p).getMemberOfClass(),
|
||||
((ICPPPointerToMemberType) a).getMemberOfClass())) {
|
||||
return false;
|
||||
}
|
||||
p = ((ICPPPointerToMemberType) p).getType();
|
||||
a = ((ICPPPointerToMemberType) a).getType();
|
||||
} else if (p instanceof IPointerType) {
|
||||
if (!(a instanceof IPointerType)) {
|
||||
return false;
|
||||
}
|
||||
p = ((IPointerType) p).getType();
|
||||
a = ((IPointerType) a).getType();
|
||||
} else if (p instanceof ICPPReferenceType) {
|
||||
if (!(a instanceof ICPPReferenceType)) {
|
||||
return false;
|
||||
}
|
||||
p = ((ICPPReferenceType) p).getType();
|
||||
a = ((ICPPReferenceType) a).getType();
|
||||
} else if (p instanceof IArrayType) {
|
||||
if (!(a instanceof IArrayType)) {
|
||||
return false;
|
||||
}
|
||||
IArrayType aa= (IArrayType) a;
|
||||
IArrayType pa= (IArrayType) p;
|
||||
IValue as= aa.getSize();
|
||||
IValue ps= pa.getSize();
|
||||
if (as != ps) {
|
||||
if (as == null || ps == null)
|
||||
return false;
|
||||
|
||||
int parID= Value.isTemplateParameter(ps);
|
||||
if (parID >= 0) {
|
||||
ICPPTemplateArgument old= fDeducedArgs.getArgument(parID, fPackOffset);
|
||||
if (old == null) {
|
||||
if (!deduce(parID, new CPPTemplateArgument(as, new CPPBasicType(ICPPBasicType.Kind.eInt, 0)))) {
|
||||
return false;
|
||||
}
|
||||
} else if (!as.equals(old.getNonTypeValue())) {
|
||||
return false;
|
||||
}
|
||||
} else if (!as.equals(as)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
p = pa.getType();
|
||||
a = aa.getType();
|
||||
} else if (p instanceof IQualifierType) {
|
||||
IType uqp = SemanticUtil.getNestedType(p, ALLCVQ);
|
||||
IType uqa = SemanticUtil.getNestedType(a, ALLCVQ);
|
||||
if (uqp instanceof ICPPTemplateParameter) {
|
||||
CVQualifier remaining= SemanticUtil.getCVQualifier(a).remove(SemanticUtil.getCVQualifier(p));
|
||||
if (remaining != CVQualifier._) {
|
||||
uqa= SemanticUtil.addQualifiers(uqa, remaining.isConst(), remaining.isVolatile());
|
||||
}
|
||||
}
|
||||
a= uqa;
|
||||
p= uqp;
|
||||
} else if (p instanceof IFunctionType) {
|
||||
if (!(a instanceof IFunctionType))
|
||||
return false;
|
||||
return fromFunctionType((IFunctionType) p, (IFunctionType) a);
|
||||
} else if (p instanceof ICPPTemplateParameter) {
|
||||
ICPPTemplateArgument current= fDeducedArgs.getArgument(((ICPPTemplateParameter) p).getParameterID(), fPackOffset);
|
||||
if (current != null) {
|
||||
if (current.isNonTypeValue())
|
||||
return false;
|
||||
return current.getTypeValue().isSameType(a);
|
||||
}
|
||||
if (a == null)
|
||||
return false;
|
||||
return deduce(((ICPPTemplateParameter)p).getParameterID(), new CPPTemplateArgument(a));
|
||||
} else if (p instanceof ICPPTemplateInstance) {
|
||||
if (!(a instanceof ICPPTemplateInstance))
|
||||
return false;
|
||||
return fromTemplateInstance((ICPPTemplateInstance) p, (ICPPTemplateInstance) a);
|
||||
} else if (p instanceof ICPPUnknownBinding) {
|
||||
return true; // An unknown type may match anything.
|
||||
} else {
|
||||
return p.isSameType(a);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean fromTemplateInstance(ICPPTemplateInstance pInst, ICPPTemplateInstance aInst)
|
||||
throws DOMException {
|
||||
ICPPClassTemplate pTemplate= getPrimaryTemplate(pInst);
|
||||
ICPPClassTemplate aTemplate= getPrimaryTemplate(aInst);
|
||||
if (pTemplate == null || aTemplate == null || !aTemplate.isSameType(pTemplate))
|
||||
return false;
|
||||
|
||||
// Check for being a non-deduced context.
|
||||
final ICPPTemplateArgument[] pArgs = pInst.getTemplateArguments();
|
||||
for (int i = 0; i < pArgs.length-1; i++) {
|
||||
if (pArgs[i].isPackExpansion())
|
||||
return true; // non-deduced context
|
||||
}
|
||||
|
||||
final ICPPTemplateArgument[] aArgs = aInst.getTemplateArguments();
|
||||
if (pArgs.length != aArgs.length) {
|
||||
if (pArgs.length == 0 || pArgs.length > aArgs.length+1)
|
||||
return false;
|
||||
ICPPTemplateArgument lastPParam= pArgs[pArgs.length-1];
|
||||
if (!lastPParam.isPackExpansion())
|
||||
return false;
|
||||
}
|
||||
|
||||
ICPPTemplateArgument expansionPattern= null;
|
||||
TemplateArgumentDeduction deduct= this;
|
||||
for (int i = 0; i < aArgs.length; i++) {
|
||||
ICPPTemplateArgument p;
|
||||
if (expansionPattern != null) {
|
||||
p= expansionPattern;
|
||||
deduct.incPackOffset();
|
||||
p= CPPTemplates.instantiateArgument(p, fExplicitArgs, deduct.fPackOffset, null);
|
||||
if (!CPPTemplates.isValidArgument(p))
|
||||
return false;
|
||||
} else {
|
||||
p= pArgs[i];
|
||||
if (p.isPackExpansion()) {
|
||||
p= expansionPattern= p.getExpansionPattern();
|
||||
deduct= new TemplateArgumentDeduction(this, aArgs.length-i);
|
||||
p= CPPTemplates.instantiateArgument(p, fExplicitArgs, deduct.fPackOffset, null);
|
||||
if (!CPPTemplates.isValidArgument(p))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (!deduct.fromTemplateArgument(p, aArgs[i]))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean fromFunctionType(IFunctionType ftp, IFunctionType fta) throws DOMException {
|
||||
if (!fromType(ftp.getReturnType(), fta.getReturnType()))
|
||||
return false;
|
||||
|
||||
IType[] pParams = ftp.getParameterTypes();
|
||||
IType[] aParams = fta.getParameterTypes();
|
||||
if (pParams.length != aParams.length) {
|
||||
if (pParams.length == 0 || pParams.length > aParams.length+1)
|
||||
return false;
|
||||
IType lastPParam= pParams[pParams.length-1];
|
||||
if (!(lastPParam instanceof ICPPParameterPackType))
|
||||
return false;
|
||||
}
|
||||
IType parameterPack= null;
|
||||
TemplateArgumentDeduction deduct= this;
|
||||
for (int i = 0; i < aParams.length; i++) {
|
||||
IType p;
|
||||
if (parameterPack != null) {
|
||||
p= parameterPack;
|
||||
deduct.incPackOffset();
|
||||
p= CPPTemplates.instantiateType(p, fExplicitArgs, deduct.fPackOffset, null);
|
||||
if (!CPPTemplates.isValidType(p))
|
||||
return false;
|
||||
} else {
|
||||
p= pParams[i];
|
||||
if (p instanceof ICPPParameterPackType) {
|
||||
p= parameterPack= ((ICPPParameterPackType) p).getType();
|
||||
deduct= new TemplateArgumentDeduction(this, aParams.length-i);
|
||||
p= CPPTemplates.instantiateType(p, fExplicitArgs, deduct.fPackOffset, null);
|
||||
if (!CPPTemplates.isValidType(p))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (!deduct.fromType(p, aParams[i]))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean deduce(int parID, ICPPTemplateArgument arg) {
|
||||
if (fTemplateParameterPacks != null && fTemplateParameterPacks.contains(parID)) {
|
||||
if (fPackSize == 0)
|
||||
return false;
|
||||
return fDeducedArgs.putPackElement(parID, fPackOffset, arg, fPackSize);
|
||||
}
|
||||
fDeducedArgs.put(parID, arg);
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -38,8 +38,8 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
|
|||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespace;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespaceAlias;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespaceScope;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPParameterPackType;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPParameter;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPParameterPackType;
|
||||
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;
|
||||
|
@ -171,7 +171,7 @@ public class CPPCompositesFactory extends AbstractCompositeFactory {
|
|||
ICPPParameterPackType rt= (ICPPParameterPackType) rtype;
|
||||
IType r= rt.getType();
|
||||
IType r2= getCompositeType(r);
|
||||
if (r != r2) {
|
||||
if (r != r2 && r2 != null) {
|
||||
return new CPPParameterPackType(r2);
|
||||
}
|
||||
return rt;
|
||||
|
|
|
@ -43,7 +43,12 @@ public class TemplateInstanceUtil {
|
|||
try {
|
||||
for (Integer key : keys) {
|
||||
ICPPTemplateArgument arg= preresult.getArgument(key);
|
||||
if (arg != null) {
|
||||
result.put(key, convert(cf, arg));
|
||||
} else {
|
||||
ICPPTemplateArgument[] pack= preresult.getPackExpansion(key);
|
||||
result.put(key, convert(cf, pack));
|
||||
}
|
||||
}
|
||||
} catch(DOMException de) {
|
||||
CCorePlugin.log(de);
|
||||
|
|
|
@ -188,10 +188,11 @@ public class PDOM extends PlatformObject implements IPDOM {
|
|||
* 93.0 - further simplification of basic types, bug 231859.
|
||||
* 94.0 - new model for storing types, bug 294306.
|
||||
* 95.0 - parameter packs, bug 294730.
|
||||
* 96.0 - storing pack expansions in the template parameter map, bug 294730.
|
||||
*/
|
||||
private static final int MIN_SUPPORTED_VERSION= version(95, 0);
|
||||
private static final int MAX_SUPPORTED_VERSION= version(95, Short.MAX_VALUE);
|
||||
private static final int DEFAULT_VERSION = version(95, 0);
|
||||
private static final int MIN_SUPPORTED_VERSION= version(96, 0);
|
||||
private static final int MAX_SUPPORTED_VERSION= version(96, Short.MAX_VALUE);
|
||||
private static final int DEFAULT_VERSION = version(96, 0);
|
||||
|
||||
private static int version(int major, int minor) {
|
||||
return (major << 16) + minor;
|
||||
|
|
|
@ -36,6 +36,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
|
|||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPField;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter;
|
||||
import org.eclipse.cdt.core.index.IIndexBinding;
|
||||
import org.eclipse.cdt.core.parser.IToken;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
|
@ -485,25 +486,25 @@ public class PDOMASTAdapter {
|
|||
char[] name= binding.getNameCharArray();
|
||||
if (name.length == 0) {
|
||||
if (binding instanceof IEnumeration) {
|
||||
name= ASTTypeUtil.createNameForAnonymous(binding);
|
||||
name = ASTTypeUtil.createNameForAnonymous(binding);
|
||||
if (name != null) {
|
||||
if (binding instanceof ICPPBinding) {
|
||||
return new AnonymousCPPEnumeration(name, (IEnumeration) binding);
|
||||
}
|
||||
return new AnonymousEnumeration(name, (IEnumeration) binding);
|
||||
}
|
||||
}
|
||||
else if (binding instanceof ICPPClassType) {
|
||||
name= ASTTypeUtil.createNameForAnonymous(binding);
|
||||
} else if (binding instanceof ICPPClassType) {
|
||||
name = ASTTypeUtil.createNameForAnonymous(binding);
|
||||
if (name != null) {
|
||||
return new AnonymousClassType(name, (ICPPClassType) binding);
|
||||
}
|
||||
}
|
||||
else if (binding instanceof ICompositeType) {
|
||||
name= ASTTypeUtil.createNameForAnonymous(binding);
|
||||
} else if (binding instanceof ICompositeType) {
|
||||
name = ASTTypeUtil.createNameForAnonymous(binding);
|
||||
if (name != null) {
|
||||
return new AnonymousCompositeType(name, (ICompositeType) binding);
|
||||
}
|
||||
} else if (binding instanceof ICPPTemplateParameter) {
|
||||
return binding;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -22,15 +22,13 @@ import org.eclipse.cdt.internal.core.pdom.db.Database;
|
|||
import org.eclipse.cdt.internal.core.pdom.dom.PDOMLinkage;
|
||||
import org.eclipse.cdt.internal.core.pdom.dom.PDOMNode;
|
||||
import org.eclipse.cdt.internal.core.pdom.dom.PDOMValue;
|
||||
import org.eclipse.core.runtime.Assert;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
|
||||
/**
|
||||
* Collects methods to store an argument list in the database
|
||||
*/
|
||||
public class PDOMCPPTemplateParameterMap {
|
||||
private static final int PARAMPOS_OFFSET= 0;
|
||||
private static final int TYPE_OFFSET= PARAMPOS_OFFSET + 4;
|
||||
private static final int TYPE_OFFSET= 0;
|
||||
private static final int VALUE_OFFSET= TYPE_OFFSET + Database.TYPE_SIZE;
|
||||
private static final int NODE_SIZE = VALUE_OFFSET + Database.PTR_SIZE;
|
||||
|
||||
|
@ -42,43 +40,74 @@ public class PDOMCPPTemplateParameterMap {
|
|||
final PDOMLinkage linkage= parent.getLinkage();
|
||||
final Database db= linkage.getDB();
|
||||
Integer[] keys= map.getAllParameterPositions();
|
||||
final short len= (short) Math.min(keys.length, (Database.MAX_MALLOC_SIZE-2)/NODE_SIZE);
|
||||
final long block= db.malloc(2+NODE_SIZE*len);
|
||||
int keyLen= 0;
|
||||
int dataSize= 2;
|
||||
for (Integer key : keys) {
|
||||
int delta= 2+4+NODE_SIZE;
|
||||
ICPPTemplateArgument[] packExpansion= map.getPackExpansion(key);
|
||||
if (packExpansion != null) {
|
||||
delta+= (packExpansion.length-1) * NODE_SIZE;
|
||||
}
|
||||
if (dataSize+delta > Database.MAX_MALLOC_SIZE)
|
||||
break;
|
||||
dataSize += delta;
|
||||
keyLen++;
|
||||
}
|
||||
final long block= db.malloc(dataSize);
|
||||
long p= block;
|
||||
db.putShort(p, (short)keyLen); p+=2;
|
||||
for (final Integer paramId : keys) {
|
||||
if (--keyLen < 0)
|
||||
break;
|
||||
db.putInt(p, paramId); p+=4;
|
||||
final ICPPTemplateArgument arg = map.getArgument(paramId);
|
||||
if (arg != null) {
|
||||
db.putShort(p, (short) -1); p+=2;
|
||||
storeArgument(db, linkage, p, arg); p+= NODE_SIZE;
|
||||
} else {
|
||||
final ICPPTemplateArgument[] args = map.getPackExpansion(paramId);
|
||||
db.putShort(p, (short) args.length); p+=2;
|
||||
for (ICPPTemplateArgument a : args) {
|
||||
storeArgument(db, linkage, p, a); p+= NODE_SIZE;
|
||||
}
|
||||
}
|
||||
}
|
||||
assert p == block+dataSize;
|
||||
return block;
|
||||
}
|
||||
|
||||
db.putShort(p, len); p+=2;
|
||||
for (int i=0; i<len; i++) {
|
||||
final Integer paramPos = keys[i];
|
||||
db.putInt(p + PARAMPOS_OFFSET, paramPos);
|
||||
final ICPPTemplateArgument arg = map.getArgument(paramPos);
|
||||
private static void storeArgument(final Database db, final PDOMLinkage linkage, long p,
|
||||
final ICPPTemplateArgument arg) throws CoreException {
|
||||
if (arg.isNonTypeValue()) {
|
||||
linkage.storeType(p + TYPE_OFFSET, arg.getTypeOfNonTypeValue());
|
||||
db.putRecPtr(p+VALUE_OFFSET, PDOMValue.store(db, linkage, arg.getNonTypeValue()));
|
||||
} else {
|
||||
linkage.storeType(p + TYPE_OFFSET, arg.getTypeValue());
|
||||
}
|
||||
p+=NODE_SIZE;
|
||||
}
|
||||
return block;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Clears the map in the database.
|
||||
*/
|
||||
public static void clearMap(PDOMNode parent, int rec) throws CoreException {
|
||||
public static void clearMap(PDOMNode parent, final int record) throws CoreException {
|
||||
final PDOMLinkage linkage= parent.getLinkage();
|
||||
final Database db= linkage.getDB();
|
||||
final short len= db.getShort(rec);
|
||||
|
||||
Assert.isTrue(len >= 0 && len <= (Database.MAX_MALLOC_SIZE-2)/NODE_SIZE);
|
||||
rec+=2;
|
||||
long p= record;
|
||||
final short len= db.getShort(p); p+= 2;
|
||||
|
||||
for (int i=0; i<len; i++) {
|
||||
linkage.storeType(rec+TYPE_OFFSET, null);
|
||||
PDOMValue.delete(db, db.getRecPtr(rec+VALUE_OFFSET));
|
||||
rec+= NODE_SIZE;
|
||||
p+= 4; // parameter id
|
||||
short packSize= db.getShort(p); p+= 2;
|
||||
if (packSize == -1)
|
||||
packSize= 1;
|
||||
for (int j = 0; j < packSize; j++) {
|
||||
linkage.storeType(p+TYPE_OFFSET, null);
|
||||
PDOMValue.delete(db, db.getRecPtr(p+VALUE_OFFSET));
|
||||
p+= NODE_SIZE;
|
||||
}
|
||||
db.free(rec);
|
||||
}
|
||||
db.free(record);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -89,7 +118,6 @@ public class PDOMCPPTemplateParameterMap {
|
|||
final Database db= linkage.getDB();
|
||||
final short len= db.getShort(rec);
|
||||
|
||||
Assert.isTrue(len >= 0 && len <= (Database.MAX_MALLOC_SIZE-2)/NODE_SIZE);
|
||||
if (len == 0) {
|
||||
return CPPTemplateParameterMap.EMPTY;
|
||||
}
|
||||
|
@ -97,7 +125,25 @@ public class PDOMCPPTemplateParameterMap {
|
|||
rec+=2;
|
||||
CPPTemplateParameterMap result= new CPPTemplateParameterMap(len);
|
||||
for (int i=0; i<len; i++) {
|
||||
final int parPos= db.getInt(rec + PARAMPOS_OFFSET);
|
||||
final int parPos= db.getInt(rec); rec+= 4;
|
||||
short packSize= db.getShort(rec); rec+= 2;
|
||||
if (packSize == -1) {
|
||||
ICPPTemplateArgument arg = readArgument(rec, linkage, db); rec+= NODE_SIZE;
|
||||
result.put(parPos, arg);
|
||||
} else {
|
||||
ICPPTemplateArgument[] packExpansion= new ICPPTemplateArgument[packSize];
|
||||
for (int j = 0; j < packExpansion.length; j++) {
|
||||
packExpansion[j]= readArgument(rec, linkage, db); rec+= NODE_SIZE;
|
||||
}
|
||||
result.put(parPos, packExpansion);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
private static ICPPTemplateArgument readArgument(long rec, final PDOMLinkage linkage, final Database db)
|
||||
throws CoreException {
|
||||
IType type= linkage.loadType(rec + TYPE_OFFSET);
|
||||
if (type == null) {
|
||||
type= new CPPBasicType(Kind.eUnspecified, CPPBasicType.UNIQUE_TYPE_QUALIFIER);
|
||||
|
@ -110,9 +156,6 @@ public class PDOMCPPTemplateParameterMap {
|
|||
} else {
|
||||
arg= new CPPTemplateArgument(type);
|
||||
}
|
||||
result.put(parPos, arg);
|
||||
rec+= NODE_SIZE;
|
||||
}
|
||||
return result;
|
||||
return arg;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue