1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-08-04 14:55:41 +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); assertEquals(defNames.length, j);
} }
@Override protected static void assertSameType(IType first, IType second){
protected void assertSameType(IType first, IType second){
assertNotNull(first); assertNotNull(first);
assertNotNull(second); assertNotNull(second);
assertTrue("Expected types to be the same, but first was: '" + first.toString() + "' and second was: '" + second + "'", first.isSameType(second)); assertTrue("Expected types to be the same, but first was: '" + first.toString() + "' and second was: '" + second + "'", first.isSameType(second));

View file

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

View file

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

View file

@ -42,13 +42,19 @@ public class EvalFunctionSet extends CPPDependentEvaluation {
private final CPPFunctionSet fFunctionSet; private final CPPFunctionSet fFunctionSet;
private final boolean fAddressOf; private final boolean fAddressOf;
public EvalFunctionSet(CPPFunctionSet set, boolean addressOf, IASTNode pointOfDefinition) { // Where an EvalFunctionSet is created for an expression of the form 'obj.member_function',
this(set, addressOf, findEnclosingTemplate(pointOfDefinition)); // 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, 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); super(templateDefinition);
fFunctionSet= set; fFunctionSet= set;
fAddressOf= addressOf; fAddressOf= addressOf;
fImpliedObjectType= impliedObjectType;
} }
public CPPFunctionSet getFunctionSet() { public CPPFunctionSet getFunctionSet() {
@ -59,6 +65,10 @@ public class EvalFunctionSet extends CPPDependentEvaluation {
return fAddressOf; return fAddressOf;
} }
public IType getImpliedObjectType() {
return fImpliedObjectType;
}
@Override @Override
public boolean isInitializerList() { public boolean isInitializerList() {
return false; return false;
@ -126,6 +136,7 @@ public class EvalFunctionSet extends CPPDependentEvaluation {
buffer.marshalTemplateArgument(arg); buffer.marshalTemplateArgument(arg);
} }
} }
buffer.marshalType(fImpliedObjectType);
marshalTemplateDefinition(buffer); marshalTemplateDefinition(buffer);
} }
@ -144,8 +155,9 @@ public class EvalFunctionSet extends CPPDependentEvaluation {
args[i]= buffer.unmarshalTemplateArgument(); args[i]= buffer.unmarshalTemplateArgument();
} }
} }
IType impliedObjectType= buffer.unmarshalType();
IBinding templateDefinition= buffer.unmarshalBinding(); 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 @Override
@ -177,9 +189,11 @@ public class EvalFunctionSet extends CPPDependentEvaluation {
originalFunctions[i], point); 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) if (Arrays.equals(arguments, originalArguments) && functions == originalFunctions)
return this; return this;
return new EvalFunctionSet(new CPPFunctionSet(functions, arguments, null), fAddressOf, getTemplateDefinition()); return new EvalFunctionSet(new CPPFunctionSet(functions, arguments, null), fAddressOf, fImpliedObjectType, getTemplateDefinition());
} }
@Override @Override
@ -201,6 +215,8 @@ public class EvalFunctionSet extends CPPDependentEvaluation {
LookupData data = new LookupData(functions[0].getNameCharArray(), LookupData data = new LookupData(functions[0].getNameCharArray(),
fFunctionSet.getTemplateArguments(), point); fFunctionSet.getTemplateArguments(), point);
data.setFunctionArguments(false, args); data.setFunctionArguments(false, args);
if (fImpliedObjectType != null)
data.setImpliedObjectType(fImpliedObjectType);
try { try {
IBinding binding = CPPSemantics.resolveFunction(data, functions, true); IBinding binding = CPPSemantics.resolveFunction(data, functions, true);
if (binding instanceof ICPPFunction && !(binding instanceof ICPPUnknownBinding)) 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.LVALUE;
import static org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory.PRVALUE; 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.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 static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.getNestedType;
import org.eclipse.cdt.core.dom.ast.DOMException; 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) if (binding instanceof IProblemBinding || binding instanceof IType || binding instanceof ICPPConstructor)
return EvalFixed.INCOMPLETE; return EvalFixed.INCOMPLETE;
if (binding instanceof CPPFunctionSet) { 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) { if (binding instanceof ICPPUnknownBinding) {
ICPPTemplateArgument[] templateArgs = null; ICPPTemplateArgument[] templateArgs = null;
@ -207,7 +209,7 @@ public class EvalID extends CPPDependentEvaluation {
CPPDeferredFunction deferredFunction = (CPPDeferredFunction) binding; CPPDeferredFunction deferredFunction = (CPPDeferredFunction) binding;
if (deferredFunction.getCandidates() != null) { if (deferredFunction.getCandidates() != null) {
CPPFunctionSet functionSet = new CPPFunctionSet(deferredFunction.getCandidates(), templateArgs, 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; return this;
if (nameOwner instanceof ICPPClassType) { if (nameOwner instanceof ICPPClassType) {
ICPPEvaluation eval = resolveName((ICPPClassType) nameOwner, templateArgs, point); ICPPEvaluation eval = resolveName((ICPPClassType) nameOwner, templateArgs, null, point);
if (eval != null) if (eval != null)
return eval; return eval;
} }
if (fieldOwner != null && !fieldOwner.isTypeDependent()) { if (fieldOwner != null && !fieldOwner.isTypeDependent()) {
IType fieldOwnerType = fieldOwner.getTypeOrFunctionSet(point); IType fieldOwnerType = fieldOwner.getTypeOrFunctionSet(point);
if (fieldOwnerType instanceof ICPPClassType) { IType fieldOwnerClassType = SemanticUtil.getNestedType(fieldOwnerType, TDEF | REF | CVTYPE);
ICPPEvaluation eval = resolveName((ICPPClassType) fieldOwnerType, templateArgs, point); if (fieldOwnerClassType instanceof ICPPClassType) {
ICPPEvaluation eval = resolveName((ICPPClassType) fieldOwnerClassType, templateArgs, fieldOwnerType, point);
if (eval != null) if (eval != null)
return eval; return eval;
} }
@ -349,7 +352,7 @@ public class EvalID extends CPPDependentEvaluation {
} }
private ICPPEvaluation resolveName(ICPPClassType nameOwner, ICPPTemplateArgument[] templateArgs, private ICPPEvaluation resolveName(ICPPClassType nameOwner, ICPPTemplateArgument[] templateArgs,
IASTNode point) { IType impliedObjectType, IASTNode point) {
LookupData data = new LookupData(fName, templateArgs, point); LookupData data = new LookupData(fName, templateArgs, point);
data.qualified = fQualified; data.qualified = fQualified;
try { try {
@ -360,7 +363,8 @@ public class EvalID extends CPPDependentEvaluation {
if (bindings.length > 1 && bindings[0] instanceof ICPPFunction) { if (bindings.length > 1 && bindings[0] instanceof ICPPFunction) {
ICPPFunction[] functions = new ICPPFunction[bindings.length]; ICPPFunction[] functions = new ICPPFunction[bindings.length];
System.arraycopy(bindings, 0, functions, 0, 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; IBinding binding = bindings.length == 1 ? bindings[0] : null;
if (binding instanceof IEnumerator) { if (binding instanceof IEnumerator) {
@ -368,7 +372,7 @@ public class EvalID extends CPPDependentEvaluation {
} else if (binding instanceof ICPPMember) { } else if (binding instanceof ICPPMember) {
return new EvalMemberAccess(nameOwner, ValueCategory.PRVALUE, binding, false, getTemplateDefinition()); return new EvalMemberAccess(nameOwner, ValueCategory.PRVALUE, binding, false, getTemplateDefinition());
} else if (binding instanceof CPPFunctionSet) { } else if (binding instanceof CPPFunctionSet) {
return new EvalFunctionSet((CPPFunctionSet) binding, fAddressOf, getTemplateDefinition()); return new EvalFunctionSet((CPPFunctionSet) binding, fAddressOf, impliedObjectType, getTemplateDefinition());
} }
return null; return null;
} }

View file

@ -359,6 +359,15 @@ public class LookupData extends ScopeLookupData {
return fImpliedObjectType; 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() { private IType determineImpliedObjectType() {
IASTName tn = getLookupName(); IASTName tn = getLookupName();
if (tn == null) if (tn == null)

View file

@ -332,11 +332,13 @@ public class CPPCompositesFactory extends AbstractCompositeFactory {
final CPPFunctionSet fset = e.getFunctionSet(); final CPPFunctionSet fset = e.getFunctionSet();
ICPPFunction[] a = fset.getBindings(); ICPPFunction[] a = fset.getBindings();
ICPPTemplateArgument[] b = fset.getTemplateArguments(); ICPPTemplateArgument[] b = fset.getTemplateArguments();
IType c = e.getImpliedObjectType();
ICPPFunction[] a2 = getCompositeFunctionArray(a); ICPPFunction[] a2 = getCompositeFunctionArray(a);
ICPPTemplateArgument[] b2 = TemplateInstanceUtil.convert(this, b); ICPPTemplateArgument[] b2 = TemplateInstanceUtil.convert(this, b);
if (a != a2 || b != b2 || templateDefinition != templateDefinition2) IType c2 = getCompositeType(c);
e= new EvalFunctionSet(new CPPFunctionSet(a2, b2, null), e.isAddressOf(), templateDefinition2); if (a != a2 || b != b2 || c != c2 || templateDefinition != templateDefinition2)
e= new EvalFunctionSet(new CPPFunctionSet(a2, b2, null), e.isAddressOf(), c2, templateDefinition2);
return e; return e;
} }
if (eval instanceof EvalID) { 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 * 140.1 - Mechanism for tagging nodes with extended data, bug 400020
* 141.0 - Storing enclosing template bindings for evaluations, bug 399829. * 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. * 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 MIN_SUPPORTED_VERSION= version(143, 0);
private static final int MAX_SUPPORTED_VERSION= version(142, Short.MAX_VALUE); private static final int MAX_SUPPORTED_VERSION= version(143, Short.MAX_VALUE);
private static final int DEFAULT_VERSION = version(142, 0); private static final int DEFAULT_VERSION = version(143, 0);
private static int version(int major, int minor) { private static int version(int major, int minor) {
return (major << 16) + minor; return (major << 16) + minor;