在 Ubuntu 中,gcc 报告在 macOS 中未报告的函数声明错误

In Ubuntu gcc reports function declaration errors that did not report in macOS

我正尝试与队友一起使用 lex 和 yacc 构建一个简单的语言编译器。在我的 macOS 上一切顺利,但是在 win10 和 Ubuntu gcc 中报告错误。
起初我在我的 parser.y 中包含 "lex.yy.c",并且 解决了 multiple definition of main() 的错误,但是更多的错误和警告被更改:

ask.y:80:6: error: conflicting types for 'addBro'
void addBro( struct node *Leftbro, struct node *Rightbro) {     
     ^
ask.y:13:10: note: previous declaration is here
    void addBro( struct node *Leftbro, struct node *Rightbro);
         ^
ask.y:84:6: error: conflicting types for 'printTree'
void printTree(struct node *n, int type,  int level)
     ^
ask.y:11:7: note: previous declaration is here
        void printTree(struct node *tree, int type,  int level);  

我运行thirf命令后出现三个命令和错误

  1. yacc -v -d parser.y
  2. lex lexer.l
  3. gcc -Wall -o example y.tab.c lex.yy.c

gcc 和 Ubuntu 版本:gcc (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0

最小的例子是:

  1. parser.y:
%{
    #include<stdio.h>
    #include<string.h>
    #include<stdlib.h>
    #include<ctype.h>
    #define COUNT 5
    void yyerror(const char *s);
    int yylex();
    int yywrap();
    void printtree(struct node*);
    void printTree(struct node *tree, int type,  int level);  
    
    void addBro( struct node *Leftbro, struct node *Rightbro);
    struct node* mknode( char *token);
    struct node* addKid( struct node *kid,char *token);

    int count=0;
    int q;
    char type[10];
    extern int countn;
    struct node *head;
    struct node { 
        struct node *firstKid;
        struct node *rightBro;
        char *token; 
    };
%}

%union { 
    struct var_name { 
        char name[100]; 
        struct node* nd;
    } nd_obj; 
} 

%start P
%token <nd_obj> EQ  SEMI ID
// NUMBER
%type <nd_obj> P  S F

%%
/* descriptions of expected inputs     corresponding actions (in C) */
P       : S                     {$$.nd = addKid(.nd,"P");head=$$.nd;}
;
S       : ID EQ F               {.nd=mknode("ID");.nd=mknode("=");
                                addBro(.nd,.nd);addBro(.nd,.nd);
                                $$.nd = addKid(.nd,"S");}
;
F       :ID                     {.nd=mknode("ID");
                                $$.nd=addKid(.nd,"F");}                                                             
;
%%                     /* C code */

int main() {
    yyparse();
    //printtree(head); 
    printTree(head,0,0);
    printf("\n\n");
}

struct node* addKid( struct node *kid,char *token) {    
    struct node *newnode = (struct node *)malloc(sizeof(struct node));
    char *newstr = (char *)malloc(strlen(token)+1);
    strcpy(newstr, token);
    newnode->firstKid = kid;
    newnode->rightBro = NULL;
    newnode->token = newstr;
    return(newnode);
}
struct node* mknode( char *token) { 
    struct node *newnode = (struct node *)malloc(sizeof(struct node));
    char *newstr = (char *)malloc(strlen(token)+1);
    strcpy(newstr, token);
    newnode->firstKid = NULL;
    newnode->rightBro = NULL;
    newnode->token = newstr;
    return(newnode);
}
//addBro(.nd,.nd);
void addBro( struct node *Leftbro, struct node *Rightbro) { 
    Leftbro->rightBro = Rightbro;
}

void printTree(struct node *n, int type,  int level)
{
    int i;

    if (NULL == n)
        return;

    printTree(n->rightBro, 2, level);
    switch (type)
    {
    case 0:
        printf("%2s\n", n->token);
        break;
    case 1:
        for (i = 0; i < level; i++) 
            printf("\t");
        printf("\n");
        for (i = 0; i < level; i++) 
            printf("\t");
        printf("%2s\n", n->token);

        break;
    case 2:

        for (i = 0; i < level; i++) 
            printf("\t");
        printf("%2s\n", n->token);
        for (i = 0; i < level; i++) 
            printf("\t");
        printf("\n");
        break;  
    }
    printTree(n->firstKid, 1,  level+1);
}

void yyerror(const char* msg) {
    fprintf(stderr, "%s\n", msg);
}
  1. lexer.l:
%{
    #include "y.tab.h"
    int countn=0;
%}

%option yylineno

alpha [a-zA-Z]
digit [0-9]
%%
"="    {strcpy(yylval.nd_obj.name,(yytext)); return EQ;}

{alpha}({alpha}|{digit})*   {strcpy(yylval.nd_obj.name,(yytext));  return ID; }

\/\/.*                      { ; }
\/\*(.*\n)*.*\*\/           { ; } 
[ \t]*                      { ; }
[\n]                        { countn++; }
.                       { return *yytext; }
%%

int yywrap() {
    return 1;
}

输入文件in.in:

a=b

查看警告。 .

您的代码以此开头:

parser.y:10:27: warning: ‘struct node’ declared inside parameter list 
will not be visible outside of this definition or declaration
   10 |     void printtree(struct node*);
      |                           ^~~~

此处声明的 struct node 是该函数声明的局部变量,不同于其他地方声明的任何 struct node,因此通常是无用的。这正是 C 标准所说的。

解决方法:添加一行

struct node;

在函数声明之前