1
0
mirror of https://github.com/cc65/cc65.git synced 2024-12-23 04:30:10 +00:00

Added missing checks for forward declarations of the main() function.

More accurate diagnosis on implicit 'int' type specifiers.
This commit is contained in:
acqn 2024-01-23 14:33:05 +08:00
parent bea2e86210
commit ba75a2ac26
5 changed files with 50 additions and 70 deletions

View File

@ -2417,48 +2417,54 @@ int ParseDecl (DeclSpec* Spec, Declarator* D, declmode_t Mode)
/* Parse attributes for this declarator */
ParseAttribute (D);
/* 'inline' is only allowed on functions */
if (Mode != DM_ACCEPT_PARAM_IDENT &&
(D->StorageClass & SC_TYPEMASK) != SC_FUNC &&
(D->StorageClass & SC_INLINE) == SC_INLINE) {
Error ("'inline' on non-function declaration");
D->StorageClass &= ~SC_INLINE;
}
/* Check a few pre-C99 things */
if (D->Ident[0] != '\0' && (Spec->Flags & DS_TYPE_MASK) == DS_DEF_TYPE) {
/* Check and warn about an implicit int return in the function */
if (IsTypeFunc (D->Type) && IsRankInt (GetFuncReturnType (D->Type))) {
/* Function has an implicit int return. Output a warning if we don't
** have the C89 standard enabled explicitly.
/* Check a few things for the instance (rather than the type) */
if (D->Ident[0] != '\0') {
/* Check a few pre-C99 things */
if ((Spec->Flags & DS_TYPE_MASK) == DS_DEF_TYPE && IsRankInt (Spec->Type)) {
/* If the standard was not set explicitly to C89, print a warning
** for typedefs with implicit int type specifier.
*/
if (IS_Get (&Standard) >= STD_C99) {
Warning ("Implicit 'int' return type is an obsolete feature");
if ((D->StorageClass & SC_TYPEMASK) != SC_TYPEDEF) {
Warning ("Implicit 'int' type specifier is an obsolete feature");
} else {
Warning ("Type specifier defaults to 'int' in typedef of '%s'",
D->Ident);
Note ("Implicit 'int' type specifier is an obsolete feature");
}
}
GetFuncDesc (D->Type)->Flags |= FD_OLDSTYLE_INTRET;
}
/* For anything that is not a function, check for an implicit int
** declaration.
*/
if (!IsTypeFunc (D->Type) && IsRankInt (D->Type)) {
if ((D->StorageClass & SC_TYPEMASK) != SC_TYPEDEF) {
/* If the standard was not set explicitly to C89, print a warning
** for variables with implicit int type.
*/
if (IS_Get (&Standard) >= STD_C99) {
Warning ("Implicit 'int' is an obsolete feature");
/* Check other things depending on the "kind" of the instance */
if ((D->StorageClass & SC_TYPEMASK) == SC_FUNC) {
/* Special handling for main() */
if (strcmp (D->Ident, "main") == 0) {
/* main() cannot be a fastcall function */
if (IsQualFastcall (D->Type)) {
Error ("'main' cannot be declared __fastcall__");
}
} else {
/* If the standard was not set explicitly to C89, print a warning
** for typedefs with implicit int type.
*/
if (IS_Get (&Standard) >= STD_C99) {
Warning ("Type defaults to 'int' in typedef of '%s'",
D->Ident);
Note ("Implicit 'int' is an obsolete feature");
/* main() cannot be an inline function */
if ((D->StorageClass & SC_INLINE) == SC_INLINE) {
Error ("'main' cannot be declared inline");
D->StorageClass &= ~SC_INLINE;
}
/* Check return type */
if (GetUnqualRawTypeCode (GetFuncReturnType (D->Type)) != T_INT) {
/* If cc65 extensions aren't enabled, don't allow a main function
** that doesn't return an int.
*/
if (IS_Get (&Standard) != STD_CC65) {
Error ("'main' must always return an int");
}
}
}
} else if (Mode != DM_ACCEPT_PARAM_IDENT &&
(D->StorageClass & SC_INLINE) == SC_INLINE) {
/* 'inline' is only allowed on functions */
Error ("'inline' on non-function declaration");
D->StorageClass &= ~SC_INLINE;
}
}

View File

@ -450,7 +450,6 @@ void NewFunc (SymEntry* Func, FuncDesc* D)
/* Parse argument declarations and function body. */
{
int ParamComplete; /* If all paramemters have complete types */
int C99MainFunc = 0;/* Flag for C99 main function returning int */
SymEntry* Param;
const Type* RType; /* Real type used for struct parameters */
const Type* ReturnType; /* Return type */
@ -513,34 +512,6 @@ void NewFunc (SymEntry* Func, FuncDesc* D)
/* Mark this as the main function */
CurrentFunc->Flags |= FF_IS_MAIN;
/* Main cannot be a fastcall function */
if (IsQualFastcall (Func->Type)) {
Error ("'main' cannot be declared as __fastcall__");
}
/* main() cannot be an inline function */
if ((Func->Flags & SC_INLINE) == SC_INLINE) {
Error ("'main' cannot be declared inline");
Func->Flags &= ~SC_INLINE;
}
/* Check return type */
if (GetUnqualRawTypeCode (ReturnType) == T_INT) {
/* Determine if this is a main function in a C99 environment that
** returns an int.
*/
if (IS_Get (&Standard) >= STD_C99) {
C99MainFunc = 1;
}
} else {
/* If cc65 extensions aren't enabled, don't allow a main function
** that doesn't return an int.
*/
if (IS_Get (&Standard) != STD_CC65) {
Error ("'main' must always return an int");
}
}
/* Add a forced import of a symbol that is contained in the startup
** code. This will force the startup code to be linked in.
*/
@ -665,7 +636,7 @@ void NewFunc (SymEntry* Func, FuncDesc* D)
/* If this is the main function in a C99 environment returning an int,
** let it always return zero. Otherwise output a warning.
*/
if (C99MainFunc) {
if (IS_Get (&Standard) >= STD_C99 && GetUnqualRawTypeCode (ReturnType) == T_INT) {
g_getimmed (CF_INT | CF_CONST, 0, 0);
} else if (IS_Get (&WarnReturnType)) {
Warning ("Control reaches end of non-void function [-Wreturn-type]");

View File

@ -1,4 +1,4 @@
bug1889-missing-identifier.c:3: Error: Identifier or ';' expected after declaration specifiers
bug1889-missing-identifier.c:3: Warning: Implicit 'int' is an obsolete feature
bug1889-missing-identifier.c:3: Warning: Implicit 'int' type specifier is an obsolete feature
bug1889-missing-identifier.c:4: Error: 'inline' on empty declaration
bug1889-missing-identifier.c:6: Error: Expression expected

View File

@ -33,4 +33,6 @@ inline int main(void) /* Error */
f2b(); /* Still imported */
}
inline int main(void); /* Error */
/* Warning: non-external inline functions declared but undefined in TU */

View File

@ -13,8 +13,9 @@ inline-error.c:22: Error: 'inline' on non-function declaration
inline-error.c:23: Error: 'inline' on non-function declaration
inline-error.c:24: Error: 'inline' on non-function declaration
inline-error.c:34: Warning: Variable 'fp2' is defined but never used
inline-error.c:37: Warning: Inline function 'f1a' used but never defined
inline-error.c:37: Warning: Inline function 'f1b' used but never defined
inline-error.c:37: Warning: Static function 'f1c' used but never defined
inline-error.c:37: Warning: Inline function 'f2a' used but never defined
inline-error.c:37: Warning: Inline function 'f2b' used but never defined
inline-error.c:36: Error: 'main' cannot be declared inline
inline-error.c:39: Warning: Inline function 'f1a' used but never defined
inline-error.c:39: Warning: Inline function 'f1b' used but never defined
inline-error.c:39: Warning: Static function 'f1c' used but never defined
inline-error.c:39: Warning: Inline function 'f2a' used but never defined
inline-error.c:39: Warning: Inline function 'f2b' used but never defined