Search code examples
cfreebsdyaccc89ansi-c

Implicit declaration/conflicting types for 'warning' while compiling a basic sample (hoc1) yacc program


I am following the classic Kernighan & Pike The Unix Programming Environment; specifically the chapter that covers yacc. In the first example, a basic calculator named hoc1 is prepared with yacc.

Following the book I prepare the following code:

%{
#define YYSTYPE double
%}
%token NUMBER
%left '+' '-'
%left '*' '/'
%%
list:
    | list '\n'
    | list expr '\n'    { printf("\t%.8g\n", $2); }
    ;
expr:     NUMBER        { $$ = $1; }
    | expr '+' expr     { $$ = $1 + $3; }
    | expr '-' expr     { $$ = $1 - $3; }
    | expr '*' expr     { $$ = $1 * $3; }
    | expr '/' expr     { $$ = $1 / $3; }
    | '(' expr ')'      { $$ = $2; }
    ;
%%

#include <stdio.h>
#include <ctype.h>
char    *progname;
int lineno = 1;

int main(int argc, char *argv[]) {

    progname = argv[0];
    yyparse();
    
}


int yylex(void) {

    int c;
    
    /* Left trim all spaces/tabs */
    while((c=getchar()) == ' ' || c == '\t');
    
    /* Return 0 if EOF */
    if(c== EOF) {
        return 0;
    }
    
    /* Return NUMBER if number */
    if(c=='.' || isdigit(c)) {
        ungetc(c,stdin);
        scanf("%lf", &yylval);
        return NUMBER;
    }
    
    /* Count lines */
    if(c=='\n') {
        lineno++;
    }
    
    return c;       
    
}

void yyerror(char *s) {
    
    warning(s, (char *)0);

}

void warning(char *s, char *t) {

    fprintf(stderr, "%s: %s", progname, s);
    if(t) {
        fprintf(stderr, " %s", t);
    }
    fprintf(stderr, " near line %d\n", lineno);

}

But I get the following error while compiling the program:

~/tutorials/unix_programming_environment/hoc1 % yacc hoc1.y

~/tutorials/unix_programming_environment/hoc1 % cc y.tab.c -o hoc1

hoc1.y:64:2: warning: implicit declaration of function 'warning' is invalid in C99 [-Wimplicit-function-declaration]
        warning(s, (char *)0);
        ^
hoc1.y:68:6: error: conflicting types for 'warning'
void warning(char *s, char *t) {
     ^
hoc1.y:64:2: note: previous implicit declaration is here
        warning(s, (char *)0);
        ^
1 warning and 1 error generated.

I do not understand neither the warning or the error.

Edit: using yacc in FreeBSD 12.1


Solution

  • Move the definition of the yyerror function after the definition of the warning function or put this line before the yyerror function:

    void warning(char *, char *);
    

    This compiler message:

    hoc1.y:64:2: warning: implicit declaration of function 'warning' is invalid in C99 [-Wimplicit-function-declaration]
    

    tells you that the function warning is being used before any declaration of it is seen. This results in an implicit declaration due to the history of the C language.

    This compiler message:

    hoc1.y:68:6: error: conflicting types for 'warning'
    

    tells you that the actual definition of warning has a different type than that of the implicit declaration from above.

    This solution to this is to declare warning before using it, which you can do either by putting the definition (which is a declaration) before the use or by putting a separate declaration before the use.