1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-24 01:15:29 +02:00

Bug 402409 - Dependent expressions and auto type resolution

Change-Id: Ib4ed63ade9349c5be74305825884acac103e334b
Reviewed-on: https://git.eclipse.org/r/10957
Reviewed-by: Sergey Prigogin <eclipse.sprigogin@gmail.com>
IP-Clean: Sergey Prigogin <eclipse.sprigogin@gmail.com>
Tested-by: Sergey Prigogin <eclipse.sprigogin@gmail.com>
This commit is contained in:
Nathan Ridge 2013-03-08 03:21:43 -05:00 committed by Sergey Prigogin
parent bafe78b859
commit 7f2273c8b8
8 changed files with 81 additions and 31 deletions

View file

@ -263,8 +263,7 @@ public class AST2CPPTests extends AST2TestBase {
assertEquals(defNames.length, j);
}
@Override
protected void assertSameType(IType first, IType second){
protected static void assertSameType(IType first, IType second){
assertNotNull(first);
assertNotNull(second);
assertTrue("Expected types to be the same, but first was: '" + first.toString() + "' and second was: '" + second + "'", first.isSameType(second));

View file

@ -5880,19 +5880,38 @@ public class AST2TemplateTests extends AST2TestBase {
// int* begin();
// };
//
// template <class Container>
// auto begin1(Container cont) -> decltype(cont.begin());
//
// template <class Container>
// auto begin2(Container& cont) -> decltype(cont.begin());
//
// vector v;
// auto x1 = begin1(v);
// auto x2 = begin2(v);
public void testResolvingAutoTypeWithDependentExpression_402409a() throws Exception {
BindingAssertionHelper helper = new BindingAssertionHelper(getAboveComment(), true);
ICPPVariable x1 = helper.assertNonProblem("x1", ICPPVariable.class);
ICPPVariable x2 = helper.assertNonProblem("x2", ICPPVariable.class);
IType pointerToInt = new CPPPointerType(new CPPBasicType(Kind.eInt, 0));
assertSameType(pointerToInt, x1.getType());
assertSameType(pointerToInt, x2.getType());
}
// struct vector {
// int* begin();
// const int* begin() const;
// };
//
// template<class Container>
// auto begin(Container cont) -> decltype(cont.begin());
//
// vector v;
// auto x = begin(v);
public void testResolvingAutoTypeWithDependentExpression_402409() throws Exception {
BindingAssertionHelper helper = new BindingAssertionHelper(getAboveComment(), true);
ICPPVariable x = helper.assertNonProblem("x", ICPPVariable.class);
IType xType = x.getType();
assertInstance(xType, CPPPointerType.class);
IType xTypeInner = ((CPPPointerType) xType).getType();
assertInstance(xTypeInner, ICPPBasicType.class);
assertEquals(Kind.eInt, ((ICPPBasicType) xTypeInner).getKind());
// int main() {
// vector v;
// begin(v);
// }
public void testResolvingAutoTypeWithDependentExpression_402409b() throws Exception {
parseAndCheckBindings();
}
// void foo(int, int);

View file

@ -377,7 +377,7 @@ public class AST2TestBase extends BaseTestCase {
assertEquals(num, count);
}
protected void assertSameType(IType expected, IType actual) {
protected static void assertSameType(IType expected, IType actual) {
assertNotNull(expected);
assertNotNull(actual);
assertTrue("Expected same types, but the types were: '" +

View file

@ -41,14 +41,20 @@ import org.eclipse.core.runtime.CoreException;
public class EvalFunctionSet extends CPPDependentEvaluation {
private final CPPFunctionSet fFunctionSet;
private final boolean fAddressOf;
// Where an EvalFunctionSet is created for an expression of the form 'obj.member_function',
// the type of 'obj' (needed for correct overload resolution of 'member_function' later).
// Otherwise null.
private final IType fImpliedObjectType;
public EvalFunctionSet(CPPFunctionSet set, boolean addressOf, IASTNode pointOfDefinition) {
this(set, addressOf, findEnclosingTemplate(pointOfDefinition));
public EvalFunctionSet(CPPFunctionSet set, boolean addressOf, IType impliedObjectType, IASTNode pointOfDefinition) {
this(set, addressOf, impliedObjectType, findEnclosingTemplate(pointOfDefinition));
}
public EvalFunctionSet(CPPFunctionSet set, boolean addressOf, IBinding templateDefinition) {
public EvalFunctionSet(CPPFunctionSet set, boolean addressOf, IType impliedObjectType, IBinding templateDefinition) {
super(templateDefinition);
fFunctionSet= set;
fAddressOf= addressOf;
fImpliedObjectType= impliedObjectType;
}
public CPPFunctionSet getFunctionSet() {
@ -58,6 +64,10 @@ public class EvalFunctionSet extends CPPDependentEvaluation {
public boolean isAddressOf() {
return fAddressOf;
}
public IType getImpliedObjectType() {
return fImpliedObjectType;
}
@Override
public boolean isInitializerList() {
@ -126,6 +136,7 @@ public class EvalFunctionSet extends CPPDependentEvaluation {
buffer.marshalTemplateArgument(arg);
}
}
buffer.marshalType(fImpliedObjectType);
marshalTemplateDefinition(buffer);
}
@ -144,8 +155,9 @@ public class EvalFunctionSet extends CPPDependentEvaluation {
args[i]= buffer.unmarshalTemplateArgument();
}
}
IType impliedObjectType= buffer.unmarshalType();
IBinding templateDefinition= buffer.unmarshalBinding();
return new EvalFunctionSet(new CPPFunctionSet(bindings, args, null), addressOf, templateDefinition);
return new EvalFunctionSet(new CPPFunctionSet(bindings, args, null), addressOf, impliedObjectType, templateDefinition);
}
@Override
@ -177,9 +189,11 @@ public class EvalFunctionSet extends CPPDependentEvaluation {
originalFunctions[i], point);
}
}
// No need to instantiate the implied object type. An EvalFunctioNSet should only be created
// with an implied object type when that type is not dependent.
if (Arrays.equals(arguments, originalArguments) && functions == originalFunctions)
return this;
return new EvalFunctionSet(new CPPFunctionSet(functions, arguments, null), fAddressOf, getTemplateDefinition());
return new EvalFunctionSet(new CPPFunctionSet(functions, arguments, null), fAddressOf, fImpliedObjectType, getTemplateDefinition());
}
@Override
@ -201,6 +215,8 @@ public class EvalFunctionSet extends CPPDependentEvaluation {
LookupData data = new LookupData(functions[0].getNameCharArray(),
fFunctionSet.getTemplateArguments(), point);
data.setFunctionArguments(false, args);
if (fImpliedObjectType != null)
data.setImpliedObjectType(fImpliedObjectType);
try {
IBinding binding = CPPSemantics.resolveFunction(data, functions, true);
if (binding instanceof ICPPFunction && !(binding instanceof ICPPUnknownBinding))

View file

@ -15,6 +15,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.SemanticUtil.TDEF;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.REF;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.CVTYPE;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.getNestedType;
import org.eclipse.cdt.core.dom.ast.DOMException;
@ -190,7 +192,7 @@ public class EvalID extends CPPDependentEvaluation {
if (binding instanceof IProblemBinding || binding instanceof IType || binding instanceof ICPPConstructor)
return EvalFixed.INCOMPLETE;
if (binding instanceof CPPFunctionSet) {
return new EvalFunctionSet((CPPFunctionSet) binding, isAddressOf(expr), expr);
return new EvalFunctionSet((CPPFunctionSet) binding, isAddressOf(expr), null, expr);
}
if (binding instanceof ICPPUnknownBinding) {
ICPPTemplateArgument[] templateArgs = null;
@ -207,7 +209,7 @@ public class EvalID extends CPPDependentEvaluation {
CPPDeferredFunction deferredFunction = (CPPDeferredFunction) binding;
if (deferredFunction.getCandidates() != null) {
CPPFunctionSet functionSet = new CPPFunctionSet(deferredFunction.getCandidates(), templateArgs, null);
return new EvalFunctionSet(functionSet, isAddressOf(expr), expr);
return new EvalFunctionSet(functionSet, isAddressOf(expr), null, expr);
}
}
@ -320,15 +322,16 @@ public class EvalID extends CPPDependentEvaluation {
return this;
if (nameOwner instanceof ICPPClassType) {
ICPPEvaluation eval = resolveName((ICPPClassType) nameOwner, templateArgs, point);
ICPPEvaluation eval = resolveName((ICPPClassType) nameOwner, templateArgs, null, point);
if (eval != null)
return eval;
}
if (fieldOwner != null && !fieldOwner.isTypeDependent()) {
IType fieldOwnerType = fieldOwner.getTypeOrFunctionSet(point);
if (fieldOwnerType instanceof ICPPClassType) {
ICPPEvaluation eval = resolveName((ICPPClassType) fieldOwnerType, templateArgs, point);
IType fieldOwnerClassType = SemanticUtil.getNestedType(fieldOwnerType, TDEF | REF | CVTYPE);
if (fieldOwnerClassType instanceof ICPPClassType) {
ICPPEvaluation eval = resolveName((ICPPClassType) fieldOwnerClassType, templateArgs, fieldOwnerType, point);
if (eval != null)
return eval;
}
@ -349,7 +352,7 @@ public class EvalID extends CPPDependentEvaluation {
}
private ICPPEvaluation resolveName(ICPPClassType nameOwner, ICPPTemplateArgument[] templateArgs,
IASTNode point) {
IType impliedObjectType, IASTNode point) {
LookupData data = new LookupData(fName, templateArgs, point);
data.qualified = fQualified;
try {
@ -360,7 +363,8 @@ public class EvalID extends CPPDependentEvaluation {
if (bindings.length > 1 && bindings[0] instanceof ICPPFunction) {
ICPPFunction[] functions = new ICPPFunction[bindings.length];
System.arraycopy(bindings, 0, functions, 0, bindings.length);
return new EvalFunctionSet(new CPPFunctionSet(functions, templateArgs, null), fAddressOf, getTemplateDefinition());
return new EvalFunctionSet(new CPPFunctionSet(functions, templateArgs, null), fAddressOf,
impliedObjectType, getTemplateDefinition());
}
IBinding binding = bindings.length == 1 ? bindings[0] : null;
if (binding instanceof IEnumerator) {
@ -368,7 +372,7 @@ public class EvalID extends CPPDependentEvaluation {
} else if (binding instanceof ICPPMember) {
return new EvalMemberAccess(nameOwner, ValueCategory.PRVALUE, binding, false, getTemplateDefinition());
} else if (binding instanceof CPPFunctionSet) {
return new EvalFunctionSet((CPPFunctionSet) binding, fAddressOf, getTemplateDefinition());
return new EvalFunctionSet((CPPFunctionSet) binding, fAddressOf, impliedObjectType, getTemplateDefinition());
}
return null;
}

View file

@ -358,6 +358,15 @@ public class LookupData extends ScopeLookupData {
}
return fImpliedObjectType;
}
/**
* Explicitly set the implied object type.
* This is for use in cases where implied object type cannot
* be determined automatically because there is no lookup name.
*/
public void setImpliedObjectType(IType impliedObjectType) {
fImpliedObjectType = impliedObjectType;
}
private IType determineImpliedObjectType() {
IASTName tn = getLookupName();

View file

@ -332,11 +332,13 @@ public class CPPCompositesFactory extends AbstractCompositeFactory {
final CPPFunctionSet fset = e.getFunctionSet();
ICPPFunction[] a = fset.getBindings();
ICPPTemplateArgument[] b = fset.getTemplateArguments();
IType c = e.getImpliedObjectType();
ICPPFunction[] a2 = getCompositeFunctionArray(a);
ICPPTemplateArgument[] b2 = TemplateInstanceUtil.convert(this, b);
if (a != a2 || b != b2 || templateDefinition != templateDefinition2)
e= new EvalFunctionSet(new CPPFunctionSet(a2, b2, null), e.isAddressOf(), templateDefinition2);
IType c2 = getCompositeType(c);
if (a != a2 || b != b2 || c != c2 || templateDefinition != templateDefinition2)
e= new EvalFunctionSet(new CPPFunctionSet(a2, b2, null), e.isAddressOf(), c2, templateDefinition2);
return e;
}
if (eval instanceof EvalID) {

View file

@ -234,10 +234,11 @@ public class PDOM extends PlatformObject implements IPDOM {
* 140.1 - Mechanism for tagging nodes with extended data, bug 400020
* 141.0 - Storing enclosing template bindings for evaluations, bug 399829.
* 142.0 - Changed marshalling of evaluations to allow more than 15 evaluation kinds, bug 401479.
* 143.0 - Store implied object type in EvalFunctionSet, bug 402409.
*/
private static final int MIN_SUPPORTED_VERSION= version(142, 0);
private static final int MAX_SUPPORTED_VERSION= version(142, Short.MAX_VALUE);
private static final int DEFAULT_VERSION = version(142, 0);
private static final int MIN_SUPPORTED_VERSION= version(143, 0);
private static final int MAX_SUPPORTED_VERSION= version(143, Short.MAX_VALUE);
private static final int DEFAULT_VERSION = version(143, 0);
private static int version(int major, int minor) {
return (major << 16) + minor;