mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-08-11 02:05:39 +02:00
Bug 516338 - Introduce alias template specializations
We previously modelled alias template specializations as alias template instances, which was conceptually incorrect and problematic for a number of reasons. Change-Id: Ibca8b87bb3d54cd3ae312254a02e8522e446331d
This commit is contained in:
parent
3e0853ae0c
commit
8d6cab41e7
9 changed files with 254 additions and 54 deletions
|
@ -0,0 +1,61 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2017 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
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.internal.core.dom.parser.cpp;
|
||||
|
||||
import org.eclipse.cdt.core.dom.ast.IBinding;
|
||||
import org.eclipse.cdt.core.dom.ast.IType;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPAliasTemplate;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap;
|
||||
|
||||
/**
|
||||
* Specialization of an alias template.
|
||||
*/
|
||||
public class CPPAliasTemplateSpecialization extends CPPSpecialization implements ICPPAliasTemplate {
|
||||
private ICPPTemplateParameter[] fParameters;
|
||||
private IType fAliasedType;
|
||||
|
||||
public CPPAliasTemplateSpecialization(ICPPAliasTemplate specialized, IBinding owner,
|
||||
ICPPTemplateParameterMap argumentMap, IType aliasedType) {
|
||||
super(specialized, owner, argumentMap);
|
||||
fAliasedType = aliasedType;
|
||||
}
|
||||
|
||||
public void setTemplateParameters(ICPPTemplateParameter[] parameters) {
|
||||
fParameters = parameters;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSameType(IType type) {
|
||||
if (type == null) {
|
||||
return false;
|
||||
}
|
||||
return type.isSameType(fAliasedType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ICPPTemplateParameter[] getTemplateParameters() {
|
||||
return fParameters;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IType getType() {
|
||||
return fAliasedType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object clone() {
|
||||
IType t = null;
|
||||
try {
|
||||
t = (IType) super.clone();
|
||||
} catch (CloneNotSupportedException e) {
|
||||
// Not going to happen
|
||||
}
|
||||
return t;
|
||||
}
|
||||
}
|
|
@ -134,6 +134,7 @@ import org.eclipse.cdt.internal.core.dom.parser.ProblemFunctionType;
|
|||
import org.eclipse.cdt.internal.core.dom.parser.ProblemType;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTName;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPAliasTemplateInstance;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPAliasTemplateSpecialization;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPArrayType;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPClassInstance;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPClassSpecialization;
|
||||
|
@ -316,35 +317,6 @@ public class CPPTemplates {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiate a specialization of an alias template with the given arguments.
|
||||
*
|
||||
* TODO(nathanridge): The reason we have this method is that we (incorrectly) represent
|
||||
* specializations of alias templates as alias template instances. A specialization of
|
||||
* an alias template is an alias template, so it needs to be instantiated to produce
|
||||
* an actual alias template instance. Actual alias template instances do not need to be
|
||||
* instantiated.
|
||||
*/
|
||||
public static IBinding instantiateAliasTemplateInstance(ICPPAliasTemplateInstance aliasTemplateInstance,
|
||||
ICPPTemplateArgument[] args, IASTNode point) {
|
||||
ICPPAliasTemplate aliasTemplate = aliasTemplateInstance.getTemplateDefinition();
|
||||
try {
|
||||
args = addDefaultArguments(aliasTemplate, args, point);
|
||||
if (args == null) {
|
||||
return createProblem(aliasTemplate, IProblemBinding.SEMANTIC_INVALID_TEMPLATE_ARGUMENTS, point);
|
||||
}
|
||||
ICPPTemplateParameterMap parameterMap = createParameterMap(aliasTemplate, args, point);
|
||||
if (parameterMap == null) {
|
||||
return createProblem(aliasTemplate, IProblemBinding.SEMANTIC_INVALID_TEMPLATE_ARGUMENTS, point);
|
||||
}
|
||||
IType aliasedType = aliasTemplateInstance.getType();
|
||||
IBinding owner = aliasTemplateInstance.getOwner();
|
||||
return createAliasTemplaceInstance(aliasTemplate, args, parameterMap, aliasedType, owner, point);
|
||||
} catch (DOMException e) {
|
||||
return e.getProblem();
|
||||
}
|
||||
}
|
||||
|
||||
private static IBinding createProblem(ICPPTemplateDefinition template, int id, IASTNode point) {
|
||||
return new ProblemBinding(point, id, template.getNameCharArray());
|
||||
}
|
||||
|
@ -797,16 +769,6 @@ public class CPPTemplates {
|
|||
return instantiateAliasTemplate(aliasTemplate, args, id);
|
||||
}
|
||||
|
||||
// Alias template instance.
|
||||
if (template instanceof ICPPAliasTemplateInstance) {
|
||||
// TODO(nathanridge): Remove this branch once we properly represent
|
||||
// specializations of alias templates (which will then implement
|
||||
// ICPPAliasTemplate and be caught by the previous branch).
|
||||
ICPPAliasTemplateInstance aliasTemplateInstance = (ICPPAliasTemplateInstance) template;
|
||||
ICPPTemplateArgument[] args = createTemplateArgumentArray(id);
|
||||
return instantiateAliasTemplateInstance(aliasTemplateInstance, args, id);
|
||||
}
|
||||
|
||||
// Class or variable template.
|
||||
if (template instanceof ICPPConstructor) {
|
||||
template= template.getOwner();
|
||||
|
@ -1120,7 +1082,12 @@ public class CPPTemplates {
|
|||
ICPPAliasTemplate aliasTemplate = (ICPPAliasTemplate) decl;
|
||||
InstantiationContext context = createInstantiationContext(tpMap, owner, point);
|
||||
IType type= instantiateType(aliasTemplate.getType(), context);
|
||||
spec = new CPPAliasTemplateInstance(decl.getNameCharArray(), aliasTemplate, type);
|
||||
CPPAliasTemplateSpecialization aliasSpec =
|
||||
new CPPAliasTemplateSpecialization(aliasTemplate, owner, tpMap, type);
|
||||
aliasSpec.setTemplateParameters(specializeTemplateParameters(aliasSpec,
|
||||
(ICPPScope) aliasSpec.getScope(), aliasTemplate.getTemplateParameters(), classOwner,
|
||||
point));
|
||||
spec = aliasSpec;
|
||||
} else if (decl instanceof ICPPEnumeration && classOwner != null) {
|
||||
// TODO: Handle local enumerations
|
||||
spec = CPPEnumerationSpecialization.createInstance((ICPPEnumeration) decl, classOwner, tpMap, point);
|
||||
|
@ -3045,12 +3012,6 @@ public class CPPTemplates {
|
|||
} else if (result instanceof ICPPAliasTemplate) {
|
||||
result = instantiateAliasTemplate((ICPPAliasTemplate) result, args1,
|
||||
context.getPoint());
|
||||
} else if (result instanceof ICPPAliasTemplateInstance) {
|
||||
// TODO(nathanridge): Remove this branch once we properly represent
|
||||
// specializations of alias templates (which will then implement
|
||||
// ICPPAliasTemplate and be caught by the previous branch).
|
||||
result = instantiateAliasTemplateInstance((ICPPAliasTemplateInstance) result,
|
||||
args1, context.getPoint());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,7 +26,6 @@ import org.eclipse.cdt.core.dom.ast.IScope;
|
|||
import org.eclipse.cdt.core.dom.ast.IType;
|
||||
import org.eclipse.cdt.core.dom.ast.IVariable;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPAliasTemplate;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPAliasTemplateInstance;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPBase;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassSpecialization;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassTemplate;
|
||||
|
@ -451,12 +450,6 @@ public class HeuristicResolver {
|
|||
} else if (result instanceof ICPPAliasTemplate) {
|
||||
result = (IType) CPPTemplates.instantiateAliasTemplate((ICPPAliasTemplate) result,
|
||||
args, point);
|
||||
} else if (result instanceof ICPPAliasTemplateInstance) {
|
||||
// TODO(nathanridge): Remove this branch once we properly represent
|
||||
// specializations of alias templates (which will then implement
|
||||
// ICPPAliasTemplate and be caught by the previous branch).
|
||||
result = (IType) CPPTemplates.instantiateAliasTemplateInstance(
|
||||
(ICPPAliasTemplateInstance) result, args, point);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
|
|
@ -73,4 +73,5 @@ public interface IIndexCPPBindingConstants {
|
|||
int CPP_VARIABLE_TEMPLATE_PARTIAL_SPECIALIZATION = IIndexBindingConstants.LAST_CONSTANT + 59;
|
||||
int CPP_FIELD_TEMPLATE_PARTIAL_SPECIALIZATION = IIndexBindingConstants.LAST_CONSTANT + 60;
|
||||
int CPP_DEFERRED_VARIABLE_INSTANCE = IIndexBindingConstants.LAST_CONSTANT + 61;
|
||||
int CPP_ALIAS_TEMPLATE_SPECIALIZATION = IIndexBindingConstants.LAST_CONSTANT + 62;
|
||||
}
|
||||
|
|
|
@ -595,6 +595,8 @@ public class CPPCompositesFactory extends AbstractCompositeFactory {
|
|||
return new CompositeCPPMethodTemplateSpecialization(this, (ICPPMethod) binding);
|
||||
} else if (binding instanceof ICPPFunction) {
|
||||
return new CompositeCPPFunctionTemplateSpecialization(this, (ICPPFunction) binding);
|
||||
} else if (binding instanceof ICPPAliasTemplate) {
|
||||
return new CompositeCPPAliasTemplateSpecialization(this, (ICPPAliasTemplate) binding);
|
||||
} else {
|
||||
throw new CompositingNotImplementedError("Composite binding unavailable for " + binding + " " + binding.getClass()); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
}
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2017 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
|
||||
*******************************************************************************/
|
||||
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.ICPPAliasTemplate;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPSpecialization;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPTemplateParameterMap;
|
||||
import org.eclipse.cdt.internal.core.index.composite.ICompositesFactory;
|
||||
|
||||
public class CompositeCPPAliasTemplateSpecialization extends CompositeCPPAliasTemplate
|
||||
implements ICPPSpecialization {
|
||||
public CompositeCPPAliasTemplateSpecialization(ICompositesFactory cf, ICPPAliasTemplate delegate) {
|
||||
super(cf, delegate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBinding getSpecializedBinding() {
|
||||
return TemplateInstanceUtil.getSpecializedBinding(cf, rbinding);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ICPPTemplateParameterMap getTemplateParameterMap() {
|
||||
IBinding owner = getOwner();
|
||||
if (owner instanceof ICPPSpecialization) {
|
||||
return ((ICPPSpecialization) owner).getTemplateParameterMap();
|
||||
}
|
||||
return CPPTemplateParameterMap.EMPTY;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,114 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2017 Nathan Ridge.
|
||||
* Rapperswil, University of applied sciences.
|
||||
* 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
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.internal.core.pdom.dom.cpp;
|
||||
|
||||
import org.eclipse.cdt.core.CCorePlugin;
|
||||
import org.eclipse.cdt.core.dom.ast.DOMException;
|
||||
import org.eclipse.cdt.core.dom.ast.IType;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPAliasTemplate;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPSpecialization;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter;
|
||||
import org.eclipse.cdt.internal.core.index.IIndexCPPBindingConstants;
|
||||
import org.eclipse.cdt.internal.core.pdom.db.Database;
|
||||
import org.eclipse.cdt.internal.core.pdom.dom.IPDOMBinding;
|
||||
import org.eclipse.cdt.internal.core.pdom.dom.PDOMNode;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
|
||||
/**
|
||||
* PDOM binding for alias template specializations.
|
||||
*/
|
||||
public class PDOMCPPAliasTemplateSpecialization extends PDOMCPPSpecialization implements ICPPAliasTemplate {
|
||||
private static final int ALIASED_TYPE = PDOMCPPSpecialization.RECORD_SIZE; // TYPE_SIZE
|
||||
private static final int TEMPLATE_PARAMS = ALIASED_TYPE + Database.TYPE_SIZE; // PTR_SIZE
|
||||
|
||||
@SuppressWarnings("hiding")
|
||||
private static final int RECORD_SIZE = TEMPLATE_PARAMS + Database.PTR_SIZE;
|
||||
|
||||
private volatile IPDOMCPPTemplateParameter[] fParameters;
|
||||
|
||||
public PDOMCPPAliasTemplateSpecialization(PDOMCPPLinkage linkage, PDOMNode parent,
|
||||
ICPPAliasTemplate aliasTemplateSpec, IPDOMBinding specialized)
|
||||
throws CoreException, DOMException {
|
||||
super(linkage, parent, (ICPPSpecialization) aliasTemplateSpec, specialized);
|
||||
final ICPPTemplateParameter[] origParams = aliasTemplateSpec.getTemplateParameters();
|
||||
fParameters = PDOMTemplateParameterArray.createPDOMTemplateParameters(linkage, this, origParams);
|
||||
final Database db = getDB();
|
||||
long rec= PDOMTemplateParameterArray.putArray(db, fParameters);
|
||||
db.putRecPtr(record + TEMPLATE_PARAMS, rec);
|
||||
linkage.new ConfigureAliasTemplateSpecialization(aliasTemplateSpec, this);
|
||||
}
|
||||
|
||||
public PDOMCPPAliasTemplateSpecialization(PDOMCPPLinkage linkage, long record) {
|
||||
super(linkage, record);
|
||||
}
|
||||
|
||||
public void initData(IType aliasedType) {
|
||||
try {
|
||||
getLinkage().storeType(record + ALIASED_TYPE, aliasedType);
|
||||
} catch (CoreException e) {
|
||||
CCorePlugin.log(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getRecordSize() {
|
||||
return RECORD_SIZE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getNodeType() {
|
||||
return IIndexCPPBindingConstants.CPP_ALIAS_TEMPLATE_SPECIALIZATION;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSameType(IType type) {
|
||||
if (type == null) {
|
||||
return false;
|
||||
}
|
||||
return type.isSameType(getType());
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPDOMCPPTemplateParameter[] getTemplateParameters() {
|
||||
if (fParameters == null) {
|
||||
try {
|
||||
Database db = getDB();
|
||||
long rec= db.getRecPtr(record + TEMPLATE_PARAMS);
|
||||
if (rec == 0) {
|
||||
fParameters= IPDOMCPPTemplateParameter.EMPTY_ARRAY;
|
||||
} else {
|
||||
fParameters= PDOMTemplateParameterArray.getArray(this, rec);
|
||||
}
|
||||
} catch (CoreException e) {
|
||||
CCorePlugin.log(e);
|
||||
fParameters = IPDOMCPPTemplateParameter.EMPTY_ARRAY;
|
||||
}
|
||||
}
|
||||
return fParameters;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IType getType() {
|
||||
try {
|
||||
return getLinkage().loadType(record + ALIASED_TYPE);
|
||||
} catch (CoreException e) {
|
||||
CCorePlugin.log(e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object clone() {
|
||||
try {
|
||||
return super.clone();
|
||||
} catch (CloneNotSupportedException e) {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -515,6 +515,32 @@ class PDOMCPPLinkage extends PDOMLinkage implements IIndexCPPBindingConstants {
|
|||
}
|
||||
}
|
||||
|
||||
class ConfigureAliasTemplateSpecialization implements Runnable {
|
||||
private final PDOMCPPAliasTemplateSpecialization fTemplate;
|
||||
private final IPDOMCPPTemplateParameter[] fTemplateParameters;
|
||||
private final ICPPTemplateParameter[] fOriginalTemplateParameters;
|
||||
private final IType fOriginalAliasedType;
|
||||
|
||||
public ConfigureAliasTemplateSpecialization(ICPPAliasTemplate original,
|
||||
PDOMCPPAliasTemplateSpecialization template) throws DOMException {
|
||||
fTemplate = template;
|
||||
fTemplateParameters= template.getTemplateParameters();
|
||||
fOriginalTemplateParameters= original.getTemplateParameters();
|
||||
fOriginalAliasedType= original.getType();
|
||||
postProcesses.add(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
for (int i = 0; i < fOriginalTemplateParameters.length; i++) {
|
||||
final IPDOMCPPTemplateParameter tp = fTemplateParameters[i];
|
||||
if (tp != null)
|
||||
tp.configure(fOriginalTemplateParameters[i]);
|
||||
}
|
||||
fTemplate.initData(fOriginalAliasedType);
|
||||
}
|
||||
}
|
||||
|
||||
class ConfigureInstance implements Runnable {
|
||||
PDOMCPPSpecialization fInstance;
|
||||
|
||||
|
@ -933,6 +959,8 @@ class PDOMCPPLinkage extends PDOMLinkage implements IIndexCPPBindingConstants {
|
|||
result= new PDOMCPPClassTemplateSpecialization(this, parent, (ICPPClassTemplate) special, orig);
|
||||
} else if (special instanceof ICPPClassType) {
|
||||
result= new PDOMCPPClassSpecialization(this, parent, (ICPPClassType) special, orig);
|
||||
} else if (special instanceof ICPPAliasTemplate) {
|
||||
result= new PDOMCPPAliasTemplateSpecialization(this, parent, (ICPPAliasTemplate) special, orig);
|
||||
} else if (special instanceof ITypedef) {
|
||||
result= new PDOMCPPTypedefSpecialization(this, parent, (ITypedef) special, orig);
|
||||
} else if (special instanceof ICPPUsingDeclaration) {
|
||||
|
@ -1023,6 +1051,8 @@ class PDOMCPPLinkage extends PDOMLinkage implements IIndexCPPBindingConstants {
|
|||
return CPP_CLASS_TEMPLATE_SPECIALIZATION;
|
||||
} else if (binding instanceof ICPPClassType) {
|
||||
return CPP_CLASS_SPECIALIZATION;
|
||||
} else if (binding instanceof ICPPAliasTemplate) {
|
||||
return CPP_ALIAS_TEMPLATE_SPECIALIZATION;
|
||||
} else if (binding instanceof ITypedef) {
|
||||
return CPP_TYPEDEF_SPECIALIZATION;
|
||||
}
|
||||
|
@ -1329,6 +1359,8 @@ class PDOMCPPLinkage extends PDOMLinkage implements IIndexCPPBindingConstants {
|
|||
return new PDOMCPPVariableTemplatePartialSpecialization(this, record);
|
||||
case CPP_FIELD_TEMPLATE_PARTIAL_SPECIALIZATION:
|
||||
return new PDOMCPPFieldTemplatePartialSpecialization(this, record);
|
||||
case CPP_ALIAS_TEMPLATE_SPECIALIZATION:
|
||||
return new PDOMCPPAliasTemplateSpecialization(this, record);
|
||||
}
|
||||
assert false : "nodeid= " + nodeType; //$NON-NLS-1$
|
||||
return null;
|
||||
|
|
|
@ -625,7 +625,7 @@ public class CompletionTests extends CompletionTestBase {
|
|||
// C<A>::/*cursor*/
|
||||
// }
|
||||
public void testAliasTemplate_418479() throws Exception {
|
||||
final String[] expected = { "D", "E" };
|
||||
final String[] expected = { "D", "E<typename T>" };
|
||||
assertCompletionResults(fCursorOffset, expected, ID);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue