/*******************************************************************************
* Copyright (c) 2006, 2009 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)
* IBM Corporation
*******************************************************************************/
package org.eclipse.cdt.internal.core.pdom.dom.c;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.dom.ast.DOMException;
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.Util;
import org.eclipse.cdt.internal.core.dom.parser.ITypeContainer;
import org.eclipse.cdt.internal.core.index.IIndexCBindingConstants;
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 PDOMCTypedef extends PDOMBinding implements ITypedef, ITypeContainer, IIndexType {
private static final int TYPE_OFFSET = PDOMBinding.RECORD_SIZE + 0;
@SuppressWarnings("hiding")
protected static final int RECORD_SIZE = TYPE_OFFSET + Database.TYPE_SIZE;
public PDOMCTypedef(PDOMLinkage linkage, PDOMNode parent, ITypedef typedef)
throws CoreException {
super(linkage, parent, typedef.getNameCharArray());
try {
IType type = typedef.getType();
setType(parent.getLinkage(), type);
} catch (DOMException e) {
throw new CoreException(Util.createStatus(e));
}
}
public PDOMCTypedef(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;
try {
setType(linkage, td.getType());
} catch (DOMException e) {
throw new CoreException(Util.createStatus(e));
}
}
}
private void setType(final PDOMLinkage linkage, IType newType) throws CoreException, DOMException {
linkage.storeType(record+TYPE_OFFSET, newType);
if (introducesRecursion(getType(), getNameCharArray())) {
linkage.storeType(record+TYPE_OFFSET, null);
}
}
private boolean introducesRecursion(IType type, char[] tdname) throws DOMException {
int maxDepth= 50;
while (--maxDepth > 0) {
if (type instanceof ITypedef && CharArrayUtils.equals(((ITypedef) type).getNameCharArray(), tdname)) {
return true;
}
if (type instanceof ITypeContainer) {
type= ((ITypeContainer) type).getType();
}
else if (type instanceof IFunctionType) {
IFunctionType ft= (IFunctionType) type;
if (introducesRecursion(ft.getReturnType(), tdname)) {
return true;
}
IType[] params= ft.getParameterTypes();
for (IType param : params) {
if (introducesRecursion(param, tdname)) {
return true;
}
}
return false;
}
else {
return false;
}
}
return true;
}
@Override
protected int getRecordSize() {
return RECORD_SIZE;
}
@Override
public int getNodeType() {
return IIndexCBindingConstants.CTYPEDEF;
}
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();
}
return myrtype.isSameType(type);
}
@Override
protected String toStringBase() {
return getName() + ": " + super.toStringBase(); //$NON-NLS-1$
}
public void setType(IType type) {
throw new UnsupportedOperationException();
}
@Override
public Object clone() {
throw new UnsupportedOperationException();
}
}