mc-imperial / dredd

Framework for evaluating C/C++ compiler testing tools
Apache License 2.0
11 stars 3 forks source link

Add flag to check mutation sources against compile_commands.json #229

Open JamesLee-Jones opened 3 months ago

JamesLee-Jones commented 3 months ago

When mutating a project, Dredd takes in a compile_commands.json file as well as a list of files that should be mutated. This approach is okay for smaller projects but can be impractical for mutating large project. It is also not always suitable to include all .c or .cc files as some may only be used for OS specific features. This can lead to errors when mutating projects were this is the case.

To solve this problem, a flag should be added to Dredd that works as follows:

JamesLee-Jones commented 3 months ago

The documentation for ClangTool claims that 'if a source files is not found in Compilations, it is skipped'. However, when attempting to apply Dredd to tint, src/tint/utils/command/command_windows.cc is modified despite this file not appearing in compile_commands.json.

JamesLee-Jones commented 3 months ago

If you empty compile_commands.json to be just [], then all files get skipped as expected. This can be demonstrated with the math library example. However, if an entry is only one entry is left and the rest are removed (for example, the entry for math/src/exp.cc), all files still gets processed by Dredd. This means ClangTool is not checking for inclusion as expected.

JamesLee-Jones commented 3 months ago

The check whether a file exists in the compilation database happens here and calls getCompileCommands(file) defined here.

Currently I'm not entirely sure why getCompileCommands returns a non empty vector for files that are not mentioned in compile_commands.json.

JamesLee-Jones commented 3 months ago

Adding the following to main.cc prints the result of getCompileCommands for each source file.

  for (const auto& str : options.get().getSourcePathList()) {
    std::cout << clang::tooling::getAbsolutePath(str) << ":" << std::endl;
    for (auto comp_command : options.get().getCompilations().getCompileCommands(clang::tooling::getAbsolutePath(str))) {
      std::cout << " - Filename: " << comp_command.Filename << std::endl;
      std::cout << " - Heuristic: " << comp_command.Heuristic << std::endl;
      std::cout << " - Output: " << comp_command.Output << std::endl;
      std::cout << " - Directory: " << comp_command.Directory << std::endl;
      std::cout << " - CommandLine:" << std::endl;
      for (auto command : comp_command.CommandLine) {
        std:: cout << "   " << command << std::endl;
      }
    }
  }

Using the math example with only the trig.cc command in compile_commands.json, this prints:

/home/jlj/dev/dredd/examples/math/math/src/exp.cc:
 - Filename: /home/jlj/dev/dredd/examples/math/math/src/exp.cc
 - Heuristic: inferred from /home/jlj/dev/dredd/examples/math/math/src/trig.cc
 - Output: math/CMakeFiles/math.dir/src/trig.cc.o
 - Directory: /home/jlj/dev/dredd/examples/math/build
 - CommandLine:
   /home/jlj/dev/dredd/third_party/clang+llvm/bin//clang++
   --driver-mode=g++
   -I/home/jlj/dev/dredd/examples/math/math/include
   -c
   --
   /home/jlj/dev/dredd/examples/math/math/src/exp.cc
/home/jlj/dev/dredd/examples/math/math/src/number_theoretic.cc:
 - Filename: /home/jlj/dev/dredd/examples/math/math/src/number_theoretic.cc
 - Heuristic: inferred from /home/jlj/dev/dredd/examples/math/math/src/trig.cc
 - Output: math/CMakeFiles/math.dir/src/trig.cc.o
 - Directory: /home/jlj/dev/dredd/examples/math/build
 - CommandLine:
   /home/jlj/dev/dredd/third_party/clang+llvm/bin//clang++
   --driver-mode=g++
   -I/home/jlj/dev/dredd/examples/math/math/include
   -c
   --
   /home/jlj/dev/dredd/examples/math/math/src/number_theoretic.cc
/home/jlj/dev/dredd/examples/math/math/src/trig.cc:
 - Filename: /home/jlj/dev/dredd/examples/math/math/src/trig.cc
 - Heuristic: 
 - Output: math/CMakeFiles/math.dir/src/trig.cc.o
 - Directory: /home/jlj/dev/dredd/examples/math/build
 - CommandLine:
   /home/jlj/dev/dredd/third_party/clang+llvm/bin//clang++
   --driver-mode=g++
   -I/home/jlj/dev/dredd/examples/math/math/include
   -o
   math/CMakeFiles/math.dir/src/trig.cc.o
   -c
   /home/jlj/dev/dredd/examples/math/math/src/trig.cc
Processing /home/jlj/dev/dredd/examples/math/math/src/exp.cc
Processing /home/jlj/dev/dredd/examples/math/math/src/number_theoretic.cc
Processing /home/jlj/dev/dredd/examples/math/math/src/trig.cc

This seems to show that it is also inferred if a file is referenced by a compile_commands.json file based on what is in there. If the flag described in this issue is passed, then this inference should be disabled through some means.

JamesLee-Jones commented 3 months ago

After some experimenting with solutions, calling options.get().getCompilations().getAllFiles() when no source files are passed to Dredd seems to unexpectedly result in a seg fault. This appears to be coming from inside LibTooling instead of Dredd itself.

JamesLee-Jones commented 3 months ago

Due to the issues faced by this, I short term solution can be found here. This is a shell script that extracts files with user defined extensions from a compilation database file to be passed to Dredd.