/******************************************************************************* * 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) * IBM Corporation *******************************************************************************/ package org.eclipse.cdt.internal.core.pdom.dom.cpp; import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.dom.ast.DOMException; import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.IValue; import org.eclipse.cdt.core.dom.ast.cpp.ICPPParameter; import org.eclipse.cdt.core.dom.ast.cpp.ICPPParameterPackType; import org.eclipse.cdt.core.index.IIndexFile; import org.eclipse.cdt.core.parser.util.CharArrayUtils; import org.eclipse.cdt.internal.core.index.IIndexCPPBindingConstants; import org.eclipse.cdt.internal.core.index.IIndexFragment; import org.eclipse.cdt.internal.core.index.IIndexScope; import org.eclipse.cdt.internal.core.pdom.db.Database; import org.eclipse.cdt.internal.core.pdom.dom.IPDOMBinding; import org.eclipse.cdt.internal.core.pdom.dom.PDOMLinkage; import org.eclipse.cdt.internal.core.pdom.dom.PDOMNamedNode; import org.eclipse.cdt.internal.core.pdom.dom.PDOMNode; import org.eclipse.cdt.internal.core.pdom.dom.c.PDOMCAnnotation; import org.eclipse.core.runtime.CoreException; /** * Binding for a parameter of a c++ function in the index. */ class PDOMCPPParameter extends PDOMNamedNode implements ICPPParameter, IPDOMBinding { private static final int NEXT_PARAM = PDOMNamedNode.RECORD_SIZE; private static final int ANNOTATIONS = NEXT_PARAM + Database.PTR_SIZE; private static final int FLAGS = ANNOTATIONS + 1; @SuppressWarnings("hiding") protected static final int RECORD_SIZE = FLAGS + 1; static { assert RECORD_SIZE <= 22; // 23 would yield a 32-byte block } private static final byte FLAG_DEFAULT_VALUE = 0x1; private final IType fType; public PDOMCPPParameter(PDOMLinkage linkage, long record, IType type) { super(linkage, record); fType= type; } public PDOMCPPParameter(PDOMLinkage linkage, PDOMNode parent, ICPPParameter param, PDOMCPPParameter next) throws CoreException { super(linkage, parent, param.getNameCharArray()); fType= null; // this constructor is used for adding parameters to the database, only. Database db = getDB(); db.putByte(record + FLAGS, param.hasDefaultValue() ? FLAG_DEFAULT_VALUE : 0); db.putRecPtr(record + NEXT_PARAM, next == null ? 0 : next.getRecord()); storeAnnotations(db, param); } private void storeAnnotations(Database db, ICPPParameter param) throws CoreException { byte annotations = PDOMCPPAnnotation.encodeAnnotation(param); db.putByte(record + ANNOTATIONS, annotations); } public void update(ICPPParameter newPar) throws CoreException { final Database db = getDB(); // Bug 297438: Don't clear the property of having a default value. if (newPar.hasDefaultValue()) { db.putByte(record + FLAGS, FLAG_DEFAULT_VALUE); } else if (newPar.isParameterPack()) { db.putByte(record + FLAGS, (byte) 0); } storeAnnotations(db, newPar); final char[] newName = newPar.getNameCharArray(); if (!CharArrayUtils.equals(newName, getNameCharArray())) { updateName(newName); } } @Override protected int getRecordSize() { return RECORD_SIZE; } @Override public int getNodeType() { return IIndexCPPBindingConstants.CPPPARAMETER; } public String[] getQualifiedName() { return new String[] {getName()}; } public char[][] getQualifiedNameCharArray() throws DOMException { return new char[][]{getNameCharArray()}; } public boolean isGloballyQualified() { return false; } public boolean isMutable() { // ISO/IEC 14882:2003 7.1.1.8 return false; } public IType getType() { return fType; } public boolean isAuto() { // ISO/IEC 14882:2003 7.1.1.2 byte flag = 1<<PDOMCAnnotation.AUTO_OFFSET; return hasFlag(flag, true, ANNOTATIONS); } public boolean isExtern() { // ISO/IEC 14882:2003 7.1.1.5 return false; } public boolean isExternC() { return false; } public boolean isRegister() { // ISO/IEC 14882:2003 7.1.1.2 byte flag = 1<<PDOMCAnnotation.REGISTER_OFFSET; return hasFlag(flag, true, ANNOTATIONS); } public boolean isStatic() { // ISO/IEC 14882:2003 7.1.1.4 return false; } public String getName() { return new String(getNameCharArray()); } public IIndexScope getScope() { return null; } @SuppressWarnings("rawtypes") public Object getAdapter(Class adapter) { return null; } @Override public char[] getNameCharArray() { try { return super.getNameCharArray(); } catch (CoreException e) { CCorePlugin.log(e); return new char[0]; } } public boolean hasDefaultValue() { return hasFlag(FLAG_DEFAULT_VALUE, false, FLAGS); } public boolean isParameterPack() { return getType() instanceof ICPPParameterPackType; } private boolean hasFlag(byte flag, boolean defValue, int offset) { try { byte myflags= getDB().getByte(record + offset); return (myflags & flag) == flag; } catch (CoreException e) { CCorePlugin.log(e); } return defValue; } public IIndexFragment getFragment() { return getPDOM(); } public boolean hasDefinition() throws CoreException { // parameter bindings do not span index fragments return true; } public boolean hasDeclaration() throws CoreException { // parameter bindings do not span index fragments return true; } public int getBindingConstant() { return getNodeType(); } @Override public void delete(PDOMLinkage linkage) throws CoreException { PDOMCPPParameter p= this; for (;;) { long rec = p.getNextPtr(); p.flatDelete(linkage); if (rec == 0) return; p= new PDOMCPPParameter(linkage, rec, null); } } private void flatDelete(PDOMLinkage linkage) throws CoreException { super.delete(linkage); } public long getNextPtr() throws CoreException { long rec = getDB().getRecPtr(record + NEXT_PARAM); return rec; } public boolean isFileLocal() throws CoreException { return false; } public IIndexFile getLocalToFile() throws CoreException { return null; } public IValue getInitialValue() { return null; } }