Skip to content

Commit

Permalink
[clang][Driver] Don't ignore -gmodules .gch files
Browse files Browse the repository at this point in the history
A previous commit (82f75ed) made clang ignore .gch files that were not
Clang AST files. This broke `-gmodules`, which embeds the Clang AST
into an object file containing debug info.

This changes the probing to detect any valid object file as a
potential Clang PCH.
  • Loading branch information
Bigcheese committed Jan 16, 2024
1 parent 286a366 commit d3e928f
Show file tree
Hide file tree
Showing 6 changed files with 28 additions and 7 deletions.
26 changes: 19 additions & 7 deletions clang/lib/Driver/ToolChains/Clang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,9 @@
#include "clang/Driver/XRayArgs.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/BinaryFormat/Magic.h"
#include "llvm/Config/llvm-config.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Support/CodeGen.h"
#include "llvm/Support/Compiler.h"
Expand Down Expand Up @@ -948,11 +950,21 @@ static void handleAMDGPUCodeObjectVersionOptions(const Driver &D,
}
}

static bool hasClangPchSignature(const Driver &D, StringRef Path) {
if (llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> MemBuf =
D.getVFS().getBufferForFile(Path))
return (*MemBuf)->getBuffer().starts_with("CPCH");
return false;
static bool maybeHasClangPchSignature(const Driver &D, StringRef Path) {
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> MemBuf =
D.getVFS().getBufferForFile(Path);
if (!MemBuf)
return false;
llvm::file_magic Magic = llvm::identify_magic((*MemBuf)->getBuffer());
if (Magic == llvm::file_magic::unknown)
return false;
// Return true for both raw Clang AST files and object files which may
// contain a __clangast section.
if (Magic == llvm::file_magic::clang_ast)
return true;
Expected<std::unique_ptr<llvm::object::ObjectFile>> Obj =
llvm::object::ObjectFile::createObjectFile(**MemBuf, Magic);
return !Obj.takeError();
}

static bool gchProbe(const Driver &D, StringRef Path) {
Expand All @@ -964,14 +976,14 @@ static bool gchProbe(const Driver &D, StringRef Path) {
std::error_code EC;
for (llvm::vfs::directory_iterator DI = D.getVFS().dir_begin(Path, EC), DE;
!EC && DI != DE; DI = DI.increment(EC)) {
if (hasClangPchSignature(D, DI->path()))
if (maybeHasClangPchSignature(D, DI->path()))
return true;
}
D.Diag(diag::warn_drv_pch_ignoring_gch_dir) << Path;
return false;
}

if (hasClangPchSignature(D, Path))
if (maybeHasClangPchSignature(D, Path))
return true;
D.Diag(diag::warn_drv_pch_ignoring_gch_file) << Path;
return false;
Expand Down
4 changes: 4 additions & 0 deletions clang/test/PCH/gch-probe.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
// RUN: %clang -x c-header -c %s -o %t.h.gch
// RUN: %clang -fsyntax-only -include %t.h %s

// -gmodules embeds the Clang AST file in an object file.
// RUN: %clang -x c-header -c %s -gmodules -o %t.h.gch
// RUN: %clang -fsyntax-only -include %t.h %s

// gch probing should ignore files which are not clang pch files.
// RUN: %clang -fsyntax-only -include %S/Inputs/gch-probe.h %s 2>&1 | FileCheck %s
// CHECK: warning: precompiled header '{{.*}}gch-probe.h.gch' was ignored because it is not a clang PCH file
Expand Down
1 change: 1 addition & 0 deletions llvm/include/llvm/BinaryFormat/Magic.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ struct file_magic {
enum Impl {
unknown = 0, ///< Unrecognized file
bitcode, ///< Bitcode file
clang_ast, ///< Clang PCH or PCM
archive, ///< ar style archive file
elf, ///< ELF Unknown type
elf_relocatable, ///< ELF Relocatable object file
Expand Down
2 changes: 2 additions & 0 deletions llvm/lib/BinaryFormat/Magic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,8 @@ file_magic llvm::identify_magic(StringRef Magic) {
case 'C':
if (startswith(Magic, "CCOB"))
return file_magic::offload_bundle_compressed;
if (startswith(Magic, "CPCH"))
return file_magic::clang_ast;
break;
case '!':
if (startswith(Magic, "!<arch>\n") || startswith(Magic, "!<thin>\n"))
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/Object/Binary.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ Expected<std::unique_ptr<Binary>> object::createBinary(MemoryBufferRef Buffer,
// PDB does not support the Binary interface.
return errorCodeToError(object_error::invalid_file_type);
case file_magic::unknown:
case file_magic::clang_ast:
case file_magic::cuda_fatbinary:
case file_magic::coff_cl_gl_object:
case file_magic::dxcontainer_object:
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/Object/ObjectFile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ ObjectFile::createObjectFile(MemoryBufferRef Object, file_magic Type,
switch (Type) {
case file_magic::unknown:
case file_magic::bitcode:
case file_magic::clang_ast:
case file_magic::coff_cl_gl_object:
case file_magic::archive:
case file_magic::macho_universal_binary:
Expand Down

0 comments on commit d3e928f

Please sign in to comment.