DeclSpec Spec;
Declaration Decl;
+ SymEntry* Sym;
/* Allow an ellipsis as last parameter */
if (CurTok.Tok == TOK_ELLIPSIS) {
ParseAttribute (&Decl);
/* Create a symbol table entry */
- AddLocalSym (Decl.Ident, ParamTypeCvt (Decl.Type), Decl.StorageClass, 0);
+ Sym = AddLocalSym (Decl.Ident, ParamTypeCvt (Decl.Type), Decl.StorageClass, 0);
+
+ /* Add attributes if we have any */
+ SymUseAttributes (Sym, &Decl);
/* If the parameter is a struct or union, emit a warning */
if (IsClassStruct (Decl.Type)) {
* the breaks above bail out without checking.
*/
ConsumeRParen ();
-
- /* Check if this is a function definition */
- if (CurTok.Tok == TOK_LCURLY) {
- /* Print an error if we have unnamed parameters and cc65 extensions
- * are disabled.
- */
- if (IS_Get (&Standard) != STD_CC65 && (F->Flags & FD_UNNAMED_PARAMS)) {
- Error ("Parameter name omitted");
- }
- }
}
-static FuncDesc* ParseFuncDecl (Declaration* D)
+static FuncDesc* ParseFuncDecl (void)
/* Parse the argument list of a function. */
{
unsigned Offs;
/* New style function */
ParseAnsiParamList (F);
- /* Allow attributes */
- ParseAttribute (D);
-
- /* Check if this is a function definition */
- if (CurTok.Tok == TOK_LCURLY) {
- /* Print an error if we have unnamed parameters and cc65 extensions
- * are disabled.
- */
- if (IS_Get (&Standard) != STD_CC65 &&
- (F->Flags & FD_UNNAMED_PARAMS)) {
- Error ("Parameter name omitted");
- }
- }
-
} else {
/* Old style function */
ParseOldStyleParamList (F);
NextToken ();
/* Parse the function declaration */
- F = ParseFuncDecl (D);
+ F = ParseFuncDecl ();
/* We cannot specify fastcall for variadic functions */
if ((F->Flags & FD_VARIADIC) && (Qualifiers & T_QUAL_FASTCALL)) {
D->StorageClass |= SC_FUNC;
}
+ /* Parse attributes for this declaration */
+ ParseAttribute (D);
+
/* Check several things for function or function pointer types */
if (IsTypeFunc (D->Type) || IsTypeFuncPtr (D->Type)) {
/* Forwards for attribute handlers */
static void NoReturnAttr (Declaration* D);
+static void UnusedAttr (Declaration* D);
};
static const AttrDesc AttrTable [] = {
{ "__noreturn__", NoReturnAttr },
+ { "__unused__", UnusedAttr },
{ "noreturn", NoReturnAttr },
+ { "unused", UnusedAttr },
};
-void NoReturnAttr (Declaration* D)
+static void NoReturnAttr (Declaration* D)
/* Parse the "noreturn" attribute */
{
/* Add the noreturn attribute */
+static void UnusedAttr (Declaration* D)
+/* Parse the "unused" attribute */
+{
+ /* Add the noreturn attribute */
+ AddAttr (D, NewDeclAttr (atUnused));
+}
+
+
+
void ParseAttribute (Declaration* D)
/* Parse an additional __attribute__ modifier */
{
/* Supported attribute types */
typedef enum {
- atNone = -1, /* No attribute */
atNoReturn, /* Function does not return */
-
- atCount /* Number of attributes */
+ atUnused, /* Symbol is unused - don't warn */
} DeclAttrType;
/* An actual attribute description */
/* Reenter the lexical level */
ReenterFunctionLevel (D);
+ /* Check if the function header contains unnamed parameters. These are
+ * only allowed in cc65 mode.
+ */
+ if ((D->Flags & FD_UNNAMED_PARAMS) != 0 && (IS_Get (&Standard) != STD_CC65)) {
+ Error ("Parameter name omitted");
+ }
+
/* Declare two special functions symbols: __fixargs__ and __argsize__.
* The latter is different depending on the type of the function (variadic
* or not).
*/
AddConstSym ("__fixargs__", type_uint, SC_DEF | SC_CONST, D->ParamSize);
if (D->Flags & FD_VARIADIC) {
- /* Variadic function. The variable must be const. */
- static const Type T[] = { TYPE(T_UCHAR | T_QUAL_CONST), TYPE(T_END) };
- AddLocalSym ("__argsize__", T, SC_DEF | SC_REF | SC_AUTO, 0);
+ /* Variadic function. The variable must be const. */
+ static const Type T[] = { TYPE(T_UCHAR | T_QUAL_CONST), TYPE(T_END) };
+ AddLocalSym ("__argsize__", T, SC_DEF | SC_REF | SC_AUTO, 0);
} else {
- /* Non variadic */
+ /* Non variadic */
AddConstSym ("__argsize__", type_uchar, SC_DEF | SC_CONST, D->ParamSize);
}
/* If this is a fastcall function, push the last parameter onto the stack */
if (IsQualFastcall (Func->Type) && D->ParamCount > 0) {
- unsigned Flags;
+ unsigned Flags;
- /* Fastcall functions may never have an ellipsis or the compiler is buggy */
- CHECK ((D->Flags & FD_VARIADIC) == 0);
+ /* Fastcall functions may never have an ellipsis or the compiler is buggy */
+ CHECK ((D->Flags & FD_VARIADIC) == 0);
- /* Generate the push */
- if (IsTypeFunc (D->LastParam->Type)) {
+ /* Generate the push */
+ if (IsTypeFunc (D->LastParam->Type)) {
/* Pointer to function */
Flags = CF_PTR;
} else {
* defined but not used.
*/
if (((Flags & SC_AUTO) || (Flags & SC_STATIC)) && (Flags & SC_EXTERN) == 0) {
- if (SymIsDef (Entry) && !SymIsRef (Entry)) {
+ if (SymIsDef (Entry) && !SymIsRef (Entry) &&
+ SymGetAttribute (Entry, atUnused) == 0) {
if (Flags & SC_PARAM) {
if (IS_Get (&WarnUnusedParam)) {
Warning ("Parameter `%s' is never used", Entry->Name);