Made char type a distinct type.
This commit is contained in:
@@ -59,6 +59,7 @@
|
|||||||
|
|
||||||
|
|
||||||
/* Predefined type strings */
|
/* Predefined type strings */
|
||||||
|
Type type_char[] = { TYPE(T_CHAR), TYPE(T_END) };
|
||||||
Type type_schar[] = { TYPE(T_SCHAR), TYPE(T_END) };
|
Type type_schar[] = { TYPE(T_SCHAR), TYPE(T_END) };
|
||||||
Type type_uchar[] = { TYPE(T_UCHAR), TYPE(T_END) };
|
Type type_uchar[] = { TYPE(T_UCHAR), TYPE(T_END) };
|
||||||
Type type_int[] = { TYPE(T_INT), TYPE(T_END) };
|
Type type_int[] = { TYPE(T_INT), TYPE(T_END) };
|
||||||
@@ -431,14 +432,6 @@ int SignExtendChar (int C)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
TypeCode GetDefaultChar (void)
|
|
||||||
/* Return the default char type (signed/unsigned) depending on the settings */
|
|
||||||
{
|
|
||||||
return IS_Get (&SignedChars)? T_SCHAR : T_UCHAR;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Type* GetCharArrayType (unsigned Len)
|
Type* GetCharArrayType (unsigned Len)
|
||||||
/* Return the type for a char array of the given length */
|
/* Return the type for a char array of the given length */
|
||||||
{
|
{
|
||||||
@@ -448,7 +441,7 @@ Type* GetCharArrayType (unsigned Len)
|
|||||||
/* Fill the type string */
|
/* Fill the type string */
|
||||||
T[0].C = T_ARRAY;
|
T[0].C = T_ARRAY;
|
||||||
T[0].A.L = Len; /* Array length is in the L attribute */
|
T[0].A.L = Len; /* Array length is in the L attribute */
|
||||||
T[1].C = GetDefaultChar ();
|
T[1].C = T_CHAR;
|
||||||
T[2].C = T_END;
|
T[2].C = T_END;
|
||||||
|
|
||||||
/* Return the new type */
|
/* Return the new type */
|
||||||
@@ -685,8 +678,9 @@ int TypeHasAttr (const Type* T)
|
|||||||
const Type* GetUnderlyingType (const Type* Type)
|
const Type* GetUnderlyingType (const Type* Type)
|
||||||
/* Get the underlying type of an enum or other integer class type */
|
/* Get the underlying type of an enum or other integer class type */
|
||||||
{
|
{
|
||||||
if (IsTypeEnum (Type)) {
|
if (IsISOChar (Type)) {
|
||||||
|
return IS_Get (&SignedChars) ? type_schar : type_uchar;
|
||||||
|
} else if (IsTypeEnum (Type)) {
|
||||||
/* This should not happen, but just in case */
|
/* This should not happen, but just in case */
|
||||||
if (Type->A.P == 0) {
|
if (Type->A.P == 0) {
|
||||||
Internal ("Enum tag type error in GetUnderlyingTypeCode");
|
Internal ("Enum tag type error in GetUnderlyingTypeCode");
|
||||||
@@ -708,8 +702,11 @@ TypeCode GetUnderlyingTypeCode (const Type* Type)
|
|||||||
TypeCode Underlying = UnqualifiedType (Type->C);
|
TypeCode Underlying = UnqualifiedType (Type->C);
|
||||||
TypeCode TCode;
|
TypeCode TCode;
|
||||||
|
|
||||||
/* We could also support other T_CLASS_INT types, but just enums for now */
|
if (IsISOChar (Type)) {
|
||||||
if (IsTypeEnum (Type)) {
|
|
||||||
|
return IS_Get (&SignedChars) ? T_SCHAR : T_UCHAR;
|
||||||
|
|
||||||
|
} else if (IsTypeEnum (Type)) {
|
||||||
|
|
||||||
/* This should not happen, but just in case */
|
/* This should not happen, but just in case */
|
||||||
if (Type->A.P == 0) {
|
if (Type->A.P == 0) {
|
||||||
@@ -996,7 +993,7 @@ int IsClassArithmetic (const Type* T)
|
|||||||
int IsClassBasic (const Type* T)
|
int IsClassBasic (const Type* T)
|
||||||
/* Return true if this is a char, integer or floating type */
|
/* Return true if this is a char, integer or floating type */
|
||||||
{
|
{
|
||||||
return IsRawTypeChar (T) || IsClassInt (T) || IsClassFloat (T);
|
return IsClassChar (T) || IsClassInt (T) || IsClassFloat (T);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ enum {
|
|||||||
T_MASK_QUAL = 0x07F000,
|
T_MASK_QUAL = 0x07F000,
|
||||||
|
|
||||||
/* Types */
|
/* Types */
|
||||||
T_CHAR = T_TYPE_CHAR | T_CLASS_INT | T_SIGN_UNSIGNED | T_SIZE_CHAR,
|
T_CHAR = T_TYPE_CHAR | T_CLASS_INT | T_SIGN_NONE | T_SIZE_CHAR,
|
||||||
T_SCHAR = T_TYPE_CHAR | T_CLASS_INT | T_SIGN_SIGNED | T_SIZE_CHAR,
|
T_SCHAR = T_TYPE_CHAR | T_CLASS_INT | T_SIGN_SIGNED | T_SIZE_CHAR,
|
||||||
T_UCHAR = T_TYPE_CHAR | T_CLASS_INT | T_SIGN_UNSIGNED | T_SIZE_CHAR,
|
T_UCHAR = T_TYPE_CHAR | T_CLASS_INT | T_SIGN_UNSIGNED | T_SIZE_CHAR,
|
||||||
T_SHORT = T_TYPE_SHORT | T_CLASS_INT | T_SIGN_SIGNED | T_SIZE_SHORT,
|
T_SHORT = T_TYPE_SHORT | T_CLASS_INT | T_SIGN_SIGNED | T_SIZE_SHORT,
|
||||||
@@ -189,6 +189,7 @@ struct Type {
|
|||||||
#define PTR_BITS (8 * SIZEOF_PTR)
|
#define PTR_BITS (8 * SIZEOF_PTR)
|
||||||
|
|
||||||
/* Predefined type strings */
|
/* Predefined type strings */
|
||||||
|
extern Type type_char[];
|
||||||
extern Type type_schar[];
|
extern Type type_schar[];
|
||||||
extern Type type_uchar[];
|
extern Type type_uchar[];
|
||||||
extern Type type_int[];
|
extern Type type_int[];
|
||||||
@@ -250,9 +251,6 @@ void TypeFree (Type* T);
|
|||||||
int SignExtendChar (int C);
|
int SignExtendChar (int C);
|
||||||
/* Do correct sign extension of a character */
|
/* Do correct sign extension of a character */
|
||||||
|
|
||||||
TypeCode GetDefaultChar (void);
|
|
||||||
/* Return the default char type (signed/unsigned) depending on the settings */
|
|
||||||
|
|
||||||
Type* GetCharArrayType (unsigned Len);
|
Type* GetCharArrayType (unsigned Len);
|
||||||
/* Return the type for a char array of the given length */
|
/* Return the type for a char array of the given length */
|
||||||
|
|
||||||
@@ -365,7 +363,7 @@ INLINE TypeCode GetRawType (const Type* T)
|
|||||||
|
|
||||||
#if defined(HAVE_INLINE)
|
#if defined(HAVE_INLINE)
|
||||||
INLINE int IsTypeChar (const Type* T)
|
INLINE int IsTypeChar (const Type* T)
|
||||||
/* Return true if this is a character type */
|
/* Return true if this is a char type */
|
||||||
{
|
{
|
||||||
return (GetRawType (GetUnderlyingType (T)) == T_TYPE_CHAR);
|
return (GetRawType (GetUnderlyingType (T)) == T_TYPE_CHAR);
|
||||||
}
|
}
|
||||||
@@ -395,7 +393,7 @@ INLINE int IsTypeInt (const Type* T)
|
|||||||
|
|
||||||
#if defined(HAVE_INLINE)
|
#if defined(HAVE_INLINE)
|
||||||
INLINE int IsTypeLong (const Type* T)
|
INLINE int IsTypeLong (const Type* T)
|
||||||
/* Return true if this is a long type (signed or unsigned) */
|
/* Return true if this is a long int type (signed or unsigned) */
|
||||||
{
|
{
|
||||||
return (GetRawType (GetUnderlyingType (T)) == T_TYPE_LONG);
|
return (GetRawType (GetUnderlyingType (T)) == T_TYPE_LONG);
|
||||||
}
|
}
|
||||||
@@ -403,9 +401,31 @@ INLINE int IsTypeLong (const Type* T)
|
|||||||
# define IsTypeLong(T) (GetRawType (GetUnderlyingType (T)) == T_TYPE_LONG)
|
# define IsTypeLong(T) (GetRawType (GetUnderlyingType (T)) == T_TYPE_LONG)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(HAVE_INLINE)
|
||||||
|
INLINE int IsISOChar (const Type* T)
|
||||||
|
/* Return true if this is a narrow character type (without signed/unsigned) */
|
||||||
|
{
|
||||||
|
return (UnqualifiedType (T->C) == T_CHAR);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
# define IsISOChar(T) (UnqualifiedType ((T)->C) == T_CHAR)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(HAVE_INLINE)
|
||||||
|
INLINE int IsClassChar (const Type* T)
|
||||||
|
/* Return true if this is a narrow character type (including signed/unsigned).
|
||||||
|
** For now this is the same as IsRawTypeChar(T).
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
return (GetRawType (T) == T_TYPE_CHAR);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
# define IsClassChar(T) (GetRawType (T) == T_TYPE_CHAR)
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(HAVE_INLINE)
|
#if defined(HAVE_INLINE)
|
||||||
INLINE int IsRawTypeChar (const Type* T)
|
INLINE int IsRawTypeChar (const Type* T)
|
||||||
/* Return true if this is a character raw type */
|
/* Return true if this is a char raw type (including signed/unsigned) */
|
||||||
{
|
{
|
||||||
return (GetRawType (T) == T_TYPE_CHAR);
|
return (GetRawType (T) == T_TYPE_CHAR);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1169,7 +1169,7 @@ static void ParseTypeSpec (DeclSpec* D, long Default, TypeCode Qualifiers)
|
|||||||
|
|
||||||
case TOK_CHAR:
|
case TOK_CHAR:
|
||||||
NextToken ();
|
NextToken ();
|
||||||
D->Type[0].C = GetDefaultChar();
|
D->Type[0].C = T_CHAR;
|
||||||
D->Type[1].C = T_END;
|
D->Type[1].C = T_END;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -2195,7 +2195,7 @@ static unsigned ParseArrayInit (Type* T, int* Braces, int AllowFlexibleMembers)
|
|||||||
long ElementCount = GetElementCount (T);
|
long ElementCount = GetElementCount (T);
|
||||||
|
|
||||||
/* Special handling for a character array initialized by a literal */
|
/* Special handling for a character array initialized by a literal */
|
||||||
if (IsRawTypeChar (ElementType) &&
|
if (IsClassChar (ElementType) &&
|
||||||
(CurTok.Tok == TOK_SCONST || CurTok.Tok == TOK_WCSCONST ||
|
(CurTok.Tok == TOK_SCONST || CurTok.Tok == TOK_WCSCONST ||
|
||||||
(CurTok.Tok == TOK_LCURLY &&
|
(CurTok.Tok == TOK_LCURLY &&
|
||||||
(NextTok.Tok == TOK_SCONST || NextTok.Tok == TOK_WCSCONST)))) {
|
(NextTok.Tok == TOK_SCONST || NextTok.Tok == TOK_WCSCONST)))) {
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ extern IntStack EnableRegVars; /* Enable register variables */
|
|||||||
extern IntStack AllowRegVarAddr; /* Allow taking addresses of register vars */
|
extern IntStack AllowRegVarAddr; /* Allow taking addresses of register vars */
|
||||||
extern IntStack RegVarsToCallStack; /* Save reg variables on call stack */
|
extern IntStack RegVarsToCallStack; /* Save reg variables on call stack */
|
||||||
extern IntStack StaticLocals; /* Make local variables static */
|
extern IntStack StaticLocals; /* Make local variables static */
|
||||||
extern IntStack SignedChars; /* Make characters signed by default */
|
extern IntStack SignedChars; /* Use 'signed char' as the underlying type of 'char' */
|
||||||
extern IntStack CheckStack; /* Generate stack overflow checks */
|
extern IntStack CheckStack; /* Generate stack overflow checks */
|
||||||
extern IntStack Optimize; /* Optimize flag */
|
extern IntStack Optimize; /* Optimize flag */
|
||||||
extern IntStack CodeSizeFactor; /* Size factor for generated code */
|
extern IntStack CodeSizeFactor; /* Size factor for generated code */
|
||||||
|
|||||||
@@ -731,7 +731,7 @@ static void OptRodataName (const char* Opt attribute ((unused)), const char* Arg
|
|||||||
|
|
||||||
static void OptSignedChars (const char* Opt attribute ((unused)),
|
static void OptSignedChars (const char* Opt attribute ((unused)),
|
||||||
const char* Arg attribute ((unused)))
|
const char* Arg attribute ((unused)))
|
||||||
/* Make default characters signed */
|
/* Use 'signed char' as the underlying type of 'char' */
|
||||||
{
|
{
|
||||||
IS_Set (&SignedChars, 1);
|
IS_Set (&SignedChars, 1);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -783,8 +783,8 @@ static void StdFunc_strcmp (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
|
|||||||
int Offs;
|
int Offs;
|
||||||
|
|
||||||
/* Setup the argument type string */
|
/* Setup the argument type string */
|
||||||
Arg1Type[1].C = GetDefaultChar () | T_QUAL_CONST;
|
Arg1Type[1].C = T_CHAR | T_QUAL_CONST;
|
||||||
Arg2Type[1].C = GetDefaultChar () | T_QUAL_CONST;
|
Arg2Type[1].C = T_CHAR | T_QUAL_CONST;
|
||||||
|
|
||||||
/* Argument #1 */
|
/* Argument #1 */
|
||||||
ParseArg (&Arg1, Arg1Type);
|
ParseArg (&Arg1, Arg1Type);
|
||||||
@@ -983,8 +983,8 @@ static void StdFunc_strcpy (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
|
|||||||
unsigned L1;
|
unsigned L1;
|
||||||
|
|
||||||
/* Setup the argument type string */
|
/* Setup the argument type string */
|
||||||
Arg1Type[1].C = GetDefaultChar ();
|
Arg1Type[1].C = T_CHAR;
|
||||||
Arg2Type[1].C = GetDefaultChar () | T_QUAL_CONST;
|
Arg2Type[1].C = T_CHAR | T_QUAL_CONST;
|
||||||
|
|
||||||
/* Argument #1 */
|
/* Argument #1 */
|
||||||
ParseArg (&Arg1, Arg1Type);
|
ParseArg (&Arg1, Arg1Type);
|
||||||
@@ -1181,7 +1181,7 @@ static void StdFunc_strlen (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
|
|||||||
unsigned L;
|
unsigned L;
|
||||||
|
|
||||||
/* Setup the argument type string */
|
/* Setup the argument type string */
|
||||||
ArgType[1].C = GetDefaultChar () | T_QUAL_CONST;
|
ArgType[1].C = T_CHAR | T_QUAL_CONST;
|
||||||
|
|
||||||
/* Evaluate the parameter */
|
/* Evaluate the parameter */
|
||||||
hie1 (&Arg);
|
hie1 (&Arg);
|
||||||
|
|||||||
@@ -233,6 +233,12 @@ static void DoCompare (const Type* lhs, const Type* rhs, typecmp_t* Result)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 'char' is neither 'signed char' nor 'unsigned char' */
|
||||||
|
if ((IsISOChar (lhs) && !IsISOChar (rhs)) ||
|
||||||
|
(!IsISOChar (lhs) && IsISOChar (rhs))) {
|
||||||
|
SetResult (Result, TC_COMPATIBLE);
|
||||||
|
}
|
||||||
|
|
||||||
/* On indirection level zero, a qualifier or sign difference is
|
/* On indirection level zero, a qualifier or sign difference is
|
||||||
** accepted. The types are no longer equal, but compatible.
|
** accepted. The types are no longer equal, but compatible.
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user