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

Bug 302412: Overload resolution for list-initializers.

This commit is contained in:
Markus Schorn 2010-03-11 17:58:45 +00:00
parent 4deee6b218
commit d5c5ba8f02
13 changed files with 545 additions and 159 deletions

View file

@ -8077,5 +8077,68 @@ public class AST2CPPTests extends AST2BaseTest {
String code= getAboveComment();
parseAndCheckBindings(code, ParserLanguage.CPP);
}
// namespace std {
// template<typename T> class initializer_list;
// }
// template<typename T> struct complex {
// complex(const T& r, const T& i);
// };
// template<typename T> struct vector {
// vector(std::initializer_list<T>);
// };
// struct str {
// str(const char*);
// };
// template<typename T> void f(std::initializer_list<T>);
// std::initializer_list<const char*> test() {
// int a = {1};
// complex<double> z{1,2};
// new vector<str>{"a", "b", "c", "d"}; // 4 string elements
// f( {"a","b"} ); // pass list of two elements
// int* e {}; // initialization to zero / null pointer
// a = double{1}; // explicitly construct a double
// return { "a" }; // return list of one element
// }
//
// struct S {
// S(std::initializer_list<double>) {}
// S(std::initializer_list<int>) {}
// };
// void fs(S){}
// void tests() {
// fs({1,2,3});
// fs({1.0,2.0,3.0});
// }
public void _testListInitialization_302412a() throws Exception {
String code= getAboveComment();
parseAndCheckBindings(code, ParserLanguage.CPP);
}
// namespace std {
// template<typename T> class initializer_list;
// }
// void f(std::initializer_list<int>);
// //void ff(std::initializer_list<str>);
// struct A {
// A(std::initializer_list<double>); // #1
// A(std::initializer_list<const char*>); // #3
// };
// void g(A);
// void test() {
// f( {1,2,3} ); // OK: f(initializer_list<int>) identity conversion
// f( {'a','b'} ); // OK: f(initializer_list<int>) integral promotion
// f( {1.0} ); // error: narrowing
// A a{ 1.0,2.0 }; // OK, uses #1
// g({ "foo", "bar" }); // OK, uses #3
// }
public void testListInitialization_302412b() throws Exception {
String code= getAboveComment();
BindingAssertionHelper bh= new BindingAssertionHelper(code, true);
bh.assertNonProblem("f( {1,2,3} )", 1);
bh.assertNonProblem("f( {'a','b'} )", 1);
bh.assertProblem("f( {1.0} )", 1);
bh.assertNonProblem("g({ \"foo\", \"bar\" })", 1);
}
}

View file

@ -16,9 +16,9 @@ import org.eclipse.cdt.core.dom.ast.ASTVisitor;
import org.eclipse.cdt.core.dom.ast.DOMException;
import org.eclipse.cdt.core.dom.ast.ExpansionOverlapsBoundaryException;
import org.eclipse.cdt.core.dom.ast.IASTExpression;
import org.eclipse.cdt.core.dom.ast.IASTInitializerClause;
import org.eclipse.cdt.core.dom.ast.IASTIdExpression;
import org.eclipse.cdt.core.dom.ast.IASTImplicitName;
import org.eclipse.cdt.core.dom.ast.IASTInitializerClause;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IFunction;
@ -64,7 +64,7 @@ public class CPPASTFunctionCallExpression extends ASTNode implements
public CPPASTFunctionCallExpression copy() {
IASTInitializerClause[] args = null;
if (fArguments.length > 0) {
args= new IASTExpression[fArguments.length];
args= new IASTInitializerClause[fArguments.length];
for (int i=0; i<fArguments.length; i++) {
args[i]= fArguments[i].copy();
}

View file

@ -17,11 +17,11 @@ import org.eclipse.cdt.core.dom.ast.IASTEqualsInitializer;
import org.eclipse.cdt.core.dom.ast.IASTExpression;
import org.eclipse.cdt.core.dom.ast.IASTInitializer;
import org.eclipse.cdt.core.dom.ast.IASTInitializerClause;
import org.eclipse.cdt.core.dom.ast.IASTInitializerList;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.IValue;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTInitializerList;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTParameterDeclaration;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPParameterPackType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateArgument;
@ -42,6 +42,15 @@ public class CPPTemplateNonTypeParameter extends CPPTemplateParameter implements
}
public IASTExpression getDefault() {
IASTInitializerClause def= getDefaultClause();
if (def instanceof IASTExpression) {
return (IASTExpression) def;
}
return null;
}
public IASTInitializerClause getDefaultClause() {
IASTName[] nds = getDeclarations();
if (nds == null || nds.length == 0)
return null;
@ -54,12 +63,7 @@ public class CPPTemplateNonTypeParameter extends CPPTemplateParameter implements
IASTDeclarator dtor = (IASTDeclarator) parent;
IASTInitializer initializer = dtor.getInitializer();
if (initializer instanceof IASTEqualsInitializer) {
IASTInitializerClause clause= ((IASTEqualsInitializer) initializer).getInitializerClause();
if (clause instanceof IASTExpression)
return (IASTExpression) clause;
if (clause instanceof IASTInitializerList) {
// mstodo handle braced init list
}
return ((IASTEqualsInitializer) initializer).getInitializerClause();
}
}
}
@ -68,7 +72,23 @@ public class CPPTemplateNonTypeParameter extends CPPTemplateParameter implements
}
public ICPPTemplateArgument getDefaultValue() {
IASTExpression d= getDefault();
IASTInitializerClause dc= getDefault();
IASTExpression d= null;
if (dc instanceof IASTExpression) {
d= (IASTExpression) dc;
} else if (dc instanceof ICPPASTInitializerList) {
ICPPASTInitializerList list= (ICPPASTInitializerList) dc;
switch(list.getSize()) {
case 0:
return new CPPTemplateArgument(Value.create(0), getType());
case 1:
dc= list.getClauses()[0];
if (dc instanceof IASTExpression) {
d= (IASTExpression) dc;
}
}
}
if (d == null)
return null;

View file

@ -33,6 +33,7 @@ import org.eclipse.cdt.core.dom.ast.IScope;
import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.IValue;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConstructorInitializer;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTInitializerList;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPBlockScope;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPVariable;
@ -409,11 +410,18 @@ public class CPPVariable extends PlatformObject implements ICPPVariable, ICPPInt
clause= args[0];
}
}
} else if (init instanceof ICPPASTInitializerList) {
ICPPASTInitializerList list= (ICPPASTInitializerList) init;
switch (list.getSize()) {
case 0:
return Value.create(0);
case 1:
clause= list.getClauses()[0];
}
}
if (clause instanceof IASTExpression) {
return Value.create((IASTExpression) clause, maxDepth);
}
// mstodo handle braced init list
return Value.UNKNOWN;
}
}

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2004, 2009 IBM Corporation and others.
* Copyright (c) 2004, 2010 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
@ -49,6 +49,7 @@ 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.ICPPField;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMember;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPReferenceType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPUsingDeclaration;
@ -735,4 +736,30 @@ public class ClassTypeHelper {
}
return null;
}
/**
* 8.5.1 Aggregates [dcl.init.aggr]
* An aggregate is an array or a class (Clause 9) with no user-provided constructors (12.1),
* no private or protected non-static data members (Clause 11),
* no base classes (Clause 10), and no virtual functions (10.3).
*/
public static boolean isAggregateClass(ICPPClassType classTarget) throws DOMException {
if (classTarget.getBases().length > 0)
return false;
ICPPMethod[] methods = classTarget.getDeclaredMethods();
for (ICPPMethod m : methods) {
if (m instanceof ICPPConstructor)
return false;
if (m.isVirtual()) {
return false;
}
}
ICPPField[] fields = classTarget.getDeclaredFields();
for (ICPPField field : fields) {
if (!(field.getVisibility() == ICPPMember.v_public || field.isStatic())) {
return false;
}
}
return true;
}
}

View file

@ -830,7 +830,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
if (allowThrow && LT(1) == IToken.t_throw) {
expr= throwExpression();
} else if (allowBraceInitializer && LT(1) == IToken.tLBRACE) {
expr= bracedInitList();
expr= bracedInitList(true);
} else {
expr= castExpression(castCtx); // next cast expression
continue loop;
@ -1162,7 +1162,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
if (t != null) {
consume(IToken.tRPAREN);
if (LT(1) == IToken.tLBRACE) {
IASTInitializer i = bracedInitList();
IASTInitializer i = bracedInitList(false);
firstExpression= nodeFactory.newTypeIdInitializerExpression(t, i);
setRange(firstExpression, offset, calculateEndOffset(i));
break;
@ -1212,7 +1212,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
consume(IToken.tLBRACKET);
IASTInitializerClause expression;
if (LT(1) == IToken.tLBRACE) {
expression= bracedInitList();
expression= bracedInitList(false);
} else {
expression= expression();
}
@ -2795,14 +2795,14 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
// = initializer-clause
if (lt1 == IToken.tASSIGN) {
int offset= consume().getOffset();
IASTInitializerClause initClause = initClause(false);
IASTInitializerClause initClause = initClause(LT(1) == IToken.tLBRACE);
IASTEqualsInitializer initExpr= nodeFactory.newEqualsInitializer(initClause);
return setRange(initExpr, offset, calculateEndOffset(initClause));
}
// braced-init-list
if (option.fAllowBracedInitializer && lt1 == IToken.tLBRACE) {
return bracedInitList();
return bracedInitList(false);
}
// ( expression-list )
@ -2817,7 +2817,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
if (lt1 == IToken.tLPAREN) {
return ctorStyleInitializer(true);
}
return bracedInitList();
return bracedInitList(false);
}
/**
@ -2848,17 +2848,17 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
* assignment-expression
* braced-init-list
*/
private IASTInitializerClause initClause(boolean inBraces) throws EndOfFileException,
private IASTInitializerClause initClause(boolean allowSkipping) throws EndOfFileException,
BacktrackException {
// braced-init-list
if (LT(1) == IToken.tLBRACE) {
return bracedInitList();
return bracedInitList(allowSkipping);
}
// assignment expression
final BinaryExprCtx ctx = fInTemplateParameterList ? BinaryExprCtx.eTmplID : BinaryExprCtx.eNoTmplID;
IASTExpression assignmentExpression = expression(ExprKind.eAssignment, ctx);
if (inBraces && skipTrivialExpressionsInAggregateInitializers) {
if (allowSkipping && skipTrivialExpressionsInAggregateInitializers) {
if (!ASTQueries.canContainName(assignmentExpression))
return null;
}
@ -2870,7 +2870,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
* { initializer-list ,opt }
* { }
*/
private ICPPASTInitializerList bracedInitList() throws EndOfFileException, BacktrackException {
private ICPPASTInitializerList bracedInitList(boolean allowSkipping) throws EndOfFileException, BacktrackException {
int offset = consume(IToken.tLBRACE).getOffset();
// { }
@ -2879,7 +2879,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
}
// { initializer-list ,opt }
List<IASTInitializerClause> initList= initializerList(true);
List<IASTInitializerClause> initList= initializerList(allowSkipping);
if (LT(1) == IToken.tCOMMA)
consume();
@ -2896,14 +2896,14 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
* initializer-clause ...opt
* initializer-list , initializer-clause ...opt
*/
private List<IASTInitializerClause> initializerList(boolean inAggregateInit) throws EndOfFileException,
private List<IASTInitializerClause> initializerList(boolean allowSkipping) throws EndOfFileException,
BacktrackException {
List<IASTInitializerClause> result= null;
// List of initializer clauses
loop: for(;;) {
// Clause may be null, add to initializer anyways, such that the size can be computed.
IASTInitializerClause clause = initClause(inAggregateInit);
IASTInitializerClause clause = initClause(allowSkipping);
if (LT(1) == IToken.tELLIPSIS) {
final int endOffset = consume(IToken.tELLIPSIS).getEndOffset();
if (clause instanceof ICPPASTPackExpandable) {
@ -4073,7 +4073,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
IASTInitializerClause expr = null;
final int lt1 = LT(1);
if (lt1 == IToken.tLBRACE) {
expr= bracedInitList();
expr= bracedInitList(true);
} else if (lt1 != IToken.tSEMI) {
expr = expression();
}

View file

@ -93,6 +93,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTForStatement;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDeclarator;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDefinition;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTIfStatement;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTInitializerList;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTLinkageSpecification;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamedTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamespaceAlias;
@ -393,7 +394,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.hasArgumentTypes()) {
if (data.hasFunctionArguments()) {
binding= new CPPUnknownFunction(data.skippedScope, name.getSimpleID());
} else {
if (namePropertyInParent == IASTNamedTypeSpecifier.NAME) {
@ -527,11 +528,25 @@ public class CPPSemantics {
return false;
}
public static IBinding selectConstructor(ICPPClassType classTarget, ICPPASTInitializerList initializerList) {
LookupData data= new LookupData();
IASTName name = new CPPASTName(classTarget.getNameCharArray());
name.setParent(initializerList);
name.setPropertyInParent(CPPSemantics.STRING_LOOKUP_PROPERTY);
data.setFunctionArguments(initializerList);
try {
return CPPSemantics.selectConstructor(classTarget, data);
} catch (DOMException e) {
return e.getProblem();
}
}
private static IBinding selectConstructor(ICPPClassType cls, LookupData data) throws DOMException {
// Force resolution of constructor bindings
final ICPPConstructor[] constructors= cls.getConstructors();
if (constructors.length > 0) {
return CPPSemantics.resolveAmbiguities(data.astName, constructors);
data.foundItems= constructors;
return CPPSemantics.resolveAmbiguities(data, data.astName);
}
return cls;
}
@ -626,8 +641,8 @@ public class CPPSemantics {
data.setFunctionArguments();
} else if (init instanceof ICPPASTConstructorInitializer) {
data.setFunctionArguments(((ICPPASTConstructorInitializer) init).getArguments());
} else {
// mstodo handle braced init list
} else if (init instanceof ICPPASTInitializerList) {
data.setFunctionArguments(new IASTInitializerClause[] {(ICPPASTInitializerList) init});
}
}
} else if (parent instanceof ICPPASTConstructorChainInitializer) {
@ -635,8 +650,8 @@ public class CPPSemantics {
IASTInitializer init = ctorinit.getInitializer();
if (init instanceof ICPPASTConstructorInitializer) {
data.setFunctionArguments(((ICPPASTConstructorInitializer) init).getArguments());
} else {
// mstodo handle braced init list
} else if (init instanceof ICPPASTInitializerList) {
data.setFunctionArguments(new IASTInitializerClause[] {(ICPPASTInitializerList) init});
}
}
@ -644,7 +659,7 @@ public class CPPSemantics {
}
static private ObjectSet<ICPPScope> getAssociatedScopes(LookupData data) {
if (!data.hasArgumentTypes())
if (!data.hasFunctionArguments())
return ObjectSet.emptySet();
IType[] ps = data.getFunctionArgumentTypes();
@ -2138,7 +2153,8 @@ public class CPPSemantics {
}
// We don't have any arguments with which to resolve the function
if (!data.hasArgumentTypes()) {
final boolean isFuncDecl = data.forFunctionDeclaration();
if (!data.hasFunctionArguments()) {
return resolveTargetedFunction(data, fns);
}
@ -2146,7 +2162,7 @@ public class CPPSemantics {
return resolveUserDefinedConversion(data, fns);
}
if (!data.forFunctionDeclaration() || data.forExplicitFunctionSpecialization()) {
if (!isFuncDecl || data.forExplicitFunctionSpecialization()) {
CPPTemplates.instantiateFunctionTemplates(fns, data.getFunctionArgumentTypes(), data.getFunctionArgumentLValues(), data.astName);
}
@ -2165,7 +2181,7 @@ public class CPPSemantics {
}
}
}
if (firstViable == null || data.forFunctionDeclaration())
if (firstViable == null || isFuncDecl)
return firstViable;
// The arguments the function is being called with

View file

@ -30,6 +30,7 @@ import org.eclipse.cdt.core.dom.ast.IASTElaboratedTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTExpression;
import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition;
import org.eclipse.cdt.core.dom.ast.IASTIdExpression;
import org.eclipse.cdt.core.dom.ast.IASTInitializerClause;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration;
@ -50,6 +51,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTElaboratedTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTExplicitTemplateInstantiation;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDefinition;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTInitializerList;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamedTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTParameterDeclaration;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName;
@ -1542,6 +1544,8 @@ public class CPPTemplates {
}
static protected void instantiateFunctionTemplates(IFunction[] functions, IType[] fnArgs, BitSet argIsLValue, IASTName name) {
// mstodo handle list initialization
boolean requireTemplate= false;
if (name != null) {
if (name.getPropertyInParent() == ICPPASTTemplateId.TEMPLATE_NAME) {
@ -2045,12 +2049,29 @@ public class CPPTemplates {
return true;
}
t= ((ITypeContainer) t).getType();
} else if (t instanceof InitializerListType) {
return isDependentInitializerList(((InitializerListType) t).getInitializerList());
} else {
return false;
}
}
}
private static boolean isDependentInitializerList(ICPPASTInitializerList initializerList) {
IASTInitializerClause[] clauses= initializerList.getClauses();
for (IASTInitializerClause clause : clauses) {
if (clause instanceof IASTExpression) {
IType t= ((IASTExpression) clause).getExpressionType();
if (isDependentType(t))
return true;
} else if (clause instanceof ICPPASTInitializerList) {
if (isDependentInitializerList((ICPPASTInitializerList) clause))
return true;
}
}
return false;
}
public static boolean containsDependentArg(ObjectMap tpMap) {
for (Object arg : tpMap.valueArray()) {
if (isDependentType((IType)arg))

View file

@ -24,6 +24,7 @@ import org.eclipse.cdt.core.dom.ast.IASTExpression;
import org.eclipse.cdt.core.dom.ast.IASTLiteralExpression;
import org.eclipse.cdt.core.dom.ast.IArrayType;
import org.eclipse.cdt.core.dom.ast.IBasicType;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IEnumeration;
import org.eclipse.cdt.core.dom.ast.IFunctionType;
import org.eclipse.cdt.core.dom.ast.IPointerType;
@ -33,17 +34,23 @@ import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.IValue;
import org.eclipse.cdt.core.dom.ast.IBasicType.Kind;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPBasicType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassSpecialization;
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.ICPPFunctionType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespace;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPPointerToMemberType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPReferenceType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateArgument;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateInstance;
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
import org.eclipse.cdt.internal.core.dom.parser.ArithmeticConversion;
import org.eclipse.cdt.internal.core.dom.parser.Value;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPBasicType;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPPointerToMemberType;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPPointerType;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ClassTypeHelper;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.Cost.Rank;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.Cost.ReferenceBinding;
@ -58,6 +65,9 @@ public class Conversions {
static {
LVBITSET.set(0, true);
}
private static final char[] INITIALIZER_LIST_NAME = "initializer_list".toCharArray(); //$NON-NLS-1$
private static final char[] STD_NAME = "std".toCharArray(); //$NON-NLS-1$
/**
* Computes the cost of an implicit conversion sequence
* [over.best.ics] 13.3.3.1
@ -85,7 +95,7 @@ public class Conversions {
final IType cv2T2= exprType;
final IType T2= getNestedType(cv2T2, TDEF | REF | ALLCVQ);
final boolean isImplicitWithoutRefQualifier = isImpliedObjectType; // mstodo need to pass this information to here
final boolean isImplicitWithoutRefQualifier = isImpliedObjectType;
ReferenceBinding refBindingType= ReferenceBinding.OTHER;
if (!isImplicitWithoutRefQualifier) {
if (isLValueRef) {
@ -258,6 +268,9 @@ public class Conversions {
}
private static Cost nonReferenceConversion(boolean sourceIsLValue, IType source, IType target, UDCMode udc, boolean isImpliedObject) throws DOMException {
if (source instanceof InitializerListType) {
return listInitializationSequence(((InitializerListType) source), target, udc);
}
// [13.3.3.1-6] Subsume cv-qualifications
IType uqSource= SemanticUtil.getNestedType(source, TDEF | ALLCVQ);
Cost cost= checkStandardConversionSequence(uqSource, sourceIsLValue, target, isImpliedObject);
@ -271,6 +284,68 @@ public class Conversions {
return cost;
}
/**
* 13.3.3.1.5 List-initialization sequence [over.ics.list]
*/
private static Cost listInitializationSequence(InitializerListType arg, IType target, UDCMode udc) throws DOMException {
IType listType= getInitListType(target);
if (listType != null) {
IType[] exprTypes= arg.getExpressionTypes();
BitSet isLValue= arg.getIsLValue();
Cost worstCost= new Cost(arg, target, Rank.IDENTITY);
for (int i = 0; i < exprTypes.length; i++) {
IType exprType = exprTypes[i];
Cost cost= checkImplicitConversionSequence(listType, exprType, isLValue.get(i), UDCMode.allowUDC, false);
if (cost.getRank() == Rank.NO_MATCH)
return cost;
if (cost.isNarrowingConversion()) {
cost.setRank(Rank.NO_MATCH);
return cost;
}
if (cost.compareTo(worstCost) > 0) {
worstCost= cost;
}
}
return worstCost;
}
IType noCVTarget= getNestedType(target, CVTYPE | TDEF);
if (noCVTarget instanceof ICPPClassType) {
if (udc == UDCMode.noUDC)
return new Cost(arg, target, Rank.NO_MATCH);
ICPPClassType classTarget= (ICPPClassType) noCVTarget;
if (ClassTypeHelper.isAggregateClass(classTarget)) {
return new Cost(arg, target, Rank.USER_DEFINED_CONVERSION);
}
Cost cost= checkUserDefinedConversionSequence(false, arg, target, udc == UDCMode.deferUDC);
if (cost != null)
return cost;
}
return new Cost(arg, target, Rank.NO_MATCH);
}
private static IType getInitListType(IType target) throws DOMException {
if (target instanceof ICPPClassSpecialization && target instanceof ICPPTemplateInstance) {
ICPPTemplateInstance inst = (ICPPTemplateInstance) target;
if (CharArrayUtils.equals(INITIALIZER_LIST_NAME, inst.getNameCharArray())) {
IBinding owner = inst.getOwner();
if (owner instanceof ICPPNamespace
&& CharArrayUtils.equals(STD_NAME, owner.getNameCharArray())
&& owner.getOwner() == null) {
ICPPTemplateArgument[] args = inst.getTemplateArguments();
if (args.length == 1) {
ICPPTemplateArgument arg = args[0];
if (arg.isTypeValue()) {
return arg.getTypeValue();
}
}
}
}
}
return null;
}
/**
* [3.9.3-4] Implements cv-ness (partial) comparison. There is a (partial)
* ordering on cv-qualifiers, so that a type can be said to be more
@ -423,6 +498,7 @@ public class Conversions {
* @throws DOMException
*/
static final Cost checkUserDefinedConversionSequence(boolean sourceIsLValue, IType source, IType target, boolean deferUDC) throws DOMException {
// mstodo don't return null
IType s= getNestedType(source, TDEF | CVTYPE | REF);
IType t= getNestedType(target, TDEF | CVTYPE | REF);
@ -436,106 +512,130 @@ public class Conversions {
return c;
}
// 13.3.1.4 Copy initialization of class by user-defined conversion
if (t instanceof ICPPClassType) {
FunctionCost cost1= null;
Cost cost2= null;
ICPPConstructor[] ctors= ((ICPPClassType) t).getConstructors();
CPPTemplates.instantiateFunctionTemplates(ctors, new IType[]{source}, sourceIsLValue ? LVBITSET : RVBITSET, null);
for (ICPPConstructor ctor : ctors) {
if (ctor != null && !(ctor instanceof IProblemBinding) && !ctor.isExplicit()) {
final ICPPFunctionType ft = ctor.getType();
final IType[] ptypes = ft.getParameterTypes();
FunctionCost c1;
if (ptypes.length == 0) {
if (ctor.takesVarArgs()) {
c1= new FunctionCost(ctor, new Cost(source, null, Rank.ELLIPSIS_CONVERSION));
} else {
continue;
}
} else {
IType ptype= SemanticUtil.getNestedType(ptypes[0], TDEF);
// We don't need to check the implicit conversion sequence if the type is void
if (SemanticUtil.isVoidType(ptype))
continue;
if (ctor.getRequiredArgumentCount() > 1)
continue;
c1= new FunctionCost(ctor, checkImplicitConversionSequence(ptype, source, sourceIsLValue, UDCMode.noUDC, false));
}
int cmp= c1.compareTo(null, cost1);
if (cmp <= 0) {
cost1= c1;
cost2= new Cost(t, t, Rank.IDENTITY);
cost2.setUserDefinedConversion(ctor);
if (cmp == 0) {
cost2.setAmbiguousUDC(true);
}
}
}
if (s instanceof InitializerListType) {
// 13.3.1.7 Initialization by list-initialization
return listInitializationOfClass((InitializerListType) s, (ICPPClassType) t, false);
}
if (s instanceof ICPPClassType) {
ICPPMethod[] ops = SemanticUtil.getConversionOperators((ICPPClassType) s);
CPPTemplates.instantiateConversionTemplates(ops, target);
for (final ICPPMethod op : ops) {
if (op != null && !(op instanceof IProblemBinding)) {
final IType returnType = op.getType().getReturnType();
final IType uqReturnType= getNestedType(returnType, REF | TDEF | CVTYPE);
final int dist = SemanticUtil.calculateInheritanceDepth(uqReturnType, t);
if (dist >= 0) {
final ICPPFunctionType ft = op.getType();
IType implicitType= CPPSemantics.getImplicitType(op, ft.isConst(), ft.isVolatile());
final Cost udcCost = isReferenceCompatible(getNestedType(implicitType, TDEF | REF), source, true);
if (udcCost != null) {
FunctionCost c1= new FunctionCost(op, udcCost);
int cmp= c1.compareTo(null, cost1);
if (cmp <= 0) {
cost1= c1;
cost2= new Cost(t, t, Rank.IDENTITY);
if (dist > 0) {
cost2.setInheritanceDistance(dist);
cost2.setRank(Rank.CONVERSION);
}
cost2.setUserDefinedConversion(op);
if (cmp == 0) {
cost2.setAmbiguousUDC(true);
}
}
// 13.3.1.4 Copy initialization of class by user-defined conversion
return copyInitalizationOfClass(sourceIsLValue, source, s, target, (ICPPClassType) t);
}
if (s instanceof ICPPClassType) {
// 13.3.1.5 Initialization by conversion function
return initializationByConversion(source, (ICPPClassType) s, target);
}
return null;
}
private static Cost listInitializationOfClass(InitializerListType s, ICPPClassType t, boolean isDirect) throws DOMException {
// If T has an initializer-list constructor
ICPPConstructor usedCtor= null;
Cost bestCost= null;
ICPPConstructor[] ctors= t.getConstructors();
for (ICPPConstructor ctor : ctors) {
if (ctor.getRequiredArgumentCount() <= 1) {
IType[] parTypes= ctor.getType().getParameterTypes();
if (parTypes.length > 0) {
final IType target = parTypes[0];
if (getInitListType(target) != null) {
Cost cost= listInitializationSequence(s, target, UDCMode.noUDC);
if (cost.getRank() == Rank.NO_MATCH) {
if (bestCost == null) {
bestCost= cost;
}
} else {
int cmp= cost.compareTo(bestCost);
if (bestCost == null || cmp < 0) {
usedCtor= ctor;
cost.setUserDefinedConversion(ctor);
bestCost= cost;
} else if (cmp == 0) {
bestCost.setAmbiguousUDC(true);
}
}
}
}
}
if (cost1 == null || cost1.getCost(0).getRank() == Rank.NO_MATCH)
return null;
return cost2;
}
if (bestCost != null) {
if (!bestCost.isAmbiguousUDC() && !isDirect) {
if (usedCtor != null && usedCtor.isExplicit()) {
bestCost.setRank(Rank.NO_MATCH);
}
}
return bestCost;
}
// 13.3.1.5 Initialization by conversion function
// mstodo expanding the list for selecting the ctor.
return new Cost(s, t, Rank.NO_MATCH);
}
/**
* 13.3.1.4 Copy-initialization of class by user-defined conversion [over.match.copy]
*/
private static Cost copyInitalizationOfClass(boolean sourceIsLValue, IType source, IType s, IType target,
ICPPClassType t) throws DOMException {
FunctionCost cost1= null;
Cost cost2= null;
ICPPConstructor[] ctors= t.getConstructors();
CPPTemplates.instantiateFunctionTemplates(ctors, new IType[]{source}, sourceIsLValue ? LVBITSET : RVBITSET, null);
for (ICPPConstructor ctor : ctors) {
if (ctor != null && !(ctor instanceof IProblemBinding) && !ctor.isExplicit()) {
final ICPPFunctionType ft = ctor.getType();
final IType[] ptypes = ft.getParameterTypes();
FunctionCost c1;
if (ptypes.length == 0) {
if (ctor.takesVarArgs()) {
c1= new FunctionCost(ctor, new Cost(source, null, Rank.ELLIPSIS_CONVERSION));
} else {
continue;
}
} else {
IType ptype= SemanticUtil.getNestedType(ptypes[0], TDEF);
// We don't need to check the implicit conversion sequence if the type is void
if (SemanticUtil.isVoidType(ptype))
continue;
if (ctor.getRequiredArgumentCount() > 1)
continue;
c1= new FunctionCost(ctor, checkImplicitConversionSequence(ptype, source, sourceIsLValue, UDCMode.noUDC, false));
}
int cmp= c1.compareTo(null, cost1);
if (cmp <= 0) {
cost1= c1;
cost2= new Cost(t, t, Rank.IDENTITY);
cost2.setUserDefinedConversion(ctor);
if (cmp == 0) {
cost2.setAmbiguousUDC(true);
}
}
}
}
if (s instanceof ICPPClassType) {
ICPPMethod[] ops = SemanticUtil.getConversionOperators((ICPPClassType) s);
CPPTemplates.instantiateConversionTemplates(ops, target);
FunctionCost cost1= null;
Cost cost2= null;
for (final ICPPMethod op : ops) {
if (op != null && !(op instanceof IProblemBinding)) {
final IType returnType = op.getType().getReturnType();
IType uqReturnType= getNestedType(returnType, TDEF | ALLCVQ);
boolean isLValue = uqReturnType instanceof ICPPReferenceType
&& !((ICPPReferenceType) uqReturnType).isRValueReference();
Cost c2= checkImplicitConversionSequence(target, uqReturnType, isLValue, UDCMode.noUDC, false);
if (c2.getRank() != Rank.NO_MATCH) {
ICPPFunctionType ftype = op.getType();
IType implicitType= CPPSemantics.getImplicitType(op, ftype.isConst(), ftype.isVolatile());
final IType uqReturnType= getNestedType(returnType, REF | TDEF | CVTYPE);
final int dist = SemanticUtil.calculateInheritanceDepth(uqReturnType, t);
if (dist >= 0) {
final ICPPFunctionType ft = op.getType();
IType implicitType= CPPSemantics.getImplicitType(op, ft.isConst(), ft.isVolatile());
final Cost udcCost = isReferenceCompatible(getNestedType(implicitType, TDEF | REF), source, true);
if (udcCost != null) {
FunctionCost c1= new FunctionCost(op, udcCost);
int cmp= c1.compareTo(null, cost1);
if (cmp <= 0) {
cost1= c1;
cost2= c2;
cost2= new Cost(t, t, Rank.IDENTITY);
if (dist > 0) {
cost2.setInheritanceDistance(dist);
cost2.setRank(Rank.CONVERSION);
}
cost2.setUserDefinedConversion(op);
if (cmp == 0) {
cost2.setAmbiguousUDC(true);
@ -545,12 +645,51 @@ public class Conversions {
}
}
}
if (cost1 == null || cost1.getCost(0).getRank() == Rank.NO_MATCH)
return null;
return cost2;
}
return null;
if (cost1 == null || cost1.getCost(0).getRank() == Rank.NO_MATCH)
return null;
return cost2;
}
/**
* 13.3.1.5 Initialization by conversion function [over.match.conv]
*/
private static Cost initializationByConversion(IType source, ICPPClassType s, IType target) throws DOMException {
ICPPMethod[] ops = SemanticUtil.getConversionOperators(s);
CPPTemplates.instantiateConversionTemplates(ops, target);
FunctionCost cost1= null;
Cost cost2= null;
for (final ICPPMethod op : ops) {
if (op != null && !(op instanceof IProblemBinding)) {
final IType returnType = op.getType().getReturnType();
IType uqReturnType= getNestedType(returnType, TDEF | ALLCVQ);
boolean isLValue = uqReturnType instanceof ICPPReferenceType
&& !((ICPPReferenceType) uqReturnType).isRValueReference();
Cost c2= checkImplicitConversionSequence(target, uqReturnType, isLValue, UDCMode.noUDC, false);
if (c2.getRank() != Rank.NO_MATCH) {
ICPPFunctionType ftype = op.getType();
IType implicitType= CPPSemantics.getImplicitType(op, ftype.isConst(), ftype.isVolatile());
final Cost udcCost = isReferenceCompatible(getNestedType(implicitType, TDEF | REF), source, true);
if (udcCost != null) {
FunctionCost c1= new FunctionCost(op, udcCost);
int cmp= c1.compareTo(null, cost1);
if (cmp <= 0) {
cost1= c1;
cost2= c2;
cost2.setUserDefinedConversion(op);
if (cmp == 0) {
cost2.setAmbiguousUDC(true);
}
}
}
}
}
}
if (cost1 == null || cost1.getCost(0).getRank() == Rank.NO_MATCH)
return null;
return cost2;
}
/**
@ -779,6 +918,7 @@ public class Conversions {
// 4.7 An rvalue of an integer type can be converted to an rvalue of another integer type.
// An rvalue of an enumeration type can be converted to an rvalue of an integer type.
cost.setRank(Rank.CONVERSION);
cost.setCouldNarrow();
return true;
}
// 4.12 pointer or pointer to member type can be converted to an rvalue of type bool
@ -812,7 +952,7 @@ public class Conversions {
IType tgtPtrTgt= getNestedType(tgtPtr.getType(), TDEF | CVTYPE | REF);
if (SemanticUtil.isVoidType(tgtPtrTgt)) {
cost.setRank(Rank.CONVERSION);
cost.setInheritanceDistance(Short.MAX_VALUE); // mstodo add distance to last base class
cost.setInheritanceDistance(Short.MAX_VALUE);
CVQualifier cv= getCVQualifier(srcPtr.getType());
cost.source= new CPPPointerType(addQualifiers(CPPSemantics.VOID_TYPE, cv.isConst(), cv.isVolatile()));
return false;

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2004, 2009 IBM Corporation and others.
* Copyright (c) 2004, 2010 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
@ -42,6 +42,8 @@ final class Cost {
private int fInheritanceDistance;
private ICPPFunction fUserDefinedConversion;
private ReferenceBinding fReferenceBinding;
private boolean fCouldNarrow;
public Cost(IType s, IType t, Rank rank) {
source = s;
@ -125,9 +127,11 @@ final class Cost {
if (isAmbiguousUDC() || other.isAmbiguousUDC())
return 0;
if (!fUserDefinedConversion.equals(other.fUserDefinedConversion))
return 0;
if (fUserDefinedConversion != other.fUserDefinedConversion) {
if (fUserDefinedConversion == null ||
!fUserDefinedConversion.equals(other.fUserDefinedConversion))
return 0;
}
cmp= fSecondStandardConversionRank.compareTo(other.fSecondStandardConversionRank);
if (cmp != 0)
return cmp;
@ -183,4 +187,12 @@ final class Cost {
buf.append(']');
return buf.toString();
}
public boolean isNarrowingConversion() {
return fCouldNarrow;
}
public void setCouldNarrow() {
fCouldNarrow= true;
}
}

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2009 Wind River Systems, Inc. and others.
* Copyright (c) 2009, 2010 Wind River Systems, Inc. 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
@ -77,7 +77,7 @@ class FunctionCost {
Cost cost = fCosts[i];
if (cost.isDeferredUDC()) {
Cost udcCost= Conversions.checkUserDefinedConversionSequence(fSourceIsLValue.get(i), cost.source, cost.target, false);
if (udcCost == null) {
if (udcCost == null || udcCost.getRank() == Rank.NO_MATCH) {
return false;
}
fCosts[i]= udcCost;

View file

@ -0,0 +1,84 @@
/*******************************************************************************
* Copyright (c) 2010 Wind River Systems, Inc. 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
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Markus Schorn - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics;
import java.util.BitSet;
import org.eclipse.cdt.core.dom.ast.IASTExpression;
import org.eclipse.cdt.core.dom.ast.IASTInitializerClause;
import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTInitializerList;
/**
* Wrapper for initializer lists to allow for participation in the overload resolution.
*/
class InitializerListType implements IType {
private final ICPPASTInitializerList fInitializerList;
private IType[] fExpressionTypes;
private BitSet fLValues;
public InitializerListType(ICPPASTInitializerList list) {
fInitializerList= list;
}
public boolean isSameType(IType type) {
return false;
}
@Override
public Object clone() {
try {
return super.clone();
} catch (CloneNotSupportedException e) {
// Will not happen, we IType extends Clonable.
return null;
}
}
public ICPPASTInitializerList getInitializerList() {
return fInitializerList;
}
public IType[] getExpressionTypes() {
if (fExpressionTypes == null) {
final IASTInitializerClause[] clauses = fInitializerList.getClauses();
fExpressionTypes= new IType[clauses.length];
for (int i = 0; i < clauses.length; i++) {
IASTInitializerClause clause = clauses[i];
if (clause instanceof IASTExpression) {
fExpressionTypes[i]= ((IASTExpression) clause).getExpressionType();
} else if (clause instanceof ICPPASTInitializerList) {
fExpressionTypes[i]= new InitializerListType((ICPPASTInitializerList) clause);
} else {
assert false;
}
}
}
return fExpressionTypes;
}
public BitSet getIsLValue() {
if (fLValues == null) {
final IASTInitializerClause[] clauses = fInitializerList.getClauses();
fLValues= new BitSet(clauses.length);
for (int i = 0; i < clauses.length; i++) {
IASTInitializerClause clause = clauses[i];
if (clause instanceof IASTExpression) {
if (((IASTExpression) clause).isLValue()) {
fLValues.set(i);
}
}
}
}
return fLValues;
}
}

View file

@ -49,6 +49,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeleteExpression;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTElaboratedTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTExplicitTemplateInstantiation;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFieldReference;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTInitializerList;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamespaceDefinition;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTParameterDeclaration;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName;
@ -101,12 +102,14 @@ public class LookupData {
public boolean firstArgIsImpliedMethodArg = false;
public boolean ignoreMembers = false;
private ICPPASTParameterDeclaration[] functionParameters;
private IASTInitializerClause[] functionArgs;
private IType[] functionArgTypes;
private BitSet functionArgLValues;
public ICPPClassType skippedScope;
public Object foundItems = null;
private Object[] functionArgs;
private IType[] functionArgTypes;
public ProblemBinding problem;
private BitSet functionArgLValues;
public LookupData(IASTName n) {
astName = n;
@ -529,27 +532,27 @@ public class LookupData {
}
public IType[] getFunctionArgumentTypes() {
if (functionArgTypes == null && functionArgs != null) {
if (functionArgs instanceof ICPPASTParameterDeclaration[]) {
ICPPASTParameterDeclaration[] pdecls= (ICPPASTParameterDeclaration[]) functionArgs;
functionArgTypes= new IType[pdecls.length];
for (int i = 0; i < pdecls.length; i++) {
functionArgTypes[i] = SemanticUtil.getSimplifiedType(CPPVisitor.createParameterType(
pdecls[i], true));
}
} else if (functionArgs instanceof IASTInitializerClause[]) {
IASTInitializerClause[] exprs= (IASTInitializerClause[]) functionArgs;
if (functionArgTypes == null) {
if (functionArgs != null) {
IASTInitializerClause[] exprs= functionArgs;
functionArgTypes= new IType[exprs.length];
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);
} else {
// mstodo handle braced init list
} else if (e instanceof ICPPASTInitializerList) {
functionArgTypes[i]= new InitializerListType((ICPPASTInitializerList) e);
}
}
}
} else if (functionParameters != null) {
ICPPASTParameterDeclaration[] pdecls= functionParameters;
functionArgTypes= new IType[pdecls.length];
for (int i = 0; i < pdecls.length; i++) {
functionArgTypes[i] = SemanticUtil.getSimplifiedType(CPPVisitor.createParameterType(
pdecls[i], true));
}
}
}
return functionArgTypes;
}
@ -564,7 +567,7 @@ public class LookupData {
if (arg instanceof IASTExpression) {
functionArgLValues.set(i, ((IASTExpression) arg).isLValue());
} else {
// mstodo handle braced init list
functionArgLValues.set(i, false);
}
}
} else {
@ -580,32 +583,24 @@ public class LookupData {
return functionArgLValues;
}
public void setFunctionArgumentTypes(IType[] paramTypes) {
functionArgTypes= paramTypes;
}
public void setFunctionParameters(ICPPASTParameterDeclaration[] parameters) {
functionArgs= parameters;
functionParameters= parameters;
}
public IASTInitializerClause[] getFunctionArguments() {
if (functionArgs instanceof IASTInitializerClause[])
return (IASTInitializerClause[]) functionArgs;
return null;
return functionArgs;
}
public int getFunctionArgumentCount() {
if (functionArgs != null)
return functionArgs.length;
if (functionArgTypes != null)
return functionArgTypes.length;
if (functionParameters != null)
return functionParameters.length;
return 0;
}
public boolean hasArgumentTypes() {
return functionArgTypes != null || functionArgs != null;
public boolean hasFunctionArguments() {
return functionArgs != null || functionParameters != null;
}
public IBinding[] getFoundBindings() {