/******************************************************************************* * Copyright (c) 2012, 2014 Wind River Systems, Inc. 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: * Markus Schorn - initial API and implementation * Sergey Prigogin (Google) *******************************************************************************/ package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics; import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExpressionTypes.typeFromFunctionCall; import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExpressionTypes.valueCategoryFromFunctionCall; import org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory; import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.ISemanticProblem; import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.IValue; import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap; import org.eclipse.cdt.internal.core.dom.parser.DependentValue; import org.eclipse.cdt.internal.core.dom.parser.ITypeMarshalBuffer; import org.eclipse.cdt.internal.core.dom.parser.IntegralValue; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation; import org.eclipse.cdt.internal.core.dom.parser.cpp.InstantiationContext; import org.eclipse.core.runtime.CoreException; public class EvalComma extends CPPDependentEvaluation { private static final ICPPFunction[] NO_FUNCTIONS = {}; private final ICPPEvaluation[] fArguments; private ICPPFunction[] fOverloads; private IType fType; private boolean fCheckedIsConstantExpression; private boolean fIsConstantExpression; public EvalComma(ICPPEvaluation[] evals, IASTNode pointOfDefinition) { this(evals, findEnclosingTemplate(pointOfDefinition)); } public EvalComma(ICPPEvaluation[] evals, IBinding templateDefinition) { super(templateDefinition); fArguments= evals; } public ICPPEvaluation[] getArguments() { return fArguments; } @Override public boolean isInitializerList() { return false; } @Override public boolean isFunctionSet() { return false; } @Override public boolean isTypeDependent() { if (fType != null) return fType instanceof TypeOfDependentExpression; return containsDependentType(fArguments); } @Override public boolean isValueDependent() { return containsDependentValue(fArguments); } @Override public boolean isConstantExpression(IASTNode point) { if (!fCheckedIsConstantExpression) { fCheckedIsConstantExpression = true; fIsConstantExpression = computeIsConstantExpression(point); } return fIsConstantExpression; } private boolean computeIsConstantExpression(IASTNode point) { if (!areAllConstantExpressions(fArguments, point)) { return false; } for (ICPPFunction overload : fOverloads) { if (!isNullOrConstexprFunc(overload)) { return false; } } return true; } public ICPPFunction[] getOverloads(IASTNode point) { if (fOverloads == null) { fOverloads= computeOverloads(point); } return fOverloads; } private ICPPFunction[] computeOverloads(IASTNode point) { if (fArguments.length < 2) return NO_FUNCTIONS; if (isTypeDependent()) return NO_FUNCTIONS; ICPPFunction[] overloads = new ICPPFunction[fArguments.length - 1]; ICPPEvaluation e1= fArguments[0]; for (int i = 1; i < fArguments.length; i++) { ICPPEvaluation e2 = fArguments[i]; ICPPFunction overload = CPPSemantics.findOverloadedOperatorComma(point, getTemplateDefinitionScope(), e1, e2); if (overload == null) { e1= e2; } else { overloads[i - 1] = overload; e1= new EvalFixed(typeFromFunctionCall(overload), valueCategoryFromFunctionCall(overload), IntegralValue.UNKNOWN); if (e1.getType(point) instanceof ISemanticProblem) { e1= e2; } } } return overloads; } @Override public IType getType(IASTNode point) { if (fType == null) { fType= computeType(point); } return fType; } private IType computeType(IASTNode point) { if (isTypeDependent()) { return new TypeOfDependentExpression(this); } ICPPFunction[] overloads = getOverloads(point); if (overloads.length > 0) { ICPPFunction last = overloads[overloads.length - 1]; if (last != null) { return typeFromFunctionCall(last); } } return fArguments[fArguments.length - 1].getType(point); } @Override public IValue getValue(IASTNode point) { ICPPFunction[] overloads = getOverloads(point); if (overloads.length > 0) { // TODO(sprigogin): Simulate execution of a function call. return DependentValue.create(this); } return fArguments[fArguments.length - 1].getValue(point); } @Override public ValueCategory getValueCategory(IASTNode point) { ICPPFunction[] overloads = getOverloads(point); if (overloads.length > 0) { ICPPFunction last = overloads[overloads.length - 1]; if (last != null) { return valueCategoryFromFunctionCall(last); } } return fArguments[fArguments.length - 1].getValueCategory(point); } @Override public void marshal(ITypeMarshalBuffer buffer, boolean includeValue) throws CoreException { buffer.putShort(ITypeMarshalBuffer.EVAL_COMMA); buffer.putInt(fArguments.length); for (ICPPEvaluation arg : fArguments) { buffer.marshalEvaluation(arg, includeValue); } marshalTemplateDefinition(buffer); } public static ICPPEvaluation unmarshal(short firstBytes, ITypeMarshalBuffer buffer) throws CoreException { int len= buffer.getInt(); ICPPEvaluation[] args = new ICPPEvaluation[len]; for (int i = 0; i < args.length; i++) { args[i]= buffer.unmarshalEvaluation(); } IBinding templateDefinition = buffer.unmarshalBinding(); return new EvalComma(args, templateDefinition); } @Override public ICPPEvaluation instantiate(InstantiationContext context, int maxDepth) { ICPPEvaluation[] args = fArguments; for (int i = 0; i < fArguments.length; i++) { ICPPEvaluation arg = fArguments[i].instantiate(context, maxDepth); if (arg != fArguments[i]) { if (args == fArguments) { args = new ICPPEvaluation[fArguments.length]; System.arraycopy(fArguments, 0, args, 0, fArguments.length); } args[i] = arg; } } if (args == fArguments) return this; return new EvalComma(args, getTemplateDefinition()); } @Override public ICPPEvaluation computeForFunctionCall(ActivationRecord record, ConstexprEvaluationContext context) { ICPPEvaluation[] args = fArguments; for (int i = 0; i < fArguments.length; i++) { ICPPEvaluation arg = fArguments[i].computeForFunctionCall(record, context.recordStep()); if (arg != fArguments[i]) { if (args == fArguments) { args = new ICPPEvaluation[fArguments.length]; System.arraycopy(fArguments, 0, args, 0, fArguments.length); } args[i] = arg; } } if (args == fArguments) { return this; } EvalComma evalComma = new EvalComma(args, getTemplateDefinition()); return evalComma; } @Override public int determinePackSize(ICPPTemplateParameterMap tpMap) { int r = CPPTemplates.PACK_SIZE_NOT_FOUND; for (ICPPEvaluation arg : fArguments) { r = CPPTemplates.combinePackSize(r, arg.determinePackSize(tpMap)); } return r; } @Override public boolean referencesTemplateParameter() { for (ICPPEvaluation arg : fArguments) { if (arg.referencesTemplateParameter()) return true; } return false; } }