-
Notifications
You must be signed in to change notification settings - Fork 80
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Issue# 168: Fix invalidHashHash exception on valid token. #169
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -741,6 +741,31 @@ static void hashhash9() | |
ASSERT_EQUALS("file0,1,syntax_error,failed to expand 'A', Invalid ## usage when expanding 'A'.\n", toString(outputList)); | ||
} | ||
|
||
static void hashhash10() //Paste string constant, integer, real to user defined literal | ||
{ | ||
const char *code = "#define A(x) x##_y\n" | ||
"A(\"A\");\n" | ||
"A('A');\n" | ||
"A(1.0);\n" | ||
"A(1);"; | ||
|
||
const char expected[] = "\n\"A\"_y ;\n" | ||
"'A'_y ;\n" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am not sure we should generate such tokens. If a token starts with a How about outputting something like There was some tweak in Cppcheck for these operators a while ago I am not sure how that works. Can you double check? It would be good if we match that. Define such operator and look at the debug output There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I copied these changes to simplecpp in cppcheck and ran cppcheck on the below file:
#include <cstdlib>
#define NUM_CHAR(str) str##_numch
#define X(str) str##_x
#define Y(ch) ch##_y
#define Z(val) val##_z
inline auto operator "" _x(const char *ch, std::size_t size) noexcept -> std::size_t
{
return size;
}
inline auto operator "" _y(char ch) noexcept -> double
{
return static_cast<double>(ch) * 0.25;
}
inline auto operator ""_z(long double val) noexcept -> const char *
{
return (val < 0.5) ? "ABC" : "EFG";
}
int main()
{
auto a = "abc"_x;
auto b = X("abc");
auto c = 't'_y;
auto d = Y('t');
auto e = 1.0_z;
auto f = Z(1.0);
auto g = operator"" _x( "abc", 3);
auto h = operator"" _x("abc"); // Wrong signature
} As you thought, the change caused an error to be generated by cppcheck. I removed the macros and ran it again to see what it produces normally, and made the following further change to try to mimic how it appeared to be handling them: // @line 1842:
if (isStringConstant || isCharConstant)
output->push_back(new Token(*B));
else if (varargs ... //etc With this change, cppcheck runs and does not produce an error. Some select output from --debug and --verbose below:
From that it looks like just splitting it into two tokens and discarding the ## is doing the same as cppcheck is right now. It seems cppcheck is mostly just ignoring these operators right now. It has at least got the type wrong for all cases. Should we go ahead with this to make it like how cppcheck processes it, or try There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks! That is a good investigation. I feel much more comfortable now. :-)
I suggest the first option for now. We need to handle this better in cppcheck. |
||
"1.0_y ;\n" | ||
"1_y ;"; | ||
|
||
ASSERT_EQUALS(expected, preprocess(code)); | ||
|
||
const simplecpp::DUI dui; | ||
simplecpp::OutputList outputList; | ||
|
||
code = "#define A(x) x##123\n" | ||
"A(\"A\");"; | ||
outputList.clear(); | ||
preprocess(code, dui, &outputList); | ||
ASSERT_EQUALS("file0,1,syntax_error,failed to expand 'A', Invalid ## usage when expanding 'A'.\n", toString(outputList)); | ||
} | ||
|
||
static void hashhash_invalid_1() | ||
{ | ||
std::istringstream istr("#define f(a) (##x)\nf(1)"); | ||
|
@@ -1882,6 +1907,7 @@ int main(int argc, char **argv) | |
TEST_CASE(hashhash7); // # ## # (C standard; 6.10.3.3.p4) | ||
TEST_CASE(hashhash8); | ||
TEST_CASE(hashhash9); | ||
TEST_CASE(hashhash10); | ||
TEST_CASE(hashhash_invalid_1); | ||
TEST_CASE(hashhash_invalid_2); | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Err.. suppose ''' is a character constant not covered by the rule it's defining 😆