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