blob: a9dc18ad23fa9eb67028f4475238796d6a6b0a1f [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2005, 2014 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
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Andrew Niefer (IBM Corporation) - Initial API and implementation
* Markus Schorn (Wind River Systems)
*******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp;
import org.eclipse.cdt.core.dom.ILinkage;
import org.eclipse.cdt.core.dom.ast.ASTNodeProperty;
import org.eclipse.cdt.core.dom.ast.ASTTypeUtil;
import org.eclipse.cdt.core.dom.ast.IASTCompositeTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTElaboratedTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IScope;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTElaboratedTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateDeclaration;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateParameter;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassTemplate;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateArgument;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateDefinition;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateInstance;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter;
import org.eclipse.cdt.core.index.IIndex;
import org.eclipse.cdt.core.index.IIndexBinding;
import org.eclipse.cdt.core.parser.util.ArrayUtil;
import org.eclipse.cdt.core.parser.util.ObjectMap;
import org.eclipse.cdt.internal.core.dom.Linkage;
import org.eclipse.cdt.internal.core.dom.parser.ASTInternal;
import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
import org.eclipse.cdt.internal.core.dom.parser.ProblemBinding;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPTemplates;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor;
import org.eclipse.core.runtime.PlatformObject;
public abstract class CPPTemplateDefinition extends PlatformObject implements ICPPTemplateDefinition, ICPPInternalTemplate {
public static final class CPPTemplateProblem extends ProblemBinding implements ICPPTemplateDefinition {
public CPPTemplateProblem(IASTNode node, int id, char[] arg) {
super(node, id, arg);
}
@Override
public ICPPTemplateParameter[] getTemplateParameters() {
return ICPPTemplateParameter.EMPTY_TEMPLATE_PARAMETER_ARRAY;
}
}
protected IASTName[] declarations;
protected IASTName definition;
private ICPPTemplateParameter[] templateParameters;
private ObjectMap instances;
private ICPPClassTemplate indexBinding;
private boolean checkedIndex;
public CPPTemplateDefinition(IASTName name) {
if (name != null) {
ASTNodeProperty prop = name.getPropertyInParent();
if (prop == ICPPASTQualifiedName.SEGMENT_NAME) {
prop = name.getParent().getPropertyInParent();
}
if (prop == IASTCompositeTypeSpecifier.TYPE_NAME) {
definition = name;
} else if (prop == IASTElaboratedTypeSpecifier.TYPE_NAME) {
declarations = new IASTName[] { name };
} else {
IASTNode parent = name.getParent();
while (!(parent instanceof IASTDeclaration))
parent = parent.getParent();
if (parent instanceof IASTFunctionDefinition) {
definition = name;
} else {
declarations = new IASTName[] { name };
}
}
}
}
@Override
public final void addInstance(ICPPTemplateArgument[] arguments, ICPPTemplateInstance instance) {
if (instances == null)
instances = new ObjectMap(2);
String key= ASTTypeUtil.getArgumentListString(arguments, true);
instances.put(key, instance);
}
@Override
public final ICPPTemplateInstance getInstance(ICPPTemplateArgument[] arguments) {
if (instances != null) {
String key= ASTTypeUtil.getArgumentListString(arguments, true);
ICPPTemplateInstance cand = (ICPPTemplateInstance) instances.get(key);
if (cand != null)
return cand;
}
final ICPPClassTemplate ib = getIndexBinding();
if (ib instanceof ICPPInstanceCache) {
ICPPTemplateInstance cand= ((ICPPInstanceCache) ib).getInstance(arguments);
if (cand instanceof IIndexBinding) {
if (getTemplateName().getTranslationUnit().getIndexFileSet().containsDeclaration((IIndexBinding) cand)) {
return cand;
}
} else {
return cand;
}
}
return null;
}
protected ICPPClassTemplate getIndexBinding() {
if (!checkedIndex) {
checkedIndex= true;
IASTName name= getTemplateName();
if (name != null) {
IASTTranslationUnit tu = name.getTranslationUnit();
if (tu != null) {
IIndex index= tu.getIndex();
if (index != null) {
IIndexBinding ib = index.adaptBinding(this);
if (ib instanceof ICPPClassTemplate)
indexBinding= (ICPPClassTemplate) ib;
}
}
}
}
return indexBinding;
}
@Override
public ICPPTemplateInstance[] getAllInstances() {
if (instances != null) {
ICPPTemplateInstance[] result= new ICPPTemplateInstance[instances.size()];
for (int i= 0; i < instances.size(); i++) {
result[i]= (ICPPTemplateInstance) instances.getAt(i);
}
return result;
}
return ICPPTemplateInstance.EMPTY_TEMPLATE_INSTANCE_ARRAY;
}
public IASTName getTemplateName() {
if (definition != null)
return definition;
if (declarations != null && declarations.length > 0)
return declarations[0];
return null;
}
@Override
public String getName() {
return new String(getNameCharArray());
}
@Override
public char[] getNameCharArray() {
return getTemplateName().getSimpleID();
}
@Override
public IScope getScope() {
return CPPVisitor.getContainingScope(getTemplateName());
}
@Override
public String[] getQualifiedName() {
return CPPVisitor.getQualifiedName(this);
}
@Override
public char[][] getQualifiedNameCharArray() {
return CPPVisitor.getQualifiedNameCharArray(this);
}
@Override
public boolean isGloballyQualified() {
return true;
}
@Override
public ICPPTemplateParameter[] getTemplateParameters() {
if (templateParameters == null) {
ICPPTemplateParameter[] result = ICPPTemplateParameter.EMPTY_TEMPLATE_PARAMETER_ARRAY;
ICPPASTTemplateDeclaration template = CPPTemplates.getTemplateDeclaration(getTemplateName());
if (template != null) {
ICPPASTTemplateParameter[] params = template.getTemplateParameters();
for (ICPPASTTemplateParameter param : params) {
IBinding p= CPPTemplates.getTemplateParameterName(param).resolveBinding();
if (p instanceof ICPPTemplateParameter) {
result = ArrayUtil.append(result, (ICPPTemplateParameter) p);
}
}
}
templateParameters = ArrayUtil.trim(result);
}
return templateParameters;
}
@Override
public void addDefinition(IASTNode node) {
if (node instanceof ICPPASTCompositeTypeSpecifier) {
node = ((ICPPASTCompositeTypeSpecifier) node).getName();
if (node instanceof ICPPASTQualifiedName) {
node = ((ICPPASTQualifiedName) node).getLastName();
}
}
if (!(node instanceof IASTName))
return;
updateTemplateParameterBindings((IASTName) node);
definition = (IASTName) node;
}
@Override
public void addDeclaration(IASTNode node) {
if (node instanceof ICPPASTElaboratedTypeSpecifier) {
node = ((ICPPASTElaboratedTypeSpecifier) node).getName();
if (node instanceof ICPPASTQualifiedName) {
node = ((ICPPASTQualifiedName) node).getLastName();
}
}
if (!(node instanceof IASTName))
return;
IASTName declName = (IASTName) node;
updateTemplateParameterBindings(declName);
if (declarations == null) {
declarations = new IASTName[] { declName };
} else {
// Keep the lowest offset declaration in [0].
if (declarations.length > 0 && ((ASTNode) node).getOffset() < ((ASTNode) declarations[0]).getOffset()) {
declarations = ArrayUtil.prepend(IASTName.class, declarations, declName);
} else {
declarations = ArrayUtil.append(IASTName.class, declarations, declName);
}
}
}
@Override
public IBinding resolveTemplateParameter(ICPPTemplateParameter templateParameter) {
int pos= templateParameter.getParameterPosition();
int tdeclLen= declarations == null ? 0 : declarations.length;
for (int i= -1; i < tdeclLen; i++) {
IASTName tdecl;
if (i == -1) {
tdecl= definition;
if (tdecl == null)
continue;
} else {
tdecl= declarations[i];
if (tdecl == null)
break;
}
ICPPASTTemplateParameter[] params = CPPTemplates.getTemplateDeclaration(tdecl).getTemplateParameters();
if (pos < params.length) {
final IASTName oName = CPPTemplates.getTemplateParameterName(params[pos]);
return oName.resolvePreBinding();
}
}
return templateParameter;
}
final protected void updateTemplateParameterBindings(IASTName name) {
final ICPPASTTemplateDeclaration templateDeclaration = CPPTemplates.getTemplateDeclaration(name);
if (templateDeclaration == null)
return;
ICPPASTTemplateParameter[] updateParams = templateDeclaration.getTemplateParameters();
int k= 0;
int tdeclLen= declarations == null ? 0 : declarations.length;
for (int i= -1; i < tdeclLen && k < updateParams.length; i++) {
IASTName tdecl;
if (i == -1) {
tdecl= definition;
if (tdecl == null)
continue;
} else {
tdecl= declarations[i];
if (tdecl == null)
break;
}
ICPPASTTemplateParameter[] params = CPPTemplates.getTemplateDeclaration(tdecl).getTemplateParameters();
int end= Math.min(params.length, updateParams.length);
for (; k < end; k++) {
final IASTName oName = CPPTemplates.getTemplateParameterName(params[k]);
IBinding b= oName.resolvePreBinding();
IASTName n = CPPTemplates.getTemplateParameterName(updateParams[k]);
n.setBinding(b);
ASTInternal.addDeclaration(b, n);
}
}
}
@Override
public IASTNode[] getDeclarations() {
return declarations;
}
@Override
public IASTNode getDefinition() {
return definition;
}
@Override
public ILinkage getLinkage() {
return Linkage.CPP_LINKAGE;
}
@Override
public final IBinding getOwner() {
IASTName templateName= getTemplateName();
if (templateName == null)
return null;
return CPPVisitor.findNameOwner(templateName, false);
}
}