rizsotto / Bear

Bear is a tool that generates a compilation database for clang tooling.
GNU General Public License v3.0
4.83k stars 313 forks source link

Invalid recording of -D flag in compile command #508

Closed pgoodman closed 1 year ago

pgoodman commented 1 year ago

Describe the bug When a macro definition of a string is specified, e.g. -DFILE_NAME=\"hello.c\", the way that Bear records this argument in compile_commands.json is as: "-DFILE_NAME=\"hello.c\"",, i.e. the JSON encoding takes the original string escaping. When the JSON compile command is decoded, the decoded argument will have the following interpretation: -DFILE_NAME="hello.c", which is very different, because in C/C++ code, the FILE_NAME macro will no longer be a string.

To Reproduce

Makefile:

all:
        clang -DFILE_NAME=\"hello.c\" hello.c
bear -- make

compile_commands.json

[
  {
    "arguments": [
      "/usr/bin/clang",
      "-c",
      "-DFILE_NAME=\"hello.c\"",
      "hello.c"
    ],
    "directory": "/private/tmp",
    "file": "/private/tmp/hello.c"
  }
]

Expected behavior

I expect that this argument be JSON-encoded as "-DFILE_NAME=\\\"hello.c\\\"", so that when it is decoded, the original backslash is preserved.

Environment: Probably all, but tested on macOS.

$ bear --version
bear 3.0.20

Additional context Linux kernel, e.g. -DKBUILD_BASENAME=\"...\".

rizsotto commented 1 year ago

Hey @pgoodman , thanks for the report.

From your wording I could not figure how did you come to the conclusion that it's invalid output. Could you point out which tool has problem with the current output?

The tests I have in place are this and this. And these was validated against clang-tidy and clang-format tools.

asierllano commented 1 year ago

In my opinion the output is fully correct. The Makefile backslashes are used to scape the shell, so the argument passed to the process clang is without any backslash but it includes the double quotes. Then when encoded in json it requires additional backslashes in order to represent the double-quotes. If someone reads the json and wants to generate a shell command again, they should scape again any character.

Just as an example for demonstration that clang did not receive any backslash, you can make a C program:

include

int main(void) { printf(FILE_NAME); return 0; }

You will see that it compiles properly because FILE_NAME value is just "hello.c" without any back-slash. The back-slash never went out of the makefile.