Made char type a distinct type.

This commit is contained in:
acqn
2020-08-15 06:27:11 +08:00
committed by Oliver Schmidt
parent 87889df9e9
commit 56b659c0be
7 changed files with 53 additions and 30 deletions

View File

@@ -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);
} }

View File

@@ -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);
} }

View File

@@ -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)))) {

View File

@@ -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 */

View File

@@ -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);
} }

View File

@@ -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);

View File

@@ -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.
*/ */