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:
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);
|
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));
|
||||||
|
|
|
@ -5880,19 +5880,38 @@ public class AST2TemplateTests extends AST2TestBase {
|
||||||
// int* begin();
|
// 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>
|
// template<class Container>
|
||||||
// auto begin(Container cont) -> decltype(cont.begin());
|
// auto begin(Container cont) -> decltype(cont.begin());
|
||||||
//
|
//
|
||||||
// vector v;
|
// int main() {
|
||||||
// auto x = begin(v);
|
// vector v;
|
||||||
public void testResolvingAutoTypeWithDependentExpression_402409() throws Exception {
|
// begin(v);
|
||||||
BindingAssertionHelper helper = new BindingAssertionHelper(getAboveComment(), true);
|
// }
|
||||||
ICPPVariable x = helper.assertNonProblem("x", ICPPVariable.class);
|
public void testResolvingAutoTypeWithDependentExpression_402409b() throws Exception {
|
||||||
IType xType = x.getType();
|
parseAndCheckBindings();
|
||||||
assertInstance(xType, CPPPointerType.class);
|
|
||||||
IType xTypeInner = ((CPPPointerType) xType).getType();
|
|
||||||
assertInstance(xTypeInner, ICPPBasicType.class);
|
|
||||||
assertEquals(Kind.eInt, ((ICPPBasicType) xTypeInner).getKind());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// void foo(int, int);
|
// void foo(int, int);
|
||||||
|
|
|
@ -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: '" +
|
||||||
|
|
|
@ -41,14 +41,20 @@ import org.eclipse.core.runtime.CoreException;
|
||||||
public class EvalFunctionSet extends CPPDependentEvaluation {
|
public class EvalFunctionSet extends CPPDependentEvaluation {
|
||||||
private final CPPFunctionSet fFunctionSet;
|
private final CPPFunctionSet fFunctionSet;
|
||||||
private final boolean fAddressOf;
|
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) {
|
public EvalFunctionSet(CPPFunctionSet set, boolean addressOf, IType impliedObjectType, IASTNode pointOfDefinition) {
|
||||||
this(set, addressOf, findEnclosingTemplate(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() {
|
||||||
|
@ -58,6 +64,10 @@ public class EvalFunctionSet extends CPPDependentEvaluation {
|
||||||
public boolean isAddressOf() {
|
public boolean isAddressOf() {
|
||||||
return fAddressOf;
|
return fAddressOf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IType getImpliedObjectType() {
|
||||||
|
return fImpliedObjectType;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isInitializerList() {
|
public boolean isInitializerList() {
|
||||||
|
@ -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))
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -358,6 +358,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();
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Add table
Reference in a new issue