mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-07-28 19:35:36 +02:00
Bug 302412: Overload resolution for list-initializers.
This commit is contained in:
parent
4deee6b218
commit
d5c5ba8f02
13 changed files with 545 additions and 159 deletions
|
@ -8077,5 +8077,68 @@ public class AST2CPPTests extends AST2BaseTest {
|
|||
String code= getAboveComment();
|
||||
parseAndCheckBindings(code, ParserLanguage.CPP);
|
||||
}
|
||||
|
||||
// namespace std {
|
||||
// template<typename T> class initializer_list;
|
||||
// }
|
||||
// template<typename T> struct complex {
|
||||
// complex(const T& r, const T& i);
|
||||
// };
|
||||
// template<typename T> struct vector {
|
||||
// vector(std::initializer_list<T>);
|
||||
// };
|
||||
// struct str {
|
||||
// str(const char*);
|
||||
// };
|
||||
// template<typename T> void f(std::initializer_list<T>);
|
||||
// std::initializer_list<const char*> test() {
|
||||
// int a = {1};
|
||||
// complex<double> z{1,2};
|
||||
// new vector<str>{"a", "b", "c", "d"}; // 4 string elements
|
||||
// f( {"a","b"} ); // pass list of two elements
|
||||
// int* e {}; // initialization to zero / null pointer
|
||||
// a = double{1}; // explicitly construct a double
|
||||
// return { "a" }; // return list of one element
|
||||
// }
|
||||
//
|
||||
// struct S {
|
||||
// S(std::initializer_list<double>) {}
|
||||
// S(std::initializer_list<int>) {}
|
||||
// };
|
||||
// void fs(S){}
|
||||
// void tests() {
|
||||
// fs({1,2,3});
|
||||
// fs({1.0,2.0,3.0});
|
||||
// }
|
||||
public void _testListInitialization_302412a() throws Exception {
|
||||
String code= getAboveComment();
|
||||
parseAndCheckBindings(code, ParserLanguage.CPP);
|
||||
}
|
||||
|
||||
// namespace std {
|
||||
// template<typename T> class initializer_list;
|
||||
// }
|
||||
// void f(std::initializer_list<int>);
|
||||
// //void ff(std::initializer_list<str>);
|
||||
// struct A {
|
||||
// A(std::initializer_list<double>); // #1
|
||||
// A(std::initializer_list<const char*>); // #3
|
||||
// };
|
||||
// void g(A);
|
||||
// void test() {
|
||||
// f( {1,2,3} ); // OK: f(initializer_list<int>) identity conversion
|
||||
// f( {'a','b'} ); // OK: f(initializer_list<int>) integral promotion
|
||||
// f( {1.0} ); // error: narrowing
|
||||
// A a{ 1.0,2.0 }; // OK, uses #1
|
||||
// g({ "foo", "bar" }); // OK, uses #3
|
||||
// }
|
||||
public void testListInitialization_302412b() throws Exception {
|
||||
String code= getAboveComment();
|
||||
BindingAssertionHelper bh= new BindingAssertionHelper(code, true);
|
||||
bh.assertNonProblem("f( {1,2,3} )", 1);
|
||||
bh.assertNonProblem("f( {'a','b'} )", 1);
|
||||
bh.assertProblem("f( {1.0} )", 1);
|
||||
bh.assertNonProblem("g({ \"foo\", \"bar\" })", 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -16,9 +16,9 @@ import org.eclipse.cdt.core.dom.ast.ASTVisitor;
|
|||
import org.eclipse.cdt.core.dom.ast.DOMException;
|
||||
import org.eclipse.cdt.core.dom.ast.ExpansionOverlapsBoundaryException;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTInitializerClause;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTIdExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTImplicitName;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTInitializerClause;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
||||
import org.eclipse.cdt.core.dom.ast.IBinding;
|
||||
import org.eclipse.cdt.core.dom.ast.IFunction;
|
||||
|
@ -64,7 +64,7 @@ public class CPPASTFunctionCallExpression extends ASTNode implements
|
|||
public CPPASTFunctionCallExpression copy() {
|
||||
IASTInitializerClause[] args = null;
|
||||
if (fArguments.length > 0) {
|
||||
args= new IASTExpression[fArguments.length];
|
||||
args= new IASTInitializerClause[fArguments.length];
|
||||
for (int i=0; i<fArguments.length; i++) {
|
||||
args[i]= fArguments[i].copy();
|
||||
}
|
||||
|
|
|
@ -17,11 +17,11 @@ import org.eclipse.cdt.core.dom.ast.IASTEqualsInitializer;
|
|||
import org.eclipse.cdt.core.dom.ast.IASTExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTInitializer;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTInitializerClause;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTInitializerList;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTName;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
||||
import org.eclipse.cdt.core.dom.ast.IType;
|
||||
import org.eclipse.cdt.core.dom.ast.IValue;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTInitializerList;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTParameterDeclaration;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPParameterPackType;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateArgument;
|
||||
|
@ -42,6 +42,15 @@ public class CPPTemplateNonTypeParameter extends CPPTemplateParameter implements
|
|||
}
|
||||
|
||||
public IASTExpression getDefault() {
|
||||
IASTInitializerClause def= getDefaultClause();
|
||||
if (def instanceof IASTExpression) {
|
||||
return (IASTExpression) def;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public IASTInitializerClause getDefaultClause() {
|
||||
IASTName[] nds = getDeclarations();
|
||||
if (nds == null || nds.length == 0)
|
||||
return null;
|
||||
|
@ -54,12 +63,7 @@ public class CPPTemplateNonTypeParameter extends CPPTemplateParameter implements
|
|||
IASTDeclarator dtor = (IASTDeclarator) parent;
|
||||
IASTInitializer initializer = dtor.getInitializer();
|
||||
if (initializer instanceof IASTEqualsInitializer) {
|
||||
IASTInitializerClause clause= ((IASTEqualsInitializer) initializer).getInitializerClause();
|
||||
if (clause instanceof IASTExpression)
|
||||
return (IASTExpression) clause;
|
||||
if (clause instanceof IASTInitializerList) {
|
||||
// mstodo handle braced init list
|
||||
}
|
||||
return ((IASTEqualsInitializer) initializer).getInitializerClause();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -68,7 +72,23 @@ public class CPPTemplateNonTypeParameter extends CPPTemplateParameter implements
|
|||
}
|
||||
|
||||
public ICPPTemplateArgument getDefaultValue() {
|
||||
IASTExpression d= getDefault();
|
||||
IASTInitializerClause dc= getDefault();
|
||||
IASTExpression d= null;
|
||||
if (dc instanceof IASTExpression) {
|
||||
d= (IASTExpression) dc;
|
||||
} else if (dc instanceof ICPPASTInitializerList) {
|
||||
ICPPASTInitializerList list= (ICPPASTInitializerList) dc;
|
||||
switch(list.getSize()) {
|
||||
case 0:
|
||||
return new CPPTemplateArgument(Value.create(0), getType());
|
||||
case 1:
|
||||
dc= list.getClauses()[0];
|
||||
if (dc instanceof IASTExpression) {
|
||||
d= (IASTExpression) dc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (d == null)
|
||||
return null;
|
||||
|
||||
|
|
|
@ -33,6 +33,7 @@ import org.eclipse.cdt.core.dom.ast.IScope;
|
|||
import org.eclipse.cdt.core.dom.ast.IType;
|
||||
import org.eclipse.cdt.core.dom.ast.IValue;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConstructorInitializer;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTInitializerList;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPBlockScope;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPVariable;
|
||||
|
@ -409,11 +410,18 @@ public class CPPVariable extends PlatformObject implements ICPPVariable, ICPPInt
|
|||
clause= args[0];
|
||||
}
|
||||
}
|
||||
} else if (init instanceof ICPPASTInitializerList) {
|
||||
ICPPASTInitializerList list= (ICPPASTInitializerList) init;
|
||||
switch (list.getSize()) {
|
||||
case 0:
|
||||
return Value.create(0);
|
||||
case 1:
|
||||
clause= list.getClauses()[0];
|
||||
}
|
||||
}
|
||||
if (clause instanceof IASTExpression) {
|
||||
return Value.create((IASTExpression) clause, maxDepth);
|
||||
}
|
||||
// mstodo handle braced init list
|
||||
return Value.UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2004, 2009 IBM Corporation and others.
|
||||
* Copyright (c) 2004, 2010 IBM Corporation 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
|
||||
|
@ -49,6 +49,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.ICPPFunction;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMember;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPReferenceType;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPUsingDeclaration;
|
||||
|
@ -735,4 +736,30 @@ public class ClassTypeHelper {
|
|||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 8.5.1 Aggregates [dcl.init.aggr]
|
||||
* An aggregate is an array or a class (Clause 9) with no user-provided constructors (12.1),
|
||||
* no private or protected non-static data members (Clause 11),
|
||||
* no base classes (Clause 10), and no virtual functions (10.3).
|
||||
*/
|
||||
public static boolean isAggregateClass(ICPPClassType classTarget) throws DOMException {
|
||||
if (classTarget.getBases().length > 0)
|
||||
return false;
|
||||
ICPPMethod[] methods = classTarget.getDeclaredMethods();
|
||||
for (ICPPMethod m : methods) {
|
||||
if (m instanceof ICPPConstructor)
|
||||
return false;
|
||||
if (m.isVirtual()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
ICPPField[] fields = classTarget.getDeclaredFields();
|
||||
for (ICPPField field : fields) {
|
||||
if (!(field.getVisibility() == ICPPMember.v_public || field.isStatic())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -830,7 +830,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
if (allowThrow && LT(1) == IToken.t_throw) {
|
||||
expr= throwExpression();
|
||||
} else if (allowBraceInitializer && LT(1) == IToken.tLBRACE) {
|
||||
expr= bracedInitList();
|
||||
expr= bracedInitList(true);
|
||||
} else {
|
||||
expr= castExpression(castCtx); // next cast expression
|
||||
continue loop;
|
||||
|
@ -1162,7 +1162,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
if (t != null) {
|
||||
consume(IToken.tRPAREN);
|
||||
if (LT(1) == IToken.tLBRACE) {
|
||||
IASTInitializer i = bracedInitList();
|
||||
IASTInitializer i = bracedInitList(false);
|
||||
firstExpression= nodeFactory.newTypeIdInitializerExpression(t, i);
|
||||
setRange(firstExpression, offset, calculateEndOffset(i));
|
||||
break;
|
||||
|
@ -1212,7 +1212,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
consume(IToken.tLBRACKET);
|
||||
IASTInitializerClause expression;
|
||||
if (LT(1) == IToken.tLBRACE) {
|
||||
expression= bracedInitList();
|
||||
expression= bracedInitList(false);
|
||||
} else {
|
||||
expression= expression();
|
||||
}
|
||||
|
@ -2795,14 +2795,14 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
// = initializer-clause
|
||||
if (lt1 == IToken.tASSIGN) {
|
||||
int offset= consume().getOffset();
|
||||
IASTInitializerClause initClause = initClause(false);
|
||||
IASTInitializerClause initClause = initClause(LT(1) == IToken.tLBRACE);
|
||||
IASTEqualsInitializer initExpr= nodeFactory.newEqualsInitializer(initClause);
|
||||
return setRange(initExpr, offset, calculateEndOffset(initClause));
|
||||
}
|
||||
|
||||
// braced-init-list
|
||||
if (option.fAllowBracedInitializer && lt1 == IToken.tLBRACE) {
|
||||
return bracedInitList();
|
||||
return bracedInitList(false);
|
||||
}
|
||||
|
||||
// ( expression-list )
|
||||
|
@ -2817,7 +2817,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
if (lt1 == IToken.tLPAREN) {
|
||||
return ctorStyleInitializer(true);
|
||||
}
|
||||
return bracedInitList();
|
||||
return bracedInitList(false);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2848,17 +2848,17 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
* assignment-expression
|
||||
* braced-init-list
|
||||
*/
|
||||
private IASTInitializerClause initClause(boolean inBraces) throws EndOfFileException,
|
||||
private IASTInitializerClause initClause(boolean allowSkipping) throws EndOfFileException,
|
||||
BacktrackException {
|
||||
// braced-init-list
|
||||
if (LT(1) == IToken.tLBRACE) {
|
||||
return bracedInitList();
|
||||
return bracedInitList(allowSkipping);
|
||||
}
|
||||
|
||||
// assignment expression
|
||||
final BinaryExprCtx ctx = fInTemplateParameterList ? BinaryExprCtx.eTmplID : BinaryExprCtx.eNoTmplID;
|
||||
IASTExpression assignmentExpression = expression(ExprKind.eAssignment, ctx);
|
||||
if (inBraces && skipTrivialExpressionsInAggregateInitializers) {
|
||||
if (allowSkipping && skipTrivialExpressionsInAggregateInitializers) {
|
||||
if (!ASTQueries.canContainName(assignmentExpression))
|
||||
return null;
|
||||
}
|
||||
|
@ -2870,7 +2870,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
* { initializer-list ,opt }
|
||||
* { }
|
||||
*/
|
||||
private ICPPASTInitializerList bracedInitList() throws EndOfFileException, BacktrackException {
|
||||
private ICPPASTInitializerList bracedInitList(boolean allowSkipping) throws EndOfFileException, BacktrackException {
|
||||
int offset = consume(IToken.tLBRACE).getOffset();
|
||||
|
||||
// { }
|
||||
|
@ -2879,7 +2879,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
}
|
||||
|
||||
// { initializer-list ,opt }
|
||||
List<IASTInitializerClause> initList= initializerList(true);
|
||||
List<IASTInitializerClause> initList= initializerList(allowSkipping);
|
||||
if (LT(1) == IToken.tCOMMA)
|
||||
consume();
|
||||
|
||||
|
@ -2896,14 +2896,14 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
* initializer-clause ...opt
|
||||
* initializer-list , initializer-clause ...opt
|
||||
*/
|
||||
private List<IASTInitializerClause> initializerList(boolean inAggregateInit) throws EndOfFileException,
|
||||
private List<IASTInitializerClause> initializerList(boolean allowSkipping) throws EndOfFileException,
|
||||
BacktrackException {
|
||||
|
||||
List<IASTInitializerClause> result= null;
|
||||
// List of initializer clauses
|
||||
loop: for(;;) {
|
||||
// Clause may be null, add to initializer anyways, such that the size can be computed.
|
||||
IASTInitializerClause clause = initClause(inAggregateInit);
|
||||
IASTInitializerClause clause = initClause(allowSkipping);
|
||||
if (LT(1) == IToken.tELLIPSIS) {
|
||||
final int endOffset = consume(IToken.tELLIPSIS).getEndOffset();
|
||||
if (clause instanceof ICPPASTPackExpandable) {
|
||||
|
@ -4073,7 +4073,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
IASTInitializerClause expr = null;
|
||||
final int lt1 = LT(1);
|
||||
if (lt1 == IToken.tLBRACE) {
|
||||
expr= bracedInitList();
|
||||
expr= bracedInitList(true);
|
||||
} else if (lt1 != IToken.tSEMI) {
|
||||
expr = expression();
|
||||
}
|
||||
|
|
|
@ -93,6 +93,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTForStatement;
|
|||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDeclarator;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDefinition;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTIfStatement;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTInitializerList;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTLinkageSpecification;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamedTypeSpecifier;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamespaceAlias;
|
||||
|
@ -393,7 +394,7 @@ public class CPPSemantics {
|
|||
// if the lookup in base-classes ran into a deferred instance, use the computed unknown binding.
|
||||
final ASTNodeProperty namePropertyInParent = name.getPropertyInParent();
|
||||
if (binding == null && data.skippedScope != null) {
|
||||
if (data.hasArgumentTypes()) {
|
||||
if (data.hasFunctionArguments()) {
|
||||
binding= new CPPUnknownFunction(data.skippedScope, name.getSimpleID());
|
||||
} else {
|
||||
if (namePropertyInParent == IASTNamedTypeSpecifier.NAME) {
|
||||
|
@ -527,11 +528,25 @@ public class CPPSemantics {
|
|||
return false;
|
||||
}
|
||||
|
||||
public static IBinding selectConstructor(ICPPClassType classTarget, ICPPASTInitializerList initializerList) {
|
||||
LookupData data= new LookupData();
|
||||
IASTName name = new CPPASTName(classTarget.getNameCharArray());
|
||||
name.setParent(initializerList);
|
||||
name.setPropertyInParent(CPPSemantics.STRING_LOOKUP_PROPERTY);
|
||||
data.setFunctionArguments(initializerList);
|
||||
try {
|
||||
return CPPSemantics.selectConstructor(classTarget, data);
|
||||
} catch (DOMException e) {
|
||||
return e.getProblem();
|
||||
}
|
||||
}
|
||||
|
||||
private static IBinding selectConstructor(ICPPClassType cls, LookupData data) throws DOMException {
|
||||
// Force resolution of constructor bindings
|
||||
final ICPPConstructor[] constructors= cls.getConstructors();
|
||||
if (constructors.length > 0) {
|
||||
return CPPSemantics.resolveAmbiguities(data.astName, constructors);
|
||||
data.foundItems= constructors;
|
||||
return CPPSemantics.resolveAmbiguities(data, data.astName);
|
||||
}
|
||||
return cls;
|
||||
}
|
||||
|
@ -626,8 +641,8 @@ public class CPPSemantics {
|
|||
data.setFunctionArguments();
|
||||
} else if (init instanceof ICPPASTConstructorInitializer) {
|
||||
data.setFunctionArguments(((ICPPASTConstructorInitializer) init).getArguments());
|
||||
} else {
|
||||
// mstodo handle braced init list
|
||||
} else if (init instanceof ICPPASTInitializerList) {
|
||||
data.setFunctionArguments(new IASTInitializerClause[] {(ICPPASTInitializerList) init});
|
||||
}
|
||||
}
|
||||
} else if (parent instanceof ICPPASTConstructorChainInitializer) {
|
||||
|
@ -635,8 +650,8 @@ public class CPPSemantics {
|
|||
IASTInitializer init = ctorinit.getInitializer();
|
||||
if (init instanceof ICPPASTConstructorInitializer) {
|
||||
data.setFunctionArguments(((ICPPASTConstructorInitializer) init).getArguments());
|
||||
} else {
|
||||
// mstodo handle braced init list
|
||||
} else if (init instanceof ICPPASTInitializerList) {
|
||||
data.setFunctionArguments(new IASTInitializerClause[] {(ICPPASTInitializerList) init});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -644,7 +659,7 @@ public class CPPSemantics {
|
|||
}
|
||||
|
||||
static private ObjectSet<ICPPScope> getAssociatedScopes(LookupData data) {
|
||||
if (!data.hasArgumentTypes())
|
||||
if (!data.hasFunctionArguments())
|
||||
return ObjectSet.emptySet();
|
||||
|
||||
IType[] ps = data.getFunctionArgumentTypes();
|
||||
|
@ -2138,7 +2153,8 @@ public class CPPSemantics {
|
|||
}
|
||||
|
||||
// We don't have any arguments with which to resolve the function
|
||||
if (!data.hasArgumentTypes()) {
|
||||
final boolean isFuncDecl = data.forFunctionDeclaration();
|
||||
if (!data.hasFunctionArguments()) {
|
||||
return resolveTargetedFunction(data, fns);
|
||||
}
|
||||
|
||||
|
@ -2146,7 +2162,7 @@ public class CPPSemantics {
|
|||
return resolveUserDefinedConversion(data, fns);
|
||||
}
|
||||
|
||||
if (!data.forFunctionDeclaration() || data.forExplicitFunctionSpecialization()) {
|
||||
if (!isFuncDecl || data.forExplicitFunctionSpecialization()) {
|
||||
CPPTemplates.instantiateFunctionTemplates(fns, data.getFunctionArgumentTypes(), data.getFunctionArgumentLValues(), data.astName);
|
||||
}
|
||||
|
||||
|
@ -2165,7 +2181,7 @@ public class CPPSemantics {
|
|||
}
|
||||
}
|
||||
}
|
||||
if (firstViable == null || data.forFunctionDeclaration())
|
||||
if (firstViable == null || isFuncDecl)
|
||||
return firstViable;
|
||||
|
||||
// The arguments the function is being called with
|
||||
|
|
|
@ -30,6 +30,7 @@ import org.eclipse.cdt.core.dom.ast.IASTElaboratedTypeSpecifier;
|
|||
import org.eclipse.cdt.core.dom.ast.IASTExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTIdExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTInitializerClause;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTName;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration;
|
||||
|
@ -50,6 +51,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier;
|
|||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTElaboratedTypeSpecifier;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTExplicitTemplateInstantiation;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDefinition;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTInitializerList;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamedTypeSpecifier;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTParameterDeclaration;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName;
|
||||
|
@ -1542,6 +1544,8 @@ public class CPPTemplates {
|
|||
}
|
||||
|
||||
static protected void instantiateFunctionTemplates(IFunction[] functions, IType[] fnArgs, BitSet argIsLValue, IASTName name) {
|
||||
// mstodo handle list initialization
|
||||
|
||||
boolean requireTemplate= false;
|
||||
if (name != null) {
|
||||
if (name.getPropertyInParent() == ICPPASTTemplateId.TEMPLATE_NAME) {
|
||||
|
@ -2045,12 +2049,29 @@ public class CPPTemplates {
|
|||
return true;
|
||||
}
|
||||
t= ((ITypeContainer) t).getType();
|
||||
} else if (t instanceof InitializerListType) {
|
||||
return isDependentInitializerList(((InitializerListType) t).getInitializerList());
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isDependentInitializerList(ICPPASTInitializerList initializerList) {
|
||||
IASTInitializerClause[] clauses= initializerList.getClauses();
|
||||
for (IASTInitializerClause clause : clauses) {
|
||||
if (clause instanceof IASTExpression) {
|
||||
IType t= ((IASTExpression) clause).getExpressionType();
|
||||
if (isDependentType(t))
|
||||
return true;
|
||||
} else if (clause instanceof ICPPASTInitializerList) {
|
||||
if (isDependentInitializerList((ICPPASTInitializerList) clause))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean containsDependentArg(ObjectMap tpMap) {
|
||||
for (Object arg : tpMap.valueArray()) {
|
||||
if (isDependentType((IType)arg))
|
||||
|
|
|
@ -24,6 +24,7 @@ import org.eclipse.cdt.core.dom.ast.IASTExpression;
|
|||
import org.eclipse.cdt.core.dom.ast.IASTLiteralExpression;
|
||||
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.IEnumeration;
|
||||
import org.eclipse.cdt.core.dom.ast.IFunctionType;
|
||||
import org.eclipse.cdt.core.dom.ast.IPointerType;
|
||||
|
@ -33,17 +34,23 @@ import org.eclipse.cdt.core.dom.ast.IType;
|
|||
import org.eclipse.cdt.core.dom.ast.IValue;
|
||||
import org.eclipse.cdt.core.dom.ast.IBasicType.Kind;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPBasicType;
|
||||
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.ICPPConstructor;
|
||||
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.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.ICPPTemplateInstance;
|
||||
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.ArithmeticConversion;
|
||||
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.CPPPointerToMemberType;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPPointerType;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.ClassTypeHelper;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.Cost.Rank;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.Cost.ReferenceBinding;
|
||||
|
||||
|
@ -58,6 +65,9 @@ public class Conversions {
|
|||
static {
|
||||
LVBITSET.set(0, true);
|
||||
}
|
||||
private static final char[] INITIALIZER_LIST_NAME = "initializer_list".toCharArray(); //$NON-NLS-1$
|
||||
private static final char[] STD_NAME = "std".toCharArray(); //$NON-NLS-1$
|
||||
|
||||
/**
|
||||
* Computes the cost of an implicit conversion sequence
|
||||
* [over.best.ics] 13.3.3.1
|
||||
|
@ -85,7 +95,7 @@ public class Conversions {
|
|||
final IType cv2T2= exprType;
|
||||
final IType T2= getNestedType(cv2T2, TDEF | REF | ALLCVQ);
|
||||
|
||||
final boolean isImplicitWithoutRefQualifier = isImpliedObjectType; // mstodo need to pass this information to here
|
||||
final boolean isImplicitWithoutRefQualifier = isImpliedObjectType;
|
||||
ReferenceBinding refBindingType= ReferenceBinding.OTHER;
|
||||
if (!isImplicitWithoutRefQualifier) {
|
||||
if (isLValueRef) {
|
||||
|
@ -258,6 +268,9 @@ public class Conversions {
|
|||
}
|
||||
|
||||
private static Cost nonReferenceConversion(boolean sourceIsLValue, IType source, IType target, UDCMode udc, boolean isImpliedObject) throws DOMException {
|
||||
if (source instanceof InitializerListType) {
|
||||
return listInitializationSequence(((InitializerListType) source), target, udc);
|
||||
}
|
||||
// [13.3.3.1-6] Subsume cv-qualifications
|
||||
IType uqSource= SemanticUtil.getNestedType(source, TDEF | ALLCVQ);
|
||||
Cost cost= checkStandardConversionSequence(uqSource, sourceIsLValue, target, isImpliedObject);
|
||||
|
@ -271,6 +284,68 @@ public class Conversions {
|
|||
return cost;
|
||||
}
|
||||
|
||||
/**
|
||||
* 13.3.3.1.5 List-initialization sequence [over.ics.list]
|
||||
*/
|
||||
private static Cost listInitializationSequence(InitializerListType arg, IType target, UDCMode udc) throws DOMException {
|
||||
IType listType= getInitListType(target);
|
||||
if (listType != null) {
|
||||
IType[] exprTypes= arg.getExpressionTypes();
|
||||
BitSet isLValue= arg.getIsLValue();
|
||||
Cost worstCost= new Cost(arg, target, Rank.IDENTITY);
|
||||
for (int i = 0; i < exprTypes.length; i++) {
|
||||
IType exprType = exprTypes[i];
|
||||
Cost cost= checkImplicitConversionSequence(listType, exprType, isLValue.get(i), UDCMode.allowUDC, false);
|
||||
if (cost.getRank() == Rank.NO_MATCH)
|
||||
return cost;
|
||||
if (cost.isNarrowingConversion()) {
|
||||
cost.setRank(Rank.NO_MATCH);
|
||||
return cost;
|
||||
}
|
||||
if (cost.compareTo(worstCost) > 0) {
|
||||
worstCost= cost;
|
||||
}
|
||||
}
|
||||
return worstCost;
|
||||
}
|
||||
|
||||
IType noCVTarget= getNestedType(target, CVTYPE | TDEF);
|
||||
if (noCVTarget instanceof ICPPClassType) {
|
||||
if (udc == UDCMode.noUDC)
|
||||
return new Cost(arg, target, Rank.NO_MATCH);
|
||||
|
||||
ICPPClassType classTarget= (ICPPClassType) noCVTarget;
|
||||
if (ClassTypeHelper.isAggregateClass(classTarget)) {
|
||||
return new Cost(arg, target, Rank.USER_DEFINED_CONVERSION);
|
||||
}
|
||||
Cost cost= checkUserDefinedConversionSequence(false, arg, target, udc == UDCMode.deferUDC);
|
||||
if (cost != null)
|
||||
return cost;
|
||||
}
|
||||
return new Cost(arg, target, Rank.NO_MATCH);
|
||||
}
|
||||
|
||||
private static IType getInitListType(IType target) throws DOMException {
|
||||
if (target instanceof ICPPClassSpecialization && target instanceof ICPPTemplateInstance) {
|
||||
ICPPTemplateInstance inst = (ICPPTemplateInstance) target;
|
||||
if (CharArrayUtils.equals(INITIALIZER_LIST_NAME, inst.getNameCharArray())) {
|
||||
IBinding owner = inst.getOwner();
|
||||
if (owner instanceof ICPPNamespace
|
||||
&& CharArrayUtils.equals(STD_NAME, owner.getNameCharArray())
|
||||
&& owner.getOwner() == null) {
|
||||
ICPPTemplateArgument[] args = inst.getTemplateArguments();
|
||||
if (args.length == 1) {
|
||||
ICPPTemplateArgument arg = args[0];
|
||||
if (arg.isTypeValue()) {
|
||||
return arg.getTypeValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* [3.9.3-4] Implements cv-ness (partial) comparison. There is a (partial)
|
||||
* ordering on cv-qualifiers, so that a type can be said to be more
|
||||
|
@ -423,6 +498,7 @@ public class Conversions {
|
|||
* @throws DOMException
|
||||
*/
|
||||
static final Cost checkUserDefinedConversionSequence(boolean sourceIsLValue, IType source, IType target, boolean deferUDC) throws DOMException {
|
||||
// mstodo don't return null
|
||||
IType s= getNestedType(source, TDEF | CVTYPE | REF);
|
||||
IType t= getNestedType(target, TDEF | CVTYPE | REF);
|
||||
|
||||
|
@ -436,106 +512,130 @@ public class Conversions {
|
|||
return c;
|
||||
}
|
||||
|
||||
// 13.3.1.4 Copy initialization of class by user-defined conversion
|
||||
if (t instanceof ICPPClassType) {
|
||||
FunctionCost cost1= null;
|
||||
Cost cost2= null;
|
||||
ICPPConstructor[] ctors= ((ICPPClassType) t).getConstructors();
|
||||
CPPTemplates.instantiateFunctionTemplates(ctors, new IType[]{source}, sourceIsLValue ? LVBITSET : RVBITSET, null);
|
||||
|
||||
for (ICPPConstructor ctor : ctors) {
|
||||
if (ctor != null && !(ctor instanceof IProblemBinding) && !ctor.isExplicit()) {
|
||||
final ICPPFunctionType ft = ctor.getType();
|
||||
final IType[] ptypes = ft.getParameterTypes();
|
||||
FunctionCost c1;
|
||||
if (ptypes.length == 0) {
|
||||
if (ctor.takesVarArgs()) {
|
||||
c1= new FunctionCost(ctor, new Cost(source, null, Rank.ELLIPSIS_CONVERSION));
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
IType ptype= SemanticUtil.getNestedType(ptypes[0], TDEF);
|
||||
// We don't need to check the implicit conversion sequence if the type is void
|
||||
if (SemanticUtil.isVoidType(ptype))
|
||||
continue;
|
||||
if (ctor.getRequiredArgumentCount() > 1)
|
||||
continue;
|
||||
|
||||
c1= new FunctionCost(ctor, checkImplicitConversionSequence(ptype, source, sourceIsLValue, UDCMode.noUDC, false));
|
||||
}
|
||||
int cmp= c1.compareTo(null, cost1);
|
||||
if (cmp <= 0) {
|
||||
cost1= c1;
|
||||
cost2= new Cost(t, t, Rank.IDENTITY);
|
||||
cost2.setUserDefinedConversion(ctor);
|
||||
if (cmp == 0) {
|
||||
cost2.setAmbiguousUDC(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (s instanceof InitializerListType) {
|
||||
// 13.3.1.7 Initialization by list-initialization
|
||||
return listInitializationOfClass((InitializerListType) s, (ICPPClassType) t, false);
|
||||
}
|
||||
if (s instanceof ICPPClassType) {
|
||||
ICPPMethod[] ops = SemanticUtil.getConversionOperators((ICPPClassType) s);
|
||||
CPPTemplates.instantiateConversionTemplates(ops, target);
|
||||
for (final ICPPMethod op : ops) {
|
||||
if (op != null && !(op instanceof IProblemBinding)) {
|
||||
final IType returnType = op.getType().getReturnType();
|
||||
final IType uqReturnType= getNestedType(returnType, REF | TDEF | CVTYPE);
|
||||
final int dist = SemanticUtil.calculateInheritanceDepth(uqReturnType, t);
|
||||
if (dist >= 0) {
|
||||
final ICPPFunctionType ft = op.getType();
|
||||
IType implicitType= CPPSemantics.getImplicitType(op, ft.isConst(), ft.isVolatile());
|
||||
final Cost udcCost = isReferenceCompatible(getNestedType(implicitType, TDEF | REF), source, true);
|
||||
if (udcCost != null) {
|
||||
FunctionCost c1= new FunctionCost(op, udcCost);
|
||||
int cmp= c1.compareTo(null, cost1);
|
||||
if (cmp <= 0) {
|
||||
cost1= c1;
|
||||
cost2= new Cost(t, t, Rank.IDENTITY);
|
||||
if (dist > 0) {
|
||||
cost2.setInheritanceDistance(dist);
|
||||
cost2.setRank(Rank.CONVERSION);
|
||||
}
|
||||
cost2.setUserDefinedConversion(op);
|
||||
if (cmp == 0) {
|
||||
cost2.setAmbiguousUDC(true);
|
||||
}
|
||||
}
|
||||
// 13.3.1.4 Copy initialization of class by user-defined conversion
|
||||
return copyInitalizationOfClass(sourceIsLValue, source, s, target, (ICPPClassType) t);
|
||||
}
|
||||
|
||||
if (s instanceof ICPPClassType) {
|
||||
// 13.3.1.5 Initialization by conversion function
|
||||
return initializationByConversion(source, (ICPPClassType) s, target);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Cost listInitializationOfClass(InitializerListType s, ICPPClassType t, boolean isDirect) throws DOMException {
|
||||
// If T has an initializer-list constructor
|
||||
ICPPConstructor usedCtor= null;
|
||||
Cost bestCost= null;
|
||||
ICPPConstructor[] ctors= t.getConstructors();
|
||||
for (ICPPConstructor ctor : ctors) {
|
||||
if (ctor.getRequiredArgumentCount() <= 1) {
|
||||
IType[] parTypes= ctor.getType().getParameterTypes();
|
||||
if (parTypes.length > 0) {
|
||||
final IType target = parTypes[0];
|
||||
if (getInitListType(target) != null) {
|
||||
Cost cost= listInitializationSequence(s, target, UDCMode.noUDC);
|
||||
if (cost.getRank() == Rank.NO_MATCH) {
|
||||
if (bestCost == null) {
|
||||
bestCost= cost;
|
||||
}
|
||||
} else {
|
||||
int cmp= cost.compareTo(bestCost);
|
||||
if (bestCost == null || cmp < 0) {
|
||||
usedCtor= ctor;
|
||||
cost.setUserDefinedConversion(ctor);
|
||||
bestCost= cost;
|
||||
} else if (cmp == 0) {
|
||||
bestCost.setAmbiguousUDC(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (cost1 == null || cost1.getCost(0).getRank() == Rank.NO_MATCH)
|
||||
return null;
|
||||
|
||||
return cost2;
|
||||
}
|
||||
if (bestCost != null) {
|
||||
if (!bestCost.isAmbiguousUDC() && !isDirect) {
|
||||
if (usedCtor != null && usedCtor.isExplicit()) {
|
||||
bestCost.setRank(Rank.NO_MATCH);
|
||||
}
|
||||
}
|
||||
return bestCost;
|
||||
}
|
||||
|
||||
// 13.3.1.5 Initialization by conversion function
|
||||
// mstodo expanding the list for selecting the ctor.
|
||||
return new Cost(s, t, Rank.NO_MATCH);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 13.3.1.4 Copy-initialization of class by user-defined conversion [over.match.copy]
|
||||
*/
|
||||
private static Cost copyInitalizationOfClass(boolean sourceIsLValue, IType source, IType s, IType target,
|
||||
ICPPClassType t) throws DOMException {
|
||||
FunctionCost cost1= null;
|
||||
Cost cost2= null;
|
||||
ICPPConstructor[] ctors= t.getConstructors();
|
||||
CPPTemplates.instantiateFunctionTemplates(ctors, new IType[]{source}, sourceIsLValue ? LVBITSET : RVBITSET, null);
|
||||
|
||||
for (ICPPConstructor ctor : ctors) {
|
||||
if (ctor != null && !(ctor instanceof IProblemBinding) && !ctor.isExplicit()) {
|
||||
final ICPPFunctionType ft = ctor.getType();
|
||||
final IType[] ptypes = ft.getParameterTypes();
|
||||
FunctionCost c1;
|
||||
if (ptypes.length == 0) {
|
||||
if (ctor.takesVarArgs()) {
|
||||
c1= new FunctionCost(ctor, new Cost(source, null, Rank.ELLIPSIS_CONVERSION));
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
IType ptype= SemanticUtil.getNestedType(ptypes[0], TDEF);
|
||||
// We don't need to check the implicit conversion sequence if the type is void
|
||||
if (SemanticUtil.isVoidType(ptype))
|
||||
continue;
|
||||
if (ctor.getRequiredArgumentCount() > 1)
|
||||
continue;
|
||||
|
||||
c1= new FunctionCost(ctor, checkImplicitConversionSequence(ptype, source, sourceIsLValue, UDCMode.noUDC, false));
|
||||
}
|
||||
int cmp= c1.compareTo(null, cost1);
|
||||
if (cmp <= 0) {
|
||||
cost1= c1;
|
||||
cost2= new Cost(t, t, Rank.IDENTITY);
|
||||
cost2.setUserDefinedConversion(ctor);
|
||||
if (cmp == 0) {
|
||||
cost2.setAmbiguousUDC(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (s instanceof ICPPClassType) {
|
||||
ICPPMethod[] ops = SemanticUtil.getConversionOperators((ICPPClassType) s);
|
||||
CPPTemplates.instantiateConversionTemplates(ops, target);
|
||||
FunctionCost cost1= null;
|
||||
Cost cost2= null;
|
||||
for (final ICPPMethod op : ops) {
|
||||
if (op != null && !(op instanceof IProblemBinding)) {
|
||||
final IType returnType = op.getType().getReturnType();
|
||||
IType uqReturnType= getNestedType(returnType, TDEF | ALLCVQ);
|
||||
boolean isLValue = uqReturnType instanceof ICPPReferenceType
|
||||
&& !((ICPPReferenceType) uqReturnType).isRValueReference();
|
||||
Cost c2= checkImplicitConversionSequence(target, uqReturnType, isLValue, UDCMode.noUDC, false);
|
||||
if (c2.getRank() != Rank.NO_MATCH) {
|
||||
ICPPFunctionType ftype = op.getType();
|
||||
IType implicitType= CPPSemantics.getImplicitType(op, ftype.isConst(), ftype.isVolatile());
|
||||
final IType uqReturnType= getNestedType(returnType, REF | TDEF | CVTYPE);
|
||||
final int dist = SemanticUtil.calculateInheritanceDepth(uqReturnType, t);
|
||||
if (dist >= 0) {
|
||||
final ICPPFunctionType ft = op.getType();
|
||||
IType implicitType= CPPSemantics.getImplicitType(op, ft.isConst(), ft.isVolatile());
|
||||
final Cost udcCost = isReferenceCompatible(getNestedType(implicitType, TDEF | REF), source, true);
|
||||
if (udcCost != null) {
|
||||
FunctionCost c1= new FunctionCost(op, udcCost);
|
||||
int cmp= c1.compareTo(null, cost1);
|
||||
if (cmp <= 0) {
|
||||
cost1= c1;
|
||||
cost2= c2;
|
||||
cost2= new Cost(t, t, Rank.IDENTITY);
|
||||
if (dist > 0) {
|
||||
cost2.setInheritanceDistance(dist);
|
||||
cost2.setRank(Rank.CONVERSION);
|
||||
}
|
||||
cost2.setUserDefinedConversion(op);
|
||||
if (cmp == 0) {
|
||||
cost2.setAmbiguousUDC(true);
|
||||
|
@ -545,12 +645,51 @@ public class Conversions {
|
|||
}
|
||||
}
|
||||
}
|
||||
if (cost1 == null || cost1.getCost(0).getRank() == Rank.NO_MATCH)
|
||||
return null;
|
||||
|
||||
return cost2;
|
||||
}
|
||||
return null;
|
||||
if (cost1 == null || cost1.getCost(0).getRank() == Rank.NO_MATCH)
|
||||
return null;
|
||||
|
||||
return cost2;
|
||||
}
|
||||
|
||||
/**
|
||||
* 13.3.1.5 Initialization by conversion function [over.match.conv]
|
||||
*/
|
||||
private static Cost initializationByConversion(IType source, ICPPClassType s, IType target) throws DOMException {
|
||||
ICPPMethod[] ops = SemanticUtil.getConversionOperators(s);
|
||||
CPPTemplates.instantiateConversionTemplates(ops, target);
|
||||
FunctionCost cost1= null;
|
||||
Cost cost2= null;
|
||||
for (final ICPPMethod op : ops) {
|
||||
if (op != null && !(op instanceof IProblemBinding)) {
|
||||
final IType returnType = op.getType().getReturnType();
|
||||
IType uqReturnType= getNestedType(returnType, TDEF | ALLCVQ);
|
||||
boolean isLValue = uqReturnType instanceof ICPPReferenceType
|
||||
&& !((ICPPReferenceType) uqReturnType).isRValueReference();
|
||||
Cost c2= checkImplicitConversionSequence(target, uqReturnType, isLValue, UDCMode.noUDC, false);
|
||||
if (c2.getRank() != Rank.NO_MATCH) {
|
||||
ICPPFunctionType ftype = op.getType();
|
||||
IType implicitType= CPPSemantics.getImplicitType(op, ftype.isConst(), ftype.isVolatile());
|
||||
final Cost udcCost = isReferenceCompatible(getNestedType(implicitType, TDEF | REF), source, true);
|
||||
if (udcCost != null) {
|
||||
FunctionCost c1= new FunctionCost(op, udcCost);
|
||||
int cmp= c1.compareTo(null, cost1);
|
||||
if (cmp <= 0) {
|
||||
cost1= c1;
|
||||
cost2= c2;
|
||||
cost2.setUserDefinedConversion(op);
|
||||
if (cmp == 0) {
|
||||
cost2.setAmbiguousUDC(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (cost1 == null || cost1.getCost(0).getRank() == Rank.NO_MATCH)
|
||||
return null;
|
||||
|
||||
return cost2;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -779,6 +918,7 @@ public class Conversions {
|
|||
// 4.7 An rvalue of an integer type can be converted to an rvalue of another integer type.
|
||||
// An rvalue of an enumeration type can be converted to an rvalue of an integer type.
|
||||
cost.setRank(Rank.CONVERSION);
|
||||
cost.setCouldNarrow();
|
||||
return true;
|
||||
}
|
||||
// 4.12 pointer or pointer to member type can be converted to an rvalue of type bool
|
||||
|
@ -812,7 +952,7 @@ public class Conversions {
|
|||
IType tgtPtrTgt= getNestedType(tgtPtr.getType(), TDEF | CVTYPE | REF);
|
||||
if (SemanticUtil.isVoidType(tgtPtrTgt)) {
|
||||
cost.setRank(Rank.CONVERSION);
|
||||
cost.setInheritanceDistance(Short.MAX_VALUE); // mstodo add distance to last base class
|
||||
cost.setInheritanceDistance(Short.MAX_VALUE);
|
||||
CVQualifier cv= getCVQualifier(srcPtr.getType());
|
||||
cost.source= new CPPPointerType(addQualifiers(CPPSemantics.VOID_TYPE, cv.isConst(), cv.isVolatile()));
|
||||
return false;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2004, 2009 IBM Corporation and others.
|
||||
* Copyright (c) 2004, 2010 IBM Corporation 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
|
||||
|
@ -42,6 +42,8 @@ final class Cost {
|
|||
private int fInheritanceDistance;
|
||||
private ICPPFunction fUserDefinedConversion;
|
||||
private ReferenceBinding fReferenceBinding;
|
||||
|
||||
private boolean fCouldNarrow;
|
||||
|
||||
public Cost(IType s, IType t, Rank rank) {
|
||||
source = s;
|
||||
|
@ -125,9 +127,11 @@ final class Cost {
|
|||
if (isAmbiguousUDC() || other.isAmbiguousUDC())
|
||||
return 0;
|
||||
|
||||
if (!fUserDefinedConversion.equals(other.fUserDefinedConversion))
|
||||
return 0;
|
||||
|
||||
if (fUserDefinedConversion != other.fUserDefinedConversion) {
|
||||
if (fUserDefinedConversion == null ||
|
||||
!fUserDefinedConversion.equals(other.fUserDefinedConversion))
|
||||
return 0;
|
||||
}
|
||||
cmp= fSecondStandardConversionRank.compareTo(other.fSecondStandardConversionRank);
|
||||
if (cmp != 0)
|
||||
return cmp;
|
||||
|
@ -183,4 +187,12 @@ final class Cost {
|
|||
buf.append(']');
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
public boolean isNarrowingConversion() {
|
||||
return fCouldNarrow;
|
||||
}
|
||||
|
||||
public void setCouldNarrow() {
|
||||
fCouldNarrow= true;
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2009 Wind River Systems, Inc. and others.
|
||||
* Copyright (c) 2009, 2010 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
|
||||
|
@ -77,7 +77,7 @@ class FunctionCost {
|
|||
Cost cost = fCosts[i];
|
||||
if (cost.isDeferredUDC()) {
|
||||
Cost udcCost= Conversions.checkUserDefinedConversionSequence(fSourceIsLValue.get(i), cost.source, cost.target, false);
|
||||
if (udcCost == null) {
|
||||
if (udcCost == null || udcCost.getRank() == Rank.NO_MATCH) {
|
||||
return false;
|
||||
}
|
||||
fCosts[i]= udcCost;
|
||||
|
|
|
@ -0,0 +1,84 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2010 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 java.util.BitSet;
|
||||
|
||||
import org.eclipse.cdt.core.dom.ast.IASTExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTInitializerClause;
|
||||
import org.eclipse.cdt.core.dom.ast.IType;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTInitializerList;
|
||||
|
||||
/**
|
||||
* Wrapper for initializer lists to allow for participation in the overload resolution.
|
||||
*/
|
||||
class InitializerListType implements IType {
|
||||
|
||||
private final ICPPASTInitializerList fInitializerList;
|
||||
private IType[] fExpressionTypes;
|
||||
private BitSet fLValues;
|
||||
|
||||
public InitializerListType(ICPPASTInitializerList list) {
|
||||
fInitializerList= list;
|
||||
}
|
||||
|
||||
public boolean isSameType(IType type) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object clone() {
|
||||
try {
|
||||
return super.clone();
|
||||
} catch (CloneNotSupportedException e) {
|
||||
// Will not happen, we IType extends Clonable.
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public ICPPASTInitializerList getInitializerList() {
|
||||
return fInitializerList;
|
||||
}
|
||||
|
||||
public IType[] getExpressionTypes() {
|
||||
if (fExpressionTypes == null) {
|
||||
final IASTInitializerClause[] clauses = fInitializerList.getClauses();
|
||||
fExpressionTypes= new IType[clauses.length];
|
||||
for (int i = 0; i < clauses.length; i++) {
|
||||
IASTInitializerClause clause = clauses[i];
|
||||
if (clause instanceof IASTExpression) {
|
||||
fExpressionTypes[i]= ((IASTExpression) clause).getExpressionType();
|
||||
} else if (clause instanceof ICPPASTInitializerList) {
|
||||
fExpressionTypes[i]= new InitializerListType((ICPPASTInitializerList) clause);
|
||||
} else {
|
||||
assert false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return fExpressionTypes;
|
||||
}
|
||||
|
||||
public BitSet getIsLValue() {
|
||||
if (fLValues == null) {
|
||||
final IASTInitializerClause[] clauses = fInitializerList.getClauses();
|
||||
fLValues= new BitSet(clauses.length);
|
||||
for (int i = 0; i < clauses.length; i++) {
|
||||
IASTInitializerClause clause = clauses[i];
|
||||
if (clause instanceof IASTExpression) {
|
||||
if (((IASTExpression) clause).isLValue()) {
|
||||
fLValues.set(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return fLValues;
|
||||
}
|
||||
}
|
|
@ -49,6 +49,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeleteExpression;
|
|||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTElaboratedTypeSpecifier;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTExplicitTemplateInstantiation;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFieldReference;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTInitializerList;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamespaceDefinition;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTParameterDeclaration;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName;
|
||||
|
@ -101,12 +102,14 @@ public class LookupData {
|
|||
public boolean firstArgIsImpliedMethodArg = false;
|
||||
public boolean ignoreMembers = false;
|
||||
|
||||
private ICPPASTParameterDeclaration[] functionParameters;
|
||||
private IASTInitializerClause[] functionArgs;
|
||||
private IType[] functionArgTypes;
|
||||
private BitSet functionArgLValues;
|
||||
|
||||
public ICPPClassType skippedScope;
|
||||
public Object foundItems = null;
|
||||
private Object[] functionArgs;
|
||||
private IType[] functionArgTypes;
|
||||
public ProblemBinding problem;
|
||||
private BitSet functionArgLValues;
|
||||
|
||||
public LookupData(IASTName n) {
|
||||
astName = n;
|
||||
|
@ -529,27 +532,27 @@ public class LookupData {
|
|||
}
|
||||
|
||||
public IType[] getFunctionArgumentTypes() {
|
||||
if (functionArgTypes == null && functionArgs != null) {
|
||||
if (functionArgs instanceof ICPPASTParameterDeclaration[]) {
|
||||
ICPPASTParameterDeclaration[] pdecls= (ICPPASTParameterDeclaration[]) functionArgs;
|
||||
functionArgTypes= new IType[pdecls.length];
|
||||
for (int i = 0; i < pdecls.length; i++) {
|
||||
functionArgTypes[i] = SemanticUtil.getSimplifiedType(CPPVisitor.createParameterType(
|
||||
pdecls[i], true));
|
||||
}
|
||||
} else if (functionArgs instanceof IASTInitializerClause[]) {
|
||||
IASTInitializerClause[] exprs= (IASTInitializerClause[]) functionArgs;
|
||||
if (functionArgTypes == null) {
|
||||
if (functionArgs != null) {
|
||||
IASTInitializerClause[] exprs= functionArgs;
|
||||
functionArgTypes= new IType[exprs.length];
|
||||
for (int i = 0; i < exprs.length; i++) {
|
||||
IASTInitializerClause e = exprs[i];
|
||||
if (e instanceof IASTExpression) {
|
||||
IType etype= ((IASTExpression) e).getExpressionType();
|
||||
functionArgTypes[i]= SemanticUtil.getSimplifiedType(etype);
|
||||
} else {
|
||||
// mstodo handle braced init list
|
||||
} else if (e instanceof ICPPASTInitializerList) {
|
||||
functionArgTypes[i]= new InitializerListType((ICPPASTInitializerList) e);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (functionParameters != null) {
|
||||
ICPPASTParameterDeclaration[] pdecls= functionParameters;
|
||||
functionArgTypes= new IType[pdecls.length];
|
||||
for (int i = 0; i < pdecls.length; i++) {
|
||||
functionArgTypes[i] = SemanticUtil.getSimplifiedType(CPPVisitor.createParameterType(
|
||||
pdecls[i], true));
|
||||
}
|
||||
}
|
||||
}
|
||||
return functionArgTypes;
|
||||
}
|
||||
|
@ -564,7 +567,7 @@ public class LookupData {
|
|||
if (arg instanceof IASTExpression) {
|
||||
functionArgLValues.set(i, ((IASTExpression) arg).isLValue());
|
||||
} else {
|
||||
// mstodo handle braced init list
|
||||
functionArgLValues.set(i, false);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -580,32 +583,24 @@ public class LookupData {
|
|||
return functionArgLValues;
|
||||
}
|
||||
|
||||
|
||||
public void setFunctionArgumentTypes(IType[] paramTypes) {
|
||||
functionArgTypes= paramTypes;
|
||||
}
|
||||
|
||||
public void setFunctionParameters(ICPPASTParameterDeclaration[] parameters) {
|
||||
functionArgs= parameters;
|
||||
functionParameters= parameters;
|
||||
}
|
||||
|
||||
public IASTInitializerClause[] getFunctionArguments() {
|
||||
if (functionArgs instanceof IASTInitializerClause[])
|
||||
return (IASTInitializerClause[]) functionArgs;
|
||||
|
||||
return null;
|
||||
return functionArgs;
|
||||
}
|
||||
|
||||
public int getFunctionArgumentCount() {
|
||||
if (functionArgs != null)
|
||||
return functionArgs.length;
|
||||
if (functionArgTypes != null)
|
||||
return functionArgTypes.length;
|
||||
if (functionParameters != null)
|
||||
return functionParameters.length;
|
||||
return 0;
|
||||
}
|
||||
|
||||
public boolean hasArgumentTypes() {
|
||||
return functionArgTypes != null || functionArgs != null;
|
||||
public boolean hasFunctionArguments() {
|
||||
return functionArgs != null || functionParameters != null;
|
||||
}
|
||||
|
||||
public IBinding[] getFoundBindings() {
|
||||
|
|
Loading…
Add table
Reference in a new issue