mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-07-24 09:25:31 +02:00
Bug 85843: ADL for overloaded function sets.
This commit is contained in:
parent
497b9282a8
commit
4720831a18
16 changed files with 809 additions and 442 deletions
|
@ -66,7 +66,7 @@ public class ASTCPPSpecDefectTests extends AST2BaseTest {
|
|||
// void test() {
|
||||
// fp(f0);
|
||||
// }
|
||||
public void _testADLForOverloadSet_324842() throws Exception {
|
||||
public void testADLForOverloadSet_324842() throws Exception {
|
||||
parseAndCheckBindings();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -445,7 +445,7 @@ public class IndexCPPTemplateResolutionTest extends IndexBindingResolutionTestBa
|
|||
// A<B> a;
|
||||
// a.f= foo<B>;
|
||||
// }
|
||||
public void _testOverloadedFunctionTemplate() {
|
||||
public void testOverloadedFunctionTemplate() {
|
||||
IBinding b0= getBindingFromASTName("foo<B>;", 6);
|
||||
assertInstance(b0, ICPPFunction.class);
|
||||
assertInstance(b0, ICPPSpecialization.class);
|
||||
|
|
|
@ -14,6 +14,7 @@ package org.eclipse.cdt.internal.core.dom.parser.cpp;
|
|||
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.core.dom.ast.IASTExpression.ValueCategory.XVALUE;
|
||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExpressionTypes.prvalueType;
|
||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.*;
|
||||
|
||||
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
|
||||
|
@ -213,46 +214,50 @@ public class CPPASTConditionalExpression extends ASTNode implements IASTConditio
|
|||
|
||||
final ValueCategory vcat2= expr2.getValueCategory();
|
||||
final ValueCategory vcat3= expr3.getValueCategory();
|
||||
final boolean isClassType2 = uqt2 instanceof ICPPClassType;
|
||||
final boolean isClassType3 = uqt3 instanceof ICPPClassType;
|
||||
|
||||
// Same type and same value category
|
||||
// Same type
|
||||
if (t2.isSameType(t3)) {
|
||||
if (vcat2 == vcat3) {
|
||||
fType= t2;
|
||||
fValueCategory= vcat2;
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// Different types with at least one class type
|
||||
if (isClassType2 || isClassType3) {
|
||||
final Cost cost2= convertToMatch(t2, vcat2, uqt2, t3, vcat3, uqt3); // sets fType and fValueCategory
|
||||
final Cost cost3= convertToMatch(t3, vcat3, uqt3, t2, vcat2, uqt2); // sets fType and fValueCategory
|
||||
if (cost2.converts() || cost3.converts()) {
|
||||
if (cost2.converts()) {
|
||||
if (cost3.converts() || cost2.isAmbiguousUDC()) {
|
||||
fType= createProblem();
|
||||
}
|
||||
} else if (cost3.isAmbiguousUDC()) {
|
||||
} else {
|
||||
fType= prvalueType(t2);
|
||||
fValueCategory= PRVALUE;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
final boolean isClassType2 = uqt2 instanceof ICPPClassType;
|
||||
final boolean isClassType3 = uqt3 instanceof ICPPClassType;
|
||||
|
||||
// Different types with at least one class type
|
||||
if (isClassType2 || isClassType3) {
|
||||
final Cost cost2= convertToMatch(t2, vcat2, uqt2, t3, vcat3, uqt3); // sets fType and fValueCategory
|
||||
final Cost cost3= convertToMatch(t3, vcat3, uqt3, t2, vcat2, uqt2); // sets fType and fValueCategory
|
||||
if (cost2.converts() || cost3.converts()) {
|
||||
if (cost2.converts()) {
|
||||
if (cost3.converts() || cost2.isAmbiguousUDC()) {
|
||||
fType= createProblem();
|
||||
}
|
||||
return;
|
||||
}
|
||||
} else if (vcat2 == vcat3 && vcat2.isGLValue() && uqt2.isSameType(uqt3)) {
|
||||
// Two lvalues or two xvalues with same type up to qualification.
|
||||
final CVQualifier cv2 = SemanticUtil.getCVQualifier(t2);
|
||||
final CVQualifier cv3 = SemanticUtil.getCVQualifier(t3);
|
||||
if (cv2.isAtLeastAsQualifiedAs(cv3)) {
|
||||
fType= t2;
|
||||
fValueCategory= vcat2;
|
||||
} else if (cv3.isAtLeastAsQualifiedAs(cv2)) {
|
||||
fType= t3;
|
||||
fValueCategory= vcat3;
|
||||
} else {
|
||||
createProblem();
|
||||
} else if (cost3.isAmbiguousUDC()) {
|
||||
fType= createProblem();
|
||||
}
|
||||
return;
|
||||
}
|
||||
} else if (vcat2 == vcat3 && vcat2.isGLValue() && uqt2.isSameType(uqt3)) {
|
||||
// Two lvalues or two xvalues with same type up to qualification.
|
||||
final CVQualifier cv2 = SemanticUtil.getCVQualifier(t2);
|
||||
final CVQualifier cv3 = SemanticUtil.getCVQualifier(t3);
|
||||
if (cv2.isAtLeastAsQualifiedAs(cv3)) {
|
||||
fType= t2;
|
||||
fValueCategory= vcat2;
|
||||
} else if (cv3.isAtLeastAsQualifiedAs(cv2)) {
|
||||
fType= t3;
|
||||
fValueCategory= vcat3;
|
||||
} else {
|
||||
createProblem();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// 5.16-5: At least one class type but no conversion
|
||||
|
|
|
@ -14,8 +14,7 @@ package org.eclipse.cdt.internal.core.dom.parser.cpp;
|
|||
|
||||
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.ExpressionTypes.typeFromFunctionCall;
|
||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExpressionTypes.valueCategoryFromFunctionCall;
|
||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExpressionTypes.*;
|
||||
|
||||
import org.eclipse.cdt.core.dom.ast.ASTNodeProperty;
|
||||
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
|
||||
|
@ -155,22 +154,26 @@ public class CPPASTExpressionList extends ASTNode implements ICPPASTExpressionLi
|
|||
return overloads = NO_FUNCTIONS;
|
||||
|
||||
overloads = new ICPPFunction[exprs.length-1];
|
||||
IType lookupType = exprs[0].getExpressionType();
|
||||
IType lookupType = typeOrFunctionSet(exprs[0]);
|
||||
ValueCategory vcat= valueCat(exprs[0]);
|
||||
|
||||
for(int i = 1; i < exprs.length; i++) {
|
||||
IASTExpression e1 = exprs[i-1], e2 = exprs[i];
|
||||
ICPPFunction overload = CPPSemantics.findOverloadedOperatorComma(e1, e2, lookupType);
|
||||
if(overload == null) {
|
||||
lookupType = e2.getExpressionType();
|
||||
}
|
||||
else {
|
||||
overloads[i-1] = overload;
|
||||
try {
|
||||
for (int i = 1; i < exprs.length; i++) {
|
||||
IASTExpression e1 = exprs[i - 1], e2 = exprs[i];
|
||||
ICPPFunction overload = CPPSemantics.findOverloadedOperatorComma(e1, lookupType, vcat, e2);
|
||||
if (overload == null) {
|
||||
lookupType = typeOrFunctionSet(e2);
|
||||
vcat= valueCat(e2);
|
||||
} else {
|
||||
overloads[i - 1] = overload;
|
||||
try {
|
||||
lookupType = overload.getType().getReturnType();
|
||||
vcat= valueCategoryFromReturnType(lookupType);
|
||||
lookupType= typeFromReturnType(lookupType);
|
||||
} catch (DOMException e) {
|
||||
lookupType = e2.getExpressionType();
|
||||
lookupType = typeOrFunctionSet(e2);
|
||||
vcat= valueCat(e2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -42,6 +42,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
|
|||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateNonTypeParameter;
|
||||
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPFunctionSet;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil;
|
||||
|
@ -108,6 +109,9 @@ public class CPPASTIdExpression extends ASTNode implements IASTIdExpression, ICP
|
|||
|
||||
public IType getExpressionType() {
|
||||
IBinding binding = name.resolvePreBinding();
|
||||
if (binding instanceof CPPFunctionSet)
|
||||
binding= name.resolveBinding();
|
||||
|
||||
if (checkForTransformation(binding)) {
|
||||
return fTransformedExpression.getExpressionType();
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPParameter;
|
|||
*/
|
||||
public class CPPUnknownFunction extends CPPUnknownBinding implements ICPPFunction {
|
||||
|
||||
public static IFunction createForSample(IFunction sample) throws DOMException {
|
||||
public static ICPPFunction createForSample(IFunction sample) throws DOMException {
|
||||
if (sample instanceof ICPPConstructor)
|
||||
return new CPPUnknownConstructor(((ICPPConstructor) sample).getClassOwner());
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics;
|
||||
|
||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExpressionTypes.typeOrFunctionSet;
|
||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
@ -83,13 +84,13 @@ class BuiltinOperators {
|
|||
fUnary= args.length<2;
|
||||
fGlobalCandidates= globCandidates;
|
||||
if (args.length > 0 && args[0] instanceof IASTExpression) {
|
||||
IType type= ((IASTExpression) args[0]).getExpressionType();
|
||||
IType type= typeOrFunctionSet((IASTExpression) args[0]);
|
||||
if (!(type instanceof IProblemBinding))
|
||||
fType1= type;
|
||||
|
||||
}
|
||||
if (args.length > 1 && args[1] instanceof IASTExpression) {
|
||||
IType type= ((IASTExpression) args[1]).getExpressionType();
|
||||
IType type= typeOrFunctionSet((IASTExpression) args[1]);
|
||||
if (!(type instanceof IProblemBinding))
|
||||
fType2= type;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* CPPFunctionSet.java
|
||||
* Created on Sep 13, 2010
|
||||
*
|
||||
* Copyright 2010 Wind River Systems, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics;
|
||||
|
||||
import org.eclipse.cdt.core.dom.ILinkage;
|
||||
import org.eclipse.cdt.core.dom.ast.DOMException;
|
||||
import org.eclipse.cdt.core.dom.ast.IBinding;
|
||||
import org.eclipse.cdt.core.dom.ast.IScope;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction;
|
||||
import org.eclipse.cdt.core.parser.util.ArrayUtil;
|
||||
import org.eclipse.cdt.internal.core.dom.Linkage;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTNameBase;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPTwoPhaseBinding;
|
||||
|
||||
/**
|
||||
* Used as intermediate binding for names nominating a function without calling it.
|
||||
* The actual function can be resolved in certain contexts.
|
||||
*/
|
||||
public class CPPFunctionSet implements ICPPTwoPhaseBinding {
|
||||
|
||||
final ICPPFunction[] fBindings;
|
||||
|
||||
public CPPFunctionSet(ICPPFunction[] bindingList) {
|
||||
fBindings = ArrayUtil.removeNulls(bindingList);
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return fBindings[0].getName();
|
||||
}
|
||||
|
||||
public char[] getNameCharArray() {
|
||||
return fBindings[0].getNameCharArray();
|
||||
}
|
||||
|
||||
public IScope getScope() throws DOMException {
|
||||
return fBindings[0].getScope();
|
||||
}
|
||||
|
||||
public IBinding getOwner() {
|
||||
return fBindings[0].getOwner();
|
||||
}
|
||||
|
||||
public ICPPFunction[] getBindings() {
|
||||
return fBindings;
|
||||
}
|
||||
|
||||
public ILinkage getLinkage() {
|
||||
return Linkage.CPP_LINKAGE;
|
||||
}
|
||||
|
||||
public IBinding resolveFinalBinding(CPPASTNameBase astName) {
|
||||
return CPPSemantics.resolveTargetedFunction(astName, fBindings);
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public Object getAdapter(@SuppressWarnings("rawtypes") Class adapter) {
|
||||
if (adapter.isAssignableFrom(getClass()))
|
||||
return this;
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -17,6 +17,8 @@ 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.ExpressionTypes.typeOrFunctionSet;
|
||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExpressionTypes.valueCat;
|
||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
@ -51,6 +53,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.IASTImplicitNameOwner;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTInitializer;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTInitializerClause;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTLabelStatement;
|
||||
|
@ -150,7 +153,6 @@ import org.eclipse.cdt.core.index.IIndexBinding;
|
|||
import org.eclipse.cdt.core.index.IIndexFile;
|
||||
import org.eclipse.cdt.core.index.IIndexFileSet;
|
||||
import org.eclipse.cdt.core.index.IIndexName;
|
||||
import org.eclipse.cdt.core.parser.IProblem;
|
||||
import org.eclipse.cdt.core.parser.util.ArrayUtil;
|
||||
import org.eclipse.cdt.core.parser.util.CharArrayObjectMap;
|
||||
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
|
||||
|
@ -642,7 +644,7 @@ public class CPPSemantics {
|
|||
return data;
|
||||
}
|
||||
|
||||
static private Set<ICPPNamespaceScope> getAssociatedScopes(LookupData data) {
|
||||
private static Set<ICPPNamespaceScope> getAssociatedScopes(LookupData data) {
|
||||
if (!data.hasFunctionArguments())
|
||||
return Collections.emptySet();
|
||||
|
||||
|
@ -659,7 +661,7 @@ public class CPPSemantics {
|
|||
return namespaces;
|
||||
}
|
||||
|
||||
static private void getAssociatedScopes(IType t, Set<ICPPNamespaceScope> namespaces,
|
||||
private static void getAssociatedScopes(IType t, Set<ICPPNamespaceScope> namespaces,
|
||||
ObjectSet<ICPPClassType> classes, CPPASTTranslationUnit tu) throws DOMException {
|
||||
// 3.4.2-2
|
||||
if (t instanceof ICPPClassType) {
|
||||
|
@ -691,11 +693,15 @@ public class CPPSemantics {
|
|||
} else if (t instanceof ICPPPointerToMemberType) {
|
||||
IType binding = ((ICPPPointerToMemberType) t).getMemberOfClass();
|
||||
getAssociatedScopes(binding, namespaces, classes, tu);
|
||||
}
|
||||
return;
|
||||
} else if (t instanceof FunctionSetType) {
|
||||
FunctionSetType fst= (FunctionSetType) t;
|
||||
for (ICPPFunction fn : fst.getFunctionSet()) {
|
||||
getAssociatedScopes(fn.getType(), namespaces, classes, tu);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static private ICPPNamespaceScope getContainingNamespaceScope(IBinding binding,
|
||||
private static ICPPNamespaceScope getContainingNamespaceScope(IBinding binding,
|
||||
CPPASTTranslationUnit tu) throws DOMException {
|
||||
if (binding == null)
|
||||
return null;
|
||||
|
@ -1099,7 +1105,7 @@ public class CPPSemantics {
|
|||
public int visit(IASTExpression expression) {
|
||||
if (expression instanceof IASTLiteralExpression) {
|
||||
if (((IASTLiteralExpression) expression).getKind() == IASTLiteralExpression.lk_this) {
|
||||
final IType thisType = SemanticUtil.getNestedType(expression.getExpressionType(), TDEF | ALLCVQ | PTR | ARRAY | MPTR | REF);
|
||||
final IType thisType = SemanticUtil.getNestedType(typeOrFunctionSet(expression), TDEF | ALLCVQ | PTR | ARRAY | MPTR | REF);
|
||||
if (thisType instanceof ICPPUnknownBinding || thisType instanceof ICPPTemplateDefinition) {
|
||||
result[0]= true;
|
||||
return PROCESS_ABORT;
|
||||
|
@ -1250,7 +1256,7 @@ public class CPPSemantics {
|
|||
* In case of an unqualified lookup the transitive directives are stored, also. This is important because
|
||||
* the members nominated by a transitive directive can appear before those of the original directive.
|
||||
*/
|
||||
static private void storeUsingDirective(LookupData data, ICPPNamespaceScope container,
|
||||
private static void storeUsingDirective(LookupData data, ICPPNamespaceScope container,
|
||||
ICPPUsingDirective directive, Set<ICPPNamespaceScope> handled) throws DOMException {
|
||||
ICPPNamespaceScope nominated= directive.getNominatedScope();
|
||||
if (nominated instanceof IIndexScope && data.tu != null) {
|
||||
|
@ -1291,7 +1297,7 @@ public class CPPSemantics {
|
|||
/**
|
||||
* Computes the common enclosing scope of s1 and s2.
|
||||
*/
|
||||
static private ICPPScope getCommonEnclosingScope(IScope s1, IScope s2, CPPASTTranslationUnit tu) throws DOMException {
|
||||
private static ICPPScope getCommonEnclosingScope(IScope s1, IScope s2, CPPASTTranslationUnit tu) throws DOMException {
|
||||
ObjectSet<IScope> set = new ObjectSet<IScope>(2);
|
||||
IScope parent= s1;
|
||||
while (parent != null) {
|
||||
|
@ -1629,7 +1635,7 @@ public class CPPSemantics {
|
|||
* are considered if the lookup of the original directive returns empty.
|
||||
* @param fileSet
|
||||
*/
|
||||
static private void lookupInNominated(LookupData data, IIndexFileSet fileSet, ICPPNamespaceScope scope) throws DOMException {
|
||||
private static void lookupInNominated(LookupData data, IIndexFileSet fileSet, ICPPNamespaceScope scope) throws DOMException {
|
||||
List<ICPPNamespaceScope> allNominated= data.usingDirectives.remove(scope);
|
||||
while (allNominated != null) {
|
||||
for (ICPPNamespaceScope nominated : allNominated) {
|
||||
|
@ -1821,13 +1827,13 @@ public class CPPSemantics {
|
|||
return false;
|
||||
}
|
||||
|
||||
static private IBinding resolveAmbiguities(LookupData data, IASTName name) throws DOMException {
|
||||
private static IBinding resolveAmbiguities(LookupData data, IASTName name) throws DOMException {
|
||||
if (!data.hasResults() || data.contentAssist)
|
||||
return null;
|
||||
|
||||
final boolean indexBased= data.tu != null && data.tu.getIndex() != null;
|
||||
@SuppressWarnings("unchecked")
|
||||
ObjectSet<IFunction> fns= ObjectSet.EMPTY_SET;
|
||||
ObjectSet<ICPPFunction> fns= ObjectSet.EMPTY_SET;
|
||||
IBinding type = null;
|
||||
IBinding obj = null;
|
||||
IBinding temp = null;
|
||||
|
@ -1878,15 +1884,15 @@ public class CPPSemantics {
|
|||
mergeResults(data, bindings, false);
|
||||
items = (Object[]) data.foundItems;
|
||||
continue;
|
||||
} else if (temp instanceof IFunction) {
|
||||
} else if (temp instanceof ICPPFunction) {
|
||||
if (temp instanceof ICPPTemplateInstance) {
|
||||
temp= ((ICPPTemplateInstance) temp).getSpecializedBinding();
|
||||
if (!(temp instanceof IFunction))
|
||||
continue;
|
||||
}
|
||||
if (fns == ObjectSet.EMPTY_SET)
|
||||
fns = new ObjectSet<IFunction>(2);
|
||||
fns.put((IFunction) temp);
|
||||
fns = new ObjectSet<ICPPFunction>(2);
|
||||
fns.put((ICPPFunction) temp);
|
||||
} else if (temp instanceof IType) {
|
||||
// specializations are selected during instantiation
|
||||
if (temp instanceof ICPPClassTemplatePartialSpecialization)
|
||||
|
@ -1977,7 +1983,7 @@ public class CPPSemantics {
|
|||
|
||||
|
||||
if (fns.size() > 0) {
|
||||
final IFunction[] fnArray = fns.keyArray(IFunction.class);
|
||||
final ICPPFunction[] fnArray = fns.keyArray(ICPPFunction.class);
|
||||
if (type != null && overrulesByRelevance(data, type, fnArray)) {
|
||||
return type;
|
||||
}
|
||||
|
@ -2200,69 +2206,60 @@ public class CPPSemantics {
|
|||
}
|
||||
}
|
||||
|
||||
static private void reduceToViable(LookupData data, IBinding[] functions) throws DOMException {
|
||||
if (functions == null || functions.length == 0)
|
||||
return;
|
||||
|
||||
final boolean def = data.forFunctionDeclaration();
|
||||
private static ICPPFunction[] selectByArgumentCount(LookupData data, ICPPFunction[] functions) throws DOMException {
|
||||
assert !data.forFunctionDeclaration();
|
||||
|
||||
int argumentCount = data.getFunctionArgumentCount();
|
||||
|
||||
if (def && argumentCount == 1) {
|
||||
// check for parameter of type void
|
||||
final IType[] argTypes = data.getFunctionArgumentTypes();
|
||||
if (argTypes.length == 1 && SemanticUtil.isVoidType(argTypes[0])) {
|
||||
argumentCount= 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Trim the list down to the set of viable functions
|
||||
ICPPFunction function = null;
|
||||
int size = functions.length;
|
||||
for (int i = 0; i < size; i++) {
|
||||
if (functions[i] instanceof IProblemBinding) {
|
||||
functions[i]= null;
|
||||
continue;
|
||||
}
|
||||
|
||||
function = (ICPPFunction) functions[i];
|
||||
if (function == null)
|
||||
continue;
|
||||
if (function instanceof ICPPUnknownBinding) {
|
||||
if (def) {
|
||||
functions[i]= null;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// Trim the list down to the set of viable functions
|
||||
ICPPFunction[] result= new ICPPFunction[functions.length];
|
||||
int idx= 0;
|
||||
for (ICPPFunction fn : functions) {
|
||||
if (fn != null && !(fn instanceof IProblemBinding)) {
|
||||
if (fn instanceof ICPPUnknownBinding) {
|
||||
return new ICPPFunction[] {fn};
|
||||
}
|
||||
|
||||
// the index is optimized to provide the function type, try not to use the parameters
|
||||
// as long as possible.
|
||||
final IType[] parameterTypes = function.getType().getParameterTypes();
|
||||
int numPars = parameterTypes.length;
|
||||
if (numPars == 1 && SemanticUtil.isVoidType(parameterTypes[0]))
|
||||
numPars= 0;
|
||||
|
||||
int numArgs = argumentCount;
|
||||
if (function instanceof ICPPMethod && data.argsContainImpliedObject)
|
||||
numArgs--;
|
||||
|
||||
if (def) {
|
||||
if (numPars != numArgs || !isMatchingFunctionDeclaration(function, data)) {
|
||||
functions[i] = null;
|
||||
}
|
||||
} else {
|
||||
// more arguments than parameters --> need ellipsis
|
||||
// The index is optimized to provide the function type, try not to use the parameters
|
||||
// as long as possible.
|
||||
final ICPPFunctionType ft = fn.getType();
|
||||
final IType[] parameterTypes = ft.getParameterTypes();
|
||||
int numPars = parameterTypes.length;
|
||||
if (numPars == 1 && SemanticUtil.isVoidType(parameterTypes[0]))
|
||||
numPars= 0;
|
||||
|
||||
int numArgs = argumentCount;
|
||||
if (fn instanceof ICPPMethod && data.argsContainImpliedObject)
|
||||
numArgs--;
|
||||
|
||||
boolean ok;
|
||||
if (numArgs > numPars) {
|
||||
if (!function.takesVarArgs() && !function.hasParameterPack()) {
|
||||
functions[i] = null;
|
||||
// more arguments than parameters --> need ellipsis or parameter pack
|
||||
ok= fn.takesVarArgs() || fn.hasParameterPack();
|
||||
} else {
|
||||
ok = numArgs >= fn.getRequiredArgumentCount();
|
||||
}
|
||||
if (ok) {
|
||||
if (fn instanceof IIndexBinding) {
|
||||
for (ICPPFunction other : result) {
|
||||
if (other == null || other instanceof IIndexBinding)
|
||||
break;
|
||||
if (other.getType().isSameType(ft)) {
|
||||
ok= false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ok) {
|
||||
result[idx++]= fn;
|
||||
}
|
||||
} else if (numArgs < function.getRequiredArgumentCount()) {
|
||||
// fewer arguments than required
|
||||
functions[i]= null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
static private boolean isMatchingFunctionDeclaration(ICPPFunction candidate, LookupData data) {
|
||||
|
||||
private static boolean isMatchingFunctionDeclaration(ICPPFunction candidate, LookupData data) {
|
||||
IASTNode node = data.astName.getParent();
|
||||
while (node instanceof IASTName)
|
||||
node = node.getParent();
|
||||
|
@ -2272,54 +2269,65 @@ public class CPPSemantics {
|
|||
return false;
|
||||
}
|
||||
|
||||
static IBinding resolveFunction(LookupData data, IFunction[] fns, boolean allowUDC) throws DOMException {
|
||||
fns= (IFunction[]) ArrayUtil.trim(IFunction.class, fns);
|
||||
static IBinding resolveFunction(LookupData data, ICPPFunction[] fns, boolean allowUDC) throws DOMException {
|
||||
fns= (ICPPFunction[]) ArrayUtil.trim(ICPPFunction.class, fns);
|
||||
if (fns == null || fns.length == 0)
|
||||
return null;
|
||||
|
||||
if (data.forUsingDeclaration()) {
|
||||
return new CPPUsingDeclaration(data.astName, fns);
|
||||
}
|
||||
sortAstBeforeIndex(fns);
|
||||
|
||||
if (data.forUsingDeclaration())
|
||||
return new CPPUsingDeclaration(data.astName, fns);
|
||||
|
||||
// We don't have any arguments with which to resolve the function
|
||||
final boolean isFuncDecl = data.forFunctionDeclaration();
|
||||
// No arguments to resolve function
|
||||
if (!data.hasFunctionArguments()) {
|
||||
return resolveTargetedFunction(data, fns);
|
||||
ICPPFunction cand= fns[0];
|
||||
if (!(cand instanceof ICPPFunctionTemplate)) {
|
||||
if (fns.length == 1)
|
||||
return cand;
|
||||
// Just one binding from ast, use it.
|
||||
if (!(cand instanceof IIndexBinding) && fns[1] instanceof IIndexBinding)
|
||||
return cand;
|
||||
}
|
||||
return new CPPFunctionSet(fns);
|
||||
}
|
||||
|
||||
if (data.astName instanceof ICPPASTConversionName) {
|
||||
return resolveUserDefinedConversion(data, fns);
|
||||
}
|
||||
|
||||
if (!isFuncDecl || data.forExplicitFunctionSpecialization()) {
|
||||
CPPTemplates.instantiateFunctionTemplates(fns, data.getFunctionArgumentTypes(), data.getFunctionArgumentValueCategories(),
|
||||
data.astName, data.argsContainImpliedObject);
|
||||
}
|
||||
|
||||
if (data.forFunctionDeclaration())
|
||||
return resolveFunctionDeclaration(data, fns);
|
||||
|
||||
// Reduce our set of candidate functions to only those who have the right number of parameters
|
||||
reduceToViable(data, fns);
|
||||
final IType[] argTypes = data.getFunctionArgumentTypes();
|
||||
ICPPFunction[] tmp= selectByArgumentCount(data, fns);
|
||||
tmp= CPPTemplates.instantiateFunctionTemplates(tmp, argTypes, data.getFunctionArgumentValueCategories(),
|
||||
data.astName, data.argsContainImpliedObject);
|
||||
if (tmp.length == 0 || tmp[0] == null)
|
||||
return new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_NAME_NOT_FOUND, fns);
|
||||
|
||||
|
||||
int viableCount= 0;
|
||||
IFunction firstViable= null;
|
||||
for (IFunction f : fns) {
|
||||
if (f != null) {
|
||||
if (++viableCount == 1) {
|
||||
firstViable= f;
|
||||
}
|
||||
if (f instanceof ICPPUnknownBinding) {
|
||||
return f;
|
||||
}
|
||||
for (IFunction f : tmp) {
|
||||
if (f instanceof ICPPUnknownBinding) {
|
||||
setTargetedFunctionsToUnknown(argTypes);
|
||||
return f;
|
||||
}
|
||||
if (f == null)
|
||||
break;
|
||||
++viableCount;
|
||||
}
|
||||
if (firstViable == null || isFuncDecl)
|
||||
return firstViable;
|
||||
if (viableCount == 0)
|
||||
return new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_NAME_NOT_FOUND, fns);
|
||||
|
||||
// The arguments the function is being called with
|
||||
IType[] argTypes = data.getFunctionArgumentTypes();
|
||||
// Check for dependent arguments
|
||||
fns= tmp;
|
||||
if (CPPTemplates.containsDependentType(argTypes)) {
|
||||
if (viableCount == 1)
|
||||
return firstViable;
|
||||
return CPPUnknownFunction.createForSample(firstViable);
|
||||
if (viableCount == 1)
|
||||
return fns[0];
|
||||
setTargetedFunctionsToUnknown(argTypes);
|
||||
return CPPUnknownFunction.createForSample(fns[0]);
|
||||
}
|
||||
|
||||
IFunction[] ambiguousFunctions= null; // ambiguity, 2 functions are equally good
|
||||
|
@ -2336,11 +2344,12 @@ public class CPPSemantics {
|
|||
continue;
|
||||
|
||||
if (fnCost == CONTAINS_DEPENDENT_TYPES) {
|
||||
if (viableCount == 1)
|
||||
return firstViable;
|
||||
return CPPUnknownFunction.createForSample(firstViable);
|
||||
if (viableCount == 1)
|
||||
return fns[0];
|
||||
setTargetedFunctionsToUnknown(argTypes);
|
||||
return CPPUnknownFunction.createForSample(fns[0]);
|
||||
}
|
||||
|
||||
|
||||
if (fnCost.hasDeferredUDC()) {
|
||||
if (potentialCosts == null) {
|
||||
potentialCosts= new ArrayList<FunctionCost>();
|
||||
|
@ -2383,10 +2392,70 @@ public class CPPSemantics {
|
|||
return new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP,
|
||||
data.getFoundBindings());
|
||||
}
|
||||
|
||||
|
||||
for (int i = 0; i < argTypes.length; i++) {
|
||||
IType iType = argTypes[i];
|
||||
if (iType instanceof FunctionSetType) {
|
||||
((FunctionSetType) iType).applySelectedFunction(bestFnCost.getCost(i).getSelectedFunction());
|
||||
}
|
||||
}
|
||||
return bestFnCost.getFunction();
|
||||
}
|
||||
|
||||
private static void setTargetedFunctionsToUnknown(IType[] argTypes) {
|
||||
for (IType argType : argTypes) {
|
||||
if (argType instanceof FunctionSetType) {
|
||||
((FunctionSetType) argType).setToUnknown();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static IBinding resolveFunctionDeclaration(LookupData data, ICPPFunction[] fns) throws DOMException {
|
||||
if (data.forExplicitFunctionSpecialization()) {
|
||||
fns= CPPTemplates.instantiateFunctionTemplates(fns, data.getFunctionArgumentTypes(),
|
||||
data.getFunctionArgumentValueCategories(), data.astName, data.argsContainImpliedObject);
|
||||
}
|
||||
|
||||
int argCount = data.getFunctionArgumentCount();
|
||||
if (argCount == 1) {
|
||||
// check for parameter of type void
|
||||
final IType[] argTypes = data.getFunctionArgumentTypes();
|
||||
if (argTypes.length == 1 && SemanticUtil.isVoidType(argTypes[0])) {
|
||||
argCount= 0;
|
||||
}
|
||||
}
|
||||
|
||||
for (ICPPFunction fn : fns) {
|
||||
if (fn != null && !(fn instanceof IProblemBinding) && !(fn instanceof ICPPUnknownBinding)) {
|
||||
// The index is optimized to provide the function type, avoid using the parameters
|
||||
// as long as possible.
|
||||
final IType[] parameterTypes = fn.getType().getParameterTypes();
|
||||
int parCount = parameterTypes.length;
|
||||
if (parCount == 1 && SemanticUtil.isVoidType(parameterTypes[0]))
|
||||
parCount= 0;
|
||||
|
||||
if (parCount == argCount && isMatchingFunctionDeclaration(fn, data)) {
|
||||
return fn;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void sortAstBeforeIndex(IFunction[] fns) {
|
||||
int iast= 0;
|
||||
for (int i = 0; i < fns.length; i++) {
|
||||
IFunction fn= fns[i];
|
||||
if (!(fn instanceof IIndexBinding)) {
|
||||
if (iast != i) {
|
||||
fns[i]= fns[iast];
|
||||
fns[iast]= fn;
|
||||
iast++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static FunctionCost costForFunctionCall(IFunction fn, boolean allowUDC, LookupData data)
|
||||
throws DOMException {
|
||||
IType[] argTypes = data.getFunctionArgumentTypes();
|
||||
|
@ -2466,7 +2535,9 @@ public class CPPSemantics {
|
|||
continue;
|
||||
}
|
||||
|
||||
if (argType.isSameType(paramType)) {
|
||||
if (argType instanceof FunctionSetType) {
|
||||
cost= ((FunctionSetType) argType).costForTarget(paramType);
|
||||
} else if (argType.isSameType(paramType)) {
|
||||
cost = new Cost(argType, paramType, Rank.IDENTITY);
|
||||
} else {
|
||||
if (CPPTemplates.isDependentType(paramType))
|
||||
|
@ -2537,245 +2608,186 @@ public class CPPSemantics {
|
|||
|
||||
/**
|
||||
* 13.4-1 A use of an overloaded function without arguments is resolved in certain contexts to a function
|
||||
* @param data
|
||||
* @param fns
|
||||
* @return
|
||||
*/
|
||||
private static IBinding resolveTargetedFunction(LookupData data, IBinding[] fns) {
|
||||
if (fns.length == 1)
|
||||
return fns[0];
|
||||
|
||||
IBinding oneFromAST= null;
|
||||
for (IBinding fn : fns) {
|
||||
if (!isFromIndex(fn)) {
|
||||
if (oneFromAST != null) {
|
||||
oneFromAST= null;
|
||||
static IBinding resolveTargetedFunction(IASTName name, ICPPFunction[] fns) {
|
||||
boolean addressOf= false;
|
||||
IASTNode node= name.getParent();
|
||||
while (node instanceof IASTName)
|
||||
node= node.getParent();
|
||||
|
||||
if (!(node instanceof IASTIdExpression))
|
||||
return new ProblemBinding(name, IProblemBinding.SEMANTIC_INVALID_OVERLOAD);
|
||||
|
||||
ASTNodeProperty prop= node.getPropertyInParent();
|
||||
IASTNode parent = node.getParent();
|
||||
while (parent instanceof IASTUnaryExpression) {
|
||||
final int op= ((IASTUnaryExpression) parent).getOperator();
|
||||
if (op == IASTUnaryExpression.op_bracketedPrimary) {
|
||||
} else if (!addressOf && op == IASTUnaryExpression.op_amper) {
|
||||
addressOf= true;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
node= parent;
|
||||
prop= node.getPropertyInParent();
|
||||
parent= node.getParent();
|
||||
}
|
||||
|
||||
IType targetType= null;
|
||||
if (prop == IASTDeclarator.INITIALIZER) {
|
||||
// Target is an object or reference being initialized
|
||||
IASTDeclarator dtor = (IASTDeclarator) parent;
|
||||
targetType= CPPVisitor.createType(dtor);
|
||||
} else if (prop == IASTEqualsInitializer.INITIALIZER) {
|
||||
IASTEqualsInitializer initExp = (IASTEqualsInitializer) parent;
|
||||
if (initExp.getParent() instanceof IASTDeclarator) {
|
||||
IASTDeclarator dtor = (IASTDeclarator) initExp.getParent();
|
||||
targetType= CPPVisitor.createType(dtor);
|
||||
}
|
||||
} else if (prop == ICPPASTConstructorInitializer.ARGUMENT) {
|
||||
ICPPASTConstructorInitializer init = (ICPPASTConstructorInitializer) parent;
|
||||
if (init.getArguments().length == 1) {
|
||||
final IASTNode parentOfInit = init.getParent();
|
||||
if (parentOfInit instanceof IASTDeclarator) {
|
||||
IASTDeclarator dtor = (IASTDeclarator) parentOfInit;
|
||||
targetType= CPPVisitor.createType(dtor);
|
||||
} else if (parentOfInit instanceof ICPPASTConstructorChainInitializer) {
|
||||
ICPPASTConstructorChainInitializer memInit= (ICPPASTConstructorChainInitializer) parentOfInit;
|
||||
IBinding var= memInit.getMemberInitializerId().resolveBinding();
|
||||
if (var instanceof IVariable) {
|
||||
try {
|
||||
targetType= ((IVariable) var).getType();
|
||||
} catch (DOMException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (prop == IASTBinaryExpression.OPERAND_TWO) {
|
||||
IASTBinaryExpression binaryExp = (IASTBinaryExpression) parent;
|
||||
if (binaryExp.getOperator() == IASTBinaryExpression.op_assign) {
|
||||
targetType= binaryExp.getOperand1().getExpressionType();
|
||||
}
|
||||
} else if (prop == IASTFunctionCallExpression.ARGUMENT) {
|
||||
// Target is a parameter of a function, need to resolve the function call
|
||||
IASTFunctionCallExpression fnCall = (IASTFunctionCallExpression) parent;
|
||||
IType t= SemanticUtil.getNestedType(fnCall.getFunctionNameExpression().getExpressionType(), TDEF|REF|CVTYPE);
|
||||
if (t instanceof IPointerType) {
|
||||
t= SemanticUtil.getNestedType(((IPointerType) t).getType(), TDEF | REF | CVTYPE);
|
||||
}
|
||||
if (t instanceof IFunctionType) {
|
||||
int i= 0;
|
||||
for (IASTNode arg : fnCall.getArguments()) {
|
||||
if (arg == node) {
|
||||
IType[] params= ((IFunctionType) t).getParameterTypes();
|
||||
if (params.length > i) {
|
||||
targetType= params[i];
|
||||
}
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
} else if (prop == IASTCastExpression.OPERAND) {
|
||||
// target is an explicit type conversion
|
||||
IASTCastExpression cast = (IASTCastExpression) parent;
|
||||
targetType= CPPVisitor.createType(cast.getTypeId().getAbstractDeclarator());
|
||||
} else if (prop == ICPPASTTemplateId.TEMPLATE_ID_ARGUMENT) {
|
||||
// target is a template non-type parameter (14.3.2-5)
|
||||
ICPPASTTemplateId id = (ICPPASTTemplateId) parent;
|
||||
IASTNode[] args = id.getTemplateArguments();
|
||||
int i = 0;
|
||||
for (; i < args.length; i++) {
|
||||
if (args[i] == node) {
|
||||
break;
|
||||
}
|
||||
oneFromAST= fn;
|
||||
}
|
||||
}
|
||||
if (oneFromAST != null)
|
||||
return oneFromAST;
|
||||
|
||||
if (data.forAssociatedScopes) {
|
||||
return new CPPCompositeBinding(fns);
|
||||
}
|
||||
|
||||
IBinding result = null;
|
||||
|
||||
Object o = getTargetType(data);
|
||||
IType type, types[] = null;
|
||||
int idx = -1;
|
||||
if (o instanceof IType[]) {
|
||||
types = (IType[]) o;
|
||||
type = types[++idx];
|
||||
} else {
|
||||
type = (IType) o;
|
||||
}
|
||||
|
||||
while (type != null) {
|
||||
type = getUltimateType(type, false);
|
||||
if (type == null || !(type instanceof IFunctionType)) {
|
||||
return new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP,
|
||||
data.getFoundBindings());
|
||||
}
|
||||
|
||||
for (IBinding fn2 : fns) {
|
||||
IFunction fn = (IFunction) fn2;
|
||||
IType ft = null;
|
||||
try {
|
||||
ft = fn.getType();
|
||||
} catch (DOMException e) {
|
||||
ft = e.getProblem();
|
||||
}
|
||||
if (type.isSameType(ft)) {
|
||||
if (result == null) {
|
||||
result = fn;
|
||||
} else {
|
||||
int c = compareByRelevance(data, result, fn);
|
||||
if (c < 0) {
|
||||
result= fn;
|
||||
} else if (c == 0) {
|
||||
return new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP,
|
||||
data.getFoundBindings());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (types != null && ++idx < types.length) {
|
||||
type = types[idx];
|
||||
} else {
|
||||
type = null;
|
||||
}
|
||||
}
|
||||
|
||||
return result != null ? result :
|
||||
new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP, data.getFoundBindings());
|
||||
}
|
||||
|
||||
private static Object getTargetType(LookupData data) {
|
||||
IASTName name = data.astName;
|
||||
|
||||
if (name.getPropertyInParent() == ICPPASTQualifiedName.SEGMENT_NAME)
|
||||
name = (IASTName) name.getParent();
|
||||
|
||||
if (name.getPropertyInParent() != IASTIdExpression.ID_NAME)
|
||||
return null;
|
||||
|
||||
IASTIdExpression idExp = (IASTIdExpression) name.getParent();
|
||||
IASTNode node = idExp;
|
||||
ASTNodeProperty prop = null;
|
||||
while (node != null) {
|
||||
prop = node.getPropertyInParent();
|
||||
if (prop == IASTDeclarator.INITIALIZER) {
|
||||
// target is an object or reference being initialized
|
||||
IASTDeclarator dtor = (IASTDeclarator) node.getParent();
|
||||
return CPPVisitor.createType(dtor);
|
||||
} else if (prop == IASTEqualsInitializer.INITIALIZER) {
|
||||
IASTEqualsInitializer initExp = (IASTEqualsInitializer) node.getParent();
|
||||
if (initExp.getParent() instanceof IASTDeclarator) {
|
||||
IASTDeclarator dtor = (IASTDeclarator) initExp.getParent();
|
||||
return CPPVisitor.createType(dtor);
|
||||
}
|
||||
return null;
|
||||
} else if (prop == IASTBinaryExpression.OPERAND_TWO &&
|
||||
((IASTBinaryExpression) node.getParent()).getOperator() == IASTBinaryExpression.op_assign) {
|
||||
// target is the left side of an assignment
|
||||
IASTBinaryExpression binaryExp = (IASTBinaryExpression) node.getParent();
|
||||
IASTExpression exp = binaryExp.getOperand1();
|
||||
return exp.getExpressionType();
|
||||
} else if (prop == IASTFunctionCallExpression.ARGUMENT) {
|
||||
// target is a parameter of a function
|
||||
// if this function call refers to an overloaded function, there is more than one possibility
|
||||
// for the target type
|
||||
IASTFunctionCallExpression fnCall = (IASTFunctionCallExpression) node.getParent();
|
||||
int idx = 0;
|
||||
final IASTInitializerClause[] arguments = fnCall.getArguments();
|
||||
for (IASTInitializerClause arg : arguments) {
|
||||
if (arg == node)
|
||||
break;
|
||||
idx++;
|
||||
IBinding template = id.getTemplateName().resolveBinding();
|
||||
if (template instanceof ICPPTemplateDefinition) {
|
||||
try {
|
||||
ICPPTemplateParameter[] ps = ((ICPPTemplateDefinition) template).getTemplateParameters();
|
||||
if (i < args.length && i < ps.length && ps[i] instanceof ICPPTemplateNonTypeParameter) {
|
||||
targetType= ((ICPPTemplateNonTypeParameter) ps[i]).getType();
|
||||
}
|
||||
} catch (DOMException e) {
|
||||
}
|
||||
if (idx >= arguments.length)
|
||||
return null;
|
||||
|
||||
IFunctionType[] types = getPossibleFunctions(fnCall);
|
||||
if (types == null)
|
||||
return null;
|
||||
IType[] result = null;
|
||||
for (int i = 0; i < types.length && types[i] != null; i++) {
|
||||
IType[] pts = null;
|
||||
pts = types[i].getParameterTypes();
|
||||
if (pts.length > idx)
|
||||
result = (IType[]) ArrayUtil.append(IType.class, result, pts[idx]);
|
||||
}
|
||||
return result;
|
||||
} else if (prop == IASTCastExpression.OPERAND) {
|
||||
// target is an explicit type conversion
|
||||
IASTCastExpression cast = (IASTCastExpression) node.getParent();
|
||||
return CPPVisitor.createType(cast.getTypeId().getAbstractDeclarator());
|
||||
} else if (prop == ICPPASTTemplateId.TEMPLATE_ID_ARGUMENT) {
|
||||
//target is a template non-type parameter (14.3.2-5)
|
||||
ICPPASTTemplateId id = (ICPPASTTemplateId) node.getParent();
|
||||
IASTNode[] args = id.getTemplateArguments();
|
||||
int i = 0;
|
||||
for (; i < args.length; i++) {
|
||||
if (args[i] == node) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
IBinding template =id.getTemplateName().resolveBinding();
|
||||
if (template instanceof ICPPTemplateDefinition) {
|
||||
try {
|
||||
ICPPTemplateParameter[] ps = ((ICPPTemplateDefinition) template).getTemplateParameters();
|
||||
if (i < args.length && i < ps.length && ps[i] instanceof ICPPTemplateNonTypeParameter) {
|
||||
return ((ICPPTemplateNonTypeParameter) ps[i]).getType();
|
||||
}
|
||||
} catch (DOMException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
} else if (prop == IASTReturnStatement.RETURNVALUE) {
|
||||
// target is the return value of a function, operator or conversion
|
||||
while (!(node instanceof IASTFunctionDefinition)) {
|
||||
node = node.getParent();
|
||||
}
|
||||
IASTDeclarator dtor = ((IASTFunctionDefinition) node).getDeclarator();
|
||||
dtor= ASTQueries.findInnermostDeclarator(dtor);
|
||||
IBinding binding = dtor.getName().resolveBinding();
|
||||
if (binding instanceof IFunction) {
|
||||
try {
|
||||
IFunctionType ft = ((IFunction) binding).getType();
|
||||
return ft.getReturnType();
|
||||
} catch (DOMException e) {
|
||||
}
|
||||
}
|
||||
} else if (prop == IASTUnaryExpression.OPERAND) {
|
||||
IASTUnaryExpression parent = (IASTUnaryExpression) node.getParent();
|
||||
if (parent.getOperator() == IASTUnaryExpression.op_bracketedPrimary ||
|
||||
parent.getOperator() == IASTUnaryExpression.op_amper) {
|
||||
node = parent;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
} else if (prop == IASTReturnStatement.RETURNVALUE) {
|
||||
// target is the return value of a function, operator or conversion
|
||||
while (parent != null && !(parent instanceof IASTFunctionDefinition)) {
|
||||
parent = parent.getParent();
|
||||
}
|
||||
if (parent instanceof IASTFunctionDefinition) {
|
||||
IASTDeclarator dtor = ((IASTFunctionDefinition) parent).getDeclarator();
|
||||
dtor= ASTQueries.findInnermostDeclarator(dtor);
|
||||
IBinding binding = dtor.getName().resolveBinding();
|
||||
if (binding instanceof IFunction) {
|
||||
try {
|
||||
IFunctionType ft = ((IFunction) binding).getType();
|
||||
targetType= ft.getReturnType();
|
||||
} catch (DOMException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (targetType == null && parent instanceof IASTExpression
|
||||
&& parent instanceof IASTImplicitNameOwner) {
|
||||
// Trigger resolution of overloaded operator, which may resolve the
|
||||
// function set.
|
||||
((IASTImplicitNameOwner) parent).getImplicitNames();
|
||||
final IBinding newBinding = name.getPreBinding();
|
||||
if (!(newBinding instanceof CPPFunctionSet))
|
||||
return newBinding;
|
||||
}
|
||||
|
||||
ICPPFunction function = resolveTargetedFunction(targetType, name, fns);
|
||||
if (function == null)
|
||||
return new ProblemBinding(name, IProblemBinding.SEMANTIC_INVALID_OVERLOAD);
|
||||
|
||||
return function;
|
||||
}
|
||||
|
||||
static private IFunctionType[] getPossibleFunctions(IASTFunctionCallExpression call) {
|
||||
IFunctionType[] result = null;
|
||||
|
||||
IASTExpression exp = call.getFunctionNameExpression();
|
||||
if (exp instanceof IASTIdExpression) {
|
||||
IASTIdExpression idExp = (IASTIdExpression) exp;
|
||||
IASTName name = idExp.getName();
|
||||
LookupData data = createLookupData(name);
|
||||
try {
|
||||
lookup(data, null);
|
||||
} catch (DOMException e) {
|
||||
return null;
|
||||
}
|
||||
final boolean isIndexBased= data.tu != null && data.tu.getIndex() != null;
|
||||
if (data.hasResults()) {
|
||||
Object[] items = (Object[]) data.foundItems;
|
||||
IBinding temp = null;
|
||||
for (Object o : items) {
|
||||
if (o == null) break;
|
||||
if (o instanceof IASTName) {
|
||||
temp = ((IASTName) o).resolveBinding();
|
||||
} else if (o instanceof IBinding) {
|
||||
temp = (IBinding) o;
|
||||
if (!declaredBefore(temp, name, isIndexBased))
|
||||
continue;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
if (temp instanceof IFunction) {
|
||||
result = (IFunctionType[]) ArrayUtil.append(IFunctionType.class, result, ((IFunction) temp).getType());
|
||||
} else if (temp instanceof IVariable) {
|
||||
IType type = getUltimateType(((IVariable) temp).getType(), false);
|
||||
if (type instanceof IFunctionType)
|
||||
result = (IFunctionType[]) ArrayUtil.append(IFunctionType.class, result, type);
|
||||
}
|
||||
} catch (DOMException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
IType type = exp.getExpressionType();
|
||||
type = getUltimateType(type, false);
|
||||
if (type instanceof IFunctionType) {
|
||||
result = new IFunctionType[] { (IFunctionType) type };
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static ICPPFunction resolveTargetedFunction(IType targetType, IASTName name, ICPPFunction[] fns) {
|
||||
targetType= getNestedType(targetType, TDEF | REF | CVTYPE | PTR | MPTR);
|
||||
if (!(targetType instanceof ICPPFunctionType))
|
||||
return null;
|
||||
|
||||
// First pass, consider functions
|
||||
for (ICPPFunction fn : fns) {
|
||||
try {
|
||||
if (!(fn instanceof ICPPFunctionTemplate)) {
|
||||
if (targetType.isSameType(fn.getType()))
|
||||
return fn;
|
||||
}
|
||||
} catch (DOMException e) {
|
||||
}
|
||||
}
|
||||
|
||||
// Second pass, consider templates
|
||||
ICPPFunction result= null;
|
||||
ICPPFunctionTemplate resultTemplate= null;
|
||||
for (IFunction fn : fns) {
|
||||
try {
|
||||
if (fn instanceof ICPPFunctionTemplate) {
|
||||
final ICPPFunctionTemplate template = (ICPPFunctionTemplate) fn;
|
||||
ICPPFunction inst= CPPTemplates.instantiateFunctionTemplate(template, (ICPPFunctionType) targetType, name);
|
||||
if (inst != null) {
|
||||
int cmp= -1;
|
||||
if (result != null) {
|
||||
cmp= CPPTemplates.orderTemplateFunctions(resultTemplate, template);
|
||||
if (cmp == 0)
|
||||
return null;
|
||||
}
|
||||
if (cmp < 0) {
|
||||
resultTemplate= template;
|
||||
result= inst;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (DOMException e) {
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* For a pointer dereference expression e1->e2, return the type that e1 ultimately evaluates to
|
||||
|
@ -2790,7 +2802,7 @@ public class CPPSemantics {
|
|||
}
|
||||
|
||||
/*
|
||||
* Also collections the function bindings if requested.
|
||||
* Also collects the function bindings if requested.
|
||||
*/
|
||||
public static IType getFieldOwnerType(ICPPASTFieldReference fieldReference, Collection<ICPPFunction> functionBindings) throws DOMException {
|
||||
final IASTExpression owner = fieldReference.getFieldOwner();
|
||||
|
@ -2849,9 +2861,10 @@ public class CPPSemantics {
|
|||
}
|
||||
|
||||
public static ICPPFunction findOverloadedOperator(IASTArraySubscriptExpression exp) {
|
||||
IASTInitializerClause[] args = {exp.getArrayExpression(), exp.getArgument()};
|
||||
IType type = exp.getArrayExpression().getExpressionType();
|
||||
type = SemanticUtil.getUltimateTypeUptoPointers(type);
|
||||
final IASTExpression arrayExpression = exp.getArrayExpression();
|
||||
IASTInitializerClause[] args = {arrayExpression, exp.getArgument()};
|
||||
IType type = typeOrFunctionSet(arrayExpression);
|
||||
type = SemanticUtil.getNestedType(type, TDEF | REF | CVTYPE);
|
||||
return findOverloadedOperator(exp, args, type, OverloadableOperator.BRACKET, LookupMode.NO_GLOBALS);
|
||||
}
|
||||
|
||||
|
@ -2871,7 +2884,7 @@ public class CPPSemantics {
|
|||
OverloadableOperator op = OverloadableOperator.fromNewExpression(exp);
|
||||
|
||||
IType type = exp.getExpressionType();
|
||||
if (type instanceof IProblem)
|
||||
if (!(type instanceof IPointerType))
|
||||
return null;
|
||||
type = ((IPointerType) type).getType();
|
||||
|
||||
|
@ -2964,8 +2977,8 @@ public class CPPSemantics {
|
|||
ValueCategory isLValue= PRVALUE;
|
||||
if (initClause instanceof IASTExpression) {
|
||||
final IASTExpression expr = (IASTExpression) initClause;
|
||||
isLValue= expr.getValueCategory();
|
||||
sourceType= SemanticUtil.getSimplifiedType(expr.getExpressionType());
|
||||
isLValue= valueCat(expr);
|
||||
sourceType= SemanticUtil.getSimplifiedType(typeOrFunctionSet(expr));
|
||||
} else if (initClause instanceof ICPPASTInitializerList) {
|
||||
sourceType= new InitializerListType((ICPPASTInitializerList) initClause);
|
||||
}
|
||||
|
@ -3044,25 +3057,26 @@ public class CPPSemantics {
|
|||
}
|
||||
|
||||
public static ICPPFunction findOverloadedOperator(IASTUnaryExpression exp) {
|
||||
if (exp.getOperand() == null)
|
||||
final IASTExpression operand = exp.getOperand();
|
||||
if (operand == null)
|
||||
return null;
|
||||
|
||||
OverloadableOperator op = OverloadableOperator.fromUnaryExpression(exp);
|
||||
if (op == null)
|
||||
return null;
|
||||
|
||||
IASTExpression[] args;
|
||||
int operator = exp.getOperator();
|
||||
if (operator == IASTUnaryExpression.op_postFixDecr || operator == IASTUnaryExpression.op_postFixIncr)
|
||||
args = new IASTExpression[] { exp.getOperand(), CPPASTLiteralExpression.INT_ZERO };
|
||||
else
|
||||
args = new IASTExpression[] { exp.getOperand() };
|
||||
|
||||
IType type = exp.getOperand().getExpressionType();
|
||||
IType type = typeOrFunctionSet(operand);
|
||||
type = SemanticUtil.getNestedType(type, TDEF | REF | CVTYPE);
|
||||
if (!isUserDefined(type))
|
||||
if (!isUserDefined(type))
|
||||
return null;
|
||||
|
||||
IASTExpression[] args;
|
||||
int operator = exp.getOperator();
|
||||
if (operator == IASTUnaryExpression.op_postFixDecr || operator == IASTUnaryExpression.op_postFixIncr) {
|
||||
args = new IASTExpression[] { operand, CPPASTLiteralExpression.INT_ZERO };
|
||||
} else {
|
||||
args = new IASTExpression[] { operand };
|
||||
}
|
||||
return findOverloadedOperator(exp, args, type, op, LookupMode.LIMITED_GLOBALS);
|
||||
}
|
||||
|
||||
|
@ -3076,8 +3090,8 @@ public class CPPSemantics {
|
|||
if(op2==null){
|
||||
return null;
|
||||
}
|
||||
IType op1type = getNestedType(op1.getExpressionType(), TDEF | REF | CVTYPE);
|
||||
IType op2type = getNestedType(op2.getExpressionType(), TDEF | REF | CVTYPE);
|
||||
IType op1type = getNestedType(typeOrFunctionSet(op1), TDEF | REF | CVTYPE);
|
||||
IType op2type = getNestedType(typeOrFunctionSet(op2), TDEF | REF | CVTYPE);
|
||||
if (!isUserDefined(op1type) && !isUserDefined(op2type))
|
||||
return null;
|
||||
|
||||
|
@ -3105,14 +3119,15 @@ public class CPPSemantics {
|
|||
* Returns the operator,() function that would apply to the two given arguments.
|
||||
* The lookup type of the class where the operator,() might be found must also be provided.
|
||||
*/
|
||||
public static ICPPFunction findOverloadedOperatorComma(IASTExpression first, IASTExpression second, final IType lookupType) {
|
||||
public static ICPPFunction findOverloadedOperatorComma(IASTExpression first, final IType lookupType, final ValueCategory valueCat, IASTExpression second) {
|
||||
IType op1type = getNestedType(lookupType, TDEF | REF | CVTYPE);
|
||||
IType op2type = getNestedType(typeOrFunctionSet(second), TDEF | REF | CVTYPE);
|
||||
if (!isUserDefined(op1type) && !isUserDefined(op2type))
|
||||
return null;
|
||||
|
||||
IASTUnaryExpression dummy = new CPPASTUnaryExpression() {
|
||||
@Override public IType getExpressionType() { return lookupType; }
|
||||
@Override public IASTExpression getOperand() {
|
||||
return new CPPASTUnaryExpression() {
|
||||
@Override public IType getExpressionType() { return lookupType; }
|
||||
};
|
||||
}
|
||||
@Override public ValueCategory getValueCategory() { return valueCat; }
|
||||
};
|
||||
dummy.setParent(first);
|
||||
|
||||
|
@ -3126,10 +3141,16 @@ public class CPPSemantics {
|
|||
ICPPClassType callToObjectOfClassType= null;
|
||||
IType type2= null;
|
||||
if (args.length >= 2 && args[1] instanceof IASTExpression) {
|
||||
type2= getUltimateTypeUptoPointers(((IASTExpression) args[1]).getExpressionType());
|
||||
type2 = typeOrFunctionSet((IASTExpression) args[1]);
|
||||
type2= getNestedType(type2, TDEF | REF | CVTYPE);
|
||||
}
|
||||
|
||||
if (methodLookupType instanceof ICPPUnknownType || type2 instanceof ICPPUnknownType) {
|
||||
if (methodLookupType instanceof FunctionSetType)
|
||||
((FunctionSetType) methodLookupType).setToUnknown();
|
||||
if (type2 instanceof FunctionSetType)
|
||||
((FunctionSetType) type2).setToUnknown();
|
||||
|
||||
return new CPPUnknownFunction(null, operator.toCharArray());
|
||||
}
|
||||
|
||||
|
@ -3308,7 +3329,7 @@ public class CPPSemantics {
|
|||
if (type instanceof IProblemBinding)
|
||||
return false;
|
||||
|
||||
return type instanceof ICPPClassType || type instanceof IEnumeration;
|
||||
return type instanceof ICPPClassType || type instanceof IEnumeration || type instanceof ICPPUnknownType;
|
||||
}
|
||||
|
||||
public static IBinding[] findBindings(IScope scope, String name, boolean qualified) {
|
||||
|
|
|
@ -152,6 +152,7 @@ public class CPPTemplates {
|
|||
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;
|
||||
private static final ICPPFunction[] NO_FUNCTIONS = {};
|
||||
|
||||
/**
|
||||
* Instantiates a class template with the given arguments. May return <code>null</code>.
|
||||
|
@ -1515,7 +1516,7 @@ public class CPPTemplates {
|
|||
* empty IType array is returned if id is <code>null</code>
|
||||
* @throws DOMException
|
||||
*/
|
||||
static public ICPPTemplateArgument[] createTemplateArgumentArray(ICPPASTTemplateId id) throws DOMException {
|
||||
public static ICPPTemplateArgument[] createTemplateArgumentArray(ICPPASTTemplateId id) throws DOMException {
|
||||
ICPPTemplateArgument[] result= ICPPTemplateArgument.EMPTY_ARGUMENTS;
|
||||
if (id != null) {
|
||||
IASTNode[] params= id.getTemplateArguments();
|
||||
|
@ -1537,7 +1538,7 @@ public class CPPTemplates {
|
|||
return result;
|
||||
}
|
||||
|
||||
static protected void instantiateFunctionTemplates(IFunction[] functions, IType[] allFnArgs,
|
||||
static ICPPFunction[] instantiateFunctionTemplates(ICPPFunction[] fns, IType[] allFnArgs,
|
||||
ValueCategory[] allValueCategories, IASTName name, boolean argsContainImpliedObject) {
|
||||
boolean requireTemplate= false;
|
||||
if (name != null) {
|
||||
|
@ -1552,12 +1553,13 @@ public class CPPTemplates {
|
|||
IType[] reducedFnArgs= null;
|
||||
ValueCategory[] reducedValueCategories= null;
|
||||
ICPPTemplateArgument[] tmplArgs= null;
|
||||
for (int i = 0; i < functions.length; i++) {
|
||||
IFunction func = functions[i];
|
||||
ICPPFunction[] result= fns;
|
||||
int idx= 0;
|
||||
for (int i = 0; i < fns.length; i++) {
|
||||
final ICPPFunction func = fns[i];
|
||||
ICPPFunction rf= null;
|
||||
if (func instanceof ICPPFunctionTemplate) {
|
||||
ICPPFunctionTemplate template= (ICPPFunctionTemplate) func;
|
||||
functions[i]= null;
|
||||
|
||||
final IType[] fnArgs;
|
||||
final ValueCategory[] valueCategories;
|
||||
if (argsContainImpliedObject && template instanceof ICPPMethod) {
|
||||
|
@ -1583,18 +1585,16 @@ public class CPPTemplates {
|
|||
tmplArgs = ICPPTemplateArgument.EMPTY_ARGUMENTS;
|
||||
try {
|
||||
if (fnArgs == null || containsDependentType(fnArgs)) {
|
||||
functions[i]= CPPUnknownFunction.createForSample(template);
|
||||
return;
|
||||
return new ICPPFunction[] {CPPUnknownFunction.createForSample(template)};
|
||||
}
|
||||
if (name instanceof ICPPASTTemplateId && !(template instanceof ICPPConstructor)) {
|
||||
tmplArgs = createTemplateArgumentArray((ICPPASTTemplateId) name);
|
||||
if (hasDependentArgument(tmplArgs)) {
|
||||
functions[i]= CPPUnknownFunction.createForSample(template);
|
||||
return;
|
||||
return new ICPPFunction[] {CPPUnknownFunction.createForSample(template)};
|
||||
}
|
||||
}
|
||||
} catch (DOMException e) {
|
||||
return;
|
||||
return NO_FUNCTIONS;
|
||||
}
|
||||
}
|
||||
CPPTemplateParameterMap map= new CPPTemplateParameterMap(fnArgs.length);
|
||||
|
@ -1602,19 +1602,30 @@ public class CPPTemplates {
|
|||
ICPPTemplateArgument[] args= TemplateArgumentDeduction.deduceForFunctionCall(template, tmplArgs, fnArgs, valueCategories, map);
|
||||
if (args != null) {
|
||||
IBinding instance= instantiateFunctionTemplate(template, args, map);
|
||||
if (instance instanceof IFunction) {
|
||||
functions[i]= (IFunction) instance;
|
||||
if (instance instanceof ICPPFunction) {
|
||||
rf= (ICPPFunction) instance;
|
||||
}
|
||||
}
|
||||
} catch (DOMException e) {
|
||||
// try next candidate
|
||||
}
|
||||
} else if (requireTemplate
|
||||
&& !(func instanceof ICPPConstructor) && !(func instanceof ICPPUnknownBinding)
|
||||
&& !(func instanceof ICPPMethod && ((ICPPMethod) func).isDestructor())) {
|
||||
functions[i]= null;
|
||||
}
|
||||
} else if (!requireTemplate
|
||||
|| (func instanceof ICPPConstructor) || (func instanceof ICPPUnknownBinding)
|
||||
|| (func instanceof ICPPMethod && ((ICPPMethod) func).isDestructor())) {
|
||||
rf= func;
|
||||
}
|
||||
if (rf != func || result != fns) {
|
||||
if (result == fns) {
|
||||
result= new ICPPFunction[fns.length-(i-idx)];
|
||||
System.arraycopy(fns, 0, result, 0, idx);
|
||||
}
|
||||
if (rf != null)
|
||||
result[idx]= rf;
|
||||
}
|
||||
if (rf != null)
|
||||
idx++;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static protected void instantiateConversionTemplates(IFunction[] functions, IType conversionType) {
|
||||
|
@ -1653,6 +1664,42 @@ public class CPPTemplates {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 14.8.2.2 Deducing template arguments taking the address of a function template [temp.deduct.funcaddr]
|
||||
*/
|
||||
static protected ICPPFunction instantiateFunctionTemplate(ICPPFunctionTemplate template, IFunctionType target, IASTName name) {
|
||||
if (name.getPropertyInParent() == ICPPASTTemplateId.TEMPLATE_NAME) {
|
||||
name= (IASTName) name.getParent();
|
||||
}
|
||||
try {
|
||||
if (isDependentType(target)) {
|
||||
return CPPUnknownFunction.createForSample(template);
|
||||
}
|
||||
|
||||
ICPPTemplateArgument[] tmplArgs;
|
||||
if (name instanceof ICPPASTTemplateId && !(template instanceof ICPPConstructor)) {
|
||||
tmplArgs = createTemplateArgumentArray((ICPPASTTemplateId) name);
|
||||
if (hasDependentArgument(tmplArgs)) {
|
||||
return CPPUnknownFunction.createForSample(template);
|
||||
}
|
||||
} else {
|
||||
tmplArgs= ICPPTemplateArgument.EMPTY_ARGUMENTS;
|
||||
}
|
||||
|
||||
CPPTemplateParameterMap map= new CPPTemplateParameterMap(4);
|
||||
ICPPTemplateArgument[] args= TemplateArgumentDeduction.deduceForAddressOf(template, tmplArgs, target, map);
|
||||
if (args != null) {
|
||||
IBinding instance= instantiateFunctionTemplate(template, args, map);
|
||||
if (instance instanceof ICPPFunction) {
|
||||
return (ICPPFunction) instance;
|
||||
}
|
||||
}
|
||||
} catch (DOMException e) {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Transforms a function template for use in partial ordering, as described in the
|
||||
* spec 14.5.5.2-3
|
||||
|
|
|
@ -41,6 +41,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPBasicType;
|
|||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPEnumeration;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionType;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespace;
|
||||
|
@ -668,14 +669,18 @@ public class Conversions {
|
|||
|
||||
FunctionCost cost1= null;
|
||||
Cost cost2= null;
|
||||
ICPPConstructor[] ctors= t.getConstructors();
|
||||
CPPTemplates.instantiateFunctionTemplates(ctors, new IType[]{source}, new ValueCategory[] {valueCat}, null, false);
|
||||
ICPPFunction[] ctors= t.getConstructors();
|
||||
ctors= CPPTemplates.instantiateFunctionTemplates(ctors, new IType[]{source}, new ValueCategory[] {valueCat}, null, false);
|
||||
|
||||
for (ICPPConstructor ctor : ctors) {
|
||||
for (ICPPFunction f : ctors) {
|
||||
if (!(f instanceof ICPPConstructor) || f instanceof IProblemBinding)
|
||||
continue;
|
||||
|
||||
ICPPConstructor ctor= (ICPPConstructor) f;
|
||||
// Note: the special case of initializing a temporary to be bound to the first parameter
|
||||
// of a copy constructor called with a single argument in the context of direct-initialization
|
||||
// is (more naturally) handled in initializationByConversionForDirectReference.
|
||||
if (ctor != null && !(ctor instanceof IProblemBinding) && !ctor.isExplicit()) {
|
||||
if (!ctor.isExplicit()) {
|
||||
final ICPPFunctionType ft = ctor.getType();
|
||||
final IType[] ptypes = ft.getParameterTypes();
|
||||
FunctionCost c1;
|
||||
|
|
|
@ -89,6 +89,7 @@ public class Cost {
|
|||
private ReferenceBinding fReferenceBinding;
|
||||
|
||||
private boolean fCouldNarrow;
|
||||
private ICPPFunction fSelectedFunction; // For targeted functions
|
||||
|
||||
public Cost(IType s, IType t, Rank rank) {
|
||||
source = s;
|
||||
|
@ -266,4 +267,15 @@ public class Cost {
|
|||
public ICPPFunction getUserDefinedConversion() {
|
||||
return fUserDefinedConversion;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores a selected function. Used when resolving targeted functions.
|
||||
*/
|
||||
public void setSelectedFunction(ICPPFunction function) {
|
||||
fSelectedFunction= function;
|
||||
}
|
||||
|
||||
public ICPPFunction getSelectedFunction() {
|
||||
return fSelectedFunction;
|
||||
}
|
||||
}
|
|
@ -15,7 +15,12 @@ import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUti
|
|||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.TDEF;
|
||||
|
||||
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.IASTIdExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTName;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTUnaryExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IBinding;
|
||||
import org.eclipse.cdt.core.dom.ast.IFunctionType;
|
||||
import org.eclipse.cdt.core.dom.ast.IType;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction;
|
||||
|
@ -77,5 +82,46 @@ public class ExpressionTypes {
|
|||
return glvalueType(r);
|
||||
}
|
||||
return prvalueType(r);
|
||||
}
|
||||
|
||||
public static IType typeOrFunctionSet(IASTExpression e) {
|
||||
FunctionSetType fs= getFunctionSetType(e);
|
||||
if (fs != null) {
|
||||
return fs;
|
||||
}
|
||||
return e.getExpressionType();
|
||||
}
|
||||
|
||||
public static ValueCategory valueCat(IASTExpression e) {
|
||||
FunctionSetType fs= getFunctionSetType(e);
|
||||
if (fs != null)
|
||||
return fs.getValueCategory();
|
||||
return e.getValueCategory();
|
||||
}
|
||||
|
||||
private static FunctionSetType getFunctionSetType(IASTExpression e) {
|
||||
boolean addressOf= false;
|
||||
while (e instanceof IASTUnaryExpression) {
|
||||
final IASTUnaryExpression unary = (IASTUnaryExpression) e;
|
||||
final int op= unary.getOperator();
|
||||
if (op == IASTUnaryExpression.op_bracketedPrimary) {
|
||||
e= unary.getOperand();
|
||||
} else if (!addressOf && op == IASTUnaryExpression.op_amper) {
|
||||
addressOf= true;
|
||||
e= unary.getOperand();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (e instanceof IASTIdExpression) {
|
||||
IASTIdExpression idexpr= (IASTIdExpression) e;
|
||||
final IASTName name = idexpr.getName();
|
||||
IBinding b= name.resolvePreBinding();
|
||||
if (b instanceof CPPFunctionSet) {
|
||||
return new FunctionSetType(((CPPFunctionSet) b).getBindings(), name, addressOf);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
* FunctionSetType.java
|
||||
* Created on Sep 14, 2010
|
||||
*
|
||||
* Copyright 2010 Wind River Systems, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
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 org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTName;
|
||||
import org.eclipse.cdt.core.dom.ast.IBinding;
|
||||
import org.eclipse.cdt.core.dom.ast.IProblemBinding;
|
||||
import org.eclipse.cdt.core.dom.ast.IType;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPUnknownFunction;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.Cost.Rank;
|
||||
|
||||
/**
|
||||
* Used during overload resolution as a place-holder for function sets.
|
||||
*/
|
||||
public class FunctionSetType implements IType {
|
||||
|
||||
private ICPPFunction[] fFunctionSet;
|
||||
private boolean fPointerType;
|
||||
private IASTName fName;
|
||||
|
||||
public FunctionSetType(ICPPFunction[] functions, IASTName name, boolean addressOf) {
|
||||
fName= name;
|
||||
fFunctionSet= functions;
|
||||
fPointerType= addressOf;
|
||||
}
|
||||
|
||||
public boolean isSameType(IType type) {
|
||||
return type == this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object clone() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public ValueCategory getValueCategory() {
|
||||
return fPointerType ? PRVALUE : LVALUE;
|
||||
}
|
||||
|
||||
public Cost costForTarget(IType paramType) {
|
||||
IBinding result = CPPSemantics.resolveTargetedFunction(paramType, fName, fFunctionSet);
|
||||
if (result instanceof ICPPFunction && !(result instanceof IProblemBinding)) {
|
||||
Cost c= new Cost(paramType, paramType, Rank.IDENTITY);
|
||||
c.setSelectedFunction((ICPPFunction) result);
|
||||
return c;
|
||||
}
|
||||
return Cost.NO_CONVERSION;
|
||||
}
|
||||
|
||||
public void applySelectedFunction(ICPPFunction selectedFunction) {
|
||||
if (selectedFunction != null) {
|
||||
fName.setBinding(selectedFunction);
|
||||
}
|
||||
}
|
||||
|
||||
public ICPPFunction[] getFunctionSet() {
|
||||
return fFunctionSet;
|
||||
}
|
||||
|
||||
public void setToUnknown() {
|
||||
fName.setBinding(new CPPUnknownFunction(null, fName.toCharArray()));
|
||||
}
|
||||
}
|
|
@ -15,6 +15,7 @@
|
|||
package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics;
|
||||
|
||||
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.getSimplifiedType;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
@ -509,8 +510,9 @@ public class LookupData {
|
|||
for (int i = 0; i < exprs.length; i++) {
|
||||
IASTInitializerClause e = exprs[i];
|
||||
if (e instanceof IASTExpression) {
|
||||
IType etype= ((IASTExpression) e).getExpressionType();
|
||||
functionArgTypes[i]= SemanticUtil.getSimplifiedType(etype);
|
||||
// Find function set when taking an address of a function
|
||||
final IType t = ExpressionTypes.typeOrFunctionSet((IASTExpression) e);
|
||||
functionArgTypes[i]= getSimplifiedType(t);
|
||||
} else if (e instanceof ICPPASTInitializerList) {
|
||||
functionArgTypes[i]= new InitializerListType((ICPPASTInitializerList) e);
|
||||
}
|
||||
|
@ -535,7 +537,7 @@ public class LookupData {
|
|||
for (int i = 0; i < args.length; i++) {
|
||||
final IASTInitializerClause arg = args[i];
|
||||
if (arg instanceof IASTExpression) {
|
||||
functionArgValueCategories[i]= ((IASTExpression) arg).getValueCategory();
|
||||
functionArgValueCategories[i] = ExpressionTypes.valueCat((IASTExpression) arg);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -118,6 +118,87 @@ public class TemplateArgumentDeduction {
|
|||
return result.toArray(new ICPPTemplateArgument[result.size()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 14.8.2.2 [temp.deduct.funcaddr]
|
||||
* Deducing template arguments taking the address of a function template
|
||||
* @throws DOMException
|
||||
*/
|
||||
static ICPPTemplateArgument[] deduceForAddressOf(ICPPFunctionTemplate template,
|
||||
ICPPTemplateArgument[] tmplArgs, IFunctionType arg, CPPTemplateParameterMap map) throws DOMException {
|
||||
final ICPPTemplateParameter[] tmplParams = template.getTemplateParameters();
|
||||
final int numTmplParams = tmplParams.length;
|
||||
final int numTmplArgs = tmplArgs.length;
|
||||
|
||||
tmplArgs= SemanticUtil.getSimplifiedArguments(tmplArgs);
|
||||
ICPPTemplateParameter tmplParam= null;
|
||||
int packOffset= -1;
|
||||
for (int i = 0; i < numTmplArgs; i++) {
|
||||
if (packOffset < 0 || tmplParam == null) {
|
||||
if (i >= numTmplParams)
|
||||
return null;
|
||||
|
||||
tmplParam= tmplParams[i];
|
||||
if (tmplParam.isParameterPack()) {
|
||||
packOffset= i;
|
||||
}
|
||||
}
|
||||
ICPPTemplateArgument tmplArg= tmplArgs[i];
|
||||
tmplArg= CPPTemplates.matchTemplateParameterAndArgument(tmplParam, tmplArg, map);
|
||||
if (tmplArg == null)
|
||||
return null;
|
||||
|
||||
if (packOffset < 0) {
|
||||
map.put(tmplParam, tmplArg);
|
||||
}
|
||||
}
|
||||
|
||||
if (packOffset >= 0) {
|
||||
final int packSize= tmplArgs.length- packOffset;
|
||||
ICPPTemplateArgument[] pack= new ICPPTemplateArgument[packSize];
|
||||
System.arraycopy(tmplArgs, packOffset, pack, 0, packSize);
|
||||
map.put(tmplParam, pack);
|
||||
}
|
||||
|
||||
IType par= template.getType();
|
||||
par= CPPTemplates.instantiateType(par, map, -1, null);
|
||||
if (!CPPTemplates.isValidType(par))
|
||||
return null;
|
||||
|
||||
boolean isDependentPar= CPPTemplates.isDependentType(par);
|
||||
if (isDependentPar) {
|
||||
TemplateArgumentDeduction deduct= new TemplateArgumentDeduction(tmplParams, map, new CPPTemplateParameterMap(tmplParams.length), 0);
|
||||
par= SemanticUtil.getNestedType(par, SemanticUtil.TDEF);
|
||||
if (!deduct.fromType(par, arg, false))
|
||||
return null;
|
||||
if (!map.mergeToExplicit(deduct.fDeducedArgs))
|
||||
return null;
|
||||
if (!verifyDeduction(tmplParams, map, true))
|
||||
return null;
|
||||
|
||||
par= CPPTemplates.instantiateType(par, map, -1, null);
|
||||
}
|
||||
|
||||
if (arg.isSameType(par)) {
|
||||
List<ICPPTemplateArgument> result= new ArrayList<ICPPTemplateArgument>(numTmplParams);
|
||||
for (ICPPTemplateParameter tpar : tmplParams) {
|
||||
if (tpar.isParameterPack()) {
|
||||
ICPPTemplateArgument[] deducedArgs= map.getPackExpansion(tpar);
|
||||
if (deducedArgs == null)
|
||||
return null;
|
||||
result.addAll(Arrays.asList(deducedArgs));
|
||||
} else {
|
||||
ICPPTemplateArgument deducedArg= map.getArgument(tpar);
|
||||
if (deducedArg == null)
|
||||
return null;
|
||||
|
||||
result.add(deducedArg);
|
||||
}
|
||||
}
|
||||
return result.toArray(new ICPPTemplateArgument[result.size()]);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deduce arguments for a user defined conversion template
|
||||
* 14.8.2.3
|
||||
|
|
Loading…
Add table
Reference in a new issue