cmStandardLevelResolver: add query for the effective standard level

This allows for improved error messages.
This commit is contained in:
Ben Boeckel 2023-08-23 16:12:35 -04:00
parent 17ddc4ac76
commit 8b4d32c18b
2 changed files with 116 additions and 0 deletions

View File

@ -73,6 +73,8 @@ struct StandardLevelComputer
assert(this->Levels.size() == this->LevelsAsStrings.size());
}
// Note that the logic here is shadowed in `GetEffectiveStandard`; if one is
// changed, the other needs changed as well.
std::string GetCompileOptionDef(cmMakefile* makefile,
cmGeneratorTarget const* target,
std::string const& config) const
@ -238,6 +240,105 @@ struct StandardLevelComputer
return std::string{};
}
std::string GetEffectiveStandard(cmMakefile* makefile,
cmGeneratorTarget const* target,
std::string const& config) const
{
const auto& stds = this->Levels;
const auto& stdsStrings = this->LevelsAsStrings;
cmValue defaultStd = makefile->GetDefinition(
cmStrCat("CMAKE_", this->Language, "_STANDARD_DEFAULT"));
if (!cmNonempty(defaultStd)) {
// this compiler has no notion of language standard levels
return std::string{};
}
cmPolicies::PolicyStatus const cmp0128{ makefile->GetPolicyStatus(
cmPolicies::CMP0128) };
bool const defaultExt{ cmIsOn(*makefile->GetDefinition(
cmStrCat("CMAKE_", this->Language, "_EXTENSIONS_DEFAULT"))) };
bool ext = true;
if (cmp0128 == cmPolicies::NEW) {
ext = defaultExt;
}
if (cmValue extPropValue = target->GetLanguageExtensions(this->Language)) {
ext = cmIsOn(*extPropValue);
}
std::string const type{ ext ? "EXTENSION" : "STANDARD" };
cmValue standardProp = target->GetLanguageStandard(this->Language, config);
if (!standardProp) {
if (cmp0128 == cmPolicies::NEW) {
// Add extension flag if compiler's default doesn't match.
if (ext != defaultExt) {
return *defaultStd;
}
} else {
if (ext) {
return *defaultStd;
}
}
return std::string{};
}
if (target->GetLanguageStandardRequired(this->Language)) {
return *standardProp;
}
// If the request matches the compiler's defaults we don't need to add
// anything.
if (*standardProp == *defaultStd && ext == defaultExt) {
if (cmp0128 == cmPolicies::NEW) {
return std::string{};
}
}
std::string standardStr(*standardProp);
if (this->Language == "CUDA"_s && standardStr == "98"_s) {
standardStr = "03";
}
auto stdIt =
std::find(cm::cbegin(stds), cm::cend(stds), ParseStd(standardStr));
if (stdIt == cm::cend(stds)) {
return std::string{};
}
auto defaultStdIt =
std::find(cm::cbegin(stds), cm::cend(stds), ParseStd(*defaultStd));
if (defaultStdIt == cm::cend(stds)) {
return std::string{};
}
// If the standard requested is older than the compiler's default or the
// extension mode doesn't match then we need to use a flag.
if ((cmp0128 != cmPolicies::NEW && stdIt <= defaultStdIt) ||
(cmp0128 == cmPolicies::NEW &&
(stdIt < defaultStdIt || ext != defaultExt))) {
auto offset = std::distance(cm::cbegin(stds), stdIt);
return stdsStrings[offset];
}
// The compiler's default is at least as new as the requested standard,
// and the requested standard is not required. Decay to the newest
// standard for which a flag is defined.
for (; defaultStdIt < stdIt; --stdIt) {
auto offset = std::distance(cm::cbegin(stds), stdIt);
std::string option_flag =
cmStrCat("CMAKE_", this->Language, stdsStrings[offset], '_', type,
"_COMPILE_OPTION");
if (target->Target->GetMakefile()->GetDefinition(option_flag)) {
return stdsStrings[offset];
}
}
return std::string{};
}
bool GetNewRequiredStandard(cmMakefile* makefile,
std::string const& targetName,
const std::string& feature,
@ -420,6 +521,18 @@ std::string cmStandardLevelResolver::GetCompileOptionDef(
return mapping->second.GetCompileOptionDef(this->Makefile, target, config);
}
std::string cmStandardLevelResolver::GetEffectiveStandard(
cmGeneratorTarget const* target, std::string const& lang,
std::string const& config) const
{
const auto& mapping = StandardComputerMapping.find(lang);
if (mapping == cm::cend(StandardComputerMapping)) {
return std::string{};
}
return mapping->second.GetEffectiveStandard(this->Makefile, target, config);
}
bool cmStandardLevelResolver::AddRequiredTargetFeature(
cmTarget* target, const std::string& feature, std::string* error) const
{

View File

@ -22,6 +22,9 @@ public:
std::string GetCompileOptionDef(cmGeneratorTarget const* target,
std::string const& lang,
std::string const& config) const;
std::string GetEffectiveStandard(cmGeneratorTarget const* target,
std::string const& lang,
std::string const& config) const;
bool AddRequiredTargetFeature(cmTarget* target, const std::string& feature,
std::string* error = nullptr) const;