/******************************************************************************* * Copyright (c) 2005, 2011 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) - 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.IASTName; import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.IProblemBinding; import org.eclipse.cdt.core.dom.ast.IScope; import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateParameter; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplatedTypeTemplateParameter; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateDefinition; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter; import org.eclipse.cdt.core.parser.util.ArrayUtil; import org.eclipse.cdt.core.parser.util.CharArrayUtils; import org.eclipse.cdt.internal.core.dom.Linkage; 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; /** * Base implementation for template parameter bindings in the AST. */ public abstract class CPPTemplateParameter extends PlatformObject implements ICPPTemplateParameter, ICPPInternalBinding, ICPPTwoPhaseBinding { private IASTName[] declarations; private final int fParameterID; public CPPTemplateParameter(IASTName name) { declarations = new IASTName[] {name}; fParameterID= computeParameterID(name); } private int computeParameterID(IASTName name) { int nesting= 0; ICPPASTTemplateParameter tp= null; ICPPASTTemplateParameter[] tps= null; for (IASTNode node= name.getParent(); node != null; node= node.getParent()) { if (tp == null && node instanceof ICPPASTTemplateParameter) { tp= (ICPPASTTemplateParameter) node; } else if (node instanceof ICPPASTInternalTemplateDeclaration) { final ICPPASTInternalTemplateDeclaration tdecl= (ICPPASTInternalTemplateDeclaration) node; nesting+= tdecl.getNestingLevel(); if (tps == null) { tps= tdecl.getTemplateParameters(); } break; } else if (node instanceof ICPPASTTemplatedTypeTemplateParameter) { nesting++; if (tps == null) { tps= ((ICPPASTTemplatedTypeTemplateParameter) node).getTemplateParameters(); } } } int pos= 0; if (tps != null && tp != null) { for (int i = 0; i < tps.length; i++) { if (tps[i] == tp) { pos= i; break; } } } return (nesting << 16) + (pos & 0xffff); } @Override public Object clone() { IType t = null; try { t = (IType) super.clone(); } catch (CloneNotSupportedException e) { //not going to happen } return t; } /* (non-Javadoc) * @see org.eclipse.cdt.core.dom.ast.IBinding#getName() */ public final String getName() { return new String(getNameCharArray()); } /* (non-Javadoc) * @see org.eclipse.cdt.core.dom.ast.IBinding#getNameCharArray() */ public final char[] getNameCharArray() { // Search for the first declaration that has a name. for (IASTName decl : declarations) { if (decl == null) break; final char[] result= decl.getSimpleID(); if (result.length > 0) return result; } return CharArrayUtils.EMPTY; } public int getParameterID() { return fParameterID; } public short getParameterPosition() { return (short) fParameterID; } public short getTemplateNestingLevel() { return (short) (fParameterID >> 16); } public IASTName getPrimaryDeclaration () { return declarations[0]; } private ICPPASTTemplateParameter getASTTemplateParameter() { IASTNode node= declarations[0]; while (node != null && !(node instanceof ICPPASTTemplateParameter)) node= node.getParent(); assert node != null; return (ICPPASTTemplateParameter) node; } /* (non-Javadoc) * @see org.eclipse.cdt.core.dom.ast.IBinding#getScope() */ public IScope getScope() { return CPPVisitor.getContainingScope(getPrimaryDeclaration()); } /* (non-Javadoc) * @see org.eclipse.cdt.core.dom.ast.cpp.ICPPBinding#getQualifiedName() */ public String[] getQualifiedName() { return new String[] { getName() }; } /* (non-Javadoc) * @see org.eclipse.cdt.core.dom.ast.cpp.ICPPBinding#getQualifiedNameCharArray() */ public char[][] getQualifiedNameCharArray() { return new char[][] {getNameCharArray() }; } /* (non-Javadoc) * @see org.eclipse.cdt.core.dom.ast.cpp.ICPPBinding#isGloballyQualified() */ public boolean isGloballyQualified() { return false; } /* (non-Javadoc) * @see org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPInternalBinding#getDeclarations() */ public IASTName[] getDeclarations() { return declarations; } /* (non-Javadoc) * @see org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPInternalBinding#getDefinition() */ public IASTNode getDefinition() { if (declarations != null && declarations.length > 0) return declarations[0]; return null; } /* (non-Javadoc) * @see org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPInternalBinding#addDefinition(org.eclipse.cdt.core.dom.ast.IASTNode) */ public void addDefinition(IASTNode node) { addDeclaration(node); } /* (non-Javadoc) * @see org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPInternalBinding#addDeclaration(org.eclipse.cdt.core.dom.ast.IASTNode) */ public void addDeclaration(IASTNode node) { if (!(node instanceof IASTName)) return; IASTName name = (IASTName) node; if (declarations == null) { declarations = new IASTName[] { name }; } else { if (declarations.length > 0 && declarations[0] == node) return; // keep the lowest offset declaration in [0] if (declarations.length > 0 && ((ASTNode)node).getOffset() < ((ASTNode)declarations[0]).getOffset()) { declarations = (IASTName[]) ArrayUtil.prepend(IASTName.class, declarations, name); } else { declarations = (IASTName[]) ArrayUtil.append(IASTName.class, declarations, name); } } } public ILinkage getLinkage() { return Linkage.CPP_LINKAGE; } @Override public String toString() { return getName(); } public IBinding getOwner() { if (declarations == null || declarations.length == 0) return null; IASTNode node= declarations[0]; while (!(node instanceof ICPPASTTemplateParameter)) { if (node == null) return null; node= node.getParent(); } return CPPTemplates.getContainingTemplate((ICPPASTTemplateParameter) node); } public IBinding resolveFinalBinding(CPPASTNameBase name) { // check if the binding has been updated. IBinding current= name.getPreBinding(); if (current != this) return current; ICPPTemplateDefinition template= CPPTemplates.getContainingTemplate(getASTTemplateParameter()); if (template instanceof ICPPInternalTemplate) { return ((ICPPInternalTemplate) template).resolveTemplateParameter(this); } // problem finding the containing template if (template == null) { return this; } ICPPTemplateParameter[] params = template.getTemplateParameters(); final int pos= getParameterPosition(); if (pos < params.length) return params[pos]; return new ProblemBinding(getPrimaryDeclaration(), IProblemBinding.SEMANTIC_DEFINITION_NOT_FOUND); } }