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:
parent
3a65606591
commit
5d85fb4f40
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -19,8 +19,8 @@
|
|||
class cmForEachFunctionBlocker : public cmFunctionBlocker
|
||||
{
|
||||
public:
|
||||
cmForEachFunctionBlocker() {this->Depth = 0;}
|
||||
virtual ~cmForEachFunctionBlocker() {}
|
||||
cmForEachFunctionBlocker(cmMakefile* mf);
|
||||
~cmForEachFunctionBlocker();
|
||||
virtual bool IsFunctionBlocked(const cmListFileFunction& lff,
|
||||
cmMakefile &mf,
|
||||
cmExecutionStatus &);
|
||||
|
@ -29,6 +29,7 @@ public:
|
|||
std::vector<std::string> Args;
|
||||
std::vector<cmListFileFunction> Functions;
|
||||
private:
|
||||
cmMakefile* Makefile;
|
||||
int Depth;
|
||||
};
|
||||
|
||||
|
|
|
@ -3284,7 +3284,6 @@ void cmMakefile::PopFunctionBlockerBarrier(bool reportError)
|
|||
this->FunctionBlockerBarriers.back();
|
||||
while(this->FunctionBlockers.size() > barrier)
|
||||
{
|
||||
cmMakefile::LoopBlockPop loopBlockPop(this);
|
||||
cmsys::auto_ptr<cmFunctionBlocker> fb(this->FunctionBlockers.back());
|
||||
this->FunctionBlockers.pop_back();
|
||||
if(reportError)
|
||||
|
|
|
@ -125,15 +125,6 @@ public:
|
|||
};
|
||||
friend class LexicalPushPop;
|
||||
|
||||
class LoopBlockPop
|
||||
{
|
||||
public:
|
||||
LoopBlockPop(cmMakefile* mf) { this->Makefile = mf; }
|
||||
~LoopBlockPop() { this->Makefile->PopLoopBlock(); }
|
||||
private:
|
||||
cmMakefile* Makefile;
|
||||
};
|
||||
|
||||
/**
|
||||
* Try running cmake and building a file. This is used for dynalically
|
||||
* loaded commands, not as part of the usual build process.
|
||||
|
|
|
@ -12,6 +12,17 @@
|
|||
#include "cmWhileCommand.h"
|
||||
#include "cmConditionEvaluator.h"
|
||||
|
||||
cmWhileFunctionBlocker::cmWhileFunctionBlocker(cmMakefile* mf):
|
||||
Makefile(mf), Depth(0)
|
||||
{
|
||||
this->Makefile->PushLoopBlock();
|
||||
}
|
||||
|
||||
cmWhileFunctionBlocker::~cmWhileFunctionBlocker()
|
||||
{
|
||||
this->Makefile->PopLoopBlock();
|
||||
}
|
||||
|
||||
bool cmWhileFunctionBlocker::
|
||||
IsFunctionBlocked(const cmListFileFunction& lff, cmMakefile &mf,
|
||||
cmExecutionStatus &inStatus)
|
||||
|
@ -27,8 +38,6 @@ IsFunctionBlocked(const cmListFileFunction& lff, cmMakefile &mf,
|
|||
// if this is the endwhile for this while loop then execute
|
||||
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));
|
||||
|
@ -140,12 +149,10 @@ bool cmWhileCommand
|
|||
}
|
||||
|
||||
// create a function blocker
|
||||
cmWhileFunctionBlocker *f = new cmWhileFunctionBlocker();
|
||||
cmWhileFunctionBlocker *f = new cmWhileFunctionBlocker(this->Makefile);
|
||||
f->Args = args;
|
||||
this->Makefile->AddFunctionBlocker(f);
|
||||
|
||||
this->Makefile->PushLoopBlock();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -19,8 +19,8 @@
|
|||
class cmWhileFunctionBlocker : public cmFunctionBlocker
|
||||
{
|
||||
public:
|
||||
cmWhileFunctionBlocker() {this->Depth=0;}
|
||||
virtual ~cmWhileFunctionBlocker() {}
|
||||
cmWhileFunctionBlocker(cmMakefile* mf);
|
||||
~cmWhileFunctionBlocker();
|
||||
virtual bool IsFunctionBlocked(const cmListFileFunction& lff,
|
||||
cmMakefile &mf,
|
||||
cmExecutionStatus &);
|
||||
|
@ -29,6 +29,7 @@ public:
|
|||
std::vector<cmListFileArgument> Args;
|
||||
std::vector<cmListFileFunction> Functions;
|
||||
private:
|
||||
cmMakefile* Makefile;
|
||||
int Depth;
|
||||
};
|
||||
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
1
|
|
@ -0,0 +1,6 @@
|
|||
^CMake Error at CMakeLists.txt:[0-9]+ \(include\):
|
||||
A logical block opening on the line
|
||||
|
||||
.*/Tests/RunCMake/Syntax/FunctionUnmatched.cmake:[0-9]+ \(function\)
|
||||
|
||||
is not closed.$
|
|
@ -0,0 +1,2 @@
|
|||
function(f)
|
||||
#endfunction() # missing
|
|
@ -0,0 +1 @@
|
|||
1
|
|
@ -0,0 +1,6 @@
|
|||
^CMake Error at CMakeLists.txt:[0-9]+ \(include\):
|
||||
A logical block opening on the line
|
||||
|
||||
.*/Tests/RunCMake/Syntax/MacroUnmatched.cmake:[0-9]+ \(macro\)
|
||||
|
||||
is not closed.$
|
|
@ -0,0 +1,2 @@
|
|||
macro(m)
|
||||
#endmacro() # missing
|
|
@ -110,5 +110,7 @@ run_cmake(CMP0053-NameWithEscapedSpacesQuoted)
|
|||
run_cmake(CMP0053-NameWithEscapedTabsQuoted)
|
||||
|
||||
# Function and macro tests.
|
||||
run_cmake(FunctionUnmatched)
|
||||
run_cmake(FunctionUnmatchedForeach)
|
||||
run_cmake(MacroUnmatched)
|
||||
run_cmake(MacroUnmatchedForeach)
|
||||
|
|
Loading…
Reference in New Issue