Commit 6491270e authored by wahikihiki's avatar wahikihiki
Browse files

cmFunctionBlocker: Move check for matching args

parent af24e4ef
......@@ -28,7 +28,9 @@ public:
cm::string_view StartCommandName() const override { return "foreach"_s; }
cm::string_view EndCommandName() const override { return "endforeach"_s; }
bool ShouldRemove(const cmListFileFunction& lff, cmMakefile& mf) override;
bool ArgumentsMatch(cmListFileFunction const& lff,
cmMakefile& mf) const override;
bool Replay(std::vector<cmListFileFunction> const& functions,
cmExecutionStatus& inStatus) override;
......@@ -49,20 +51,12 @@ cmForEachFunctionBlocker::~cmForEachFunctionBlocker()
this->Makefile->PopLoopBlock();
}
bool cmForEachFunctionBlocker::ShouldRemove(const cmListFileFunction& lff,
cmMakefile& mf)
bool cmForEachFunctionBlocker::ArgumentsMatch(cmListFileFunction const& lff,
cmMakefile& mf) const
{
if (lff.Name.Lower == "endforeach") {
std::vector<std::string> expandedArguments;
mf.ExpandArguments(lff.Arguments, expandedArguments);
// if the endforeach has arguments then make sure
// they match the begin foreach arguments
if ((expandedArguments.empty() ||
(expandedArguments[0] == this->Args[0]))) {
return true;
}
}
return false;
std::vector<std::string> expandedArguments;
mf.ExpandArguments(lff.Arguments, expandedArguments);
return expandedArguments.empty() || expandedArguments[0] == this->Args[0];
}
bool cmForEachFunctionBlocker::Replay(
......
......@@ -2,8 +2,12 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmFunctionBlocker.h"
#include <cassert>
#include <sstream>
#include "cmExecutionStatus.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
bool cmFunctionBlocker::IsFunctionBlocked(const cmListFileFunction& lff,
cmExecutionStatus& status)
......@@ -14,7 +18,24 @@ bool cmFunctionBlocker::IsFunctionBlocked(const cmListFileFunction& lff,
this->ScopeDepth--;
if (this->ScopeDepth == 0U) {
cmMakefile& mf = status.GetMakefile();
auto self = mf.RemoveFunctionBlocker(this, lff);
auto self = mf.RemoveFunctionBlocker();
assert(self.get() == this);
if (!this->ArgumentsMatch(lff, mf)) {
cmListFileContext const& lfc = this->GetStartingContext();
cmListFileContext closingContext =
cmListFileContext::FromCommandContext(lff, lfc.FilePath);
std::ostringstream e;
/* clang-format off */
e << "A logical block opening on the line\n"
<< " " << lfc << "\n"
<< "closes on the line\n"
<< " " << closingContext << "\n"
<< "with mis-matching arguments.";
/* clang-format on */
mf.IssueMessage(MessageType::AUTHOR_WARNING, e.str());
}
return this->Replay(this->Functions, status);
}
}
......
......@@ -23,15 +23,6 @@ public:
bool IsFunctionBlocked(cmListFileFunction const& lff,
cmExecutionStatus& status);
/**
* should this function blocker be removed, useful when one function adds a
* blocker and another must remove it
*/
virtual bool ShouldRemove(const cmListFileFunction&, cmMakefile&)
{
return false;
}
virtual ~cmFunctionBlocker() = default;
/** Set/Get the context in which this blocker is created. */
......@@ -48,6 +39,9 @@ private:
virtual cm::string_view StartCommandName() const = 0;
virtual cm::string_view EndCommandName() const = 0;
virtual bool ArgumentsMatch(cmListFileFunction const& lff,
cmMakefile& mf) const = 0;
virtual bool Replay(std::vector<cmListFileFunction> const& functions,
cmExecutionStatus& status) = 0;
......
......@@ -113,29 +113,22 @@ public:
cm::string_view StartCommandName() const override { return "function"_s; }
cm::string_view EndCommandName() const override { return "endfunction"_s; }
bool ShouldRemove(const cmListFileFunction&, cmMakefile& mf) override;
bool ArgumentsMatch(cmListFileFunction const&,
cmMakefile& mf) const override;
bool Replay(std::vector<cmListFileFunction> const& functions,
cmExecutionStatus& status) override;
std::vector<std::string> Args;
};
bool cmFunctionFunctionBlocker::ShouldRemove(const cmListFileFunction& lff,
cmMakefile& mf)
bool cmFunctionFunctionBlocker::ArgumentsMatch(cmListFileFunction const& lff,
cmMakefile& mf) const
{
if (lff.Name.Lower == "endfunction") {
std::vector<std::string> expandedArguments;
mf.ExpandArguments(lff.Arguments, expandedArguments,
this->GetStartingContext().FilePath.c_str());
// if the endfunction has arguments then make sure
// they match the ones in the opening function command
if ((expandedArguments.empty() ||
(expandedArguments[0] == this->Args[0]))) {
return true;
}
}
return false;
std::vector<std::string> expandedArguments;
mf.ExpandArguments(lff.Arguments, expandedArguments,
this->GetStartingContext().FilePath.c_str());
return expandedArguments.empty() || expandedArguments[0] == this->Args[0];
}
bool cmFunctionFunctionBlocker::Replay(
......
......@@ -38,7 +38,9 @@ public:
cm::string_view StartCommandName() const override { return "if"_s; }
cm::string_view EndCommandName() const override { return "endif"_s; }
bool ShouldRemove(const cmListFileFunction& lff, cmMakefile& mf) override;
bool ArgumentsMatch(cmListFileFunction const& lff,
cmMakefile&) const override;
bool Replay(std::vector<cmListFileFunction> const& functions,
cmExecutionStatus& inStatus) override;
......@@ -48,18 +50,10 @@ public:
bool ElseSeen = false;
};
bool cmIfFunctionBlocker::ShouldRemove(const cmListFileFunction& lff,
cmMakefile&)
bool cmIfFunctionBlocker::ArgumentsMatch(cmListFileFunction const& lff,
cmMakefile&) const
{
if (lff.Name.Lower == "endif") {
// if the endif has arguments, then make sure
// they match the arguments of the matching if
if (lff.Arguments.empty() || lff.Arguments == this->Args) {
return true;
}
}
return false;
return lff.Arguments.empty() || lff.Arguments == this->Args;
}
bool cmIfFunctionBlocker::Replay(
......
......@@ -146,29 +146,22 @@ public:
cm::string_view StartCommandName() const override { return "macro"_s; }
cm::string_view EndCommandName() const override { return "endmacro"_s; }
bool ShouldRemove(const cmListFileFunction&, cmMakefile& mf) override;
bool ArgumentsMatch(cmListFileFunction const&,
cmMakefile& mf) const override;
bool Replay(std::vector<cmListFileFunction> const& functions,
cmExecutionStatus& status) override;
std::vector<std::string> Args;
};
bool cmMacroFunctionBlocker::ShouldRemove(const cmListFileFunction& lff,
cmMakefile& mf)
bool cmMacroFunctionBlocker::ArgumentsMatch(cmListFileFunction const& lff,
cmMakefile& mf) const
{
if (lff.Name.Lower == "endmacro") {
std::vector<std::string> expandedArguments;
mf.ExpandArguments(lff.Arguments, expandedArguments,
this->GetStartingContext().FilePath.c_str());
// if the endmacro has arguments make sure they
// match the arguments of the macro
if ((expandedArguments.empty() ||
(expandedArguments[0] == this->Args[0]))) {
return true;
}
}
return false;
std::vector<std::string> expandedArguments;
mf.ExpandArguments(lff.Arguments, expandedArguments,
this->GetStartingContext().FilePath.c_str());
return expandedArguments.empty() || expandedArguments[0] == this->Args[0];
}
bool cmMacroFunctionBlocker::Replay(
......
......@@ -3220,30 +3220,12 @@ void cmMakefile::AddFunctionBlocker(std::unique_ptr<cmFunctionBlocker> fb)
this->FunctionBlockers.push(std::move(fb));
}
std::unique_ptr<cmFunctionBlocker> cmMakefile::RemoveFunctionBlocker(
cmFunctionBlocker* fb, const cmListFileFunction& lff)
std::unique_ptr<cmFunctionBlocker> cmMakefile::RemoveFunctionBlocker()
{
assert(!this->FunctionBlockers.empty());
assert(this->FunctionBlockers.top().get() == fb);
assert(this->FunctionBlockerBarriers.empty() ||
this->FunctionBlockers.size() > this->FunctionBlockerBarriers.back());
// Warn if the arguments do not match, but always remove.
if (!fb->ShouldRemove(lff, *this)) {
cmListFileContext const& lfc = fb->GetStartingContext();
cmListFileContext closingContext =
cmListFileContext::FromCommandContext(lff, lfc.FilePath);
std::ostringstream e;
/* clang-format off */
e << "A logical block opening on the line\n"
<< " " << lfc << "\n"
<< "closes on the line\n"
<< " " << closingContext << "\n"
<< "with mis-matching arguments.";
/* clang-format on */
this->IssueMessage(MessageType::AUTHOR_WARNING, e.str());
}
auto b = std::move(this->FunctionBlockers.top());
this->FunctionBlockers.pop();
return b;
......
......@@ -107,8 +107,7 @@ public:
* Remove the function blocker whose scope ends with the given command.
* This returns ownership of the function blocker object.
*/
std::unique_ptr<cmFunctionBlocker> RemoveFunctionBlocker(
cmFunctionBlocker* fb, const cmListFileFunction& lff);
std::unique_ptr<cmFunctionBlocker> RemoveFunctionBlocker();
/**
* Try running cmake and building a file. This is used for dynalically
......
......@@ -27,7 +27,9 @@ public:
cm::string_view StartCommandName() const override { return "while"_s; }
cm::string_view EndCommandName() const override { return "endwhile"_s; }
bool ShouldRemove(const cmListFileFunction& lff, cmMakefile& mf) override;
bool ArgumentsMatch(cmListFileFunction const& lff,
cmMakefile& mf) const override;
bool Replay(std::vector<cmListFileFunction> const& functions,
cmExecutionStatus& inStatus) override;
......@@ -48,17 +50,10 @@ cmWhileFunctionBlocker::~cmWhileFunctionBlocker()
this->Makefile->PopLoopBlock();
}
bool cmWhileFunctionBlocker::ShouldRemove(const cmListFileFunction& lff,
cmMakefile&)
bool cmWhileFunctionBlocker::ArgumentsMatch(cmListFileFunction const& lff,
cmMakefile&) const
{
if (lff.Name.Lower == "endwhile") {
// if the endwhile has arguments, then make sure
// they match the arguments of the matching while
if (lff.Arguments.empty() || lff.Arguments == this->Args) {
return true;
}
}
return false;
return lff.Arguments.empty() || lff.Arguments == this->Args;
}
bool cmWhileFunctionBlocker::Replay(
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment