/*******************************************************************************
* Copyright (c) 2010 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
*******************************************************************************/
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;
import org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory;
import org.eclipse.cdt.core.dom.ast.IASTIdExpression;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTUnaryExpression;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IFunctionType;
import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPReferenceType;
/**
* Methods for computing the type of an expression
*/
public class ExpressionTypes {
public static IType glvalueType(IType type) {
// Reference types are removed.
return SemanticUtil.getNestedType(type, TDEF | REF);
}
public static IType prvalueType(IType type) {
return Conversions.lvalue_to_rvalue(type);
}
public static ValueCategory valueCategoryFromFunctionCall(ICPPFunction function) {
final ICPPFunctionType ft = function.getType();
return valueCategoryFromReturnType(ft.getReturnType());
}
public static ValueCategory valueCategoryFromReturnType(IType r) {
r= SemanticUtil.getNestedType(r, TDEF);
if (r instanceof ICPPReferenceType) {
ICPPReferenceType refType= (ICPPReferenceType) r;
if (!refType.isRValueReference()) {
return ValueCategory.LVALUE;
}
if (SemanticUtil.getNestedType(refType.getType(), TDEF | REF | CVTYPE) instanceof IFunctionType) {
return ValueCategory.LVALUE;
}
return ValueCategory.XVALUE;
}
return ValueCategory.PRVALUE;
}
public static IType typeFromFunctionCall(ICPPFunction function) {
final ICPPFunctionType ft = function.getType();
return typeFromReturnType(ft.getReturnType());
}
public static IType typeFromReturnType(IType r) {
r= SemanticUtil.getNestedType(r, TDEF);
if (r instanceof ICPPReferenceType) {
return glvalueType(r);
}
return prvalueType(r);
}
public static IType typeOrFunctionSet(IASTExpression e) {
FunctionSetType fs= getFunctionSetType(e);
if (fs != null) {
return fs;
}
return e.getExpressionType();
}
public static ValueCategory valueCat(IASTExpression e) {
FunctionSetType fs= getFunctionSetType(e);
if (fs != null)
return fs.getValueCategory();
return e.getValueCategory();
}
private static FunctionSetType getFunctionSetType(IASTExpression e) {
boolean addressOf= false;
while (e instanceof IASTUnaryExpression) {
final IASTUnaryExpression unary = (IASTUnaryExpression) e;
final int op= unary.getOperator();
if (op == IASTUnaryExpression.op_bracketedPrimary) {
e= unary.getOperand();
} else if (!addressOf && op == IASTUnaryExpression.op_amper) {
addressOf= true;
e= unary.getOperand();
} else {
break;
}
}
if (e instanceof IASTIdExpression) {
IASTIdExpression idexpr= (IASTIdExpression) e;
final IASTName name = idexpr.getName();
IBinding b= name.resolvePreBinding();
if (b instanceof CPPFunctionSet) {
return new FunctionSetType(((CPPFunctionSet) b).getBindings(), name, addressOf);
}
}
return null;
}
}