/******************************************************************************* * Copyright (c) 2016 Institute for Software, HSR Hochschule fuer Technik * Rapperswil, University of applied sciences 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 *******************************************************************************/ package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics; import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.CVTYPE; import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.REF; import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.TDEF; import org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory; import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.IArrayType; import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.IValue; import org.eclipse.cdt.core.dom.ast.cpp.ICPPBasicType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap; import org.eclipse.cdt.internal.core.dom.parser.ITypeMarshalBuffer; import org.eclipse.cdt.internal.core.dom.parser.cpp.ClassTypeHelper; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation; import org.eclipse.cdt.internal.core.dom.parser.cpp.InstantiationContext; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalFunctionCall.ParameterPackType; import org.eclipse.core.runtime.CoreException; /** * Represents an access to a sub-value of a composite value, identified by an index. * Composite values can include arrays, structures, and parameter packs (see {@code CompositeValue}). */ public final class EvalCompositeAccess implements ICPPEvaluation { private final ICPPEvaluation parent; // The composite value being accessed private final int elementId; // The index of the sub-value being accessed public EvalCompositeAccess(ICPPEvaluation parent, int elementId) { this.parent = parent; this.elementId = elementId; } public void update(ICPPEvaluation newValue) { parent.getValue(null).setSubValue(elementId, newValue); } @Override public boolean isInitializerList() { return getTargetEvaluation().isInitializerList(); } private ICPPEvaluation getTargetEvaluation() { return parent.getValue(null).getSubValue(elementId); } @Override public boolean isFunctionSet() { return getTargetEvaluation().isFunctionSet(); } @Override public boolean isTypeDependent() { return getTargetEvaluation().isTypeDependent(); } @Override public boolean isValueDependent() { return getTargetEvaluation().isValueDependent(); } @Override public boolean isConstantExpression(IASTNode point) { return getTargetEvaluation().isConstantExpression(point); } @Override public IType getType(IASTNode point) { IType type = getParent().getType(point); type = SemanticUtil.getNestedType(type, TDEF | REF | CVTYPE); if (type instanceof IArrayType) { IArrayType arrayType = (IArrayType) type; return arrayType.getType(); } else if (type instanceof InitializerListType) { InitializerListType initListType = (InitializerListType) type; return initListType.getEvaluation().getClauses()[elementId].getType(point); } else if (type instanceof ICPPClassType) { ICPPClassType classType = (ICPPClassType) type; return ClassTypeHelper.getFields(classType, point)[elementId].getType(); } else if (type instanceof ParameterPackType) { ParameterPackType parameterPackType = (ParameterPackType) type; return parameterPackType.getTypes()[elementId]; } else if (type instanceof ICPPBasicType) { return type; } return null; } @Override public IValue getValue(IASTNode point) { return getTargetEvaluation().getValue(point); } @Override public ValueCategory getValueCategory(IASTNode point) { return getTargetEvaluation().getValueCategory(point); } @Override public char[] getSignature() { return getTargetEvaluation().getSignature(); } @Override public ICPPEvaluation computeForFunctionCall(ActivationRecord record, ConstexprEvaluationContext context) { if (getTargetEvaluation() != EvalFixed.INCOMPLETE) { return getTargetEvaluation().computeForFunctionCall(record, context); } else { ICPPEvaluation evaluatedComposite = parent.computeForFunctionCall(record, context); return evaluatedComposite.getValue(context.getPoint()).getSubValue(elementId).computeForFunctionCall(record, context); } } @Override public int determinePackSize(ICPPTemplateParameterMap tpMap) { return getTargetEvaluation().determinePackSize(tpMap); } @Override public boolean referencesTemplateParameter() { return getTargetEvaluation().referencesTemplateParameter(); } @Override public IBinding getTemplateDefinition() { return parent.getTemplateDefinition(); } public ICPPEvaluation getParent() { return parent; } public int getElementId() { return elementId; } @Override public ICPPEvaluation instantiate(InstantiationContext context, int maxDepth) { return getTargetEvaluation().instantiate(context, maxDepth); } @Override public void marshal(ITypeMarshalBuffer buffer, boolean includeValue) throws CoreException { buffer.putShort(ITypeMarshalBuffer.EVAL_COMPOSITE_ACCESS); buffer.marshalEvaluation(parent, includeValue); buffer.putInt(elementId); } public static ICPPEvaluation unmarshal(short firstBytes, ITypeMarshalBuffer buffer) throws CoreException { ICPPEvaluation parent = buffer.unmarshalEvaluation(); int elementId = buffer.getInt(); return new EvalCompositeAccess(parent, elementId); } }