Index: clang/lib/Driver/Driver.cpp =================================================================== --- clang/lib/Driver/Driver.cpp +++ clang/lib/Driver/Driver.cpp @@ -1058,73 +1058,75 @@ bool Driver::loadDefaultConfigFiles(ArrayRef 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. + // from executable name. + + StringRef EffectiveDriverMode; + if (CLOptions) + EffectiveDriverMode = CLOptions->getLastArgValue(options::OPT_driver_mode); + if (EffectiveDriverMode.empty()) + EffectiveDriverMode = ClangNameParts.DriverMode; + + llvm::Triple EffectiveTriple = + computeTargetTriple(*this, TargetTriple, *CLOptions); + assert(!EffectiveTriple.str().empty()); + StringRef EffectiveModeSuffix = llvm::StringSwitch(EffectiveDriverMode) + .Case("g++", "clang++") + .Case("cpp", "clang-cpp") + .Case("cl", "clang-cl") + .Case("flang", "flang") + .Case("dxc", "clang-dxc") + .Default("clang"); + + // Start with the effective triple and driver mode since this should yield the most correct config for our invocation. 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 = EffectiveTriple.str() + '-' + EffectiveModeSuffix.str() + ".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"); + // If we can deduce prefix and suffix from the filename, try it next. + std::string FixedTargetPrefix; + if (!ClangNameParts.TargetPrefix.empty()) { + // Determine architecture part of the file name. If it is different + // from the effective target, replace the architecture in the filename + // prefix. + StringRef ArchPrefix, PostArchPart; + std::tie(ArchPrefix, PostArchPart) = llvm::StringRef(ClangNameParts.TargetPrefix).split('-'); + llvm::Triple ArchTriple{llvm::Triple::normalize(ArchPrefix)}; + if (ArchTriple.getArch() != llvm::Triple::ArchType::UnknownArch && ArchTriple.getArch() != EffectiveTriple.getArch()) { + FixedTargetPrefix = EffectiveTriple.getArchName().str() + '-' + PostArchPart.str(); + + // Try finding a config file with the corrected architecture, + // e.g. "x86_64-clang.cfg" -> "i386-clang.cfg". + CfgFileName = FixedTargetPrefix + '-' + ClangNameParts.ModeSuffix + + ".cfg"; + if (searchForFile(CfgFilePath, CfgFileSearchDirs, CfgFileName, getVFS())) + return readConfigFile(CfgFilePath); + } + + // Then try the original file name. + CfgFileName = ClangNameParts.TargetPrefix + '-' + ClangNameParts.ModeSuffix + + ".cfg"; + if (searchForFile(CfgFilePath, CfgFileSearchDirs, CfgFileName, getVFS())) + return readConfigFile(CfgFilePath); + } + + // If we haven't been successful with the full name, try finding separate configs for target and for driver, and loading both. + for (auto &Triple : {EffectiveTriple.str(), FixedTargetPrefix, ClangNameParts.TargetPrefix}) { + if (Triple.empty()) + continue; + CfgFileName = Triple + ".cfg"; + if (searchForFile(CfgFilePath, CfgFileSearchDirs, CfgFileName, getVFS())) { + if (readConfigFile(CfgFilePath)) + return true; + break; + } + } + for (auto &ModeName : {EffectiveModeSuffix.str(), ClangNameParts.ModeSuffix}) { + if (ModeName.empty()) + continue; + CfgFileName = ModeName + ".cfg"; if (searchForFile(CfgFilePath, CfgFileSearchDirs, CfgFileName, getVFS())) return readConfigFile(CfgFilePath); }