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:
parent
bafe78b859
commit
7f2273c8b8
8 changed files with 81 additions and 31 deletions
|
@ -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));
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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: '" +
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Reference in a new issue