mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-08-10 01:35:39 +02:00
Constructor template in implicit conversion sequence, bug 264314.
This commit is contained in:
parent
59bc9825a4
commit
86041e3f39
8 changed files with 122 additions and 141 deletions
|
@ -6719,4 +6719,20 @@ public class AST2CPPTests extends AST2BaseTest {
|
|||
String code= getAboveComment();
|
||||
parseAndCheckBindings(code, ParserLanguage.CPP);
|
||||
}
|
||||
|
||||
// template<typename IteratorT> class range {
|
||||
// public:
|
||||
// template<class Range> range(const Range& r) {}
|
||||
// };
|
||||
// void onRange(const range<const char*>& r) {}
|
||||
// void test() {
|
||||
// range<char*> ir(0);
|
||||
// onRange(ir);
|
||||
// }
|
||||
public void testConstructorTemplateInImplicitConversion_264314() throws Exception {
|
||||
final String code = getAboveComment();
|
||||
BindingAssertionHelper ba= new BindingAssertionHelper(code, true);
|
||||
ba.assertNonProblem("onRange(ir)", 7);
|
||||
parseAndCheckBindings(code, ParserLanguage.CPP);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -162,8 +162,8 @@ public class CPPASTUnaryExpression extends ASTNode implements
|
|||
} catch (DOMException e) {
|
||||
return e.getProblem();
|
||||
}
|
||||
return new CPPPointerToMemberType(type, (ICPPClassType) nestedType,
|
||||
thisType.isConst(), thisType.isVolatile());
|
||||
return new CPPPointerToMemberType(type, nestedType, thisType.isConst(), thisType
|
||||
.isVolatile());
|
||||
}
|
||||
}
|
||||
return new CPPPointerType(type);
|
||||
|
|
|
@ -1651,13 +1651,10 @@ public class CPPSemantics {
|
|||
final boolean indexBased= data.tu != null && data.tu.getIndex() != null;
|
||||
@SuppressWarnings("unchecked")
|
||||
ObjectSet<IFunction> fns= ObjectSet.EMPTY_SET;
|
||||
@SuppressWarnings("unchecked")
|
||||
ObjectSet<IFunction> templateFns= ObjectSet.EMPTY_SET;
|
||||
IBinding type = null;
|
||||
IBinding obj = null;
|
||||
IBinding temp = null;
|
||||
boolean fnsFromAST= false;
|
||||
boolean fnTmplsFromAST= false;
|
||||
|
||||
Object[] items = (Object[]) data.foundItems;
|
||||
for (int i = 0; i < items.length && items[i] != null; i++) {
|
||||
|
@ -1713,36 +1710,19 @@ public class CPPSemantics {
|
|||
}
|
||||
|
||||
IFunction function= (IFunction) temp;
|
||||
if (function instanceof ICPPFunctionTemplate) {
|
||||
if (templateFns == ObjectSet.EMPTY_SET)
|
||||
templateFns = new ObjectSet<IFunction>(2);
|
||||
if (isFromIndex(function)) {
|
||||
// accept bindings from index only, in case we have none in the AST
|
||||
if (!fnTmplsFromAST) {
|
||||
templateFns.put(function);
|
||||
}
|
||||
} else {
|
||||
if (!fnTmplsFromAST) {
|
||||
templateFns.clear();
|
||||
fnTmplsFromAST= true;
|
||||
}
|
||||
templateFns.put(function);
|
||||
}
|
||||
} else {
|
||||
if (fns == ObjectSet.EMPTY_SET)
|
||||
fns = new ObjectSet<IFunction>(2);
|
||||
if (isFromIndex(function)) {
|
||||
// accept bindings from index only, in case we have none in the AST
|
||||
if (!fnsFromAST) {
|
||||
fns.put(function);
|
||||
}
|
||||
} else {
|
||||
if (!fnsFromAST) {
|
||||
fns.clear();
|
||||
fnsFromAST= true;
|
||||
}
|
||||
if (fns == ObjectSet.EMPTY_SET)
|
||||
fns = new ObjectSet<IFunction>(2);
|
||||
if (isFromIndex(function)) {
|
||||
// accept bindings from index only, in case we have none in the AST
|
||||
if (!fnsFromAST) {
|
||||
fns.put(function);
|
||||
}
|
||||
} else {
|
||||
if (!fnsFromAST) {
|
||||
fns.clear();
|
||||
fnsFromAST= true;
|
||||
}
|
||||
fns.put(function);
|
||||
}
|
||||
} else if (temp instanceof IType) {
|
||||
// specializations are selected during instantiation
|
||||
|
@ -1804,46 +1784,31 @@ public class CPPSemantics {
|
|||
// if (fns == null) return type;
|
||||
bindings = (IBinding[]) ArrayUtil.append(IBinding.class, bindings, type);
|
||||
bindings = (IBinding[]) ArrayUtil.addAll(IBinding.class, bindings, fns.keyArray());
|
||||
bindings = (IBinding[]) ArrayUtil.addAll(IBinding.class, bindings, templateFns.keyArray());
|
||||
}
|
||||
bindings = (IBinding[]) ArrayUtil.trim(IBinding.class, bindings);
|
||||
ICPPUsingDeclaration composite = new CPPUsingDeclaration(data.astName, bindings);
|
||||
return composite;
|
||||
}
|
||||
|
||||
int numTemplateFns = templateFns.size();
|
||||
if (numTemplateFns > 0) {
|
||||
if (data.functionParameters != null &&
|
||||
(!data.forFunctionDeclaration() || data.forExplicitFunctionSpecialization())) {
|
||||
IFunction[] fs = CPPTemplates.selectTemplateFunctions(templateFns, data.functionParameters, data.astName);
|
||||
if (fs != null && fs.length > 0) {
|
||||
if (fns == ObjectSet.EMPTY_SET)
|
||||
fns = new ObjectSet<IFunction>(fs.length);
|
||||
fns.addAll(fs);
|
||||
}
|
||||
} else {
|
||||
if (fns == ObjectSet.EMPTY_SET)
|
||||
fns = templateFns;
|
||||
else
|
||||
fns.addAll(templateFns);
|
||||
}
|
||||
}
|
||||
int numFns = fns.size();
|
||||
if (type != null) {
|
||||
if (data.typesOnly || (obj == null && numFns == 0))
|
||||
if (data.typesOnly) {
|
||||
if (type != null)
|
||||
return type;
|
||||
if (obj instanceof ICPPNamespace)
|
||||
return obj;
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
int numFns = fns.size();
|
||||
if (numFns > 0) {
|
||||
if (obj != null)
|
||||
return new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP);
|
||||
return resolveFunction(data, fns.keyArray(IFunction.class));
|
||||
return resolveFunction(data, fns.keyArray(IFunction.class), true);
|
||||
}
|
||||
|
||||
if (data.typesOnly && obj instanceof ICPPNamespace == false) {
|
||||
return null;
|
||||
if (obj != null) {
|
||||
return obj;
|
||||
}
|
||||
return obj;
|
||||
return type;
|
||||
}
|
||||
|
||||
private static boolean isFromIndex(IBinding binding) {
|
||||
|
@ -1878,12 +1843,14 @@ public class CPPSemantics {
|
|||
// Trim the list down to the set of viable functions
|
||||
IFunction function = null;
|
||||
int size = functions.length;
|
||||
for (int i = 0; i < size && functions[i] != null; i++) {
|
||||
for (int i = 0; i < size; i++) {
|
||||
function = (IFunction) functions[i];
|
||||
if (function == null)
|
||||
continue;
|
||||
if (function instanceof IProblemBinding) {
|
||||
functions[i]= null;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (function instanceof ICPPUnknownBinding) {
|
||||
if (def) {
|
||||
functions[i]= null;
|
||||
|
@ -1978,7 +1945,7 @@ public class CPPSemantics {
|
|||
return result;
|
||||
}
|
||||
|
||||
static IBinding resolveFunction(LookupData data, IFunction[] fns) throws DOMException {
|
||||
static IBinding resolveFunction(LookupData data, IFunction[] fns, boolean allowUDC) throws DOMException {
|
||||
fns= (IFunction[]) ArrayUtil.trim(IFunction.class, fns);
|
||||
if (fns == null || fns.length == 0)
|
||||
return null;
|
||||
|
@ -1987,14 +1954,19 @@ public class CPPSemantics {
|
|||
return new CPPUsingDeclaration(data.astName, fns);
|
||||
}
|
||||
|
||||
if (data.astName instanceof ICPPASTConversionName) {
|
||||
return resolveUserDefinedConversion((ICPPASTConversionName) data.astName, fns);
|
||||
}
|
||||
|
||||
// We don't have any arguments with which to resolve the function
|
||||
if (data.functionParameters == null) {
|
||||
return resolveTargetedFunction(data, fns);
|
||||
}
|
||||
|
||||
if (!data.forFunctionDeclaration() || data.forExplicitFunctionSpecialization()) {
|
||||
CPPTemplates.instantiateFunctionTemplates(fns, data.functionParameters, data.astName);
|
||||
}
|
||||
|
||||
if (data.astName instanceof ICPPASTConversionName) {
|
||||
return resolveUserDefinedConversion((ICPPASTConversionName) data.astName, fns);
|
||||
}
|
||||
|
||||
// Reduce our set of candidate functions to only those who have the right number of parameters
|
||||
reduceToViable(data, fns);
|
||||
|
||||
|
@ -2060,7 +2032,6 @@ public class CPPSemantics {
|
|||
currFnCost= new Cost[sourceLen];
|
||||
}
|
||||
|
||||
comparison = 0;
|
||||
boolean varArgs = false;
|
||||
boolean isImpliedObject= false;
|
||||
for (int j = 0; j < sourceLen; j++) {
|
||||
|
@ -2097,8 +2068,8 @@ public class CPPSemantics {
|
|||
cost = new Cost(source, target);
|
||||
cost.rank = Cost.IDENTITY_RANK; // exact match, no cost
|
||||
} else {
|
||||
cost= Conversions.checkImplicitConversionSequence(!data.forUserDefinedConversion,
|
||||
sourceExp, source, target, isImpliedObject);
|
||||
cost= Conversions.checkImplicitConversionSequence(sourceExp,
|
||||
source, target, allowUDC, isImpliedObject);
|
||||
}
|
||||
|
||||
if (cost.rank < 0)
|
||||
|
|
|
@ -85,7 +85,6 @@ import org.eclipse.cdt.core.parser.util.ArrayUtil;
|
|||
import org.eclipse.cdt.core.parser.util.CharArraySet;
|
||||
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
|
||||
import org.eclipse.cdt.core.parser.util.ObjectMap;
|
||||
import org.eclipse.cdt.core.parser.util.ObjectSet;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.ASTAmbiguousNode;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.ASTQueries;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.IASTInternalScope;
|
||||
|
@ -1332,50 +1331,50 @@ public class CPPTemplates {
|
|||
return result;
|
||||
}
|
||||
|
||||
static protected IFunction[] selectTemplateFunctions(ObjectSet<IFunction> templates,
|
||||
static protected void instantiateFunctionTemplates(IFunction[] functions,
|
||||
Object[] functionArguments, IASTName name) {
|
||||
|
||||
if (templates == null || templates.size() == 0)
|
||||
return null;
|
||||
|
||||
ICPPTemplateArgument[] templateArguments = ICPPTemplateArgument.EMPTY_ARGUMENTS;
|
||||
final IType[] fnArgs= createTypeArray(functionArguments);
|
||||
try {
|
||||
if (containsDependentType(fnArgs))
|
||||
return new IFunction[] {CPPUnknownFunction.createForSample(templates.keyAt(0), name)};
|
||||
|
||||
if (name instanceof ICPPASTTemplateId) {
|
||||
templateArguments = createTemplateArgumentArray((ICPPASTTemplateId) name);
|
||||
if (hasDependentArgument(templateArguments))
|
||||
return new IFunction[] {CPPUnknownFunction.createForSample(templates.keyAt(0), name)};
|
||||
}
|
||||
} catch (DOMException e) {
|
||||
return new IFunction[0];
|
||||
}
|
||||
|
||||
IFunction[] instances= null;
|
||||
final int size = templates.size();
|
||||
for (int idx = 0; idx < size; idx++) {
|
||||
ICPPFunctionTemplate template = (ICPPFunctionTemplate) templates.keyAt(idx);
|
||||
CPPTemplateParameterMap map= new CPPTemplateParameterMap(fnArgs.length);
|
||||
try {
|
||||
ICPPTemplateArgument[] useArgs = templateArguments;
|
||||
if (template instanceof ICPPConstructor)
|
||||
useArgs= ICPPTemplateArgument.EMPTY_ARGUMENTS;
|
||||
ICPPTemplateArgument[] templateArguments= null;
|
||||
IType[] fnArgs= null;
|
||||
for (int i = 0; i < functions.length; i++) {
|
||||
IFunction func = functions[i];
|
||||
if (func instanceof ICPPFunctionTemplate) {
|
||||
ICPPFunctionTemplate template= (ICPPFunctionTemplate) func;
|
||||
functions[i]= null;
|
||||
|
||||
ICPPTemplateArgument[] args= deduceTemplateFunctionArguments(template, useArgs, fnArgs, map);
|
||||
if (args != null) {
|
||||
IBinding temp= instantiateFunctionTemplate(template, args);
|
||||
if (temp instanceof IFunction) {
|
||||
instances = (IFunction[]) ArrayUtil.append(IFunction.class, instances, temp);
|
||||
// extract template arguments and parameter types.
|
||||
if (templateArguments == null || fnArgs == null) {
|
||||
templateArguments = ICPPTemplateArgument.EMPTY_ARGUMENTS;
|
||||
fnArgs= createTypeArray(functionArguments);
|
||||
try {
|
||||
if (containsDependentType(fnArgs)) {
|
||||
functions[i]= CPPUnknownFunction.createForSample(template, name);
|
||||
return;
|
||||
}
|
||||
if (name instanceof ICPPASTTemplateId && !(template instanceof ICPPConstructor)) {
|
||||
templateArguments = createTemplateArgumentArray((ICPPASTTemplateId) name);
|
||||
if (hasDependentArgument(templateArguments)) {
|
||||
functions[i]= CPPUnknownFunction.createForSample(template, name);
|
||||
return;
|
||||
}
|
||||
}
|
||||
} catch (DOMException e) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
} catch (DOMException e) {
|
||||
// try next candidate
|
||||
}
|
||||
CPPTemplateParameterMap map= new CPPTemplateParameterMap(fnArgs.length);
|
||||
try {
|
||||
ICPPTemplateArgument[] args= deduceTemplateFunctionArguments(template, templateArguments, fnArgs, map);
|
||||
if (args != null) {
|
||||
IBinding instance= instantiateFunctionTemplate(template, args);
|
||||
if (instance instanceof IFunction) {
|
||||
functions[i]= (IFunction) instance;
|
||||
}
|
||||
}
|
||||
} catch (DOMException e) {
|
||||
// try next candidate
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (IFunction[]) ArrayUtil.trim(IFunction.class, instances);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -52,17 +52,17 @@ public class Conversions {
|
|||
/**
|
||||
* Computes the cost of an implicit conversion sequence
|
||||
* [over.best.ics] 13.3.3.1
|
||||
*
|
||||
* @param allowUDC whether a user-defined conversion is allowed during the sequence
|
||||
* @param sourceExp the expression behind the source type
|
||||
* @param source the source (argument) type
|
||||
* @param target the target (parameter) type
|
||||
* @param allowUDC whether a user-defined conversion is allowed during the sequence
|
||||
* @param isImpliedObject
|
||||
*
|
||||
* @return the cost of converting from source to target
|
||||
* @throws DOMException
|
||||
*/
|
||||
public static Cost checkImplicitConversionSequence(boolean allowUDC, IASTExpression sourceExp,
|
||||
IType source, IType target, boolean isImpliedObject) throws DOMException {
|
||||
public static Cost checkImplicitConversionSequence(IASTExpression sourceExp, IType source,
|
||||
IType target, boolean allowUDC, boolean isImpliedObject) throws DOMException {
|
||||
allowUDC &= !isImpliedObject;
|
||||
target= getNestedType(target, TYPEDEFS);
|
||||
source= getNestedType(source, TYPEDEFS);
|
||||
|
@ -166,26 +166,20 @@ public class Conversions {
|
|||
|
||||
// We must do a non-reference initialization
|
||||
if (!illformed) {
|
||||
Cost cost= checkStandardConversionSequence(source, cv1T1, isImpliedObject);
|
||||
// 12.3-4 At most one user-defined conversion is implicitly applied to
|
||||
// a single value. (also prevents infinite loop)
|
||||
if (allowUDC && (cost.rank == Cost.NO_MATCH_RANK ||
|
||||
cost.rank == Cost.FUZZY_TEMPLATE_PARAMETERS)) {
|
||||
Cost temp = checkUserDefinedConversionSequence(source, cv1T1);
|
||||
if (temp != null) {
|
||||
cost = temp;
|
||||
}
|
||||
}
|
||||
return cost;
|
||||
return nonReferenceConversion(source, cv1T1, allowUDC, isImpliedObject);
|
||||
}
|
||||
}
|
||||
return new Cost(source, cv1T1);
|
||||
}
|
||||
|
||||
// Non-reference binding
|
||||
return nonReferenceConversion(source, target, allowUDC, isImpliedObject);
|
||||
}
|
||||
|
||||
private static Cost nonReferenceConversion(IType source, IType target, boolean allowUDC,
|
||||
boolean isImpliedObject) throws DOMException {
|
||||
Cost cost= checkStandardConversionSequence(source, target, isImpliedObject);
|
||||
if (allowUDC && (cost.rank == Cost.NO_MATCH_RANK ||
|
||||
cost.rank == Cost.FUZZY_TEMPLATE_PARAMETERS)) {
|
||||
if (allowUDC && cost.rank == Cost.NO_MATCH_RANK) {
|
||||
Cost temp = checkUserDefinedConversionSequence(source, target);
|
||||
if (temp != null) {
|
||||
cost = temp;
|
||||
|
@ -349,19 +343,23 @@ public class Conversions {
|
|||
|
||||
//constructors
|
||||
if (t instanceof ICPPClassType) {
|
||||
ICPPConstructor [] constructors= ((ICPPClassType) t).getConstructors();
|
||||
if (constructors.length > 0 && !(constructors[0] instanceof IProblemBinding)) {
|
||||
ICPPConstructor[] ctors= ((ICPPClassType) t).getConstructors();
|
||||
// select converting constructors
|
||||
int j= 0;
|
||||
ICPPConstructor[] convertingCtors= new ICPPConstructor[ctors.length];
|
||||
for (int i = 0; i < ctors.length; i++) {
|
||||
ICPPConstructor ctor= ctors[i];
|
||||
if (!(ctor instanceof IProblemBinding) && !ctor.isExplicit())
|
||||
convertingCtors[j++]= ctor;
|
||||
}
|
||||
if (j > 0) {
|
||||
LookupData data= new LookupData();
|
||||
data.forUserDefinedConversion= true;
|
||||
data.functionParameters= new IType [] { source };
|
||||
IBinding binding = CPPSemantics.resolveFunction(data, constructors);
|
||||
if (binding instanceof ICPPConstructor) {
|
||||
ICPPConstructor constructor= (ICPPConstructor) binding;
|
||||
if (!constructor.isExplicit()) {
|
||||
constructorCost = checkStandardConversionSequence(t, target, false);
|
||||
if (constructorCost.rank == Cost.NO_MATCH_RANK) {
|
||||
constructorCost= null;
|
||||
}
|
||||
IBinding binding = CPPSemantics.resolveFunction(data, convertingCtors, false);
|
||||
if (binding instanceof ICPPConstructor && !(binding instanceof IProblemBinding)) {
|
||||
constructorCost = checkStandardConversionSequence(t, target, false);
|
||||
if (constructorCost.rank == Cost.NO_MATCH_RANK) {
|
||||
constructorCost= null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,7 +37,6 @@ class Cost {
|
|||
public static final int DERIVED_TO_BASE_CONVERSION = 3;
|
||||
public static final int USERDEFINED_CONVERSION_RANK = 4;
|
||||
public static final int ELLIPSIS_CONVERSION = 5;
|
||||
public static final int FUZZY_TEMPLATE_PARAMETERS = 6;
|
||||
|
||||
public IType source;
|
||||
public IType target;
|
||||
|
|
|
@ -93,7 +93,6 @@ public class LookupData {
|
|||
public boolean ignoreUsingDirectives = false;
|
||||
public boolean usingDirectivesOnly = false;
|
||||
public boolean forceQualified = false;
|
||||
public boolean forUserDefinedConversion = false;
|
||||
public boolean forAssociatedScopes = false;
|
||||
public boolean contentAssist = false;
|
||||
public boolean prefixLookup = false;
|
||||
|
|
|
@ -29,7 +29,6 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
|
|||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPPointerToMemberType;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPReferenceType;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateArgument;
|
||||
import org.eclipse.cdt.core.model.ITypeDef;
|
||||
import org.eclipse.cdt.core.parser.Keywords;
|
||||
import org.eclipse.cdt.core.parser.util.ArrayUtil;
|
||||
import org.eclipse.cdt.core.parser.util.CharArraySet;
|
||||
|
@ -284,7 +283,7 @@ public class SemanticUtil {
|
|||
return new CPPFunctionType(ret, params, ((ICPPFunctionType) type).getThisType());
|
||||
}
|
||||
|
||||
if (type instanceof ITypeDef) {
|
||||
if (type instanceof ITypedef) {
|
||||
IType t= ((ITypedef) type).getType();
|
||||
if (t != null)
|
||||
return getSimplifiedType(t);
|
||||
|
|
Loading…
Add table
Reference in a new issue