From d3e928fc5b725cb3e484a8cfd50fa23c26f7eb22 Mon Sep 17 00:00:00 2001 From: Michael Spencer Date: Wed, 10 Jan 2024 16:58:59 -0800 Subject: [PATCH] [clang][Driver] Don't ignore -gmodules .gch files 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. --- clang/lib/Driver/ToolChains/Clang.cpp | 26 +++++++++++++++++++------- clang/test/PCH/gch-probe.c | 4 ++++ llvm/include/llvm/BinaryFormat/Magic.h | 1 + llvm/lib/BinaryFormat/Magic.cpp | 2 ++ llvm/lib/Object/Binary.cpp | 1 + llvm/lib/Object/ObjectFile.cpp | 1 + 6 files changed, 28 insertions(+), 7 deletions(-) diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 9edae3fec91a87..997ec2d491d02c 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -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" @@ -948,11 +950,21 @@ static void handleAMDGPUCodeObjectVersionOptions(const Driver &D, } } -static bool hasClangPchSignature(const Driver &D, StringRef Path) { - if (llvm::ErrorOr> MemBuf = - D.getVFS().getBufferForFile(Path)) - return (*MemBuf)->getBuffer().starts_with("CPCH"); - return false; +static bool maybeHasClangPchSignature(const Driver &D, StringRef Path) { + llvm::ErrorOr> 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> Obj = + llvm::object::ObjectFile::createObjectFile(**MemBuf, Magic); + return !Obj.takeError(); } static bool gchProbe(const Driver &D, StringRef Path) { @@ -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; diff --git a/clang/test/PCH/gch-probe.c b/clang/test/PCH/gch-probe.c index 8b1e1fab5ad97b..0905c9baebdae0 100644 --- a/clang/test/PCH/gch-probe.c +++ b/clang/test/PCH/gch-probe.c @@ -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 diff --git a/llvm/include/llvm/BinaryFormat/Magic.h b/llvm/include/llvm/BinaryFormat/Magic.h index c635a269576587..6978c066bda468 100644 --- a/llvm/include/llvm/BinaryFormat/Magic.h +++ b/llvm/include/llvm/BinaryFormat/Magic.h @@ -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 diff --git a/llvm/lib/BinaryFormat/Magic.cpp b/llvm/lib/BinaryFormat/Magic.cpp index 45a0b7e11452b4..bd378337ed3338 100644 --- a/llvm/lib/BinaryFormat/Magic.cpp +++ b/llvm/lib/BinaryFormat/Magic.cpp @@ -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, "!\n") || startswith(Magic, "!\n")) diff --git a/llvm/lib/Object/Binary.cpp b/llvm/lib/Object/Binary.cpp index 0b9d95485287dc..2dfae8ab5d3c64 100644 --- a/llvm/lib/Object/Binary.cpp +++ b/llvm/lib/Object/Binary.cpp @@ -84,6 +84,7 @@ Expected> 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: diff --git a/llvm/lib/Object/ObjectFile.cpp b/llvm/lib/Object/ObjectFile.cpp index c05eb0a0468e2b..6a226a3bbdbca3 100644 --- a/llvm/lib/Object/ObjectFile.cpp +++ b/llvm/lib/Object/ObjectFile.cpp @@ -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: