1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-19 15:05:36 +02:00

Bug 509396 - Unresolved symbol with address of overload set containing

function templates

This change fixes the examples contained in
https://bugs.eclipse.org/bugs/show_bug.cgi?id=509396#c0 and
https://bugs.eclipse.org/bugs/show_bug.cgi?id=509396#c4

Change-Id: Id5c81469b6700ddc775ab714b0b68d5ea9a809ae
This commit is contained in:
Sergey Prigogin 2017-03-10 16:30:24 -08:00 committed by Gerrit Code Review @ Eclipse.org
parent 8bfd2cdc22
commit 8da53f1e5e
8 changed files with 135 additions and 23 deletions

View file

@ -5969,6 +5969,43 @@ public class AST2TemplateTests extends AST2TestBase {
parseAndCheckBindings();
}
// struct A {
// template <typename U>
// void m(U);
// int m(int);
// };
//
// void foo(void(A::*)(int));
// void foo(int);
//
// template <typename T>
// decltype(foo(&T::m)) waldo(T);
//
// int main() {
// waldo(A());
// }
public void testAddressOfMethodTargeted_509396() throws Exception {
parseAndCheckBindings();
}
// struct A {
// template <typename U>
// void m(U t);
// };
//
// template <typename T>
// void waldo(T t);
//
// template <typename T>
// decltype(&T::m) waldo(T t);
//
// void test() {
// waldo(A());
// }
public void testAddressOfMethodUntargeted_509396() throws Exception {
parseAndCheckBindings();
}
// template<typename T, unsigned length> struct Templ {
// Templ(){}
// };

View file

@ -254,7 +254,7 @@ public class CPPASTFunctionCallExpression extends ASTNode
LookupData data= CPPSemantics.createLookupData(((IASTIdExpression) fFunctionName).getName());
try {
ICPPConstructor[] constructors = ClassTypeHelper.getConstructors(cls, data.getLookupPoint());
IBinding b= CPPSemantics.resolveFunction(data, constructors, true);
IBinding b= CPPSemantics.resolveFunction(data, constructors, true, false);
if (b instanceof ICPPFunction)
return (ICPPFunction) b;
} catch (DOMException e) {

View file

@ -198,6 +198,7 @@ import org.eclipse.cdt.internal.core.dom.parser.ASTQueries;
import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguousDeclarator;
import org.eclipse.cdt.internal.core.dom.parser.IASTInternalScope;
import org.eclipse.cdt.internal.core.dom.parser.IRecursionResolvingBinding;
import org.eclipse.cdt.internal.core.dom.parser.ITypeContainer;
import org.eclipse.cdt.internal.core.dom.parser.IntegralValue;
import org.eclipse.cdt.internal.core.dom.parser.ProblemBinding;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTIdExpression;
@ -478,7 +479,7 @@ public class CPPSemantics {
// Do not interpret template arguments to a template class as being
// explicit template arguments to its templated constructor.
data.setTemplateArguments(null);
binding= resolveFunction(data, ClassTypeHelper.getConstructors(cls, lookupPoint), true);
binding= resolveFunction(data, ClassTypeHelper.getConstructors(cls, lookupPoint), true, false);
}
} catch (DOMException e) {
return e.getProblem();
@ -2289,7 +2290,7 @@ public class CPPSemantics {
return obj;
}
}
return resolveFunction(data, fnArray, true);
return resolveFunction(data, fnArray, true, false);
}
if (obj != null) {
@ -2560,7 +2561,8 @@ public class CPPSemantics {
return result;
}
public static IBinding resolveFunction(LookupData data, ICPPFunction[] fns, boolean allowUDC) throws DOMException {
public static IBinding resolveFunction(LookupData data, ICPPFunction[] fns, boolean allowUDC,
boolean resolveTargetedArgumentTypes) throws DOMException {
final IASTName lookupName = data.getLookupName();
if (fns == null || fns.length == 0 || fns[0] == null)
return null;
@ -2585,7 +2587,7 @@ public class CPPSemantics {
return createFunctionSet(fns, data.getTemplateArguments(), lookupPoint, lookupName);
}
// Reduce our set of candidate functions to only those who have the right number of parameters
// Reduce our set of candidate functions to only those who have the right number of parameters.
final IType[] argTypes = data.getFunctionArgumentTypes();
ICPPFunction[] tmp= selectByArgumentCount(data, fns);
if (tmp.length == 0 || tmp[0] == null)
@ -2631,7 +2633,7 @@ public class CPPSemantics {
continue;
UDCMode udc = allowUDC ? UDCMode.DEFER : UDCMode.FORBIDDEN;
final FunctionCost fnCost= costForFunctionCall(fn, udc, data);
FunctionCost fnCost= costForFunctionCall(fn, udc, data, resolveTargetedArgumentTypes);
if (fnCost == null)
continue;
@ -2706,6 +2708,37 @@ public class CPPSemantics {
return result;
}
/**
* If {@code type} is a {@link FunctionSetType} or a pointer type containing a FunctionSetType,
* resolves the FunctionSetType using the given target type.
*
* @param type the type to resolve
* @param targetType the target type
* @param point the name lookup context
* @return the resolved type, or the given {@type} if the type didn't contain a FunctionSetType
* or the targeted function resolution failed
*/
private static IType resolveTargetedFunctionSetType(IType type, IType targetType, IASTNode point) {
IType t = type;
if (type instanceof IPointerType) {
t = ((IPointerType) type).getType();
}
if (t instanceof FunctionSetType) {
ICPPFunction function =
resolveTargetedFunction(targetType, ((FunctionSetType) t).getFunctionSet(), point);
if (function != null && !(function instanceof IProblemBinding)) {
type = function.getType();
if (targetType instanceof ITypeContainer) {
ITypeContainer containerType = (ITypeContainer) targetType.clone();
containerType.setType(type);
type = containerType;
}
}
}
return type;
}
private static IBinding createFunctionSet(ICPPFunction[] fns, ICPPTemplateArgument[] args, IASTNode point, IASTName name) {
// First try to find a unique function
if (name != null && name.getPropertyInParent() == ICPPASTTemplateId.TEMPLATE_NAME) {
@ -2861,15 +2894,35 @@ public class CPPSemantics {
}
}
private static FunctionCost costForFunctionCall(ICPPFunction fn, UDCMode udc, LookupData data)
throws DOMException {
IType[] argTypes= data.getFunctionArgumentTypes();
ValueCategory[] argValueCategories= data.getFunctionArgumentValueCategories();
int skipArg= 0;
private static FunctionCost costForFunctionCall(ICPPFunction fn, UDCMode udc, LookupData data,
boolean resolveTargetedArgumentTypes) throws DOMException {
final ICPPFunctionType ftype= fn.getType();
if (ftype == null)
return null;
IType[] argTypes= data.getFunctionArgumentTypes();
ValueCategory[] argValueCategories= data.getFunctionArgumentValueCategories();
if (resolveTargetedArgumentTypes) {
IType[] newArgTypes = null;
IType[] paramTypes = fn.getType().getParameterTypes();
for (int i = 0; i < argTypes.length && i < paramTypes.length; i++) {
IType argType = argTypes[i];
IType paramType = paramTypes[i];
IType newArgType = resolveTargetedFunctionSetType(argType, paramType, data.getLookupPoint());
if (newArgType != argType) {
if (newArgTypes == null) {
newArgTypes = new IType[argTypes.length];
System.arraycopy(argTypes, 0, newArgTypes, 0, argTypes.length);
}
newArgTypes[i] = newArgType;
}
}
if (newArgTypes != null) {
argTypes = newArgTypes;
}
}
int skipArg= 0;
IType implicitParameterType= null;
IType impliedObjectType= null;
ValueCategory impliedObjectValueCategory= null;
@ -3087,7 +3140,7 @@ public class CPPSemantics {
data.setFunctionArguments(false, init.getArguments());
try {
IBinding ctor = resolveFunction(data,
ClassTypeHelper.getConstructors((ICPPClassType) targetType, name), true);
ClassTypeHelper.getConstructors((ICPPClassType) targetType, name), true, false);
if (ctor instanceof ICPPConstructor) {
int i= 0;
for (IASTNode arg : init.getArguments()) {
@ -3268,7 +3321,7 @@ public class CPPSemantics {
*/
CPPBasicType t = new CPPBasicType(Kind.eInt, IBasicType.IS_UNSIGNED | IBasicType.IS_LONG_LONG, exp);
data.setFunctionArguments(false, createArgForType(exp, t));
ret = resolveFunction(data, funcs, true);
ret = resolveFunction(data, funcs, true, false);
if (isViableUserDefinedLiteralOperator(ret, kind)) {
return ret;
}
@ -3282,7 +3335,7 @@ public class CPPSemantics {
*/
CPPBasicType t = new CPPBasicType(Kind.eDouble, IBasicType.IS_LONG, exp);
data.setFunctionArguments(false, createArgForType(exp, t));
ret = resolveFunction(data, funcs, true);
ret = resolveFunction(data, funcs, true, false);
if (isViableUserDefinedLiteralOperator(ret, kind)) {
return ret;
}
@ -3297,7 +3350,7 @@ public class CPPSemantics {
CPPPointerType charArray = new CPPPointerType(CPPBasicType.CHAR, true, false, false);
data = new LookupData(((CPPASTLiteralExpression) exp).getOperatorName(), null, exp);
data.setFunctionArguments(false, createArgForType(exp, charArray));
ret = resolveFunction(data, funcs, true);
ret = resolveFunction(data, funcs, true, false);
//
char[] stringLiteral = exp.getValue(); // The string literal that was passed to the operator
@ -3310,7 +3363,7 @@ public class CPPSemantics {
}
data = new LookupData(((CPPASTLiteralExpression) exp).getOperatorName(), args, exp);
IBinding litTpl = resolveFunction(data, tplFunctions, true);
IBinding litTpl = resolveFunction(data, tplFunctions, true, false);
// Do we have valid template and non-template bindings?
if (ret != null && !(ret instanceof IProblemBinding)) {
@ -3342,7 +3395,7 @@ public class CPPSemantics {
createArgForType(null, CPPBasicType.UNSIGNED_INT)
};
data.setFunctionArguments(false, initializer);
ret = resolveFunction(data, funcs, true);
ret = resolveFunction(data, funcs, true, false);
} else if (kind == IASTLiteralExpression.lk_char_constant) {
/*
* 2.14.8.6
@ -3353,12 +3406,16 @@ public class CPPSemantics {
*/
CPPBasicType t = new CPPBasicType(((CPPASTLiteralExpression) exp).getBasicCharKind(), 0, exp);
data.setFunctionArguments(false, createArgForType(exp, t));
ret = resolveFunction(data, funcs, true);
ret = resolveFunction(data, funcs, true, false);
}
return ret;
}
/**
* 13.4-1 A use of an overloaded function without arguments is resolved in certain contexts to
* a function.
*/
static ICPPFunction resolveTargetedFunction(IType targetType, CPPFunctionSet set, IASTNode point) {
targetType= getNestedType(targetType, TDEF | REF | CVTYPE | PTR | MPTR);
if (!(targetType instanceof ICPPFunctionType))

View file

@ -17,7 +17,9 @@ 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.InstantiationContext.getContextClassSpecialization;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.ALLCVQ;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.CVTYPE;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.REF;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.TDEF;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.getNestedType;
@ -2276,7 +2278,7 @@ public class CPPTemplates {
IBinding instance= instantiateFunctionTemplate(template, args, map, point);
if (instance instanceof ICPPFunction) {
final ICPPFunction f = (ICPPFunction) instance;
if (SemanticUtil.isValidType(f.getType())) {
if (isValidFunctionType(f.getType())) {
// The number of arguments have been checked against the function
// template's required argument count at an earlier stage. However,
// the process of instantiation can increase the required argument
@ -2294,6 +2296,22 @@ public class CPPTemplates {
return null;
}
/**
* Checks if the given function type is problem-free and that the return type is not a function set.
*/
public static boolean isValidFunctionType(IFunctionType type) {
if (!SemanticUtil.isValidType(type))
return false;
IType t = type.getReturnType();
t = SemanticUtil.getNestedType(t, ALLCVQ | TDEF | REF);
if (t instanceof IPointerType)
t = ((IPointerType) t).getType();
if (t instanceof FunctionSetType)
return false;
return true;
}
/**
* 14.8.2.3 Deducing conversion function template arguments
* @param point

View file

@ -716,7 +716,7 @@ public class Conversions {
}
}
}
final IBinding result= CPPSemantics.resolveFunction(data, filteredConstructors, true);
final IBinding result= CPPSemantics.resolveFunction(data, filteredConstructors, true, false);
final Cost c;
if (result instanceof ICPPMethod) {
c= new Cost(arg.getType(point), t, Rank.IDENTITY);

View file

@ -338,7 +338,7 @@ public class EvalFunctionSet extends CPPDependentEvaluation {
}
// Perform template instantiation and overload resolution.
IBinding binding = CPPSemantics.resolveFunction(data, functions, true);
IBinding binding = CPPSemantics.resolveFunction(data, functions, true, true);
if (binding == null || binding instanceof IProblemBinding)
return EvalFixed.INCOMPLETE;
if (binding instanceof ICPPFunction && !(binding instanceof ICPPUnknownBinding))

View file

@ -282,7 +282,7 @@ public class EvalTypeId extends CPPDependentEvaluation {
data.foundItems = constructors;
data.setFunctionArguments(false, arguments);
try {
IBinding binding = CPPSemantics.resolveFunction(data, constructors, true);
IBinding binding = CPPSemantics.resolveFunction(data, constructors, true, false);
if (binding instanceof ICPPFunction) {
return (ICPPFunction) binding;
}

View file

@ -1082,7 +1082,7 @@ public class BindingClassifier {
lookupData.setFunctionArguments(false, new IASTInitializerClause[] { argument });
lookupData.qualified = true;
try {
IBinding constructor = CPPSemantics.resolveFunction(lookupData, ClassTypeHelper.getConstructors(classType, argument), false);
IBinding constructor = CPPSemantics.resolveFunction(lookupData, ClassTypeHelper.getConstructors(classType, argument), false, false);
if (constructor instanceof ICPPConstructor && !((ICPPConstructor) constructor).isExplicit())
return true;
} catch (DOMException e) {