Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 9 additions & 18 deletions simplecpp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1692,10 +1692,9 @@ namespace simplecpp {
}

/** base class for errors */
struct Error {
Error(const Location &loc, const std::string &s) : location(loc), what(s) {}
struct Error : public std::runtime_error {
Error(const Location &loc, const std::string &s) : std::runtime_error(s), location(loc) {}
const Location location;
const std::string what;
};

/** Struct that is thrown when macro is expanded with wrong number of parameters */
Expand Down Expand Up @@ -1739,6 +1738,9 @@ namespace simplecpp {
return tok;
}

/**
* @throws Error thrown in case of __VA_OPT__ issues
*/
bool parseDefine(const Token *nametoken) {
nameTokDef = nametoken;
variadic = false;
Expand Down Expand Up @@ -3278,7 +3280,7 @@ static bool preprocessToken(simplecpp::TokenList &output, const simplecpp::Token
simplecpp::Output out{
simplecpp::Output::SYNTAX_ERROR,
err.location,
"failed to expand \'" + tok->str() + "\', " + err.what
"failed to expand \'" + tok->str() + "\', " + err.what()
};
outputList->emplace_back(std::move(out));
}
Expand Down Expand Up @@ -3507,23 +3509,12 @@ void simplecpp::preprocess(simplecpp::TokenList &output, const simplecpp::TokenL
else
it->second = macro;
}
} catch (const std::runtime_error &) {
} catch (const std::runtime_error &err) {
if (outputList) {
simplecpp::Output err{
simplecpp::Output out{
Output::SYNTAX_ERROR,
rawtok->location,
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this will not read the location from the exception. are you 100% sure that exception provides the rawtok location?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. The location in the existing test did not change so I missed that. The issue is that the tests do not provide a filename. I will improve the tests.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if the location here is actually correct since a std::runtime_error can already be thrown from several places. We should possibly throw a custom class.

I will adjust this PR to add the additional exception handling to address the issue and extract all the further changes into a separate PR.

"Failed to parse #define"
};
outputList->emplace_back(std::move(err));
}
output.clear();
return;
} catch (const simplecpp::Macro::Error &err) {
if (outputList) {
simplecpp::Output out{
simplecpp::Output::SYNTAX_ERROR,
err.location,
"Failed to parse #define, " + err.what
std::string("Failed to parse #define, ") + err.what()
};
outputList->emplace_back(std::move(out));
}
Expand Down
14 changes: 12 additions & 2 deletions test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -687,15 +687,15 @@ static void define_invalid_1()
const char code[] = "#define A(\nB\n";
simplecpp::OutputList outputList;
ASSERT_EQUALS("", preprocess(code, &outputList));
ASSERT_EQUALS("file0,1,syntax_error,Failed to parse #define\n", toString(outputList));
ASSERT_EQUALS("file0,1,syntax_error,Failed to parse #define, bad macro syntax\n", toString(outputList));
}

static void define_invalid_2()
{
const char code[] = "#define\nhas#";
simplecpp::OutputList outputList;
ASSERT_EQUALS("", preprocess(code, &outputList));
ASSERT_EQUALS("file0,1,syntax_error,Failed to parse #define\n", toString(outputList));
ASSERT_EQUALS("file0,1,syntax_error,Failed to parse #define, bad macro syntax\n", toString(outputList));
}

static void define_define_1()
Expand Down Expand Up @@ -1094,6 +1094,15 @@ static void define_va_opt_8()
ASSERT_EQUALS("", toString(outputList));
}

static void define_va_opt_9()
{
simplecpp::DUI dui;
dui.defines.emplace_back("f(...)=__VA_OPT__");
simplecpp::OutputList outputList;
ASSERT_EQUALS("", preprocess("", dui, &outputList));
ASSERT_EQUALS("file0,0,dui_error,In definition of 'f': Missing opening parenthesis for __VA_OPT__\n", toString(outputList));
}

static void define_ifdef()
{
const char code[] = "#define A(X) X\n"
Expand Down Expand Up @@ -3599,6 +3608,7 @@ int main(int argc, char **argv)
TEST_CASE(define_va_opt_6);
TEST_CASE(define_va_opt_7);
TEST_CASE(define_va_opt_8);
TEST_CASE(define_va_opt_9); // #632

TEST_CASE(pragma_backslash); // multiline pragma directive

Expand Down