diff options
author | Brad King <brad.king@kitware.com> | 2009-01-22 15:57:16 (GMT) |
---|---|---|
committer | Brad King <brad.king@kitware.com> | 2009-01-22 15:57:16 (GMT) |
commit | dfc181a1dc0baa3b4f36b64a0b64e68c1a2f636a (patch) | |
tree | 4417f27921d73ef74d37a72031c39c2d1c2f873d /Source | |
parent | ac14b5d2eb995f0cb1cfc1acca9d06ec02cff7d7 (diff) | |
download | CMake-dfc181a1dc0baa3b4f36b64a0b64e68c1a2f636a.zip CMake-dfc181a1dc0baa3b4f36b64a0b64e68c1a2f636a.tar.gz CMake-dfc181a1dc0baa3b4f36b64a0b64e68c1a2f636a.tar.bz2 |
ENH: Create policy scope barriers
This creates a barrier mechanism to prevent user code from using
cmake_policy(POP) to pop a scope it didn't push with cmake_policy(PUSH).
Diffstat (limited to 'Source')
-rw-r--r-- | Source/cmCMakePolicyCommand.cxx | 14 | ||||
-rw-r--r-- | Source/cmMakefile.cxx | 110 | ||||
-rw-r--r-- | Source/cmMakefile.h | 12 |
3 files changed, 82 insertions, 54 deletions
diff --git a/Source/cmCMakePolicyCommand.cxx b/Source/cmCMakePolicyCommand.cxx index 7672a6c..dc99c86 100644 --- a/Source/cmCMakePolicyCommand.cxx +++ b/Source/cmCMakePolicyCommand.cxx @@ -43,7 +43,8 @@ bool cmCMakePolicyCommand this->SetError("PUSH may not be given additional arguments."); return false; } - return this->Makefile->PushPolicy(); + this->Makefile->PushPolicy(); + return true; } else if(args[0] == "POP") { @@ -52,15 +53,8 @@ bool cmCMakePolicyCommand this->SetError("POP may not be given additional arguments."); return false; } - if(this->Makefile->PopPolicy(false)) - { - return true; - } - else - { - this->SetError("POP without matching PUSH"); - return false; - } + this->Makefile->PopPolicy(); + return true; } else if(args[0] == "VERSION") { diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index b402a6d..8fc4210 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -150,6 +150,9 @@ void cmMakefile::Initialize() // Enter a policy level for this directory. this->PushPolicy(); + // Protect the directory-level policies. + this->PushPolicyBarrier(); + // By default the check is not done. It is enabled by // cmListFileCache in the top level if necessary. this->CheckCMP0000 = false; @@ -441,6 +444,34 @@ bool cmMakefile::ExecuteCommand(const cmListFileFunction& lff, return result; } +//---------------------------------------------------------------------------- +class cmMakefile::IncludeScope +{ +public: + IncludeScope(cmMakefile* mf); + ~IncludeScope(); + void Quiet() { this->ReportError = false; } +private: + cmMakefile* Makefile; + bool ReportError; +}; + +//---------------------------------------------------------------------------- +cmMakefile::IncludeScope::IncludeScope(cmMakefile* mf): + Makefile(mf), ReportError(true) +{ + // The included file cannot pop our policy scope. + this->Makefile->PushPolicyBarrier(); +} + +//---------------------------------------------------------------------------- +cmMakefile::IncludeScope::~IncludeScope() +{ + // Enforce matching policy scopes inside the included file. + this->Makefile->PopPolicyBarrier(this->ReportError); +} + +//---------------------------------------------------------------------------- // Parse the given CMakeLists.txt file executing all commands // bool cmMakefile::ReadListFile(const char* filename_in, @@ -533,10 +564,7 @@ bool cmMakefile::ReadListFile(const char* filename_in, // Enforce balanced blocks (if/endif, function/endfunction, etc.). { LexicalPushPop lexScope(this); - bool endScopeNicely = true; - - // Save the current policy stack depth. - size_t const policy_depth = this->PolicyStack.size(); + IncludeScope incScope(this); // Run the parsed commands. const size_t numberFunctions = cacheFile.Functions.size(); @@ -547,8 +575,8 @@ bool cmMakefile::ReadListFile(const char* filename_in, if(cmSystemTools::GetFatalErrorOccured()) { // Exit early due to error. - endScopeNicely = false; lexScope.Quiet(); + incScope.Quiet(); break; } if(status.GetReturnInvoked()) @@ -557,17 +585,6 @@ bool cmMakefile::ReadListFile(const char* filename_in, break; } } - - // Restore policy stack depth. - while(this->PolicyStack.size() > policy_depth) - { - if(endScopeNicely) - { - this->IssueMessage(cmake::FATAL_ERROR, - "cmake_policy PUSH without matching POP"); - } - this->PopPolicy(false); - } } // If this is the directory-level CMakeLists.txt file then perform @@ -3675,54 +3692,65 @@ bool cmMakefile::SetPolicy(cmPolicies::PolicyID id, } //---------------------------------------------------------------------------- -cmMakefile::PolicyPushPop::PolicyPushPop(cmMakefile* m): Makefile(m) +cmMakefile::PolicyPushPop::PolicyPushPop(cmMakefile* m): + Makefile(m), ReportError(true) { this->Makefile->PushPolicy(); - this->PolicyDepth = this->Makefile->PolicyStack.size(); + this->Makefile->PushPolicyBarrier(); } //---------------------------------------------------------------------------- cmMakefile::PolicyPushPop::~PolicyPushPop() { - // Enforce matching PUSH/POP pairs. - if(this->Makefile->PolicyStack.size() < this->PolicyDepth) + this->Makefile->PopPolicyBarrier(this->ReportError); + this->Makefile->PopPolicy(); +} + +//---------------------------------------------------------------------------- +void cmMakefile::PushPolicy() +{ + // Allocate a new stack entry. + this->PolicyStack.push_back(PolicyStackEntry()); +} + +//---------------------------------------------------------------------------- +void cmMakefile::PopPolicy() +{ + if(this->PolicyStack.size() > this->PolicyBarriers.back()) { - this->Makefile->IssueMessage(cmake::FATAL_ERROR, - "cmake_policy POP without matching PUSH"); - return; + this->PolicyStack.pop_back(); } - while(this->Makefile->PolicyStack.size() > this->PolicyDepth) + else { - this->Makefile->IssueMessage(cmake::FATAL_ERROR, - "cmake_policy PUSH without matching POP"); - this->Makefile->PopPolicy(false); + this->IssueMessage(cmake::FATAL_ERROR, + "cmake_policy POP without matching PUSH"); } - - // Pop our scope. - this->Makefile->PopPolicy(); } //---------------------------------------------------------------------------- -bool cmMakefile::PushPolicy() +void cmMakefile::PushPolicyBarrier() { - // Allocate a new stack entry. - this->PolicyStack.push_back(PolicyStackEntry()); - return true; + this->PolicyBarriers.push_back(this->PolicyStack.size()); } -bool cmMakefile::PopPolicy(bool reportError) +//---------------------------------------------------------------------------- +void cmMakefile::PopPolicyBarrier(bool reportError) { - if(this->PolicyStack.size() == 1) + // Remove any extra entries pushed on the barrier. + PolicyStackType::size_type barrier = this->PolicyBarriers.back(); + while(this->PolicyStack.size() > barrier) { if(reportError) { - cmSystemTools::Error("Attempt to pop the policy stack past " - "it's beginning."); + this->IssueMessage(cmake::FATAL_ERROR, + "cmake_policy PUSH without matching POP"); + reportError = false; } - return false; + this->PopPolicy(); } - this->PolicyStack.pop_back(); - return true; + + // Remove the barrier. + this->PolicyBarriers.pop_back(); } bool cmMakefile::SetPolicyVersion(const char *version) diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h index 48dc768..b7b9dc7 100644 --- a/Source/cmMakefile.h +++ b/Source/cmMakefile.h @@ -351,9 +351,10 @@ public: public: PolicyPushPop(cmMakefile* m); ~PolicyPushPop(); + void Quiet() { this->ReportError = false; } private: cmMakefile* Makefile; - size_t PolicyDepth; + bool ReportError; }; friend class PolicyPushPop; @@ -942,9 +943,13 @@ private: std::map<cmStdString, cmTarget*> ImportedTargets; // Internal policy stack management. - bool PushPolicy(); - bool PopPolicy(bool reportError = true); + void PushPolicy(); + void PopPolicy(); + void PushPolicyBarrier(); + void PopPolicyBarrier(bool reportError = true); friend class cmCMakePolicyCommand; + class IncludeScope; + friend class IncludeScope; // stack of policy settings struct PolicyStackEntry: public cmPolicies::PolicyMap @@ -956,6 +961,7 @@ private: }; typedef std::vector<PolicyStackEntry> PolicyStackType; PolicyStackType PolicyStack; + std::vector<PolicyStackType::size_type> PolicyBarriers; cmPolicies::PolicyStatus GetPolicyStatusInternal(cmPolicies::PolicyID id); bool CheckCMP0000; |