diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/AccessContext.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/AccessContext.java index fc290600c7b..1625e78e331 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/AccessContext.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/AccessContext.java @@ -36,6 +36,7 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPClosureType; import org.eclipse.cdt.internal.core.dom.parser.cpp.ClassTypeHelper; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPDeferredClassInstance; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPInternalUnknownScope; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownMemberClass; /** * The context that determines access to private and protected class members. @@ -82,13 +83,19 @@ public class AccessContext { * A class through which the bindings are accessed (11.2.4). */ private boolean isUnqualifiedLookup; + private boolean isPrefixLookup; private ICPPClassType namingClass; // Depends on the binding for which we check the access. // The first candidate is independent of the binding for which we do the access-check. private ICPPClassType firstCandidateForNamingClass; private DOMException initializationException; public AccessContext(IASTName name) { + this(name, false); + } + + public AccessContext(IASTName name, boolean prefixLookup) { this.name = name; + this.isPrefixLookup = prefixLookup; } /** @@ -296,6 +303,13 @@ public class AccessContext { if (scopeType instanceof ICPPDeferredClassInstance) { return ((ICPPDeferredClassInstance) scopeType).getClassTemplate(); } + if (scopeType instanceof ICPPUnknownMemberClass && isPrefixLookup) { + scopeType = HeuristicResolver.resolveUnknownType((ICPPUnknownMemberClass) scopeType, + name.getParent()); + if (scopeType instanceof ICPPClassType) { + return (ICPPClassType) scopeType; + } + } } scope = CPPSemantics.getParentScope(scope, data.getTranslationUnit()); diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/contentassist2/CompletionTests.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/contentassist2/CompletionTests.java index 267fefb98c7..5ccfc967e6b 100644 --- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/contentassist2/CompletionTests.java +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/contentassist2/CompletionTests.java @@ -590,6 +590,22 @@ public class CompletionTests extends CompletionTestBase { assertCompletionResults(fCursorOffset, expected, ID); } + // template + // struct A { + // struct AA { + // static int i; + // }; + // }; + // + // template + // void test() + // { + // A::AA::/*cursor*/ + // } + public void testUnknownMemberClassAccessContext_520783() throws Exception { + assertCompletionResults(new String[] { "i" }); + } + // template // struct A { // template @@ -1126,51 +1142,7 @@ public class CompletionTests extends CompletionTestBase { final String[] expected= { "add(tOther)" }; assertCompletionResults(fCursorOffset, expected, REPLACEMENT); } - - // template - // struct A { - // struct { - // int i; - // } test; - // }; - // - // template - // struct B { - // - // A const* a; - // - // void - // test() - // { - // a->test./*cursor*/ - // } - // }; - public void testHeuristicTypeResolution1_520470() throws Exception { - assertCompletionResults(new String[] { "i" }); - } - - // template - // struct A { - // struct { - // int i; - // } test; - // }; - // - // template - // struct B { - // - // A const* a(); - // - // void - // test() - // { - // a()->t/*cursor*/ - // } - // }; - public void testHeuristicTypeResolution2_520470() throws Exception { - assertCompletionResults(new String[] { "test" }); - } - + //namespace ns { // template // class Base { diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/DOMCompletionProposalComputer.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/DOMCompletionProposalComputer.java index 66657d824af..52360c7299c 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/DOMCompletionProposalComputer.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/DOMCompletionProposalComputer.java @@ -183,7 +183,7 @@ public class DOMCompletionProposalComputer extends ParsingBasedProposalComputer IBinding[] bindings = astContext.findBindings(name, !context.isContextInformationStyle()); if (bindings != null) { - AccessContext accessibilityContext = new AccessContext(name); + AccessContext accessibilityContext = new AccessContext(name, true); for (IBinding binding : bindings) { if (accessibilityContext.isAccessible(binding)) handleBinding(binding, context, prefix, astContext, proposals); @@ -844,7 +844,7 @@ public class DOMCompletionProposalComputer extends ParsingBasedProposalComputer }); Map elementsMap = new HashMap<>(); - AccessContext accessibilityContext = new AccessContext(name); + AccessContext accessibilityContext = new AccessContext(name, true); for (IBinding binding : bindings) { // Consider only fields and variables that are declared in the current translation unit. if (binding instanceof IVariable