diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java index 7dd193a8f44..7c053699bba 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java @@ -4565,4 +4565,28 @@ public class AST2CPPTests extends AST2BaseTest { assertTrue( cs.length == 2 ); assertSame( cs[1], ctor ); } + + public void testBug91707() throws Exception { + StringBuffer buffer = new StringBuffer(); + buffer.append("class C { public: int foo; }; \n"); + buffer.append("class B { \n"); + buffer.append(" C* operator ->(); \n"); + buffer.append(" C& operator [] ( int ); \n"); + buffer.append("}; \n"); + buffer.append("void f(){ \n"); + buffer.append(" B b; \n"); + buffer.append(" b->foo; \n"); + buffer.append(" b[0].foo; \n"); + buffer.append("} \n"); + + IASTTranslationUnit tu = parse( buffer.toString(), ParserLanguage.CPP ); + CPPNameCollector col = new CPPNameCollector(); + tu.accept(col); + + ICPPField foo = (ICPPField) col.getName(1).resolveBinding(); + + assertSame( foo, col.getName(12).resolveBinding() ); + assertSame( foo, col.getName(14).resolveBinding() ); + } + } diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java index 1d47589ad40..414ffe90f10 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java @@ -1589,4 +1589,45 @@ public class AST2TemplateTests extends AST2BaseTest { ICPPMethod init = (ICPPMethod) col.getName(4).resolveBinding(); assertSame( init, col.getName(19).resolveBinding() ); } + + public void testBug91707() throws Exception { + StringBuffer buffer = new StringBuffer(); + buffer.append("template class iter { \n"); //$NON-NLS-1$ + buffer.append(" Tp operator -> () const; \n"); //$NON-NLS-1$ + buffer.append(" Tr operator [] (int) const; \n"); //$NON-NLS-1$ + buffer.append("}; \n"); //$NON-NLS-1$ + buffer.append("template class list { \n"); //$NON-NLS-1$ + buffer.append(" typedef iter< T*, T& > iterator; \n"); //$NON-NLS-1$ + buffer.append(" iterator begin(); \n"); //$NON-NLS-1$ + buffer.append(" iterator end(); \n"); //$NON-NLS-1$ + buffer.append("}; \n"); //$NON-NLS-1$ + buffer.append("class Bar { public: int foo; }; \n"); //$NON-NLS-1$ + buffer.append("void f() { \n"); //$NON-NLS-1$ + buffer.append(" list bar; \n"); //$NON-NLS-1$ + buffer.append(" for( list::iterator i = bar.begin(); i != bar.end(); ++i ){ \n"); //$NON-NLS-1$ + buffer.append(" i->foo; i[0].foo; \n"); //$NON-NLS-1$ + buffer.append(" } \n"); //$NON-NLS-1$ + buffer.append("} \n"); //$NON-NLS-1$ + + + IASTTranslationUnit tu = parse( buffer.toString(), ParserLanguage.CPP ); + CPPNameCollector col = new CPPNameCollector(); + tu.accept( col ); + + ICPPMethod begin = (ICPPMethod) col.getName(16).resolveBinding(); + ICPPMethod end = (ICPPMethod) col.getName(18).resolveBinding(); + + ICPPField foo = (ICPPField) col.getName(20).resolveBinding(); + + IBinding r = col.getName(33).resolveBinding(); + assertTrue( r instanceof ICPPSpecialization ); + assertSame( ((ICPPSpecialization)r).getSpecializedBinding(), begin ); + + r = col.getName(36).resolveBinding(); + assertTrue( r instanceof ICPPSpecialization ); + assertSame( ((ICPPSpecialization)r).getSpecializedBinding(), end ); + + assertSame( foo, col.getName(39).resolveBinding() ); + assertSame( foo, col.getName(41).resolveBinding() ); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassTemplatePartialSpecialization.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassTemplatePartialSpecialization.java index 41805b83697..06937a2c6bb 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassTemplatePartialSpecialization.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassTemplatePartialSpecialization.java @@ -76,7 +76,7 @@ public class CPPClassTemplatePartialSpecialization extends CPPClassTemplate impl IType arg = args[i]; //If the argument is a template parameter, we can't instantiate yet, defer for later - if( arg instanceof ICPPTemplateParameter ){ + if( CPPTemplates.typeContainsTemplateParameter( arg ) ){ return deferredInstance( args ); } try { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPSemantics.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPSemantics.java index f3c070215b7..3e70bde34ad 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPSemantics.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPSemantics.java @@ -15,6 +15,7 @@ package org.eclipse.cdt.internal.core.dom.parser.cpp; import org.eclipse.cdt.core.dom.ast.ASTNodeProperty; import org.eclipse.cdt.core.dom.ast.DOMException; +import org.eclipse.cdt.core.dom.ast.IASTArraySubscriptExpression; import org.eclipse.cdt.core.dom.ast.IASTBinaryExpression; import org.eclipse.cdt.core.dom.ast.IASTCastExpression; import org.eclipse.cdt.core.dom.ast.IASTCompositeTypeSpecifier; @@ -74,6 +75,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamedTypeSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamespaceAlias; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamespaceDefinition; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNewExpression; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTOperatorName; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateDeclaration; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateId; @@ -338,7 +340,9 @@ public class CPPSemantics { tempName = (IASTName) tempName.getParent(); ASTNodeProperty prop = tempName.getPropertyInParent(); - if( prop == IASTFieldReference.FIELD_NAME ){ + if( prop == IASTFieldReference.FIELD_NAME || + (prop == STRING_LOOKUP_PROPERTY && tempName.getParent() instanceof ICPPASTFieldReference) ) + { ICPPASTFieldReference fieldRef = (ICPPASTFieldReference) tempName.getParent(); implied = CPPVisitor.getExpressionType( fieldRef.getFieldOwner() ); if( fieldRef.isPointerDereference() && implied instanceof IPointerType ){ @@ -362,6 +366,9 @@ public class CPPSemantics { } } } + } else if( prop == STRING_LOOKUP_PROPERTY && tempName.getParent() instanceof IASTArraySubscriptExpression ){ + IASTExpression exp = ((IASTArraySubscriptExpression)tempName.getParent()).getArrayExpression(); + implied = CPPVisitor.getExpressionType( exp ); } } return implied; @@ -2916,6 +2923,42 @@ public class CPPSemantics { return -1; } + public static ICPPFunction findOperator( IASTExpression exp, ICPPClassType cls ){ + IScope scope = null; + try { + scope = cls.getCompositeScope(); + } catch (DOMException e1) { + return null; + } + CPPASTName astName = new CPPASTName(); + astName.setParent( exp ); + astName.setPropertyInParent( STRING_LOOKUP_PROPERTY ); + LookupData data = null; + + if( exp instanceof IASTArraySubscriptExpression ){ + astName.setName( ICPPASTOperatorName.OPERATOR_BRACKET ); + data = new LookupData( astName ); + data.forceQualified = true; + data.functionParameters = new IASTExpression [] { ((IASTArraySubscriptExpression)exp).getSubscriptExpression() }; + } else if( exp instanceof IASTFieldReference ){ + astName.setName( ICPPASTOperatorName.OPERATOR_ARROW ); + data = new LookupData( astName ); + data.forceQualified = true; + data.functionParameters = IASTExpression.EMPTY_EXPRESSION_ARRAY; + } else { + return null; + } + + try { + lookup( data, scope ); + IBinding binding = resolveAmbiguities( data, astName ); + if( binding instanceof ICPPFunction ) + return (ICPPFunction) binding; + } catch( DOMException e ){ + } + return null; + } + public static IBinding[] findBindings( IScope scope, String name, boolean qualified ) throws DOMException{ return findBindings( scope, name.toCharArray(), qualified ); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPTemplates.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPTemplates.java index 283d92031e8..f902da4ef86 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPTemplates.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPTemplates.java @@ -1453,6 +1453,13 @@ public class CPPTemplates { return template; } + public static boolean typeContainsTemplateParameter( IType t ){ + if( t instanceof ICPPTemplateParameter ) + return true; + t = CPPSemantics.getUltimateType( t, false ); + return (t instanceof ICPPTemplateParameter); + } + public static IBinding instantiateTemplate( ICPPTemplateDefinition template, IType [] arguments, ObjectMap specializedArgs ){ if( template == null ){ template = null; @@ -1484,7 +1491,7 @@ public class CPPTemplates { if( i < numArgs ){ arg = arguments[i]; //If the argument is a template parameter, we can't instantiate yet, defer for later - if( arg instanceof ICPPTemplateParameter ){ + if( typeContainsTemplateParameter( arg ) ){ return ((ICPPInternalTemplate)template).deferredInstance( arguments ); } } else { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPVisitor.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPVisitor.java index 3b1adec7bf0..206922c531a 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPVisitor.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPVisitor.java @@ -790,7 +790,18 @@ public class CPPVisitor { } } else if( parent instanceof ICPPASTFieldReference ){ IASTExpression owner = ((ICPPASTFieldReference)parent).getFieldOwner(); - IType type = CPPSemantics.getUltimateType( getExpressionType( owner ), false ); + IType type = getExpressionType( owner ); + if( ((ICPPASTFieldReference)parent).isPointerDereference() ){ + while( type instanceof ITypedef ) + type = ((ITypedef)type).getType(); + if( type instanceof ICPPClassType ){ + ICPPFunction op = CPPSemantics.findOperator( (IASTFieldReference)parent, (ICPPClassType) type ); + if( op != null ){ + type = op.getType().getReturnType(); + } + } + } + type = CPPSemantics.getUltimateType( type, false ); if( type instanceof ICPPClassType ){ return ((ICPPClassType) type).getCompositeScope(); } @@ -1830,6 +1841,12 @@ public class CPPVisitor { while( t instanceof ITypedef ){ t = ((ITypedef)t).getType(); } + if( t instanceof ICPPClassType ){ + ICPPFunction op = CPPSemantics.findOperator( expression, (ICPPClassType) t ); + if( op != null ){ + return op.getType().getReturnType(); + } + } if( t instanceof IPointerType ) return ((IPointerType)t).getType(); else if( t instanceof IArrayType )