Skip to content

Commit

Permalink
CPreProcessor,C: skip #ifdef __cplusplus ~ #endif branch
Browse files Browse the repository at this point in the history
Close #2647.

C parser doesn't work when C++ code "extern "C" {" and "}" is given.

    $ cat /tmp/extern-c.c
    extern "C" {
    #ifdef X
      void f() {}
    #else
      void g() {}
    #endif
    }
    $ u-ctags --output-format=xref --kinds-c=+plz --fields=+nie -o - /tmp/extern-c.c
    f                function      3 /tmp/extern-c.c  void f() {}

    $ cat /tmp/none-extern-c.c
    #ifdef X
      void f() {}
    #else
      void g() {}
    #endif
    $ u-ctags --output-format=xref --kinds-c=+plz --fields=+nie -o - /tmp/none-extern-c.c
    f                function      2 /tmp/none-extern-c.c void f() {}
    g                function      4 /tmp/none-extern-c.c void g() {}

The function g() is missed if the code is surrounded by extern "C" { and }.

This change uses a heuristic rule to skip the code in the C parser.

In most of cases, the code is in #ifdef __cplusplus ~ #endif branch.
So when the CPreProcessor parser detects #ifdef __cplusplus ~ #endif,
with this change, the CPreProcessor parser doesn't pass the code inside __cplusplus branch
to its client parser that requests to the CPreProcessor parser to do so.

C parser requests it. C++ parser doesn't.

Signed-off-by: Masatake YAMATO <yamato@redhat.com>
  • Loading branch information
masatake committed Sep 17, 2020
1 parent d1102ea commit a26c377
Show file tree
Hide file tree
Showing 8 changed files with 41 additions and 5 deletions.
1 change: 1 addition & 0 deletions parsers/asm.c
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,7 @@ static void findAsmTags (void)
.headerKindIndex = KIND_GHOST_INDEX,
.headerSystemRoleIndex = 0,
.headerLocalRoleIndex = 0,
.skip__cplusplus_branch = false,
};
cppInit (&initData);

Expand Down
1 change: 1 addition & 0 deletions parsers/c.c
Original file line number Diff line number Diff line change
Expand Up @@ -3508,6 +3508,7 @@ static rescanReason findCTags (const unsigned int passCount)
.headerKindIndex = kind_for_header,
.headerSystemRoleIndex = role_for_header_system,
.headerLocalRoleIndex = role_for_header_local,
.skip__cplusplus_branch = !isInputLanguage (Lang_cpp),
};
cppInit (&initData);

Expand Down
29 changes: 28 additions & 1 deletion parsers/cpreprocessor.c
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,8 @@ typedef struct sCppState {

int macrodefFieldIndex;

bool skip__cplusplus_branch;

struct sDirective {
enum eState state; /* current directive being processed */
bool accept; /* is a directive syntactically permitted? */
Expand Down Expand Up @@ -317,6 +319,8 @@ static void cppInitCommon(langType clientLang, const struct cppInitData *initDat
Cpp.headerLocalRoleIndex = CPREPRO_HEADER_KIND_LOCAL_ROLE;
}

Cpp.skip__cplusplus_branch = initData->skip__cplusplus_branch;

Cpp.directive.state = DRCTV_NONE;
Cpp.directive.accept = true;
Cpp.directive.nestLevel = 0;
Expand Down Expand Up @@ -931,10 +935,32 @@ static void directivePragma (int c)
Cpp.directive.state = DRCTV_NONE;
}

static bool isDefCondition (const int c, const char *condition)
{
if (*condition == '\0')
return true;
else if (c == EOF)
return false;

if (*condition != '\0' && c == condition[0])
{
const int next = cppGetcFromUngetBufferOrFile ();
return isDefCondition (next, condition + 1);
}

return false;
}

static bool directiveIf (const int c)
{
DebugStatement ( const bool ignore0 = isIgnore (); )
const bool ignore = pushConditional ((bool) (c != '0'));
bool firstBranchChosen = true;

if (c == '0'
|| (Cpp.skip__cplusplus_branch && isDefCondition (c, "__cplusplus")))
firstBranchChosen = false;

const bool ignore = pushConditional (firstBranchChosen);

Cpp.directive.state = DRCTV_NONE;
DebugStatement ( debugCppNest (true, Cpp.directive.nestLevel);
Expand Down Expand Up @@ -1624,6 +1650,7 @@ static void findCppTags (void)
.headerKindIndex = KIND_GHOST_INDEX,
.headerSystemRoleIndex = 0,
.headerLocalRoleIndex = 0,
.skip__cplusplus_branch = false,
};

cppInitCommon (Cpp.lang, &initData);
Expand Down
2 changes: 2 additions & 0 deletions parsers/cpreprocessor.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@ struct cppInitData {
int headerKindIndex;
int headerSystemRoleIndex;
int headerLocalRoleIndex;

bool skip__cplusplus_branch; /* #ifdef __cplusplus ... #endif */
};

extern void cppInit (const struct cppInitData *initData);
Expand Down
10 changes: 6 additions & 4 deletions parsers/cxx/cxx_parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -1821,7 +1821,8 @@ bool cxxParserParseIfForWhileSwitchCatchParenthesis(void)
return true;
}

static rescanReason cxxParserMain(const unsigned int passCount)
static rescanReason cxxParserMain(const unsigned int passCount,
bool cppSkip__cpluscplus_branch)
{
cxxScopeClear();
cxxTokenAPINewFile();
Expand All @@ -1848,6 +1849,7 @@ static rescanReason cxxParserMain(const unsigned int passCount)
.headerKindIndex = kind_for_header,
.headerSystemRoleIndex = role_for_header_system,
.headerLocalRoleIndex = role_for_header_local,
.skip__cplusplus_branch = cppSkip__cpluscplus_branch,
};

cppInit(&initData);
Expand Down Expand Up @@ -1885,7 +1887,7 @@ rescanReason cxxCParserMain(const unsigned int passCount)
g_cxx.bConfirmedCPPLanguage = false;
cxxKeywordEnablePublicProtectedPrivate(false);

rescanReason r = cxxParserMain(passCount);
rescanReason r = cxxParserMain(passCount, true);
CXX_DEBUG_LEAVE();
return r;
}
Expand All @@ -1899,7 +1901,7 @@ rescanReason cxxCUDAParserMain(const unsigned int passCount)
g_cxx.bConfirmedCPPLanguage = false;
cxxKeywordEnablePublicProtectedPrivate(false);

rescanReason r = cxxParserMain(passCount);
rescanReason r = cxxParserMain(passCount, true);
CXX_DEBUG_LEAVE();
return r;
}
Expand All @@ -1915,7 +1917,7 @@ rescanReason cxxCppParserMain(const unsigned int passCount)
g_cxx.bConfirmedCPPLanguage = !isInputHeaderFile();
cxxKeywordEnablePublicProtectedPrivate(g_cxx.bConfirmedCPPLanguage);

rescanReason r = cxxParserMain(passCount);
rescanReason r = cxxParserMain(passCount, false);
CXX_DEBUG_LEAVE();
return r;
}
Expand Down
1 change: 1 addition & 0 deletions parsers/dts.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ static void runCppGetc (void)
.headerKindIndex = KIND_GHOST_INDEX,
.headerSystemRoleIndex = 0,
.headerLocalRoleIndex = 0,
.skip__cplusplus_branch = false,
};
cppInit (&initData);

Expand Down
1 change: 1 addition & 0 deletions parsers/ldscript.c
Original file line number Diff line number Diff line change
Expand Up @@ -708,6 +708,7 @@ static void findLdScriptTags (void)
.headerKindIndex = KIND_GHOST_INDEX,
.headerSystemRoleIndex = 0,
.headerLocalRoleIndex = 0,
.skip__cplusplus_branch = false,
};
cppInit (&initData);

Expand Down
1 change: 1 addition & 0 deletions parsers/protobuf.c
Original file line number Diff line number Diff line change
Expand Up @@ -666,6 +666,7 @@ static void findProtobufTags (void)
.headerKindIndex = KIND_GHOST_INDEX,
.headerSystemRoleIndex = 0,
.headerLocalRoleIndex = 0,
.skip__cplusplus_branch = false,
};
cppInit (&initData);
token.value = vStringNew ();
Expand Down

0 comments on commit a26c377

Please sign in to comment.