[clang] 063e17d - [clang] [Driver] More flexible rules for loading default configs

Michał Górny via cfe-commits cfe-commits at lists.llvm.org
Thu Sep 29 12:00:29 PDT 2022


Author: Michał Górny
Date: 2022-09-29T20:58:59+02:00
New Revision: 063e17d8b04b41cd8bd174aebb6603eb1a76d34a

URL: https://github.com/llvm/llvm-project/commit/063e17d8b04b41cd8bd174aebb6603eb1a76d34a
DIFF: https://github.com/llvm/llvm-project/commit/063e17d8b04b41cd8bd174aebb6603eb1a76d34a.diff

LOG: [clang] [Driver] More flexible rules for loading default configs

Change the default config file loading logic to be more flexible
and more readable at the same time.  The new algorithm focuses on four
locations, in order:

1. <triple>-<mode>.cfg using real driver mode
2. <triple>-<mode>.cfg using executable suffix
3. <triple>.cfg + <mode>.cfg using real driver mode
4. <triple>.cfg + <mode>.cfg using executable suffix

This is meant to preserve reasonable level of compatibility with
the existing use, while introducing more flexibility and making the code
simpler.  Notably:

1. In this layout, the actual target triple is normally respected,
   and e.g. in `-m32` build the `x86_64-*` configs will never be used.

2. Both real driver mode (preferable) and executable suffix are
   supported.  This permits correctly handling calls with explicit
   `--driver-mode=` while at the same time preserving compatibility
   with the existing code.

3. The first two locations provide users with the ability to override
   configuration per specific target+mode combinaton, while the next two
   make it possible to independently specify per-target and per-mode
   configuration.

4. All config file locations are applicable independently of whether
   clang is started via a prefixed executable, or bare `clang`.

5. If the target is not explicitly specified and the executable prefix
   does not name a valid triple, it is used instead of the actual target
   triple for backwards compatibility.

This is particularly meant to address Gentoo's use case for
configuration files: to configure the default runtimes (i.e. `-rtlib=`,
`-stdlib=`) and `--gcc-install-dir=` for all the relevant drivers,
as well as to make it more convenient for users to override `-W` flags
to test compatibility with future versions of Clang easier.

Differential Revision: https://reviews.llvm.org/D134337

Added: 
    

Modified: 
    clang/docs/ReleaseNotes.rst
    clang/docs/UsersManual.rst
    clang/include/clang/Driver/Driver.h
    clang/lib/Driver/Driver.cpp
    clang/test/Driver/config-file3.c

Removed: 
    


################################################################################
diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index d4f8de4dfd84..f464439f7832 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -242,6 +242,21 @@ Non-comprehensive list of changes in this release
 - Unicode support has been updated to support Unicode 15.0.
   New unicode codepoints are supported as appropriate in diagnostics,
   C and C++ identifiers, and escape sequences.
+- Clang now supports loading multiple configuration files. The files from
+  default configuration paths are loaded first, unless ``--no-default-config``
+  option is used. All files explicitly specified using ``--config=`` option
+  are loaded afterwards.
+- When loading default configuration files, clang now unconditionally uses
+  the real target triple (respecting options such as ``--target=`` and ``-m32``)
+  rather than the executable prefix. The respective configuration files are
+  also loaded when clang is called via an executable without a prefix (e.g.
+  plain ``clang``).
+- Default configuration paths were partially changed. Clang now attempts to load
+  ``<triple>-<driver>.cfg`` first, and falls back to loading both
+  ``<driver>.cfg`` and ``<triple>.cfg`` if the former is not found. `Triple`
+  is the target triple and `driver` first tries the canonical name
+  for the driver (respecting ``--driver-mode=``), and then the name found
+  in the executable.
 
 New Compiler Flags
 ------------------
@@ -257,12 +272,16 @@ New Compiler Flags
   `::operator new(size_­t, std::aligned_val_t, nothrow_­t)` if there is
   `get_­return_­object_­on_­allocation_­failure`. We feel this is more consistent
   with the intention.
+- Added ``--no-default-config`` to disable automatically loading configuration
+  files using default paths.
 
 Deprecated Compiler Flags
 -------------------------
 
 Modified Compiler Flags
 -----------------------
+- Clang now permits specifying ``--config=`` multiple times, to load multiple
+  configuration files.
 
 Removed Compiler Flags
 -------------------------

diff  --git a/clang/docs/UsersManual.rst b/clang/docs/UsersManual.rst
index d4c66e661dac..6428b69e94cf 100644
--- a/clang/docs/UsersManual.rst
+++ b/clang/docs/UsersManual.rst
@@ -914,27 +914,55 @@ following the rules described in the next paragraphs. Loading default
 configuration files can be disabled entirely via passing
 the ``--no-default-config`` flag.
 
-The name of the default configuration file is deduced from the clang executable
-name.  For example, if the Clang executable is named ``armv7l-clang`` (it may
-be a symbolic link to ``clang``), then Clang will search for file
-``armv7l.cfg`` in the directory where Clang resides.
+First, the algorithm searches for a configuration file named
+``<triple>-<driver>.cfg`` where `triple` is the triple for the target being
+built for, and `driver` is the name of the currently used driver. The algorithm
+first attempts to use the canonical name for the driver used, then falls back
+to the one found in the executable name.
 
-If a driver mode is specified in invocation, Clang tries to find a file specific
-for the specified mode. For example, if the executable file is named
-``x86_64-clang-cl``, Clang first looks for ``x86_64-clang-cl.cfg`` and if it is
-not found, looks for ``x86_64.cfg``.
+The following canonical driver names are used:
 
-If the command line contains options that effectively change target architecture
-(these are ``-m32``, ``-EL``, and some others) and the configuration file starts
-with an architecture name, Clang tries to load the configuration file for the
-effective architecture. For example, invocation:
+- ``clang`` for the ``gcc`` driver (used to compile C programs)
+- ``clang++`` for the ``gxx`` driver (used to compile C++ programs)
+- ``clang-cpp`` for the ``cpp`` driver (pure preprocessor)
+- ``clang-cl`` for the ``cl`` driver
+- ``flang`` for the ``flang`` driver
+- ``clang-dxc`` for the ``dxc`` driver
 
-::
+For example, when calling ``x86_64-pc-linux-gnu-clang-g++``,
+the driver will first attempt to use the configuration file named::
+
+    x86_64-pc-linux-gnu-clang++.cfg
+
+If this file is not found, it will attempt to use the name found
+in the executable instead::
+
+    x86_64-pc-linux-gnu-clang-g++.cfg
+
+Note that options such as ``--driver-mode=``, ``--target=``, ``-m32`` affect
+the search algorithm. For example, the aforementioned executable called with
+``-m32`` argument will instead search for::
+
+    i386-pc-linux-gnu-clang++.cfg
+
+If none of the aforementioned files are found, the driver will instead search
+for separate driver and target configuration files and attempt to load both.
+The former is named ``<driver>.cfg`` while the latter is named
+``<triple>.cfg``. Similarly to the previous variants, the canonical driver name
+will be preferred, and the compiler will fall back to the actual name.
+
+For example, ``x86_64-pc-linux-gnu-clang-g++`` will attempt to load two
+configuration files named respectively::
+
+    clang++.cfg
+    x86_64-pc-linux-gnu.cfg
+
+with fallback to trying::
 
-    x86_64-clang -m32 abc.c
+    clang-g++.cfg
+    x86_64-pc-linux-gnu.cfg
 
-causes Clang search for a file ``i368.cfg`` first, and if no such file is found,
-Clang looks for the file ``x86_64.cfg``.
+It is not an error if either of these files is not found.
 
 The configuration file consists of command-line options specified on one or
 more lines. Lines composed of whitespace characters only are ignored as well as

diff  --git a/clang/include/clang/Driver/Driver.h b/clang/include/clang/Driver/Driver.h
index 203557a5cfc6..fe2b4bd629fa 100644
--- a/clang/include/clang/Driver/Driver.h
+++ b/clang/include/clang/Driver/Driver.h
@@ -731,6 +731,9 @@ class Driver {
           &CachedResults,
       Action::OffloadKind TargetDeviceOffloadKind) const;
 
+  /// Return the typical executable name for the specified driver \p Mode.
+  static const char *getExecutableForDriverMode(DriverMode Mode);
+
 public:
   /// GetReleaseVersion - Parse (([0-9]+)(.([0-9]+)(.([0-9]+)?))?)? and
   /// return the grouped values as integers. Numbers which are not

diff  --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index f2ae25df5825..b8ef37904574 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -1068,79 +1068,74 @@ bool Driver::loadConfigFiles() {
 bool Driver::loadDefaultConfigFiles(ArrayRef<StringRef> CfgFileSearchDirs) {
   if (CLOptions && CLOptions->hasArg(options::OPT_no_default_config))
     return false;
-  if (ClangNameParts.TargetPrefix.empty())
-    return false;
 
-  // If config file is not specified explicitly, try to deduce configuration
-  // from executable name. For instance, an executable 'armv7l-clang' will
-  // search for config file 'armv7l-clang.cfg'.
-  std::string CfgFileName =
-        ClangNameParts.TargetPrefix + '-' + ClangNameParts.ModeSuffix;
-
-  // Determine architecture part of the file name, if it is present.
-  StringRef CfgFileArch = CfgFileName;
-  size_t ArchPrefixLen = CfgFileArch.find('-');
-  if (ArchPrefixLen == StringRef::npos)
-    ArchPrefixLen = CfgFileArch.size();
-  llvm::Triple CfgTriple;
-  CfgFileArch = CfgFileArch.take_front(ArchPrefixLen);
-  CfgTriple = llvm::Triple(llvm::Triple::normalize(CfgFileArch));
-  if (CfgTriple.getArch() == llvm::Triple::ArchType::UnknownArch)
-    ArchPrefixLen = 0;
-
-  if (!StringRef(CfgFileName).endswith(".cfg"))
-    CfgFileName += ".cfg";
-
-  // If config file starts with architecture name and command line options
-  // redefine architecture (with options like -m32 -LE etc), try finding new
-  // config file with that architecture.
-  SmallString<128> FixedConfigFile;
-  size_t FixedArchPrefixLen = 0;
-  if (ArchPrefixLen) {
-    // Get architecture name from config file name like 'i386.cfg' or
-    // 'armv7l-clang.cfg'.
-    // Check if command line options changes effective triple.
-    llvm::Triple EffectiveTriple =
-        computeTargetTriple(*this, CfgTriple.getTriple(), *CLOptions);
-    if (CfgTriple.getArch() != EffectiveTriple.getArch()) {
-      FixedConfigFile = EffectiveTriple.getArchName();
-      FixedArchPrefixLen = FixedConfigFile.size();
-      // Append the rest of original file name so that file name transforms
-      // like: i386-clang.cfg -> x86_64-clang.cfg.
-      if (ArchPrefixLen < CfgFileName.size())
-        FixedConfigFile += CfgFileName.substr(ArchPrefixLen);
-    }
-  }
-
-  // Try to find config file. First try file with corrected architecture.
+  std::string RealMode = getExecutableForDriverMode(Mode);
+  std::string Triple;
+
+  // If name prefix is present, no --target= override was passed via CLOptions
+  // and the name prefix is not a valid triple, force it for backwards
+  // compatibility.
+  if (!ClangNameParts.TargetPrefix.empty() &&
+      computeTargetTriple(*this, "/invalid/", *CLOptions).str() ==
+          "/invalid/") {
+    llvm::Triple PrefixTriple{ClangNameParts.TargetPrefix};
+    if (PrefixTriple.getArch() == llvm::Triple::UnknownArch ||
+        PrefixTriple.isOSUnknown())
+      Triple = PrefixTriple.str();
+  }
+
+  // Otherwise, use the real triple as used by the driver.
+  if (Triple.empty()) {
+    llvm::Triple RealTriple =
+        computeTargetTriple(*this, TargetTriple, *CLOptions);
+    Triple = RealTriple.str();
+    assert(!Triple.empty());
+  }
+
+  // Search for config files in the following order:
+  // 1. <triple>-<mode>.cfg using real driver mode
+  //    (e.g. i386-pc-linux-gnu-clang++.cfg).
+  // 2. <triple>-<mode>.cfg using executable suffix
+  //    (e.g. i386-pc-linux-gnu-clang-g++.cfg for *clang-g++).
+  // 3. <triple>.cfg + <mode>.cfg using real driver mode
+  //    (e.g. i386-pc-linux-gnu.cfg + clang++.cfg).
+  // 4. <triple>.cfg + <mode>.cfg using executable suffix
+  //    (e.g. i386-pc-linux-gnu.cfg + clang-g++.cfg for *clang-g++).
+
+  // Try loading <triple>-<mode>.cfg, and return if we find a match.
   llvm::SmallString<128> CfgFilePath;
-  if (!FixedConfigFile.empty()) {
-    if (searchForFile(CfgFilePath, CfgFileSearchDirs, FixedConfigFile,
-                      getVFS()))
-      return readConfigFile(CfgFilePath);
-    // If 'x86_64-clang.cfg' was not found, try 'x86_64.cfg'.
-    FixedConfigFile.resize(FixedArchPrefixLen);
-    FixedConfigFile.append(".cfg");
-    if (searchForFile(CfgFilePath, CfgFileSearchDirs, FixedConfigFile,
-                      getVFS()))
-      return readConfigFile(CfgFilePath);
-  }
-
-  // Then try original file name.
+  std::string CfgFileName = Triple + '-' + RealMode + ".cfg";
   if (searchForFile(CfgFilePath, CfgFileSearchDirs, CfgFileName, getVFS()))
     return readConfigFile(CfgFilePath);
 
-  // Finally try removing driver mode part: 'x86_64-clang.cfg' -> 'x86_64.cfg'.
-  if (!ClangNameParts.ModeSuffix.empty() &&
-      !ClangNameParts.TargetPrefix.empty()) {
-    CfgFileName.assign(ClangNameParts.TargetPrefix);
-    CfgFileName.append(".cfg");
+  bool TryModeSuffix = !ClangNameParts.ModeSuffix.empty() &&
+                       ClangNameParts.ModeSuffix != RealMode;
+  if (TryModeSuffix) {
+    CfgFileName = Triple + '-' + ClangNameParts.ModeSuffix + ".cfg";
     if (searchForFile(CfgFilePath, CfgFileSearchDirs, CfgFileName, getVFS()))
       return readConfigFile(CfgFilePath);
   }
 
+  // Try loading <mode>.cfg, and return if loading failed.  If a matching file
+  // was not found, still proceed on to try <triple>.cfg.
+  CfgFileName = RealMode + ".cfg";
+  if (searchForFile(CfgFilePath, CfgFileSearchDirs, CfgFileName, getVFS())) {
+    if (readConfigFile(CfgFilePath))
+      return true;
+  } else if (TryModeSuffix) {
+    CfgFileName = ClangNameParts.ModeSuffix + ".cfg";
+    if (searchForFile(CfgFilePath, CfgFileSearchDirs, CfgFileName, getVFS()) &&
+        readConfigFile(CfgFilePath))
+      return true;
+  }
+
+  // Try loading <triple>.cfg and return if we find a match.
+  CfgFileName = Triple + ".cfg";
+  if (searchForFile(CfgFilePath, CfgFileSearchDirs, CfgFileName, getVFS()))
+    return readConfigFile(CfgFilePath);
+
   // If we were unable to find a config file deduced from executable name,
-  // do not report an error.
+  // that is not an error.
   return false;
 }
 
@@ -6201,6 +6196,25 @@ Driver::getIncludeExcludeOptionFlagMasks(bool IsClCompatMode) const {
   return std::make_pair(IncludedFlagsBitmask, ExcludedFlagsBitmask);
 }
 
+const char *Driver::getExecutableForDriverMode(DriverMode Mode) {
+  switch (Mode) {
+  case GCCMode:
+    return "clang";
+  case GXXMode:
+    return "clang++";
+  case CPPMode:
+    return "clang-cpp";
+  case CLMode:
+    return "clang-cl";
+  case FlangMode:
+    return "flang";
+  case DXCMode:
+    return "clang-dxc";
+  }
+
+  llvm_unreachable("Unhandled Mode");
+}
+
 bool clang::driver::isOptimizationLevelFast(const ArgList &Args) {
   return Args.hasFlag(options::OPT_Ofast, options::OPT_O_Group, false);
 }

diff  --git a/clang/test/Driver/config-file3.c b/clang/test/Driver/config-file3.c
index 3158ac0d7f3b..17a230947105 100644
--- a/clang/test/Driver/config-file3.c
+++ b/clang/test/Driver/config-file3.c
@@ -9,112 +9,256 @@
 // RUN: echo "@subdir/cfg-s2" > %t/workdir/cfg-1
 // RUN: echo "-Wundefined-var-template" > %t/workdir/subdir/cfg-s2
 //
-// RUN: ( cd %t && %clang --config workdir/cfg-1 -c -### %s 2>&1 | FileCheck %s -check-prefix CHECK-REL )
+// RUN: ( cd %t && %clang --config=workdir/cfg-1 -c -### %s 2>&1 | FileCheck %s -check-prefix CHECK-REL )
 //
 // CHECK-REL: Configuration file: {{.*}}/workdir/cfg-1
 // CHECK-REL: -Wundefined-var-template
 
+//--- Config files are searched for in binary directory as well.
+//
+// RUN: mkdir %t/testbin
+// RUN: ln -s %clang %t/testbin/clang
+// RUN: echo "-Werror" > %t/testbin/aaa.cfg
+// RUN: %t/testbin/clang --config-system-dir= --config-user-dir= --config=aaa.cfg -c -no-canonical-prefixes -### %s 2>&1 | FileCheck %s -check-prefix CHECK-BIN
+//
+// CHECK-BIN: Configuration file: {{.*}}/testbin/aaa.cfg
+// CHECK-BIN: -Werror
 
-//--- Invocation qqq-clang-g++ tries to find config file qqq-clang-g++.cfg first.
+//--- Invocation x86_64-unknown-linux-gnu-clang-g++ tries x86_64-unknown-linux-gnu-clang++.cfg first.
 //
 // RUN: mkdir %t/testdmode
+// RUN: ln -s %clang %t/testdmode/cheribsd-riscv64-hybrid-clang++
 // RUN: ln -s %clang %t/testdmode/qqq-clang-g++
-// RUN: echo "-Wundefined-func-template" > %t/testdmode/qqq-clang-g++.cfg
-// RUN: echo "-Werror" > %t/testdmode/qqq.cfg
-// RUN: %t/testdmode/qqq-clang-g++ --config-system-dir= --config-user-dir= -c -no-canonical-prefixes -### %s 2>&1 | FileCheck %s -check-prefix FULL-NAME
+// RUN: ln -s %clang %t/testdmode/x86_64-clang
+// RUN: ln -s %clang %t/testdmode/i386-unknown-linux-gnu-clang-g++
+// RUN: ln -s %clang %t/testdmode/x86_64-unknown-linux-gnu-clang-g++
+// RUN: ln -s %clang %t/testdmode/x86_64-unknown-linux-gnu-clang
+// RUN: touch %t/testdmode/cheribsd-riscv64-hybrid-clang++.cfg
+// RUN: touch %t/testdmode/cheribsd-riscv64-hybrid.cfg
+// RUN: touch %t/testdmode/qqq-clang-g++.cfg
+// RUN: touch %t/testdmode/qqq.cfg
+// RUN: touch %t/testdmode/x86_64-clang.cfg
+// RUN: touch %t/testdmode/x86_64.cfg
+// RUN: touch %t/testdmode/x86_64-unknown-linux-gnu-clang++.cfg
+// RUN: touch %t/testdmode/x86_64-unknown-linux-gnu-clang-g++.cfg
+// RUN: touch %t/testdmode/x86_64-unknown-linux-gnu-clang.cfg
+// RUN: touch %t/testdmode/x86_64-unknown-linux-gnu.cfg
+// RUN: touch %t/testdmode/i386-unknown-linux-gnu-clang++.cfg
+// RUN: touch %t/testdmode/i386-unknown-linux-gnu-clang-g++.cfg
+// RUN: touch %t/testdmode/i386-unknown-linux-gnu-clang.cfg
+// RUN: touch %t/testdmode/i386-unknown-linux-gnu.cfg
+// RUN: touch %t/testdmode/clang++.cfg
+// RUN: touch %t/testdmode/clang-g++.cfg
+// RUN: touch %t/testdmode/clang.cfg
+// RUN: %t/testdmode/x86_64-unknown-linux-gnu-clang-g++ --config-system-dir= --config-user-dir= -no-canonical-prefixes --version 2>&1 | FileCheck %s -check-prefix FULL1
+//
+// FULL1-NOT: Configuration file:
+// FULL1: Configuration file: {{.*}}/testdmode/x86_64-unknown-linux-gnu-clang++.cfg
+// FULL1-NOT: Configuration file:
+
+//--- -m32 overrides triple.
+//
+// RUN: %t/testdmode/x86_64-unknown-linux-gnu-clang-g++ -m32 --config-system-dir= --config-user-dir= -no-canonical-prefixes --version 2>&1 | FileCheck %s -check-prefix FULL1-I386
+//
+// FULL1-I386-NOT: Configuration file:
+// FULL1-I386: Configuration file: {{.*}}/testdmode/i386-unknown-linux-gnu-clang++.cfg
+// FULL1-I386-NOT: Configuration file:
+
+//--- --target= also works for overriding triple.
+//
+// RUN: %t/testdmode/x86_64-unknown-linux-gnu-clang-g++ --target=i386-unknown-linux-gnu --config-system-dir= --config-user-dir= -no-canonical-prefixes --version 2>&1 | FileCheck %s -check-prefix FULL1-I386
+
+//--- With --target= + -m64, -m64 takes precedence.
+//
+// RUN: %t/testdmode/x86_64-unknown-linux-gnu-clang-g++ --target=i386-unknown-linux-gnu -m64 --config-system-dir= --config-user-dir= -no-canonical-prefixes --version 2>&1 | FileCheck %s -check-prefix FULL1
+
+//--- i386 prefix also works for 32-bit.
+//
+// RUN: %t/testdmode/i386-unknown-linux-gnu-clang-g++ --config-system-dir= --config-user-dir= -no-canonical-prefixes --version 2>&1 | FileCheck %s -check-prefix FULL1-I386
+
+//--- i386 prefix + -m64 also works for 64-bit.
+//
+// RUN: %t/testdmode/i386-unknown-linux-gnu-clang-g++ -m64 --config-system-dir= --config-user-dir= -no-canonical-prefixes --version 2>&1 | FileCheck %s -check-prefix FULL1
+
+//--- File specified by --config= is loaded after the one inferred from the executable.
 //
-// FULL-NAME: Configuration file: {{.*}}/testdmode/qqq-clang-g++.cfg
-// FULL-NAME: -Wundefined-func-template
-// FULL-NAME-NOT: -Werror
+// RUN: %t/testdmode/x86_64-unknown-linux-gnu-clang-g++ --config-system-dir=%S/Inputs/config --config-user-dir= --config=i386-qqq.cfg -no-canonical-prefixes --version 2>&1 | FileCheck %s -check-prefix EXPLICIT
 //
-//--- Invocation qqq-clang-g++ tries to find config file qqq-clang-g++.cfg even without -no-canonical-prefixes.
-// (As the clang executable and symlink are in 
diff erent directories, this
-// requires specifying the path via --config-*-dir= though.)
+// EXPLICIT: Configuration file: {{.*}}/testdmode/x86_64-unknown-linux-gnu-clang++.cfg
+// EXPLICIT-NEXT: Configuration file: {{.*}}/Inputs/config/i386-qqq.cfg
+
+//--- --no-default-config --config= loads only specified file.
 //
-// RUN: %t/testdmode/qqq-clang-g++ --config-system-dir= --config-user-dir=%t/testdmode -c -### %s 2>&1 | FileCheck %s -check-prefix SYMLINK
+// RUN: %t/testdmode/x86_64-unknown-linux-gnu-clang-g++ --config-system-dir=%S/Inputs/config --config-user-dir= --no-default-config --config=i386-qqq.cfg -no-canonical-prefixes --version 2>&1 | FileCheck %s -check-prefix EXPLICIT-ONLY
 //
-// SYMLINK: Configuration file: {{.*}}/testdmode/qqq-clang-g++.cfg
+// EXPLICIT-ONLY-NOT: Configuration file: {{.*}}/testdmode/x86_64-unknown-linux-gnu-clang++.cfg
+// EXPLICIT-ONLY: Configuration file: {{.*}}/Inputs/config/i386-qqq.cfg
 
-//--- File specified by --config is loaded after the one inferred from the executable.
+//--- --no-default-config disables default filenames.
 //
-// RUN: %t/testdmode/qqq-clang-g++ --config-system-dir=%S/Inputs/config --config-user-dir= --config i386-qqq.cfg -c -no-canonical-prefixes -### %s 2>&1 | FileCheck %s -check-prefix CHECK-EXPLICIT
+// RUN: %t/testdmode/x86_64-unknown-linux-gnu-clang-g++ --config-system-dir=%S/Inputs/config --config-user-dir= --no-default-config -no-canonical-prefixes --version 2>&1 | FileCheck %s -check-prefix NO-CONFIG
 //
-// CHECK-EXPLICIT: Configuration file: {{.*}}/testdmode/qqq-clang-g++.cfg
-// CHECK-EXPLICIT-NEXT: Configuration file: {{.*}}/Inputs/config/i386-qqq.cfg
+// NO-CONFIG-NOT: Configuration file:
 
-//--- --no-default-config disables config search.
+//--- --driver-mode= is respected.
+//
+// RUN: %t/testdmode/x86_64-unknown-linux-gnu-clang-g++ --driver-mode=gcc --config-system-dir= --config-user-dir= -no-canonical-prefixes --version 2>&1 | FileCheck %s -check-prefix FULL1-GCC
 //
-// RUN: %t/testdmode/qqq-clang-g++ --config-system-dir= --config-user-dir=%t/testdmode --no-default-config -c -### %s 2>&1 | FileCheck %s -check-prefix NO-DEFAULT-CONFIG
+// FULL1-GCC-NOT: Configuration file:
+// FULL1-GCC: Configuration file: {{.*}}/testdmode/x86_64-unknown-linux-gnu-clang.cfg
+// FULL1-GCC-NOT: Configuration file:
+
+//--- "clang" driver symlink should yield the "*-clang" configuration file.
 //
-// NO-DEFAULT-CONFIG-NOT: Configuration file:
+// RUN: %t/testdmode/x86_64-unknown-linux-gnu-clang --config-system-dir= --config-user-dir= -no-canonical-prefixes --version 2>&1 | FileCheck %s -check-prefix FULL1-GCC
 
-//--- Explicit --config works with --no-default-config.
+//--- "clang" + --driver-mode= should yield "*-clang++".
 //
-// RUN: %t/testdmode/qqq-clang-g++ --config-system-dir=%S/Inputs/config --config-user-dir= --no-default-config --config i386-qqq.cfg -c -no-canonical-prefixes -### %s 2>&1 | FileCheck %s -check-prefix CHECK-EXPLICIT-NO-DEFAULT
+// RUN: %t/testdmode/x86_64-unknown-linux-gnu-clang --driver-mode=g++ --config-system-dir= --config-user-dir= -no-canonical-prefixes --version 2>&1 | FileCheck %s -check-prefix FULL1
+
+//--- Clang started via name prefix that is not valid is forcing that prefix instead of target triple.
+//
+// RUN: %t/testdmode/qqq-clang-g++ --config-system-dir= --config-user-dir= -no-canonical-prefixes --version 2>&1 | FileCheck %s -check-prefix QQQ
+//
+// QQQ-NOT: Configuration file:
+// QQQ: Configuration file: {{.*}}/testdmode/qqq-clang-g++.cfg
+// QQQ-NOT: Configuration file:
+
+//--- Explicit --target= overrides the triple even with non-standard name prefix.
 //
-// CHECK-EXPLICIT-NO-DEFAULT-NOT: Configuration file: {{.*}}/testdmode/qqq-clang-g++.cfg
-// CHECK-EXPLICIT-NO-DEFAULT: Configuration file: {{.*}}/Inputs/config/i386-qqq.cfg
+// RUN: %t/testdmode/qqq-clang-g++ --target=x86_64-unknown-linux-gnu --config-system-dir= --config-user-dir= -no-canonical-prefixes --version 2>&1 | FileCheck %s -check-prefix FULL1
 
-//--- Invocation qqq-clang-g++ tries to find config file qqq.cfg if qqq-clang-g++.cfg is not found.
+//--- "x86_64" prefix does not form a valid triple either.
 //
+// RUN: %t/testdmode/x86_64-clang --config-system-dir= --config-user-dir= -no-canonical-prefixes --version 2>&1 | FileCheck %s -check-prefix X86_64
+//
+// X86_64-NOT: Configuration file:
+// X86_64: Configuration file: {{.*}}/testdmode/x86_64-clang.cfg
+// X86_64-NOT: Configuration file:
+
+//--- Try cheribsd prefix using misordered triple components.
+//
+// RUN: %t/testdmode/cheribsd-riscv64-hybrid-clang++ --config-system-dir= --config-user-dir= -no-canonical-prefixes --version 2>&1 | FileCheck %s -check-prefix CHERIBSD
+//
+// CHERIBSD-NOT: Configuration file:
+// CHERIBSD: Configuration file: {{.*}}/testdmode/cheribsd-riscv64-hybrid-clang++.cfg
+// CHERIBSD-NOT: Configuration file:
+
+//--- Test fallback to x86_64-unknown-linux-gnu-clang-g++.cfg.
+//
+// RUN: rm %t/testdmode/x86_64-unknown-linux-gnu-clang++.cfg
+// RUN: rm %t/testdmode/i386-unknown-linux-gnu-clang++.cfg
+// RUN: %t/testdmode/x86_64-unknown-linux-gnu-clang-g++ --config-system-dir= --config-user-dir= -no-canonical-prefixes --version 2>&1 | FileCheck %s -check-prefix FULL2
+//
+// FULL2-NOT: Configuration file:
+// FULL2: Configuration file: {{.*}}/testdmode/x86_64-unknown-linux-gnu-clang-g++.cfg
+// FULL2-NOT: Configuration file:
+
+//--- FULL2 + -m32.
+//
+// RUN: %t/testdmode/x86_64-unknown-linux-gnu-clang-g++ -m32 --config-system-dir= --config-user-dir= -no-canonical-prefixes --version 2>&1 | FileCheck %s -check-prefix FULL2-I386
+//
+// FULL2-I386-NOT: Configuration file:
+// FULL2-I386: Configuration file: {{.*}}/testdmode/i386-unknown-linux-gnu-clang-g++.cfg
+// FULL2-I386-NOT: Configuration file:
+
+//--- Test fallback to x86_64-unknown-linux-gnu-clang.cfg + clang++.cfg.
+//
+// RUN: rm %t/testdmode/cheribsd-riscv64-hybrid-clang++.cfg
 // RUN: rm %t/testdmode/qqq-clang-g++.cfg
-// RUN: %t/testdmode/qqq-clang-g++ --config-system-dir= --config-user-dir= -c -no-canonical-prefixes -### %s 2>&1 | FileCheck %s -check-prefix SHORT-NAME
+// RUN: rm %t/testdmode/x86_64-clang.cfg
+// RUN: rm %t/testdmode/x86_64-unknown-linux-gnu-clang-g++.cfg
+// RUN: rm %t/testdmode/i386-unknown-linux-gnu-clang-g++.cfg
+// RUN: rm %t/testdmode/x86_64-unknown-linux-gnu-clang.cfg
+// RUN: rm %t/testdmode/i386-unknown-linux-gnu-clang.cfg
+// RUN: %t/testdmode/x86_64-unknown-linux-gnu-clang-g++ --config-system-dir= --config-user-dir= -no-canonical-prefixes --version 2>&1 | FileCheck %s -check-prefix FULL3
 //
-// SHORT-NAME: Configuration file: {{.*}}/testdmode/qqq.cfg
-// SHORT-NAME: -Werror
-// SHORT-NAME-NOT: -Wundefined-func-template
+// FULL3-NOT: Configuration file:
+// FULL3: Configuration file: {{.*}}/testdmode/clang++.cfg
+// FULL3-NOT: Configuration file:
+// FULL3: Configuration file: {{.*}}/testdmode/x86_64-unknown-linux-gnu.cfg
+// FULL3-NOT: Configuration file:
 
+//--- FULL3 + -m32.
+//
+// RUN: %t/testdmode/x86_64-unknown-linux-gnu-clang-g++ -m32 --config-system-dir= --config-user-dir= -no-canonical-prefixes --version 2>&1 | FileCheck %s -check-prefix FULL3-I386
+//
+// FULL3-I386-NOT: Configuration file:
+// FULL3-I386: Configuration file: {{.*}}/testdmode/clang++.cfg
+// FULL3-I386-NOT: Configuration file:
+// FULL3-I386: Configuration file: {{.*}}/testdmode/i386-unknown-linux-gnu.cfg
+// FULL3-I386-NOT: Configuration file:
 
-//--- Config files are searched for in binary directory as well.
+//--- FULL3 + --driver-mode=.
 //
-// RUN: mkdir %t/testbin
-// RUN: ln -s %clang %t/testbin/clang
-// RUN: echo "-Werror" > %t/testbin/aaa.cfg
-// RUN: %t/testbin/clang --config-system-dir= --config-user-dir= --config aaa.cfg -c -no-canonical-prefixes -### %s 2>&1 | FileCheck %s -check-prefix CHECK-BIN
+// RUN: %t/testdmode/x86_64-unknown-linux-gnu-clang-g++ --driver-mode=gcc --config-system-dir= --config-user-dir= -no-canonical-prefixes --version 2>&1 | FileCheck %s -check-prefix FULL3-GCC
 //
-// CHECK-BIN: Configuration file: {{.*}}/testbin/aaa.cfg
-// CHECK-BIN: -Werror
+// FULL3-GCC-NOT: Configuration file:
+// FULL3-GCC: Configuration file: {{.*}}/testdmode/clang.cfg
+// FULL3-GCC-NOT: Configuration file:
+// FULL3-GCC: Configuration file: {{.*}}/testdmode/x86_64-unknown-linux-gnu.cfg
+// FULL3-GCC-NOT: Configuration file:
 
+//--- QQQ fallback.
+//
+// RUN: %t/testdmode/qqq-clang-g++ --config-system-dir= --config-user-dir= -no-canonical-prefixes --version 2>&1 | FileCheck %s -check-prefix QQQ-FALLBACK
+//
+// QQQ-FALLBACK-NOT: Configuration file:
+// QQQ-FALLBACK: Configuration file: {{.*}}/testdmode/clang++.cfg
+// QQQ-FALLBACK-NOT: Configuration file:
+// QQQ-FALLBACK: Configuration file: {{.*}}/testdmode/qqq.cfg
+// QQQ-FALLBACK-NOT: Configuration file:
 
-//--- If command line contains options that change triple (for instance, -m32), clang tries
-//    reloading config file.
+//--- "x86_64" falback.
+//
+// RUN: %t/testdmode/x86_64-clang --config-system-dir= --config-user-dir= -no-canonical-prefixes --version 2>&1 | FileCheck %s -check-prefix X86_64-FALLBACK
+//
+// X86_64-FALLBACK-NOT: Configuration file:
+// X86_64-FALLBACK: Configuration file: {{.*}}/testdmode/clang.cfg
+// X86_64-FALLBACK-NOT: Configuration file:
+// X86_64-FALLBACK: Configuration file: {{.*}}/testdmode/x86_64.cfg
+// X86_64-FALLBACK-NOT: Configuration file:
 
-//--- When reloading config file, x86_64-clang-g++ tries to find config i386-clang-g++.cfg first.
+//--- cheribsd fallback.
 //
-// RUN: mkdir %t/testreload
-// RUN: ln -s %clang %t/testreload/x86_64-clang-g++
-// RUN: echo "-Wundefined-func-template" > %t/testreload/i386-clang-g++.cfg
-// RUN: echo "-Werror" > %t/testreload/i386.cfg
-// RUN: echo "-Wall" > %t/testreload/x86_64-clang-g++.cfg
-// RUN: %t/testreload/x86_64-clang-g++ --config-system-dir= --config-user-dir= -c -m32 -no-canonical-prefixes -### %s 2>&1 | FileCheck %s -check-prefix CHECK-RELOAD
+// RUN: %t/testdmode/cheribsd-riscv64-hybrid-clang++ --config-system-dir= --config-user-dir= -no-canonical-prefixes --version 2>&1 | FileCheck %s -check-prefix CHERIBSD-FALLBACK
 //
-// CHECK-RELOAD: Configuration file: {{.*}}/testreload/i386-clang-g++.cfg
-// CHECK-RELOAD: -Wundefined-func-template
-// CHECK-RELOAD-NOT: -Werror
-// CHECK-RELOAD-NOT: -Wall
+// CHERIBSD-FALLBACK-NOT: Configuration file:
+// CHERIBSD-FALLBACK: Configuration file: {{.*}}/testdmode/clang++.cfg
+// CHERIBSD-FALLBACK-NOT: Configuration file:
+// CHERIBSD-FALLBACK: Configuration file: {{.*}}/testdmode/cheribsd-riscv64-hybrid.cfg
+// CHERIBSD-FALLBACK-NOT: Configuration file:
 
-//--- Same for -target in place of -m32.
-// RUN: %t/testreload/x86_64-clang-g++ --config-system-dir= --config-user-dir= -c -target i386 -no-canonical-prefixes -### %s 2>&1 | FileCheck %s -check-prefix CHECK-RELOAD
+//--- Test fallback to x86_64-unknown-linux-gnu.cfg + clang-g++.cfg.
+//
+// RUN: rm %t/testdmode/clang++.cfg
+// RUN: %t/testdmode/x86_64-unknown-linux-gnu-clang-g++ --config-system-dir= --config-user-dir= -no-canonical-prefixes --version 2>&1 | FileCheck %s -check-prefix FULL4
+//
+// FULL4-NOT: Configuration file:
+// FULL4: Configuration file: {{.*}}/testdmode/clang-g++.cfg
+// FULL4-NOT: Configuration file:
+// FULL4: Configuration file: {{.*}}/testdmode/x86_64-unknown-linux-gnu.cfg
+// FULL4-NOT: Configuration file:
 
-//--- `-target i386 -m64` should load the 64-bit config.
-// RUN: %t/testreload/x86_64-clang-g++ --config-system-dir= --config-user-dir= -c -target i386 -m64 -no-canonical-prefixes -### %s 2>&1 | FileCheck %s -check-prefix CHECK-RELOAD1a
+//--- Test fallback to clang-g++.cfg if x86_64-unknown-linux-gnu-clang.cfg does not exist.
+//
+// RUN: rm %t/testdmode/x86_64-unknown-linux-gnu.cfg
+// RUN: rm %t/testdmode/i386-unknown-linux-gnu.cfg
+// RUN: %t/testdmode/x86_64-unknown-linux-gnu-clang-g++ --config-system-dir= --config-user-dir= -no-canonical-prefixes --version 2>&1 | FileCheck %s -check-prefix FULL5
 //
-// CHECK-RELOAD1a: Configuration file: {{.*}}/testreload/x86_64-clang-g++.cfg
-// CHECK-RELOAD1a: -Wall
-// CHECK-RELOAD1a-NOT: -Werror
-// CHECK-RELOAD1a-NOT: -Wundefined-func-template
+// FULL5-NOT: Configuration file:
+// FULL5: Configuration file: {{.*}}/testdmode/clang-g++.cfg
+// FULL5-NOT: Configuration file:
 
-//--- x86_64-clang-g++ tries to find config i386.cfg if i386-clang-g++.cfg is not found.
+//--- FULL5 + -m32.
 //
-// RUN: rm %t/testreload/i386-clang-g++.cfg
-// RUN: %t/testreload/x86_64-clang-g++ --config-system-dir= --config-user-dir= -c -m32 -no-canonical-prefixes -### %s 2>&1 | FileCheck %s -check-prefix CHECK-RELOAD1d
+// RUN: %t/testdmode/x86_64-unknown-linux-gnu-clang-g++ -m32 --config-system-dir= --config-user-dir= -no-canonical-prefixes --version 2>&1 | FileCheck %s -check-prefix FULL5-I386
 //
-// CHECK-RELOAD1d: Configuration file: {{.*}}/testreload/i386.cfg
-// CHECK-RELOAD1d: -Werror
-// CHECK-RELOAD1d-NOT: -Wundefined-func-template
-// CHECK-RELOAD1d-NOT: -Wall
+// FULL5-I386-NOT: Configuration file:
+// FULL5-I386: Configuration file: {{.*}}/testdmode/clang-g++.cfg
+// FULL5-I386-NOT: Configuration file:
 
-//--- x86_64-clang-g++ uses x86_64-clang-g++.cfg if i386*.cfg are not found.
+//--- Test that incorrect driver mode config file is not used.
 //
-// RUN: rm %t/testreload/i386.cfg
-// RUN: %t/testreload/x86_64-clang-g++ --config-system-dir= --config-user-dir= -c -m32 -no-canonical-prefixes -### %s 2>&1 | FileCheck %s -check-prefix CHECK-RELOAD1a
+// RUN: rm %t/testdmode/clang-g++.cfg
+// RUN: %t/testdmode/x86_64-unknown-linux-gnu-clang-g++ --config-system-dir= --config-user-dir= -no-canonical-prefixes --version 2>&1 | FileCheck %s -check-prefix NO-CONFIG


        


More information about the cfe-commits mailing list