2
votes

Although "Undefined Reference error" questions have been asked several times, I couldn't find solution to my problem.

I am trying to get flex and bison to work in a Qt app. I am facing problem in linking only.

These are the relevant files-

1) icd.l - Lex specification - It generates iclexer.c and contains definition of functions-

void yyerror(char const *s){...}
void* setUpBuffer(char const* text){...}
void tearDownBuffer(void* buffer){...}
int nextToken(){...}

2) iclexer.h

#ifndef ICLEXER_H
#define ICLEXER_H

extern void  yyerror(char const *);
extern int   yylex();
extern char* yytext;
extern void* setUpBuffer(char const* text);
extern void  tearDownBuffer(void* buffer);
extern int nextToken();

#endif // ICLEXER_H

3) icparser.h

#ifndef ICPARSER_H
#define ICPARSER_H
#include "iclexer.h"
#include <string>

extern void initLexer(std::string const& t);
extern void clearLexer();
extern int yyparse();

class Parser
{
public:
    Parser(std::string const& s)
    {
        initLexer(s);
    }
    void parse()
    {
        yyparse();
    }
    ~Parser()
    {
        clearLexer();
    }
};
#endif // ICPARSER_H

4) icd.y - Bison specification - It generates icparser.cpp and contains definition of functions-

void initLexer(std::string const& t);
void clearLexer();
int yylex();

In my GUI code I include icparser.h and use class Parser's interface. But I am getting following error-

/home/vinayak/codes/qt/dic_sim/icparser.cpp:1402:
error: undefined reference to `yyerror(char const*)'

And similar errors for setUpBuffer(char const* text);, tearDownBuffer(void* buffer); and nextToken();. Basically the functions in iclexer.c are not getting linked properly.

Please tell me how to either modify this code or how to change linking order in Qt (Qt Creator)?

2
Are you compiling and linking all of your binaries? Are you using extern "C" around the C declarations?David Rodríguez - dribeas
@DavidRodríguez-dribeas: All the files are added to the project so I believe -- all the binaries are compiled and linked. No I am not using extern "C" anywhere.Vinayak Garg

2 Answers

2
votes

If the generated header file is exactly as stated, i.e. without any extern "C" then the problem you might be facing is that the C compiler will generate an unmangled symbol when compiling the function, but the C++ compiler will generate a dependency to the mangled name. The linker will see the dependency and the symbol, but not having the same name it will fail to match them together.

Take a look at the documentation of the tool used to generate the code and find how to generate C++ compatible code (usually just requires the inclusion of extra extern "C" code in the headers).

2
votes

Concerning your error: undefined reference to 'yyerror(char const*)', you might want to read the Bison documentation, and more specifically the part about yyerror. It reads:

— Method on parser: void error (const location_type& l, const std::string& m)

The definition for this member function must be supplied by the user: the parser
uses it to report a parser error occurring at l, described by m.

This definition is probably missing in your code. Note that yyerror is actually yy::parser::error, with yy:: the parser's default namespace (which can be changed with %define namespace "foo")and parser:: the parser class's name by default (which can be changed with %define parser_class_name foo).

Your other errors seem unrelated to Bison.

Edit: oh, you seem to be generating C parsers, not C++ parsers. Well, it's the same for C parsers: yyerror is user-supplied.

The following definition suffices in simple programs:

 void
 yyerror (char const *s)
 {
   fprintf (stderr, "%s\n", s);
 }