Skip to content

Commit 98eefc4

Browse files
committed
[Clang] Support for MSVC compatible header search path ordering.
Clang has historically matched GCC's behavior for header search path order and pruning of duplicate paths. That traditional behavior is to order user search paths before system search paths, to ignore user search paths that duplicate a (later) system search path, and to ignore search paths that duplicate an earlier search path of the same user/system kind. This differs from MSVC and can result in inconsistent header file resolution for `#include` directives. MSVC orders header search paths as follows: 1) Paths specified by the `/I` and `/external:I` options are processed in the order that they appear. Paths specified by `/I` that duplicate a path specified by `/external:I` are ignored regardless of the order of the options. Paths specified by `/I` that duplicate a path from a prior `/I` option are ignored. Paths specified by `/external:I` that duplicate a path from a later `/external:I` option are ignored. 2) Paths specified by `/external:env` are processed in the order that they appear. Paths that duplicate a path from a `/I` or `/external:I` option are ignored regardless of the order of the options. Paths that duplicate a path from a prior `/external:env` option or an earlier path from the same `/external:env` option are ignored. 3) Paths specified by the `INCLUDE` environment variable are processed in the order they appear. Paths that duplicate a path from a `/I`, `/external:I`, or `/external:env` option are ignored. Paths that duplicate an earlier path in the `INCLUDE` environment variable are ignored. 4) Paths specified by the `EXTERNAL_INCLUDE` environment variable are processed in the order they appear. Paths that duplicate a path from a `/I`, `/external:I`, or `/external:env` option are ignored. Paths that duplicate a path from the `INCLUDE` environment variable are ignored. Paths that duplicate an earlier path in the `EXTERNAL_INCLUDE environment variable are ignored. Prior to this change, Clang handled the MSVC `/external:I` and `/external:env` options and the paths present in the `INCLUDE` and `EXTERNAL_INCLUDE` environment variables as though they were specified with the `-isystem` option. The GCC behavior described above then lead to a command line such as `/external:I dir1 /Idir2` having a header search order of `dir2` followed by `dir1`; contrary to MSVC behavior. Paths specified by the MSVC `/external:I` or `/external:env` options or by the `EXTERNAL_INCLUDE` environment variable are not just used to nominate a header search path. MSVC also uses these paths as external directory prefixes to mark paths that are to be treated as system directories. When a header file is resolved to a path for which one of these paths is a prefix match, that header file is treated as a system header regardless of whether the header file was resolved against a `/I` specified path. Note that it is not necessary for the final path component of the external path to match a directory in the filesystem in order to be used as an external directory prefix, though trailing path separators are significant. For example: Include directive Command line System header ------------------------ ------------------ ------------- #include <foobar/file.h> /I. /external:Ifoo Yes #include <foobar/file.h> /I. /external:Ifoo\ No This change adds support for the MSVC external path concept through the addition of new driver options with the following option syntax. clang clang-cl ------------------------ ------------------- -iexternal <dir> /external:I <dir> -iexternal-env=<ENV> /external:env:<ENV> Paths specified by these options are treated as system paths. That is, whether warnings are issued in header files found via these paths remains subject to use of the `-Wsystem-headers` and `-Wno-system-headers` options. Note that the MSVC `/external:W<N>` options are mapped to these options. The MSVC behavior described above implies that (system) paths present in the `INCLUDE` and `EXTERNAL_INCLUDE` environment variables do not suppress matching user paths specified via `/I`. This contrasts with GCC's behavior, and Clang's historical behavior, of suppressing user paths that match a system path regardless of how each is specified. In order to support both behaviors, the following driver option has been added. The option arguments shown reflect the default behavior for each driver. clang clang-cl ------------------------ ------------------------- -fheader-search=gcc -fheader-search=microsoft Use of the MSVC compatible header search path order by default for `clang-cl` is a change in behavior with potential to cause problems for some projects that build with `clang-cl`. Potentially impacted projects include those that specify a header search path via either the `/I` option or in the `CPATH` environment variable, but rely on the path being suppressed and/or treated as a system header due to a duplicate path specified by another MSVC option or environment variable or by the `-imsvc` option or one of the `-isystem` family of options. Such projects can pass the `-fheader-search=gcc` option in their `clang-cl` invocations to (mostly) restore previous behavior. Clang emulates the MSVC behavior of resolving quoted header file inclusions (e.g., `#include "file.h"`) by searching for a matching file in the directories for the including files in the include stack. See Microsoft's documentation of this feature in the Microsoft-specific section of https://learn.microsoft.com/en-us/cpp/preprocessor/hash-include-directive-c-cpp. Previously, this behavior was implicitly enabled when the `-fms-compatibility` option is specified (implicitly for Windows targets). This change ties this behavior to the `-fheader-search=microsoft` option instead. Projects that use the `clang` (not `clang-cl`) driver to build code targeting Windows that depend on this local header file lookup may be impacted by this change. Such projects can try adding `-fheader-search=microsoft` to their `clang` invocations to restore the prior behavior. There is at least one behavior that MSVC exhibits that is not currently replicated with these changes. Clang treats paths specified in the `INCLUDE` environment variable as system directories; MSVC does not. Clang will therefore suppress warnings in header files found via these paths by default while MSVC will not. However, recent MSVC releases set the `EXTERNAL_INCLUDE` environment variable to have the same paths as `INCLUDE` by default, so, for recent releases, MSVC appears to suppress warnings for header files found via `INCLUDE` by default when it does not. Note that many Microsoft provided header files use `#pragma` directives to suppress warnings. Finally, this change enables support for the MSVC `/external:anglebrackets` option with the following option syntax. Use of this option results in all header files included with angle bracket syntax (`#include <file.h>`) being treated as system headers for the purposes of warning suppression. clang clang-cl ------------------------ ----------------------- -iexternal-anglebrackets /external:anglebrackets
1 parent 3f9e073 commit 98eefc4

32 files changed

+2057
-177
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -389,6 +389,49 @@ Android Support
389389
Windows Support
390390
^^^^^^^^^^^^^^^
391391

392+
- Clang now matches MSVC behavior regarding the handling of duplicate header
393+
search paths when run via the ``clang-cl`` driver (by default) or with the
394+
``-fheader-search=microsoft`` option otherwise. Historically, Clang has
395+
mimicked GCC behavior in which user search paths are ordered before system
396+
search paths, user search paths that duplicate a (later) system search
397+
path are ignored, and search paths that duplicate an earlier search path of
398+
the same user/system kind are ignored. This ordering is not compatible with
399+
the ordering that MSVC uses when paths are duplicated across ``/I`` options
400+
and the ``INCLUDE`` environment variable.
401+
402+
The order that MSVC uses and that Clang now replicates when the
403+
``-fheader-search=microsoft`` option is enabled follows.
404+
405+
- Paths specified by the ``/I`` and ``/external:I`` options are processed in
406+
the order that they appear. Paths specified by ``/I`` that duplicate a path
407+
specified by ``/external:I`` are ignored regardless of the order of the
408+
options. Paths specified by ``/I`` that duplicate a path from a prior ``/I``
409+
option are ignored. Paths specified by ``/external:I`` that duplicate a
410+
path from a later ``/external:I`` option are ignored.
411+
412+
- Paths specified by ``/external:env`` are processed in the order that they
413+
appear. Paths that duplicate a path from a ``/I`` or ``/external:I`` option
414+
are ignored regardless of the order of the options. Paths that duplicate a
415+
path from a prior ``/external:env`` option or an earlier path from the same
416+
``/external:env`` option are ignored.
417+
418+
- Paths specified by the ``INCLUDE`` environment variable are processed in
419+
the order they appear. Paths that duplicate a path from a ``/I``,
420+
``/external:I``, or ``/external:env`` option are ignored. Paths that
421+
duplicate an earlier path in the ``INCLUDE`` environment variable are
422+
ignored.
423+
424+
- Paths specified by the ``EXTERNAL_INCLUDE`` environment variable are
425+
processed in the order they appear. Paths that duplicate a path from a
426+
``/I``, ``/external:I``, or ``/external:env`` option are ignored. Paths that
427+
duplicate a path from the ``INCLUDE`` environment variable are ignored.
428+
Paths that duplicate an earlier path in the ``EXTERNAL_INCLUDE``
429+
environment variable are ignored.
430+
431+
The ``-fheader-search=gcc`` option can be used to opt in to GCC duplicate
432+
header search path handling (which remains the default behavior for the GCC
433+
compatible drivers).
434+
392435
LoongArch Support
393436
^^^^^^^^^^^^^^^^^
394437

clang/docs/UsersManual.rst

Lines changed: 37 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5418,12 +5418,26 @@ follows:
54185418

54195419
2. Consult the environment.
54205420

5421-
TODO: This is not yet implemented.
5421+
- `/external:env:[VARIABLE]`
54225422

5423-
This will consult the environment variables:
5423+
This command line option specifies a user identified environment variable
5424+
which is treated as a path delimited (`;`) list of system header paths.
54245425

5425-
- `WindowsSdkDir`
5426-
- `UCRTVersion`
5426+
- `INCLUDE`
5427+
5428+
This environment variable is treated as a path delimited (`;`) list of
5429+
system header paths.
5430+
5431+
- `EXTERNAL_INCLUDE`
5432+
5433+
This environment variable is treated as a path delimited (`;`) list of
5434+
system header paths.
5435+
5436+
The following environment variables will be consulted and used to form paths
5437+
to validate and load content from as appropriate:
5438+
5439+
- `WindowsSdkDir`
5440+
- `UCRTVersion`
54275441

54285442
3. Fallback to the registry.
54295443

@@ -5435,6 +5449,8 @@ The Visual C++ Toolset has a slightly more elaborate mechanism for detection.
54355449

54365450
1. Consult the command line.
54375451

5452+
Anything the user specifies is always given precedence.
5453+
54385454
- `/winsysroot:`
54395455

54405456
The `/winsysroot:` is used as an equivalent to `-sysroot` on Unix
@@ -5452,21 +5468,30 @@ The Visual C++ Toolset has a slightly more elaborate mechanism for detection.
54525468

54535469
2. Consult the environment.
54545470

5455-
- `/external:[VARIABLE]`
5471+
- `/external:env:[VARIABLE]`
5472+
5473+
This command line option specifies a user identified environment variable
5474+
which is treated as a path delimited (`;`) list of external header search
5475+
paths. Additionally, any header search path provided by other means that
5476+
has a prefix that matches one of these paths is treated as an external
5477+
header search path.
5478+
5479+
- `INCLUDE`
54565480

5457-
This specifies a user identified environment variable which is treated as
5458-
a path delimiter (`;`) separated list of paths to map into `-imsvc`
5459-
arguments which are treated as `-isystem`.
5481+
This environment variable is treated as a path delimited (`;`) list of
5482+
header search paths.
54605483

5461-
- `INCLUDE` and `EXTERNAL_INCLUDE`
5484+
- `EXTERNAL_INCLUDE`
54625485

5463-
The path delimiter (`;`) separated list of paths will be mapped to
5464-
`-imsvc` arguments which are treated as `-isystem`.
5486+
This environment variable is treated as a path delimited (`;`) list of
5487+
external header search paths. Additionally, any header search path
5488+
provided by other means that has a prefix that matches one of these paths
5489+
is treated as an external header search path.
54655490

54665491
- `LIB` (indirectly)
54675492

54685493
The linker `link.exe` or `lld-link.exe` will honour the environment
5469-
variable `LIB` which is a path delimiter (`;`) set of paths to consult for
5494+
variable `LIB` which is a path delimited (`;`) set of paths to consult for
54705495
the import libraries to use when linking the final target.
54715496

54725497
The following environment variables will be consulted and used to form paths

clang/include/clang/Driver/Options.td

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4811,6 +4811,19 @@ def iapinotes_modules : JoinedOrSeparate<["-"], "iapinotes-modules">, Group<clan
48114811
def idirafter : JoinedOrSeparate<["-"], "idirafter">, Group<clang_i_Group>,
48124812
Visibility<[ClangOption, CC1Option]>,
48134813
HelpText<"Add directory to AFTER include search path">;
4814+
def iexternal : Separate<["-"], "iexternal">, Group<clang_i_Group>,
4815+
Visibility<[ClangOption, CC1Option]>,
4816+
HelpText<"Add directory to include search path with warnings suppressed">, MetaVarName<"<dir>">;
4817+
def iexternal_system : Separate<["-"], "iexternal-system">, Group<clang_i_Group>,
4818+
Visibility<[CC1Option]>,
4819+
HelpText<"Add directory to include search path with warnings suppressed">, MetaVarName<"<dir>">;
4820+
def iexternal_env_EQ : Joined<["-"], "iexternal-env=">, Group<clang_i_Group>,
4821+
Visibility<[ClangOption]>,
4822+
HelpText<"Add dirs in env var <var> to include search path with warnings suppressed">, MetaVarName<"<var>">;
4823+
def iexternal_anglebrackets : Flag<["-"], "iexternal-anglebrackets">, Group<clang_i_Group>,
4824+
Visibility<[ClangOption, CC1Option]>,
4825+
HelpText<"Treat all #include paths enclosed in angle brackets as including a system header">,
4826+
MarshallingInfoFlag<HeaderSearchOpts<"AngleBracketsImpliesSystemHeader">>;
48144827
def iframework : JoinedOrSeparate<["-"], "iframework">, Group<clang_i_Group>,
48154828
Visibility<[ClangOption, CC1Option]>,
48164829
HelpText<"Add directory to SYSTEM framework search path">;
@@ -4853,6 +4866,10 @@ def isysroot : JoinedOrSeparate<["-"], "isysroot">, Group<clang_i_Group>,
48534866
def isystem : JoinedOrSeparate<["-"], "isystem">, Group<clang_i_Group>,
48544867
Visibility<[ClangOption, CC1Option]>,
48554868
HelpText<"Add directory to SYSTEM include search path">, MetaVarName<"<directory>">;
4869+
def isystem_env_EQ : Joined<["-"], "isystem-env=">, Group<clang_i_Group>,
4870+
MetaVarName<"<var>">,
4871+
Visibility<[ClangOption]>,
4872+
HelpText<"Add directoires in env var <var> to SYSTEM include search path">;
48564873
def isystem_after : JoinedOrSeparate<["-"], "isystem-after">,
48574874
Group<clang_i_Group>, Flags<[NoXarchOption]>, MetaVarName<"<directory>">,
48584875
HelpText<"Add directory to end of the SYSTEM include search path">;
@@ -8620,6 +8637,17 @@ def fexperimental_max_bitint_width_EQ:
86208637
// Header Search Options
86218638
//===----------------------------------------------------------------------===//
86228639

8640+
let Visibility = [ClangOption, CC1Option, CLOption] in {
8641+
8642+
def fheader_search : Joined<["-"], "fheader-search=">, Group<clang_i_Group>,
8643+
HelpText<"Specify the method used to resolve included header files">,
8644+
Values<"gcc,microsoft">,
8645+
NormalizedValuesScope<"clang::HeaderSearchMode">,
8646+
NormalizedValues<["GCC", "Microsoft"]>,
8647+
MarshallingInfoEnum<HeaderSearchOpts<"Mode">, "GCC">;
8648+
8649+
} // let Visibility = [ClangOption, CC1Option, CLOption]
8650+
86238651
let Visibility = [CC1Option] in {
86248652

86258653
def nostdsysteminc : Flag<["-"], "nostdsysteminc">,
@@ -8653,6 +8681,12 @@ def internal_isystem : Separate<["-"], "internal-isystem">,
86538681
HelpText<"Add directory to the internal system include search path; these "
86548682
"are assumed to not be user-provided and are used to model system "
86558683
"and standard headers' paths.">;
8684+
def internal_iexternal_system : Separate<["-"], "internal-iexternal-system">,
8685+
MetaVarName<"<directory>">,
8686+
HelpText<"Add directory to the internal system include search path with "
8687+
"external directory prefix semantics; these are assumed to not be "
8688+
"user-provided and are used to model system and standard headers' "
8689+
"paths.">;
86568690
def internal_externc_isystem : Separate<["-"], "internal-externc-isystem">,
86578691
MetaVarName<"<directory>">,
86588692
HelpText<"Add directory to the internal system include search path with "
@@ -8906,9 +8940,14 @@ def _SLASH_diagnostics_classic : CLFlag<"diagnostics:classic">,
89068940
def _SLASH_D : CLJoinedOrSeparate<"D", [CLOption, DXCOption]>,
89078941
HelpText<"Define macro">, MetaVarName<"<macro[=value]>">, Alias<D>;
89088942
def _SLASH_E : CLFlag<"E">, HelpText<"Preprocess to stdout">, Alias<E>;
8909-
def _SLASH_external_COLON_I : CLJoinedOrSeparate<"external:I">, Alias<isystem>,
8943+
def _SLASH_external_COLON_I : CLJoinedOrSeparate<"external:I">, Alias<iexternal>,
89108944
HelpText<"Add directory to include search path with warnings suppressed">,
89118945
MetaVarName<"<dir>">;
8946+
def _SLASH_external_env : CLJoined<"external:env:">, Alias<iexternal_env_EQ>,
8947+
HelpText<"Add dirs in env var <var> to include search path with warnings suppressed">,
8948+
MetaVarName<"<var>">;
8949+
def _SLASH_external_anglebrackets : CLFlag<"external:anglebrackets">, Alias<iexternal_anglebrackets>,
8950+
HelpText<"Treat all #include paths enclosed in angle brackets as including a system header">;
89128951
def _SLASH_fp_contract : CLFlag<"fp:contract">, HelpText<"">, Alias<ffp_contract>, AliasArgs<["on"]>;
89138952
def _SLASH_fp_except : CLFlag<"fp:except">, HelpText<"">, Alias<ffp_exception_behavior_EQ>, AliasArgs<["strict"]>;
89148953
def _SLASH_fp_except_ : CLFlag<"fp:except-">, HelpText<"">, Alias<ffp_exception_behavior_EQ>, AliasArgs<["ignore"]>;
@@ -9148,9 +9187,6 @@ def _SLASH_d2epilogunwindrequirev2 : CLFlag<"d2epilogunwindrequirev2">,
91489187
def _SLASH_EH : CLJoined<"EH">, HelpText<"Set exception handling model">;
91499188
def _SLASH_EP : CLFlag<"EP">,
91509189
HelpText<"Disable linemarker output and preprocess to stdout">;
9151-
def _SLASH_external_env : CLJoined<"external:env:">,
9152-
HelpText<"Add dirs in env var <var> to include search path with warnings suppressed">,
9153-
MetaVarName<"<var>">;
91549190
def _SLASH_FA : CLJoined<"FA">,
91559191
HelpText<"Output assembly code file during compilation">;
91569192
def _SLASH_Fa : CLJoined<"Fa">,

clang/include/clang/Driver/ToolChain.h

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,7 @@ class ToolChain {
219219
/// \return The subdirectory path if it exists.
220220
std::optional<std::string> getTargetSubDirPath(StringRef BaseDir) const;
221221

222+
public:
222223
/// \name Utilities for implementing subclasses.
223224
///@{
224225
static void addSystemFrameworkInclude(const llvm::opt::ArgList &DriverArgs,
@@ -236,16 +237,28 @@ class ToolChain {
236237
ArrayRef<StringRef> Paths);
237238
static void addSystemIncludes(const llvm::opt::ArgList &DriverArgs,
238239
llvm::opt::ArgStringList &CC1Args,
239-
ArrayRef<StringRef> Paths);
240+
ArrayRef<StringRef> Paths,
241+
bool Internal = true);
242+
static bool addSystemIncludesFromEnv(const llvm::opt::ArgList &DriverArgs,
243+
llvm::opt::ArgStringList &CC1Args,
244+
StringRef Var, bool Internal = true);
245+
static void addExternalSystemIncludes(const llvm::opt::ArgList &DriverArgs,
246+
llvm::opt::ArgStringList &CC1Args,
247+
ArrayRef<StringRef> Paths,
248+
bool Internal = true);
249+
static bool
250+
addExternalSystemIncludesFromEnv(const llvm::opt::ArgList &DriverArgs,
251+
llvm::opt::ArgStringList &CC1Args,
252+
StringRef Var, bool Internal = true);
240253

241254
static std::string concat(StringRef Path, const Twine &A, const Twine &B = "",
242255
const Twine &C = "", const Twine &D = "");
243256
///@}
244257

245-
public:
246258
static void addSystemInclude(const llvm::opt::ArgList &DriverArgs,
247259
llvm::opt::ArgStringList &CC1Args,
248-
const Twine &Path);
260+
const Twine &Path, bool Internal = true);
261+
249262
virtual ~ToolChain();
250263

251264
// Accessors

clang/include/clang/Lex/HeaderSearch.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,15 @@ class HeaderSearch {
276276
/// a system header.
277277
std::vector<std::pair<std::string, bool>> SystemHeaderPrefixes;
278278

279+
/// External directories are user specified directories that are to be treated
280+
/// like system directories for the purposes of warning suppression. A header
281+
/// file that has a path that matches one of these prefixes is promoted to a
282+
/// system header regardless of which header search path was used to resolve
283+
/// the \#include directive. llvm::sys::path::remove_dots() is used to
284+
/// normalize these paths by removing "." and ".." path components and
285+
/// duplicate path separators. Trailing path separators are retained.
286+
llvm::StringSet<llvm::BumpPtrAllocator> ExternalDirectoryPrefixes;
287+
279288
/// The hash used for module cache paths.
280289
std::string ModuleHash;
281290

@@ -401,6 +410,9 @@ class HeaderSearch {
401410
SearchDirsUsage.push_back(false);
402411
}
403412

413+
/// Add an additional external directory prefix path.
414+
bool AddExternalDirectoryPrefix(StringRef Path);
415+
404416
/// Set the list of system header prefixes.
405417
void SetSystemHeaderPrefixes(ArrayRef<std::pair<std::string, bool>> P) {
406418
SystemHeaderPrefixes.assign(P.begin(), P.end());

clang/include/clang/Lex/HeaderSearchOptions.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,19 @@ enum IncludeDirGroup {
3535
/// Paths for '\#include <>' added by '-I'.
3636
Angled,
3737

38+
/// Like Angled, but marks the directory as an external directory prefix.
39+
/// This group is intended to match the semantics of the MSVC /external:I
40+
/// option.
41+
External,
42+
3843
/// Like Angled, but marks system directories.
3944
System,
4045

46+
/// Like System, but marks the directory as an external directory prefix.
47+
/// This group is intended to match the semantics of the MSVC
48+
/// /external:env option.
49+
ExternalSystem,
50+
4151
/// Like System, but headers are implicitly wrapped in extern "C".
4252
ExternCSystem,
4353

@@ -59,6 +69,11 @@ enum IncludeDirGroup {
5969

6070
} // namespace frontend
6171

72+
/// HeaderSearchMode - The method used to resolve included headers to files.
73+
/// This controls the order in which include paths are searched and how
74+
/// duplicate search paths are handled.
75+
enum class HeaderSearchMode { GCC, Microsoft };
76+
6277
/// HeaderSearchOptions - Helper class for storing options related to the
6378
/// initialization of the HeaderSearch object.
6479
class HeaderSearchOptions {
@@ -93,6 +108,9 @@ class HeaderSearchOptions {
93108
: Prefix(Prefix), IsSystemHeader(IsSystemHeader) {}
94109
};
95110

111+
/// The header search mode to use.
112+
HeaderSearchMode Mode = HeaderSearchMode::GCC;
113+
96114
/// If non-empty, the directory to use as a "virtual system root" for include
97115
/// paths.
98116
std::string Sysroot;
@@ -207,6 +225,11 @@ class HeaderSearchOptions {
207225
LLVM_PREFERRED_TYPE(bool)
208226
unsigned Verbose : 1;
209227

228+
/// Whether header files specified in angle brackets should be treated as
229+
/// system headers.
230+
LLVM_PREFERRED_TYPE(bool)
231+
unsigned AngleBracketsImpliesSystemHeader : 1;
232+
210233
/// If true, skip verifying input files used by modules if the
211234
/// module was already verified during this build session (see
212235
/// \c BuildSessionTimestamp).
@@ -289,6 +312,7 @@ class HeaderSearchOptions {
289312
ModuleFileHomeIsCwd(false), EnablePrebuiltImplicitModules(false),
290313
UseBuiltinIncludes(true), UseStandardSystemIncludes(true),
291314
UseStandardCXXIncludes(true), UseLibcxx(false), Verbose(false),
315+
AngleBracketsImpliesSystemHeader(false),
292316
ModulesValidateOncePerBuildSession(false),
293317
ModulesValidateSystemHeaders(false),
294318
ModulesForceValidateUserHeaders(true),

clang/lib/Driver/Driver.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1534,7 +1534,10 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
15341534
if (VFS->setCurrentWorkingDirectory(WD->getValue()))
15351535
Diag(diag::err_drv_unable_to_set_working_directory) << WD->getValue();
15361536

1537-
// Check for missing include directories.
1537+
// Check for missing include directories. Diagnostics should not be issued
1538+
// for directories specified with -iexternal, -iexternal-env=, or
1539+
// -iexternal-system since those options may be used to specify external
1540+
// directory prefixes that don't necessarily match an existing path.
15381541
if (!Diags.isIgnored(diag::warn_missing_include_dirs, SourceLocation())) {
15391542
for (auto IncludeDir : Args.getAllArgValues(options::OPT_I_Group)) {
15401543
if (!VFS->exists(IncludeDir))

0 commit comments

Comments
 (0)