mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-29 19:45:01 +02:00
operator-> for template parameters, bug 257194.
This commit is contained in:
parent
b63ecc5470
commit
fbe8ca1282
2 changed files with 53 additions and 50 deletions
|
@ -3426,7 +3426,7 @@ public class AST2TemplateTests extends AST2BaseTest {
|
|||
// f(b); g(b); h(b); m(b);
|
||||
// }
|
||||
// };
|
||||
public void testUnknownReferences_Bug257186() throws Exception {
|
||||
public void testUnknownReferences_Bug257194() throws Exception {
|
||||
final String code = getAboveComment();
|
||||
parseAndCheckBindings(code, ParserLanguage.CPP);
|
||||
BindingAssertionHelper bh= new BindingAssertionHelper(code, true);
|
||||
|
@ -3446,9 +3446,10 @@ public class AST2TemplateTests extends AST2BaseTest {
|
|||
// T::b.f();
|
||||
// T::b.f().d;
|
||||
// T::f1();
|
||||
// T.x; T.y();
|
||||
// }
|
||||
// };
|
||||
public void testTypeOfUnknownReferences_Bug257186a() throws Exception {
|
||||
public void testTypeOfUnknownReferences_Bug257194a() throws Exception {
|
||||
final String code = getAboveComment();
|
||||
parseAndCheckBindings(code, ParserLanguage.CPP);
|
||||
BindingAssertionHelper bh= new BindingAssertionHelper(code, true);
|
||||
|
@ -3459,6 +3460,8 @@ public class AST2TemplateTests extends AST2BaseTest {
|
|||
bh.assertNonProblem("f().", 1, ICPPUnknownBinding.class, IFunction.class);
|
||||
bh.assertNonProblem("d;", 1, ICPPUnknownBinding.class);
|
||||
bh.assertNonProblem("f1();", 2, ICPPUnknownBinding.class, IFunction.class);
|
||||
bh.assertNonProblem("x;", 1, ICPPUnknownBinding.class);
|
||||
bh.assertNonProblem("y();", 1, ICPPUnknownBinding.class, IFunction.class);
|
||||
}
|
||||
|
||||
// template<typename T> struct A {
|
||||
|
@ -3467,9 +3470,10 @@ public class AST2TemplateTests extends AST2BaseTest {
|
|||
// T::b->f();
|
||||
// T::b->f()->d;
|
||||
// T::f1();
|
||||
// T->x; T->y();
|
||||
// }
|
||||
// };
|
||||
public void testTypeOfUnknownReferences_Bug257186b() throws Exception {
|
||||
public void testTypeOfUnknownReferences_Bug257194b() throws Exception {
|
||||
final String code = getAboveComment();
|
||||
parseAndCheckBindings(code, ParserLanguage.CPP);
|
||||
BindingAssertionHelper bh= new BindingAssertionHelper(code, true);
|
||||
|
@ -3480,6 +3484,8 @@ public class AST2TemplateTests extends AST2BaseTest {
|
|||
bh.assertNonProblem("f()->", 1, ICPPUnknownBinding.class, IFunction.class);
|
||||
bh.assertNonProblem("d;", 1, ICPPUnknownBinding.class);
|
||||
bh.assertNonProblem("f1();", 2, ICPPUnknownBinding.class, IFunction.class);
|
||||
bh.assertNonProblem("x;", 1, ICPPUnknownBinding.class);
|
||||
bh.assertNonProblem("y();", 1, ICPPUnknownBinding.class, IFunction.class);
|
||||
}
|
||||
|
||||
// template<typename T> class XT {
|
||||
|
|
|
@ -144,6 +144,7 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPQualifierType;
|
|||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPReferenceType;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPScope;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPUnknownBinding;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPUnknownClass;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPUnknownFunction;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPUsingDeclaration;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPUsingDirective;
|
||||
|
@ -2434,59 +2435,55 @@ public class CPPSemantics {
|
|||
*/
|
||||
public static IType getChainedMemberAccessOperatorReturnType(ICPPASTFieldReference fieldReference) throws DOMException {
|
||||
IASTExpression owner = fieldReference.getFieldOwner();
|
||||
IType result= CPPVisitor.getExpressionType(owner);
|
||||
IType type= CPPVisitor.getExpressionType(owner);
|
||||
|
||||
if (!fieldReference.isPointerDereference())
|
||||
return type;
|
||||
|
||||
// bug 205964: as long as the type is a class type, recurse.
|
||||
// Be defensive and allow a max of 10 levels.
|
||||
boolean foundOperator= false;
|
||||
for (int j = 0; j < 10; j++) {
|
||||
IType uTemp= getUltimateTypeUptoPointers(type);
|
||||
if (uTemp instanceof IPointerType)
|
||||
return type;
|
||||
|
||||
if (fieldReference.isPointerDereference() && !(result instanceof ICPPUnknownType)) {
|
||||
IType type= getUltimateTypeUptoPointers(result);
|
||||
boolean needCheckClassMemberAccessOperator= true;
|
||||
if (type instanceof IPointerType) {
|
||||
type= getUltimateTypeUptoPointers(((IPointerType) type).getType());
|
||||
if (type instanceof ICPPClassType) {
|
||||
needCheckClassMemberAccessOperator= false;
|
||||
}
|
||||
// for unknown types we cannot determine the overloaded -> operator
|
||||
if (uTemp instanceof ICPPUnknownType)
|
||||
return CPPUnknownClass.createUnnamedInstance();
|
||||
|
||||
if (!(uTemp instanceof ICPPClassType))
|
||||
break;
|
||||
|
||||
/*
|
||||
* 13.5.6-1: An expression x->m is interpreted as (x.operator->())->m for a
|
||||
* class object x of type T
|
||||
*
|
||||
* Construct an AST fragment for x.operator-> which the lookup routines can
|
||||
* examine for type information.
|
||||
*/
|
||||
|
||||
CPPASTName x= new CPPASTName();
|
||||
boolean isConst= false, isVolatile= false;
|
||||
if (type instanceof IQualifierType) {
|
||||
isConst= ((IQualifierType)type).isConst();
|
||||
isVolatile= ((IQualifierType)type).isVolatile();
|
||||
}
|
||||
x.setBinding(createVariable(x, uTemp, isConst, isVolatile));
|
||||
|
||||
if (needCheckClassMemberAccessOperator) {
|
||||
IType temp= result;
|
||||
result= null;
|
||||
IASTName arw= new CPPASTName(OverloadableOperator.ARROW.toCharArray());
|
||||
IASTFieldReference innerFR= new CPPASTFieldReference(arw, new CPPASTIdExpression(x));
|
||||
innerFR.setParent(fieldReference); // connect to the AST
|
||||
|
||||
// bug 205964: as long as the type is a class type, recurse.
|
||||
// Be defensive and allow a max of 10 levels.
|
||||
for (int j = 0; j < 10; j++) {
|
||||
IType uTemp= getUltimateTypeUptoPointers(temp);
|
||||
if (uTemp instanceof ICPPClassType) {
|
||||
/*
|
||||
* 13.5.6-1: An expression x->m is interpreted as (x.operator->())->m for a
|
||||
* class object x of type T
|
||||
*
|
||||
* Construct an AST fragment for x.operator-> which the lookup routines can
|
||||
* examine for type information.
|
||||
*/
|
||||
ICPPFunction op = CPPSemantics.findOperator(innerFR, (ICPPClassType) uTemp);
|
||||
if (op == null)
|
||||
break;
|
||||
|
||||
CPPASTName x= new CPPASTName();
|
||||
boolean isConst= false, isVolatile= false;
|
||||
if (temp instanceof IQualifierType) {
|
||||
isConst= ((IQualifierType)temp).isConst();
|
||||
isVolatile= ((IQualifierType)temp).isVolatile();
|
||||
}
|
||||
x.setBinding(createVariable(x, uTemp, isConst, isVolatile));
|
||||
|
||||
IASTName arw= new CPPASTName(OverloadableOperator.ARROW.toCharArray());
|
||||
IASTFieldReference innerFR= new CPPASTFieldReference(arw, new CPPASTIdExpression(x));
|
||||
innerFR.setParent(fieldReference); // connect to the AST
|
||||
|
||||
ICPPFunction op = CPPSemantics.findOperator(innerFR, (ICPPClassType) uTemp);
|
||||
if (op != null) {
|
||||
result= temp= op.getType().getReturnType();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
type= op.getType().getReturnType();
|
||||
foundOperator= true;
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
return foundOperator ? type : null;
|
||||
}
|
||||
|
||||
private static ICPPVariable createVariable(IASTName name, final IType type, final boolean isConst, final boolean isVolatile) {
|
||||
|
|
Loading…
Add table
Reference in a new issue