/*******************************************************************************
* Copyright (c) 2012, 2016 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.core.dom.ast.IASTExpression.ValueCategory.LVALUE;
import static org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory.PRVALUE;
import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_alignof;
import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_has_nothrow_constructor;
import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_has_nothrow_copy;
import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_has_trivial_assign;
import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_has_trivial_constructor;
import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_has_trivial_copy;
import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_has_trivial_destructor;
import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_has_virtual_destructor;
import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_is_abstract;
import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_is_class;
import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_is_empty;
import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_is_enum;
import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_is_final;
import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_is_literal_type;
import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_is_pod;
import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_is_polymorphic;
import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_is_standard_layout;
import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_is_trivial;
import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_is_trivially_copyable;
import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_is_union;
import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_sizeof;
import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_sizeofParameterPack;
import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_typeid;
import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_typeof;
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.IType;
import org.eclipse.cdt.core.dom.ast.IValue;
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.ProblemType;
import org.eclipse.cdt.internal.core.dom.parser.ValueFactory;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPBasicType;
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 EvalUnaryTypeID extends CPPDependentEvaluation {
private final int fOperator;
private final IType fOrigType;
private IType fType;
public EvalUnaryTypeID(int operator, IType type, IASTNode pointOfDefinition) {
this(operator, type, findEnclosingTemplate(pointOfDefinition));
}
public EvalUnaryTypeID(int operator, IType type, IBinding templateDefinition) {
super(templateDefinition);
fOperator= operator;
fOrigType= type;
}
public int getOperator() {
return fOperator;
}
public IType getArgument() {
return fOrigType;
}
@Override
public boolean isInitializerList() {
return false;
}
@Override
public boolean isFunctionSet() {
return false;
}
@Override
public boolean isTypeDependent() {
if (fOperator == op_typeof)
return CPPTemplates.isDependentType(fOrigType);
return false;
}
@Override
public boolean isValueDependent() {
switch (fOperator) {
case op_sizeofParameterPack:
return true;
case op_sizeof:
case op_alignof:
case op_has_nothrow_copy:
case op_has_nothrow_constructor:
case op_has_trivial_assign:
case op_has_trivial_constructor:
case op_has_trivial_copy:
case op_has_trivial_destructor:
case op_has_virtual_destructor:
case op_is_abstract:
case op_is_class:
case op_is_empty:
case op_is_enum:
case op_is_final:
case op_is_literal_type:
case op_is_pod:
case op_is_polymorphic:
case op_is_standard_layout:
case op_is_trivial:
case op_is_trivially_copyable:
case op_is_union:
return CPPTemplates.isDependentType(fOrigType);
case op_typeid:
case op_typeof:
return false;
}
return false;
}
@Override
public boolean isConstantExpression(IASTNode point) {
return true;
}
@Override
public IType getType(IASTNode point) {
if (fType == null)
fType= computeType(point);
return fType;
}
private IType computeType(IASTNode point) {
switch (fOperator) {
case op_sizeof:
case op_sizeofParameterPack:
case op_alignof:
return CPPVisitor.get_SIZE_T(point);
case op_typeid:
return CPPVisitor.get_type_info(point);
case op_has_nothrow_copy:
case op_has_nothrow_constructor:
case op_has_trivial_assign:
case op_has_trivial_constructor:
case op_has_trivial_copy:
case op_has_trivial_destructor:
case op_has_virtual_destructor:
case op_is_abstract:
case op_is_class:
case op_is_empty:
case op_is_enum:
case op_is_final:
case op_is_literal_type:
case op_is_pod:
case op_is_polymorphic:
case op_is_standard_layout:
case op_is_trivial:
case op_is_trivially_copyable:
case op_is_union:
return CPPBasicType.BOOLEAN;
case op_typeof:
if (isTypeDependent())
return new TypeOfDependentExpression(this);
return fOrigType;
}
return ProblemType.UNKNOWN_FOR_EXPRESSION;
}
@Override
public IValue getValue(IASTNode point) {
if (isValueDependent())
return DependentValue.create(this);
return ValueFactory.evaluateUnaryTypeIdExpression(fOperator, fOrigType, point);
}
@Override
public ValueCategory getValueCategory(IASTNode point) {
return fOperator == op_typeid ? LVALUE : PRVALUE;
}
@Override
public void marshal(ITypeMarshalBuffer buffer, boolean includeValue) throws CoreException {
buffer.putShort(ITypeMarshalBuffer.EVAL_UNARY_TYPE_ID);
buffer.putByte((byte) fOperator);
buffer.marshalType(fOrigType);
marshalTemplateDefinition(buffer);
}
public static ICPPEvaluation unmarshal(short firstBytes, ITypeMarshalBuffer buffer) throws CoreException {
int op= buffer.getByte();
IType arg= buffer.unmarshalType();
IBinding templateDefinition= buffer.unmarshalBinding();
return new EvalUnaryTypeID(op, arg, templateDefinition);
}
@Override
public ICPPEvaluation instantiate(InstantiationContext context, int maxDepth) {
if (fOperator == op_sizeofParameterPack) {
int packSize = determinePackSize(context.getParameterMap());
if (packSize == CPPTemplates.PACK_SIZE_FAIL || packSize == CPPTemplates.PACK_SIZE_NOT_FOUND) {
return EvalFixed.INCOMPLETE;
} else if (packSize != CPPTemplates.PACK_SIZE_DEFER) {
IASTNode point = context.getPoint();
return new EvalFixed(getType(point), getValueCategory(point), IntegralValue.create(packSize));
}
}
IType type = CPPTemplates.instantiateType(fOrigType, context);
if (type == fOrigType)
return this;
return new EvalUnaryTypeID(fOperator, type, getTemplateDefinition());
}
@Override
public ICPPEvaluation computeForFunctionCall(ActivationRecord record, ConstexprEvaluationContext context) {
return this;
}
@Override
public int determinePackSize(ICPPTemplateParameterMap tpMap) {
return CPPTemplates.determinePackSize(fOrigType, tpMap);
}
@Override
public boolean referencesTemplateParameter() {
return false;
}
}