mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-29 19:45:01 +02:00
Bug 257293: Support specializations of using declarations.
This commit is contained in:
parent
8bc2b56358
commit
ca59d810e3
13 changed files with 272 additions and 8 deletions
|
@ -5481,4 +5481,29 @@ public class AST2TemplateTests extends AST2BaseTest {
|
|||
public void testExplicitSpecializationOfForbiddenAsImplicit_356818() throws Exception {
|
||||
parseAndCheckBindings();
|
||||
}
|
||||
|
||||
// struct A {
|
||||
// void f() { }
|
||||
// };
|
||||
// template <typename T> struct B : A {
|
||||
// using A::f;
|
||||
// void f(int) { }
|
||||
// };
|
||||
// template <typename T> struct C : B<T> {
|
||||
// using B<T>::f;
|
||||
// void f(int, int);
|
||||
// };
|
||||
//
|
||||
// void test() {
|
||||
// B<float> b;
|
||||
// C<float> c;
|
||||
// b.f();
|
||||
// b.f(1);
|
||||
// c.f();
|
||||
// c.f(1);
|
||||
// c.f(1,1);
|
||||
// }
|
||||
public void testSpecializationOfUsingDeclaration_357293() throws Exception {
|
||||
parseAndCheckBindings();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 <typename T> struct B : A {
|
||||
// using A::f;
|
||||
// void f(int) { }
|
||||
// };
|
||||
// template <typename T> struct C : B<T> {
|
||||
// using B<T>::f;
|
||||
// void f(int, int);
|
||||
// };
|
||||
// B<float> b;
|
||||
// C<float> 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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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<IBinding> result= new ArrayList<IBinding>();
|
||||
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()]);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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$
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -54,7 +54,7 @@ class PDOMCPPUsingDeclaration extends PDOMCPPBinding implements ICPPUsingDeclara
|
|||
Set<PDOMBinding> targets= new LinkedHashSet<PDOMBinding>();
|
||||
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);
|
||||
|
|
|
@ -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<PDOMBinding> targets= new LinkedHashSet<PDOMBinding>();
|
||||
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<IBinding> result= new ArrayList<IBinding>();
|
||||
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;
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue