summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Source/cmCMakePolicyCommand.cxx14
-rw-r--r--Source/cmMakefile.cxx110
-rw-r--r--Source/cmMakefile.h12
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;