cplusplus icon indicating copy to clipboard operation
cplusplus copied to clipboard

Preprocessor macro problem

Open mingodad opened this issue 2 years ago • 4 comments

While testing some files I've used to test https://github.com/tyfkda/xcc I found one that cxx stil can't handle:

#define FOO(x)  {x}

FOO(
#if 1
    bar
#else
    qux
#endif
)
g++ -E foo-if.c
# 1 "foo-if.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 1 "<command-line>" 2
# 1 "foo-if.c"
{bar}
cxx -E foo-if.c
# 1 "foo-if.c"
{
# 5 "foo-if.c"
bar

Notice that cxx is eating the closing brace !

mingodad avatar Dec 29 '23 12:12 mingodad

I've been testing this C++ parser https://github.com/panda3d/panda3d/tree/master/dtool/src/cppparser and we had a bit of work done with it's preprocessor here https://github.com/panda3d/panda3d/issues/1638 probably it's worth for you to now about it and maybe even collaborate both ways with then.

mingodad avatar Mar 28 '24 19:03 mingodad

Even when adding other text at the end of the macro the output miss the closing brace:

#define FOO(x)  {x}

FOO(
#if 1
    bar
#else
    qux
#endif
)
int x;

Output:

# 1 "foo-if.c"
                {
    bar
int x;

mingodad avatar Aug 09 '24 17:08 mingodad

The problem seem to be here : https://github.com/robertoraggi/cplusplus/blob/3b93d2b26a953d66c6b2845b48db87593a68702f/src/parser/cxx/preprocessor.cc#L2658-L2665 When skipping the endif you are only breaking the loop when it->bol is true but when tokenizing the } is not marked with bol equals true and is skipped, we need another way to manage it here.

mingodad avatar Aug 09 '24 18:08 mingodad

With this hack it seems to work, all tests pass and it parses sqlite3.c so far:

------------------------ src/parser/cxx/preprocessor.cc ------------------------
index c07548e..2fe9d51 100644
@@ -1651,7 +1651,8 @@ auto Preprocessor::Private::expand(
 
     if (const auto start = it; it->bol && match(it, last, TokenKind::T_HASH)) {
       // skip the rest of the line
-      it = skipLine(it, last);
+      if (it->kind == TokenKind::T_IDENTIFIER && it->text == "endif") ++it;
+      else it = skipLine(it, last);
 
       if (auto parsedInclude = parseDirective(source, start.toTokList())) {
         NeedToResolveInclude status{

Output:

# 1 "foo-if.c"
                {
    bar }
int x;

mingodad avatar Aug 09 '24 18:08 mingodad