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 478da74c6c7..194e8879ab3 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 @@ -5481,4 +5481,29 @@ public class AST2TemplateTests extends AST2BaseTest { public void testExplicitSpecializationOfForbiddenAsImplicit_356818() throws Exception { parseAndCheckBindings(); } + + // struct A { + // void f() { } + // }; + // template struct B : A { + // using A::f; + // void f(int) { } + // }; + // template struct C : B { + // using B::f; + // void f(int, int); + // }; + // + // void test() { + // B b; + // C c; + // b.f(); + // b.f(1); + // c.f(); + // c.f(1); + // c.f(1,1); + // } + public void testSpecializationOfUsingDeclaration_357293() throws Exception { + parseAndCheckBindings(); + } } diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexCPPTemplateResolutionTest.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexCPPTemplateResolutionTest.java index 73aedf05974..727c98a3edc 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexCPPTemplateResolutionTest.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexCPPTemplateResolutionTest.java @@ -1866,4 +1866,35 @@ public class IndexCPPTemplateResolutionTest extends IndexBindingResolutionTestBa IBinding[] friends = ct.getFriends(); assertEquals(0, friends.length); // not yet supported } + + // struct A { + // void f() { } + // }; + // template struct B : A { + // using A::f; + // void f(int) { } + // }; + // template struct C : B { + // using B::f; + // void f(int, int); + // }; + // B b; + // C c; + + // #include "header.h" + // void test() { + // b.f(); + // b.f(1); + // c.f( ); + // c.f(2); + // c.f(2,1); + // } + public void testSpecializationOfUsingDeclaration_357293() throws Exception { + getBindingFromASTName("f()", 1, ICPPMethod.class); + getBindingFromASTName("f(1)", 1, ICPPMethod.class); + getBindingFromASTName("f( )", 1, ICPPMethod.class); + getBindingFromASTName("f(2)", 1, ICPPMethod.class); + getBindingFromASTName("f(2,1)", 1, ICPPMethod.class); + } + } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPUsingDeclarationSpecialization.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPUsingDeclarationSpecialization.java new file mode 100644 index 00000000000..3e8ebd91cea --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPUsingDeclarationSpecialization.java @@ -0,0 +1,66 @@ +/******************************************************************************* + * Copyright (c) 2011 Wind River Systems, Inc. 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Markus Schorn (Wind River Systems) + *******************************************************************************/ +package org.eclipse.cdt.internal.core.dom.parser.cpp; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.cdt.core.dom.ast.DOMException; +import org.eclipse.cdt.core.dom.ast.IBinding; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassSpecialization; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPUsingDeclaration; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPFunctionSet; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPTemplates; + +/** + * Specialization of a typedef in the context of a class-specialization. + */ +public class CPPUsingDeclarationSpecialization extends CPPSpecialization implements ICPPUsingDeclaration { + private IBinding[] fDelegates; + + public CPPUsingDeclarationSpecialization(ICPPUsingDeclaration specialized, ICPPClassSpecialization owner, + ICPPTemplateParameterMap tpmap) { + super(specialized, owner, tpmap); + } + + public IBinding[] getDelegates() { + if (fDelegates == null) { + fDelegates= specializeDelegates(); + } + return fDelegates; + } + + private IBinding[] specializeDelegates() { + IBinding[] origDelegates= ((ICPPUsingDeclaration) getSpecializedBinding()).getDelegates(); + List result= new ArrayList(); + ICPPClassSpecialization owner= (ICPPClassSpecialization) getOwner(); + for (IBinding delegate : origDelegates) { + if (delegate instanceof ICPPUnknownBinding) { + try { + delegate= CPPTemplates.resolveUnknown((ICPPUnknownBinding) delegate, + owner.getTemplateParameterMap(), -1, null); + if (delegate instanceof CPPFunctionSet) { + for (IBinding b : ((CPPFunctionSet) delegate).getBindings()) { + result.add(b); + } + } else if (delegate != null) { + result.add(delegate); + } + } catch (DOMException e) { + } + } else { + result.add(delegate); + } + } + return result.toArray(new IBinding[result.size()]); + } +} 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 6af7c70a0a8..9eb3b1bb794 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 @@ -2465,7 +2465,7 @@ public class CPPSemantics { boolean haveASTResult= false; for (ICPPFunction f : fns) { // Use the ast binding - final boolean fromIndex = f instanceof IIndexBinding; + final boolean fromIndex = isFromIndex(f); if (haveASTResult && fromIndex) break; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPTemplates.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPTemplates.java index 034b816e34b..974deaa6e2f 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPTemplates.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPTemplates.java @@ -89,6 +89,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateTemplateParameter; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateTypeParameter; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPUsingDeclaration; import org.eclipse.cdt.core.index.IIndexBinding; import org.eclipse.cdt.core.parser.util.ArrayUtil; import org.eclipse.cdt.core.parser.util.CharArraySet; @@ -134,6 +135,7 @@ 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.CPPUnknownClassInstance; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPUnknownFunction; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPUsingDeclarationSpecialization; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPASTInternalTemplateDeclaration; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPDeferredClassInstance; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPInstanceCache; @@ -794,6 +796,8 @@ public class CPPTemplates { } else if (decl instanceof IEnumeration || decl instanceof IEnumerator) { // TODO(sprigogin): Deal with a case when an enumerator value depends on a template parameter. spec = decl; + } else if (decl instanceof ICPPUsingDeclaration) { + spec= new CPPUsingDeclarationSpecialization((ICPPUsingDeclaration) decl, owner, tpMap); } return spec; } @@ -2294,7 +2298,7 @@ public class CPPTemplates { /** * Attempts to (partially) resolve an unknown binding with the given arguments. */ - private static IBinding resolveUnknown(ICPPUnknownBinding unknown, ICPPTemplateParameterMap tpMap, + public static IBinding resolveUnknown(ICPPUnknownBinding unknown, ICPPTemplateParameterMap tpMap, int packOffset, ICPPClassSpecialization within) throws DOMException { if (unknown instanceof ICPPDeferredClassInstance) { return resolveDeferredClassInstance((ICPPDeferredClassInstance) unknown, tpMap, packOffset, within); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IIndexCPPBindingConstants.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IIndexCPPBindingConstants.java index 6185ba51929..adc31d84c7b 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IIndexCPPBindingConstants.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IIndexCPPBindingConstants.java @@ -58,4 +58,5 @@ public interface IIndexCPPBindingConstants { int CPP_TEMPLATE_TEMPLATE_PARAMETER= IIndexBindingConstants.LAST_CONSTANT + 46; int CPP_CLASS_TEMPLATE_PARTIAL_SPEC_SPEC = IIndexBindingConstants.LAST_CONSTANT + 47; int CPP_UNKNOWN_BINDING = IIndexBindingConstants.LAST_CONSTANT + 48; + int CPP_USING_DECLARATION_SPECIALIZATION= IIndexBindingConstants.LAST_CONSTANT + 49; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CPPCompositesFactory.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CPPCompositesFactory.java index 545020408d7..86ff782071a 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CPPCompositesFactory.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CPPCompositesFactory.java @@ -293,6 +293,8 @@ public class CPPCompositesFactory extends AbstractCompositeFactory { return new CompositeCPPParameterSpecialization(this, (ICPPParameter) binding); } else if (binding instanceof ITypedef) { return new CompositeCPPTypedefSpecialization(this, (ICPPBinding) binding); + } else if (binding instanceof ICPPUsingDeclaration) { + return new CompositeCPPUsingDeclarationSpecialization(this, (ICPPUsingDeclaration) binding); } else { throw new CompositingNotImplementedError("composite binding unavailable for " + binding + " " + binding.getClass()); //$NON-NLS-1$ //$NON-NLS-2$ } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPUsingDeclarationSpecialization.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPUsingDeclarationSpecialization.java new file mode 100644 index 00000000000..401e2d9a3bb --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPUsingDeclarationSpecialization.java @@ -0,0 +1,42 @@ +/******************************************************************************* + * Copyright (c) 2011 Wind River Systems, Inc. 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Markus Schorn (Wind River Systems) + *******************************************************************************/ +package org.eclipse.cdt.internal.core.index.composite.cpp; + +import org.eclipse.cdt.core.dom.ast.IBinding; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPSpecialization; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPUsingDeclaration; +import org.eclipse.cdt.core.parser.util.ObjectMap; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPTemplateParameterMap; +import org.eclipse.cdt.internal.core.index.composite.ICompositesFactory; + +class CompositeCPPUsingDeclarationSpecialization extends CompositeCPPUsingDeclaration implements ICPPSpecialization { + public CompositeCPPUsingDeclarationSpecialization(ICompositesFactory cf, ICPPUsingDeclaration delegate) { + super(cf, delegate); + } + + public IBinding getSpecializedBinding() { + return TemplateInstanceUtil.getSpecializedBinding(cf, rbinding); + } + + public ICPPTemplateParameterMap getTemplateParameterMap() { + IBinding owner= getOwner(); + if (owner instanceof ICPPSpecialization) { + return ((ICPPSpecialization) owner).getTemplateParameterMap(); + } + return CPPTemplateParameterMap.EMPTY; + } + + @Deprecated + public ObjectMap getArgumentMap() { + return TemplateInstanceUtil.getArgumentMap(cf, rbinding); + } +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java index 79f9fecac9d..0c1d82decf1 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java @@ -209,10 +209,11 @@ public class PDOM extends PlatformObject implements IPDOM { * * CDT 8.1 development (versions not supported on teh 8.0.x branch) * 120.0 - Enumerators in global index, bug 356235 + * 120.1 - Specializations of using declarations, bug 357293. */ private static final int MIN_SUPPORTED_VERSION= version(120, 0); private static final int MAX_SUPPORTED_VERSION= version(120, Short.MAX_VALUE); - private static final int DEFAULT_VERSION = version(120, 0); + private static final int DEFAULT_VERSION = version(120, 1); private static int version(int major, int minor) { return (major << 16) + minor; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMLinkage.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMLinkage.java index 16e67f87efc..35cc42ef67b 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMLinkage.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMLinkage.java @@ -379,11 +379,11 @@ public abstract class PDOMLinkage extends PDOMNamedNode implements IIndexLinkage } /** - * Usually bindings are added on behalf of a name, only. For unknown values we need to - * add further bindings. + * Usually bindings are added on behalf of a name, only. For unknown values or using declarations + * we need to add further bindings. * @throws CoreException */ - public PDOMBinding addUnknownValue(IBinding binding) throws CoreException { + public PDOMBinding addPotentiallyUnknownBinding(IBinding binding) throws CoreException { return null; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPLinkage.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPLinkage.java index cad18e550a2..8b7dab40caf 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPLinkage.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPLinkage.java @@ -239,7 +239,7 @@ class PDOMCPPLinkage extends PDOMLinkage implements IIndexCPPBindingConstants { } @Override - public PDOMBinding addUnknownValue(IBinding binding) throws CoreException { + public PDOMBinding addPotentiallyUnknownBinding(IBinding binding) throws CoreException { return addBinding(binding, null); } @@ -461,6 +461,8 @@ class PDOMCPPLinkage extends PDOMLinkage implements IIndexCPPBindingConstants { result= new PDOMCPPClassSpecialization(this, parent, (ICPPClassType) special, orig); } else if (special instanceof ITypedef) { result= new PDOMCPPTypedefSpecialization(this, parent, (ITypedef) special, orig); + } else if (special instanceof ICPPUsingDeclaration) { + result= new PDOMCPPUsingDeclarationSpecialization(this, parent, (ICPPUsingDeclaration) special, orig); } return result; @@ -805,6 +807,8 @@ class PDOMCPPLinkage extends PDOMLinkage implements IIndexCPPBindingConstants { return new PDOMCPPClassTemplateSpecialization(this, record); case CPP_TYPEDEF_SPECIALIZATION: return new PDOMCPPTypedefSpecialization(this, record); + case CPP_USING_DECLARATION_SPECIALIZATION: + return new PDOMCPPUsingDeclarationSpecialization(this, record); } assert false : "nodeid= " + nodeType; //$NON-NLS-1$ return null; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPUsingDeclaration.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPUsingDeclaration.java index 8f3aa29586d..07ceaa1c657 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPUsingDeclaration.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPUsingDeclaration.java @@ -54,7 +54,7 @@ class PDOMCPPUsingDeclaration extends PDOMCPPBinding implements ICPPUsingDeclara Set targets= new LinkedHashSet(); PDOMCPPUsingDeclaration last= null; for (IBinding delegate : using.getDelegates()) { - PDOMBinding target = getLinkage().adaptBinding(delegate); + PDOMBinding target = getLinkage().addPotentiallyUnknownBinding(delegate); if (target != null && targets.add(target)) { if (last == null) { setTargetBinding(linkage, target); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPUsingDeclarationSpecialization.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPUsingDeclarationSpecialization.java new file mode 100644 index 00000000000..5e84e80e8a6 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPUsingDeclarationSpecialization.java @@ -0,0 +1,88 @@ +/******************************************************************************* + * Copyright (c) 2011 Wind River Systems, Inc. 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Markus Schorn (Wind River Systems) + *******************************************************************************/ +package org.eclipse.cdt.internal.core.pdom.dom.cpp; + +import java.util.ArrayList; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Set; + +import org.eclipse.cdt.core.dom.IPDOMNode; +import org.eclipse.cdt.core.dom.IPDOMVisitor; +import org.eclipse.cdt.core.dom.ast.IBinding; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPSpecialization; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPUsingDeclaration; +import org.eclipse.cdt.internal.core.index.IIndexCPPBindingConstants; +import org.eclipse.cdt.internal.core.pdom.db.Database; +import org.eclipse.cdt.internal.core.pdom.db.PDOMNodeLinkedList; +import org.eclipse.cdt.internal.core.pdom.dom.PDOMBinding; +import org.eclipse.cdt.internal.core.pdom.dom.PDOMLinkage; +import org.eclipse.cdt.internal.core.pdom.dom.PDOMNode; +import org.eclipse.core.runtime.CoreException; + +class PDOMCPPUsingDeclarationSpecialization extends PDOMCPPSpecialization implements ICPPUsingDeclaration { + private static final int TARGET_BINDINGS = PDOMCPPSpecialization.RECORD_SIZE; + + @SuppressWarnings("hiding") + protected static final int RECORD_SIZE = TARGET_BINDINGS + Database.PTR_SIZE; + + private volatile IBinding[] delegates; + + public PDOMCPPUsingDeclarationSpecialization(PDOMLinkage linkage, PDOMNode parent, ICPPUsingDeclaration using, PDOMBinding specialized) + throws CoreException { + super(linkage, parent, (ICPPSpecialization) using, specialized); + + Set targets= new LinkedHashSet(); + PDOMNodeLinkedList list = new PDOMNodeLinkedList(getLinkage(), record + TARGET_BINDINGS); + for (IBinding delegate : using.getDelegates()) { + PDOMBinding target = getLinkage().adaptBinding(delegate); + if (target != null && targets.add(target)) { + list.addMember(target); + } + } + } + + public PDOMCPPUsingDeclarationSpecialization(PDOMLinkage linkage, long record) { + super(linkage, record); + } + + @Override + protected int getRecordSize() { + return RECORD_SIZE; + } + + @Override + public int getNodeType() { + return IIndexCPPBindingConstants.CPP_USING_DECLARATION; + } + + public IBinding[] getDelegates() { + if (delegates == null) { + PDOMNodeLinkedList list= new PDOMNodeLinkedList(getLinkage(), record+TARGET_BINDINGS); + final List result= new ArrayList(); + try { + list.accept(new IPDOMVisitor() { + public boolean visit(IPDOMNode node) { + if (node instanceof IBinding) { + result.add((IBinding) node); + } + return true; + } + public void leave(IPDOMNode node) { + } + }); + } catch (CoreException e) { + } + delegates = result.toArray(new IBinding[result.size()]); + } + return delegates; + } +}