blob: 23e42cc6ca99dc171ccdad364af0363b7a8eaba6 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2013, 2014 Nathan Ridge 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:
* Nathan Ridge - Initial API and implementation
* Marc-Andre Laperle (Ericsson)
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp;
import org.eclipse.cdt.core.dom.ast.IBasicType;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IEnumerator;
import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.ITypedef;
import org.eclipse.cdt.core.dom.ast.IValue;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassSpecialization;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPEnumeration;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPEnumerationSpecialization;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPScope;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPSpecialization;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap;
import org.eclipse.cdt.internal.core.dom.parser.ASTEnumerator;
import org.eclipse.cdt.internal.core.dom.parser.IntegralValue;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPTemplates;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil;
/**
* Binding for a specialization of an enumeration.
*/
public class CPPEnumerationSpecialization extends CPPSpecialization implements ICPPEnumerationSpecialization {
private final IEnumerator[] fEnumerators;
private final IType fFixedType;
private boolean fInitializationComplete;
public static IBinding createInstance(ICPPEnumeration enumeration,
ICPPClassSpecialization owner, ICPPTemplateParameterMap tpMap) {
IType fixedType = enumeration.getFixedType();
if (fixedType != null) {
ICPPClassSpecialization within = CPPTemplates.getSpecializationContext(owner);
InstantiationContext context = new InstantiationContext(tpMap, within);
fixedType = CPPTemplates.instantiateType(fixedType, context);
}
CPPEnumerationSpecialization specializedEnumeration =
new CPPEnumerationSpecialization(enumeration, owner, tpMap, fixedType);
specializedEnumeration.initialize();
return specializedEnumeration;
}
private CPPEnumerationSpecialization(ICPPEnumeration specialized, IBinding owner,
ICPPTemplateParameterMap argumentMap, IType fixedType) {
super(specialized, owner, argumentMap);
fFixedType = fixedType;
fEnumerators = new IEnumerator[specialized.getEnumerators().length];
}
private void initialize() {
ICPPTemplateParameterMap tpMap = getTemplateParameterMap();
IEnumerator[] enumerators = getSpecializedBinding().getEnumerators();
IType previousInternalType = CPPBasicType.INT;
for (int i = 0; i < enumerators.length; ++i) {
IEnumerator enumerator = enumerators[i];
InstantiationContext context = new InstantiationContext(tpMap, this);
IValue specializedValue =
CPPTemplates.instantiateValue(enumerator.getValue(), context, IntegralValue.MAX_RECURSION_DEPTH);
IType internalType = null;
if (fFixedType == null && enumerator instanceof ICPPInternalEnumerator) {
internalType = ((ICPPInternalEnumerator) enumerator).getInternalType();
if (internalType != null) {
internalType = CPPTemplates.instantiateType(internalType, context);
} else if (previousInternalType instanceof IBasicType) {
internalType = ASTEnumerator.getTypeOfIncrementedValue(
(IBasicType) previousInternalType, specializedValue);
}
if (internalType != null) {
previousInternalType = internalType;
}
}
fEnumerators[i] = new CPPEnumeratorSpecialization(enumerator, this, tpMap, specializedValue,
internalType);
}
fInitializationComplete = true;
}
public boolean isInitializing() {
return !fInitializationComplete;
}
@Override
public ICPPEnumeration getSpecializedBinding() {
return (ICPPEnumeration) super.getSpecializedBinding();
}
@Override
public IEnumerator[] getEnumerators() {
return fEnumerators;
}
@Override
public long getMinValue() {
return SemanticUtil.computeMinValue(this);
}
@Override
public long getMaxValue() {
return SemanticUtil.computeMaxValue(this);
}
@Override
public boolean isSameType(IType type) {
if (type == this)
return true;
if (type instanceof ITypedef)
return type.isSameType(this);
if (!(type instanceof ICPPEnumerationSpecialization))
return false;
ICPPEnumerationSpecialization otherEnumSpec = (ICPPEnumerationSpecialization) type;
return getSpecializedBinding().isSameType(otherEnumSpec.getSpecializedBinding())
&& ((IType) getOwner()).isSameType((IType) otherEnumSpec.getOwner());
}
@Override
public boolean isScoped() {
return getSpecializedBinding().isScoped();
}
@Override
public IType getFixedType() {
return fFixedType;
}
@Override
public ICPPScope asScope() {
// TODO(nathanridge): Do we need a CPPEnumSpecializationScope?
return getSpecializedBinding().asScope();
}
@Override
public Object clone() {
throw new IllegalArgumentException("Enums must not be cloned"); //$NON-NLS-1$
}
@Override
public IEnumerator specializeEnumerator(IEnumerator enumerator) {
if (enumerator instanceof ICPPSpecialization && ((ICPPSpecialization) enumerator).getOwner() == this) {
return enumerator;
}
// The specialized enumerators are already computed, just need to look up the right one.
IEnumerator[] unspecializedEnumerators = getSpecializedBinding().getEnumerators();
for (int i = 0; i < fEnumerators.length; ++i) {
if (enumerator.equals(unspecializedEnumerators[i])) {
IEnumerator specializedEnumerator = fEnumerators[i];
return specializedEnumerator == null ? enumerator : specializedEnumerator;
}
}
return enumerator;
}
}