mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-08-05 07:15:39 +02:00
Bug 324096: Use value categories in overload resolution.
This commit is contained in:
parent
4f83e760c3
commit
f8a5d13356
11 changed files with 303 additions and 225 deletions
|
@ -42,6 +42,7 @@ import org.eclipse.cdt.core.dom.ast.IASTFunctionCallExpression;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTFunctionDeclarator;
|
import org.eclipse.cdt.core.dom.ast.IASTFunctionDeclarator;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition;
|
import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTIdExpression;
|
import org.eclipse.cdt.core.dom.ast.IASTIdExpression;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTImplicitName;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTImplicitNameOwner;
|
import org.eclipse.cdt.core.dom.ast.IASTImplicitNameOwner;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTLabelStatement;
|
import org.eclipse.cdt.core.dom.ast.IASTLabelStatement;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTLiteralExpression;
|
import org.eclipse.cdt.core.dom.ast.IASTLiteralExpression;
|
||||||
|
@ -8915,4 +8916,25 @@ public class AST2CPPTests extends AST2BaseTest {
|
||||||
bh.assertProblem("fint(pe + pe);", 4);
|
bh.assertProblem("fint(pe + pe);", 4);
|
||||||
bh.assertNonProblem("fint(p + p);", 4);
|
bh.assertNonProblem("fint(p + p);", 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// struct C {
|
||||||
|
// C(const C& c) {}
|
||||||
|
// };
|
||||||
|
// struct D {
|
||||||
|
// explicit operator C();
|
||||||
|
// };
|
||||||
|
// void f() {
|
||||||
|
// D d;
|
||||||
|
// C c (d);
|
||||||
|
// }
|
||||||
|
public void testExplicitOperatorInDirectInit() throws Exception {
|
||||||
|
String code= getAboveComment();
|
||||||
|
IASTTranslationUnit tu= parseAndCheckBindings(code);
|
||||||
|
ICPPASTFunctionDefinition fdef= getDeclaration(tu, 2);
|
||||||
|
IASTDeclarationStatement declstmt= getStatement(fdef, 1);
|
||||||
|
IASTSimpleDeclaration decl= (IASTSimpleDeclaration) declstmt.getDeclaration();
|
||||||
|
IASTImplicitName[] names = ((IASTImplicitNameOwner) decl.getDeclarators()[0]).getImplicitNames();
|
||||||
|
assertEquals(1, names.length);
|
||||||
|
assertTrue(names[0].resolveBinding() instanceof ICPPConstructor);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -134,7 +134,7 @@ public class CPPASTConditionalExpression extends ASTNode implements IASTConditio
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// mstodo type of conditional operator
|
// mstodo conditional operator (type)
|
||||||
public IType getExpressionType() {
|
public IType getExpressionType() {
|
||||||
IASTExpression positiveExpression = getPositiveResultExpression();
|
IASTExpression positiveExpression = getPositiveResultExpression();
|
||||||
if (positiveExpression == null) {
|
if (positiveExpression == null) {
|
||||||
|
@ -147,7 +147,7 @@ public class CPPASTConditionalExpression extends ASTNode implements IASTConditio
|
||||||
return t2;
|
return t2;
|
||||||
}
|
}
|
||||||
|
|
||||||
// mstodo
|
// mstodo conditional operator (value category)
|
||||||
public ValueCategory getValueCategory() {
|
public ValueCategory getValueCategory() {
|
||||||
return PRVALUE;
|
return PRVALUE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,10 +15,11 @@
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics;
|
package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics;
|
||||||
|
|
||||||
|
import static org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory.LVALUE;
|
||||||
|
import static org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory.PRVALUE;
|
||||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.*;
|
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.*;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.BitSet;
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
@ -44,6 +45,7 @@ import org.eclipse.cdt.core.dom.ast.IASTElaboratedTypeSpecifier;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTEnumerationSpecifier.IASTEnumerator;
|
import org.eclipse.cdt.core.dom.ast.IASTEnumerationSpecifier.IASTEnumerator;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTEqualsInitializer;
|
import org.eclipse.cdt.core.dom.ast.IASTEqualsInitializer;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTExpression;
|
import org.eclipse.cdt.core.dom.ast.IASTExpression;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTFieldReference;
|
import org.eclipse.cdt.core.dom.ast.IASTFieldReference;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTFunctionCallExpression;
|
import org.eclipse.cdt.core.dom.ast.IASTFunctionCallExpression;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTFunctionDeclarator;
|
import org.eclipse.cdt.core.dom.ast.IASTFunctionDeclarator;
|
||||||
|
@ -131,6 +133,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespace;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespaceScope;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespaceScope;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPParameter;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPParameter;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPPointerToMemberType;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPPointerToMemberType;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPReferenceType;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPScope;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPScope;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPSpecialization;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPSpecialization;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateArgument;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateArgument;
|
||||||
|
@ -193,6 +196,7 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPInternalNamespaceScope;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownBinding;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownBinding;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownType;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownType;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.OverloadableOperator;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.OverloadableOperator;
|
||||||
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.Conversions.Context;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.Conversions.UDCMode;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.Conversions.UDCMode;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.Cost.Rank;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.Cost.Rank;
|
||||||
import org.eclipse.cdt.internal.core.index.IIndexScope;
|
import org.eclipse.cdt.internal.core.index.IIndexScope;
|
||||||
|
@ -2288,7 +2292,7 @@ public class CPPSemantics {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isFuncDecl || data.forExplicitFunctionSpecialization()) {
|
if (!isFuncDecl || data.forExplicitFunctionSpecialization()) {
|
||||||
CPPTemplates.instantiateFunctionTemplates(fns, data.getFunctionArgumentTypes(), data.getFunctionArgumentLValues(),
|
CPPTemplates.instantiateFunctionTemplates(fns, data.getFunctionArgumentTypes(), data.getFunctionArgumentValueCategories(),
|
||||||
data.astName, data.argsContainImpliedObject);
|
data.astName, data.argsContainImpliedObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2386,7 +2390,7 @@ public class CPPSemantics {
|
||||||
private static FunctionCost costForFunctionCall(IFunction fn, boolean allowUDC, LookupData data)
|
private static FunctionCost costForFunctionCall(IFunction fn, boolean allowUDC, LookupData data)
|
||||||
throws DOMException {
|
throws DOMException {
|
||||||
IType[] argTypes = data.getFunctionArgumentTypes();
|
IType[] argTypes = data.getFunctionArgumentTypes();
|
||||||
BitSet isLValue= data.getFunctionArgumentLValues();
|
ValueCategory[] isLValue= data.getFunctionArgumentValueCategories();
|
||||||
int skipArg= 0;
|
int skipArg= 0;
|
||||||
final ICPPFunctionType ftype= (ICPPFunctionType) fn.getType();
|
final ICPPFunctionType ftype= (ICPPFunctionType) fn.getType();
|
||||||
if (ftype == null)
|
if (ftype == null)
|
||||||
|
@ -2412,7 +2416,7 @@ public class CPPSemantics {
|
||||||
} else {
|
} else {
|
||||||
result= new FunctionCost(fn, sourceLen + 1);
|
result= new FunctionCost(fn, sourceLen + 1);
|
||||||
|
|
||||||
boolean sourceIsLValue= true;
|
ValueCategory sourceIsLValue= LVALUE;
|
||||||
if (impliedObjectType == null) {
|
if (impliedObjectType == null) {
|
||||||
impliedObjectType= data.getImpliedObjectType();
|
impliedObjectType= data.getImpliedObjectType();
|
||||||
}
|
}
|
||||||
|
@ -2425,7 +2429,7 @@ public class CPPSemantics {
|
||||||
} else if (impliedObjectType.isSameType(implicitParameterType)) {
|
} else if (impliedObjectType.isSameType(implicitParameterType)) {
|
||||||
cost = new Cost(impliedObjectType, implicitParameterType, Rank.IDENTITY);
|
cost = new Cost(impliedObjectType, implicitParameterType, Rank.IDENTITY);
|
||||||
} else {
|
} else {
|
||||||
cost = Conversions.checkImplicitConversionSequence(implicitParameterType, impliedObjectType, sourceIsLValue, UDCMode.noUDC, true);
|
cost = Conversions.checkImplicitConversionSequence(implicitParameterType, impliedObjectType, sourceIsLValue, UDCMode.FORBIDDEN, Context.IMPLICIT_OBJECT);
|
||||||
if (!cost.converts()) {
|
if (!cost.converts()) {
|
||||||
if (CPPTemplates.isDependentType(implicitParameterType) || CPPTemplates.isDependentType(impliedObjectType)) {
|
if (CPPTemplates.isDependentType(implicitParameterType) || CPPTemplates.isDependentType(impliedObjectType)) {
|
||||||
IType s= getNestedType(impliedObjectType, TDEF|REF|CVTYPE);
|
IType s= getNestedType(impliedObjectType, TDEF|REF|CVTYPE);
|
||||||
|
@ -2443,17 +2447,17 @@ public class CPPSemantics {
|
||||||
result.setCost(k++, cost, sourceIsLValue);
|
result.setCost(k++, cost, sourceIsLValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
final UDCMode udc = allowUDC ? UDCMode.deferUDC : UDCMode.noUDC;
|
final UDCMode udc = allowUDC ? UDCMode.DEFER : UDCMode.FORBIDDEN;
|
||||||
for (int j = 0; j < sourceLen; j++) {
|
for (int j = 0; j < sourceLen; j++) {
|
||||||
final IType argType= SemanticUtil.getNestedType(argTypes[j+skipArg], TDEF | REF);
|
final IType argType= SemanticUtil.getNestedType(argTypes[j+skipArg], TDEF | REF);
|
||||||
if (argType == null)
|
if (argType == null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
final boolean sourceIsLValue = isLValue.get(j+skipArg);
|
final ValueCategory sourceIsLValue = isLValue[j+skipArg];
|
||||||
|
|
||||||
IType paramType;
|
IType paramType;
|
||||||
if (j < paramTypes.length) {
|
if (j < paramTypes.length) {
|
||||||
paramType= paramTypes[j];
|
paramType= getNestedType(paramTypes[j], TDEF);
|
||||||
} else if (!fn.takesVarArgs()) {
|
} else if (!fn.takesVarArgs()) {
|
||||||
paramType= VOID_TYPE;
|
paramType= VOID_TYPE;
|
||||||
} else {
|
} else {
|
||||||
|
@ -2467,7 +2471,16 @@ public class CPPSemantics {
|
||||||
} else {
|
} else {
|
||||||
if (CPPTemplates.isDependentType(paramType))
|
if (CPPTemplates.isDependentType(paramType))
|
||||||
return CONTAINS_DEPENDENT_TYPES;
|
return CONTAINS_DEPENDENT_TYPES;
|
||||||
cost = Conversions.checkImplicitConversionSequence(paramType, argType, sourceIsLValue, udc, false);
|
|
||||||
|
Context ctx= Context.ORDINARY;
|
||||||
|
if (j==0 && sourceLen == 1 && fn instanceof ICPPConstructor) {
|
||||||
|
if (paramType instanceof ICPPReferenceType && !((ICPPReferenceType) paramType).isRValueReference()) {
|
||||||
|
if (((ICPPConstructor) fn).getClassOwner().isSameType(getNestedType(paramType, TDEF|REF|CVTYPE))) {
|
||||||
|
ctx= Context.FIRST_PARAM_OF_DIRECT_COPY_CTOR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cost = Conversions.checkImplicitConversionSequence(paramType, argType, sourceIsLValue, udc, ctx);
|
||||||
if (data.fNoNarrowing && cost.isNarrowingConversion()) {
|
if (data.fNoNarrowing && cost.isNarrowingConversion()) {
|
||||||
cost= Cost.NO_CONVERSION;
|
cost= Cost.NO_CONVERSION;
|
||||||
}
|
}
|
||||||
|
@ -2941,22 +2954,23 @@ public class CPPSemantics {
|
||||||
type = SemanticUtil.getNestedType(((ICPPVariable) binding).getType(), TDEF | CVTYPE);
|
type = SemanticUtil.getNestedType(((ICPPVariable) binding).getType(), TDEF | CVTYPE);
|
||||||
if (!(type instanceof ICPPClassType))
|
if (!(type instanceof ICPPClassType))
|
||||||
return null;
|
return null;
|
||||||
|
final ICPPClassType classType = (ICPPClassType) type;
|
||||||
|
|
||||||
// Copy initialization
|
// Copy initialization
|
||||||
if (initializer instanceof IASTEqualsInitializer) {
|
if (initializer instanceof IASTEqualsInitializer) {
|
||||||
IASTEqualsInitializer eqInit= (IASTEqualsInitializer) initializer;
|
IASTEqualsInitializer eqInit= (IASTEqualsInitializer) initializer;
|
||||||
IASTInitializerClause initClause = eqInit.getInitializerClause();
|
IASTInitializerClause initClause = eqInit.getInitializerClause();
|
||||||
IType sourceType= null;
|
IType sourceType= null;
|
||||||
boolean isLValue= false;
|
ValueCategory isLValue= PRVALUE;
|
||||||
if (initClause instanceof IASTExpression) {
|
if (initClause instanceof IASTExpression) {
|
||||||
final IASTExpression expr = (IASTExpression) initClause;
|
final IASTExpression expr = (IASTExpression) initClause;
|
||||||
isLValue= expr.isLValue();
|
isLValue= expr.getValueCategory();
|
||||||
sourceType= SemanticUtil.getSimplifiedType(expr.getExpressionType());
|
sourceType= SemanticUtil.getSimplifiedType(expr.getExpressionType());
|
||||||
} else if (initClause instanceof ICPPASTInitializerList) {
|
} else if (initClause instanceof ICPPASTInitializerList) {
|
||||||
sourceType= new InitializerListType((ICPPASTInitializerList) initClause);
|
sourceType= new InitializerListType((ICPPASTInitializerList) initClause);
|
||||||
}
|
}
|
||||||
if (sourceType != null) {
|
if (sourceType != null) {
|
||||||
Cost c= Conversions.checkUserDefinedConversionSequence(isLValue, sourceType, type, false, false);
|
Cost c= Conversions.copyInitializationOfClass(isLValue, sourceType, classType, false);
|
||||||
if (c.converts()) {
|
if (c.converts()) {
|
||||||
IFunction f= c.getUserDefinedConversion();
|
IFunction f= c.getUserDefinedConversion();
|
||||||
if (f instanceof ICPPConstructor)
|
if (f instanceof ICPPConstructor)
|
||||||
|
@ -2967,7 +2981,6 @@ public class CPPSemantics {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Direct Initialization
|
// Direct Initialization
|
||||||
ICPPClassType classType = (ICPPClassType) type;
|
|
||||||
CPPASTName astName = new CPPASTName();
|
CPPASTName astName = new CPPASTName();
|
||||||
astName.setName(classType.getNameCharArray());
|
astName.setName(classType.getNameCharArray());
|
||||||
astName.setOffsetAndLength((ASTNode) name);
|
astName.setOffsetAndLength((ASTNode) name);
|
||||||
|
@ -3022,9 +3035,6 @@ public class CPPSemantics {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* mstodo remove
|
|
||||||
*/
|
|
||||||
public static IASTExpression createArgForType(IASTNode node, IType type) {
|
public static IASTExpression createArgForType(IASTNode node, IType type) {
|
||||||
CPPASTName x= new CPPASTName();
|
CPPASTName x= new CPPASTName();
|
||||||
x.setBinding(createVariable(x, type, false, false));
|
x.setBinding(createVariable(x, type, false, false));
|
||||||
|
|
|
@ -13,8 +13,9 @@
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics;
|
package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics;
|
||||||
|
|
||||||
|
import static org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory.LVALUE;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.BitSet;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
@ -28,6 +29,7 @@ import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTDeclarator;
|
import org.eclipse.cdt.core.dom.ast.IASTDeclarator;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTElaboratedTypeSpecifier;
|
import org.eclipse.cdt.core.dom.ast.IASTElaboratedTypeSpecifier;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTExpression;
|
import org.eclipse.cdt.core.dom.ast.IASTExpression;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition;
|
import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTIdExpression;
|
import org.eclipse.cdt.core.dom.ast.IASTIdExpression;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTInitializerClause;
|
import org.eclipse.cdt.core.dom.ast.IASTInitializerClause;
|
||||||
|
@ -139,6 +141,7 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownBinding;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownClassInstance;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownClassInstance;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownClassType;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownClassType;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownType;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownType;
|
||||||
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.Conversions.Context;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.Conversions.UDCMode;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.Conversions.UDCMode;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -146,7 +149,6 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.Conversions.UDCMod
|
||||||
* type instantiation.
|
* type instantiation.
|
||||||
*/
|
*/
|
||||||
public class CPPTemplates {
|
public class CPPTemplates {
|
||||||
private static final BitSet ALL_RVALUES = new BitSet();
|
|
||||||
private static final int PACK_SIZE_DEFER = -1;
|
private static final int PACK_SIZE_DEFER = -1;
|
||||||
private static final int PACK_SIZE_FAIL = -2;
|
private static final int PACK_SIZE_FAIL = -2;
|
||||||
private static final int PACK_SIZE_NOT_FOUND = Integer.MAX_VALUE;
|
private static final int PACK_SIZE_NOT_FOUND = Integer.MAX_VALUE;
|
||||||
|
@ -1539,7 +1541,7 @@ public class CPPTemplates {
|
||||||
}
|
}
|
||||||
|
|
||||||
static protected void instantiateFunctionTemplates(IFunction[] functions, IType[] allFnArgs,
|
static protected void instantiateFunctionTemplates(IFunction[] functions, IType[] allFnArgs,
|
||||||
BitSet allArgIsLValue, IASTName name, boolean argsContainImpliedObject) {
|
ValueCategory[] allValueCategories, IASTName name, boolean argsContainImpliedObject) {
|
||||||
boolean requireTemplate= false;
|
boolean requireTemplate= false;
|
||||||
if (name != null) {
|
if (name != null) {
|
||||||
if (name.getPropertyInParent() == ICPPASTTemplateId.TEMPLATE_NAME) {
|
if (name.getPropertyInParent() == ICPPASTTemplateId.TEMPLATE_NAME) {
|
||||||
|
@ -1551,7 +1553,7 @@ public class CPPTemplates {
|
||||||
}
|
}
|
||||||
|
|
||||||
IType[] reducedFnArgs= null;
|
IType[] reducedFnArgs= null;
|
||||||
BitSet reducedIsLValue= null;
|
ValueCategory[] reducedValueCategories= null;
|
||||||
ICPPTemplateArgument[] tmplArgs= null;
|
ICPPTemplateArgument[] tmplArgs= null;
|
||||||
for (int i = 0; i < functions.length; i++) {
|
for (int i = 0; i < functions.length; i++) {
|
||||||
IFunction func = functions[i];
|
IFunction func = functions[i];
|
||||||
|
@ -1560,23 +1562,23 @@ public class CPPTemplates {
|
||||||
functions[i]= null;
|
functions[i]= null;
|
||||||
|
|
||||||
final IType[] fnArgs;
|
final IType[] fnArgs;
|
||||||
final BitSet argIsLValue;
|
final ValueCategory[] valueCategories;
|
||||||
if (argsContainImpliedObject && template instanceof ICPPMethod) {
|
if (argsContainImpliedObject && template instanceof ICPPMethod) {
|
||||||
if (reducedIsLValue == null) {
|
if (reducedValueCategories == null) {
|
||||||
if (allFnArgs != null && allFnArgs.length > 0) {
|
if (allFnArgs != null && allFnArgs.length > 0) {
|
||||||
reducedFnArgs= ArrayUtil.removeFirst(allFnArgs);
|
reducedFnArgs= ArrayUtil.removeFirst(allFnArgs);
|
||||||
}
|
}
|
||||||
if (allArgIsLValue == null || allArgIsLValue.length() == 0) {
|
if (allValueCategories == null || allValueCategories.length == 0) {
|
||||||
reducedIsLValue= ALL_RVALUES;
|
reducedValueCategories= new ValueCategory[0];
|
||||||
} else {
|
} else {
|
||||||
reducedIsLValue= allArgIsLValue.get(1, allArgIsLValue.length());
|
reducedValueCategories= ArrayUtil.removeFirst(allValueCategories);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fnArgs= reducedFnArgs;
|
fnArgs= reducedFnArgs;
|
||||||
argIsLValue= reducedIsLValue;
|
valueCategories= reducedValueCategories;
|
||||||
} else {
|
} else {
|
||||||
fnArgs= allFnArgs;
|
fnArgs= allFnArgs;
|
||||||
argIsLValue= allArgIsLValue;
|
valueCategories= allValueCategories;
|
||||||
}
|
}
|
||||||
|
|
||||||
// extract template arguments and parameter types.
|
// extract template arguments and parameter types.
|
||||||
|
@ -1600,7 +1602,7 @@ public class CPPTemplates {
|
||||||
}
|
}
|
||||||
CPPTemplateParameterMap map= new CPPTemplateParameterMap(fnArgs.length);
|
CPPTemplateParameterMap map= new CPPTemplateParameterMap(fnArgs.length);
|
||||||
try {
|
try {
|
||||||
ICPPTemplateArgument[] args= TemplateArgumentDeduction.deduceForFunctionCall(template, tmplArgs, fnArgs, argIsLValue, map);
|
ICPPTemplateArgument[] args= TemplateArgumentDeduction.deduceForFunctionCall(template, tmplArgs, fnArgs, valueCategories, map);
|
||||||
if (args != null) {
|
if (args != null) {
|
||||||
IBinding instance= instantiateFunctionTemplate(template, args, map);
|
IBinding instance= instantiateFunctionTemplate(template, args, map);
|
||||||
if (instance instanceof IFunction) {
|
if (instance instanceof IFunction) {
|
||||||
|
@ -1719,7 +1721,7 @@ public class CPPTemplates {
|
||||||
|
|
||||||
map= new CPPTemplateParameterMap(2);
|
map= new CPPTemplateParameterMap(2);
|
||||||
final IType[] transferredParameterTypes = ((ICPPFunction) transferredTemplate).getType().getParameterTypes();
|
final IType[] transferredParameterTypes = ((ICPPFunction) transferredTemplate).getType().getParameterTypes();
|
||||||
if (!TemplateArgumentDeduction.deduceFromFunctionArgs(f2, transferredParameterTypes, ALL_RVALUES, map, true))
|
if (!TemplateArgumentDeduction.deduceFromFunctionArgs(f2, transferredParameterTypes, null, map, true))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
final int last = tmplParams1.length -1;
|
final int last = tmplParams1.length -1;
|
||||||
|
@ -1981,7 +1983,7 @@ public class CPPTemplates {
|
||||||
} else if (paramType instanceof IArrayType) {
|
} else if (paramType instanceof IArrayType) {
|
||||||
paramType = new CPPPointerType(((IArrayType) paramType).getType());
|
paramType = new CPPPointerType(((IArrayType) paramType).getType());
|
||||||
}
|
}
|
||||||
Cost cost = Conversions.checkImplicitConversionSequence(paramType, arg, true, UDCMode.noUDC, false);
|
Cost cost = Conversions.checkImplicitConversionSequence(paramType, arg, LVALUE, UDCMode.FORBIDDEN, Context.ORDINARY);
|
||||||
return cost != null && cost.converts();
|
return cost != null && cost.converts();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,6 @@ package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics;
|
||||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.*;
|
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.*;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.BitSet;
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
@ -40,6 +39,7 @@ import org.eclipse.cdt.core.dom.ast.IASTEnumerationSpecifier;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTEnumerationSpecifier.IASTEnumerator;
|
import org.eclipse.cdt.core.dom.ast.IASTEnumerationSpecifier.IASTEnumerator;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTEqualsInitializer;
|
import org.eclipse.cdt.core.dom.ast.IASTEqualsInitializer;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTExpression;
|
import org.eclipse.cdt.core.dom.ast.IASTExpression;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTFieldReference;
|
import org.eclipse.cdt.core.dom.ast.IASTFieldReference;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTForStatement;
|
import org.eclipse.cdt.core.dom.ast.IASTForStatement;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTFunctionCallExpression;
|
import org.eclipse.cdt.core.dom.ast.IASTFunctionCallExpression;
|
||||||
|
@ -1791,6 +1791,7 @@ public class CPPVisitor extends ASTQueries {
|
||||||
|
|
||||||
IType type = AutoTypeResolver.AUTO_TYPE;
|
IType type = AutoTypeResolver.AUTO_TYPE;
|
||||||
IType initType = null;
|
IType initType = null;
|
||||||
|
ValueCategory valueCat= null;
|
||||||
ICPPClassTemplate initializer_list_template = null;
|
ICPPClassTemplate initializer_list_template = null;
|
||||||
try {
|
try {
|
||||||
if (initClause instanceof ICPPASTInitializerList) {
|
if (initClause instanceof ICPPASTInitializerList) {
|
||||||
|
@ -1804,7 +1805,9 @@ public class CPPVisitor extends ASTQueries {
|
||||||
type = decorateType(type, declSpec, declarator);
|
type = decorateType(type, declSpec, declarator);
|
||||||
|
|
||||||
if (initClause instanceof IASTExpression) {
|
if (initClause instanceof IASTExpression) {
|
||||||
initType = ((IASTExpression) initClause).getExpressionType();
|
final IASTExpression expression = (IASTExpression) initClause;
|
||||||
|
initType = expression.getExpressionType();
|
||||||
|
valueCat= expression.getValueCategory();
|
||||||
} else if (initClause instanceof ICPPASTInitializerList) {
|
} else if (initClause instanceof ICPPASTInitializerList) {
|
||||||
initType = new InitializerListType((ICPPASTInitializerList) initClause);
|
initType = new InitializerListType((ICPPASTInitializerList) initClause);
|
||||||
}
|
}
|
||||||
|
@ -1816,8 +1819,8 @@ public class CPPVisitor extends ASTQueries {
|
||||||
}
|
}
|
||||||
ICPPFunctionTemplate template = new AutoTypeResolver(type);
|
ICPPFunctionTemplate template = new AutoTypeResolver(type);
|
||||||
CPPTemplateParameterMap paramMap = new CPPTemplateParameterMap(1);
|
CPPTemplateParameterMap paramMap = new CPPTemplateParameterMap(1);
|
||||||
TemplateArgumentDeduction.deduceFromFunctionArgs(template, new IType[] { initType }, new BitSet(),
|
TemplateArgumentDeduction.deduceFromFunctionArgs(template, new IType[] { initType },
|
||||||
paramMap, false);
|
new ValueCategory[] { valueCat }, paramMap, false);
|
||||||
ICPPTemplateArgument argument = paramMap.getArgument(0, 0);
|
ICPPTemplateArgument argument = paramMap.getArgument(0, 0);
|
||||||
if (argument == null) {
|
if (argument == null) {
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -14,13 +14,14 @@
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics;
|
package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics;
|
||||||
|
|
||||||
|
import static org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory.LVALUE;
|
||||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CVQualifier._;
|
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CVQualifier._;
|
||||||
|
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExpressionTypes.valueCategoryFromReturnType;
|
||||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.*;
|
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.*;
|
||||||
|
|
||||||
import java.util.BitSet;
|
|
||||||
|
|
||||||
import org.eclipse.cdt.core.dom.ast.DOMException;
|
import org.eclipse.cdt.core.dom.ast.DOMException;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTExpression;
|
import org.eclipse.cdt.core.dom.ast.IASTExpression;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTInitializerClause;
|
import org.eclipse.cdt.core.dom.ast.IASTInitializerClause;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTLiteralExpression;
|
import org.eclipse.cdt.core.dom.ast.IASTLiteralExpression;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTName;
|
import org.eclipse.cdt.core.dom.ast.IASTName;
|
||||||
|
@ -55,6 +56,7 @@ 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.CPPPointerToMemberType;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPPointerType;
|
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.ClassTypeHelper;
|
||||||
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.Cost.DeferredUDC;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.Cost.Rank;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.Cost.Rank;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.Cost.ReferenceBinding;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.Cost.ReferenceBinding;
|
||||||
|
|
||||||
|
@ -62,30 +64,26 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.Cost.ReferenceBind
|
||||||
* Routines for calculating the cost of conversions.
|
* Routines for calculating the cost of conversions.
|
||||||
*/
|
*/
|
||||||
public class Conversions {
|
public class Conversions {
|
||||||
enum UDCMode {allowUDC, noUDC, deferUDC}
|
enum UDCMode {ALLOWED, FORBIDDEN, DEFER}
|
||||||
|
enum Context {ORDINARY, IMPLICIT_OBJECT, FIRST_PARAM_OF_DIRECT_COPY_CTOR}
|
||||||
|
|
||||||
private static final BitSet RVBITSET = new BitSet();
|
|
||||||
private static final BitSet LVBITSET = new BitSet();
|
|
||||||
static {
|
|
||||||
LVBITSET.set(0, true);
|
|
||||||
}
|
|
||||||
private static final char[] INITIALIZER_LIST_NAME = "initializer_list".toCharArray(); //$NON-NLS-1$
|
private static final char[] INITIALIZER_LIST_NAME = "initializer_list".toCharArray(); //$NON-NLS-1$
|
||||||
private static final char[] STD_NAME = "std".toCharArray(); //$NON-NLS-1$
|
private static final char[] STD_NAME = "std".toCharArray(); //$NON-NLS-1$
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Computes the cost of an implicit conversion sequence
|
* Computes the cost of an implicit conversion sequence [over.best.ics] 13.3.3.1
|
||||||
* [over.best.ics] 13.3.3.1
|
* The semantics of the initialization is explained in 8.5-16
|
||||||
* @param target the target (parameter) type
|
* @param target the target (parameter) type
|
||||||
* @param exprType the source (argument) type
|
* @param exprType the source (argument) type
|
||||||
* @param exprIsLValue whether the source type is an lvalue
|
* @param valueCat value category of the expression
|
||||||
* @param isImpliedObjectType
|
|
||||||
* @return the cost of converting from source to target
|
* @return the cost of converting from source to target
|
||||||
* @throws DOMException
|
* @throws DOMException
|
||||||
*/
|
*/
|
||||||
public static Cost checkImplicitConversionSequence(IType target, IType exprType,
|
public static Cost checkImplicitConversionSequence(IType target, IType exprType,
|
||||||
boolean exprIsLValue, UDCMode udc, boolean isImpliedObjectType) throws DOMException {
|
ValueCategory valueCat, UDCMode udc, Context ctx) throws DOMException {
|
||||||
if (isImpliedObjectType) {
|
final boolean isImpliedObject= ctx == Context.IMPLICIT_OBJECT;
|
||||||
udc= UDCMode.noUDC;
|
if (isImpliedObject) {
|
||||||
|
udc= UDCMode.FORBIDDEN;
|
||||||
}
|
}
|
||||||
|
|
||||||
target= getNestedType(target, TDEF);
|
target= getNestedType(target, TDEF);
|
||||||
|
@ -99,12 +97,13 @@ public class Conversions {
|
||||||
final IType cv2T2= exprType;
|
final IType cv2T2= exprType;
|
||||||
final IType T2= getNestedType(cv2T2, TDEF | REF | ALLCVQ);
|
final IType T2= getNestedType(cv2T2, TDEF | REF | ALLCVQ);
|
||||||
|
|
||||||
final boolean isImplicitWithoutRefQualifier = isImpliedObjectType;
|
// mstodo: will change when implementing rvalue references on this pointer
|
||||||
|
final boolean isImplicitWithoutRefQualifier = isImpliedObject;
|
||||||
ReferenceBinding refBindingType= ReferenceBinding.OTHER;
|
ReferenceBinding refBindingType= ReferenceBinding.OTHER;
|
||||||
if (!isImplicitWithoutRefQualifier) {
|
if (!isImplicitWithoutRefQualifier) {
|
||||||
if (isLValueRef) {
|
if (isLValueRef) {
|
||||||
refBindingType= ReferenceBinding.LVALUE_REF;
|
refBindingType= ReferenceBinding.LVALUE_REF;
|
||||||
} else if (exprIsLValue) {
|
} else if (valueCat == LVALUE) {
|
||||||
refBindingType= ReferenceBinding.RVALUE_REF_BINDS_RVALUE;
|
refBindingType= ReferenceBinding.RVALUE_REF_BINDS_RVALUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -113,9 +112,9 @@ public class Conversions {
|
||||||
if (isLValueRef) {
|
if (isLValueRef) {
|
||||||
// ... the initializer expression is an lvalue (but is not a bit field)
|
// ... the initializer expression is an lvalue (but is not a bit field)
|
||||||
// [for overload resolution bit-fields are treated the same, error if selected as best match]
|
// [for overload resolution bit-fields are treated the same, error if selected as best match]
|
||||||
if (exprIsLValue) {
|
if (valueCat == LVALUE) {
|
||||||
// ... and "cv1 T1" is reference-compatible with "cv2 T2"
|
// ... and "cv1 T1" is reference-compatible with "cv2 T2"
|
||||||
Cost cost= isReferenceCompatible(cv1T1, cv2T2, isImpliedObjectType);
|
Cost cost= isReferenceCompatible(cv1T1, cv2T2, isImpliedObject);
|
||||||
if (cost != null) {
|
if (cost != null) {
|
||||||
// [13.3.3.1.4-1] direct binding has either identity or conversion rank.
|
// [13.3.3.1.4-1] direct binding has either identity or conversion rank.
|
||||||
if (cost.getInheritanceDistance() > 0) {
|
if (cost.getInheritanceDistance() > 0) {
|
||||||
|
@ -129,8 +128,8 @@ public class Conversions {
|
||||||
// implicitly converted to an lvalue of type 'cv3 T3', where 'cv1 T1' is reference-compatible with
|
// implicitly converted to an lvalue of type 'cv3 T3', where 'cv1 T1' is reference-compatible with
|
||||||
// 'cv3 T3' (this conversion is selected by enumerating the applicable conversion functions (13.3.1.6)
|
// 'cv3 T3' (this conversion is selected by enumerating the applicable conversion functions (13.3.1.6)
|
||||||
// and choosing the best one through overload resolution (13.3)),
|
// and choosing the best one through overload resolution (13.3)),
|
||||||
if (T2 instanceof ICPPClassType && udc != UDCMode.noUDC && isReferenceRelated(T1, T2) < 0) {
|
if (T2 instanceof ICPPClassType && udc != UDCMode.FORBIDDEN && isReferenceRelated(T1, T2) < 0) {
|
||||||
Cost cost= conversionFuncForDirectReference(cv1T1, cv2T2, T2, true);
|
Cost cost= initializationByConversionForDirectReference(cv1T1, cv2T2, (ICPPClassType) T2, true, ctx);
|
||||||
if (cost != null) {
|
if (cost != null) {
|
||||||
cost.setReferenceBinding(refBindingType);
|
cost.setReferenceBinding(refBindingType);
|
||||||
return cost;
|
return cost;
|
||||||
|
@ -140,22 +139,46 @@ public class Conversions {
|
||||||
|
|
||||||
// Otherwise, the reference shall be an lvalue reference to a non-volatile const type (i.e., cv1
|
// Otherwise, the reference shall be an lvalue reference to a non-volatile const type (i.e., cv1
|
||||||
// shall be const), or the reference shall be an rvalue reference and the initializer expression
|
// shall be const), or the reference shall be an rvalue reference and the initializer expression
|
||||||
// shall be an rvalue.
|
// shall be an rvalue or have function type.
|
||||||
boolean ok;
|
boolean ok;
|
||||||
if (isLValueRef) {
|
if (isLValueRef) {
|
||||||
ok = getCVQualifier(cv1T1) == CVQualifier.c;
|
ok = getCVQualifier(cv1T1) == CVQualifier.c;
|
||||||
} else {
|
} else {
|
||||||
ok= !exprIsLValue;
|
ok= valueCat.isRValue() || T2 instanceof IFunctionType;
|
||||||
}
|
}
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
return Cost.NO_CONVERSION;
|
return Cost.NO_CONVERSION;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If T1 and T2 are class types and ...
|
// If T1 is a function type, then
|
||||||
if (T1 instanceof ICPPClassType && T2 instanceof ICPPClassType) {
|
if (T1 instanceof IFunctionType) {
|
||||||
// ... the initializer expression is an rvalue and �cv1 T1� is reference-compatible with �cv2 T2�
|
// if T2 is the same type as T1, the reference is bound to the initializer expression lvalue;
|
||||||
if (!exprIsLValue) {
|
if (T2.isSameType(T1)) {
|
||||||
Cost cost= isReferenceCompatible(cv1T1, cv2T2, isImpliedObjectType);
|
Cost cost= new Cost(T1, T2, Rank.IDENTITY);
|
||||||
|
cost.setReferenceBinding(refBindingType);
|
||||||
|
return cost;
|
||||||
|
}
|
||||||
|
// if T2 is a class type and the initializer expression can be implicitly converted to an lvalue of
|
||||||
|
// type T1 (this conversion is selected by enumerating the applicable conversion functions (13.3.1.6)
|
||||||
|
// and choosing the best one through overload resolution (13.3)), the reference is bound to the
|
||||||
|
// function lvalue that is the result of the conversion;
|
||||||
|
if (T2 instanceof ICPPClassType) {
|
||||||
|
Cost cost= initializationByConversionForDirectReference(cv1T1, cv2T2, (ICPPClassType) T2, true, ctx);
|
||||||
|
if (cost != null) {
|
||||||
|
cost.setReferenceBinding(refBindingType);
|
||||||
|
return cost;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// — otherwise, the program is ill-formed.
|
||||||
|
return Cost.NO_CONVERSION;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, if T2 is a class type and
|
||||||
|
if (T2 instanceof ICPPClassType) {
|
||||||
|
// ... the initializer expression is an rvalue and 'cv1 T1' is reference-compatible with 'cv2 T2'
|
||||||
|
// ..., then the reference is bound to the initializer expression rvalue in the first case
|
||||||
|
if (valueCat.isRValue()) {
|
||||||
|
Cost cost= isReferenceCompatible(cv1T1, cv2T2, isImpliedObject);
|
||||||
if (cost != null) {
|
if (cost != null) {
|
||||||
// [13.3.3.1.4-1] direct binding has either identity or conversion rank.
|
// [13.3.3.1.4-1] direct binding has either identity or conversion rank.
|
||||||
if (cost.getInheritanceDistance() > 0) {
|
if (cost.getInheritanceDistance() > 0) {
|
||||||
|
@ -167,13 +190,13 @@ public class Conversions {
|
||||||
}
|
}
|
||||||
|
|
||||||
// or T1 is not reference-related to T2 and the initializer expression can be implicitly
|
// or T1 is not reference-related to T2 and the initializer expression can be implicitly
|
||||||
// converted to an rvalue of type �cv3 T3� (this conversion is selected by enumerating the
|
// converted to an rvalue of type 'cv3 T3' (this conversion is selected by enumerating the
|
||||||
// applicable conversion functions (13.3.1.6) and choosing the best one through overload
|
// applicable conversion functions (13.3.1.6) and choosing the best one through overload
|
||||||
// resolution (13.3)), then the reference is bound to the initializer expression rvalue in the
|
// resolution (13.3)), then the reference is bound to the initializer expression rvalue in the
|
||||||
// first case and to the object that is the result of the conversion in the second case (or,
|
// first case and to the object that is the result of the conversion in the second case (or,
|
||||||
// in either case, to the appropriate base class subobject of the object).
|
// in either case, to the appropriate base class sub-object of the object).
|
||||||
if (udc != UDCMode.noUDC && isReferenceRelated(T1, T2) < 0) {
|
if (udc != UDCMode.FORBIDDEN && isReferenceRelated(T1, T2) < 0) {
|
||||||
Cost cost= conversionFuncForDirectReference(cv1T1, cv2T2, T2, false);
|
Cost cost= initializationByConversionForDirectReference(cv1T1, cv2T2, (ICPPClassType) T2, false, ctx);
|
||||||
if (cost != null) {
|
if (cost != null) {
|
||||||
cost.setReferenceBinding(refBindingType);
|
cost.setReferenceBinding(refBindingType);
|
||||||
return cost;
|
return cost;
|
||||||
|
@ -181,11 +204,11 @@ public class Conversions {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the initializer expression is an rvalue, with T2 an array type, and �cv1 T1� is
|
// If the initializer expression is an rvalue, with T2 an array type, and 'cv1 T1' is
|
||||||
// reference-compatible with �cv2 T2,� the reference is bound to the object represented by the
|
// reference-compatible with 'cv2 T2' the reference is bound to the object represented by the
|
||||||
// rvalue (see 3.10).
|
// rvalue (see 3.10).
|
||||||
if (!exprIsLValue && T2 instanceof IArrayType) {
|
if (T2 instanceof IArrayType && valueCat.isRValue()) {
|
||||||
Cost cost= isReferenceCompatible(cv1T1, cv2T2, isImpliedObjectType);
|
Cost cost= isReferenceCompatible(cv1T1, cv2T2, isImpliedObject);
|
||||||
if (cost != null) {
|
if (cost != null) {
|
||||||
cost.setReferenceBinding(refBindingType);
|
cost.setReferenceBinding(refBindingType);
|
||||||
return cost;
|
return cost;
|
||||||
|
@ -198,9 +221,9 @@ public class Conversions {
|
||||||
// as, or greater cv-qualification than, cv2; otherwise, the program is ill-formed.
|
// as, or greater cv-qualification than, cv2; otherwise, the program is ill-formed.
|
||||||
|
|
||||||
// 13.3.3.1.7 no temporary object when converting the implicit object parameter
|
// 13.3.3.1.7 no temporary object when converting the implicit object parameter
|
||||||
if (!isImpliedObjectType) {
|
if (!isImpliedObject) {
|
||||||
if (isReferenceRelated(T1, T2) < 0 || compareQualifications(cv1T1, cv2T2) >= 0) {
|
if (isReferenceRelated(T1, T2) < 0 || compareQualifications(cv1T1, cv2T2) >= 0) {
|
||||||
Cost cost= nonReferenceConversion(exprIsLValue, cv2T2, T1, udc, false);
|
Cost cost= nonReferenceConversion(valueCat, cv2T2, T1, udc, false);
|
||||||
if (!isImplicitWithoutRefQualifier && cost.converts()) {
|
if (!isImplicitWithoutRefQualifier && cost.converts()) {
|
||||||
cost.setReferenceBinding(isLValueRef ? ReferenceBinding.LVALUE_REF : ReferenceBinding.RVALUE_REF_BINDS_RVALUE);
|
cost.setReferenceBinding(isLValueRef ? ReferenceBinding.LVALUE_REF : ReferenceBinding.RVALUE_REF_BINDS_RVALUE);
|
||||||
}
|
}
|
||||||
|
@ -227,31 +250,36 @@ public class Conversions {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nonReferenceConversion(exprIsLValue, exprType, uqtarget, udc, isImpliedObjectType);
|
return nonReferenceConversion(valueCat, exprType, uqtarget, udc, isImpliedObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* C++0x: 13.3.1.6 Initialization by conversion function for direct reference binding
|
* C++0x: 13.3.1.6 Initialization by conversion function for direct reference binding
|
||||||
*/
|
*/
|
||||||
private static Cost conversionFuncForDirectReference(final IType cv1T1, final IType cv2T2, final IType T2, boolean forLValue)
|
private static Cost initializationByConversionForDirectReference(final IType cv1T1, final IType cv2T2, final ICPPClassType T2, boolean needLValue, Context ctx)
|
||||||
throws DOMException {
|
throws DOMException {
|
||||||
ICPPMethod[] fcns= SemanticUtil.getConversionOperators((ICPPClassType) T2);
|
ICPPMethod[] fcns= SemanticUtil.getConversionOperators(T2);
|
||||||
Cost operatorCost= null;
|
Cost operatorCost= null;
|
||||||
FunctionCost bestUdcCost= null;
|
FunctionCost bestUdcCost= null;
|
||||||
boolean ambiguousConversionOperator= false;
|
boolean ambiguousConversionOperator= false;
|
||||||
if (fcns.length > 0 && !(fcns[0] instanceof IProblemBinding)) {
|
if (fcns.length > 0 && !(fcns[0] instanceof IProblemBinding)) {
|
||||||
for (final ICPPMethod op : fcns) {
|
for (final ICPPMethod op : fcns) {
|
||||||
|
// Note: the special case of initializing a temporary to be bound to the first parameter
|
||||||
|
// of a copy constructor called with a single argument in the context of direct-initialization
|
||||||
|
// is (more naturally) handled here rather than in copyInitializationOfClass().
|
||||||
|
if (op.isExplicit() && ctx != Context.FIRST_PARAM_OF_DIRECT_COPY_CTOR)
|
||||||
|
continue;
|
||||||
final ICPPFunctionType ft = op.getType();
|
final ICPPFunctionType ft = op.getType();
|
||||||
IType convertedType= ft.getReturnType();
|
IType t= getNestedType(ft.getReturnType(), TDEF);
|
||||||
final boolean isLValue = CPPVisitor.isLValueReference(convertedType);
|
final boolean isLValueRef= t instanceof ICPPReferenceType && !((ICPPReferenceType) t).isRValueReference();
|
||||||
if (isLValue == forLValue) { // require an lvalue or rvalue
|
if (isLValueRef == needLValue) { // require an lvalue or rvalue
|
||||||
IType implicitObjectType= CPPSemantics.getImplicitParameterType(op, ft.isConst(), ft.isVolatile());
|
IType implicitParameterType= CPPSemantics.getImplicitParameterType(op, ft.isConst(), ft.isVolatile());
|
||||||
Cost udcCost= isReferenceCompatible(getNestedType(implicitObjectType, TDEF | REF), cv2T2, true); // expression type to implicit object type
|
Cost udcCost= isReferenceCompatible(getNestedType(implicitParameterType, TDEF | REF), cv2T2, true); // expression type to implicit object type
|
||||||
if (udcCost != null) {
|
if (udcCost != null) {
|
||||||
FunctionCost udcFuncCost= new FunctionCost(op, udcCost);
|
FunctionCost udcFuncCost= new FunctionCost(op, udcCost);
|
||||||
int cmp= udcFuncCost.compareTo(null, bestUdcCost);
|
int cmp= udcFuncCost.compareTo(null, bestUdcCost);
|
||||||
if (cmp <= 0) {
|
if (cmp <= 0) {
|
||||||
Cost cost= isReferenceCompatible(cv1T1, getNestedType(convertedType, TDEF | REF), false); // converted to target
|
Cost cost= isReferenceCompatible(cv1T1, getNestedType(t, TDEF | REF), false); // converted to target
|
||||||
if (cost != null) {
|
if (cost != null) {
|
||||||
bestUdcCost= udcFuncCost;
|
bestUdcCost= udcFuncCost;
|
||||||
ambiguousConversionOperator= cmp == 0;
|
ambiguousConversionOperator= cmp == 0;
|
||||||
|
@ -270,18 +298,43 @@ public class Conversions {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Cost nonReferenceConversion(boolean sourceIsLValue, IType source, IType target, UDCMode udc, boolean isImpliedObject) throws DOMException {
|
/**
|
||||||
// mstodo fix this to better match the specification
|
* 8.5-16
|
||||||
|
*/
|
||||||
|
private static Cost nonReferenceConversion(ValueCategory valueCat, IType source, IType target, UDCMode udc, boolean isImpliedObject) throws DOMException {
|
||||||
if (source instanceof InitializerListType) {
|
if (source instanceof InitializerListType) {
|
||||||
return listInitializationSequence(((InitializerListType) source), target, udc, false);
|
return listInitializationSequence(((InitializerListType) source), target, udc, false);
|
||||||
}
|
}
|
||||||
// [13.3.3.1-6] Subsume cv-qualifications
|
|
||||||
IType uqSource= SemanticUtil.getNestedType(source, TDEF | ALLCVQ);
|
|
||||||
Cost cost= checkStandardConversionSequence(uqSource, sourceIsLValue, target, isImpliedObject);
|
|
||||||
if (cost.converts() || udc == UDCMode.noUDC)
|
|
||||||
return cost;
|
|
||||||
|
|
||||||
return checkUserDefinedConversionSequence(sourceIsLValue, source, target, udc == UDCMode.deferUDC, false);
|
IType uqTarget= SemanticUtil.getNestedType(target, TDEF | REF | CVTYPE);
|
||||||
|
IType uqSource= SemanticUtil.getNestedType(source, TDEF | REF | CVTYPE);
|
||||||
|
if (uqTarget instanceof ICPPClassType) {
|
||||||
|
if (uqSource instanceof ICPPClassType) {
|
||||||
|
// 13.3.3.1-6 Conceptual derived to base conversion
|
||||||
|
int depth= calculateInheritanceDepth(uqTarget, uqSource);
|
||||||
|
if (depth >= 0) {
|
||||||
|
if (depth == 0) {
|
||||||
|
return new Cost(source, target, Rank.IDENTITY);
|
||||||
|
}
|
||||||
|
Cost cost= new Cost(source, target, Rank.CONVERSION);
|
||||||
|
cost.setInheritanceDistance(depth);
|
||||||
|
return cost;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (udc == UDCMode.FORBIDDEN)
|
||||||
|
return Cost.NO_CONVERSION;
|
||||||
|
|
||||||
|
return copyInitializationOfClass(valueCat, source, (ICPPClassType) uqTarget, udc == UDCMode.DEFER);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (uqSource instanceof ICPPClassType) {
|
||||||
|
if (udc == UDCMode.FORBIDDEN)
|
||||||
|
return Cost.NO_CONVERSION;
|
||||||
|
|
||||||
|
return initializationByConversion(valueCat, source, (ICPPClassType) uqSource, target, udc == UDCMode.DEFER);
|
||||||
|
}
|
||||||
|
|
||||||
|
return checkStandardConversionSequence(uqSource, target, isImpliedObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -291,11 +344,11 @@ public class Conversions {
|
||||||
IType listType= getInitListType(target);
|
IType listType= getInitListType(target);
|
||||||
if (listType != null) {
|
if (listType != null) {
|
||||||
IType[] exprTypes= arg.getExpressionTypes();
|
IType[] exprTypes= arg.getExpressionTypes();
|
||||||
BitSet isLValue= arg.getIsLValue();
|
ValueCategory[] valueCats= arg.getValueCategories();
|
||||||
Cost worstCost= new Cost(arg, target, Rank.IDENTITY);
|
Cost worstCost= new Cost(arg, target, Rank.IDENTITY);
|
||||||
for (int i = 0; i < exprTypes.length; i++) {
|
for (int i = 0; i < exprTypes.length; i++) {
|
||||||
IType exprType = exprTypes[i];
|
IType exprType = exprTypes[i];
|
||||||
Cost cost= checkImplicitConversionSequence(listType, exprType, isLValue.get(i), UDCMode.allowUDC, false);
|
Cost cost= checkImplicitConversionSequence(listType, exprType, valueCats[i], UDCMode.ALLOWED, Context.ORDINARY);
|
||||||
if (!cost.converts())
|
if (!cost.converts())
|
||||||
return cost;
|
return cost;
|
||||||
if (cost.isNarrowingConversion()) {
|
if (cost.isNarrowingConversion()) {
|
||||||
|
@ -311,7 +364,7 @@ public class Conversions {
|
||||||
|
|
||||||
IType noCVTarget= getNestedType(target, CVTYPE | TDEF);
|
IType noCVTarget= getNestedType(target, CVTYPE | TDEF);
|
||||||
if (noCVTarget instanceof ICPPClassType) {
|
if (noCVTarget instanceof ICPPClassType) {
|
||||||
if (udc == UDCMode.noUDC)
|
if (udc == UDCMode.FORBIDDEN)
|
||||||
return Cost.NO_CONVERSION;
|
return Cost.NO_CONVERSION;
|
||||||
|
|
||||||
ICPPClassType classTarget= (ICPPClassType) noCVTarget;
|
ICPPClassType classTarget= (ICPPClassType) noCVTarget;
|
||||||
|
@ -320,7 +373,7 @@ public class Conversions {
|
||||||
cost.setUserDefinedConversion(null);
|
cost.setUserDefinedConversion(null);
|
||||||
return cost;
|
return cost;
|
||||||
}
|
}
|
||||||
return checkUserDefinedConversionSequence(false, arg, target, udc == UDCMode.deferUDC, isDirect);
|
return listInitializationOfClass(arg, classTarget, isDirect, udc == UDCMode.DEFER);
|
||||||
}
|
}
|
||||||
|
|
||||||
IASTInitializerClause[] args = arg.getInitializerList().getClauses();
|
IASTInitializerClause[] args = arg.getInitializerList().getClauses();
|
||||||
|
@ -328,7 +381,7 @@ public class Conversions {
|
||||||
final IASTInitializerClause firstArg = args[0];
|
final IASTInitializerClause firstArg = args[0];
|
||||||
if (firstArg instanceof IASTExpression) {
|
if (firstArg instanceof IASTExpression) {
|
||||||
IASTExpression expr= (IASTExpression) firstArg;
|
IASTExpression expr= (IASTExpression) firstArg;
|
||||||
Cost cost= checkImplicitConversionSequence(target, expr.getExpressionType(), expr.isLValue(), udc, false);
|
Cost cost= checkImplicitConversionSequence(target, expr.getExpressionType(), expr.getValueCategory(), udc, Context.ORDINARY);
|
||||||
if (cost.isNarrowingConversion()) {
|
if (cost.isNarrowingConversion()) {
|
||||||
return Cost.NO_CONVERSION;
|
return Cost.NO_CONVERSION;
|
||||||
}
|
}
|
||||||
|
@ -484,10 +537,9 @@ public class Conversions {
|
||||||
* classes are nominated via using-declarations. In such a situation the derived to
|
* classes are nominated via using-declarations. In such a situation the derived to
|
||||||
* base conversion does not cause any costs.
|
* base conversion does not cause any costs.
|
||||||
*/
|
*/
|
||||||
private static final Cost checkStandardConversionSequence(IType source, boolean isLValue, IType target,
|
private static final Cost checkStandardConversionSequence(IType source, IType target, boolean isImplicitThis) {
|
||||||
boolean isImplicitThis) {
|
|
||||||
final Cost cost= new Cost(source, target, Rank.IDENTITY);
|
final Cost cost= new Cost(source, target, Rank.IDENTITY);
|
||||||
if (lvalue_to_rvalue(cost, isLValue))
|
if (lvalue_to_rvalue(cost))
|
||||||
return cost;
|
return cost;
|
||||||
|
|
||||||
if (promotion(cost))
|
if (promotion(cost))
|
||||||
|
@ -504,40 +556,14 @@ public class Conversions {
|
||||||
return cost;
|
return cost;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
// 13.3.1.7 Initialization by list-initialization
|
||||||
* [13.3.3.1.2] User-defined conversions
|
static Cost listInitializationOfClass(InitializerListType arg, ICPPClassType t, boolean isDirect, boolean deferUDC) throws DOMException {
|
||||||
*/
|
|
||||||
static final Cost checkUserDefinedConversionSequence(boolean sourceIsLValue, IType source, IType target, boolean deferUDC, boolean isDirect) throws DOMException {
|
|
||||||
IType s= getNestedType(source, TDEF | CVTYPE | REF);
|
|
||||||
IType t= getNestedType(target, TDEF | CVTYPE | REF);
|
|
||||||
|
|
||||||
if (!(s instanceof ICPPClassType || t instanceof ICPPClassType)) {
|
|
||||||
return Cost.NO_CONVERSION;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (deferUDC) {
|
if (deferUDC) {
|
||||||
Cost c= new Cost(source, target, Rank.USER_DEFINED_CONVERSION);
|
Cost c= new Cost(arg, t, Rank.USER_DEFINED_CONVERSION);
|
||||||
c.setDeferredUDC(true);
|
c.setDeferredUDC(isDirect ? DeferredUDC.DIRECT_LIST_INIT_OF_CLASS : DeferredUDC.LIST_INIT_OF_CLASS);
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (t instanceof ICPPClassType) {
|
|
||||||
if (s instanceof InitializerListType) {
|
|
||||||
// 13.3.1.7 Initialization by list-initialization
|
|
||||||
return listInitializationOfClass((InitializerListType) s, (ICPPClassType) t, isDirect);
|
|
||||||
}
|
|
||||||
// 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, isDirect);
|
|
||||||
}
|
|
||||||
return Cost.NO_CONVERSION;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Cost listInitializationOfClass(InitializerListType arg, ICPPClassType t, boolean isDirect) throws DOMException {
|
|
||||||
// If T has an initializer-list constructor
|
// If T has an initializer-list constructor
|
||||||
ICPPConstructor usedCtor= null;
|
ICPPConstructor usedCtor= null;
|
||||||
Cost bestCost= null;
|
Cost bestCost= null;
|
||||||
|
@ -551,7 +577,7 @@ public class Conversions {
|
||||||
final IType target = parTypes[0];
|
final IType target = parTypes[0];
|
||||||
if (getInitListType(target) != null) {
|
if (getInitListType(target) != null) {
|
||||||
hasInitListConstructor= true;
|
hasInitListConstructor= true;
|
||||||
Cost cost= listInitializationSequence(arg, target, UDCMode.noUDC, isDirect);
|
Cost cost= listInitializationSequence(arg, target, UDCMode.FORBIDDEN, isDirect);
|
||||||
if (cost.converts()) {
|
if (cost.converts()) {
|
||||||
int cmp= cost.compareTo(bestCost);
|
int cmp= cost.compareTo(bestCost);
|
||||||
if (bestCost == null || cmp < 0) {
|
if (bestCost == null || cmp < 0) {
|
||||||
|
@ -624,14 +650,22 @@ public class Conversions {
|
||||||
/**
|
/**
|
||||||
* 13.3.1.4 Copy-initialization of class by user-defined conversion [over.match.copy]
|
* 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,
|
static final Cost copyInitializationOfClass(ValueCategory valueCat, IType source, ICPPClassType t, boolean deferUDC) throws DOMException {
|
||||||
ICPPClassType t) throws DOMException {
|
if (deferUDC) {
|
||||||
|
Cost c= new Cost(source, t, Rank.USER_DEFINED_CONVERSION);
|
||||||
|
c.setDeferredUDC(DeferredUDC.COPY_INIT_OF_CLASS);
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
FunctionCost cost1= null;
|
FunctionCost cost1= null;
|
||||||
Cost cost2= null;
|
Cost cost2= null;
|
||||||
ICPPConstructor[] ctors= t.getConstructors();
|
ICPPConstructor[] ctors= t.getConstructors();
|
||||||
CPPTemplates.instantiateFunctionTemplates(ctors, new IType[]{source}, sourceIsLValue ? LVBITSET : RVBITSET, null, false);
|
CPPTemplates.instantiateFunctionTemplates(ctors, new IType[]{source}, new ValueCategory[] {valueCat}, null, false);
|
||||||
|
|
||||||
for (ICPPConstructor ctor : ctors) {
|
for (ICPPConstructor ctor : ctors) {
|
||||||
|
// Note: the special case of initializing a temporary to be bound to the first parameter
|
||||||
|
// of a copy constructor called with a single argument in the context of direct-initialization
|
||||||
|
// is (more naturally) handled in initializationByConversionForDirectReference.
|
||||||
if (ctor != null && !(ctor instanceof IProblemBinding) && !ctor.isExplicit()) {
|
if (ctor != null && !(ctor instanceof IProblemBinding) && !ctor.isExplicit()) {
|
||||||
final ICPPFunctionType ft = ctor.getType();
|
final ICPPFunctionType ft = ctor.getType();
|
||||||
final IType[] ptypes = ft.getParameterTypes();
|
final IType[] ptypes = ft.getParameterTypes();
|
||||||
|
@ -650,7 +684,7 @@ public class Conversions {
|
||||||
if (ctor.getRequiredArgumentCount() > 1)
|
if (ctor.getRequiredArgumentCount() > 1)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
c1= new FunctionCost(ctor, checkImplicitConversionSequence(ptype, source, sourceIsLValue, UDCMode.noUDC, false));
|
c1= new FunctionCost(ctor, checkImplicitConversionSequence(ptype, source, valueCat, UDCMode.FORBIDDEN, Context.ORDINARY));
|
||||||
}
|
}
|
||||||
int cmp= c1.compareTo(null, cost1);
|
int cmp= c1.compareTo(null, cost1);
|
||||||
if (cmp <= 0) {
|
if (cmp <= 0) {
|
||||||
|
@ -663,9 +697,11 @@ public class Conversions {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (s instanceof ICPPClassType) {
|
|
||||||
ICPPMethod[] ops = SemanticUtil.getConversionOperators((ICPPClassType) s);
|
final IType uqSource= getNestedType(source, TDEF | REF | CVTYPE);
|
||||||
CPPTemplates.instantiateConversionTemplates(ops, target);
|
if (uqSource instanceof ICPPClassType) {
|
||||||
|
ICPPMethod[] ops = SemanticUtil.getConversionOperators((ICPPClassType) uqSource);
|
||||||
|
CPPTemplates.instantiateConversionTemplates(ops, t);
|
||||||
for (final ICPPMethod op : ops) {
|
for (final ICPPMethod op : ops) {
|
||||||
if (op != null && !(op instanceof IProblemBinding)) {
|
if (op != null && !(op instanceof IProblemBinding)) {
|
||||||
if (op.isExplicit())
|
if (op.isExplicit())
|
||||||
|
@ -706,22 +742,25 @@ public class Conversions {
|
||||||
/**
|
/**
|
||||||
* 13.3.1.5 Initialization by conversion function [over.match.conv]
|
* 13.3.1.5 Initialization by conversion function [over.match.conv]
|
||||||
*/
|
*/
|
||||||
private static Cost initializationByConversion(IType source, ICPPClassType s, IType target, boolean direct) throws DOMException {
|
static Cost initializationByConversion(ValueCategory valueCat, IType source, ICPPClassType uqSource, IType target, boolean deferUDC) throws DOMException {
|
||||||
ICPPMethod[] ops = SemanticUtil.getConversionOperators(s);
|
if (deferUDC) {
|
||||||
|
Cost c= new Cost(source, target, Rank.USER_DEFINED_CONVERSION);
|
||||||
|
c.setDeferredUDC(DeferredUDC.INIT_BY_CONVERSION);
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
ICPPMethod[] ops = SemanticUtil.getConversionOperators(uqSource);
|
||||||
CPPTemplates.instantiateConversionTemplates(ops, target);
|
CPPTemplates.instantiateConversionTemplates(ops, target);
|
||||||
FunctionCost cost1= null;
|
FunctionCost cost1= null;
|
||||||
Cost cost2= null;
|
Cost cost2= null;
|
||||||
for (final ICPPMethod op : ops) {
|
for (final ICPPMethod op : ops) {
|
||||||
if (op != null && !(op instanceof IProblemBinding)) {
|
if (op != null && !(op instanceof IProblemBinding)) {
|
||||||
final boolean isExplicitConversion= op.isExplicit();
|
final boolean isExplicitConversion= op.isExplicit();
|
||||||
if (isExplicitConversion && !direct)
|
if (isExplicitConversion /** && !direct **/)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
final IType returnType = op.getType().getReturnType();
|
final IType returnType = op.getType().getReturnType();
|
||||||
IType uqReturnType= getNestedType(returnType, TDEF | ALLCVQ);
|
IType uqReturnType= getNestedType(returnType, TDEF | ALLCVQ);
|
||||||
boolean isLValue = uqReturnType instanceof ICPPReferenceType
|
Cost c2= checkImplicitConversionSequence(target, uqReturnType, valueCategoryFromReturnType(uqReturnType), UDCMode.FORBIDDEN, Context.ORDINARY);
|
||||||
&& !((ICPPReferenceType) uqReturnType).isRValueReference();
|
|
||||||
Cost c2= checkImplicitConversionSequence(target, uqReturnType, isLValue, UDCMode.noUDC, false);
|
|
||||||
if (c2.converts()) {
|
if (c2.converts()) {
|
||||||
if (isExplicitConversion && c2.getRank() != Rank.IDENTITY)
|
if (isExplicitConversion && c2.getRank() != Rank.IDENTITY)
|
||||||
continue;
|
continue;
|
||||||
|
@ -756,33 +795,15 @@ public class Conversions {
|
||||||
* [4.2] array-to-ptr
|
* [4.2] array-to-ptr
|
||||||
* [4.3] function-to-ptr
|
* [4.3] function-to-ptr
|
||||||
*/
|
*/
|
||||||
private static final boolean lvalue_to_rvalue(final Cost cost, boolean isLValue) {
|
private static final boolean lvalue_to_rvalue(final Cost cost) {
|
||||||
// mstodo request value category
|
IType target = getNestedType(cost.target, REF | TDEF | ALLCVQ);
|
||||||
// target should not be a reference here.
|
IType source= getNestedType(cost.source, REF | TDEF | ALLCVQ);
|
||||||
boolean isConverted= false;
|
|
||||||
IType target = getNestedType(cost.target, REF | TDEF);
|
|
||||||
IType source= getNestedType(cost.source, REF | TDEF);
|
|
||||||
|
|
||||||
// 4.1 lvalue to rvalue
|
|
||||||
if (isLValue) {
|
|
||||||
// 4.1 lvalue of non-function and non-array
|
|
||||||
if (!(source instanceof IFunctionType) && !(source instanceof IArrayType)) {
|
|
||||||
// 4.1 if T is a non-class type, the type of the rvalue is the cv-unqualified version of T
|
|
||||||
IType unqualifiedSrcRValue= getNestedType(source, ALLCVQ | TDEF | REF);
|
|
||||||
if (unqualifiedSrcRValue instanceof ICPPClassType) {
|
|
||||||
cost.setRank(Rank.NO_MATCH);
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
source= unqualifiedSrcRValue;
|
|
||||||
}
|
|
||||||
isConverted= true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 4.2 array to pointer conversion
|
// 4.2 array to pointer conversion
|
||||||
if (!isConverted && source instanceof IArrayType) {
|
if (source instanceof IArrayType) {
|
||||||
final IArrayType arrayType= (IArrayType) source;
|
final IArrayType arrayType= (IArrayType) source;
|
||||||
|
|
||||||
|
boolean isConverted= false;
|
||||||
if (target instanceof IPointerType) {
|
if (target instanceof IPointerType) {
|
||||||
final IType targetPtrTgt= getNestedType(((IPointerType) target).getType(), TDEF);
|
final IType targetPtrTgt= getNestedType(((IPointerType) target).getType(), TDEF);
|
||||||
|
|
||||||
|
@ -807,16 +828,12 @@ public class Conversions {
|
||||||
}
|
}
|
||||||
if (!isConverted && (target instanceof IPointerType || target instanceof IBasicType)) {
|
if (!isConverted && (target instanceof IPointerType || target instanceof IBasicType)) {
|
||||||
source = new CPPPointerType(getNestedType(arrayType.getType(), TDEF));
|
source = new CPPPointerType(getNestedType(arrayType.getType(), TDEF));
|
||||||
isConverted= true;
|
|
||||||
}
|
}
|
||||||
}
|
} else if (target instanceof IPointerType) {
|
||||||
|
// 4.3 function to pointer conversion
|
||||||
// 4.3 function to pointer conversion
|
|
||||||
if (!isConverted && target instanceof IPointerType) {
|
|
||||||
final IType targetPtrTgt= getNestedType(((IPointerType) target).getType(), TDEF);
|
final IType targetPtrTgt= getNestedType(((IPointerType) target).getType(), TDEF);
|
||||||
if (targetPtrTgt instanceof IFunctionType && source instanceof IFunctionType) {
|
if (targetPtrTgt instanceof IFunctionType && source instanceof IFunctionType) {
|
||||||
source = new CPPPointerType(source);
|
source = new CPPPointerType(source);
|
||||||
isConverted= true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,9 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPBasicType;
|
||||||
* See [over.best.ics] 13.3.3.1.
|
* See [over.best.ics] 13.3.3.1.
|
||||||
*/
|
*/
|
||||||
class Cost {
|
class Cost {
|
||||||
|
public enum DeferredUDC {
|
||||||
|
NONE, COPY_INIT_OF_CLASS, INIT_BY_CONVERSION, LIST_INIT_OF_CLASS, DIRECT_LIST_INIT_OF_CLASS
|
||||||
|
}
|
||||||
enum Rank {
|
enum Rank {
|
||||||
IDENTITY, PROMOTION, CONVERSION, CONVERSION_PTR_BOOL,
|
IDENTITY, PROMOTION, CONVERSION, CONVERSION_PTR_BOOL,
|
||||||
USER_DEFINED_CONVERSION, ELLIPSIS_CONVERSION, NO_MATCH
|
USER_DEFINED_CONVERSION, ELLIPSIS_CONVERSION, NO_MATCH
|
||||||
|
@ -52,7 +55,7 @@ class Cost {
|
||||||
assert false;
|
assert false;
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public void setDeferredUDC(boolean val) {
|
public void setDeferredUDC(DeferredUDC val) {
|
||||||
assert false;
|
assert false;
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
|
@ -79,7 +82,7 @@ class Cost {
|
||||||
private Rank fRank;
|
private Rank fRank;
|
||||||
private Rank fSecondStandardConversionRank;
|
private Rank fSecondStandardConversionRank;
|
||||||
private boolean fAmbiguousUDC;
|
private boolean fAmbiguousUDC;
|
||||||
private boolean fDeferredUDC;
|
private DeferredUDC fDeferredUDC= DeferredUDC.NONE;
|
||||||
private int fQualificationAdjustments;
|
private int fQualificationAdjustments;
|
||||||
private int fInheritanceDistance;
|
private int fInheritanceDistance;
|
||||||
private ICPPFunction fUserDefinedConversion;
|
private ICPPFunction fUserDefinedConversion;
|
||||||
|
@ -119,12 +122,12 @@ class Cost {
|
||||||
fAmbiguousUDC= val;
|
fAmbiguousUDC= val;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isDeferredUDC() {
|
public DeferredUDC isDeferredUDC() {
|
||||||
return fDeferredUDC;
|
return fDeferredUDC;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setDeferredUDC(boolean val) {
|
public void setDeferredUDC(DeferredUDC udc) {
|
||||||
fDeferredUDC= val;
|
fDeferredUDC= udc;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getInheritanceDistance() {
|
public int getInheritanceDistance() {
|
||||||
|
@ -160,7 +163,7 @@ class Cost {
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
// cannot compare costs with deferred user defined conversions
|
// cannot compare costs with deferred user defined conversions
|
||||||
assert !fDeferredUDC && !other.fDeferredUDC;
|
assert fDeferredUDC == DeferredUDC.NONE && other.fDeferredUDC == DeferredUDC.NONE;
|
||||||
|
|
||||||
int cmp= fRank.compareTo(other.fRank);
|
int cmp= fRank.compareTo(other.fRank);
|
||||||
if (cmp != 0)
|
if (cmp != 0)
|
||||||
|
@ -218,8 +221,8 @@ class Cost {
|
||||||
buf.append(comma).append("inheritance=").append(fInheritanceDistance);
|
buf.append(comma).append("inheritance=").append(fInheritanceDistance);
|
||||||
comma= ", ";
|
comma= ", ";
|
||||||
}
|
}
|
||||||
if (fDeferredUDC) {
|
if (fDeferredUDC != DeferredUDC.NONE) {
|
||||||
buf.append(comma).append("deferred UDC");
|
buf.append(comma).append(fDeferredUDC);
|
||||||
comma= ", ";
|
comma= ", ";
|
||||||
}
|
}
|
||||||
if (fAmbiguousUDC) {
|
if (fAmbiguousUDC) {
|
||||||
|
|
|
@ -10,13 +10,17 @@
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics;
|
package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics;
|
||||||
|
|
||||||
import java.util.BitSet;
|
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.*;
|
||||||
|
|
||||||
import org.eclipse.cdt.core.dom.ast.DOMException;
|
import org.eclipse.cdt.core.dom.ast.DOMException;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory;
|
||||||
import org.eclipse.cdt.core.dom.ast.IBinding;
|
import org.eclipse.cdt.core.dom.ast.IBinding;
|
||||||
import org.eclipse.cdt.core.dom.ast.IFunction;
|
import org.eclipse.cdt.core.dom.ast.IFunction;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IType;
|
||||||
|
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.ICPPFunctionTemplate;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPSpecialization;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPSpecialization;
|
||||||
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.Cost.DeferredUDC;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cost for the entire function call
|
* Cost for the entire function call
|
||||||
|
@ -24,18 +28,18 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPSpecialization;
|
||||||
class FunctionCost {
|
class FunctionCost {
|
||||||
private final IFunction fFunction;
|
private final IFunction fFunction;
|
||||||
private final Cost[] fCosts;
|
private final Cost[] fCosts;
|
||||||
private final BitSet fSourceIsLValue;
|
private final ValueCategory[] fValueCategories;
|
||||||
|
|
||||||
public FunctionCost(IFunction fn, int paramCount) {
|
public FunctionCost(IFunction fn, int paramCount) {
|
||||||
fFunction= fn;
|
fFunction= fn;
|
||||||
fCosts= new Cost[paramCount];
|
fCosts= new Cost[paramCount];
|
||||||
fSourceIsLValue= new BitSet(paramCount);
|
fValueCategories= new ValueCategory[paramCount];
|
||||||
}
|
}
|
||||||
|
|
||||||
public FunctionCost(IFunction fn, Cost cost) {
|
public FunctionCost(IFunction fn, Cost cost) {
|
||||||
fFunction= fn;
|
fFunction= fn;
|
||||||
fCosts= new Cost[] {cost};
|
fCosts= new Cost[] {cost};
|
||||||
fSourceIsLValue= null; // no udc will be performed
|
fValueCategories= null; // no udc will be performed
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getLength() {
|
public int getLength() {
|
||||||
|
@ -46,9 +50,9 @@ class FunctionCost {
|
||||||
return fCosts[idx];
|
return fCosts[idx];
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCost(int idx, Cost cost, boolean sourceIsLValue) {
|
public void setCost(int idx, Cost cost, ValueCategory valueCat) {
|
||||||
fCosts[idx]= cost;
|
fCosts[idx]= cost;
|
||||||
fSourceIsLValue.set(idx, sourceIsLValue);
|
fValueCategories[idx]= valueCat;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IFunction getFunction() {
|
public IFunction getFunction() {
|
||||||
|
@ -67,7 +71,7 @@ class FunctionCost {
|
||||||
for (Cost cost : fCosts) {
|
for (Cost cost : fCosts) {
|
||||||
if (!cost.converts())
|
if (!cost.converts())
|
||||||
return false;
|
return false;
|
||||||
if (cost.isDeferredUDC())
|
if (cost.isDeferredUDC() != DeferredUDC.NONE)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -76,13 +80,33 @@ class FunctionCost {
|
||||||
public boolean performUDC() throws DOMException {
|
public boolean performUDC() throws DOMException {
|
||||||
for (int i = 0; i < fCosts.length; i++) {
|
for (int i = 0; i < fCosts.length; i++) {
|
||||||
Cost cost = fCosts[i];
|
Cost cost = fCosts[i];
|
||||||
if (cost.isDeferredUDC()) {
|
Cost udcCost= null;
|
||||||
Cost udcCost = Conversions.checkUserDefinedConversionSequence(fSourceIsLValue.get(i),
|
switch(cost.isDeferredUDC()) {
|
||||||
cost.source, cost.target, false, false);
|
case NONE:
|
||||||
fCosts[i] = udcCost;
|
continue;
|
||||||
if (!udcCost.converts()) {
|
case COPY_INIT_OF_CLASS:
|
||||||
return false;
|
udcCost = Conversions.copyInitializationOfClass(fValueCategories[i], cost.source,
|
||||||
}
|
(ICPPClassType) cost.target, false);
|
||||||
|
break;
|
||||||
|
case INIT_BY_CONVERSION:
|
||||||
|
IType uqSource= getNestedType(cost.source, TDEF | REF | CVTYPE);
|
||||||
|
udcCost = Conversions.initializationByConversion(fValueCategories[i], cost.source,
|
||||||
|
(ICPPClassType) uqSource, cost.target, false);
|
||||||
|
break;
|
||||||
|
case LIST_INIT_OF_CLASS:
|
||||||
|
udcCost = Conversions.listInitializationOfClass((InitializerListType) cost.source,
|
||||||
|
(ICPPClassType) cost.target, false, false);
|
||||||
|
break;
|
||||||
|
case DIRECT_LIST_INIT_OF_CLASS:
|
||||||
|
udcCost = Conversions.listInitializationOfClass((InitializerListType) cost.source,
|
||||||
|
(ICPPClassType) cost.target, true, false);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
fCosts[i] = udcCost;
|
||||||
|
if (!udcCost.converts()) {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -163,7 +187,7 @@ class FunctionCost {
|
||||||
Cost otherCost= other.getCost(idxOther);
|
Cost otherCost= other.getCost(idxOther);
|
||||||
|
|
||||||
int cmp;
|
int cmp;
|
||||||
if (cost.isDeferredUDC()) {
|
if (cost.isDeferredUDC() != DeferredUDC.NONE) {
|
||||||
cmp= cost.getRank().compareTo(otherCost.getRank());
|
cmp= cost.getRank().compareTo(otherCost.getRank());
|
||||||
} else {
|
} else {
|
||||||
cmp= cost.compareTo(otherCost);
|
cmp= cost.compareTo(otherCost);
|
||||||
|
|
|
@ -10,9 +10,8 @@
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics;
|
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.IASTExpression;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTInitializerClause;
|
import org.eclipse.cdt.core.dom.ast.IASTInitializerClause;
|
||||||
import org.eclipse.cdt.core.dom.ast.IType;
|
import org.eclipse.cdt.core.dom.ast.IType;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTInitializerList;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTInitializerList;
|
||||||
|
@ -24,7 +23,7 @@ class InitializerListType implements IType {
|
||||||
|
|
||||||
private final ICPPASTInitializerList fInitializerList;
|
private final ICPPASTInitializerList fInitializerList;
|
||||||
private IType[] fExpressionTypes;
|
private IType[] fExpressionTypes;
|
||||||
private BitSet fLValues;
|
private ValueCategory[] fLValues;
|
||||||
|
|
||||||
public InitializerListType(ICPPASTInitializerList list) {
|
public InitializerListType(ICPPASTInitializerList list) {
|
||||||
fInitializerList= list;
|
fInitializerList= list;
|
||||||
|
@ -66,16 +65,14 @@ class InitializerListType implements IType {
|
||||||
return fExpressionTypes;
|
return fExpressionTypes;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BitSet getIsLValue() {
|
public ValueCategory[] getValueCategories() {
|
||||||
if (fLValues == null) {
|
if (fLValues == null) {
|
||||||
final IASTInitializerClause[] clauses = fInitializerList.getClauses();
|
final IASTInitializerClause[] clauses = fInitializerList.getClauses();
|
||||||
fLValues= new BitSet(clauses.length);
|
fLValues= new ValueCategory[clauses.length];
|
||||||
for (int i = 0; i < clauses.length; i++) {
|
for (int i = 0; i < clauses.length; i++) {
|
||||||
IASTInitializerClause clause = clauses[i];
|
IASTInitializerClause clause = clauses[i];
|
||||||
if (clause instanceof IASTExpression) {
|
if (clause instanceof IASTExpression) {
|
||||||
if (((IASTExpression) clause).isLValue()) {
|
fLValues[i]= ((IASTExpression) clause).getValueCategory();
|
||||||
fLValues.set(i);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,8 @@
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics;
|
package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics;
|
||||||
|
|
||||||
import java.util.BitSet;
|
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExpressionTypes.valueCategoryFromReturnType;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -25,6 +26,7 @@ import org.eclipse.cdt.core.dom.ast.IASTCompositeTypeSpecifier;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
|
import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTDeclarator;
|
import org.eclipse.cdt.core.dom.ast.IASTDeclarator;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTExpression;
|
import org.eclipse.cdt.core.dom.ast.IASTExpression;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTFieldReference;
|
import org.eclipse.cdt.core.dom.ast.IASTFieldReference;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTFunctionCallExpression;
|
import org.eclipse.cdt.core.dom.ast.IASTFunctionCallExpression;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition;
|
import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition;
|
||||||
|
@ -60,7 +62,6 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassScope;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespaceScope;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespaceScope;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPReferenceType;
|
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPUsingDeclaration;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPUsingDeclaration;
|
||||||
import org.eclipse.cdt.core.parser.util.ArrayUtil;
|
import org.eclipse.cdt.core.parser.util.ArrayUtil;
|
||||||
import org.eclipse.cdt.core.parser.util.CharArrayObjectMap;
|
import org.eclipse.cdt.core.parser.util.CharArrayObjectMap;
|
||||||
|
@ -103,7 +104,7 @@ public class LookupData {
|
||||||
private ICPPASTParameterDeclaration[] functionParameters;
|
private ICPPASTParameterDeclaration[] functionParameters;
|
||||||
private IASTInitializerClause[] functionArgs;
|
private IASTInitializerClause[] functionArgs;
|
||||||
private IType[] functionArgTypes;
|
private IType[] functionArgTypes;
|
||||||
private BitSet functionArgLValues;
|
private ValueCategory[] functionArgValueCategories;
|
||||||
|
|
||||||
public ICPPClassType skippedScope;
|
public ICPPClassType skippedScope;
|
||||||
public Object foundItems = null;
|
public Object foundItems = null;
|
||||||
|
@ -526,40 +527,37 @@ public class LookupData {
|
||||||
return functionArgTypes;
|
return functionArgTypes;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BitSet getFunctionArgumentLValues() {
|
public ValueCategory[] getFunctionArgumentValueCategories() {
|
||||||
if (functionArgLValues == null) {
|
if (functionArgValueCategories == null) {
|
||||||
functionArgLValues= new BitSet();
|
IASTInitializerClause[] args= functionArgs;
|
||||||
IASTInitializerClause[] args= getFunctionArguments();
|
|
||||||
if (args != null) {
|
if (args != null) {
|
||||||
|
functionArgValueCategories= new ValueCategory[args.length];
|
||||||
for (int i = 0; i < args.length; i++) {
|
for (int i = 0; i < args.length; i++) {
|
||||||
final IASTInitializerClause arg = args[i];
|
final IASTInitializerClause arg = args[i];
|
||||||
if (arg instanceof IASTExpression) {
|
if (arg instanceof IASTExpression) {
|
||||||
functionArgLValues.set(i, ((IASTExpression) arg).isLValue());
|
functionArgValueCategories[i]= ((IASTExpression) arg).getValueCategory();
|
||||||
} else {
|
|
||||||
functionArgLValues.set(i, false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
IType[] argTypes= getFunctionArgumentTypes();
|
IType[] argTypes= getFunctionArgumentTypes();
|
||||||
if (argTypes != null) {
|
if (argTypes != null) {
|
||||||
|
functionArgValueCategories= new ValueCategory[argTypes.length];
|
||||||
for (int i = 0; i < argTypes.length; i++) {
|
for (int i = 0; i < argTypes.length; i++) {
|
||||||
IType t= argTypes[i];
|
IType t= argTypes[i];
|
||||||
functionArgLValues.set(i, t instanceof ICPPReferenceType && !((ICPPReferenceType) t).isRValueReference());
|
functionArgValueCategories[i]= valueCategoryFromReturnType(t);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
functionArgValueCategories= new ValueCategory[0];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return functionArgLValues;
|
return functionArgValueCategories;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setFunctionParameters(ICPPASTParameterDeclaration[] parameters) {
|
public void setFunctionParameters(ICPPASTParameterDeclaration[] parameters) {
|
||||||
functionParameters= parameters;
|
functionParameters= parameters;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IASTInitializerClause[] getFunctionArguments() {
|
|
||||||
return functionArgs;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getFunctionArgumentCount() {
|
public int getFunctionArgumentCount() {
|
||||||
if (functionArgs != null)
|
if (functionArgs != null)
|
||||||
return functionArgs.length;
|
return functionArgs.length;
|
||||||
|
|
|
@ -10,16 +10,17 @@
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics;
|
package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics;
|
||||||
|
|
||||||
|
import static org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory.LVALUE;
|
||||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.*;
|
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.*;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.BitSet;
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.eclipse.cdt.core.dom.ast.DOMException;
|
import org.eclipse.cdt.core.dom.ast.DOMException;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory;
|
||||||
import org.eclipse.cdt.core.dom.ast.IArrayType;
|
import org.eclipse.cdt.core.dom.ast.IArrayType;
|
||||||
import org.eclipse.cdt.core.dom.ast.IBasicType;
|
import org.eclipse.cdt.core.dom.ast.IBasicType;
|
||||||
import org.eclipse.cdt.core.dom.ast.IBinding;
|
import org.eclipse.cdt.core.dom.ast.IBinding;
|
||||||
|
@ -60,7 +61,7 @@ public class TemplateArgumentDeduction {
|
||||||
* 14.8.2.1
|
* 14.8.2.1
|
||||||
*/
|
*/
|
||||||
static ICPPTemplateArgument[] deduceForFunctionCall(ICPPFunctionTemplate template,
|
static ICPPTemplateArgument[] deduceForFunctionCall(ICPPFunctionTemplate template,
|
||||||
ICPPTemplateArgument[] tmplArgs, IType[] fnArgs, BitSet argIsLValue, CPPTemplateParameterMap map)
|
ICPPTemplateArgument[] tmplArgs, IType[] fnArgs, ValueCategory[] argIsLValue, CPPTemplateParameterMap map)
|
||||||
throws DOMException {
|
throws DOMException {
|
||||||
final ICPPTemplateParameter[] tmplParams = template.getTemplateParameters();
|
final ICPPTemplateParameter[] tmplParams = template.getTemplateParameters();
|
||||||
final int numTmplParams = tmplParams.length;
|
final int numTmplParams = tmplParams.length;
|
||||||
|
@ -151,7 +152,7 @@ public class TemplateArgumentDeduction {
|
||||||
* Deduces the mapping for the template parameters from the function parameters,
|
* Deduces the mapping for the template parameters from the function parameters,
|
||||||
* returns <code>false</code> if there is no mapping.
|
* returns <code>false</code> if there is no mapping.
|
||||||
*/
|
*/
|
||||||
static boolean deduceFromFunctionArgs(ICPPFunctionTemplate template, IType[] fnArgs, BitSet argIsLValue,
|
static boolean deduceFromFunctionArgs(ICPPFunctionTemplate template, IType[] fnArgs, ValueCategory[] argIsLValue,
|
||||||
CPPTemplateParameterMap map, boolean checkExactMatch) {
|
CPPTemplateParameterMap map, boolean checkExactMatch) {
|
||||||
try {
|
try {
|
||||||
IType[] fnPars = template.getType().getParameterTypes();
|
IType[] fnPars = template.getType().getParameterTypes();
|
||||||
|
@ -214,7 +215,8 @@ public class TemplateArgumentDeduction {
|
||||||
// lvalue, the type "lvalue reference to A" is used in place of A for type deduction.
|
// lvalue, the type "lvalue reference to A" is used in place of A for type deduction.
|
||||||
isReferenceTypeParameter= true;
|
isReferenceTypeParameter= true;
|
||||||
final ICPPReferenceType refPar = (ICPPReferenceType) par;
|
final ICPPReferenceType refPar = (ICPPReferenceType) par;
|
||||||
if (refPar.isRValueReference() && refPar.getType() instanceof ICPPTemplateParameter && argIsLValue.get(j)) {
|
if (refPar.isRValueReference() && refPar.getType() instanceof ICPPTemplateParameter &&
|
||||||
|
argIsLValue != null && argIsLValue[j] == LVALUE) {
|
||||||
arg= new CPPReferenceType(getSimplifiedType(arg), false);
|
arg= new CPPReferenceType(getSimplifiedType(arg), false);
|
||||||
} else {
|
} else {
|
||||||
arg= getArgumentTypeForDeduction(arg, true);
|
arg= getArgumentTypeForDeduction(arg, true);
|
||||||
|
|
Loading…
Add table
Reference in a new issue