From 56b659c0be743a2630993bf4b7eaaff1c8415a2d Mon Sep 17 00:00:00 2001 From: acqn Date: Sat, 15 Aug 2020 06:27:11 +0800 Subject: [PATCH] Made char type a distinct type. --- src/cc65/datatype.c | 25 +++++++++++-------------- src/cc65/datatype.h | 34 +++++++++++++++++++++++++++------- src/cc65/declare.c | 4 ++-- src/cc65/global.h | 2 +- src/cc65/main.c | 2 +- src/cc65/stdfunc.c | 10 +++++----- src/cc65/typecmp.c | 6 ++++++ 7 files changed, 53 insertions(+), 30 deletions(-) diff --git a/src/cc65/datatype.c b/src/cc65/datatype.c index 0f3c3e5f9..b95e37f87 100644 --- a/src/cc65/datatype.c +++ b/src/cc65/datatype.c @@ -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); } diff --git a/src/cc65/datatype.h b/src/cc65/datatype.h index 54f601364..472098788 100644 --- a/src/cc65/datatype.h +++ b/src/cc65/datatype.h @@ -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); } diff --git a/src/cc65/declare.c b/src/cc65/declare.c index 36286b6d5..44d4e4142 100644 --- a/src/cc65/declare.c +++ b/src/cc65/declare.c @@ -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)))) { diff --git a/src/cc65/global.h b/src/cc65/global.h index 4ffc84a39..b9bcf5550 100644 --- a/src/cc65/global.h +++ b/src/cc65/global.h @@ -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 */ diff --git a/src/cc65/main.c b/src/cc65/main.c index 3e60bcb95..26dd721be 100644 --- a/src/cc65/main.c +++ b/src/cc65/main.c @@ -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); } diff --git a/src/cc65/stdfunc.c b/src/cc65/stdfunc.c index 6d61f2750..94e56a625 100644 --- a/src/cc65/stdfunc.c +++ b/src/cc65/stdfunc.c @@ -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); diff --git a/src/cc65/typecmp.c b/src/cc65/typecmp.c index e3e42e67f..24d9a385f 100644 --- a/src/cc65/typecmp.c +++ b/src/cc65/typecmp.c @@ -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. */