mirror of
https://github.com/cc65/cc65.git
synced 2024-12-24 11:31:31 +00:00
Made char type a distinct type.
This commit is contained in:
parent
87889df9e9
commit
56b659c0be
@ -59,6 +59,7 @@
|
||||
|
||||
|
||||
/* Predefined type strings */
|
||||
Type type_char[] = { TYPE(T_CHAR), TYPE(T_END) };
|
||||
Type type_schar[] = { TYPE(T_SCHAR), TYPE(T_END) };
|
||||
Type type_uchar[] = { TYPE(T_UCHAR), 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)
|
||||
/* Return the type for a char array of the given length */
|
||||
{
|
||||
@ -448,7 +441,7 @@ Type* GetCharArrayType (unsigned Len)
|
||||
/* Fill the type string */
|
||||
T[0].C = T_ARRAY;
|
||||
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;
|
||||
|
||||
/* Return the new type */
|
||||
@ -685,8 +678,9 @@ int TypeHasAttr (const Type* T)
|
||||
const Type* GetUnderlyingType (const Type* 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 */
|
||||
if (Type->A.P == 0) {
|
||||
Internal ("Enum tag type error in GetUnderlyingTypeCode");
|
||||
@ -708,8 +702,11 @@ TypeCode GetUnderlyingTypeCode (const Type* Type)
|
||||
TypeCode Underlying = UnqualifiedType (Type->C);
|
||||
TypeCode TCode;
|
||||
|
||||
/* We could also support other T_CLASS_INT types, but just enums for now */
|
||||
if (IsTypeEnum (Type)) {
|
||||
if (IsISOChar (Type)) {
|
||||
|
||||
return IS_Get (&SignedChars) ? T_SCHAR : T_UCHAR;
|
||||
|
||||
} else if (IsTypeEnum (Type)) {
|
||||
|
||||
/* This should not happen, but just in case */
|
||||
if (Type->A.P == 0) {
|
||||
@ -996,7 +993,7 @@ int IsClassArithmetic (const Type* T)
|
||||
int IsClassBasic (const Type* T)
|
||||
/* 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,
|
||||
|
||||
/* 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_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,
|
||||
@ -189,6 +189,7 @@ struct Type {
|
||||
#define PTR_BITS (8 * SIZEOF_PTR)
|
||||
|
||||
/* Predefined type strings */
|
||||
extern Type type_char[];
|
||||
extern Type type_schar[];
|
||||
extern Type type_uchar[];
|
||||
extern Type type_int[];
|
||||
@ -250,9 +251,6 @@ void TypeFree (Type* T);
|
||||
int SignExtendChar (int C);
|
||||
/* 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);
|
||||
/* 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)
|
||||
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);
|
||||
}
|
||||
@ -395,7 +393,7 @@ INLINE int IsTypeInt (const Type* T)
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
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);
|
||||
}
|
||||
@ -403,9 +401,31 @@ INLINE int IsTypeLong (const Type* T)
|
||||
# define IsTypeLong(T) (GetRawType (GetUnderlyingType (T)) == T_TYPE_LONG)
|
||||
#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)
|
||||
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);
|
||||
}
|
||||
|
@ -1169,7 +1169,7 @@ static void ParseTypeSpec (DeclSpec* D, long Default, TypeCode Qualifiers)
|
||||
|
||||
case TOK_CHAR:
|
||||
NextToken ();
|
||||
D->Type[0].C = GetDefaultChar();
|
||||
D->Type[0].C = T_CHAR;
|
||||
D->Type[1].C = T_END;
|
||||
break;
|
||||
|
||||
@ -2195,7 +2195,7 @@ static unsigned ParseArrayInit (Type* T, int* Braces, int AllowFlexibleMembers)
|
||||
long ElementCount = GetElementCount (T);
|
||||
|
||||
/* 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_LCURLY &&
|
||||
(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 RegVarsToCallStack; /* Save reg variables on call stack */
|
||||
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 Optimize; /* Optimize flag */
|
||||
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)),
|
||||
const char* Arg attribute ((unused)))
|
||||
/* Make default characters signed */
|
||||
/* Use 'signed char' as the underlying type of 'char' */
|
||||
{
|
||||
IS_Set (&SignedChars, 1);
|
||||
}
|
||||
|
@ -783,8 +783,8 @@ static void StdFunc_strcmp (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
|
||||
int Offs;
|
||||
|
||||
/* Setup the argument type string */
|
||||
Arg1Type[1].C = GetDefaultChar () | T_QUAL_CONST;
|
||||
Arg2Type[1].C = GetDefaultChar () | T_QUAL_CONST;
|
||||
Arg1Type[1].C = T_CHAR | T_QUAL_CONST;
|
||||
Arg2Type[1].C = T_CHAR | T_QUAL_CONST;
|
||||
|
||||
/* Argument #1 */
|
||||
ParseArg (&Arg1, Arg1Type);
|
||||
@ -983,8 +983,8 @@ static void StdFunc_strcpy (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
|
||||
unsigned L1;
|
||||
|
||||
/* Setup the argument type string */
|
||||
Arg1Type[1].C = GetDefaultChar ();
|
||||
Arg2Type[1].C = GetDefaultChar () | T_QUAL_CONST;
|
||||
Arg1Type[1].C = T_CHAR;
|
||||
Arg2Type[1].C = T_CHAR | T_QUAL_CONST;
|
||||
|
||||
/* Argument #1 */
|
||||
ParseArg (&Arg1, Arg1Type);
|
||||
@ -1181,7 +1181,7 @@ static void StdFunc_strlen (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
|
||||
unsigned L;
|
||||
|
||||
/* Setup the argument type string */
|
||||
ArgType[1].C = GetDefaultChar () | T_QUAL_CONST;
|
||||
ArgType[1].C = T_CHAR | T_QUAL_CONST;
|
||||
|
||||
/* Evaluate the parameter */
|
||||
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
|
||||
** accepted. The types are no longer equal, but compatible.
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user