1
0
Fork 0
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:
Markus Schorn 2008-12-16 08:43:06 +00:00
parent b63ecc5470
commit fbe8ca1282
2 changed files with 53 additions and 50 deletions

View file

@ -3426,7 +3426,7 @@ public class AST2TemplateTests extends AST2BaseTest {
// f(b); g(b); h(b); m(b); // f(b); g(b); h(b); m(b);
// } // }
// }; // };
public void testUnknownReferences_Bug257186() throws Exception { public void testUnknownReferences_Bug257194() throws Exception {
final String code = getAboveComment(); final String code = getAboveComment();
parseAndCheckBindings(code, ParserLanguage.CPP); parseAndCheckBindings(code, ParserLanguage.CPP);
BindingAssertionHelper bh= new BindingAssertionHelper(code, true); BindingAssertionHelper bh= new BindingAssertionHelper(code, true);
@ -3446,9 +3446,10 @@ public class AST2TemplateTests extends AST2BaseTest {
// T::b.f(); // T::b.f();
// T::b.f().d; // T::b.f().d;
// T::f1(); // T::f1();
// T.x; T.y();
// } // }
// }; // };
public void testTypeOfUnknownReferences_Bug257186a() throws Exception { public void testTypeOfUnknownReferences_Bug257194a() throws Exception {
final String code = getAboveComment(); final String code = getAboveComment();
parseAndCheckBindings(code, ParserLanguage.CPP); parseAndCheckBindings(code, ParserLanguage.CPP);
BindingAssertionHelper bh= new BindingAssertionHelper(code, true); 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("f().", 1, ICPPUnknownBinding.class, IFunction.class);
bh.assertNonProblem("d;", 1, ICPPUnknownBinding.class); bh.assertNonProblem("d;", 1, ICPPUnknownBinding.class);
bh.assertNonProblem("f1();", 2, ICPPUnknownBinding.class, IFunction.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 { // template<typename T> struct A {
@ -3467,9 +3470,10 @@ public class AST2TemplateTests extends AST2BaseTest {
// T::b->f(); // T::b->f();
// T::b->f()->d; // T::b->f()->d;
// T::f1(); // T::f1();
// T->x; T->y();
// } // }
// }; // };
public void testTypeOfUnknownReferences_Bug257186b() throws Exception { public void testTypeOfUnknownReferences_Bug257194b() throws Exception {
final String code = getAboveComment(); final String code = getAboveComment();
parseAndCheckBindings(code, ParserLanguage.CPP); parseAndCheckBindings(code, ParserLanguage.CPP);
BindingAssertionHelper bh= new BindingAssertionHelper(code, true); 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("f()->", 1, ICPPUnknownBinding.class, IFunction.class);
bh.assertNonProblem("d;", 1, ICPPUnknownBinding.class); bh.assertNonProblem("d;", 1, ICPPUnknownBinding.class);
bh.assertNonProblem("f1();", 2, ICPPUnknownBinding.class, IFunction.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 { // template<typename T> class XT {

View file

@ -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.CPPReferenceType;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPScope; 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.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.CPPUnknownFunction;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPUsingDeclaration; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPUsingDeclaration;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPUsingDirective; 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 { public static IType getChainedMemberAccessOperatorReturnType(ICPPASTFieldReference fieldReference) throws DOMException {
IASTExpression owner = fieldReference.getFieldOwner(); 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)) { // for unknown types we cannot determine the overloaded -> operator
IType type= getUltimateTypeUptoPointers(result); if (uTemp instanceof ICPPUnknownType)
boolean needCheckClassMemberAccessOperator= true; return CPPUnknownClass.createUnnamedInstance();
if (type instanceof IPointerType) {
type= getUltimateTypeUptoPointers(((IPointerType) type).getType()); if (!(uTemp instanceof ICPPClassType))
if (type instanceof ICPPClassType) { break;
needCheckClassMemberAccessOperator= false;
} /*
* 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) { IASTName arw= new CPPASTName(OverloadableOperator.ARROW.toCharArray());
IType temp= result; IASTFieldReference innerFR= new CPPASTFieldReference(arw, new CPPASTIdExpression(x));
result= null; innerFR.setParent(fieldReference); // connect to the AST
// bug 205964: as long as the type is a class type, recurse. ICPPFunction op = CPPSemantics.findOperator(innerFR, (ICPPClassType) uTemp);
// Be defensive and allow a max of 10 levels. if (op == null)
for (int j = 0; j < 10; j++) { break;
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.
*/
CPPASTName x= new CPPASTName(); type= op.getType().getReturnType();
boolean isConst= false, isVolatile= false; foundOperator= true;
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;
}
}
} }
return result; return foundOperator ? type : null;
} }
private static ICPPVariable createVariable(IASTName name, final IType type, final boolean isConst, final boolean isVolatile) { private static ICPPVariable createVariable(IASTName name, final IType type, final boolean isConst, final boolean isVolatile) {