Fix assertion failure on unmatched function or macro

The fix in commit v3.2.3~3^2 (Fix assertion failure on unmatched foreach
in function, 2015-05-18) broke handling of unmatched non-loop blocks
because it assumed all function blockers removed during error unwinding
were for loops, essentially switching the set of mishandled cases.

The purpose of the loop block push/pop operations is to define a scope
matching the lifetime of the loop function blockers.  Since our function
blockers already have the proper lifetime, simply move the push/pop
operations to their constructor/destructor.

Extend the RunCMake.Syntax test with a case covering this.
This commit is contained in:
Brad King
2015-06-22 11:31:04 -04:00
parent 3a65606591
commit 5d85fb4f40
13 changed files with 52 additions and 27 deletions
+14 -8
View File
@@ -13,6 +13,17 @@
#include <cmsys/auto_ptr.hxx>
cmForEachFunctionBlocker::cmForEachFunctionBlocker(cmMakefile* mf):
Makefile(mf), Depth(0)
{
this->Makefile->PushLoopBlock();
}
cmForEachFunctionBlocker::~cmForEachFunctionBlocker()
{
this->Makefile->PopLoopBlock();
}
bool cmForEachFunctionBlocker::
IsFunctionBlocked(const cmListFileFunction& lff, cmMakefile &mf,
cmExecutionStatus &inStatus)
@@ -27,8 +38,6 @@ IsFunctionBlocked(const cmListFileFunction& lff, cmMakefile &mf,
// if this is the endofreach for this statement
if (!this->Depth)
{
cmMakefile::LoopBlockPop loopBlockPop(&mf);
// Remove the function blocker for this scope or bail.
cmsys::auto_ptr<cmFunctionBlocker>
fb(mf.RemoveFunctionBlocker(this, lff));
@@ -130,7 +139,7 @@ bool cmForEachCommand
}
// create a function blocker
cmForEachFunctionBlocker *f = new cmForEachFunctionBlocker();
cmForEachFunctionBlocker *f = new cmForEachFunctionBlocker(this->Makefile);
if ( args.size() > 1 )
{
if ( args[1] == "RANGE" )
@@ -206,15 +215,14 @@ bool cmForEachCommand
}
this->Makefile->AddFunctionBlocker(f);
this->Makefile->PushLoopBlock();
return true;
}
//----------------------------------------------------------------------------
bool cmForEachCommand::HandleInMode(std::vector<std::string> const& args)
{
cmsys::auto_ptr<cmForEachFunctionBlocker> f(new cmForEachFunctionBlocker());
cmsys::auto_ptr<cmForEachFunctionBlocker>
f(new cmForEachFunctionBlocker(this->Makefile));
f->Args.push_back(args[0]);
enum Doing { DoingNone, DoingLists, DoingItems };
@@ -252,7 +260,5 @@ bool cmForEachCommand::HandleInMode(std::vector<std::string> const& args)
this->Makefile->AddFunctionBlocker(f.release()); // TODO: pass auto_ptr
this->Makefile->PushLoopBlock();
return true;
}