blob: 22f8e0606472c107082d72a86b1863e280634ff7 [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) - 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;
}
@Override
public final String getName() {
return new String(getNameCharArray());
}
@Override
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;
}
@Override
public int getParameterID() {
return fParameterID;
}
@Override
public short getParameterPosition() {
return (short) fParameterID;
}
@Override
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;
}
@Override
public IScope getScope() {
return CPPVisitor.getContainingScope(getPrimaryDeclaration());
}
@Override
public String[] getQualifiedName() {
return new String[] { getName() };
}
@Override
public char[][] getQualifiedNameCharArray() {
return new char[][] { getNameCharArray() };
}
@Override
public boolean isGloballyQualified() {
return false;
}
@Override
public IASTName[] getDeclarations() {
return declarations;
}
@Override
public IASTNode getDefinition() {
if (declarations != null && declarations.length > 0)
return declarations[0];
return null;
}
@Override
public void addDefinition(IASTNode node) {
addDeclaration(node);
}
@Override
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 = ArrayUtil.prepend(IASTName.class, declarations, name);
} else {
declarations = ArrayUtil.append(IASTName.class, declarations, name);
}
}
}
@Override
public ILinkage getLinkage() {
return Linkage.CPP_LINKAGE;
}
@Override
public String toString() {
return getName();
}
@Override
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);
}
@Override
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 ICPPTemplateParameterOwner) {
return ((ICPPTemplateParameterOwner) 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);
}
}