summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJustin Goshi <jgoshi@microsoft.com>2020-07-02 11:26:20 -0700
committerJustin Goshi <jgoshi@microsoft.com>2020-07-06 11:40:39 -0700
commit2f383d852d8d946a61419fe5f4b5c8501216dae9 (patch)
tree26423c46641812fa92f29c418f03cf47d2bbc5ca
parentcc96fb617b65ffa9db8dd3f242ee3b9319b4c4c4 (diff)
downloadcmake-2f383d852d8d946a61419fe5f4b5c8501216dae9.tar.gz
fileapi: Support multiple backtraces for language standard
-rw-r--r--Source/cmFileAPICodemodel.cxx69
-rw-r--r--Source/cmGeneratorTarget.cxx19
-rw-r--r--Source/cmGeneratorTarget.h4
-rw-r--r--Source/cmStandardLevelResolver.cxx6
-rw-r--r--Source/cmTarget.cxx15
-rw-r--r--Source/cmTarget.h2
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_standard_compile_feature_exe_languagestandard.json18
-rw-r--r--Tests/RunCMake/FileAPI/cxx/CMakeLists.txt1
8 files changed, 102 insertions, 32 deletions
diff --git a/Source/cmFileAPICodemodel.cxx b/Source/cmFileAPICodemodel.cxx
index ca1ed566da..e9af208a69 100644
--- a/Source/cmFileAPICodemodel.cxx
+++ b/Source/cmFileAPICodemodel.cxx
@@ -175,6 +175,38 @@ public:
}
};
+template <typename T>
+class JBTs
+{
+public:
+ JBTs(T v = T(), std::vector<JBTIndex> ids = std::vector<JBTIndex>())
+ : Value(std::move(v))
+ , Backtraces(std::move(ids))
+ {
+ }
+ T Value;
+ std::vector<JBTIndex> Backtraces;
+ friend bool operator==(JBTs<T> const& l, JBTs<T> const& r)
+ {
+ if ((l.Value == r.Value) && (l.Backtraces.size() == r.Backtraces.size())) {
+ for (size_t i = 0; i < l.Backtraces.size(); i++) {
+ if (l.Backtraces[i].Index != r.Backtraces[i].Index) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+ static bool ValueEq(JBTs<T> const& l, JBTs<T> const& r)
+ {
+ return l.Value == r.Value;
+ }
+ static bool ValueLess(JBTs<T> const& l, JBTs<T> const& r)
+ {
+ return l.Value < r.Value;
+ }
+};
+
class BacktraceData
{
std::string TopSource;
@@ -277,7 +309,7 @@ struct CompileData
std::string Language;
std::string Sysroot;
- JBT<std::string> LanguageStandard;
+ JBTs<std::string> LanguageStandard;
std::vector<JBT<std::string>> Flags;
std::vector<JBT<std::string>> Defines;
std::vector<JBT<std::string>> PrecompileHeaders;
@@ -323,8 +355,10 @@ struct hash<CompileData>
hash<Json::ArrayIndex>()(i.Backtrace.Index);
}
if (!in.LanguageStandard.Value.empty()) {
- result = result ^ hash<std::string>()(in.LanguageStandard.Value) ^
- hash<Json::ArrayIndex>()(in.LanguageStandard.Backtrace.Index);
+ result = result ^ hash<std::string>()(in.LanguageStandard.Value);
+ for (JBTIndex backtrace : in.LanguageStandard.Backtraces) {
+ result = result ^ hash<Json::ArrayIndex>()(backtrace.Index);
+ }
}
return result;
}
@@ -369,6 +403,16 @@ class Target
return JBT<T>(bt.Value, this->Backtraces.Add(bt.Backtrace));
}
+ template <typename T>
+ JBTs<T> ToJBTs(BTs<T> const& bts)
+ {
+ std::vector<JBTIndex> ids;
+ for (cmListFileBacktrace const& backtrace : bts.Backtraces) {
+ ids.emplace_back(this->Backtraces.Add(backtrace));
+ }
+ return JBTs<T>(bts.Value, ids);
+ }
+
void ProcessLanguages();
void ProcessLanguage(std::string const& lang);
@@ -383,7 +427,7 @@ class Target
Json::Value DumpCompileData(CompileData const& cd);
Json::Value DumpInclude(CompileData::IncludeEntry const& inc);
Json::Value DumpPrecompileHeader(JBT<std::string> const& header);
- Json::Value DumpLanguageStandard(JBT<std::string> const& standard);
+ Json::Value DumpLanguageStandard(JBTs<std::string> const& standard);
Json::Value DumpDefine(JBT<std::string> const& def);
Json::Value DumpSources();
Json::Value DumpSource(cmGeneratorTarget::SourceAndKind const& sk,
@@ -845,10 +889,10 @@ void Target::ProcessLanguage(std::string const& lang)
for (BT<std::string> const& pch : precompileHeaders) {
cd.PrecompileHeaders.emplace_back(this->ToJBT(pch));
}
- BT<std::string> const* languageStandard =
+ BTs<std::string> const* languageStandard =
this->GT->GetLanguageStandardProperty(lang, this->Config);
if (languageStandard) {
- cd.LanguageStandard = this->ToJBT(*languageStandard);
+ cd.LanguageStandard = this->ToJBTs(*languageStandard);
}
}
@@ -1195,18 +1239,15 @@ Json::Value Target::DumpPrecompileHeader(JBT<std::string> const& header)
return precompileHeader;
}
-Json::Value Target::DumpLanguageStandard(JBT<std::string> const& standard)
+Json::Value Target::DumpLanguageStandard(JBTs<std::string> const& standard)
{
Json::Value languageStandard = Json::objectValue;
languageStandard["standard"] = standard.Value;
- if (standard.Backtrace) {
- // Only one backtrace is currently stored for a given language standard,
- // but we represent this as an array because it's possible for multiple
- // compile features to set the same language standard value. Representing
- // this as an array will allow things to just work once we support storing
- // multiple backtraces for a language standard value.
+ if (!standard.Backtraces.empty()) {
Json::Value backtraces = Json::arrayValue;
- backtraces.append(standard.Backtrace.Index);
+ for (JBTIndex backtrace : standard.Backtraces) {
+ backtraces.append(backtrace.Index);
+ }
languageStandard["backtraces"] = backtraces;
}
return languageStandard;
diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx
index cc6f817ebf..ccd8e7e9bc 100644
--- a/Source/cmGeneratorTarget.cxx
+++ b/Source/cmGeneratorTarget.cxx
@@ -949,7 +949,7 @@ bool cmGeneratorTarget::HasExplicitObjectName(cmSourceFile const* file) const
return it != this->ExplicitObjectName.end();
}
-BT<std::string> const* cmGeneratorTarget::GetLanguageStandardProperty(
+BTs<std::string> const* cmGeneratorTarget::GetLanguageStandardProperty(
std::string const& lang, std::string const& config) const
{
std::string key = cmStrCat(cmSystemTools::UpperCase(config), '-', lang);
@@ -965,7 +965,7 @@ BT<std::string> const* cmGeneratorTarget::GetLanguageStandardProperty(
cmProp cmGeneratorTarget::GetLanguageStandard(std::string const& lang,
std::string const& config) const
{
- BT<std::string> const* languageStandard =
+ BTs<std::string> const* languageStandard =
this->GetLanguageStandardProperty(lang, config);
if (languageStandard) {
@@ -4486,8 +4486,13 @@ bool cmGeneratorTarget::ComputeCompileFeatures(std::string const& config) const
}
if (!newRequiredStandard.empty()) {
- this->LanguageStandardMap[key] =
- BT<std::string>(newRequiredStandard, f.Backtrace);
+ BTs<std::string>& languageStandardProperty =
+ this->LanguageStandardMap[key];
+ if (languageStandardProperty.Value != newRequiredStandard) {
+ languageStandardProperty.Value = newRequiredStandard;
+ languageStandardProperty.Backtraces.clear();
+ }
+ languageStandardProperty.Backtraces.emplace_back(f.Backtrace);
}
}
@@ -4498,14 +4503,14 @@ bool cmGeneratorTarget::ComputeCompileFeatures(
std::string const& config, std::set<LanguagePair> const& languagePairs) const
{
for (const auto& language : languagePairs) {
- BT<std::string> const* generatorTargetLanguageStandard =
+ BTs<std::string> const* generatorTargetLanguageStandard =
this->GetLanguageStandardProperty(language.first, config);
if (!generatorTargetLanguageStandard) {
// If the standard isn't explicitly set we copy it over from the
// specified paired language.
std::string key =
cmStrCat(cmSystemTools::UpperCase(config), '-', language.first);
- BT<std::string> const* standardToCopy =
+ BTs<std::string> const* standardToCopy =
this->GetLanguageStandardProperty(language.second, config);
if (standardToCopy != nullptr) {
this->LanguageStandardMap[key] = *standardToCopy;
@@ -4514,7 +4519,7 @@ bool cmGeneratorTarget::ComputeCompileFeatures(
cmProp defaultStandard = this->Makefile->GetDef(
cmStrCat("CMAKE_", language.second, "_STANDARD_DEFAULT"));
if (defaultStandard != nullptr) {
- this->LanguageStandardMap[key] = BT<std::string>(*defaultStandard);
+ this->LanguageStandardMap[key] = BTs<std::string>(*defaultStandard);
generatorTargetLanguageStandard = &this->LanguageStandardMap[key];
}
}
diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h
index 20f3a079dc..07f071b5b1 100644
--- a/Source/cmGeneratorTarget.h
+++ b/Source/cmGeneratorTarget.h
@@ -148,7 +148,7 @@ public:
bool HasExplicitObjectName(cmSourceFile const* file) const;
void AddExplicitObjectName(cmSourceFile const* sf);
- BT<std::string> const* GetLanguageStandardProperty(
+ BTs<std::string> const* GetLanguageStandardProperty(
std::string const& lang, std::string const& config) const;
cmProp GetLanguageStandard(std::string const& lang,
@@ -1053,7 +1053,7 @@ private:
bool GetRPATH(const std::string& config, const std::string& prop,
std::string& rpath) const;
- mutable std::map<std::string, BT<std::string>> LanguageStandardMap;
+ mutable std::map<std::string, BTs<std::string>> LanguageStandardMap;
cmProp GetPropertyWithPairedLanguageSupport(std::string const& lang,
const char* suffix) const;
diff --git a/Source/cmStandardLevelResolver.cxx b/Source/cmStandardLevelResolver.cxx
index 3592b113e0..5e306802a2 100644
--- a/Source/cmStandardLevelResolver.cxx
+++ b/Source/cmStandardLevelResolver.cxx
@@ -58,7 +58,11 @@ struct StanardLevelComputer
std::string& newRequiredStandard,
std::string* error) const
{
- newRequiredStandard.clear();
+ if (currentLangStandardValue) {
+ newRequiredStandard = *currentLangStandardValue;
+ } else {
+ newRequiredStandard.clear();
+ }
auto needed = this->HighestStandardNeeded(makefile, feature);
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index 72c7600baf..a4f9083cf3 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -186,7 +186,7 @@ public:
std::vector<cmInstallTargetGenerator*> InstallGenerators;
std::set<std::string> SystemIncludeDirectories;
cmTarget::LinkLibraryVectorType OriginalLinkLibraries;
- std::map<std::string, BT<std::string>> LanguageStandardProperties;
+ std::map<std::string, BTs<std::string>> LanguageStandardProperties;
std::vector<std::string> IncludeDirectoriesEntries;
std::vector<cmListFileBacktrace> IncludeDirectoriesBacktraces;
std::vector<std::string> CompileOptionsEntries;
@@ -600,7 +600,7 @@ cmGlobalGenerator* cmTarget::GetGlobalGenerator() const
return impl->Makefile->GetGlobalGenerator();
}
-BT<std::string> const* cmTarget::GetLanguageStandardProperty(
+BTs<std::string> const* cmTarget::GetLanguageStandardProperty(
const std::string& propertyName) const
{
auto entry = impl->LanguageStandardProperties.find(propertyName);
@@ -625,8 +625,13 @@ void cmTarget::SetLanguageStandardProperty(std::string const& lang,
}
}
- impl->LanguageStandardProperties[cmStrCat(lang, "_STANDARD")] =
- BT<std::string>(value, featureBacktrace);
+ BTs<std::string>& languageStandardProperty =
+ impl->LanguageStandardProperties[cmStrCat(lang, "_STANDARD")];
+ if (languageStandardProperty.Value != value) {
+ languageStandardProperty.Value = value;
+ languageStandardProperty.Backtraces.clear();
+ }
+ languageStandardProperty.Backtraces.emplace_back(featureBacktrace);
}
void cmTarget::AddUtility(std::string const& name, bool cross, cmMakefile* mf)
@@ -1357,7 +1362,7 @@ void cmTarget::SetProperty(const std::string& prop, const char* value)
prop == propOBJCXX_STANDARD) {
if (value) {
impl->LanguageStandardProperties[prop] =
- BT<std::string>(value, impl->Makefile->GetBacktrace());
+ BTs<std::string>(value, impl->Makefile->GetBacktrace());
} else {
impl->LanguageStandardProperties.erase(prop);
}
diff --git a/Source/cmTarget.h b/Source/cmTarget.h
index b3d6fe0dde..7a16de8962 100644
--- a/Source/cmTarget.h
+++ b/Source/cmTarget.h
@@ -236,7 +236,7 @@ public:
void AddSystemIncludeDirectories(std::set<std::string> const& incs);
std::set<std::string> const& GetSystemIncludeDirectories() const;
- BT<std::string> const* GetLanguageStandardProperty(
+ BTs<std::string> const* GetLanguageStandardProperty(
const std::string& propertyName) const;
void SetLanguageStandardProperty(std::string const& lang,
diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_standard_compile_feature_exe_languagestandard.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_standard_compile_feature_exe_languagestandard.json
index 57b4161e65..0c4eabb09c 100644
--- a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_standard_compile_feature_exe_languagestandard.json
+++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_standard_compile_feature_exe_languagestandard.json
@@ -15,8 +15,22 @@
"command": null,
"hasParent": false
}
+ ],
+ [
+ {
+ "file": "^cxx/CMakeLists\\.txt$",
+ "line": 30,
+ "command": "target_compile_features",
+ "hasParent": true
+ },
+ {
+ "file": "^cxx/CMakeLists\\.txt$",
+ "line": null,
+ "command": null,
+ "hasParent": false
+ }
]
- ],
- "standard" : "11"
+ ],
+ "standard" : "11"
}
}
diff --git a/Tests/RunCMake/FileAPI/cxx/CMakeLists.txt b/Tests/RunCMake/FileAPI/cxx/CMakeLists.txt
index 5758cc49be..76235f5c5a 100644
--- a/Tests/RunCMake/FileAPI/cxx/CMakeLists.txt
+++ b/Tests/RunCMake/FileAPI/cxx/CMakeLists.txt
@@ -27,5 +27,6 @@ add_executable(cxx_standard_compile_feature_exe ../empty.cxx)
set_property(TARGET cxx_standard_compile_feature_exe PROPERTY CXX_STANDARD 98)
if(CMAKE_CXX_STANDARD_DEFAULT AND DEFINED CMAKE_CXX11_STANDARD_COMPILE_OPTION)
target_compile_features(cxx_standard_compile_feature_exe PRIVATE cxx_std_11)
+ target_compile_features(cxx_standard_compile_feature_exe PRIVATE cxx_decltype)
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/cxx_std_11.txt" "")
endif()