/*******************************************************************************
* Copyright (c) 2008, 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:
* Bryan Wilkinson (QNX) - Initial API and implementation
* Andrew Ferguson (Symbian)
* 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.DOMException;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPSpecialization;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateInstance;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap;
import org.eclipse.cdt.internal.core.index.IndexCPPSignatureUtil;
import org.eclipse.cdt.internal.core.pdom.dom.IPDOMBinding;
import org.eclipse.cdt.internal.core.pdom.dom.IPDOMOverloader;
import org.eclipse.cdt.internal.core.pdom.dom.PDOMLinkage;
import org.eclipse.cdt.internal.core.pdom.dom.PDOMNode;
import org.eclipse.core.runtime.CoreException;
/**
* Base class for specializations and instances of other bindings.
*/
abstract class PDOMCPPSpecialization extends PDOMCPPBinding implements ICPPSpecialization, IPDOMOverloader {
private static final int ARGMAP = PDOMCPPBinding.RECORD_SIZE + 0;
private static final int SIGNATURE_HASH = PDOMCPPBinding.RECORD_SIZE + 4;
private static final int SPECIALIZED = PDOMCPPBinding.RECORD_SIZE + 8;
/**
* The size in bytes of a PDOMCPPSpecialization record in the database.
*/
@SuppressWarnings("hiding")
protected static final int RECORD_SIZE = PDOMCPPBinding.RECORD_SIZE + 12;
private volatile IBinding fSpecializedCache;
private volatile ICPPTemplateParameterMap fArgMap;
public PDOMCPPSpecialization(PDOMCPPLinkage linkage, PDOMNode parent, ICPPSpecialization spec,
IPDOMBinding specialized) throws CoreException {
super(linkage, parent, spec.getNameCharArray());
getDB().putRecPtr(record + SPECIALIZED, specialized.getRecord());
// Specializations that are not instances have the same map as their owner.
if (this instanceof ICPPTemplateInstance) {
// Defer storing of template parameter map to the post-process
// to avoid infinite recursion when the evaluation of a non-type
// template argument tries to store its template definition.
// Until the post-process runs, temporarily store the input (possibly
// non-PDOM) map.
fArgMap = spec.getTemplateParameterMap();
linkage.new ConfigureInstance(this);
}
try {
Integer sigHash = IndexCPPSignatureUtil.getSignatureHash(spec);
getDB().putInt(record + SIGNATURE_HASH, sigHash != null ? sigHash.intValue() : 0);
} catch (DOMException e) {
}
}
public PDOMCPPSpecialization(PDOMLinkage linkage, long bindingRecord) {
super(linkage, bindingRecord);
}
@Override
public IBinding getSpecializedBinding() {
if (fSpecializedCache == null) {
try {
long specializedRec = getDB().getRecPtr(record + SPECIALIZED);
fSpecializedCache= loadSpecializedBinding(specializedRec);
} catch (CoreException e) {
CCorePlugin.log(e);
}
}
return fSpecializedCache;
}
protected IPDOMBinding loadSpecializedBinding(long specializedRec) throws CoreException {
return (IPDOMBinding) PDOMNode.load(getPDOM(), specializedRec);
}
@Override
public ICPPTemplateParameterMap getTemplateParameterMap() {
if (fArgMap == null) {
try {
if (this instanceof ICPPTemplateInstance) {
fArgMap= PDOMCPPTemplateParameterMap.getMap(this, getDB().getRecPtr(record + ARGMAP));
} else {
// specializations that are no instances have the same argmap as their owner.
IBinding owner= getOwner();
if (owner instanceof ICPPSpecialization) {
fArgMap= ((ICPPSpecialization) owner).getTemplateParameterMap();
}
}
} catch (CoreException e) {
CCorePlugin.log(e);
}
}
return fArgMap;
}
public void storeTemplateParameterMap() {
try {
// fArgMap here is the temporarily stored, possibly non-PDOM
// map stored by the constructor. Construct the PDOM map and
// store it.
long rec= PDOMCPPTemplateParameterMap.putMap(this, fArgMap);
getDB().putRecPtr(record + ARGMAP, rec);
// Read the stored map next time getTemplateParameterMap()
// is called.
fArgMap = null;
} catch (CoreException e) {
CCorePlugin.log(e);
}
}
@Override
public int getSignatureHash() throws CoreException {
return getDB().getInt(record + SIGNATURE_HASH);
}
}