mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-07-23 17:05:26 +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.IASTFunctionDefinition;
|
||||
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.IASTLabelStatement;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTLiteralExpression;
|
||||
|
@ -8915,4 +8916,25 @@ public class AST2CPPTests extends AST2BaseTest {
|
|||
bh.assertProblem("fint(pe + pe);", 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() {
|
||||
IASTExpression positiveExpression = getPositiveResultExpression();
|
||||
if (positiveExpression == null) {
|
||||
|
@ -147,7 +147,7 @@ public class CPPASTConditionalExpression extends ASTNode implements IASTConditio
|
|||
return t2;
|
||||
}
|
||||
|
||||
// mstodo
|
||||
// mstodo conditional operator (value category)
|
||||
public ValueCategory getValueCategory() {
|
||||
return PRVALUE;
|
||||
}
|
||||
|
|
|
@ -15,10 +15,11 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics;
|
||||
|
||||
import static org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory.LVALUE;
|
||||
import static org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory.PRVALUE;
|
||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.BitSet;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
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.IASTEqualsInitializer;
|
||||
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.IASTFunctionCallExpression;
|
||||
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.ICPPParameter;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPPointerToMemberType;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPReferenceType;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPScope;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPSpecialization;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateArgument;
|
||||
|
@ -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.ICPPUnknownType;
|
||||
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.Cost.Rank;
|
||||
import org.eclipse.cdt.internal.core.index.IIndexScope;
|
||||
|
@ -2288,7 +2292,7 @@ public class CPPSemantics {
|
|||
}
|
||||
|
||||
if (!isFuncDecl || data.forExplicitFunctionSpecialization()) {
|
||||
CPPTemplates.instantiateFunctionTemplates(fns, data.getFunctionArgumentTypes(), data.getFunctionArgumentLValues(),
|
||||
CPPTemplates.instantiateFunctionTemplates(fns, data.getFunctionArgumentTypes(), data.getFunctionArgumentValueCategories(),
|
||||
data.astName, data.argsContainImpliedObject);
|
||||
}
|
||||
|
||||
|
@ -2386,7 +2390,7 @@ public class CPPSemantics {
|
|||
private static FunctionCost costForFunctionCall(IFunction fn, boolean allowUDC, LookupData data)
|
||||
throws DOMException {
|
||||
IType[] argTypes = data.getFunctionArgumentTypes();
|
||||
BitSet isLValue= data.getFunctionArgumentLValues();
|
||||
ValueCategory[] isLValue= data.getFunctionArgumentValueCategories();
|
||||
int skipArg= 0;
|
||||
final ICPPFunctionType ftype= (ICPPFunctionType) fn.getType();
|
||||
if (ftype == null)
|
||||
|
@ -2412,7 +2416,7 @@ public class CPPSemantics {
|
|||
} else {
|
||||
result= new FunctionCost(fn, sourceLen + 1);
|
||||
|
||||
boolean sourceIsLValue= true;
|
||||
ValueCategory sourceIsLValue= LVALUE;
|
||||
if (impliedObjectType == null) {
|
||||
impliedObjectType= data.getImpliedObjectType();
|
||||
}
|
||||
|
@ -2425,7 +2429,7 @@ public class CPPSemantics {
|
|||
} else if (impliedObjectType.isSameType(implicitParameterType)) {
|
||||
cost = new Cost(impliedObjectType, implicitParameterType, Rank.IDENTITY);
|
||||
} 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 (CPPTemplates.isDependentType(implicitParameterType) || CPPTemplates.isDependentType(impliedObjectType)) {
|
||||
IType s= getNestedType(impliedObjectType, TDEF|REF|CVTYPE);
|
||||
|
@ -2443,17 +2447,17 @@ public class CPPSemantics {
|
|||
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++) {
|
||||
final IType argType= SemanticUtil.getNestedType(argTypes[j+skipArg], TDEF | REF);
|
||||
if (argType == null)
|
||||
return null;
|
||||
|
||||
final boolean sourceIsLValue = isLValue.get(j+skipArg);
|
||||
final ValueCategory sourceIsLValue = isLValue[j+skipArg];
|
||||
|
||||
IType paramType;
|
||||
if (j < paramTypes.length) {
|
||||
paramType= paramTypes[j];
|
||||
paramType= getNestedType(paramTypes[j], TDEF);
|
||||
} else if (!fn.takesVarArgs()) {
|
||||
paramType= VOID_TYPE;
|
||||
} else {
|
||||
|
@ -2467,7 +2471,16 @@ public class CPPSemantics {
|
|||
} else {
|
||||
if (CPPTemplates.isDependentType(paramType))
|
||||
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()) {
|
||||
cost= Cost.NO_CONVERSION;
|
||||
}
|
||||
|
@ -2941,22 +2954,23 @@ public class CPPSemantics {
|
|||
type = SemanticUtil.getNestedType(((ICPPVariable) binding).getType(), TDEF | CVTYPE);
|
||||
if (!(type instanceof ICPPClassType))
|
||||
return null;
|
||||
|
||||
final ICPPClassType classType = (ICPPClassType) type;
|
||||
|
||||
// Copy initialization
|
||||
if (initializer instanceof IASTEqualsInitializer) {
|
||||
IASTEqualsInitializer eqInit= (IASTEqualsInitializer) initializer;
|
||||
IASTInitializerClause initClause = eqInit.getInitializerClause();
|
||||
IType sourceType= null;
|
||||
boolean isLValue= false;
|
||||
ValueCategory isLValue= PRVALUE;
|
||||
if (initClause instanceof IASTExpression) {
|
||||
final IASTExpression expr = (IASTExpression) initClause;
|
||||
isLValue= expr.isLValue();
|
||||
isLValue= expr.getValueCategory();
|
||||
sourceType= SemanticUtil.getSimplifiedType(expr.getExpressionType());
|
||||
} else if (initClause instanceof ICPPASTInitializerList) {
|
||||
sourceType= new InitializerListType((ICPPASTInitializerList) initClause);
|
||||
}
|
||||
if (sourceType != null) {
|
||||
Cost c= Conversions.checkUserDefinedConversionSequence(isLValue, sourceType, type, false, false);
|
||||
Cost c= Conversions.copyInitializationOfClass(isLValue, sourceType, classType, false);
|
||||
if (c.converts()) {
|
||||
IFunction f= c.getUserDefinedConversion();
|
||||
if (f instanceof ICPPConstructor)
|
||||
|
@ -2967,7 +2981,6 @@ public class CPPSemantics {
|
|||
}
|
||||
|
||||
// Direct Initialization
|
||||
ICPPClassType classType = (ICPPClassType) type;
|
||||
CPPASTName astName = new CPPASTName();
|
||||
astName.setName(classType.getNameCharArray());
|
||||
astName.setOffsetAndLength((ASTNode) name);
|
||||
|
@ -3022,9 +3035,6 @@ public class CPPSemantics {
|
|||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* mstodo remove
|
||||
*/
|
||||
public static IASTExpression createArgForType(IASTNode node, IType type) {
|
||||
CPPASTName x= new CPPASTName();
|
||||
x.setBinding(createVariable(x, type, false, false));
|
||||
|
|
|
@ -13,8 +13,9 @@
|
|||
*******************************************************************************/
|
||||
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.BitSet;
|
||||
import java.util.Collections;
|
||||
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.IASTElaboratedTypeSpecifier;
|
||||
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.IASTIdExpression;
|
||||
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.ICPPUnknownClassType;
|
||||
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;
|
||||
|
||||
/**
|
||||
|
@ -146,7 +149,6 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.Conversions.UDCMod
|
|||
* type instantiation.
|
||||
*/
|
||||
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_FAIL = -2;
|
||||
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,
|
||||
BitSet allArgIsLValue, IASTName name, boolean argsContainImpliedObject) {
|
||||
ValueCategory[] allValueCategories, IASTName name, boolean argsContainImpliedObject) {
|
||||
boolean requireTemplate= false;
|
||||
if (name != null) {
|
||||
if (name.getPropertyInParent() == ICPPASTTemplateId.TEMPLATE_NAME) {
|
||||
|
@ -1551,7 +1553,7 @@ public class CPPTemplates {
|
|||
}
|
||||
|
||||
IType[] reducedFnArgs= null;
|
||||
BitSet reducedIsLValue= null;
|
||||
ValueCategory[] reducedValueCategories= null;
|
||||
ICPPTemplateArgument[] tmplArgs= null;
|
||||
for (int i = 0; i < functions.length; i++) {
|
||||
IFunction func = functions[i];
|
||||
|
@ -1560,23 +1562,23 @@ public class CPPTemplates {
|
|||
functions[i]= null;
|
||||
|
||||
final IType[] fnArgs;
|
||||
final BitSet argIsLValue;
|
||||
final ValueCategory[] valueCategories;
|
||||
if (argsContainImpliedObject && template instanceof ICPPMethod) {
|
||||
if (reducedIsLValue == null) {
|
||||
if (reducedValueCategories == null) {
|
||||
if (allFnArgs != null && allFnArgs.length > 0) {
|
||||
reducedFnArgs= ArrayUtil.removeFirst(allFnArgs);
|
||||
}
|
||||
if (allArgIsLValue == null || allArgIsLValue.length() == 0) {
|
||||
reducedIsLValue= ALL_RVALUES;
|
||||
if (allValueCategories == null || allValueCategories.length == 0) {
|
||||
reducedValueCategories= new ValueCategory[0];
|
||||
} else {
|
||||
reducedIsLValue= allArgIsLValue.get(1, allArgIsLValue.length());
|
||||
reducedValueCategories= ArrayUtil.removeFirst(allValueCategories);
|
||||
}
|
||||
}
|
||||
fnArgs= reducedFnArgs;
|
||||
argIsLValue= reducedIsLValue;
|
||||
valueCategories= reducedValueCategories;
|
||||
} else {
|
||||
fnArgs= allFnArgs;
|
||||
argIsLValue= allArgIsLValue;
|
||||
valueCategories= allValueCategories;
|
||||
}
|
||||
|
||||
// extract template arguments and parameter types.
|
||||
|
@ -1600,7 +1602,7 @@ public class CPPTemplates {
|
|||
}
|
||||
CPPTemplateParameterMap map= new CPPTemplateParameterMap(fnArgs.length);
|
||||
try {
|
||||
ICPPTemplateArgument[] args= TemplateArgumentDeduction.deduceForFunctionCall(template, tmplArgs, fnArgs, argIsLValue, map);
|
||||
ICPPTemplateArgument[] args= TemplateArgumentDeduction.deduceForFunctionCall(template, tmplArgs, fnArgs, valueCategories, map);
|
||||
if (args != null) {
|
||||
IBinding instance= instantiateFunctionTemplate(template, args, map);
|
||||
if (instance instanceof IFunction) {
|
||||
|
@ -1719,7 +1721,7 @@ public class CPPTemplates {
|
|||
|
||||
map= new CPPTemplateParameterMap(2);
|
||||
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;
|
||||
|
||||
final int last = tmplParams1.length -1;
|
||||
|
@ -1981,7 +1983,7 @@ public class CPPTemplates {
|
|||
} else if (paramType instanceof IArrayType) {
|
||||
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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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 java.util.ArrayList;
|
||||
import java.util.BitSet;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
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.IASTEqualsInitializer;
|
||||
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.IASTForStatement;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTFunctionCallExpression;
|
||||
|
@ -1791,6 +1791,7 @@ public class CPPVisitor extends ASTQueries {
|
|||
|
||||
IType type = AutoTypeResolver.AUTO_TYPE;
|
||||
IType initType = null;
|
||||
ValueCategory valueCat= null;
|
||||
ICPPClassTemplate initializer_list_template = null;
|
||||
try {
|
||||
if (initClause instanceof ICPPASTInitializerList) {
|
||||
|
@ -1804,7 +1805,9 @@ public class CPPVisitor extends ASTQueries {
|
|||
type = decorateType(type, declSpec, declarator);
|
||||
|
||||
if (initClause instanceof IASTExpression) {
|
||||
initType = ((IASTExpression) initClause).getExpressionType();
|
||||
final IASTExpression expression = (IASTExpression) initClause;
|
||||
initType = expression.getExpressionType();
|
||||
valueCat= expression.getValueCategory();
|
||||
} else if (initClause instanceof ICPPASTInitializerList) {
|
||||
initType = new InitializerListType((ICPPASTInitializerList) initClause);
|
||||
}
|
||||
|
@ -1816,8 +1819,8 @@ public class CPPVisitor extends ASTQueries {
|
|||
}
|
||||
ICPPFunctionTemplate template = new AutoTypeResolver(type);
|
||||
CPPTemplateParameterMap paramMap = new CPPTemplateParameterMap(1);
|
||||
TemplateArgumentDeduction.deduceFromFunctionArgs(template, new IType[] { initType }, new BitSet(),
|
||||
paramMap, false);
|
||||
TemplateArgumentDeduction.deduceFromFunctionArgs(template, new IType[] { initType },
|
||||
new ValueCategory[] { valueCat }, paramMap, false);
|
||||
ICPPTemplateArgument argument = paramMap.getArgument(0, 0);
|
||||
if (argument == null) {
|
||||
return null;
|
||||
|
|
|
@ -14,13 +14,14 @@
|
|||
*******************************************************************************/
|
||||
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.ExpressionTypes.valueCategoryFromReturnType;
|
||||
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.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.IASTLiteralExpression;
|
||||
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.CPPPointerType;
|
||||
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.ReferenceBinding;
|
||||
|
||||
|
@ -62,30 +64,26 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.Cost.ReferenceBind
|
|||
* Routines for calculating the cost of 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[] STD_NAME = "std".toCharArray(); //$NON-NLS-1$
|
||||
|
||||
/**
|
||||
* Computes the cost of an implicit conversion sequence
|
||||
* [over.best.ics] 13.3.3.1
|
||||
* Computes the cost of an implicit conversion sequence [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 exprType the source (argument) type
|
||||
* @param exprIsLValue whether the source type is an lvalue
|
||||
* @param isImpliedObjectType
|
||||
* @param valueCat value category of the expression
|
||||
* @return the cost of converting from source to target
|
||||
* @throws DOMException
|
||||
*/
|
||||
public static Cost checkImplicitConversionSequence(IType target, IType exprType,
|
||||
boolean exprIsLValue, UDCMode udc, boolean isImpliedObjectType) throws DOMException {
|
||||
if (isImpliedObjectType) {
|
||||
udc= UDCMode.noUDC;
|
||||
ValueCategory valueCat, UDCMode udc, Context ctx) throws DOMException {
|
||||
final boolean isImpliedObject= ctx == Context.IMPLICIT_OBJECT;
|
||||
if (isImpliedObject) {
|
||||
udc= UDCMode.FORBIDDEN;
|
||||
}
|
||||
|
||||
target= getNestedType(target, TDEF);
|
||||
|
@ -99,12 +97,13 @@ public class Conversions {
|
|||
final IType cv2T2= exprType;
|
||||
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;
|
||||
if (!isImplicitWithoutRefQualifier) {
|
||||
if (isLValueRef) {
|
||||
refBindingType= ReferenceBinding.LVALUE_REF;
|
||||
} else if (exprIsLValue) {
|
||||
} else if (valueCat == LVALUE) {
|
||||
refBindingType= ReferenceBinding.RVALUE_REF_BINDS_RVALUE;
|
||||
}
|
||||
}
|
||||
|
@ -113,9 +112,9 @@ public class Conversions {
|
|||
if (isLValueRef) {
|
||||
// ... 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]
|
||||
if (exprIsLValue) {
|
||||
if (valueCat == LVALUE) {
|
||||
// ... and "cv1 T1" is reference-compatible with "cv2 T2"
|
||||
Cost cost= isReferenceCompatible(cv1T1, cv2T2, isImpliedObjectType);
|
||||
Cost cost= isReferenceCompatible(cv1T1, cv2T2, isImpliedObject);
|
||||
if (cost != null) {
|
||||
// [13.3.3.1.4-1] direct binding has either identity or conversion rank.
|
||||
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
|
||||
// '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)),
|
||||
if (T2 instanceof ICPPClassType && udc != UDCMode.noUDC && isReferenceRelated(T1, T2) < 0) {
|
||||
Cost cost= conversionFuncForDirectReference(cv1T1, cv2T2, T2, true);
|
||||
if (T2 instanceof ICPPClassType && udc != UDCMode.FORBIDDEN && isReferenceRelated(T1, T2) < 0) {
|
||||
Cost cost= initializationByConversionForDirectReference(cv1T1, cv2T2, (ICPPClassType) T2, true, ctx);
|
||||
if (cost != null) {
|
||||
cost.setReferenceBinding(refBindingType);
|
||||
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
|
||||
// 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;
|
||||
if (isLValueRef) {
|
||||
ok = getCVQualifier(cv1T1) == CVQualifier.c;
|
||||
} else {
|
||||
ok= !exprIsLValue;
|
||||
ok= valueCat.isRValue() || T2 instanceof IFunctionType;
|
||||
}
|
||||
if (!ok) {
|
||||
return Cost.NO_CONVERSION;
|
||||
}
|
||||
|
||||
// If T1 and T2 are class types and ...
|
||||
if (T1 instanceof ICPPClassType && T2 instanceof ICPPClassType) {
|
||||
// ... the initializer expression is an rvalue and �cv1 T1� is reference-compatible with �cv2 T2�
|
||||
if (!exprIsLValue) {
|
||||
Cost cost= isReferenceCompatible(cv1T1, cv2T2, isImpliedObjectType);
|
||||
// If T1 is a function type, then
|
||||
if (T1 instanceof IFunctionType) {
|
||||
// if T2 is the same type as T1, the reference is bound to the initializer expression lvalue;
|
||||
if (T2.isSameType(T1)) {
|
||||
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) {
|
||||
// [13.3.3.1.4-1] direct binding has either identity or conversion rank.
|
||||
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
|
||||
// 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
|
||||
// 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,
|
||||
// in either case, to the appropriate base class subobject of the object).
|
||||
if (udc != UDCMode.noUDC && isReferenceRelated(T1, T2) < 0) {
|
||||
Cost cost= conversionFuncForDirectReference(cv1T1, cv2T2, T2, false);
|
||||
// in either case, to the appropriate base class sub-object of the object).
|
||||
if (udc != UDCMode.FORBIDDEN && isReferenceRelated(T1, T2) < 0) {
|
||||
Cost cost= initializationByConversionForDirectReference(cv1T1, cv2T2, (ICPPClassType) T2, false, ctx);
|
||||
if (cost != null) {
|
||||
cost.setReferenceBinding(refBindingType);
|
||||
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
|
||||
// reference-compatible with �cv2 T2,� the reference is bound to the object represented by the
|
||||
// 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
|
||||
// rvalue (see 3.10).
|
||||
if (!exprIsLValue && T2 instanceof IArrayType) {
|
||||
Cost cost= isReferenceCompatible(cv1T1, cv2T2, isImpliedObjectType);
|
||||
if (T2 instanceof IArrayType && valueCat.isRValue()) {
|
||||
Cost cost= isReferenceCompatible(cv1T1, cv2T2, isImpliedObject);
|
||||
if (cost != null) {
|
||||
cost.setReferenceBinding(refBindingType);
|
||||
return cost;
|
||||
|
@ -198,9 +221,9 @@ public class Conversions {
|
|||
// 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
|
||||
if (!isImpliedObjectType) {
|
||||
if (!isImpliedObject) {
|
||||
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()) {
|
||||
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
|
||||
*/
|
||||
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 {
|
||||
ICPPMethod[] fcns= SemanticUtil.getConversionOperators((ICPPClassType) T2);
|
||||
ICPPMethod[] fcns= SemanticUtil.getConversionOperators(T2);
|
||||
Cost operatorCost= null;
|
||||
FunctionCost bestUdcCost= null;
|
||||
boolean ambiguousConversionOperator= false;
|
||||
if (fcns.length > 0 && !(fcns[0] instanceof IProblemBinding)) {
|
||||
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();
|
||||
IType convertedType= ft.getReturnType();
|
||||
final boolean isLValue = CPPVisitor.isLValueReference(convertedType);
|
||||
if (isLValue == forLValue) { // require an lvalue or rvalue
|
||||
IType implicitObjectType= CPPSemantics.getImplicitParameterType(op, ft.isConst(), ft.isVolatile());
|
||||
Cost udcCost= isReferenceCompatible(getNestedType(implicitObjectType, TDEF | REF), cv2T2, true); // expression type to implicit object type
|
||||
IType t= getNestedType(ft.getReturnType(), TDEF);
|
||||
final boolean isLValueRef= t instanceof ICPPReferenceType && !((ICPPReferenceType) t).isRValueReference();
|
||||
if (isLValueRef == needLValue) { // require an lvalue or rvalue
|
||||
IType implicitParameterType= CPPSemantics.getImplicitParameterType(op, ft.isConst(), ft.isVolatile());
|
||||
Cost udcCost= isReferenceCompatible(getNestedType(implicitParameterType, TDEF | REF), cv2T2, true); // expression type to implicit object type
|
||||
if (udcCost != null) {
|
||||
FunctionCost udcFuncCost= new FunctionCost(op, udcCost);
|
||||
int cmp= udcFuncCost.compareTo(null, bestUdcCost);
|
||||
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) {
|
||||
bestUdcCost= udcFuncCost;
|
||||
ambiguousConversionOperator= cmp == 0;
|
||||
|
@ -270,18 +298,43 @@ public class Conversions {
|
|||
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) {
|
||||
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;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
return checkUserDefinedConversionSequence(sourceIsLValue, source, target, udc == UDCMode.deferUDC, false);
|
||||
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);
|
||||
if (listType != null) {
|
||||
IType[] exprTypes= arg.getExpressionTypes();
|
||||
BitSet isLValue= arg.getIsLValue();
|
||||
ValueCategory[] valueCats= arg.getValueCategories();
|
||||
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);
|
||||
Cost cost= checkImplicitConversionSequence(listType, exprType, valueCats[i], UDCMode.ALLOWED, Context.ORDINARY);
|
||||
if (!cost.converts())
|
||||
return cost;
|
||||
if (cost.isNarrowingConversion()) {
|
||||
|
@ -311,7 +364,7 @@ public class Conversions {
|
|||
|
||||
IType noCVTarget= getNestedType(target, CVTYPE | TDEF);
|
||||
if (noCVTarget instanceof ICPPClassType) {
|
||||
if (udc == UDCMode.noUDC)
|
||||
if (udc == UDCMode.FORBIDDEN)
|
||||
return Cost.NO_CONVERSION;
|
||||
|
||||
ICPPClassType classTarget= (ICPPClassType) noCVTarget;
|
||||
|
@ -320,7 +373,7 @@ public class Conversions {
|
|||
cost.setUserDefinedConversion(null);
|
||||
return cost;
|
||||
}
|
||||
return checkUserDefinedConversionSequence(false, arg, target, udc == UDCMode.deferUDC, isDirect);
|
||||
return listInitializationOfClass(arg, classTarget, isDirect, udc == UDCMode.DEFER);
|
||||
}
|
||||
|
||||
IASTInitializerClause[] args = arg.getInitializerList().getClauses();
|
||||
|
@ -328,7 +381,7 @@ public class Conversions {
|
|||
final IASTInitializerClause firstArg = args[0];
|
||||
if (firstArg instanceof IASTExpression) {
|
||||
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()) {
|
||||
return Cost.NO_CONVERSION;
|
||||
}
|
||||
|
@ -484,10 +537,9 @@ public class Conversions {
|
|||
* classes are nominated via using-declarations. In such a situation the derived to
|
||||
* base conversion does not cause any costs.
|
||||
*/
|
||||
private static final Cost checkStandardConversionSequence(IType source, boolean isLValue, IType target,
|
||||
boolean isImplicitThis) {
|
||||
private static final Cost checkStandardConversionSequence(IType source, IType target, boolean isImplicitThis) {
|
||||
final Cost cost= new Cost(source, target, Rank.IDENTITY);
|
||||
if (lvalue_to_rvalue(cost, isLValue))
|
||||
if (lvalue_to_rvalue(cost))
|
||||
return cost;
|
||||
|
||||
if (promotion(cost))
|
||||
|
@ -504,40 +556,14 @@ public class Conversions {
|
|||
return cost;
|
||||
}
|
||||
|
||||
/**
|
||||
* [13.3.3.1.2] User-defined conversions
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
// 13.3.1.7 Initialization by list-initialization
|
||||
static Cost listInitializationOfClass(InitializerListType arg, ICPPClassType t, boolean isDirect, boolean deferUDC) throws DOMException {
|
||||
if (deferUDC) {
|
||||
Cost c= new Cost(source, target, Rank.USER_DEFINED_CONVERSION);
|
||||
c.setDeferredUDC(true);
|
||||
Cost c= new Cost(arg, t, Rank.USER_DEFINED_CONVERSION);
|
||||
c.setDeferredUDC(isDirect ? DeferredUDC.DIRECT_LIST_INIT_OF_CLASS : DeferredUDC.LIST_INIT_OF_CLASS);
|
||||
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
|
||||
ICPPConstructor usedCtor= null;
|
||||
Cost bestCost= null;
|
||||
|
@ -551,7 +577,7 @@ public class Conversions {
|
|||
final IType target = parTypes[0];
|
||||
if (getInitListType(target) != null) {
|
||||
hasInitListConstructor= true;
|
||||
Cost cost= listInitializationSequence(arg, target, UDCMode.noUDC, isDirect);
|
||||
Cost cost= listInitializationSequence(arg, target, UDCMode.FORBIDDEN, isDirect);
|
||||
if (cost.converts()) {
|
||||
int cmp= cost.compareTo(bestCost);
|
||||
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]
|
||||
*/
|
||||
private static Cost copyInitalizationOfClass(boolean sourceIsLValue, IType source, IType s, IType target,
|
||||
ICPPClassType t) throws DOMException {
|
||||
static final Cost copyInitializationOfClass(ValueCategory valueCat, IType source, ICPPClassType t, boolean deferUDC) 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;
|
||||
Cost cost2= null;
|
||||
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) {
|
||||
// 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()) {
|
||||
final ICPPFunctionType ft = ctor.getType();
|
||||
final IType[] ptypes = ft.getParameterTypes();
|
||||
|
@ -650,7 +684,7 @@ public class Conversions {
|
|||
if (ctor.getRequiredArgumentCount() > 1)
|
||||
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);
|
||||
if (cmp <= 0) {
|
||||
|
@ -663,9 +697,11 @@ public class Conversions {
|
|||
}
|
||||
}
|
||||
}
|
||||
if (s instanceof ICPPClassType) {
|
||||
ICPPMethod[] ops = SemanticUtil.getConversionOperators((ICPPClassType) s);
|
||||
CPPTemplates.instantiateConversionTemplates(ops, target);
|
||||
|
||||
final IType uqSource= getNestedType(source, TDEF | REF | CVTYPE);
|
||||
if (uqSource instanceof ICPPClassType) {
|
||||
ICPPMethod[] ops = SemanticUtil.getConversionOperators((ICPPClassType) uqSource);
|
||||
CPPTemplates.instantiateConversionTemplates(ops, t);
|
||||
for (final ICPPMethod op : ops) {
|
||||
if (op != null && !(op instanceof IProblemBinding)) {
|
||||
if (op.isExplicit())
|
||||
|
@ -706,22 +742,25 @@ public class Conversions {
|
|||
/**
|
||||
* 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 {
|
||||
ICPPMethod[] ops = SemanticUtil.getConversionOperators(s);
|
||||
static Cost initializationByConversion(ValueCategory valueCat, IType source, ICPPClassType uqSource, IType target, boolean deferUDC) throws DOMException {
|
||||
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);
|
||||
FunctionCost cost1= null;
|
||||
Cost cost2= null;
|
||||
for (final ICPPMethod op : ops) {
|
||||
if (op != null && !(op instanceof IProblemBinding)) {
|
||||
final boolean isExplicitConversion= op.isExplicit();
|
||||
if (isExplicitConversion && !direct)
|
||||
if (isExplicitConversion /** && !direct **/)
|
||||
continue;
|
||||
|
||||
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);
|
||||
Cost c2= checkImplicitConversionSequence(target, uqReturnType, valueCategoryFromReturnType(uqReturnType), UDCMode.FORBIDDEN, Context.ORDINARY);
|
||||
if (c2.converts()) {
|
||||
if (isExplicitConversion && c2.getRank() != Rank.IDENTITY)
|
||||
continue;
|
||||
|
@ -756,33 +795,15 @@ public class Conversions {
|
|||
* [4.2] array-to-ptr
|
||||
* [4.3] function-to-ptr
|
||||
*/
|
||||
private static final boolean lvalue_to_rvalue(final Cost cost, boolean isLValue) {
|
||||
// mstodo request value category
|
||||
// target should not be a reference here.
|
||||
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;
|
||||
}
|
||||
}
|
||||
private static final boolean lvalue_to_rvalue(final Cost cost) {
|
||||
IType target = getNestedType(cost.target, REF | TDEF | ALLCVQ);
|
||||
IType source= getNestedType(cost.source, REF | TDEF | ALLCVQ);
|
||||
|
||||
// 4.2 array to pointer conversion
|
||||
if (!isConverted && source instanceof IArrayType) {
|
||||
if (source instanceof IArrayType) {
|
||||
final IArrayType arrayType= (IArrayType) source;
|
||||
|
||||
boolean isConverted= false;
|
||||
if (target instanceof IPointerType) {
|
||||
final IType targetPtrTgt= getNestedType(((IPointerType) target).getType(), TDEF);
|
||||
|
||||
|
@ -807,16 +828,12 @@ public class Conversions {
|
|||
}
|
||||
if (!isConverted && (target instanceof IPointerType || target instanceof IBasicType)) {
|
||||
source = new CPPPointerType(getNestedType(arrayType.getType(), TDEF));
|
||||
isConverted= true;
|
||||
}
|
||||
}
|
||||
|
||||
// 4.3 function to pointer conversion
|
||||
if (!isConverted && target instanceof IPointerType) {
|
||||
} else if (target instanceof IPointerType) {
|
||||
// 4.3 function to pointer conversion
|
||||
final IType targetPtrTgt= getNestedType(((IPointerType) target).getType(), TDEF);
|
||||
if (targetPtrTgt instanceof IFunctionType && source instanceof IFunctionType) {
|
||||
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.
|
||||
*/
|
||||
class Cost {
|
||||
public enum DeferredUDC {
|
||||
NONE, COPY_INIT_OF_CLASS, INIT_BY_CONVERSION, LIST_INIT_OF_CLASS, DIRECT_LIST_INIT_OF_CLASS
|
||||
}
|
||||
enum Rank {
|
||||
IDENTITY, PROMOTION, CONVERSION, CONVERSION_PTR_BOOL,
|
||||
USER_DEFINED_CONVERSION, ELLIPSIS_CONVERSION, NO_MATCH
|
||||
|
@ -52,7 +55,7 @@ class Cost {
|
|||
assert false;
|
||||
}
|
||||
@Override
|
||||
public void setDeferredUDC(boolean val) {
|
||||
public void setDeferredUDC(DeferredUDC val) {
|
||||
assert false;
|
||||
}
|
||||
@Override
|
||||
|
@ -79,7 +82,7 @@ class Cost {
|
|||
private Rank fRank;
|
||||
private Rank fSecondStandardConversionRank;
|
||||
private boolean fAmbiguousUDC;
|
||||
private boolean fDeferredUDC;
|
||||
private DeferredUDC fDeferredUDC= DeferredUDC.NONE;
|
||||
private int fQualificationAdjustments;
|
||||
private int fInheritanceDistance;
|
||||
private ICPPFunction fUserDefinedConversion;
|
||||
|
@ -119,12 +122,12 @@ class Cost {
|
|||
fAmbiguousUDC= val;
|
||||
}
|
||||
|
||||
public boolean isDeferredUDC() {
|
||||
public DeferredUDC isDeferredUDC() {
|
||||
return fDeferredUDC;
|
||||
}
|
||||
|
||||
public void setDeferredUDC(boolean val) {
|
||||
fDeferredUDC= val;
|
||||
public void setDeferredUDC(DeferredUDC udc) {
|
||||
fDeferredUDC= udc;
|
||||
}
|
||||
|
||||
public int getInheritanceDistance() {
|
||||
|
@ -160,7 +163,7 @@ class Cost {
|
|||
return -1;
|
||||
|
||||
// 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);
|
||||
if (cmp != 0)
|
||||
|
@ -218,8 +221,8 @@ class Cost {
|
|||
buf.append(comma).append("inheritance=").append(fInheritanceDistance);
|
||||
comma= ", ";
|
||||
}
|
||||
if (fDeferredUDC) {
|
||||
buf.append(comma).append("deferred UDC");
|
||||
if (fDeferredUDC != DeferredUDC.NONE) {
|
||||
buf.append(comma).append(fDeferredUDC);
|
||||
comma= ", ";
|
||||
}
|
||||
if (fAmbiguousUDC) {
|
||||
|
|
|
@ -10,13 +10,17 @@
|
|||
*******************************************************************************/
|
||||
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.IASTExpression.ValueCategory;
|
||||
import org.eclipse.cdt.core.dom.ast.IBinding;
|
||||
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.ICPPSpecialization;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.Cost.DeferredUDC;
|
||||
|
||||
/**
|
||||
* Cost for the entire function call
|
||||
|
@ -24,18 +28,18 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPSpecialization;
|
|||
class FunctionCost {
|
||||
private final IFunction fFunction;
|
||||
private final Cost[] fCosts;
|
||||
private final BitSet fSourceIsLValue;
|
||||
private final ValueCategory[] fValueCategories;
|
||||
|
||||
public FunctionCost(IFunction fn, int paramCount) {
|
||||
fFunction= fn;
|
||||
fCosts= new Cost[paramCount];
|
||||
fSourceIsLValue= new BitSet(paramCount);
|
||||
fValueCategories= new ValueCategory[paramCount];
|
||||
}
|
||||
|
||||
public FunctionCost(IFunction fn, Cost cost) {
|
||||
fFunction= fn;
|
||||
fCosts= new Cost[] {cost};
|
||||
fSourceIsLValue= null; // no udc will be performed
|
||||
fValueCategories= null; // no udc will be performed
|
||||
}
|
||||
|
||||
public int getLength() {
|
||||
|
@ -46,9 +50,9 @@ class FunctionCost {
|
|||
return fCosts[idx];
|
||||
}
|
||||
|
||||
public void setCost(int idx, Cost cost, boolean sourceIsLValue) {
|
||||
public void setCost(int idx, Cost cost, ValueCategory valueCat) {
|
||||
fCosts[idx]= cost;
|
||||
fSourceIsLValue.set(idx, sourceIsLValue);
|
||||
fValueCategories[idx]= valueCat;
|
||||
}
|
||||
|
||||
public IFunction getFunction() {
|
||||
|
@ -67,7 +71,7 @@ class FunctionCost {
|
|||
for (Cost cost : fCosts) {
|
||||
if (!cost.converts())
|
||||
return false;
|
||||
if (cost.isDeferredUDC())
|
||||
if (cost.isDeferredUDC() != DeferredUDC.NONE)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -76,13 +80,33 @@ class FunctionCost {
|
|||
public boolean performUDC() throws DOMException {
|
||||
for (int i = 0; i < fCosts.length; i++) {
|
||||
Cost cost = fCosts[i];
|
||||
if (cost.isDeferredUDC()) {
|
||||
Cost udcCost = Conversions.checkUserDefinedConversionSequence(fSourceIsLValue.get(i),
|
||||
cost.source, cost.target, false, false);
|
||||
fCosts[i] = udcCost;
|
||||
if (!udcCost.converts()) {
|
||||
return false;
|
||||
}
|
||||
Cost udcCost= null;
|
||||
switch(cost.isDeferredUDC()) {
|
||||
case NONE:
|
||||
continue;
|
||||
case COPY_INIT_OF_CLASS:
|
||||
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;
|
||||
|
@ -163,7 +187,7 @@ class FunctionCost {
|
|||
Cost otherCost= other.getCost(idxOther);
|
||||
|
||||
int cmp;
|
||||
if (cost.isDeferredUDC()) {
|
||||
if (cost.isDeferredUDC() != DeferredUDC.NONE) {
|
||||
cmp= cost.getRank().compareTo(otherCost.getRank());
|
||||
} else {
|
||||
cmp= cost.compareTo(otherCost);
|
||||
|
|
|
@ -10,9 +10,8 @@
|
|||
*******************************************************************************/
|
||||
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.ValueCategory;
|
||||
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;
|
||||
|
@ -24,7 +23,7 @@ class InitializerListType implements IType {
|
|||
|
||||
private final ICPPASTInitializerList fInitializerList;
|
||||
private IType[] fExpressionTypes;
|
||||
private BitSet fLValues;
|
||||
private ValueCategory[] fLValues;
|
||||
|
||||
public InitializerListType(ICPPASTInitializerList list) {
|
||||
fInitializerList= list;
|
||||
|
@ -66,16 +65,14 @@ class InitializerListType implements IType {
|
|||
return fExpressionTypes;
|
||||
}
|
||||
|
||||
public BitSet getIsLValue() {
|
||||
public ValueCategory[] getValueCategories() {
|
||||
if (fLValues == null) {
|
||||
final IASTInitializerClause[] clauses = fInitializerList.getClauses();
|
||||
fLValues= new BitSet(clauses.length);
|
||||
fLValues= new ValueCategory[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);
|
||||
}
|
||||
fLValues[i]= ((IASTExpression) clause).getValueCategory();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,7 +14,8 @@
|
|||
*******************************************************************************/
|
||||
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.List;
|
||||
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.IASTDeclarator;
|
||||
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.IASTFunctionCallExpression;
|
||||
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.ICPPMethod;
|
||||
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.parser.util.ArrayUtil;
|
||||
import org.eclipse.cdt.core.parser.util.CharArrayObjectMap;
|
||||
|
@ -103,7 +104,7 @@ public class LookupData {
|
|||
private ICPPASTParameterDeclaration[] functionParameters;
|
||||
private IASTInitializerClause[] functionArgs;
|
||||
private IType[] functionArgTypes;
|
||||
private BitSet functionArgLValues;
|
||||
private ValueCategory[] functionArgValueCategories;
|
||||
|
||||
public ICPPClassType skippedScope;
|
||||
public Object foundItems = null;
|
||||
|
@ -526,40 +527,37 @@ public class LookupData {
|
|||
return functionArgTypes;
|
||||
}
|
||||
|
||||
public BitSet getFunctionArgumentLValues() {
|
||||
if (functionArgLValues == null) {
|
||||
functionArgLValues= new BitSet();
|
||||
IASTInitializerClause[] args= getFunctionArguments();
|
||||
public ValueCategory[] getFunctionArgumentValueCategories() {
|
||||
if (functionArgValueCategories == null) {
|
||||
IASTInitializerClause[] args= functionArgs;
|
||||
if (args != null) {
|
||||
functionArgValueCategories= new ValueCategory[args.length];
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
final IASTInitializerClause arg = args[i];
|
||||
if (arg instanceof IASTExpression) {
|
||||
functionArgLValues.set(i, ((IASTExpression) arg).isLValue());
|
||||
} else {
|
||||
functionArgLValues.set(i, false);
|
||||
}
|
||||
functionArgValueCategories[i]= ((IASTExpression) arg).getValueCategory();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
IType[] argTypes= getFunctionArgumentTypes();
|
||||
if (argTypes != null) {
|
||||
functionArgValueCategories= new ValueCategory[argTypes.length];
|
||||
for (int i = 0; i < argTypes.length; 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) {
|
||||
functionParameters= parameters;
|
||||
}
|
||||
|
||||
public IASTInitializerClause[] getFunctionArguments() {
|
||||
return functionArgs;
|
||||
}
|
||||
|
||||
public int getFunctionArgumentCount() {
|
||||
if (functionArgs != null)
|
||||
return functionArgs.length;
|
||||
|
|
|
@ -10,16 +10,17 @@
|
|||
*******************************************************************************/
|
||||
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 java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.BitSet;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.eclipse.cdt.core.dom.ast.DOMException;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory;
|
||||
import org.eclipse.cdt.core.dom.ast.IArrayType;
|
||||
import org.eclipse.cdt.core.dom.ast.IBasicType;
|
||||
import org.eclipse.cdt.core.dom.ast.IBinding;
|
||||
|
@ -60,7 +61,7 @@ public class TemplateArgumentDeduction {
|
|||
* 14.8.2.1
|
||||
*/
|
||||
static ICPPTemplateArgument[] deduceForFunctionCall(ICPPFunctionTemplate template,
|
||||
ICPPTemplateArgument[] tmplArgs, IType[] fnArgs, BitSet argIsLValue, CPPTemplateParameterMap map)
|
||||
ICPPTemplateArgument[] tmplArgs, IType[] fnArgs, ValueCategory[] argIsLValue, CPPTemplateParameterMap map)
|
||||
throws DOMException {
|
||||
final ICPPTemplateParameter[] tmplParams = template.getTemplateParameters();
|
||||
final int numTmplParams = tmplParams.length;
|
||||
|
@ -151,7 +152,7 @@ public class TemplateArgumentDeduction {
|
|||
* Deduces the mapping for the template parameters from the function parameters,
|
||||
* returns <code>false</code> if there is no mapping.
|
||||
*/
|
||||
static boolean deduceFromFunctionArgs(ICPPFunctionTemplate template, IType[] fnArgs, BitSet argIsLValue,
|
||||
static boolean deduceFromFunctionArgs(ICPPFunctionTemplate template, IType[] fnArgs, ValueCategory[] argIsLValue,
|
||||
CPPTemplateParameterMap map, boolean checkExactMatch) {
|
||||
try {
|
||||
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.
|
||||
isReferenceTypeParameter= true;
|
||||
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);
|
||||
} else {
|
||||
arg= getArgumentTypeForDeduction(arg, true);
|
||||
|
|
Loading…
Add table
Reference in a new issue