blob: 958832d87c1d41e1f98a751ce9fd95feb32cbb88 [file] [log] [blame]
/**********************************************************************
* Copyright (c) 2002,2003 Rational Software Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v0.5
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v05.html
*
* Contributors:
* IBM Rational Software - Initial API and implementation
***********************************************************************/
package org.eclipse.cdt.internal.core.parser.pst;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import org.eclipse.cdt.core.parser.Enum;
public class TypeInfo {
public TypeInfo(){
super();
}
public TypeInfo( TypeInfo.eType type, int info, ISymbol symbol ){
super();
_typeInfo = info;
_type = type;
_typeDeclaration = symbol;
}
public TypeInfo( TypeInfo.eType type, int info, ISymbol symbol, TypeInfo.PtrOp op, boolean hasDefault ){
super();
_typeInfo = info;
_type = type;
_typeDeclaration = symbol;
if( op != null ){
_ptrOperators = new LinkedList();
_ptrOperators.add( op );
} else {
_ptrOperators = null;
}
_hasDefaultValue = hasDefault;
}
public TypeInfo( TypeInfo.eType type, int info, ISymbol symbol, TypeInfo.PtrOp op, Object def ){
super();
_typeInfo = info;
_type = type;
_typeDeclaration = symbol;
if( op != null ){
_ptrOperators = new LinkedList();
_ptrOperators.add( op );
} else {
_ptrOperators = null;
}
_hasDefaultValue = true;
setDefault( def );
}
public TypeInfo( TypeInfo info ){
super();
_typeInfo = info._typeInfo;
_type = info._type;
_typeDeclaration = info._typeDeclaration;
_ptrOperators = ( info._ptrOperators == null ) ? null : (LinkedList)info._ptrOperators.clone();
_hasDefaultValue = info._hasDefaultValue;
}
public static final int typeMask = 0x001f;
public static final int isAuto = 0x0020;
public static final int isRegister = 0x0040;
public static final int isStatic = 0x0080;
public static final int isExtern = 0x0100;
public static final int isMutable = 0x0200;
public static final int isInline = 0x0400;
public static final int isVirtual = 0x0800;
public static final int isExplicit = 0x1000;
public static final int isTypedef = 0x2000;
public static final int isFriend = 0x4000;
public static final int isConst = 0x8000;
public static final int isVolatile = 0x10000;
public static final int isUnsigned = 0x20000;
public static final int isShort = 0x40000;
public static final int isLong = 0x80000;
public static final int isForward = 0x100000;
public static final int isComplex = 0x200000;
public static final int isImaginary= 0x400000;
// Types (maximum type is typeMask
// Note that these should be considered ordered and if you change
// the order, you should consider the ParserSymbolTable uses
public static final TypeInfo.eType t_any = new TypeInfo.eType( -1 ); //don't care
public static final TypeInfo.eType t_undef = new TypeInfo.eType( 0 ); //not specified
public static final TypeInfo.eType t_type = new TypeInfo.eType( 1 ); //Type Specifier
public static final TypeInfo.eType t_namespace = new TypeInfo.eType( 2 );
public static final TypeInfo.eType t_class = new TypeInfo.eType( 3 );
public static final TypeInfo.eType t_struct = new TypeInfo.eType( 4 );
public static final TypeInfo.eType t_union = new TypeInfo.eType( 5 );
public static final TypeInfo.eType t_enumeration = new TypeInfo.eType( 6 );
public static final TypeInfo.eType t_constructor = new TypeInfo.eType( 7 );
public static final TypeInfo.eType t_function = new TypeInfo.eType( 8 );
public static final TypeInfo.eType t__Bool = new TypeInfo.eType( 9 );
public static final TypeInfo.eType t_bool = new TypeInfo.eType( 10 );
public static final TypeInfo.eType t_char = new TypeInfo.eType( 11 );
public static final TypeInfo.eType t_wchar_t = new TypeInfo.eType( 12 );
public static final TypeInfo.eType t_int = new TypeInfo.eType( 13 );
public static final TypeInfo.eType t_float = new TypeInfo.eType( 14 );
public static final TypeInfo.eType t_double = new TypeInfo.eType( 15 );
public static final TypeInfo.eType t_void = new TypeInfo.eType( 16 );
public static final TypeInfo.eType t_enumerator = new TypeInfo.eType( 17 );
public static final TypeInfo.eType t_block = new TypeInfo.eType( 18 );
public static final TypeInfo.eType t_template = new TypeInfo.eType( 19 );
public static final TypeInfo.eType t_asm = new TypeInfo.eType( 20 );
public static final TypeInfo.eType t_linkage = new TypeInfo.eType( 21 );
//public static final eType t_templateParameter = new eType( 18 );
public static class eType implements Comparable{
protected eType( int v ){
_val = v;
}
public int compareTo( Object o ){
TypeInfo.eType t = (TypeInfo.eType) o;
return _val - t._val;
}
public int toInt(){
return _val;
}
private int _val;
}
public static class OperatorExpression extends Enum{
//5.3.1-1 : The unary * operator, the expression to which it is applied shall be
//a pointer to an object type or a pointer to a function type and the result
//is an lvalue refering to the object or function to which the expression points
public static final OperatorExpression indirection = new OperatorExpression( 1 );
//5.3.1-2 : The result of the unary & operator is a pointer to its operand
public static final OperatorExpression addressof = new OperatorExpression( 0 );
//5.2.1 A postfix expression followed by an expression in square brackets is a postfix
//expression. one of the expressions shall have the type "pointer to T" and the other
//shall have a enumeration or integral type. The result is an lvalue of type "T"
public static final OperatorExpression subscript = new OperatorExpression( 2 );
protected OperatorExpression(int enumValue) {
super(enumValue);
}
}
public static class PtrOp {
public PtrOp( TypeInfo.eType type ){
this.type = type;
}
public PtrOp( TypeInfo.eType type, boolean isConst, boolean isVolatile ){
this.type = type;
this.isConst = isConst;
this.isVolatile = isVolatile;
}
public PtrOp( ISymbol memberOf, boolean isConst, boolean isVolatile ){
this.type = PtrOp.t_memberPointer;
this.isConst = isConst;
this.isVolatile = isVolatile;
this.memberOf = memberOf;
}
public PtrOp(){
super();
}
public static final TypeInfo.eType t_undef = new TypeInfo.eType( 0 );
public static final TypeInfo.eType t_pointer = new TypeInfo.eType( 1 );
public static final TypeInfo.eType t_reference = new TypeInfo.eType( 2 );
public static final TypeInfo.eType t_array = new TypeInfo.eType( 3 );
public static final TypeInfo.eType t_memberPointer = new TypeInfo.eType( 4 );
public TypeInfo.eType getType() { return type; }
public void setType( TypeInfo.eType type ) { this.type = type; }
public boolean isConst() { return isConst; }
public boolean isVolatile() { return isVolatile; }
public void setConst( boolean isConst ) { this.isConst = isConst; }
public void setVolatile(boolean isVolatile) { this.isVolatile = isVolatile; }
public ISymbol getMemberOf() { return memberOf; }
public void setMemberOf( ISymbol member ) { this.memberOf = member; }
public int compareCVTo( TypeInfo.PtrOp ptr ){
int cv1 = ( isConst() ? 1 : 0 ) + ( isVolatile() ? 1 : 0 );
int cv2 = ( ptr.isConst() ? 1 : 0 ) + ( ptr.isVolatile() ? 1 : 0 );
return cv1 - cv2;
}
public boolean equals( Object o ){
if( o == null || !(o instanceof TypeInfo.PtrOp) ){
return false;
}
TypeInfo.PtrOp op = (TypeInfo.PtrOp)o;
return ( isConst() == op.isConst() &&
isVolatile() == op.isVolatile() &&
getType() == op.getType() );
}
private TypeInfo.eType type = PtrOp.t_undef;
private boolean isConst = false;
private boolean isVolatile = false;
private ISymbol memberOf = null;
}
private static final String _image[] = { "", //$NON-NLS-1$ t_undef
"", //$NON-NLS-1$ t_type
"namespace", //$NON-NLS-1$ t_namespace
"class", //$NON-NLS-1$ t_class
"struct", //$NON-NLS-1$ t_struct
"union", //$NON-NLS-1$ t_union
"enum", //$NON-NLS-1$ t_enumeration
"", //$NON-NLS-1$ t_constructor
"", //$NON-NLS-1$ t_function
"bool", //$NON-NLS-1$ t_bool
"char", //$NON-NLS-1$ t_char
"wchar_t", //$NON-NLS-1$ t_wchar_t
"int", //$NON-NLS-1$ t_int
"float", //$NON-NLS-1$ t_float
"double", //$NON-NLS-1$ t_double
"void", //$NON-NLS-1$ t_void
"", //$NON-NLS-1$ t_enumerator
"", //$NON-NLS-1$ t_block
"template", //$NON-NLS-1$ t_template
"", //$NON-NLS-1$ t_asm
"" //$NON-NLS-1$ t_linkage
};
//Partial ordering :
// none < const
// none < volatile
// none < const volatile
// const < const volatile
// volatile < const volatile
public static final int cvConst = 2;
public static final int cvVolatile = 3;
public static final int cvConstVolatile = 5;
// Convenience methods
public void setBit(boolean b, int mask){
if( b ){
_typeInfo = _typeInfo | mask;
} else {
_typeInfo = _typeInfo & ~mask;
}
}
public boolean checkBit(int mask){
return (_typeInfo & mask) != 0;
}
public void setType( TypeInfo.eType t){
_type = t;
}
public TypeInfo.eType getType(){
return _type;
}
public boolean isType( TypeInfo.eType type ){
return isType( type, TypeInfo.t_undef );
}
public int getTypeInfo(){
return _typeInfo;
}
public void setTypeInfo( int typeInfo ){
_typeInfo = typeInfo;
}
/**
*
* @param type
* @param upperType
* @return boolean
*
* type checking, check that this declaration's type is between type and
* upperType (inclusive). upperType of 0 means no range and our type must
* be type.
*/
public boolean isType( TypeInfo.eType type, TypeInfo.eType upperType ){
//type of -1 means we don't care
if( type == TypeInfo.t_any )
return true;
//upperType of 0 means no range
if( upperType == TypeInfo.t_undef ){
return ( getType() == type );
} else {
return ( getType().compareTo( type ) >= 0 && getType().compareTo( upperType ) <= 0 );
}
}
public ISymbol getTypeSymbol(){
return _typeDeclaration;
}
public void setTypeSymbol( ISymbol type ){
_typeDeclaration = type;
}
public boolean hasPtrOperators(){
return ( _ptrOperators != null && _ptrOperators.size() > 0 );
}
public List getPtrOperators(){
if( _ptrOperators == null ){
_ptrOperators = new LinkedList();
}
return _ptrOperators;
}
public boolean hasSamePtrs( TypeInfo type ){
int size = getPtrOperators().size();
int size2 = type.getPtrOperators().size();
Iterator iter1 = getPtrOperators().iterator();
Iterator iter2 = type.getPtrOperators().iterator();
TypeInfo.PtrOp ptr1 = null, ptr2 = null;
if( size2 < size ) {
for( int i = size; i > size2; i-- ){
ptr2 = (PtrOp) iter1.next();
if( ptr2.getType() != PtrOp.t_undef ){
return false;
}
}
size = size2;
} else if ( size < size2 ){
for( int i = size2; i > size; i-- ){
ptr1 = (PtrOp)iter2.next();
if( ptr1.getType() != PtrOp.t_undef ){
return false;
}
}
size2 = size;
}
if( size == size2 ){
if( size > 0 ){
for( int i = size; i > 0; i-- ){
ptr1 = (TypeInfo.PtrOp)iter1.next();
ptr2 = (TypeInfo.PtrOp)iter2.next();
if( ptr1.getType() != ptr2.getType() ){
return false;
}
}
}
return true;
}
return false;
}
public List getOperatorExpressions(){
if( _operatorExpressions == null ){
_operatorExpressions = new LinkedList();
}
return _operatorExpressions;
}
public void applyOperatorExpressions( List ops ){
if( ops == null || ops.isEmpty() )
return;
int size = ops.size();
Iterator iter = ops.iterator();
OperatorExpression op = null;
for( int i = size; i > 0; i-- ){
op = (OperatorExpression)iter.next();
if( op == OperatorExpression.indirection ||
op == OperatorExpression.subscript )
{
//indirection operator, can only be applied to a pointer
//subscript should be applied to something that is "pointer to T", the result is a lvalue of type "T"
if( hasPtrOperators() ){
ListIterator iterator = getPtrOperators().listIterator( getPtrOperators().size() );
TypeInfo.PtrOp last = (TypeInfo.PtrOp)iterator.previous();
if( last.getType() == TypeInfo.PtrOp.t_pointer ||
last.getType() == TypeInfo.PtrOp.t_array )
{
iterator.remove();
}
}
} else if( op == OperatorExpression.addressof ){
//Address-of unary operator, results in pointer to T
//TODO or pointer to member
TypeInfo.PtrOp newOp = new TypeInfo.PtrOp( PtrOp.t_pointer );
addPtrOperator( newOp );
}
}
}
public void addPtrOperator( TypeInfo.PtrOp ptr ){
if( _ptrOperators == null ){
_ptrOperators = new LinkedList();
}
if( ptr != null )
_ptrOperators.add( ptr );
}
public void addPtrOperator( List ptrs ){
if( _ptrOperators == null ){
_ptrOperators = new LinkedList();
}
if( ptrs != null )
_ptrOperators.addAll( ptrs );
}
public void addOperatorExpression( OperatorExpression exp ){
if( _operatorExpressions == null ){
_operatorExpressions = new LinkedList();
}
_operatorExpressions.add( exp );
}
public boolean getHasDefault(){
return _hasDefaultValue;
}
public void setHasDefault( boolean def ){
_hasDefaultValue = def;
}
public void setDefault( Object t ){
_defaultValue = t;
}
public Object getDefault(){
return _defaultValue;
}
public boolean isForwardDeclaration(){
return checkBit( isForward );
}
public void setIsForwardDeclaration( boolean forward ){
setBit( forward, isForward );
}
/**
* canHold
* @param type
* @return boolean
* return true is the our type can hold all the values of the passed in
* type.
* TODO, for now return true if our type is "larger" (based on ordering of
* the type values)
*/
public boolean canHold( TypeInfo type ){
return getType().compareTo( type.getType() ) >= 0;
}
public boolean equals( Object t ){
if( t == null || !(t instanceof TypeInfo) ){
return false;
}
TypeInfo type = (TypeInfo)t;
boolean result = ( _typeInfo == type._typeInfo );
result &= ( _type == type._type );
if( _typeDeclaration instanceof TemplateInstance ){
result &= _typeDeclaration.equals( type._typeDeclaration );
} else {
if( _typeDeclaration != null && type._typeDeclaration != null &&
_typeDeclaration.isType( TypeInfo.t_bool, TypeInfo.t_void ) &&
type._typeDeclaration.isType( TypeInfo.t_bool, TypeInfo.t_void ) )
{
//if typeDeclaration is a basic type, then only need the types the same
result &= ( _typeDeclaration.getType() == type._typeDeclaration.getType() );
} else {
//otherwise, its a user defined type, need the decls the same
result &= ( _typeDeclaration == type._typeDeclaration );
}
}
int size1 = (_ptrOperators == null) ? 0 : _ptrOperators.size();
int size2 = (type._ptrOperators == null) ? 0 : type._ptrOperators.size();
if( size1 == size2 ){
if( size1 != 0 ){
Iterator iter1 = _ptrOperators.iterator();
Iterator iter2 = type._ptrOperators.iterator();
TypeInfo.PtrOp op1 = null, op2 = null;
for( int i = size1; i > 0; i-- ){
op1 = (TypeInfo.PtrOp)iter1.next();
op2 = (TypeInfo.PtrOp)iter2.next();
if( !op1.equals(op2) ){
return false;
}
}
}
} else {
return false;
}
return result;
}
public String toString(){
if( isType( TypeInfo.t_type ) ){
return _typeDeclaration.getName();
} else {
return TypeInfo._image[ getType().toInt() ];
}
}
private int _typeInfo = 0;
private TypeInfo.eType _type = TypeInfo.t_undef;
private ISymbol _typeDeclaration;
private boolean _hasDefaultValue = false;
private Object _defaultValue = null;
private LinkedList _ptrOperators;
private LinkedList _operatorExpressions;
}