cppparser: Improve error messages involving macro expansion

Now shows the expansion of the macro if a parse error occurs in one.
This commit is contained in:
rdb 2024-03-27 02:23:58 +01:00
parent 6f6cbf318e
commit c5ab6573b0
2 changed files with 88 additions and 32 deletions

View File

@ -92,12 +92,13 @@ trim_blanks(const string &str) {
CPPPreprocessor::InputFile:: CPPPreprocessor::InputFile::
InputFile() { InputFile() {
_in = nullptr; _in = nullptr;
_ignore_manifest = nullptr; _manifest = nullptr;
_line_number = 0; _line_number = 0;
_col_number = 0; _col_number = 0;
_next_line_number = 1; _next_line_number = 1;
_next_col_number = 1; _next_col_number = 1;
_lock_position = false; _lock_position = false;
_ignore_manifest = false;
} }
/** /**
@ -548,6 +549,34 @@ error(const string &message, const YYLTYPE &loc) {
cerr << " error: " << message << "\n"; cerr << " error: " << message << "\n";
show_line(loc); show_line(loc);
if (!_files.empty() && !loc.file.empty()) {
Files::reverse_iterator rit;
for (rit = _files.rbegin();
rit != _files.rend() && (*rit)._file == loc.file && (*rit)._manifest != nullptr;
++rit) {
}
if (rit != _files.rbegin() && rit != _files.rend()) {
--rit;
InputFile &infile = *rit;
if (_verbose >= 3) {
cerr << "Expansion of " << infile._manifest->_name << ":\n";
cerr << " -> " << trim_blanks(infile._input) << "\n";
while (rit != _files.rbegin()) {
--rit;
InputFile &infile = *rit;
cerr << " -> " << trim_blanks(infile._input) << "\n";
}
}
else {
cerr << "with " << infile._manifest->_name;
if (infile._manifest->_has_parameters) {
cerr << "()";
}
cerr << " expanded to: " << trim_blanks(_files.back()._input) << "\n";
}
}
}
if (_error_abort) { if (_error_abort) {
cerr << "Aborting.\n"; cerr << "Aborting.\n";
abort(); abort();
@ -706,7 +735,7 @@ init_const_expr(const string &expr) {
_state = S_normal; _state = S_normal;
_saved_tokens.push_back(CPPToken(START_CONST_EXPR)); _saved_tokens.push_back(CPPToken(START_CONST_EXPR));
return push_string(expr, false); return push_string(expr);
} }
/** /**
@ -717,7 +746,7 @@ init_type(const string &type) {
_state = S_normal; _state = S_normal;
_saved_tokens.push_back(CPPToken(START_TYPE)); _saved_tokens.push_back(CPPToken(START_TYPE));
return push_string(type, false); return push_string(type);
} }
/** /**
@ -752,25 +781,54 @@ push_file(const CPPFile &file) {
* *
*/ */
bool CPPPreprocessor:: bool CPPPreprocessor::
push_string(const string &input, bool lock_position) { push_string(const string &input) {
#ifdef CPP_VERBOSE_LEX #ifdef CPP_VERBOSE_LEX
indent(cerr, _files.size() * 2) indent(cerr, _files.size() * 2)
<< "Pushing to string \"" << input << "Pushing to string \"" << input
<< "\"\nlock_position = " << lock_position << "\n"; << "\"\n";
#endif #endif
CPPFile first_file = get_file();
int first_line = get_line_number();
int first_col = get_col_number();
_files.push_back(InputFile()); _files.push_back(InputFile());
InputFile &infile = _files.back(); InputFile &infile = _files.back();
if (infile.connect_input(input)) { if (infile.connect_input(input)) {
if (lock_position) { infile._prev_last_c = _last_c;
infile._file = first_file; _last_c = '\0';
infile._line_number = first_line; return true;
infile._col_number = first_col; }
infile._lock_position = true;
#ifdef CPP_VERBOSE_LEX
indent(cerr, _files.size() * 2)
<< "Unable to read string\n";
#endif
_files.pop_back();
return false;
}
/**
*
*/
bool CPPPreprocessor::
push_expansion(const string &input, const CPPManifest *manifest, const YYLTYPE &loc) {
#ifdef CPP_VERBOSE_LEX
indent(cerr, _files.size() * 2)
<< "Pushing to expansion \"" << input
<< "\"\n";
#endif
_files.push_back(InputFile());
InputFile &infile = _files.back();
if (infile.connect_input(input)) {
infile._manifest = manifest;
infile._file = loc.file;
infile._line_number = loc.first_line;
infile._col_number = loc.first_column;
infile._lock_position = true;
if (!manifest->_has_parameters) {
// If the manifest does not use arguments, then disallow recursive
// expansion.
infile._ignore_manifest = true;
} }
infile._prev_last_c = _last_c; infile._prev_last_c = _last_c;
@ -780,7 +838,7 @@ push_string(const string &input, bool lock_position) {
#ifdef CPP_VERBOSE_LEX #ifdef CPP_VERBOSE_LEX
indent(cerr, _files.size() * 2) indent(cerr, _files.size() * 2)
<< "Unable to read string\n"; << "Unable to read expansion\n";
#endif #endif
_files.pop_back(); _files.pop_back();
@ -1888,11 +1946,11 @@ get_identifier(int c) {
} }
if (c == '(') { if (c == '(') {
// It is followed by a parenthesis, so we can expand this. // It is followed by a parenthesis, so we can expand this.
return expand_manifest(manifest); return expand_manifest(manifest, loc);
} }
} else { } else {
// Non-function-like macros are always expanded. // Non-function-like macros are always expanded.
return expand_manifest(manifest); return expand_manifest(manifest, loc);
} }
} }
if (name == "__FILE__") { if (name == "__FILE__") {
@ -2113,7 +2171,7 @@ get_literal(int token, YYLTYPE loc, const string &str, const YYSTYPE &value) {
* *
*/ */
CPPToken CPPPreprocessor:: CPPToken CPPPreprocessor::
expand_manifest(const CPPManifest *manifest) { expand_manifest(const CPPManifest *manifest, const YYLTYPE &loc) {
vector_string args; vector_string args;
if (manifest->_has_parameters) { if (manifest->_has_parameters) {
@ -2125,11 +2183,8 @@ expand_manifest(const CPPManifest *manifest) {
string expanded = " " + manifest->expand(args) + " "; string expanded = " " + manifest->expand(args) + " ";
push_string(expanded, true); push_string(expanded, true);
if (!manifest->_has_parameters) { string expanded = " " + manifest->expand(args) + " ";
// If the manifest does not use arguments, then disallow recursive push_expansion(expanded, manifest, loc);
// expansion.
_files.back()._ignore_manifest = manifest;
}
#ifdef CPP_VERBOSE_LEX #ifdef CPP_VERBOSE_LEX
indent(cerr, _files.size() * 2) indent(cerr, _files.size() * 2)
@ -2908,9 +2963,8 @@ scan_raw(int c) {
*/ */
bool CPPPreprocessor:: bool CPPPreprocessor::
should_ignore_manifest(const CPPManifest *manifest) const { should_ignore_manifest(const CPPManifest *manifest) const {
Files::const_iterator fi; for (const InputFile &infile : _files) {
for (fi = _files.begin(); fi != _files.end(); ++fi) { if (infile._ignore_manifest && infile._manifest == manifest) {
if ((*fi)._ignore_manifest == manifest) {
return true; return true;
} }
} }
@ -2924,9 +2978,8 @@ should_ignore_manifest(const CPPManifest *manifest) const {
*/ */
bool CPPPreprocessor:: bool CPPPreprocessor::
should_ignore_preprocessor() const { should_ignore_preprocessor() const {
Files::const_iterator fi; for (const InputFile &infile : _files) {
for (fi = _files.begin(); fi != _files.end(); ++fi) { if (infile._ignore_manifest) {
if ((*fi)._ignore_manifest != nullptr) {
return true; return true;
} }
} }

View File

@ -112,7 +112,9 @@ protected:
bool init_const_expr(const std::string &expr); bool init_const_expr(const std::string &expr);
bool init_type(const std::string &type); bool init_type(const std::string &type);
bool push_file(const CPPFile &file); bool push_file(const CPPFile &file);
bool push_string(const std::string &input, bool lock_position); bool push_string(const std::string &input);
bool push_expansion(const std::string &input, const CPPManifest *manifest,
const YYLTYPE &loc);
std::string expand_manifests(const std::string &input_expr, bool expand_undefined, std::string expand_manifests(const std::string &input_expr, bool expand_undefined,
const YYLTYPE &loc); const YYLTYPE &loc);
@ -151,7 +153,7 @@ private:
CPPToken get_identifier(int c); CPPToken get_identifier(int c);
CPPToken get_literal(int token, YYLTYPE loc, const std::string &str, CPPToken get_literal(int token, YYLTYPE loc, const std::string &str,
const YYSTYPE &result = YYSTYPE()); const YYSTYPE &result = YYSTYPE());
CPPToken expand_manifest(const CPPManifest *manifest); CPPToken expand_manifest(const CPPManifest *manifest, const YYLTYPE &loc);
void r_expand_manifests(std::string &expr, bool expand_undefined, void r_expand_manifests(std::string &expr, bool expand_undefined,
const YYLTYPE &loc, std::set<const CPPManifest *> &expanded); const YYLTYPE &loc, std::set<const CPPManifest *> &expanded);
void extract_manifest_args(const std::string &name, int num_args, void extract_manifest_args(const std::string &name, int num_args,
@ -192,7 +194,7 @@ private:
int get(); int get();
int peek(); int peek();
const CPPManifest *_ignore_manifest; const CPPManifest *_manifest;
CPPFile _file; CPPFile _file;
std::string _input; std::string _input;
std::istream *_in; std::istream *_in;
@ -201,6 +203,7 @@ private:
int _next_line_number; int _next_line_number;
int _next_col_number; int _next_col_number;
bool _lock_position; bool _lock_position;
bool _ignore_manifest;
int _prev_last_c; int _prev_last_c;
}; };