/*******************************************************************************
* Copyright (c) 2006, 2014 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:
* QNX - Initial API and implementation
* IBM Corporation
* Andrew Ferguson (Symbian)
* Markus Schorn (Wind River Systems)
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.internal.core.pdom.dom.c;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IFunction;
import org.eclipse.cdt.core.dom.ast.IFunctionType;
import org.eclipse.cdt.core.dom.ast.IParameter;
import org.eclipse.cdt.core.dom.ast.IScope;
import org.eclipse.cdt.core.dom.ast.ISemanticProblem;
import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.internal.core.dom.parser.ProblemFunctionType;
import org.eclipse.cdt.internal.core.index.IIndexCBindingConstants;
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;
/**
* @author Doug Schaefer
*/
class PDOMCFunction extends PDOMBinding implements IFunction {
/**
* Offset of total number of function parameters (relative to the beginning of the record).
*/
public static final int NUM_PARAMS = PDOMBinding.RECORD_SIZE;
/**
* Offset of total number of function parameters (relative to the beginning of the record).
*/
public static final int FIRST_PARAM = NUM_PARAMS + 4;
/**
* Offset for the type of this function (relative to the beginning of the record).
*/
private static final int FUNCTION_TYPE = FIRST_PARAM + Database.PTR_SIZE;
/**
* Offset of annotation information (relative to the beginning of the record).
*/
private static final int ANNOTATIONS = FUNCTION_TYPE + Database.TYPE_SIZE; // byte
/**
* The size in bytes of a PDOMCPPFunction record in the database.
*/
@SuppressWarnings("hiding")
public static final int RECORD_SIZE = ANNOTATIONS + 1;
public PDOMCFunction(PDOMLinkage linkage, long record) {
super(linkage, record);
}
public PDOMCFunction(PDOMLinkage linkage, PDOMNode parent, IFunction function) throws CoreException {
super(linkage, parent, function.getNameCharArray());
IFunctionType type = function.getType();
setType(getLinkage(), type);
IParameter[] parameters = function.getParameters();
setParameters(parameters);
byte annotations = PDOMCAnnotations.encodeFunctionAnnotations(function);
getDB().putByte(record + ANNOTATIONS, annotations);
}
@Override
public void update(final PDOMLinkage linkage, IBinding newBinding, IASTNode point) throws CoreException {
if (!(newBinding instanceof IFunction))
return;
IFunction func= (IFunction) newBinding;
IFunctionType newType = func.getType();
setType(linkage, newType);
PDOMCParameter oldParams= getFirstParameter(null);
IParameter[] newParams = func.getParameters();
setParameters(newParams);
if (oldParams != null) {
oldParams.delete(linkage);
}
byte newAnnotation = PDOMCAnnotations.encodeFunctionAnnotations(func);
getDB().putByte(record + ANNOTATIONS, newAnnotation);
}
private void setType(PDOMLinkage linkage, IFunctionType ft) throws CoreException {
linkage.storeType(record + FUNCTION_TYPE, ft);
}
private void setParameters(IParameter[] params) throws CoreException {
final PDOMLinkage linkage = getLinkage();
final Database db= getDB();
db.putInt(record + NUM_PARAMS, params.length);
db.putRecPtr(record + FIRST_PARAM, 0);
PDOMCParameter next= null;
for (int i= params.length; --i >= 0;) {
next= new PDOMCParameter(linkage, this, params[i], next);
}
db.putRecPtr(record + FIRST_PARAM, next == null ? 0 : next.getRecord());
}
public PDOMCParameter getFirstParameter(IType t) throws CoreException {
long rec = getDB().getRecPtr(record + FIRST_PARAM);
return rec != 0 ? new PDOMCParameter(getLinkage(), rec, t) : null;
}
@Override
protected int getRecordSize() {
return RECORD_SIZE;
}
@Override
public int getNodeType() {
return IIndexCBindingConstants.CFUNCTION;
}
@Override
public IFunctionType getType() {
try {
return (IFunctionType) getLinkage().loadType(record + FUNCTION_TYPE);
} catch (CoreException e) {
CCorePlugin.log(e);
return new ProblemFunctionType(ISemanticProblem.TYPE_NOT_PERSISTED);
}
}
@Override
public boolean isStatic() {
return PDOMCAnnotations.isStatic(getAnnotations());
}
@Override
public boolean isExtern() {
return PDOMCAnnotations.isExtern(getAnnotations());
}
@Override
public IParameter[] getParameters() {
try {
PDOMLinkage linkage= getLinkage();
Database db= getDB();
IFunctionType ft = getType();
IType[] ptypes= ft == null ? IType.EMPTY_TYPE_ARRAY : ft.getParameterTypes();
int n = db.getInt(record + NUM_PARAMS);
IParameter[] result = new IParameter[n];
long next = db.getRecPtr(record + FIRST_PARAM);
for (int i = 0; i < n && next != 0; i++) {
IType type= i < ptypes.length ? ptypes[i] : null;
final PDOMCParameter par = new PDOMCParameter(linkage, next, type);
next= par.getNextPtr();
result[i]= par;
}
return result;
} catch (CoreException e) {
CCorePlugin.log(e);
return IParameter.EMPTY_PARAMETER_ARRAY;
}
}
@Override
public boolean isAuto() {
// ISO/IEC 9899:TC1 6.9.1.4
return false;
}
@Override
public boolean isRegister() {
// ISO/IEC 9899:TC1 6.9.1.4
return false;
}
@Override
public boolean isInline() {
return PDOMCAnnotations.isInline(getAnnotations());
}
private byte getAnnotations() {
return getByte(record + ANNOTATIONS);
}
@Override
public boolean takesVarArgs() {
return PDOMCAnnotations.isVarargsFunction(getAnnotations());
}
@Override
public boolean isNoReturn() {
return PDOMCAnnotations.isNoReturnFunction(getAnnotations());
}
@Override
public IScope getFunctionScope() {
return null;
}
}