diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/prefix/BasicCompletionTest.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/prefix/BasicCompletionTest.java index 7c3340f0624..860a034ce4f 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/prefix/BasicCompletionTest.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/prefix/BasicCompletionTest.java @@ -191,4 +191,17 @@ public class BasicCompletionTest extends CompletionTestBase { checkCompletion(code, true, expectedCpp); checkCompletion(code, false, expectedC); } + + // struct A{ + // virtual void test() {} + // }; + // struct B : A { + // void test() {} + // void func() { + // A::t + public void testQualifiedMemberAccess_Bug300139() throws Exception { + String code = getAboveComment(); + String[] expectedCpp= {"test"}; + checkCompletion(code, true, expectedCpp); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTQualifiedName.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTQualifiedName.java index 316dfad6726..ea60a612a82 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTQualifiedName.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTQualifiedName.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2004, 2008 IBM Corporation and others. + * Copyright (c) 2004, 2010 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -18,6 +18,8 @@ import java.util.List; import org.eclipse.cdt.core.dom.ast.ASTVisitor; import org.eclipse.cdt.core.dom.ast.DOMException; import org.eclipse.cdt.core.dom.ast.IASTCompletionContext; +import org.eclipse.cdt.core.dom.ast.IASTFieldReference; +import org.eclipse.cdt.core.dom.ast.IASTIdExpression; import org.eclipse.cdt.core.dom.ast.IASTName; import org.eclipse.cdt.core.dom.ast.IASTNameOwner; import org.eclipse.cdt.core.dom.ast.IASTNode; @@ -25,11 +27,13 @@ import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration; import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.IEnumerator; import org.eclipse.cdt.core.dom.ast.IField; +import org.eclipse.cdt.core.dom.ast.IScope; import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConversionName; 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.ICPPASTTemplateId; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassScope; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor; import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod; @@ -38,6 +42,8 @@ import org.eclipse.cdt.core.parser.util.ArrayUtil; import org.eclipse.cdt.core.parser.util.CharArrayUtils; import org.eclipse.cdt.internal.core.dom.parser.IASTInternalNameOwner; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil; import org.eclipse.core.runtime.Assert; /** @@ -246,36 +252,58 @@ public class CPPASTQualifiedName extends CPPASTNameBase IBinding binding = names[namesPos-1].resolveBinding(); if (binding instanceof ICPPClassType) { ICPPClassType classType = (ICPPClassType) binding; - final boolean isDeclaration = getParent().getParent() instanceof IASTSimpleDeclaration; - List filtered = filterClassScopeBindings(classType, bindings, isDeclaration); - - if (isDeclaration && nameMatches(classType.getNameCharArray(), - n.getLookupKey(), isPrefix)) { - try { - ICPPConstructor[] constructors = classType.getConstructors(); - for (int i = 0; i < constructors.length; i++) { - if (!constructors[i].isImplicit()) { - filtered.add(constructors[i]); + if (!canBeFieldAccess(classType)) { + final boolean isDeclaration = getParent().getParent() instanceof IASTSimpleDeclaration; + List filtered = filterClassScopeBindings(classType, bindings, isDeclaration); + if (isDeclaration && nameMatches(classType.getNameCharArray(), + n.getLookupKey(), isPrefix)) { + try { + ICPPConstructor[] constructors = classType.getConstructors(); + for (int i = 0; i < constructors.length; i++) { + if (!constructors[i].isImplicit()) { + filtered.add(constructors[i]); + } } + } catch (DOMException e) { } - } catch (DOMException e) { } + return filtered.toArray(new IBinding[filtered.size()]); } - - return filtered.toArray(new IBinding[filtered.size()]); } } return bindings; } + private boolean canBeFieldAccess(ICPPClassType baseClass) { + IASTNode parent= getParent(); + if (parent instanceof IASTFieldReference) { + return true; + } + if (parent instanceof IASTIdExpression) { + IScope scope= CPPVisitor.getContainingScope(this); + try { + while(scope != null) { + if (scope instanceof ICPPClassScope) { + ICPPClassType classType = ((ICPPClassScope) scope).getClassType(); + if (SemanticUtil.calculateInheritanceDepth(classType, baseClass) >= 0) { + return true; + } + } + scope= scope.getParent(); + } + } catch (DOMException e) { + } + } + return false; + } + private List filterClassScopeBindings(ICPPClassType classType, IBinding[] bindings, final boolean isDeclaration) { List filtered = new ArrayList(); try { - for (int i = 0; i < bindings.length; i++) { - final IBinding binding = bindings[i]; + for (final IBinding binding : bindings) { if (binding instanceof IField) { IField field = (IField) binding; if (!field.isStatic()) diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java index 1b0bf15b435..fc48735332a 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java @@ -2163,7 +2163,7 @@ public class CPPSemantics { if (CPPTemplates.isDependentType(implicitType) || CPPTemplates.isDependentType(thisType)) { IType s= getNestedType(thisType, TDEF|REF|CVTYPE); IType t= getNestedType(implicitType, TDEF|REF|CVTYPE); - if (Conversions.calculateInheritanceDepth(MAX_INHERITANCE_DEPTH, s, t) >= 0) + if (SemanticUtil.calculateInheritanceDepth(s, t) >= 0) return null; return CONTAINS_DEPENDENT_TYPES; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/Conversions.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/Conversions.java index e6b580662fd..35679d0a656 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/Conversions.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/Conversions.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2004, 2009 IBM Corporation and others. + * Copyright (c) 2004, 2010 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -24,7 +24,6 @@ import org.eclipse.cdt.core.dom.ast.IASTExpression; import org.eclipse.cdt.core.dom.ast.IASTLiteralExpression; import org.eclipse.cdt.core.dom.ast.IArrayType; import org.eclipse.cdt.core.dom.ast.IBasicType; -import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.IEnumeration; import org.eclipse.cdt.core.dom.ast.IFunctionType; import org.eclipse.cdt.core.dom.ast.IPointerType; @@ -33,7 +32,6 @@ import org.eclipse.cdt.core.dom.ast.IQualifierType; import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.IValue; import org.eclipse.cdt.core.dom.ast.IBasicType.Kind; -import org.eclipse.cdt.core.dom.ast.cpp.ICPPBase; import org.eclipse.cdt.core.dom.ast.cpp.ICPPBasicType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor; @@ -41,13 +39,11 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod; import org.eclipse.cdt.core.dom.ast.cpp.ICPPPointerToMemberType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPReferenceType; -import org.eclipse.cdt.core.dom.ast.cpp.ICPPSpecialization; import org.eclipse.cdt.internal.core.dom.parser.ArithmeticConversion; import org.eclipse.cdt.internal.core.dom.parser.Value; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPBasicType; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPPointerToMemberType; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPPointerType; -import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPDeferredClassInstance; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.Cost.Rank; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.Cost.ReferenceBinding; @@ -207,7 +203,7 @@ public class Conversions { // [13.3.3.1-6] Derived to base conversion if (uqsource instanceof ICPPClassType && uqtarget instanceof ICPPClassType) { - int depth= calculateInheritanceDepth(CPPSemantics.MAX_INHERITANCE_DEPTH, uqsource, uqtarget); + int depth= SemanticUtil.calculateInheritanceDepth(uqsource, uqtarget); if (depth > -1) { if (depth == 0) { return new Cost(uqsource, uqtarget, Rank.IDENTITY); @@ -356,7 +352,7 @@ public class Conversions { s= SemanticUtil.getNestedType(((IQualifierType) s).getType(), TDEF | REF); if (t instanceof ICPPClassType && s instanceof ICPPClassType) { - return calculateInheritanceDepth(CPPSemantics.MAX_INHERITANCE_DEPTH, s, t); + return SemanticUtil.calculateInheritanceDepth(s, t); } } if (t == s || (t != null && s != null && t.isSameType(s))) { @@ -486,7 +482,7 @@ public class Conversions { if (op != null && !(op instanceof IProblemBinding)) { final IType returnType = op.getType().getReturnType(); final IType uqReturnType= getNestedType(returnType, REF | TDEF | CVTYPE); - final int dist = calculateInheritanceDepth(CPPSemantics.MAX_INHERITANCE_DEPTH, uqReturnType, t); + final int dist = SemanticUtil.calculateInheritanceDepth(uqReturnType, t); if (dist >= 0) { final ICPPFunctionType ft = op.getType(); IType implicitType= CPPSemantics.getImplicitType(op, ft.isConst(), ft.isVolatile()); @@ -557,49 +553,6 @@ public class Conversions { return null; } - /** - * Calculates the number of edges in the inheritance path of clazz to - * ancestorToFind, returning -1 if no inheritance relationship is found. - * @param clazz the class to search upwards from - * @param ancestorToFind the class to find in the inheritance graph - * @return the number of edges in the inheritance graph, or -1 if the specified classes have - * no inheritance relation - * @throws DOMException - */ - static final int calculateInheritanceDepth(int maxdepth, IType type, IType ancestorToFind) - throws DOMException { - if (type == ancestorToFind || type.isSameType(ancestorToFind)) { - return 0; - } - - if (maxdepth > 0 && type instanceof ICPPClassType && ancestorToFind instanceof ICPPClassType) { - ICPPClassType clazz = (ICPPClassType) type; - if (clazz instanceof ICPPDeferredClassInstance) { - clazz= (ICPPClassType) ((ICPPDeferredClassInstance) clazz).getSpecializedBinding(); - } - - for (ICPPBase cppBase : clazz.getBases()) { - IBinding base= cppBase.getBaseClass(); - if (base instanceof IType) { - IType tbase= (IType) base; - if (tbase.isSameType(ancestorToFind) || - (ancestorToFind instanceof ICPPSpecialization && // allow some flexibility with templates - ((IType)((ICPPSpecialization) ancestorToFind).getSpecializedBinding()).isSameType(tbase))) { - return 1; - } - - if (tbase instanceof ICPPClassType) { - int n= calculateInheritanceDepth(maxdepth - 1, tbase, ancestorToFind); - if (n > 0) - return n + 1; - } - } - } - } - - return -1; - } - /** * Attempts the conversions below and returns whether this completely converts the source to * the target type. @@ -872,7 +825,7 @@ public class Conversions { // to an rvalue of type "pointer to cv B", where B is a base class of D. IType srcPtrTgt= getNestedType(srcPtr.getType(), TDEF | CVTYPE | REF); if (tgtPtrTgt instanceof ICPPClassType && srcPtrTgt instanceof ICPPClassType) { - int depth= calculateInheritanceDepth(CPPSemantics.MAX_INHERITANCE_DEPTH, srcPtrTgt, tgtPtrTgt); + int depth= SemanticUtil.calculateInheritanceDepth(srcPtrTgt, tgtPtrTgt); if (depth == -1) { cost.setRank(Rank.NO_MATCH); return true; @@ -896,8 +849,8 @@ public class Conversions { IType st = spm.getType(); IType tt = tpm.getType(); if (st != null && tt != null && st.isSameType(tt)) { - int depth= calculateInheritanceDepth(CPPSemantics.MAX_INHERITANCE_DEPTH, - tpm.getMemberOfClass(), spm.getMemberOfClass()); + int depth = SemanticUtil.calculateInheritanceDepth(tpm.getMemberOfClass(), + spm.getMemberOfClass()); if (depth == -1) { cost.setRank(Rank.NO_MATCH); return true; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/SemanticUtil.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/SemanticUtil.java index 8e5e09ef739..6c0194d86f4 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/SemanticUtil.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/SemanticUtil.java @@ -36,6 +36,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod; import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespace; import org.eclipse.cdt.core.dom.ast.cpp.ICPPPointerToMemberType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPReferenceType; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPSpecialization; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateArgument; import org.eclipse.cdt.core.index.IIndexBinding; import org.eclipse.cdt.core.parser.Keywords; @@ -538,4 +539,51 @@ public class SemanticUtil { } return false; } + + /** + * Calculates the number of edges in the inheritance path of type to + * ancestorToFind, returning -1 if no inheritance relationship is found. + * @param type the class to search upwards from + * @param baseClass the class to find in the inheritance graph + * @return the number of edges in the inheritance graph, or -1 if the specified classes have + * no inheritance relation + * @throws DOMException + */ + public static final int calculateInheritanceDepth(IType type, IType baseClass) throws DOMException { + return calculateInheritanceDepth(CPPSemantics.MAX_INHERITANCE_DEPTH, type, baseClass); + } + + private static final int calculateInheritanceDepth(int maxdepth, IType type, IType baseClass) + throws DOMException { + if (type == baseClass || type.isSameType(baseClass)) { + return 0; + } + + if (maxdepth > 0 && type instanceof ICPPClassType && baseClass instanceof ICPPClassType) { + ICPPClassType clazz = (ICPPClassType) type; + if (clazz instanceof ICPPDeferredClassInstance) { + clazz= (ICPPClassType) ((ICPPDeferredClassInstance) clazz).getSpecializedBinding(); + } + + for (ICPPBase cppBase : clazz.getBases()) { + IBinding base= cppBase.getBaseClass(); + if (base instanceof IType) { + IType tbase= (IType) base; + if (tbase.isSameType(baseClass) || + (baseClass instanceof ICPPSpecialization && // allow some flexibility with templates + ((IType)((ICPPSpecialization) baseClass).getSpecializedBinding()).isSameType(tbase))) { + return 1; + } + + if (tbase instanceof ICPPClassType) { + int n= calculateInheritanceDepth(maxdepth - 1, tbase, baseClass); + if (n > 0) + return n + 1; + } + } + } + } + + return -1; + } }