Skip to content
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

Empty output when calculating metrics for this function in C #1006

Open
MartinLwx opened this issue Feb 23, 2023 · 5 comments
Open

Empty output when calculating metrics for this function in C #1006

MartinLwx opened this issue Feb 23, 2023 · 5 comments

Comments

@MartinLwx
Copy link

Description

I attempted to extract code metrics from a certain function, but the output turned out to be empty. I discovered that there are multiple nodes labeled as ERROR in AST. Is it caused by this?

Steps to reproduce

The command I tried

$ rust-code-analysis-cli --paths foo.c -m

The code

static YYACTIONTYPE
yy_find_shift_action(YYCODETYPE iLookAhead, /* The look-ahead token */
                     YYACTIONTYPE stateno   /* Current state number */
) {
  int i;

  if (stateno > YY_MAX_SHIFT)
    return stateno;
  assert(stateno <= YY_SHIFT_COUNT);
#if defined(YYCOVERAGE)
  yycoverage[stateno][iLookAhead] = 1;
#endif
  do {
    i = yy_shift_ofst[stateno];
    assert(i >= 0);
    /* assert( i+YYNTOKEN<=(int)YY_NLOOKAHEAD ); */
    assert(iLookAhead != YYNOCODE);
    assert(iLookAhead < YYNTOKEN);
    i += iLookAhead;
    if (i >= YY_NLOOKAHEAD || yy_lookahead[i] != iLookAhead) {
#ifdef YYFALLBACK
      YYCODETYPE iFallback; /* Fallback token */
      if (iLookAhead < sizeof(yyFallback) / sizeof(yyFallback[0]) &&
          (iFallback = yyFallback[iLookAhead]) != 0) {
#ifndef NDEBUG
        if (yyTraceFILE) {
          fprintf(yyTraceFILE, "%sFALLBACK %s => %s\n", yyTracePrompt,
                  yyTokenName[iLookAhead], yyTokenName[iFallback]);
        }
#endif
        assert(yyFallback[iFallback] == 0); /* Fallback loop must terminate */
        iLookAhead = iFallback;
        continue;
      }
#endif
#ifdef YYWILDCARD
      {
        int j = i - iLookAhead + YYWILDCARD;
        if (
#if YY_SHIFT_MIN + YYWILDCARD < 0
            j >= 0 &&
#endif
#if YY_SHIFT_MAX + YYWILDCARD >= YY_ACTTAB_COUNT
            j < YY_ACTTAB_COUNT &&
#endif
            j < (int)(sizeof(yy_lookahead) / sizeof(yy_lookahead[0])) &&
            yy_lookahead[j] == YYWILDCARD && iLookAhead > 0) {
#ifndef NDEBUG
          if (yyTraceFILE) {
            fprintf(yyTraceFILE, "%sWILDCARD %s => %s\n", yyTracePrompt,
                    yyTokenName[iLookAhead], yyTokenName[YYWILDCARD]);
          }
#endif /* NDEBUG */
          return yy_action[j];
        }
      }
#endif /* YYWILDCARD */
      return yy_default[stateno];
    } else {
      return yy_action[i];
    }
  } while (1);
}
@marco-c
Copy link
Collaborator

marco-c commented Feb 24, 2023

Yep, this is probably a bug in the C grammar (maybe related to the preprocessor stuff).

Are you able to reduce the test case to the minimum?

@MartinLwx
Copy link
Author

Yep, this is probably a bug in the C grammar (maybe related to the preprocessor stuff).

Are you able to reduce the test case to the minimum?

I made some revisions to the code by removing certain preprocessor parts and code lines. I'm not entirely certain if this was the correct approach, but I hope that it will be helpful.

static YYACTIONTYPE
yy_find_shift_action(YYCODETYPE iLookAhead, /* The look-ahead token */
                     YYACTIONTYPE stateno   /* Current state number */
) {
  do {
    if (i >= YY_NLOOKAHEAD || yy_lookahead[i] != iLookAhead) {
#ifdef YYWILDCARD
      {
        if (
#if YY_SHIFT_MAX + YYWILDCARD >= YY_ACTTAB_COUNT
            j < YY_ACTTAB_COUNT &&
#endif
            j < (int)(sizeof(yy_lookahead) / sizeof(yy_lookahead[0])) &&
            yy_lookahead[j] == YYWILDCARD && iLookAhead > 0) {
#ifndef NDEBUG
          if (yyTraceFILE) {
            fprintf(yyTraceFILE, "%sWILDCARD %s => %s\n", yyTracePrompt,
                    yyTokenName[iLookAhead], yyTokenName[YYWILDCARD]);
          }
#endif /* NDEBUG */
          return yy_action[j];
        }
      }
#endif /* YYWILDCARD */
      return yy_default[stateno];
    }
  } while (1);
}

@marco-c
Copy link
Collaborator

marco-c commented Feb 24, 2023

Are you sure this is the minimum amount of code to make it fail?
Could you try removing more and more until you get to something that doesn't fail? Then you can show us the snippet of code right before the last modification that makes it fail, and the snippet of code after that modification.

@MartinLwx
Copy link
Author

Are you sure this is the minimum amount of code to make it fail? Could you try removing more and more until you get to something that doesn't fail? Then you can show us the snippet of code right before the last modification that makes it fail, and the snippet of code after that modification.

Hi, sorry for that. This time I made more eager modification through trial and error. I believe that the code has been reduced to the most minimal amount possible.

The code before last modification that makes it fail:

static YYACTIONTYPE yy_find_shift_action() {
  do {
    if (yy_lookahead[i] != iLookAhead) {
#ifdef YYWILDCARD
      {
        if (
#if YY_SHIFT_MAX + YYWILDCARD >= YY_ACTTAB_COUNT
            j < YY_ACTTAB_COUNT &&
#endif
            yy_lookahead[j] == YYWILDCARD) {
#ifndef NDEBUG
          if (yyTraceFILE) {
            fprintf(yyTraceFILE, "%sWILDCARD %s", yyTracePrompt,
                    yyTokenName[iLookAhead]);
          }
#endif
        }
      }
#endif
    }
  } while (1);
}

Possible fix: Delete any inner #if... pairs(additional code has been omitted for brevity).

...
#ifdef YYWILDCARD
      {
        if (
            yy_lookahead[j] == YYWILDCARD) {
#ifndef NDEBUG
          if (yyTraceFILE) {
            fprintf(yyTraceFILE, "%sWILDCARD %s", yyTracePrompt,
                    yyTokenName[iLookAhead]);
          }
#endif
        }
      }
#endif
...

Possible fix: Remove the brackets(i.e {})

...
          if (yyTraceFILE) 
            fprintf(yyTraceFILE, "%sWILDCARD %s", yyTracePrompt,
                    yyTokenName[iLookAhead]);
...

Possible fix: Condense the function call into a single line

...
          if (yyTraceFILE) {
            fprintf(yyTraceFILE, "%sWILDCARD %s", yyTracePrompt, yyTokenName[iLookAhead]);
          }
...

Possible fix: Change the condition of if statement.

...
#if YY_SHIFT_MAX + YYWILDCARD >= YY_ACTTAB_COUNT
            j < YY_ACTTAB_COUNT
#endif
            ) {
...

@marco-c
Copy link
Collaborator

marco-c commented Mar 9, 2023

Thanks, that's better. I guess we could further reduce it by simplifying the statements (e.g. fprintf(yyTraceFILE, "%sWILDCARD %s", yyTracePrompt, yyTokenName[iLookAhead]); could be a single statement like int x = 0; or similar).

There is probably a but in the handling of macros.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants