blob: c7f8728fc908e8f13475a03097c4310dff04ca7e [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2007, 2013 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:
* Bryan Wilkinson (QNX) - Initial API and implementation
* Markus Schorn (Wind River Systems)
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.internal.core.pdom.dom.cpp;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IFunctionType;
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.core.dom.ast.cpp.ICPPFunction;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionSpecialization;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPParameter;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPSpecialization;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateInstance;
import org.eclipse.cdt.internal.core.dom.parser.ProblemFunctionType;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPComputableFunction;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPExecution;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPTemplates;
import org.eclipse.cdt.internal.core.index.IIndexCPPBindingConstants;
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;
/**
* Binding for function specialization in the index.
*/
class PDOMCPPFunctionSpecialization extends PDOMCPPSpecialization
implements ICPPFunctionSpecialization, ICPPComputableFunction {
/** Offset of total number of function parameters (relative to the beginning of the record). */
private static final int NUM_PARAMS = PDOMCPPSpecialization.RECORD_SIZE;
/** Offset of pointer to the first parameter of this function (relative to the beginning of the record). */
private static final int FIRST_PARAM = NUM_PARAMS + 4;
/** Offset for type of this function (relative to the beginning of the record). */
private static final int FUNCTION_TYPE = FIRST_PARAM + Database.PTR_SIZE;
/** Offset of start of exception specification. */
protected static final int EXCEPTION_SPEC = FUNCTION_TYPE + Database.TYPE_SIZE; // int
/** Offset of annotation information (relative to the beginning of the record). */
private static final int ANNOTATION = EXCEPTION_SPEC + Database.PTR_SIZE; // short
/** Offset of the number of the required arguments. */
private static final int REQUIRED_ARG_COUNT = ANNOTATION + 2; // short
/** Offset of the function body execution for constexpr functions. */
private static final int FUNCTION_BODY = REQUIRED_ARG_COUNT + 2; // Database.EXECUTION_SIZE
/**
* The size in bytes of a PDOMCPPFunctionSpecialization record in the database.
*/
@SuppressWarnings("hiding")
protected static final int RECORD_SIZE = FUNCTION_BODY + Database.EXECUTION_SIZE;
private ICPPFunctionType fType; // No need for volatile, all fields of ICPPFunctionTypes are final.
private short fAnnotations= -1;
private int fRequiredArgCount= -1;
public PDOMCPPFunctionSpecialization(PDOMCPPLinkage linkage, PDOMNode parent, ICPPFunction astFunction,
PDOMBinding specialized, IASTNode point) throws CoreException {
super(linkage, parent, (ICPPSpecialization) astFunction, specialized);
Database db = getDB();
ICPPParameter[] astParams= astFunction.getParameters();
IFunctionType astFt= astFunction.getType();
if (astFt != null) {
getLinkage().storeType(record + FUNCTION_TYPE, astFt);
}
ICPPFunction origAstFunc= (ICPPFunction) ((ICPPSpecialization) astFunction).getSpecializedBinding();
ICPPParameter[] origAstParams= origAstFunc.getParameters();
if (origAstParams.length == 0) {
db.putInt(record + NUM_PARAMS, 0);
db.putRecPtr(record + FIRST_PARAM, 0);
} else {
final int length= astParams.length;
db.putInt(record + NUM_PARAMS, length);
db.putRecPtr(record + FIRST_PARAM, 0);
PDOMCPPParameter origPar= null;
PDOMCPPParameterSpecialization next= null;
for (int i= length; --i >= 0;) {
// There may be fewer or less original parameters, because of parameter packs.
if (i < origAstParams.length - 1) {
// Normal case
origPar= new PDOMCPPParameter(linkage, specialized, origAstParams[i], null);
} else if (origPar == null) {
// Use last parameter
origPar= new PDOMCPPParameter(linkage, specialized, origAstParams[origAstParams.length - 1], null);
}
next= new PDOMCPPParameterSpecialization(linkage, this, astParams[i], origPar, next);
}
db.putRecPtr(record + FIRST_PARAM, next == null ? 0 : next.getRecord());
}
fAnnotations = PDOMCPPAnnotations.encodeFunctionAnnotations(astFunction);
db.putShort(record + ANNOTATION, fAnnotations);
db.putShort(record + REQUIRED_ARG_COUNT , (short) astFunction.getRequiredArgumentCount());
long typelist= 0;
if (astFunction instanceof ICPPMethod && ((ICPPMethod) astFunction).isImplicit()) {
// Don't store the exception specification, it is computed on demand.
} else {
typelist = PDOMCPPTypeList.putTypes(this, astFunction.getExceptionSpecification());
}
db.putRecPtr(record + EXCEPTION_SPEC, typelist);
if (!(astFunction instanceof ICPPTemplateInstance)
|| ((ICPPTemplateInstance) astFunction).isExplicitSpecialization()) {
linkage.new ConfigureFunctionSpecialization(astFunction, this, point);
}
}
public PDOMCPPFunctionSpecialization(PDOMLinkage linkage, long bindingRecord) {
super(linkage, bindingRecord);
}
public void initData(ICPPExecution functionBody) {
if (functionBody == null)
return;
try {
getLinkage().storeExecution(record + FUNCTION_BODY, functionBody);
} catch (CoreException e) {
CCorePlugin.log(e);
}
}
@Override
protected int getRecordSize() {
return RECORD_SIZE;
}
@Override
public int getNodeType() {
return IIndexCPPBindingConstants.CPP_FUNCTION_SPECIALIZATION;
}
@Override
public boolean isInline() {
return PDOMCPPAnnotations.isInline(getAnnotations());
}
protected final short getAnnotations() {
if (fAnnotations == -1) {
try {
fAnnotations= getDB().getShort(record + ANNOTATION);
} catch (CoreException e) {
CCorePlugin.log(e);
fAnnotations= 0;
}
}
return fAnnotations;
}
@Override
public boolean isMutable() {
return false;
}
@Override
public IScope getFunctionScope() {
return null;
}
@Override
public ICPPParameter[] getParameters() {
try {
PDOMLinkage linkage= getLinkage();
Database db= getDB();
ICPPFunctionType ft = getType();
IType[] ptypes= ft == null ? IType.EMPTY_TYPE_ARRAY : ft.getParameterTypes();
int n = db.getInt(record + NUM_PARAMS);
ICPPParameter[] result = new ICPPParameter[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 PDOMCPPParameterSpecialization par =
new PDOMCPPParameterSpecialization(linkage, next, type);
next= par.getNextPtr();
result[i]= par;
}
return result;
} catch (CoreException e) {
CCorePlugin.log(e);
return ICPPParameter.EMPTY_CPPPARAMETER_ARRAY;
}
}
@Override
public ICPPFunctionType getType() {
if (fType == null) {
try {
fType= (ICPPFunctionType) getLinkage().loadType(record + FUNCTION_TYPE);
} catch (CoreException e) {
CCorePlugin.log(e);
fType= new ProblemFunctionType(ISemanticProblem.TYPE_NOT_PERSISTED);
}
}
return fType;
}
@Override
public boolean isAuto() {
// ISO/IEC 14882:2003 7.1.1.2
return false;
}
@Override
public boolean isConstexpr() {
return PDOMCPPAnnotations.isConstexpr(getAnnotations());
}
@Override
public boolean isExtern() {
return PDOMCPPAnnotations.isExtern(getAnnotations());
}
@Override
public boolean isExternC() {
return PDOMCPPAnnotations.isExternC(getAnnotations());
}
@Override
public boolean isRegister() {
// ISO/IEC 14882:2003 7.1.1.2
return false;
}
@Override
public boolean isStatic() {
return PDOMCPPAnnotations.isStatic(getAnnotations());
}
@Override
public boolean takesVarArgs() {
return PDOMCPPAnnotations.isVarargsFunction(getAnnotations());
}
@Override
public boolean isNoReturn() {
return PDOMCPPAnnotations.isNoReturnFunction(getAnnotations());
}
@Override
public int getRequiredArgumentCount() {
if (fRequiredArgCount == -1) {
try {
fRequiredArgCount= getDB().getShort(record + REQUIRED_ARG_COUNT );
} catch (CoreException e) {
fRequiredArgCount= 0;
}
}
return fRequiredArgCount;
}
@Override
public boolean hasParameterPack() {
return PDOMCPPAnnotations.hasParameterPack(getAnnotations());
}
@Override
public boolean isDeleted() {
return PDOMCPPAnnotations.isDeletedFunction(getAnnotations());
}
@Override
public int pdomCompareTo(PDOMBinding other) {
int cmp= super.pdomCompareTo(other);
return cmp == 0 ? PDOMCPPFunction.compareSignatures(this, other) : cmp;
}
@Override
public IType[] getExceptionSpecification() {
try {
final long rec = getPDOM().getDB().getRecPtr(record + EXCEPTION_SPEC);
return PDOMCPPTypeList.getTypes(this, rec);
} catch (CoreException e) {
CCorePlugin.log(e);
return null;
}
}
@Override
public ICPPExecution getFunctionBodyExecution(IASTNode point) {
if (!isConstexpr())
return null;
try {
ICPPExecution exec = getLinkage().loadExecution(record + FUNCTION_BODY);
if (exec == null) {
exec = CPPTemplates.instantiateFunctionBody(this, point);
}
return exec;
} catch (CoreException e) {
CCorePlugin.log(e);
return null;
}
}
}