/*******************************************************************************
* Copyright (c) 2006, 2010 QNX Software Systems 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:
* Doug Schaefer (QNX) - Initial API and implementation
* Markus Schorn (Wind River Systems)
*******************************************************************************/
package org.eclipse.cdt.internal.core.pdom.dom.cpp;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.dom.ast.ASTTypeUtil;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IFunctionType;
import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.ITypedef;
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
import org.eclipse.cdt.internal.core.dom.parser.ITypeContainer;
import org.eclipse.cdt.internal.core.index.CPPTypedefClone;
import org.eclipse.cdt.internal.core.index.IIndexCPPBindingConstants;
import org.eclipse.cdt.internal.core.index.IIndexType;
import org.eclipse.cdt.internal.core.pdom.db.Database;
import org.eclipse.cdt.internal.core.pdom.dom.PDOMBinding;
import org.eclipse.cdt.internal.core.pdom.dom.PDOMLinkage;
import org.eclipse.cdt.internal.core.pdom.dom.PDOMNode;
import org.eclipse.core.runtime.CoreException;
/**
* Typedefs for c++
*/
class PDOMCPPTypedef extends PDOMCPPBinding implements ITypedef, ITypeContainer, IIndexType {
private static final int TYPE_OFFSET = PDOMBinding.RECORD_SIZE;
@SuppressWarnings("hiding")
protected static final int RECORD_SIZE = TYPE_OFFSET + Database.TYPE_SIZE;
public PDOMCPPTypedef(PDOMLinkage linkage, PDOMNode parent, ITypedef typedef) throws CoreException {
super(linkage, parent, typedef.getNameCharArray());
setType(parent.getLinkage(), typedef.getType());
}
public PDOMCPPTypedef(PDOMLinkage linkage, long record) {
super(linkage, record);
}
@Override
public void update(final PDOMLinkage linkage, IBinding newBinding) throws CoreException {
if (newBinding instanceof ITypedef) {
ITypedef td= (ITypedef) newBinding;
setType(linkage, td.getType());
}
}
private void setType(final PDOMLinkage linkage, IType newType) throws CoreException {
linkage.storeType(record + TYPE_OFFSET, newType);
if (introducesRecursion(getType(), getParentNodeRec(), getNameCharArray())) {
linkage.storeType(record + TYPE_OFFSET, null);
}
}
static boolean introducesRecursion(IType type, long parentRec, char[] tdname) {
int maxDepth= 50;
while (--maxDepth > 0) {
if (type instanceof ITypedef) {
try {
if ((!(type instanceof PDOMNode) || // this should not be the case anyhow
((PDOMNode) type).getParentNodeRec() == parentRec) &&
CharArrayUtils.equals(((ITypedef) type).getNameCharArray(), tdname)) {
return true;
}
} catch (CoreException e) {
return true;
}
}
if (type instanceof ITypeContainer) {
type= ((ITypeContainer) type).getType();
} else if (type instanceof IFunctionType) {
IFunctionType ft= (IFunctionType) type;
if (introducesRecursion(ft.getReturnType(), parentRec, tdname)) {
return true;
}
IType[] params= ft.getParameterTypes();
for (IType param : params) {
if (introducesRecursion(param, parentRec, tdname)) {
return true;
}
}
return false;
} else {
return false;
}
}
return true;
}
@Override
protected int getRecordSize() {
return RECORD_SIZE;
}
@Override
public int getNodeType() {
return IIndexCPPBindingConstants.CPPTYPEDEF;
}
public IType getType() {
try {
return getLinkage().loadType(record + TYPE_OFFSET);
} catch (CoreException e) {
CCorePlugin.log(e);
return null;
}
}
public boolean isSameType(IType type) {
IType myrtype = getType();
if (myrtype == null)
return false;
if (type instanceof ITypedef) {
type= ((ITypedef)type).getType();
if (type == null) {
return false;
}
}
return myrtype.isSameType(type);
}
@Override
protected String toStringBase() {
return ASTTypeUtil.getQualifiedName(this) + " -> " + super.toStringBase(); //$NON-NLS-1$
}
public void setType(IType type) {
throw new UnsupportedOperationException();
}
@Override
public Object clone() {
return new CPPTypedefClone(this);
}
}