| /******************************************************************************* |
| * 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); |
| } |
| } |