From 4bbe261cd34818379d06b68d2e153a98cfccfcf5 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Mon, 8 Jun 2015 20:04:24 +0200 Subject: [PATCH 1/6] cmMakefile: Extract InitializeVarScope method. --- Source/cmMakefile.cxx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index 85bc493d2..5b2499ba3 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -55,6 +55,11 @@ public: this->VarStack.push_back(cmDefinitions()); } + void InitializeVarScope() + { + this->PushDefinitions(); + } + void InitializeDefinitions(cmMakefile* parent) { this->VarStack.back() = @@ -141,7 +146,7 @@ cmMakefile::cmMakefile(cmLocalGenerator* localGenerator) LocalGenerator(localGenerator), StateSnapshot(localGenerator->GetStateSnapshot()) { - this->Internal->PushDefinitions(); + this->Internal->InitializeVarScope(); this->Internal->IsSourceFileTryCompile = false; // Initialize these first since AddDefaultDefinitions calls AddDefinition From 25e04ddffeba6d4b1c9deab1ea42038c322cec83 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Sat, 30 May 2015 17:08:34 +0200 Subject: [PATCH 2/6] cmDefinitions: Implement in terms of cmLinkedTree. Store the definitions in a cmLinkedTree in the cmMakefile. This can be moved to cmState and then the tree will provide snapshotting possibilities. It will also make the Closure copy created at the start of each cmMakefile unnecesarry. --- Source/cmDefinitions.cxx | 14 +++++++------- Source/cmDefinitions.h | 17 ++++++++++------- Source/cmMakefile.cxx | 41 +++++++++++++++++++++------------------- 3 files changed, 39 insertions(+), 33 deletions(-) diff --git a/Source/cmDefinitions.cxx b/Source/cmDefinitions.cxx index 2dab169ef..b06fb5c0b 100644 --- a/Source/cmDefinitions.cxx +++ b/Source/cmDefinitions.cxx @@ -56,9 +56,9 @@ void cmDefinitions::Raise(const std::string& key, } bool cmDefinitions::HasKey(const std::string& key, - StackConstIter begin, StackConstIter end) + StackIter begin, StackIter end) { - for (StackConstIter it = begin; it != end; ++it) + for (StackIter it = begin; it != end; ++it) { MapType::const_iterator i = it->Map.find(key); if (i != it->Map.end()) @@ -94,12 +94,12 @@ std::vector cmDefinitions::UnusedKeys() const } //---------------------------------------------------------------------------- -cmDefinitions cmDefinitions::MakeClosure(StackConstIter begin, - StackConstIter end) +cmDefinitions cmDefinitions::MakeClosure(StackIter begin, + StackIter end) { cmDefinitions closure; std::set undefined; - for (StackConstIter it = begin; it != end; ++it) + for (StackIter it = begin; it != end; ++it) { // Consider local definitions. for(MapType::const_iterator mi = it->Map.begin(); @@ -125,12 +125,12 @@ cmDefinitions cmDefinitions::MakeClosure(StackConstIter begin, //---------------------------------------------------------------------------- std::vector -cmDefinitions::ClosureKeys(StackConstIter begin, StackConstIter end) +cmDefinitions::ClosureKeys(StackIter begin, StackIter end) { std::set bound; std::vector defined; - for (StackConstIter it = begin; it != end; ++it) + for (StackIter it = begin; it != end; ++it) { defined.reserve(defined.size() + it->Map.size()); for(MapType::const_iterator mi = it->Map.begin(); diff --git a/Source/cmDefinitions.h b/Source/cmDefinitions.h index 5fdcaab72..411867c52 100644 --- a/Source/cmDefinitions.h +++ b/Source/cmDefinitions.h @@ -13,6 +13,9 @@ #define cmDefinitions_h #include "cmStandardIncludes.h" + +#include "cmLinkedTree.h" + #if defined(CMAKE_BUILD_WITH_CMAKE) #ifdef CMake_HAVE_CXX11_UNORDERED_MAP #include @@ -32,26 +35,26 @@ */ class cmDefinitions { - typedef std::list::reverse_iterator StackIter; - typedef std::list::const_reverse_iterator StackConstIter; + typedef cmLinkedTree::iterator StackIter; public: static const char* Get(const std::string& key, StackIter begin, StackIter end); - static void Raise(const std::string& key, StackIter begin, StackIter end); + static void Raise(const std::string& key, + StackIter begin, StackIter end); static bool HasKey(const std::string& key, - StackConstIter begin, StackConstIter end); + StackIter begin, StackIter end); /** Set (or unset if null) a value associated with a key. */ void Set(const std::string& key, const char* value); std::vector UnusedKeys() const; - static std::vector ClosureKeys(StackConstIter begin, - StackConstIter end); + static std::vector ClosureKeys(StackIter begin, + StackIter end); - static cmDefinitions MakeClosure(StackConstIter begin, StackConstIter end); + static cmDefinitions MakeClosure(StackIter begin, StackIter end); private: // String with existence boolean. diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index 5b2499ba3..afb016640 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -47,70 +47,73 @@ class cmMakefile::Internals { public: - std::list VarStack; + cmLinkedTree VarTree; + cmLinkedTree::iterator VarTreeIter; bool IsSourceFileTryCompile; void PushDefinitions() { - this->VarStack.push_back(cmDefinitions()); + assert(this->VarTreeIter.IsValid()); + this->VarTreeIter = this->VarTree.Extend(this->VarTreeIter); } void InitializeVarScope() { + this->VarTreeIter = this->VarTree.Root(); this->PushDefinitions(); } void InitializeDefinitions(cmMakefile* parent) { - this->VarStack.back() = - cmDefinitions::MakeClosure(parent->Internal->VarStack.rbegin(), - parent->Internal->VarStack.rend()); + *this->VarTreeIter = + cmDefinitions::MakeClosure(parent->Internal->VarTreeIter, + parent->Internal->VarTree.Root()); } const char* GetDefinition(std::string const& name) { - return cmDefinitions::Get(name, this->VarStack.rbegin(), - this->VarStack.rend()); + assert(this->VarTreeIter != this->VarTree.Root()); + return cmDefinitions::Get(name, + this->VarTreeIter, this->VarTree.Root()); } bool IsInitialized(std::string const& name) { - return cmDefinitions::HasKey(name, this->VarStack.rbegin(), - this->VarStack.rend()); + return cmDefinitions::HasKey(name, + this->VarTreeIter, this->VarTree.Root()); } void SetDefinition(std::string const& name, std::string const& value) { - this->VarStack.back().Set(name, value.c_str()); + this->VarTreeIter->Set(name, value.c_str()); } void RemoveDefinition(std::string const& name) { - this->VarStack.back().Set(name, 0); + this->VarTreeIter->Set(name, 0); } std::vector UnusedKeys() const { - return this->VarStack.back().UnusedKeys(); + return this->VarTreeIter->UnusedKeys(); } std::vector ClosureKeys() const { - return cmDefinitions::ClosureKeys(this->VarStack.rbegin(), - this->VarStack.rend()); + return cmDefinitions::ClosureKeys(this->VarTreeIter, this->VarTree.Root()); } void PopDefinitions() { - this->VarStack.pop_back(); + ++this->VarTreeIter; } bool RaiseScope(std::string const& var, const char* varDef, cmMakefile* mf) { - std::list::reverse_iterator it = this->VarStack.rbegin(); - assert(it != this->VarStack.rend()); + cmLinkedTree::iterator it = this->VarTreeIter; + assert(it != this->VarTree.Root()); ++it; - if(it == this->VarStack.rend()) + if(it == this->VarTree.Root()) { cmLocalGenerator* plg = mf->LocalGenerator->GetParent(); if(!plg) @@ -132,7 +135,7 @@ public: return true; } // First localize the definition in the current scope. - cmDefinitions::Raise(var, this->VarStack.rbegin(), this->VarStack.rend()); + cmDefinitions::Raise(var, this->VarTreeIter, this->VarTree.Root()); // Now update the definition in the parent scope. it->Set(var, varDef); From 0f070dd3e12408e0e33945c3c8f585268c4b0db9 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Sun, 31 May 2015 11:26:05 +0200 Subject: [PATCH 3/6] cmMakefile: Decouple the container of cmDefinitions from scoping logic. Maintain a Parent tree node for writing to in RaiseScope. --- Source/cmMakefile.cxx | 80 ++++++++++++++++++++++++++++++------------- 1 file changed, 56 insertions(+), 24 deletions(-) diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index afb016640..aef016e60 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -47,73 +47,105 @@ class cmMakefile::Internals { public: + + enum ScopeType + { + BaseScope, + MacroScope, + FunctionScope, + VariableScope + }; + + struct VarScope + { + ScopeType Type; + cmLinkedTree::iterator Vars; + cmLinkedTree::iterator ParentScope; + }; + cmLinkedTree VarTree; - cmLinkedTree::iterator VarTreeIter; + cmLinkedTree VarScopes; + cmLinkedTree::iterator VarScopeIter; bool IsSourceFileTryCompile; - void PushDefinitions() + void PushDefinitions(ScopeType scope) { - assert(this->VarTreeIter.IsValid()); - this->VarTreeIter = this->VarTree.Extend(this->VarTreeIter); + assert(this->VarScopeIter.IsValid()); + assert(this->VarScopeIter->Vars.IsValid()); + cmLinkedTree::iterator origin = + this->VarScopeIter->Vars; + cmLinkedTree::iterator parentScope = +// this->VarTree.Extend(origin); + origin; + this->VarScopeIter->Vars = parentScope; + this->VarScopeIter = this->VarScopes.Extend(this->VarScopeIter); + this->VarScopeIter->ParentScope = parentScope; + this->VarScopeIter->Vars = this->VarTree.Extend(origin); + this->VarScopeIter->Type = scope; } void InitializeVarScope() { - this->VarTreeIter = this->VarTree.Root(); - this->PushDefinitions(); + assert(!this->VarScopeIter.IsValid()); + this->VarScopeIter = this->VarScopes.Extend(this->VarScopes.Root()); + this->VarScopeIter->Vars = this->VarTree.Extend(this->VarTree.Root()); + this->VarScopeIter->ParentScope = this->VarTree.Root(); + this->VarScopeIter->Type = BaseScope; } void InitializeDefinitions(cmMakefile* parent) { - *this->VarTreeIter = - cmDefinitions::MakeClosure(parent->Internal->VarTreeIter, + assert(this->VarScopeIter.IsValid()); + assert(this->VarScopeIter->Vars.IsValid()); + *this->VarScopeIter->Vars = + cmDefinitions::MakeClosure(parent->Internal->VarScopeIter->Vars, parent->Internal->VarTree.Root()); } const char* GetDefinition(std::string const& name) { - assert(this->VarTreeIter != this->VarTree.Root()); + assert(this->VarScopeIter.IsValid()); + assert(this->VarScopeIter->Vars.IsValid()); return cmDefinitions::Get(name, - this->VarTreeIter, this->VarTree.Root()); + this->VarScopeIter->Vars, this->VarTree.Root()); } bool IsInitialized(std::string const& name) { return cmDefinitions::HasKey(name, - this->VarTreeIter, this->VarTree.Root()); + this->VarScopeIter->Vars, this->VarTree.Root()); } void SetDefinition(std::string const& name, std::string const& value) { - this->VarTreeIter->Set(name, value.c_str()); + this->VarScopeIter->Vars->Set(name, value.c_str()); } void RemoveDefinition(std::string const& name) { - this->VarTreeIter->Set(name, 0); + this->VarScopeIter->Vars->Set(name, 0); } std::vector UnusedKeys() const { - return this->VarTreeIter->UnusedKeys(); + return this->VarScopeIter->Vars->UnusedKeys(); } std::vector ClosureKeys() const { - return cmDefinitions::ClosureKeys(this->VarTreeIter, this->VarTree.Root()); + return cmDefinitions::ClosureKeys(this->VarScopeIter->Vars, + this->VarTree.Root()); } void PopDefinitions() { - ++this->VarTreeIter; + ++this->VarScopeIter; } bool RaiseScope(std::string const& var, const char* varDef, cmMakefile* mf) { - cmLinkedTree::iterator it = this->VarTreeIter; - assert(it != this->VarTree.Root()); - ++it; - if(it == this->VarTree.Root()) + assert(this->VarScopeIter->Vars != this->VarTree.Root()); + if(this->VarScopeIter->ParentScope == this->VarTree.Root()) { cmLocalGenerator* plg = mf->LocalGenerator->GetParent(); if(!plg) @@ -135,10 +167,10 @@ public: return true; } // First localize the definition in the current scope. - cmDefinitions::Raise(var, this->VarTreeIter, this->VarTree.Root()); + cmDefinitions::Raise(var, this->VarScopeIter->Vars, this->VarTree.Root()); // Now update the definition in the parent scope. - it->Set(var, varDef); + this->VarScopeIter->ParentScope->Set(var, varDef); return true; } }; @@ -1642,7 +1674,7 @@ void cmMakefile::PushFunctionScope(std::string const& fileName, fileName); assert(this->StateSnapshot.IsValid()); - this->Internal->PushDefinitions(); + this->Internal->PushDefinitions(Internals::FunctionScope); this->PushLoopBlockBarrier(); @@ -4430,7 +4462,7 @@ std::string cmMakefile::FormatListFileStack() const void cmMakefile::PushScope() { - this->Internal->PushDefinitions(); + this->Internal->PushDefinitions(Internals::VariableScope); this->PushLoopBlockBarrier(); From 1fc645bd9cffb3170743de5c983f2407eeaaa086 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Sat, 1 Aug 2015 19:44:47 +0200 Subject: [PATCH 4/6] cmState: Add a Base snapshot type. For completeness mostly. --- Source/cmState.cxx | 5 +++-- Source/cmState.h | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Source/cmState.cxx b/Source/cmState.cxx index f42586114..c777514d6 100644 --- a/Source/cmState.cxx +++ b/Source/cmState.cxx @@ -736,7 +736,7 @@ cmState::Snapshot cmState::CreateBaseSnapshot() { PositionType pos = this->SnapshotData.Extend(this->SnapshotData.Root()); pos->DirectoryParent = this->SnapshotData.Root(); - pos->SnapshotType = BuildsystemDirectoryType; + pos->SnapshotType = BaseType; pos->BuildSystemDirectory = this->BuildsystemDirectory.Extend(this->BuildsystemDirectory.Root()); pos->ExecutionListFile = @@ -1019,7 +1019,8 @@ cmState::Snapshot cmState::Snapshot::GetCallStackParent() const { ++parentPos; } - if (parentPos->SnapshotType == cmState::BuildsystemDirectoryType) + if (parentPos->SnapshotType == cmState::BuildsystemDirectoryType + || parentPos->SnapshotType == cmState::BaseType) { return snapshot; } diff --git a/Source/cmState.h b/Source/cmState.h index 07aa2a55b..bc89cc83c 100644 --- a/Source/cmState.h +++ b/Source/cmState.h @@ -35,6 +35,7 @@ public: enum SnapshotType { + BaseType, BuildsystemDirectoryType, FunctionCallType, MacroCallType, From 6954c8936f52dcf7710e4b72b2e090b79bf38d1c Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Sat, 1 Aug 2015 19:41:26 +0200 Subject: [PATCH 5/6] cmState: Add a VariableScope snapshot type. Match the scopes currently used in cmMakefile for definitions. --- Source/cmMakefile.cxx | 14 ++++++++++++++ Source/cmState.cxx | 19 +++++++++++++++++++ Source/cmState.h | 6 +++++- 3 files changed, 38 insertions(+), 1 deletion(-) diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index aef016e60..1d02cfaf6 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -4464,6 +4464,17 @@ void cmMakefile::PushScope() { this->Internal->PushDefinitions(Internals::VariableScope); + std::string commandName; + long line = 0; + if (!this->ContextStack.empty()) + { + commandName = this->ContextStack.back()->Name; + line = this->ContextStack.back()->Line; + } + this->StateSnapshot = this->GetState()->CreateVariableScopeSnapshot( + this->StateSnapshot, + commandName, + line); this->PushLoopBlockBarrier(); #if defined(CMAKE_BUILD_WITH_CMAKE) @@ -4482,6 +4493,9 @@ void cmMakefile::PopScope() this->CheckForUnusedVariables(); this->Internal->PopDefinitions(); + this->StateSnapshot = + this->GetState()->Pop(this->StateSnapshot); + assert(this->StateSnapshot.IsValid()); } void cmMakefile::RaiseScope(const std::string& var, const char *varDef) diff --git a/Source/cmState.cxx b/Source/cmState.cxx index c777514d6..9e09353b0 100644 --- a/Source/cmState.cxx +++ b/Source/cmState.cxx @@ -20,6 +20,7 @@ struct cmState::SnapshotDataType { + cmState::PositionType ScopeParent; cmState::PositionType DirectoryParent; cmLinkedTree::iterator Policies; cmLinkedTree::iterator PolicyRoot; @@ -736,6 +737,7 @@ cmState::Snapshot cmState::CreateBaseSnapshot() { PositionType pos = this->SnapshotData.Extend(this->SnapshotData.Root()); pos->DirectoryParent = this->SnapshotData.Root(); + pos->ScopeParent = this->SnapshotData.Root(); pos->SnapshotType = BaseType; pos->BuildSystemDirectory = this->BuildsystemDirectory.Extend(this->BuildsystemDirectory.Root()); @@ -763,6 +765,7 @@ cmState::CreateBuildsystemDirectorySnapshot(Snapshot originSnapshot, pos->EntryPointLine = entryPointLine; pos->EntryPointCommand = entryPointCommand; pos->DirectoryParent = originSnapshot.Position; + pos->ScopeParent = originSnapshot.Position; pos->SnapshotType = BuildsystemDirectoryType; pos->BuildSystemDirectory = this->BuildsystemDirectory.Extend( @@ -787,6 +790,7 @@ cmState::CreateFunctionCallSnapshot(cmState::Snapshot originSnapshot, { PositionType pos = this->SnapshotData.Extend(originSnapshot.Position, *originSnapshot.Position); + pos->ScopeParent = originSnapshot.Position; pos->EntryPointLine = entryPointLine; pos->EntryPointCommand = entryPointCommand; pos->SnapshotType = FunctionCallType; @@ -834,6 +838,21 @@ cmState::CreateCallStackSnapshot(cmState::Snapshot originSnapshot, return cmState::Snapshot(this, pos); } +cmState::Snapshot +cmState::CreateVariableScopeSnapshot(cmState::Snapshot originSnapshot, + std::string const& entryPointCommand, + long entryPointLine) +{ + PositionType pos = this->SnapshotData.Extend(originSnapshot.Position, + *originSnapshot.Position); + pos->ScopeParent = originSnapshot.Position; + pos->EntryPointLine = entryPointLine; + pos->EntryPointCommand = entryPointCommand; + pos->SnapshotType = VariableScopeType; + + return cmState::Snapshot(this, pos); +} + cmState::Snapshot cmState::CreateInlineListFileSnapshot(cmState::Snapshot originSnapshot, const std::string& entryPointCommand, diff --git a/Source/cmState.h b/Source/cmState.h index bc89cc83c..4d87653bb 100644 --- a/Source/cmState.h +++ b/Source/cmState.h @@ -41,7 +41,8 @@ public: MacroCallType, CallStackType, InlineListFileType, - PolicyScopeType + PolicyScopeType, + VariableScopeType }; class Directory; @@ -155,6 +156,9 @@ public: std::string const& entryPointCommand, long entryPointLine, std::string const& fileName); + Snapshot CreateVariableScopeSnapshot(Snapshot originSnapshot, + std::string const& entryPointCommand, + long entryPointLine); Snapshot CreateInlineListFileSnapshot(Snapshot originSnapshot, const std::string& entryPointCommand, long entryPointLine, From bff27391a91d1410ef33187c0c35acc0a709720d Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Sun, 21 Jun 2015 21:26:43 +0200 Subject: [PATCH 6/6] cmState: Host variable definitions. --- Source/cmMakefile.cxx | 161 ++++-------------------------------------- Source/cmState.cxx | 102 ++++++++++++++++++++++++++ Source/cmState.h | 11 +++ 3 files changed, 126 insertions(+), 148 deletions(-) diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index 1d02cfaf6..513a643da 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -31,7 +31,6 @@ #endif #include "cmInstallGenerator.h" #include "cmTestGenerator.h" -#include "cmDefinitions.h" #include "cmAlgorithms.h" #include "cmake.h" #include // required for atoi @@ -47,132 +46,7 @@ class cmMakefile::Internals { public: - - enum ScopeType - { - BaseScope, - MacroScope, - FunctionScope, - VariableScope - }; - - struct VarScope - { - ScopeType Type; - cmLinkedTree::iterator Vars; - cmLinkedTree::iterator ParentScope; - }; - - cmLinkedTree VarTree; - cmLinkedTree VarScopes; - cmLinkedTree::iterator VarScopeIter; bool IsSourceFileTryCompile; - - void PushDefinitions(ScopeType scope) - { - assert(this->VarScopeIter.IsValid()); - assert(this->VarScopeIter->Vars.IsValid()); - cmLinkedTree::iterator origin = - this->VarScopeIter->Vars; - cmLinkedTree::iterator parentScope = -// this->VarTree.Extend(origin); - origin; - this->VarScopeIter->Vars = parentScope; - this->VarScopeIter = this->VarScopes.Extend(this->VarScopeIter); - this->VarScopeIter->ParentScope = parentScope; - this->VarScopeIter->Vars = this->VarTree.Extend(origin); - this->VarScopeIter->Type = scope; - } - - void InitializeVarScope() - { - assert(!this->VarScopeIter.IsValid()); - this->VarScopeIter = this->VarScopes.Extend(this->VarScopes.Root()); - this->VarScopeIter->Vars = this->VarTree.Extend(this->VarTree.Root()); - this->VarScopeIter->ParentScope = this->VarTree.Root(); - this->VarScopeIter->Type = BaseScope; - } - - void InitializeDefinitions(cmMakefile* parent) - { - assert(this->VarScopeIter.IsValid()); - assert(this->VarScopeIter->Vars.IsValid()); - *this->VarScopeIter->Vars = - cmDefinitions::MakeClosure(parent->Internal->VarScopeIter->Vars, - parent->Internal->VarTree.Root()); - } - - const char* GetDefinition(std::string const& name) - { - assert(this->VarScopeIter.IsValid()); - assert(this->VarScopeIter->Vars.IsValid()); - return cmDefinitions::Get(name, - this->VarScopeIter->Vars, this->VarTree.Root()); - } - - bool IsInitialized(std::string const& name) - { - return cmDefinitions::HasKey(name, - this->VarScopeIter->Vars, this->VarTree.Root()); - } - - void SetDefinition(std::string const& name, std::string const& value) - { - this->VarScopeIter->Vars->Set(name, value.c_str()); - } - - void RemoveDefinition(std::string const& name) - { - this->VarScopeIter->Vars->Set(name, 0); - } - - std::vector UnusedKeys() const - { - return this->VarScopeIter->Vars->UnusedKeys(); - } - - std::vector ClosureKeys() const - { - return cmDefinitions::ClosureKeys(this->VarScopeIter->Vars, - this->VarTree.Root()); - } - - void PopDefinitions() - { - ++this->VarScopeIter; - } - - bool RaiseScope(std::string const& var, const char* varDef, cmMakefile* mf) - { - assert(this->VarScopeIter->Vars != this->VarTree.Root()); - if(this->VarScopeIter->ParentScope == this->VarTree.Root()) - { - cmLocalGenerator* plg = mf->LocalGenerator->GetParent(); - if(!plg) - { - return false; - } - // Update the definition in the parent directory top scope. This - // directory's scope was initialized by the closure of the parent - // scope, so we do not need to localize the definition first. - cmMakefile* parent = plg->GetMakefile(); - if (varDef) - { - parent->AddDefinition(var, varDef); - } - else - { - parent->RemoveDefinition(var); - } - return true; - } - // First localize the definition in the current scope. - cmDefinitions::Raise(var, this->VarScopeIter->Vars, this->VarTree.Root()); - - // Now update the definition in the parent scope. - this->VarScopeIter->ParentScope->Set(var, varDef); - return true; - } }; // default is not to be building executables @@ -181,7 +55,6 @@ cmMakefile::cmMakefile(cmLocalGenerator* localGenerator) LocalGenerator(localGenerator), StateSnapshot(localGenerator->GetStateSnapshot()) { - this->Internal->InitializeVarScope(); this->Internal->IsSourceFileTryCompile = false; // Initialize these first since AddDefaultDefinitions calls AddDefinition @@ -1607,9 +1480,6 @@ void cmMakefile::AddLinkLibrary(const std::string& lib) void cmMakefile::InitializeFromParent(cmMakefile* parent) { - // Initialize definitions with the closure of the parent scope. - this->Internal->InitializeDefinitions(parent); - this->StateSnapshot.InitializeFromParent(); this->AddDefinition("CMAKE_CURRENT_SOURCE_DIR", @@ -1674,8 +1544,6 @@ void cmMakefile::PushFunctionScope(std::string const& fileName, fileName); assert(this->StateSnapshot.IsValid()); - this->Internal->PushDefinitions(Internals::FunctionScope); - this->PushLoopBlockBarrier(); #if defined(CMAKE_BUILD_WITH_CMAKE) @@ -1702,8 +1570,6 @@ void cmMakefile::PopFunctionScope(bool reportError) this->PopLoopBlockBarrier(); this->CheckForUnusedVariables(); - - this->Internal->PopDefinitions(); } void cmMakefile::PushMacroScope(std::string const& fileName, @@ -2007,7 +1873,7 @@ void cmMakefile::AddDefinition(const std::string& name, const char* value) { this->LogUnused("changing definition", name); } - this->Internal->SetDefinition(name, value); + this->StateSnapshot.SetDefinition(name, value); #ifdef CMAKE_BUILD_WITH_CMAKE cmVariableWatch* vv = this->GetVariableWatch(); @@ -2070,7 +1936,7 @@ void cmMakefile::AddCacheDefinition(const std::string& name, const char* value, this->GetState()->AddCacheEntry(name, haveVal ? val.c_str() : 0, doc, type); // if there was a definition then remove it - this->Internal->RemoveDefinition(name); + this->StateSnapshot.RemoveDefinition(name); } @@ -2080,7 +1946,9 @@ void cmMakefile::AddDefinition(const std::string& name, bool value) { this->LogUnused("changing definition", name); } - this->Internal->SetDefinition(name, value ? "ON" : "OFF"); + + this->StateSnapshot.SetDefinition(name, value ? "ON" : "OFF"); + #ifdef CMAKE_BUILD_WITH_CMAKE cmVariableWatch* vv = this->GetVariableWatch(); if ( vv ) @@ -2097,7 +1965,7 @@ void cmMakefile::CheckForUnusedVariables() const { return; } - const std::vector& unused = this->Internal->UnusedKeys(); + const std::vector& unused = this->StateSnapshot.UnusedKeys(); std::vector::const_iterator it = unused.begin(); for (; it != unused.end(); ++it) { @@ -2107,12 +1975,12 @@ void cmMakefile::CheckForUnusedVariables() const void cmMakefile::MarkVariableAsUsed(const std::string& var) { - this->Internal->GetDefinition(var); + this->StateSnapshot.GetDefinition(var); } bool cmMakefile::VariableInitialized(const std::string& var) const { - return this->Internal->IsInitialized(var); + return this->StateSnapshot.IsInitialized(var); } void cmMakefile::LogUnused(const char* reason, @@ -2160,7 +2028,7 @@ void cmMakefile::RemoveDefinition(const std::string& name) { this->LogUnused("unsetting", name); } - this->Internal->RemoveDefinition(name); + this->StateSnapshot.RemoveDefinition(name); #ifdef CMAKE_BUILD_WITH_CMAKE cmVariableWatch* vv = this->GetVariableWatch(); if ( vv ) @@ -2626,7 +2494,7 @@ const char* cmMakefile::GetRequiredDefinition(const std::string& name) const bool cmMakefile::IsDefinitionSet(const std::string& name) const { - const char* def = this->Internal->GetDefinition(name); + const char* def = this->StateSnapshot.GetDefinition(name); if(!def) { def = this->GetState()->GetInitializedCacheValue(name); @@ -2647,7 +2515,7 @@ bool cmMakefile::IsDefinitionSet(const std::string& name) const const char* cmMakefile::GetDefinition(const std::string& name) const { - const char* def = this->Internal->GetDefinition(name); + const char* def = this->StateSnapshot.GetDefinition(name); if(!def) { def = this->GetState()->GetInitializedCacheValue(name); @@ -2683,7 +2551,7 @@ const char* cmMakefile::GetSafeDefinition(const std::string& def) const std::vector cmMakefile::GetDefinitions() const { - std::vector res = this->Internal->ClosureKeys(); + std::vector res = this->StateSnapshot.ClosureKeys(); std::vector cacheKeys = this->GetState()->GetCacheEntryKeys(); res.insert(res.end(), cacheKeys.begin(), cacheKeys.end()); std::sort(res.begin(), res.end()); @@ -4462,8 +4330,6 @@ std::string cmMakefile::FormatListFileStack() const void cmMakefile::PushScope() { - this->Internal->PushDefinitions(Internals::VariableScope); - std::string commandName; long line = 0; if (!this->ContextStack.empty()) @@ -4492,7 +4358,6 @@ void cmMakefile::PopScope() this->CheckForUnusedVariables(); - this->Internal->PopDefinitions(); this->StateSnapshot = this->GetState()->Pop(this->StateSnapshot); assert(this->StateSnapshot.IsValid()); @@ -4505,7 +4370,7 @@ void cmMakefile::RaiseScope(const std::string& var, const char *varDef) return; } - if (!this->Internal->RaiseScope(var, varDef, this)) + if (!this->StateSnapshot.RaiseScope(var, varDef)) { std::ostringstream m; m << "Cannot set \"" << var << "\": current scope has no parent."; diff --git a/Source/cmState.cxx b/Source/cmState.cxx index 9e09353b0..ab309ad31 100644 --- a/Source/cmState.cxx +++ b/Source/cmState.cxx @@ -15,6 +15,7 @@ #include "cmCacheManager.h" #include "cmCommand.h" #include "cmAlgorithms.h" +#include "cmDefinitions.h" #include @@ -29,6 +30,9 @@ struct cmState::SnapshotDataType cmLinkedTree::iterator ExecutionListFile; cmLinkedTree::iterator BuildSystemDirectory; + cmLinkedTree::iterator Vars; + cmLinkedTree::iterator Root; + cmLinkedTree::iterator Parent; std::string EntryPointCommand; long EntryPointLine; std::vector::size_type IncludeDirectoryPosition; @@ -275,6 +279,10 @@ cmState::Snapshot cmState::Reset() pos->PolicyScope = this->PolicyStack.Root(); assert(pos->Policies.IsValid()); assert(pos->PolicyRoot.IsValid()); + this->VarTree.Clear(); + pos->Vars = this->VarTree.Extend(this->VarTree.Root()); + pos->Parent = this->VarTree.Root(); + pos->Root = this->VarTree.Root(); this->DefineProperty ("RULE_LAUNCH_COMPILE", cmProperty::DIRECTORY, @@ -752,6 +760,10 @@ cmState::Snapshot cmState::CreateBaseSnapshot() pos->PolicyScope = this->PolicyStack.Root(); assert(pos->Policies.IsValid()); assert(pos->PolicyRoot.IsValid()); + pos->Vars = this->VarTree.Extend(this->VarTree.Root()); + assert(pos->Vars.IsValid()); + pos->Parent = this->VarTree.Root(); + pos->Root = this->VarTree.Root(); return cmState::Snapshot(this, pos); } @@ -779,6 +791,12 @@ cmState::CreateBuildsystemDirectorySnapshot(Snapshot originSnapshot, pos->PolicyScope = originSnapshot.Position->Policies; assert(pos->Policies.IsValid()); assert(pos->PolicyRoot.IsValid()); + + cmLinkedTree::iterator origin = + originSnapshot.Position->Vars; + pos->Parent = origin; + pos->Root = origin; + pos->Vars = this->VarTree.Extend(origin); return cmState::Snapshot(this, pos); } @@ -798,6 +816,11 @@ cmState::CreateFunctionCallSnapshot(cmState::Snapshot originSnapshot, originSnapshot.Position->ExecutionListFile, fileName); pos->BuildSystemDirectory->DirectoryEnd = pos; pos->PolicyScope = originSnapshot.Position->Policies; + assert(originSnapshot.Position->Vars.IsValid()); + cmLinkedTree::iterator origin = + originSnapshot.Position->Vars; + pos->Parent = origin; + pos->Vars = this->VarTree.Extend(origin); return cmState::Snapshot(this, pos); } @@ -815,6 +838,7 @@ cmState::CreateMacroCallSnapshot(cmState::Snapshot originSnapshot, pos->SnapshotType = MacroCallType; pos->ExecutionListFile = this->ExecutionListFiles.Extend( originSnapshot.Position->ExecutionListFile, fileName); + assert(originSnapshot.Position->Vars.IsValid()); pos->BuildSystemDirectory->DirectoryEnd = pos; pos->PolicyScope = originSnapshot.Position->Policies; return cmState::Snapshot(this, pos); @@ -833,6 +857,7 @@ cmState::CreateCallStackSnapshot(cmState::Snapshot originSnapshot, pos->SnapshotType = CallStackType; pos->ExecutionListFile = this->ExecutionListFiles.Extend( originSnapshot.Position->ExecutionListFile, fileName); + assert(originSnapshot.Position->Vars.IsValid()); pos->BuildSystemDirectory->DirectoryEnd = pos; pos->PolicyScope = originSnapshot.Position->Policies; return cmState::Snapshot(this, pos); @@ -849,7 +874,13 @@ cmState::CreateVariableScopeSnapshot(cmState::Snapshot originSnapshot, pos->EntryPointLine = entryPointLine; pos->EntryPointCommand = entryPointCommand; pos->SnapshotType = VariableScopeType; + assert(originSnapshot.Position->Vars.IsValid()); + cmLinkedTree::iterator origin = + originSnapshot.Position->Vars; + pos->Parent = origin; + pos->Vars = this->VarTree.Extend(origin); + assert(pos->Vars.IsValid()); return cmState::Snapshot(this, pos); } @@ -1141,6 +1172,72 @@ bool cmState::Snapshot::HasDefinedPolicyCMP0011() return !this->Position->Policies->IsEmpty(); } +const char* cmState::Snapshot::GetDefinition(std::string const& name) const +{ + assert(this->Position->Vars.IsValid()); + return cmDefinitions::Get(name, this->Position->Vars, + this->Position->Root); +} + +bool cmState::Snapshot::IsInitialized(std::string const& name) const +{ + return cmDefinitions::HasKey(name, this->Position->Vars, + this->Position->Root); +} + +void cmState::Snapshot::SetDefinition(std::string const& name, + std::string const& value) +{ + this->Position->Vars->Set(name, value.c_str()); +} + +void cmState::Snapshot::RemoveDefinition(std::string const& name) +{ + this->Position->Vars->Set(name, 0); +} + +std::vector cmState::Snapshot::UnusedKeys() const +{ + return this->Position->Vars->UnusedKeys(); +} + +std::vector cmState::Snapshot::ClosureKeys() const +{ + return cmDefinitions::ClosureKeys(this->Position->Vars, + this->Position->Root); +} + +bool cmState::Snapshot::RaiseScope(std::string const& var, const char* varDef) +{ + if(this->Position->ScopeParent == this->Position->DirectoryParent) + { + Snapshot parentDir = this->GetBuildsystemDirectoryParent(); + if(!parentDir.IsValid()) + { + return false; + } + // Update the definition in the parent directory top scope. This + // directory's scope was initialized by the closure of the parent + // scope, so we do not need to localize the definition first. + if (varDef) + { + parentDir.SetDefinition(var, varDef); + } + else + { + parentDir.RemoveDefinition(var); + } + return true; + } + // First localize the definition in the current scope. + cmDefinitions::Raise(var, this->Position->Vars, + this->Position->Root); + + // Now update the definition in the parent scope. + this->Position->Parent->Set(var, varDef); + return true; +} + static const std::string cmPropertySentinal = std::string(); template @@ -1177,6 +1274,11 @@ void InitializeContentFromParent(T& parentContent, void cmState::Snapshot::InitializeFromParent() { PositionType parent = this->Position->DirectoryParent; + assert(this->Position->Vars.IsValid()); + assert(parent->Vars.IsValid()); + + *this->Position->Vars = + cmDefinitions::MakeClosure(parent->Vars, parent->Root); InitializeContentFromParent(parent->BuildSystemDirectory->IncludeDirectories, this->Position->BuildSystemDirectory->IncludeDirectories, diff --git a/Source/cmState.h b/Source/cmState.h index 4d87653bb..549966549 100644 --- a/Source/cmState.h +++ b/Source/cmState.h @@ -21,6 +21,8 @@ class cmake; class cmCommand; +class cmDefinitions; +class cmListFileBacktrace; class cmState { @@ -52,6 +54,14 @@ public: Snapshot(cmState* state = 0); Snapshot(cmState* state, PositionType position); + const char* GetDefinition(std::string const& name) const; + bool IsInitialized(std::string const& name) const; + void SetDefinition(std::string const& name, std::string const& value); + void RemoveDefinition(std::string const& name); + std::vector UnusedKeys() const; + std::vector ClosureKeys() const; + bool RaiseScope(std::string const& var, const char* varDef); + void SetListFile(std::string const& listfile); std::string GetExecutionListFile() const; @@ -273,6 +283,7 @@ private: cmLinkedTree PolicyStack; cmLinkedTree SnapshotData; + cmLinkedTree VarTree; std::vector SourceDirectoryComponents; std::vector BinaryDirectoryComponents;