1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-23 14:42:11 +02:00

Resolution of functions with dependent arguments, bug 265926.

This commit is contained in:
Markus Schorn 2009-02-24 14:06:33 +00:00
parent 1dbc6e0877
commit a401523e2f
7 changed files with 165 additions and 137 deletions

View file

@ -3893,4 +3893,17 @@ public class AST2TemplateTests extends AST2BaseTest {
parseAndCheckBindings(code, ParserLanguage.CPP);
}
// template <typename T> void f(T t) {
// g(t);
// }
// template <typename T> void g(T t) {}
public void testDependentNameReferencingLaterDeclaration_265926() throws Exception {
final String code = getAboveComment();
BindingAssertionHelper bh= new BindingAssertionHelper(code, true);
IFunction gref= bh.assertNonProblem("g(t)", 1);
assertInstance(gref, ICPPUnknownBinding.class);
IFunction gdecl= bh.assertNonProblem("g(T t)", 1);
parseAndCheckBindings(code, ParserLanguage.CPP);
}
}

View file

@ -700,6 +700,9 @@ public class ASTTypeUtil {
result.addFirst(new String(name));
}
}
if (owner instanceof ICPPTemplateParameter)
break;
owner= owner.getOwner();
}
return result.toArray(new String[result.size()]);

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2004, 2008 IBM Corporation and others.
* Copyright (c) 2004, 2009 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@ -8,10 +8,6 @@
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
/*
* Created on Jul 15, 2004
*/
package org.eclipse.cdt.core.parser.util;
import java.util.Collections;
@ -33,6 +29,13 @@ public class ObjectSet<T> extends ObjectTable<T> {
@Override public void addAll( ObjectSet set ) { throw new UnsupportedOperationException(); }
};
/**
* @since 5.1
*/
@SuppressWarnings("unchecked")
public static <T> ObjectSet<T> emptySet() {
return EMPTY_SET;
}
/**
* Construct an empty ObjectSet, allocating an initial storage for the specified
* number of elements

View file

@ -382,7 +382,7 @@ public class CPPSemantics {
// if the lookup in base-classes ran into a deferred instance, use the computed unknown binding.
final ASTNodeProperty namePropertyInParent = name.getPropertyInParent();
if (binding == null && data.skippedScope != null) {
if (data.functionParameters != null) {
if (data.hasArgumentTypes()) {
binding= new CPPUnknownFunction(data.skippedScope, name.getSimpleID());
} else {
if (namePropertyInParent == IASTNamedTypeSpecifier.NAME) {
@ -441,10 +441,6 @@ public class CPPSemantics {
LookupData data = new LookupData(name);
IASTNode parent = name.getParent();
if (name instanceof ICPPASTTemplateId) {
data.templateId= ((ICPPASTTemplateId)name);
}
if (parent instanceof ICPPASTTemplateId)
parent = parent.getParent();
if (parent instanceof ICPPASTQualifiedName)
@ -457,7 +453,7 @@ public class CPPSemantics {
}
if (parent instanceof ICPPASTFunctionDeclarator) {
data.functionParameters = ((ICPPASTFunctionDeclarator)parent).getParameters();
data.setFunctionParameters(((ICPPASTFunctionDeclarator)parent).getParameters());
} else if (parent instanceof IASTIdExpression) {
IASTNode grand= parent.getParent();
while (grand instanceof IASTUnaryExpression
@ -468,12 +464,7 @@ public class CPPSemantics {
if (parent.getPropertyInParent() == IASTFunctionCallExpression.FUNCTION_NAME) {
parent = parent.getParent();
IASTExpression exp = ((IASTFunctionCallExpression)parent).getParameterExpression();
if (exp instanceof IASTExpressionList)
data.functionParameters = ((IASTExpressionList) exp).getExpressions();
else if (exp != null)
data.functionParameters = new IASTExpression[] { exp };
else
data.functionParameters = IASTExpression.EMPTY_EXPRESSION_ARRAY;
data.setFunctionArguments(exp);
}
} else if (parent instanceof ICPPASTFieldReference) {
IASTNode grand= parent.getParent();
@ -484,34 +475,19 @@ public class CPPSemantics {
}
if (parent.getPropertyInParent() == IASTFunctionCallExpression.FUNCTION_NAME) {
IASTExpression exp = ((IASTFunctionCallExpression)parent.getParent()).getParameterExpression();
if (exp instanceof IASTExpressionList)
data.functionParameters = ((IASTExpressionList) exp).getExpressions();
else if (exp != null)
data.functionParameters = new IASTExpression[] { exp };
else
data.functionParameters = IASTExpression.EMPTY_EXPRESSION_ARRAY;
data.setFunctionArguments(exp);
}
} else if (parent instanceof ICPPASTNamedTypeSpecifier && parent.getParent() instanceof IASTTypeId) {
IASTTypeId typeId = (IASTTypeId) parent.getParent();
if (typeId.getParent() instanceof ICPPASTNewExpression) {
ICPPASTNewExpression newExp = (ICPPASTNewExpression) typeId.getParent();
IASTExpression init = newExp.getNewInitializer();
if (init instanceof IASTExpressionList)
data.functionParameters = ((IASTExpressionList) init).getExpressions();
else if (init != null)
data.functionParameters = new IASTExpression[] { init };
else
data.functionParameters = IASTExpression.EMPTY_EXPRESSION_ARRAY;
data.setFunctionArguments(init);
}
} else if (parent instanceof ICPPASTConstructorChainInitializer) {
ICPPASTConstructorChainInitializer ctorinit = (ICPPASTConstructorChainInitializer) parent;
IASTExpression val = ctorinit.getInitializerValue();
if (val instanceof IASTExpressionList)
data.functionParameters = ((IASTExpressionList) val).getExpressions();
else if (val != null)
data.functionParameters = new IASTExpression[] { val };
else
data.functionParameters = IASTExpression.EMPTY_EXPRESSION_ARRAY;
data.setFunctionArguments(val);
}
if (considerAssociatedScopes && !(name.getParent() instanceof ICPPASTQualifiedName) && data.functionCall()) {
@ -522,7 +498,10 @@ public class CPPSemantics {
}
static private ObjectSet<IScope> getAssociatedScopes(LookupData data) {
IType[] ps = getArgumentTypes(data.functionParameters);
if (!data.hasArgumentTypes())
return ObjectSet.emptySet();
IType[] ps = data.getFunctionArgumentTypes();
ObjectSet<IScope> namespaces = new ObjectSet<IScope>(2);
ObjectSet<ICPPClassType> classes = new ObjectSet<ICPPClassType>(2);
for (IType p : ps) {
@ -1841,13 +1820,11 @@ public class CPPSemantics {
if (functions == null || functions.length == 0)
return;
final Object[] funcArgs = data.functionParameters;
int numArgs = (funcArgs != null) ? funcArgs.length : 0;
final boolean def = data.forFunctionDeclaration();
int numArgs= data.getFunctionArgumentCount();
if (def && numArgs == 1) {
// check for parameter of type void
IType[] argTypes= getArgumentTypes(funcArgs);
final IType[] argTypes = data.getFunctionArgumentTypes();
if (argTypes.length == 1) {
IType t= getNestedType(argTypes[0], TDEF);
if (t instanceof IBasicType && ((IBasicType)t).getType() == IBasicType.t_void) {
@ -1915,32 +1892,6 @@ public class CPPSemantics {
return false;
}
static private IType[] getArgumentTypes(Object[] args) {
if (args instanceof IType[]) {
return (IType[]) args;
}
if (args == null || args.length == 0)
return IType.EMPTY_TYPE_ARRAY;
if (args instanceof IASTExpression[]) {
IASTExpression[] exps = (IASTExpression[]) args;
IType[] result = new IType[exps.length];
for (int i = 0; i < exps.length; i++) {
result[i] = exps[i].getExpressionType();
}
return result;
} else if (args instanceof IASTParameterDeclaration[]) {
IASTParameterDeclaration[] decls = (IASTParameterDeclaration[]) args;
IType[] result = new IType[decls.length];
for (int i = 0; i < args.length; i++) {
result[i] = CPPVisitor.createType(decls[i].getDeclarator());
}
return result;
}
return null;
}
static IBinding resolveFunction(LookupData data, IFunction[] fns, boolean allowUDC) throws DOMException {
fns= (IFunction[]) ArrayUtil.trim(IFunction.class, fns);
if (fns == null || fns.length == 0)
@ -1951,12 +1902,12 @@ public class CPPSemantics {
}
// We don't have any arguments with which to resolve the function
if (data.functionParameters == null) {
if (!data.hasArgumentTypes()) {
return resolveTargetedFunction(data, fns);
}
if (!data.forFunctionDeclaration() || data.forExplicitFunctionSpecialization()) {
CPPTemplates.instantiateFunctionTemplates(fns, data.functionParameters, data.astName);
CPPTemplates.instantiateFunctionTemplates(fns, data.getFunctionArgumentTypes(), data.astName);
}
if (data.astName instanceof ICPPASTConversionName) {
@ -1982,8 +1933,8 @@ public class CPPSemantics {
return firstViable;
// The arguments the function is being called with
final Object[] args= data.functionParameters;
final IType[] argTypes = getArgumentTypes(data.functionParameters);
final IASTExpression[] args= data.getFunctionArguments();
IType[] argTypes = data.getFunctionArgumentTypes();
if (CPPTemplates.containsDependentType(argTypes)) {
if (viableCount == 1)
return firstViable;
@ -2101,7 +2052,7 @@ public class CPPSemantics {
return bestFn;
}
private static Cost[] costForFunctionCall(IFunction fn, IType thisType, IType[] argTypes, Object[] args,
private static Cost[] costForFunctionCall(IFunction fn, IType thisType, IType[] argTypes, IASTExpression[] args,
boolean allowUDC) throws DOMException {
final ICPPFunctionType ftype= (ICPPFunctionType) fn.getType();
if (ftype == null)
@ -2143,12 +2094,11 @@ public class CPPSemantics {
for (int j = 0; j < sourceLen; j++) {
final IType argType= argTypes[j];
final Object arg= j < args.length ? args[j] : null;
final IASTExpression argExpr= (arg instanceof IASTExpression) ? (IASTExpression) arg : null;
if (argType == null)
return null;
final IASTExpression arg= args != null && j < args.length ? args[j] : null;
IType paramType;
if (j < paramTypes.length) {
paramType= paramTypes[j];
@ -2167,7 +2117,7 @@ public class CPPSemantics {
} else {
if (CPPTemplates.isDependentType(paramType))
return CONTAINS_DEPENDENT_TYPES;
cost = Conversions.checkImplicitConversionSequence(argExpr, argType, paramType, allowUDC, false);
cost = Conversions.checkImplicitConversionSequence(arg, argType, paramType, allowUDC, false);
}
if (cost.rank < 0)
return null;
@ -2553,29 +2503,22 @@ public class CPPSemantics {
astName.setName(OverloadableOperator.STAR.toCharArray());
data = new LookupData(astName);
data.forceQualified = true;
data.functionParameters = IASTExpression.EMPTY_EXPRESSION_ARRAY;
data.setFunctionArguments(IASTExpression.EMPTY_EXPRESSION_ARRAY);
} else if (exp instanceof IASTArraySubscriptExpression) {
astName.setName(OverloadableOperator.BRACKET.toCharArray());
data = new LookupData(astName);
data.forceQualified = true;
data.functionParameters = new IASTExpression[] { ((IASTArraySubscriptExpression) exp).getSubscriptExpression() };
data.setFunctionArguments(((IASTArraySubscriptExpression) exp).getSubscriptExpression());
} else if (exp instanceof IASTFieldReference) {
astName.setName(OverloadableOperator.ARROW.toCharArray());
data = new LookupData(astName);
data.forceQualified = true;
data.functionParameters = IASTExpression.EMPTY_EXPRESSION_ARRAY;
data.setFunctionArguments(IASTExpression.EMPTY_EXPRESSION_ARRAY);
} else if (exp instanceof IASTFunctionCallExpression) {
astName.setName(OverloadableOperator.PAREN.toCharArray());
data = new LookupData(astName);
data.forceQualified = true;
final IASTExpression paramExpression = ((IASTFunctionCallExpression) exp).getParameterExpression();
if (paramExpression == null) {
data.functionParameters= IASTExpression.EMPTY_EXPRESSION_ARRAY;
} else if (paramExpression instanceof IASTExpressionList) {
data.functionParameters= ((IASTExpressionList) paramExpression).getExpressions();
} else {
data.functionParameters = new IASTExpression[] {paramExpression};
}
data.setFunctionArguments(((IASTFunctionCallExpression) exp).getParameterExpression());
} else if (exp instanceof IASTBinaryExpression) {
final IASTBinaryExpression binary = (IASTBinaryExpression) exp;
OverloadableOperator operator = OverloadableOperator.fromBinaryExpression(binary);
@ -2585,7 +2528,7 @@ public class CPPSemantics {
astName.setName(operator.toCharArray());
data = new LookupData(astName);
data.forceQualified = true;
data.functionParameters = new IASTExpression[] { binary.getOperand2() };
data.setFunctionArguments(new IASTExpression[] { binary.getOperand2() });
} else {
return null;
}
@ -2621,7 +2564,7 @@ public class CPPSemantics {
astName.setPropertyInParent(STRING_LOOKUP_PROPERTY);
astName.setName(operator.toCharArray());
LookupData data = new LookupData(astName);
data.functionParameters = new IASTExpression[] { exp.getOperand1(), exp.getOperand2() };
data.setFunctionArguments(new IASTExpression[] {exp.getOperand1(), exp.getOperand2()});
try {
lookup(data, scope);

View file

@ -1310,41 +1310,8 @@ public class CPPTemplates {
return result;
}
/*
* aftodo - need to review this
*/
static public IType[] createTypeArray(Object[] params) {
if (params == null)
return IType.EMPTY_TYPE_ARRAY;
if (params instanceof IType[])
return (IType[]) params;
IType[] result = new IType[params.length];
for (int i = 0; i < params.length; i++) {
IType type= null;
final Object param = params[i];
if (param instanceof IASTNode) {
type= CPPVisitor.createType((IASTNode) param);
} else if (param instanceof IParameter) {
try {
type= ((IParameter) param).getType();
} catch (DOMException e) {
type= e.getProblem();
}
}
// prevent null pointer exception when the type cannot be determined
// happens when templates with still ambiguous template-ids are accessed during
// resolution of other ambiguities.
result[i]= type == null ? new CPPBasicType(-1, 0) : type;
}
return result;
}
static protected void instantiateFunctionTemplates(IFunction[] functions,
Object[] functionArguments, IASTName name) {
static protected void instantiateFunctionTemplates(IFunction[] functions, IType[] fnArgs, IASTName name) {
ICPPTemplateArgument[] templateArguments= null;
IType[] fnArgs= null;
for (int i = 0; i < functions.length; i++) {
IFunction func = functions[i];
if (func instanceof ICPPFunctionTemplate) {
@ -1354,7 +1321,6 @@ public class CPPTemplates {
// 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);

View file

@ -14,7 +14,13 @@
*******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.*;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.CVQ;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.PTR_CVQ;
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.addQualifiers;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.getNestedType;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.getUltimateType;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.dom.ast.DOMException;
@ -354,7 +360,7 @@ public class Conversions {
}
if (j > 0) {
LookupData data= new LookupData();
data.functionParameters= new IType [] { source };
data.setFunctionArgumentTypes(new IType [] { source });
IBinding binding = CPPSemantics.resolveFunction(data, convertingCtors, false);
if (binding instanceof ICPPConstructor && !(binding instanceof IProblemBinding)) {
constructorCost = checkStandardConversionSequence(t, target, false);

View file

@ -26,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.IASTExpressionList;
import org.eclipse.cdt.core.dom.ast.IASTFieldReference;
import org.eclipse.cdt.core.dom.ast.IASTFunctionCallExpression;
import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition;
@ -34,6 +35,7 @@ import org.eclipse.cdt.core.dom.ast.IASTInitializer;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNamedTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTParameterDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTTypeId;
import org.eclipse.cdt.core.dom.ast.IPointerType;
@ -102,8 +104,8 @@ public class LookupData {
public ICPPClassType skippedScope;
public Object foundItems = null;
public Object[] functionParameters;
public ICPPASTTemplateId templateId;
private Object[] functionArgs;
private IType[] functionArgTypes;
public ProblemBinding problem;
public LookupData(IASTName n) {
@ -512,4 +514,96 @@ public class LookupData {
return false;
return (astName instanceof ICPPASTTemplateId || astName.getPropertyInParent() == ICPPASTTemplateId.TEMPLATE_NAME);
}
public void setFunctionArguments(IASTExpression args) {
IASTExpression[] exprs;
if (args instanceof IASTExpressionList) {
ASTNodeProperty prop = args.getPropertyInParent();
if (prop == IASTFunctionCallExpression.PARAMETERS || prop == ICPPASTNewExpression.NEW_INITIALIZER
|| prop == ICPPASTConstructorChainInitializer.INITIALIZER) {
exprs= ((IASTExpressionList) args).getExpressions();
} else {
exprs= new IASTExpression[] {args};
}
} else if (args != null) {
exprs= new IASTExpression[] { args };
} else {
exprs = IASTExpression.EMPTY_EXPRESSION_ARRAY;
}
setFunctionArguments(exprs);
}
public void setFunctionArguments(IASTExpression[] exprs) {
functionArgs= exprs;
if (exprs.length != 0) {
IASTNode node= exprs[0];
boolean checkForDependentName= false;
while (node != null) {
if (node instanceof ICPPASTTemplateDeclaration) {
checkForDependentName= true;
break;
}
node= node.getParent();
}
if (checkForDependentName) {
IType[] types= getFunctionArgumentTypes();
for (int i = 0; i < types.length; i++) {
if (CPPTemplates.isDependentType(types[i])) {
checkPointOfDecl= false;
break;
}
}
}
}
}
public IType[] getFunctionArgumentTypes() {
if (functionArgTypes == null && functionArgs != null) {
if (functionArgs instanceof IASTParameterDeclaration[]) {
IASTParameterDeclaration[] pdecls= (IASTParameterDeclaration[]) functionArgs;
functionArgTypes= new IType[pdecls.length];
for (int i = 0; i < pdecls.length; i++) {
IASTParameterDeclaration p = pdecls[i];
functionArgTypes[i]= CPPVisitor.createType(p.getDeclarator());
}
} else if (functionArgs instanceof IASTExpression[]) {
IASTExpression[] exprs= (IASTExpression[]) functionArgs;
functionArgTypes= new IType[exprs.length];
for (int i = 0; i < exprs.length; i++) {
IASTExpression e = exprs[i];
IType etype= e.getExpressionType();
functionArgTypes[i]= etype;
}
}
}
return functionArgTypes;
}
public void setFunctionArgumentTypes(IType[] paramTypes) {
functionArgTypes= paramTypes;
}
public void setFunctionParameters(IASTParameterDeclaration[] parameters) {
functionArgs= parameters;
}
public IASTExpression[] getFunctionArguments() {
if (functionArgs instanceof IASTExpression[])
return (IASTExpression[]) functionArgs;
return null;
}
public int getFunctionArgumentCount() {
if (functionArgs != null)
return functionArgs.length;
if (functionArgTypes != null)
return functionArgTypes.length;
return 0;
}
public boolean hasArgumentTypes() {
return functionArgTypes != null || functionArgs != null;
}
}