Origami404 created this revision.
Herald added a project: All.
Origami404 added reviewers: aaron.ballman, erichkeane, mgorny, jyknight, 
mibintc, clang-language-wg.
Origami404 published this revision for review.
Herald added subscribers: cfe-commits, MaskRay.
Herald added a project: clang.

On GNU/Linux, GCC will automatically include `stdc-predefs.h`, while clang does
not. That is OK for glibc system because glibc includes this file manually. But
with other libc (e.g. musl), which does not manually include this, clang will
fail but GCC can get it compiled.

In 2017, D34158 <https://reviews.llvm.org/D34158> try to introduce a new flag 
called `fsystem-include-if-exists`
to fix this, but it was reverted. Nearly, D106577 
<https://reviews.llvm.org/D106577> points out that macro
`__STDC_ISO_10646__` was indeed needed, which is defined in `stdc-predefs.h`.
After a discussion, the community reaches a consensus, to make this macro
available with a D34158 <https://reviews.llvm.org/D34158>-like method.

In this patch, we port the patch in D34158 <https://reviews.llvm.org/D34158> 
into the current clang codebase. The
change is almost the same with D34158 <https://reviews.llvm.org/D34158>, but we 
change some tests to suit current
codes:

1. c-index-test now does not accept a `-ffreestanding` flag, and it should not.

We choose to disable this pre-include action in Objective-C because it will
cause some c-index-test's tests on Objective-C to fail.

2. Some unit tests about parsing and re-parsing will be affected by this change.

To keep such tests passed, we add `-ffreestanding` flags to them.

3. The new tool, Clang-Scan-Deps, will analyze all header files to find

dependencies. After we add an implicit include, its result will have an extra
`stdc-predefs.h`. Currently, we choose to add `-ffreestanding` flags to all the
affected tests for it. But maybe making it ignore the default header will be a
better choice.

Signed-off-by: Tao Liang <origami...@foxmail.com>
Co-authored-by: YingChi Long <m...@inclyc.cn>

Link: https://reviews.llvm.org/D34158
Link: https://gcc.gnu.org/gcc-4.8/porting_to.html
Link: https://reviews.llvm.org/D106577


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D137043

Files:
  clang/include/clang/Driver/Options.td
  clang/include/clang/Lex/PreprocessorOptions.h
  clang/lib/Driver/Job.cpp
  clang/lib/Driver/ToolChains/Linux.cpp
  clang/lib/Driver/ToolChains/Linux.h
  clang/lib/Frontend/CompilerInvocation.cpp
  clang/lib/Frontend/InitPreprocessor.cpp
  clang/test/ClangScanDeps/Inputs/has_include_if_elif.json
  clang/test/ClangScanDeps/Inputs/header_stat_before_open_cdb.json
  clang/test/ClangScanDeps/Inputs/headerwithdirname.json
  clang/test/ClangScanDeps/Inputs/headerwithdirnamefollowedbyinclude.json
  clang/test/ClangScanDeps/Inputs/module_fmodule_name_cdb.json
  clang/test/ClangScanDeps/Inputs/modules-context-hash/cdb_a.json.template
  clang/test/ClangScanDeps/Inputs/modules-context-hash/cdb_b.json.template
  clang/test/ClangScanDeps/Inputs/modules-pch-common-submodule/cdb_pch.json
  clang/test/ClangScanDeps/Inputs/modules-pch-common-submodule/cdb_tu.json
  clang/test/ClangScanDeps/Inputs/modules-pch-common-via-submodule/cdb_pch.json
  clang/test/ClangScanDeps/Inputs/modules-pch-common-via-submodule/cdb_tu.json
  clang/test/ClangScanDeps/Inputs/modules-pch/cdb_pch.json
  clang/test/ClangScanDeps/Inputs/modules-pch/cdb_tu.json
  clang/test/ClangScanDeps/Inputs/modules-pch/cdb_tu_with_common.json
  clang/test/ClangScanDeps/Inputs/modules_cdb.json
  clang/test/ClangScanDeps/Inputs/modules_inferred_cdb.json
  clang/test/ClangScanDeps/Inputs/no-werror.json
  clang/test/ClangScanDeps/Inputs/preprocess_minimized_pragmas_cdb.json
  clang/test/ClangScanDeps/Inputs/regular_cdb.json
  clang/test/ClangScanDeps/Inputs/relative_directory.json
  clang/test/ClangScanDeps/Inputs/static-analyzer-cdb.json
  clang/test/ClangScanDeps/Inputs/subframework_header_dir_symlink_cdb.json
  clang/test/ClangScanDeps/Inputs/symlink_cdb.json
  clang/test/ClangScanDeps/Inputs/target-filename-cdb.json
  clang/test/ClangScanDeps/Inputs/vfsoverlay_cdb.json
  clang/test/ClangScanDeps/header-search-pruning-transitive.c
  clang/test/ClangScanDeps/modules-dep-args.c
  clang/test/ClangScanDeps/modules-header-sharing.m
  clang/test/ClangScanDeps/modules-implementation-module-map.c
  clang/test/ClangScanDeps/modules-implicit-dot-private.m
  clang/test/ClangScanDeps/modules-incomplete-umbrella.c
  clang/test/ClangScanDeps/modules-no-undeclared-includes.c
  clang/test/Driver/Inputs/stdc-predef/usr/include/stdc-predef.h
  clang/test/Driver/stdc-predef.c
  clang/test/Driver/stdc-predef.i
  clang/unittests/Tooling/TestVisitor.h
  clang/unittests/libclang/LibclangTest.cpp

Index: clang/unittests/libclang/LibclangTest.cpp
===================================================================
--- clang/unittests/libclang/LibclangTest.cpp
+++ clang/unittests/libclang/LibclangTest.cpp
@@ -366,8 +366,11 @@
     "printf(\"mmm!!\");\n"
     "#endif");
 
-  ClangTU = clang_parseTranslationUnit(Index, Main.c_str(), nullptr, 0,
-                                       nullptr, 0, TUFlags);
+  const char *argv[] = {"-ffreestanding"};
+  const int argc = sizeof(argv) / sizeof(*argv);
+
+  ClangTU = clang_parseTranslationUnit(Index, Main.c_str(), argv, argc, nullptr,
+                                       0, TUFlags);
 
   CXSourceRangeList *Ranges = clang_getAllSkippedRanges(ClangTU);
   EXPECT_EQ(2U, Ranges->count);
@@ -607,6 +610,9 @@
     "printf(\"mmm!!\");\n"
     "#endif");
 
+  const char *argv[] = {"-ffreestanding"};
+  const int argc = sizeof(argv) / sizeof(*argv);
+
   for (int i = 0; i != 3; ++i) {
     unsigned flags = TUFlags | CXTranslationUnit_PrecompiledPreamble;
     if (i == 2)
@@ -616,7 +622,7 @@
        clang_disposeTranslationUnit(ClangTU);  // dispose from previous iter
 
     // parse once
-    ClangTU = clang_parseTranslationUnit(Index, Main.c_str(), nullptr, 0,
+    ClangTU = clang_parseTranslationUnit(Index, Main.c_str(), argv, argc,
                                          nullptr, 0, flags);
     if (i != 0) {
       // reparse
Index: clang/unittests/Tooling/TestVisitor.h
===================================================================
--- clang/unittests/Tooling/TestVisitor.h
+++ clang/unittests/Tooling/TestVisitor.h
@@ -53,6 +53,7 @@
   /// \brief Runs the current AST visitor over the given code.
   bool runOver(StringRef Code, Language L = Lang_CXX) {
     std::vector<std::string> Args;
+    Args.push_back("-ffreestanding");
     switch (L) {
       case Lang_C:
         Args.push_back("-x");
Index: clang/test/Driver/stdc-predef.i
===================================================================
--- /dev/null
+++ clang/test/Driver/stdc-predef.i
@@ -0,0 +1,8 @@
+// The automatic preinclude of stdc-predef.h should not occur if
+// the source filename indicates a preprocessed file.
+//
+// RUN: %clang %s -### -c 2>&1 \
+// RUN: --sysroot=%S/Inputs/stdc-predef \
+// RUN: | FileCheck --implicit-check-not "stdc-predef.h" %s
+
+int i;
Index: clang/test/Driver/stdc-predef.c
===================================================================
--- /dev/null
+++ clang/test/Driver/stdc-predef.c
@@ -0,0 +1,25 @@
+// Test that clang preincludes stdc-predef.h, if the include file is available
+//
+// RUN: %clang %s -### -c 2>&1 \
+// RUN: --sysroot=%S/Inputs/stdc-predef \
+// RUN: | FileCheck -check-prefix CHECK-PREDEF %s
+// RUN: %clang %s -### -c -ffreestanding 2>&1 \
+// RUN: --sysroot=%S/Inputs/stdc-predef \
+// RUN: | FileCheck --implicit-check-not "stdc-predef.h" %s
+// RUN: %clang %s -c -E 2>&1 \
+// RUN: --sysroot=%S/Inputs/basic_linux_tree \
+// RUN: | FileCheck --implicit-check-not "stdc-predef.h" %s
+// RUN: %clang -x cpp-output %s -### -c 2>&1 \
+// RUN: --sysroot=%S/Inputs/stdc-predef \
+// RUN: | FileCheck --implicit-check-not "stdc-predef.h" %s
+// RUN: %clang -c %s -Xclang -verify -DCHECK_DUMMY=1 \
+// RUN: --sysroot=%S/Inputs/stdc-predef 
+// expected-no-diagnostics
+
+// CHECK-PREDEF: "-fsystem-include-if-exists" "stdc-predef.h"
+int i;
+#if CHECK_DUMMY
+#if !DUMMY_STDC_PREDEF 
+  #error "Expected macro symbol DUMMY_STDC_PREDEF is not defined."
+#endif
+#endif
Index: clang/test/Driver/Inputs/stdc-predef/usr/include/stdc-predef.h
===================================================================
--- /dev/null
+++ clang/test/Driver/Inputs/stdc-predef/usr/include/stdc-predef.h
@@ -0,0 +1,4 @@
+#ifndef	_STDC_PREDEF_H
+#define	_STDC_PREDEF_H	1
+#define DUMMY_STDC_PREDEF 1
+#endif
Index: clang/test/ClangScanDeps/modules-no-undeclared-includes.c
===================================================================
--- clang/test/ClangScanDeps/modules-no-undeclared-includes.c
+++ clang/test/ClangScanDeps/modules-no-undeclared-includes.c
@@ -24,7 +24,7 @@
 //--- cdb.json.template
 [{
   "directory": "DIR",
-  "command": "clang -fmodules -gmodules -fimplicit-module-maps -fmodules-cache-path=DIR/cache -IDIR/undeclared -c DIR/test.c -o DIR/test.o",
+  "command": "clang -ffreestanding -fmodules -gmodules -fimplicit-module-maps -fmodules-cache-path=DIR/cache -IDIR/undeclared -c DIR/test.c -o DIR/test.o",
   "file": "DIR/test.c"
 }]
 
Index: clang/test/ClangScanDeps/modules-incomplete-umbrella.c
===================================================================
--- clang/test/ClangScanDeps/modules-incomplete-umbrella.c
+++ clang/test/ClangScanDeps/modules-incomplete-umbrella.c
@@ -26,7 +26,7 @@
 [{
   "file": "DIR/from_tu.m",
   "directory": "DIR",
-  "command": "clang -fmodules -fmodules-cache-path=DIR/cache -iframework DIR/frameworks -c DIR/from_tu.m -o DIR/from_tu.o"
+  "command": "clang -ffreestanding -fmodules -fmodules-cache-path=DIR/cache -iframework DIR/frameworks -c DIR/from_tu.m -o DIR/from_tu.o"
 }]
 //--- from_tu.m
 #include "FW/FW.h"
Index: clang/test/ClangScanDeps/modules-implicit-dot-private.m
===================================================================
--- clang/test/ClangScanDeps/modules-implicit-dot-private.m
+++ clang/test/ClangScanDeps/modules-implicit-dot-private.m
@@ -15,7 +15,7 @@
 [{
   "file": "DIR/tu.m",
   "directory": "DIR",
-  "command": "clang -fmodules -fmodules-cache-path=DIR/cache -iframework DIR/frameworks -c DIR/tu.m -o DIR/tu.o"
+  "command": "clang -ffreestanding -fmodules -fmodules-cache-path=DIR/cache -iframework DIR/frameworks -c DIR/tu.m -o DIR/tu.o"
 }]
 //--- tu.m
 @import FW.Private;
Index: clang/test/ClangScanDeps/modules-implementation-module-map.c
===================================================================
--- clang/test/ClangScanDeps/modules-implementation-module-map.c
+++ clang/test/ClangScanDeps/modules-implementation-module-map.c
@@ -5,7 +5,7 @@
 [{
   "file": "DIR/tu.m",
   "directory": "DIR",
-  "command": "clang -fmodules -fimplicit-module-maps -fmodules-cache-path=DIR/cache -fmodule-name=FWPrivate -c DIR/tu.m -o DIR/tu.o -F DIR/frameworks -Wprivate-module"
+  "command": "clang -ffreestanding -fmodules -fimplicit-module-maps -fmodules-cache-path=DIR/cache -fmodule-name=FWPrivate -c DIR/tu.m -o DIR/tu.o -F DIR/frameworks -Wprivate-module"
 }]
 
 //--- frameworks/FW.framework/Modules/module.modulemap
Index: clang/test/ClangScanDeps/modules-header-sharing.m
===================================================================
--- clang/test/ClangScanDeps/modules-header-sharing.m
+++ clang/test/ClangScanDeps/modules-header-sharing.m
@@ -55,7 +55,7 @@
 [{
   "file": "DIR/tu.m",
   "directory": "DIR",
-  "command": "clang -fmodules -fmodules-cache-path=DIR/cache -fmodule-name=A -ivfsoverlay DIR/overlay.json -F DIR/frameworks -c DIR/tu.m -o DIR/tu.o"
+  "command": "clang -ffreestanding -fmodules -fmodules-cache-path=DIR/cache -fmodule-name=A -ivfsoverlay DIR/overlay.json -F DIR/frameworks -c DIR/tu.m -o DIR/tu.o"
 }]
 
 //--- tu.m
Index: clang/test/ClangScanDeps/modules-dep-args.c
===================================================================
--- clang/test/ClangScanDeps/modules-dep-args.c
+++ clang/test/ClangScanDeps/modules-dep-args.c
@@ -8,7 +8,7 @@
 [{
   "file": "DIR/tu.c",
   "directory": "DIR",
-  "command": "clang DIR/tu.c -fmodules -fmodules-cache-path=DIR/cache -o DIR/tu.o"
+  "command": "clang DIR/tu.c -ffreestanding -fmodules -fmodules-cache-path=DIR/cache -o DIR/tu.o"
 }]
 
 //--- module.modulemap
Index: clang/test/ClangScanDeps/header-search-pruning-transitive.c
===================================================================
--- clang/test/ClangScanDeps/header-search-pruning-transitive.c
+++ clang/test/ClangScanDeps/header-search-pruning-transitive.c
@@ -41,14 +41,14 @@
 [{
   "file": "DIR/test.c",
   "directory": "DIR",
-  "command": "clang -fsyntax-only test.c -fmodules -fimplicit-modules -fmodules-cache-path=DIR/module-cache -fimplicit-module-maps -Ibegin -Ia -Ib -Iend"
+  "command": "clang -fsyntax-only test.c -ffreestanding -fmodules -fimplicit-modules -fmodules-cache-path=DIR/module-cache -fimplicit-module-maps -Ibegin -Ia -Ib -Iend"
 }]
 
 //--- cdb_without_a.json.template
 [{
   "file": "DIR/test.c",
   "directory": "DIR",
-  "command": "clang -fsyntax-only test.c -fmodules -fimplicit-modules -fmodules-cache-path=DIR/module-cache -fimplicit-module-maps -Ibegin     -Ib -Iend"
+  "command": "clang -fsyntax-only test.c -ffreestanding -fmodules -fimplicit-modules -fmodules-cache-path=DIR/module-cache -fimplicit-module-maps -Ibegin     -Ib -Iend"
 }]
 
 // RUN: sed -e "s|DIR|%/t|g" %t/cdb_with_a.json.template    > %t/cdb_with_a.json
Index: clang/test/ClangScanDeps/Inputs/vfsoverlay_cdb.json
===================================================================
--- clang/test/ClangScanDeps/Inputs/vfsoverlay_cdb.json
+++ clang/test/ClangScanDeps/Inputs/vfsoverlay_cdb.json
@@ -1,7 +1,7 @@
 [
 {
   "directory": "DIR",
-  "command": "clang -E DIR/vfsoverlay_input.cpp -IInputs -ivfsoverlay DIR/vfsoverlay.yaml",
+  "command": "clang -E DIR/vfsoverlay_input.cpp -IInputs -ivfsoverlay DIR/vfsoverlay.yaml -ffreestanding",
   "file": "DIR/vfsoverlay_input.cpp"
 },
 {
Index: clang/test/ClangScanDeps/Inputs/target-filename-cdb.json
===================================================================
--- clang/test/ClangScanDeps/Inputs/target-filename-cdb.json
+++ clang/test/ClangScanDeps/Inputs/target-filename-cdb.json
@@ -1,22 +1,22 @@
 [
 {
   "directory": "DIR",
-  "command": "clang -E DIR/target-filename_input.cpp",
+  "command": "clang -E DIR/target-filename_input.cpp -ffreestanding",
   "file": "DIR/target-filename_input.cpp"
 },
 {
   "directory": "DIR",
-  "command": "clang -E DIR/target-filename_input.cpp -o a.o",
+  "command": "clang -E DIR/target-filename_input.cpp -o a.o -ffreestanding",
   "file": "DIR/target-filename_input.cpp"
 },
 {
   "directory": "DIR",
-  "command": "clang -E DIR/target-filename_input.cpp -ob.o",
+  "command": "clang -E DIR/target-filename_input.cpp -ob.o -ffreestanding",
   "file": "DIR/target-filename_input.cpp"
 },
 {
   "directory": "DIR",
-  "command": "clang -E DIR/target-filename_input.cpp -o first.o -o last.o",
+  "command": "clang -E DIR/target-filename_input.cpp -o first.o -o last.o -ffreestanding",
   "file": "DIR/target-filename_input.cpp"
 },
 {
Index: clang/test/ClangScanDeps/Inputs/symlink_cdb.json
===================================================================
--- clang/test/ClangScanDeps/Inputs/symlink_cdb.json
+++ clang/test/ClangScanDeps/Inputs/symlink_cdb.json
@@ -1,12 +1,12 @@
 [
 {
   "directory": "DIR",
-  "command": "clang -E DIR/symlink_input.cpp -IInputs",
+  "command": "clang -E DIR/symlink_input.cpp -IInputs -ffreestanding",
   "file": "DIR/symlink_input.cpp"
 },
 {
   "directory": "DIR",
-  "command": "clang -E DIR/symlink_input2.cpp -IInputs",
+  "command": "clang -E DIR/symlink_input2.cpp -IInputs -ffreestanding",
   "file": "DIR/symlink_input2.cpp"
 }
 ]
Index: clang/test/ClangScanDeps/Inputs/subframework_header_dir_symlink_cdb.json
===================================================================
--- clang/test/ClangScanDeps/Inputs/subframework_header_dir_symlink_cdb.json
+++ clang/test/ClangScanDeps/Inputs/subframework_header_dir_symlink_cdb.json
@@ -1,12 +1,12 @@
 [
 {
   "directory": "DIR",
-  "command": "clang -E DIR/subframework_header_dir_symlink_input.m -D EMPTY -iframework Inputs/frameworks",
+  "command": "clang -E DIR/subframework_header_dir_symlink_input.m -D EMPTY -iframework Inputs/frameworks -ffreestanding",
   "file": "DIR/subframework_header_dir_symlink_input.m"
 },
 {
   "directory": "DIR",
-  "command": "clang -E DIR/subframework_header_dir_symlink_input2.m -FInputs/frameworks -iframework Inputs/frameworks_symlink/../frameworks_symlink",
+  "command": "clang -E DIR/subframework_header_dir_symlink_input2.m -FInputs/frameworks -iframework Inputs/frameworks_symlink/../frameworks_symlink -ffreestanding",
   "file": "DIR/subframework_header_dir_symlink_input2.m"
 }
 ]
Index: clang/test/ClangScanDeps/Inputs/static-analyzer-cdb.json
===================================================================
--- clang/test/ClangScanDeps/Inputs/static-analyzer-cdb.json
+++ clang/test/ClangScanDeps/Inputs/static-analyzer-cdb.json
@@ -1,12 +1,12 @@
 [
 {
   "directory": "DIR",
-  "command": "clang --analyze DIR/static-analyzer_clang.c",
+  "command": "clang --analyze DIR/static-analyzer_clang.c -ffreestanding",
   "file": "DIR/static-analyzer_clang.c"
 },
 {
   "directory": "DIR",
-  "command": "clang-cl --analyze -- DIR/static-analyzer_clangcl.c",
+  "command": "clang-cl --analyze -- DIR/static-analyzer_clangcl.c -ffreestanding",
   "file": "DIR/static-analyzer_clangcl.c"
 }
 ]
Index: clang/test/ClangScanDeps/Inputs/relative_directory.json
===================================================================
--- clang/test/ClangScanDeps/Inputs/relative_directory.json
+++ clang/test/ClangScanDeps/Inputs/relative_directory.json
@@ -1,12 +1,12 @@
 [
 {
   "directory": "DIR",
-  "command": "clang -E Inputs/relative_directory_input1.cpp -IInputs",
+  "command": "clang -E Inputs/relative_directory_input1.cpp -IInputs -ffreestanding",
   "file": "DIR/Inputs/relative_directory_input1.cpp"
 },
 {
   "directory": "DIR/Inputs",
-  "command": "clang -E relative_directory_input2.cpp -I.",
+  "command": "clang -E relative_directory_input2.cpp -I. -ffreestanding",
   "file": "DIR/Inputs/relative_directory_input2.cpp"
 }
 ]
Index: clang/test/ClangScanDeps/Inputs/regular_cdb.json
===================================================================
--- clang/test/ClangScanDeps/Inputs/regular_cdb.json
+++ clang/test/ClangScanDeps/Inputs/regular_cdb.json
@@ -1,17 +1,17 @@
 [
 {
   "directory": "DIR",
-  "command": "clang -E -fsyntax-only DIR/regular_cdb_input2.cpp -IInputs -D INCLUDE_HEADER2 -MD -MF DIR/regular_cdb2.d",
+  "command": "clang -E -ffreestanding -fsyntax-only DIR/regular_cdb_input2.cpp -IInputs -D INCLUDE_HEADER2 -MD -MF DIR/regular_cdb2.d",
   "file": "DIR/regular_cdb_input2.cpp"
 },
 {
   "directory": "DIR",
-  "command": "clang -E DIR/regular_cdb_input.cpp -IInputs",
+  "command": "clang -ffreestanding -E DIR/regular_cdb_input.cpp -IInputs",
   "file": "DIR/regular_cdb_input.cpp"
 },
 {
   "directory": "DIR",
-  "command": "clang -E -IInputs -o adena.o -- DIR/regular_cdb_input.cpp",
+  "command": "clang -ffreestanding -E -IInputs -o adena.o -- DIR/regular_cdb_input.cpp",
   "file": "DIR/regular_cdb_input.cpp"
 }
 ]
Index: clang/test/ClangScanDeps/Inputs/preprocess_minimized_pragmas_cdb.json
===================================================================
--- clang/test/ClangScanDeps/Inputs/preprocess_minimized_pragmas_cdb.json
+++ clang/test/ClangScanDeps/Inputs/preprocess_minimized_pragmas_cdb.json
@@ -1,7 +1,7 @@
 [
 {
   "directory": "DIR",
-  "command": "clang -E DIR/preprocess_minimized_pragmas_basic.cpp -IInputs -target x86_64-linux",
+  "command": "clang -E DIR/preprocess_minimized_pragmas_basic.cpp -IInputs -target x86_64-linux -ffreestanding",
   "file": "DIR/preprocess_minimized_pragmas_basic.cpp"
 },
 {
Index: clang/test/ClangScanDeps/Inputs/no-werror.json
===================================================================
--- clang/test/ClangScanDeps/Inputs/no-werror.json
+++ clang/test/ClangScanDeps/Inputs/no-werror.json
@@ -1,7 +1,7 @@
 [
 {
   "directory": "DIR",
-  "command": "clang -E DIR/no-werror_input.cpp -IInputs -std=c++17 -Weverything -Werror",
+  "command": "clang -E DIR/no-werror_input.cpp -IInputs -std=c++17 -Weverything -Werror -ffreestanding",
   "file": "DIR/no-werror.cpp"
 },
 {
Index: clang/test/ClangScanDeps/Inputs/modules_inferred_cdb.json
===================================================================
--- clang/test/ClangScanDeps/Inputs/modules_inferred_cdb.json
+++ clang/test/ClangScanDeps/Inputs/modules_inferred_cdb.json
@@ -1,7 +1,7 @@
 [
 {
   "directory": "DIR",
-  "command": "clang -E DIR/modules_cdb_input.cpp -FFRAMEWORKS -fmodules -fcxx-modules -fmodules-cache-path=DIR/module-cache -fimplicit-modules -fimplicit-module-maps -pedantic -Werror",
+  "command": "clang -E DIR/modules_cdb_input.cpp -FFRAMEWORKS -ffreestanding -fmodules -fcxx-modules -fmodules-cache-path=DIR/module-cache -fimplicit-modules -fimplicit-module-maps -pedantic -Werror",
   "file": "DIR/modules_cdb_input.cpp"
 }
 ]
Index: clang/test/ClangScanDeps/Inputs/modules_cdb.json
===================================================================
--- clang/test/ClangScanDeps/Inputs/modules_cdb.json
+++ clang/test/ClangScanDeps/Inputs/modules_cdb.json
@@ -1,22 +1,22 @@
 [
 {
   "directory": "DIR",
-  "command": "clang -E DIR/modules_cdb_input2.cpp -IInputs -D INCLUDE_HEADER2 -MD -MF DIR/modules_cdb2.d -fmodules -fcxx-modules -fmodules-cache-path=DIR/module-cache -fimplicit-modules -fimplicit-module-maps",
+  "command": "clang -E DIR/modules_cdb_input2.cpp -IInputs -D INCLUDE_HEADER2 -MD -MF DIR/modules_cdb2.d -ffreestanding -fmodules -fcxx-modules -fmodules-cache-path=DIR/module-cache -fimplicit-modules -fimplicit-module-maps",
   "file": "DIR/modules_cdb_input2.cpp"
 },
 {
   "directory": "DIR",
-  "command": "clang -E DIR/modules_cdb_input.cpp -IInputs -fmodules -fcxx-modules -fmodules-cache-path=DIR/module-cache -fimplicit-modules -fimplicit-module-maps",
+  "command": "clang -E DIR/modules_cdb_input.cpp -IInputs -ffreestanding -fmodules -fcxx-modules -fmodules-cache-path=DIR/module-cache -fimplicit-modules -fimplicit-module-maps",
   "file": "DIR/modules_cdb_input.cpp"
 },
 {
   "directory": "DIR",
-  "command": "clang -E DIR/modules_cdb_input.cpp -IInputs -fmodules -fcxx-modules -fmodules-cache-path=DIR/module-cache -fimplicit-modules -fimplicit-module-maps -o a.o",
+  "command": "clang -E DIR/modules_cdb_input.cpp -IInputs -ffreestanding -fmodules -fcxx-modules -fmodules-cache-path=DIR/module-cache -fimplicit-modules -fimplicit-module-maps -o a.o",
   "file": "DIR/modules_cdb_input.cpp"
 },
 {
   "directory": "DIR",
-  "command": "clang -E DIR/modules_cdb_input.cpp -IInputs -fmodules -fcxx-modules -fmodules-cache-path=DIR/module-cache -fimplicit-modules -fimplicit-module-maps -o b.o",
+  "command": "clang -E DIR/modules_cdb_input.cpp -IInputs -ffreestanding -fmodules -fcxx-modules -fmodules-cache-path=DIR/module-cache -fimplicit-modules -fimplicit-module-maps -o b.o",
   "file": "DIR/modules_cdb_input.cpp"
 }
 ]
Index: clang/test/ClangScanDeps/Inputs/modules-pch/cdb_tu_with_common.json
===================================================================
--- clang/test/ClangScanDeps/Inputs/modules-pch/cdb_tu_with_common.json
+++ clang/test/ClangScanDeps/Inputs/modules-pch/cdb_tu_with_common.json
@@ -1,7 +1,7 @@
 [
   {
     "directory": "DIR",
-    "command": "clang -fsyntax-only DIR/tu_with_common.c -fmodules -gmodules -fimplicit-module-maps -fmodules-cache-path=DIR/cache -include DIR/pch.h -o DIR/tu_with_common.o",
+    "command": "clang -ffreestanding -fsyntax-only DIR/tu_with_common.c -fmodules -gmodules -fimplicit-module-maps -fmodules-cache-path=DIR/cache -include DIR/pch.h -o DIR/tu_with_common.o",
     "file": "DIR/tu_with_common.c"
   }
 ]
Index: clang/test/ClangScanDeps/Inputs/modules-pch/cdb_tu.json
===================================================================
--- clang/test/ClangScanDeps/Inputs/modules-pch/cdb_tu.json
+++ clang/test/ClangScanDeps/Inputs/modules-pch/cdb_tu.json
@@ -1,7 +1,7 @@
 [
   {
     "directory": "DIR",
-    "command": "clang -fsyntax-only DIR/tu.c -fmodules -gmodules -fimplicit-module-maps -fmodules-cache-path=DIR/cache -include DIR/pch.h -o DIR/tu.o",
+    "command": "clang -ffreestanding -fsyntax-only DIR/tu.c -fmodules -gmodules -fimplicit-module-maps -fmodules-cache-path=DIR/cache -include DIR/pch.h -o DIR/tu.o",
     "file": "DIR/tu.c"
   }
 ]
Index: clang/test/ClangScanDeps/Inputs/modules-pch/cdb_pch.json
===================================================================
--- clang/test/ClangScanDeps/Inputs/modules-pch/cdb_pch.json
+++ clang/test/ClangScanDeps/Inputs/modules-pch/cdb_pch.json
@@ -1,7 +1,7 @@
 [
   {
     "directory": "DIR",
-    "command": "clang -x c-header DIR/pch.h -fmodules -gmodules -fimplicit-module-maps -fmodules-cache-path=DIR/cache -o DIR/pch.h.gch",
+    "command": "clang -x c-header DIR/pch.h -ffreestanding -fmodules -gmodules -fimplicit-module-maps -fmodules-cache-path=DIR/cache -o DIR/pch.h.gch",
     "file": "DIR/pch.h"
   }
 ]
Index: clang/test/ClangScanDeps/Inputs/modules-pch-common-via-submodule/cdb_tu.json
===================================================================
--- clang/test/ClangScanDeps/Inputs/modules-pch-common-via-submodule/cdb_tu.json
+++ clang/test/ClangScanDeps/Inputs/modules-pch-common-via-submodule/cdb_tu.json
@@ -1,7 +1,7 @@
 [
   {
     "directory": "DIR",
-    "command": "clang -fsyntax-only DIR/tu.c -fmodules -gmodules -fimplicit-module-maps -fmodules-cache-path=DIR/cache -include DIR/pch.h -o DIR/tu.o",
+    "command": "clang -ffreestanding -fsyntax-only DIR/tu.c -fmodules -gmodules -fimplicit-module-maps -fmodules-cache-path=DIR/cache -include DIR/pch.h -o DIR/tu.o",
     "file": "DIR/tu.c"
   }
 ]
Index: clang/test/ClangScanDeps/Inputs/modules-pch-common-via-submodule/cdb_pch.json
===================================================================
--- clang/test/ClangScanDeps/Inputs/modules-pch-common-via-submodule/cdb_pch.json
+++ clang/test/ClangScanDeps/Inputs/modules-pch-common-via-submodule/cdb_pch.json
@@ -1,7 +1,7 @@
 [
   {
     "directory": "DIR",
-    "command": "clang -x c-header DIR/pch.h -fmodules -gmodules -fimplicit-module-maps -fmodules-cache-path=DIR/cache -o DIR/pch.h.gch",
+    "command": "clang -x c-header DIR/pch.h -ffreestanding -fmodules -gmodules -fimplicit-module-maps -fmodules-cache-path=DIR/cache -o DIR/pch.h.gch",
     "file": "DIR/pch.h"
   }
 ]
Index: clang/test/ClangScanDeps/Inputs/modules-pch-common-submodule/cdb_tu.json
===================================================================
--- clang/test/ClangScanDeps/Inputs/modules-pch-common-submodule/cdb_tu.json
+++ clang/test/ClangScanDeps/Inputs/modules-pch-common-submodule/cdb_tu.json
@@ -1,7 +1,7 @@
 [
   {
     "directory": "DIR",
-    "command": "clang -fsyntax-only DIR/tu.c -fmodules -gmodules -fimplicit-module-maps -fmodules-cache-path=DIR/cache -include DIR/pch.h -o DIR/tu.o",
+    "command": "clang -ffreestanding -fsyntax-only DIR/tu.c -fmodules -gmodules -fimplicit-module-maps -fmodules-cache-path=DIR/cache -include DIR/pch.h -o DIR/tu.o",
     "file": "DIR/tu.c"
   }
 ]
Index: clang/test/ClangScanDeps/Inputs/modules-pch-common-submodule/cdb_pch.json
===================================================================
--- clang/test/ClangScanDeps/Inputs/modules-pch-common-submodule/cdb_pch.json
+++ clang/test/ClangScanDeps/Inputs/modules-pch-common-submodule/cdb_pch.json
@@ -1,7 +1,7 @@
 [
   {
     "directory": "DIR",
-    "command": "clang -x c-header DIR/pch.h -fmodules -gmodules -fimplicit-module-maps -fmodules-cache-path=DIR/cache -o DIR/pch.h.gch",
+    "command": "clang -x c-header DIR/pch.h -ffreestanding -fmodules -gmodules -fimplicit-module-maps -fmodules-cache-path=DIR/cache -o DIR/pch.h.gch",
     "file": "DIR/pch.h"
   }
 ]
Index: clang/test/ClangScanDeps/Inputs/modules-context-hash/cdb_b.json.template
===================================================================
--- clang/test/ClangScanDeps/Inputs/modules-context-hash/cdb_b.json.template
+++ clang/test/ClangScanDeps/Inputs/modules-context-hash/cdb_b.json.template
@@ -1,7 +1,7 @@
 [
   {
     "directory": "DIR",
-    "command": "clang -c DIR/tu.c -fmodules -fmodules-cache-path=DIR/cache -IDIR/b -o DIR/tu_b.o",
+    "command": "clang -c DIR/tu.c -ffreestanding -fmodules -fmodules-cache-path=DIR/cache -IDIR/b -o DIR/tu_b.o",
     "file": "DIR/tu.c"
   }
 ]
Index: clang/test/ClangScanDeps/Inputs/modules-context-hash/cdb_a.json.template
===================================================================
--- clang/test/ClangScanDeps/Inputs/modules-context-hash/cdb_a.json.template
+++ clang/test/ClangScanDeps/Inputs/modules-context-hash/cdb_a.json.template
@@ -1,7 +1,7 @@
 [
   {
     "directory": "DIR",
-    "command": "clang -c DIR/tu.c -fmodules -fmodules-cache-path=DIR/cache -IDIR/a -o DIR/tu_a.o",
+    "command": "clang -c DIR/tu.c -ffreestanding -fmodules -fmodules-cache-path=DIR/cache -IDIR/a -o DIR/tu_a.o",
     "file": "DIR/tu.c"
   }
 ]
Index: clang/test/ClangScanDeps/Inputs/module_fmodule_name_cdb.json
===================================================================
--- clang/test/ClangScanDeps/Inputs/module_fmodule_name_cdb.json
+++ clang/test/ClangScanDeps/Inputs/module_fmodule_name_cdb.json
@@ -1,7 +1,7 @@
 [
 {
   "directory": "DIR",
-  "command": "clang -E DIR/modules-fmodule-name-no-module-built.m -IInputs -D INCLUDE_HEADER2 -MD -MF DIR/modules_cdb.d -fmodules -fcxx-modules -fmodules-cache-path=DIR/module-cache -fimplicit-modules -fmodule-name=header3 -fimplicit-module-maps",
+  "command": "clang -E DIR/modules-fmodule-name-no-module-built.m -IInputs -D INCLUDE_HEADER2 -MD -MF DIR/modules_cdb.d -ffreestanding -fmodules -fcxx-modules -fmodules-cache-path=DIR/module-cache -fimplicit-modules -fmodule-name=header3 -fimplicit-module-maps",
   "file": "DIR/modules-fmodule-name-no-module-built.m"
 }
 ]
Index: clang/test/ClangScanDeps/Inputs/headerwithdirnamefollowedbyinclude.json
===================================================================
--- clang/test/ClangScanDeps/Inputs/headerwithdirnamefollowedbyinclude.json
+++ clang/test/ClangScanDeps/Inputs/headerwithdirnamefollowedbyinclude.json
@@ -1,7 +1,7 @@
 [
     {
       "directory": "DIR",
-      "command": "clang -c -IDIR -IInputs DIR/headerwithdirname_input.cpp",
+      "command": "clang -c -IDIR -IInputs DIR/headerwithdirname_input.cpp -ffreestanding",
       "file": "DIR/headerwithdirname_input.cpp"
     },
     {
Index: clang/test/ClangScanDeps/Inputs/headerwithdirname.json
===================================================================
--- clang/test/ClangScanDeps/Inputs/headerwithdirname.json
+++ clang/test/ClangScanDeps/Inputs/headerwithdirname.json
@@ -1,7 +1,7 @@
 [
     {
       "directory": "DIR",
-      "command": "clang -c -IDIR -IDIR/foodir -IInputs DIR/headerwithdirname_input.cpp",
+      "command": "clang -c -IDIR -IDIR/foodir -IInputs DIR/headerwithdirname_input.cpp -ffreestanding",
       "file": "DIR/headerwithdirname_input.cpp"
     },
     {
Index: clang/test/ClangScanDeps/Inputs/header_stat_before_open_cdb.json
===================================================================
--- clang/test/ClangScanDeps/Inputs/header_stat_before_open_cdb.json
+++ clang/test/ClangScanDeps/Inputs/header_stat_before_open_cdb.json
@@ -1,7 +1,7 @@
 [
 {
   "directory": "DIR",
-  "command": "clang -E DIR/header_stat_before_open_input.m -iframework Inputs/frameworks",
+  "command": "clang -E DIR/header_stat_before_open_input.m -ffreestanding -iframework Inputs/frameworks",
   "file": "DIR/header_stat_before_open_input.m"
 },
 {
Index: clang/test/ClangScanDeps/Inputs/has_include_if_elif.json
===================================================================
--- clang/test/ClangScanDeps/Inputs/has_include_if_elif.json
+++ clang/test/ClangScanDeps/Inputs/has_include_if_elif.json
@@ -1,7 +1,7 @@
 [
 {
   "directory": "DIR",
-  "command": "clang -E DIR/has_include_if_elif2.cpp -IInputs",
+  "command": "clang -ffreestanding -E DIR/has_include_if_elif2.cpp -IInputs",
   "file": "DIR/has_include_if_elif2.cpp"
 },
 {
Index: clang/lib/Frontend/InitPreprocessor.cpp
===================================================================
--- clang/lib/Frontend/InitPreprocessor.cpp
+++ clang/lib/Frontend/InitPreprocessor.cpp
@@ -71,6 +71,15 @@
   Builder.append(Twine("#include \"") + File + "\"");
 }
 
+/// AddImplicitSystemIncludeIfExists - Add an implicit system \#include of the
+/// specified file to the predefines buffer: precheck with __has_include.
+static void AddImplicitSystemIncludeIfExists(MacroBuilder &Builder,
+                                             StringRef File) {
+  Builder.append(Twine("#if __has_include( <") + File + ">)");
+  Builder.append(Twine("#include <") + File + ">");
+  Builder.append(Twine("#endif"));
+}
+
 static void AddImplicitIncludeMacros(MacroBuilder &Builder, StringRef File) {
   Builder.append(Twine("#__include_macros \"") + File + "\"");
   // Marker token to stop the __include_macros fetch loop.
@@ -1374,6 +1383,15 @@
   if (!PP.getLangOpts().AsmPreprocessor)
     Builder.append("# 1 \"<built-in>\" 2");
 
+  // Process -fsystem-include-if-exists directives
+  if (!PP.getLangOpts().ObjC) {
+    for (unsigned i = 0, e = InitOpts.FSystemIncludeIfExists.size(); i != e;
+         ++i) {
+      const std::string &Path = InitOpts.FSystemIncludeIfExists[i];
+      AddImplicitSystemIncludeIfExists(Builder, Path);
+    }
+  }
+
   // If -imacros are specified, include them now.  These are processed before
   // any -include directives.
   for (unsigned i = 0, e = InitOpts.MacroIncludes.size(); i != e; ++i)
Index: clang/lib/Frontend/CompilerInvocation.cpp
===================================================================
--- clang/lib/Frontend/CompilerInvocation.cpp
+++ clang/lib/Frontend/CompilerInvocation.cpp
@@ -4224,6 +4224,9 @@
   for (const auto &CI : Opts.ChainedIncludes)
     GenerateArg(Args, OPT_chain_include, CI, SA);
 
+  for (const auto &FI : Opts.FSystemIncludeIfExists)
+    GenerateArg(Args, OPT_fsystem_include_if_exists, FI, SA);
+
   for (const auto &RF : Opts.RemappedFiles)
     GenerateArg(Args, OPT_remap_file, RF.first + ";" + RF.second, SA);
 
@@ -4301,6 +4304,10 @@
   for (const auto *A : Args.filtered(OPT_chain_include))
     Opts.ChainedIncludes.emplace_back(A->getValue());
 
+  // Add the ordered list of -fsystem-include-if-exists.
+  for (const Arg *A : Args.filtered(OPT_fsystem_include_if_exists))
+    Opts.FSystemIncludeIfExists.emplace_back(A->getValue());
+
   for (const auto *A : Args.filtered(OPT_remap_file)) {
     std::pair<StringRef, StringRef> Split = StringRef(A->getValue()).split(';');
 
Index: clang/lib/Driver/ToolChains/Linux.h
===================================================================
--- clang/lib/Driver/ToolChains/Linux.h
+++ clang/lib/Driver/ToolChains/Linux.h
@@ -33,6 +33,8 @@
   void addLibStdCxxIncludePaths(
       const llvm::opt::ArgList &DriverArgs,
       llvm::opt::ArgStringList &CC1Args) const override;
+  void AddGnuIncludeArgs(const llvm::opt::ArgList &DriverArgs,
+                         llvm::opt::ArgStringList &CC1Args) const;
   void AddCudaIncludeArgs(const llvm::opt::ArgList &DriverArgs,
                           llvm::opt::ArgStringList &CC1Args) const override;
   void AddHIPIncludeArgs(const llvm::opt::ArgList &DriverArgs,
Index: clang/lib/Driver/ToolChains/Linux.cpp
===================================================================
--- clang/lib/Driver/ToolChains/Linux.cpp
+++ clang/lib/Driver/ToolChains/Linux.cpp
@@ -632,10 +632,22 @@
 
   addExternCSystemInclude(DriverArgs, CC1Args, concat(SysRoot, "/usr/include"));
 
+  AddGnuIncludeArgs(DriverArgs, CC1Args);
+
   if (!DriverArgs.hasArg(options::OPT_nobuiltininc) && getTriple().isMusl())
     addSystemInclude(DriverArgs, CC1Args, ResourceDirInclude);
 }
 
+void Linux::AddGnuIncludeArgs(const llvm::opt::ArgList &DriverArgs,
+                              llvm::opt::ArgStringList &CC1Args) const {
+  if (!DriverArgs.hasArg(options::OPT_ffreestanding)) {
+    // For gcc compatibility, clang will preinclude <stdc-predef.h>
+    // -ffreestanding suppresses this behavior.
+    CC1Args.push_back("-fsystem-include-if-exists");
+    CC1Args.push_back("stdc-predef.h");
+  }
+}
+
 void Linux::addLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
                                      llvm::opt::ArgStringList &CC1Args) const {
   // We need a detected GCC installation on Linux to provide libstdc++'s
Index: clang/lib/Driver/Job.cpp
===================================================================
--- clang/lib/Driver/Job.cpp
+++ clang/lib/Driver/Job.cpp
@@ -67,14 +67,16 @@
     return true;
 
   // Some include flags shouldn't be skipped if we have a crash VFS
-  IsInclude = llvm::StringSwitch<bool>(Flag)
-    .Cases("-include", "-header-include-file", true)
-    .Cases("-idirafter", "-internal-isystem", "-iwithprefix", true)
-    .Cases("-internal-externc-isystem", "-iprefix", true)
-    .Cases("-iwithprefixbefore", "-isystem", "-iquote", true)
-    .Cases("-isysroot", "-I", "-F", "-resource-dir", true)
-    .Cases("-iframework", "-include-pch", true)
-    .Default(false);
+  IsInclude =
+      llvm::StringSwitch<bool>(Flag)
+          .Cases("-include", "-header-include-file", true)
+          .Cases("-idirafter", "-internal-isystem", "-iwithprefix", true)
+          .Cases("-internal-externc-isystem", "-iprefix", true)
+          .Cases("-iwithprefixbefore", "-isystem", "-iquote", true)
+          .Cases("-isysroot", "-I", "-F", "-resource-dir", true)
+          .Cases("-iframework", "-include-pch", "-fsystem-include-if-exists",
+                 true)
+          .Default(false);
   if (IsInclude)
     return !HaveCrashVFS;
 
Index: clang/include/clang/Lex/PreprocessorOptions.h
===================================================================
--- clang/include/clang/Lex/PreprocessorOptions.h
+++ clang/include/clang/Lex/PreprocessorOptions.h
@@ -99,6 +99,9 @@
   /// Headers that will be converted to chained PCHs in memory.
   std::vector<std::string> ChainedIncludes;
 
+  /// System Headers that are pre-included if they exist.
+  std::vector<std::string> FSystemIncludeIfExists;
+
   /// Whether to disable most of the normal validation performed on
   /// precompiled headers and module files.
   DisableValidationForModuleKind DisablePCHOrModuleValidation =
@@ -254,6 +257,7 @@
     ChainedIncludes.clear();
     DumpDeserializedPCHDecls = false;
     ImplicitPCHInclude.clear();
+    FSystemIncludeIfExists.clear();
     SingleFileParseMode = false;
     LexEditorPlaceholders = true;
     RetainRemappedFileBuffers = true;
Index: clang/include/clang/Driver/Options.td
===================================================================
--- clang/include/clang/Driver/Options.td
+++ clang/include/clang/Driver/Options.td
@@ -6315,6 +6315,8 @@
 def source_date_epoch : Separate<["-"], "source-date-epoch">,
   MetaVarName<"<time since Epoch in seconds>">,
   HelpText<"Time to be used in __DATE__, __TIME__, and __TIMESTAMP__ macros">;
+def fsystem_include_if_exists : Separate<["-"], "fsystem-include-if-exists">, MetaVarName<"<file>">,
+  HelpText<"Include system file before parsing if file exists">;
 
 } // let Flags = [CC1Option, NoDriverOption]
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to