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 423fd5011a8..e4dc436fbf6 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 @@ -8216,4 +8216,21 @@ public class AST2TemplateTests extends AST2TestBase { BindingAssertionHelper helper = getAssertionHelper(); helper.assertNonProblem("waldo", ICPPDeferredFunction.class); } + + // template + // struct C { + // friend bool operator==(C, C); + // friend bool operator!=(C, C); + // }; + // + // template + // void waldo(U, U); + // + // void test() { + // C x; + // waldo(x, x); + // } + public void testStrayFriends_419301() throws Exception { + parseAndCheckBindings(); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/util/ArrayUtil.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/util/ArrayUtil.java index 96860d9c8aa..e1963735b1d 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/util/ArrayUtil.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/util/ArrayUtil.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2004, 2009 IBM Corporation and others. + * Copyright (c) 2004, 2013 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 @@ -11,6 +11,7 @@ * Andrew Ferguson (Symbian) * Mike Kucera (IBM) * Sergey Prigogin (Google) + * Nathan Ridge *******************************************************************************/ package org.eclipse.cdt.core.parser.util; @@ -741,4 +742,29 @@ public abstract class ArrayUtil { array[idx] = val; return array; } + + /** + * Filter the elements of an array down to just the ones + * that match the given predicate. + * @since 5.6 + */ + public static T[] filter(T[] array, IUnaryPredicate predicate) { + T[] result = array; + int resultIndex = 0; + for (int i = 0; i < array.length; ++i) { + if (predicate.apply(array[i])) { + if (result != array) { + result[resultIndex] = array[i]; + } + ++resultIndex; + } else { + if (result == array) { + // There will be at most array.length - 1 filtered elements. + result = Arrays.copyOf(array, array.length - 1); + Arrays.fill(result, i, result.length, null); + } + } + } + return resultIndex == result.length ? result : Arrays.copyOf(result, resultIndex); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/util/CollectionUtils.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/util/CollectionUtils.java index aa1587d1349..d93a69016ca 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/util/CollectionUtils.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/util/CollectionUtils.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2006, 2012 IBM Corporation and others. + * Copyright (c) 2006, 2013 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 @@ -8,6 +8,7 @@ * Contributors: * Mike Kucera (IBM Corporation) - initial API and implementation * Sergey Prigogin (Google) + * Nathan Ridge *******************************************************************************/ package org.eclipse.cdt.core.parser.util; @@ -151,4 +152,19 @@ public final class CollectionUtils { } return result; } + + /** + * Filter the elements of a collection down to just the ones + * that match the given predicate. + * @since 5.6 + */ + public static Collection filter(Collection collection, IUnaryPredicate predicate) { + if (collection.isEmpty()) + return collection; + Collection result = new ArrayList(); + for (T t : collection) + if (predicate.apply(t)) + result.add(t); + return result; + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/util/IUnaryPredicate.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/util/IUnaryPredicate.java new file mode 100644 index 00000000000..ca2473d5e35 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/util/IUnaryPredicate.java @@ -0,0 +1,20 @@ +/******************************************************************************* + * Copyright (c) 2013 Nathan Ridge. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Nathan Ridge - initial API + *******************************************************************************/ +package org.eclipse.cdt.core.parser.util; + +/** + * A generic unary predicate interface. + * Useful for operations that use unary predicates, like filtering an array. + * @since 5.6 + */ +public interface IUnaryPredicate { + boolean apply(T argument); +} \ No newline at end of file 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 4bb8ffe430b..f87f6863ec2 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 @@ -180,7 +180,9 @@ import org.eclipse.cdt.core.index.IIndexName; import org.eclipse.cdt.core.parser.util.ArrayUtil; import org.eclipse.cdt.core.parser.util.CharArrayObjectMap; import org.eclipse.cdt.core.parser.util.CharArrayUtils; +import org.eclipse.cdt.core.parser.util.CollectionUtils; import org.eclipse.cdt.core.parser.util.DebugUtil; +import org.eclipse.cdt.core.parser.util.IUnaryPredicate; import org.eclipse.cdt.core.parser.util.ObjectSet; import org.eclipse.cdt.internal.core.dom.parser.ASTAmbiguousNode; import org.eclipse.cdt.internal.core.dom.parser.ASTInternal; @@ -597,10 +599,26 @@ public class CPPSemantics { lookup(data, scope); } } - mergeResults(data, friendFns.toArray(), false); + Object[] matchingFriendFns = CollectionUtils.filter( + friendFns, + new NameMatcherPredicate(data.getLookupKey())).toArray(); + mergeResults(data, matchingFriendFns, false); data.qualified = originalQualified; } - + + private static class NameMatcherPredicate implements IUnaryPredicate { + private char[] fKey; + + public NameMatcherPredicate(char[] key) { + fKey = key; + } + + @Override + public boolean apply(ICPPFunction argument) { + return Arrays.equals(argument.getNameCharArray(), fKey); + } + } + static IBinding checkDeclSpecifier(IBinding binding, IASTName name, IASTNode decl) { // Check for empty declaration specifiers. if (!isCtorOrConversionOperator(binding)) { @@ -1262,31 +1280,19 @@ public class CPPSemantics { } if (data.ignoreRecursionResolvingBindings()) { - bindings = filterOutRecursionResovingBindings(bindings); + bindings = ArrayUtil.filter(bindings, new RecursionResolvingBindingFilter()); } return expandUsingDeclarationsAndRemoveObjects(bindings, data); } - private static IBinding[] filterOutRecursionResovingBindings(IBinding[] bindings) { - IBinding[] result = bindings; - int resultIndex = 0; - for (int i = 0; i < bindings.length; ++i) { - if (bindings[i] instanceof IRecursionResolvingBinding) { - if (result == bindings) { - result = new IBinding[bindings.length - 1]; - System.arraycopy(bindings, 0, result, 0, i); - } - } else { - if (result != bindings) { - result[resultIndex] = bindings[i]; - } - ++resultIndex; - } + private static class RecursionResolvingBindingFilter implements IUnaryPredicate { + @Override + public boolean apply(IBinding argument) { + return !(argument instanceof IRecursionResolvingBinding); } - return ArrayUtil.trim(result); } - + private static IBinding[] expandUsingDeclarationsAndRemoveObjects(final IBinding[] bindings, LookupData data) { if (bindings == null || bindings.length == 0)