diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPAliasTemplateSpecialization.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPAliasTemplateSpecialization.java new file mode 100644 index 00000000000..84398bdaf15 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPAliasTemplateSpecialization.java @@ -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; + } +} 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 75a83d7d672..0c9591ddbec 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 @@ -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()); } } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/HeuristicResolver.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/HeuristicResolver.java index 1b51d0bc107..366d32c0464 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/HeuristicResolver.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/HeuristicResolver.java @@ -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; 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 cc005df8d14..8e422605725 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 @@ -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; } 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 16b3ac21b51..a90d9393397 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 @@ -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$ } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPAliasTemplateSpecialization.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPAliasTemplateSpecialization.java new file mode 100644 index 00000000000..868ff5bb018 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPAliasTemplateSpecialization.java @@ -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; + } +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPAliasTemplateSpecialization.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPAliasTemplateSpecialization.java new file mode 100644 index 00000000000..8d3b58859c7 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPAliasTemplateSpecialization.java @@ -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; + } +} 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 a61e6691603..8ced0892f45 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 @@ -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; 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 3917fbb4ae0..978719a67f5 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 @@ -625,7 +625,7 @@ public class CompletionTests extends CompletionTestBase { // C::/*cursor*/ // } public void testAliasTemplate_418479() throws Exception { - final String[] expected = { "D", "E" }; + final String[] expected = { "D", "E" }; assertCompletionResults(fCursorOffset, expected, ID); }