mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 14:48:21 +00:00
Merge remote-tracking branch 'origin/topic/vern/script-opt-maint.Aug23'
* origin/topic/vern/script-opt-maint.Aug23: updated notes regarding "-O gen-C++" maintenance "-O gen-C++" support for "assert" statements addressed some nits re "-O gen-C++" script optimization fixes for compiling lambdas to C++ fixes to avoid ambiguities in analyzing captures for script optimization disambiguate lambdas by adding scoping and consideration of captures addressed performance and correctness issues flagged by Coverity
This commit is contained in:
commit
ae03d591b8
19 changed files with 254 additions and 124 deletions
16
CHANGES
16
CHANGES
|
@ -1,3 +1,19 @@
|
||||||
|
6.1.0-dev.327 | 2023-08-24 12:17:42 -0700
|
||||||
|
|
||||||
|
* updated notes regarding "-O gen-C++" maintenance (Vern Paxson, Corelight)
|
||||||
|
|
||||||
|
* "-O gen-C++" support for "assert" statements (Vern Paxson, Corelight)
|
||||||
|
|
||||||
|
* addressed some nits re "-O gen-C++" script optimization (Vern Paxson, Corelight)
|
||||||
|
|
||||||
|
* fixes for compiling lambdas to C++ (Vern Paxson, Corelight)
|
||||||
|
|
||||||
|
* fixes to avoid ambiguities in analyzing captures for script optimization (Vern Paxson, Corelight)
|
||||||
|
|
||||||
|
* disambiguate lambdas by adding scoping and consideration of captures (Vern Paxson, Corelight)
|
||||||
|
|
||||||
|
* addressed performance and correctness issues flagged by Coverity (Vern Paxson, Corelight)
|
||||||
|
|
||||||
6.1.0-dev.319 | 2023-08-24 12:26:00 +0200
|
6.1.0-dev.319 | 2023-08-24 12:26:00 +0200
|
||||||
|
|
||||||
* PPP: Add PPP analyzer to handle LINKTYPE_PPP (0x9) (Arne Welzel, Corelight)
|
* PPP: Add PPP analyzer to handle LINKTYPE_PPP (0x9) (Arne Welzel, Corelight)
|
||||||
|
|
2
VERSION
2
VERSION
|
@ -1 +1 @@
|
||||||
6.1.0-dev.319
|
6.1.0-dev.327
|
||||||
|
|
41
src/Expr.cc
41
src/Expr.cc
|
@ -4648,13 +4648,25 @@ LambdaExpr::LambdaExpr(FunctionIngredientsPtr arg_ing, IDPList arg_outer_ids, st
|
||||||
|
|
||||||
auto ingr_t = ingredients->GetID()->GetType<FuncType>();
|
auto ingr_t = ingredients->GetID()->GetType<FuncType>();
|
||||||
SetType(ingr_t);
|
SetType(ingr_t);
|
||||||
|
captures = ingr_t->GetCaptures();
|
||||||
|
|
||||||
if ( ! CheckCaptures(when_parent) )
|
if ( ! CheckCaptures(std::move(when_parent)) )
|
||||||
{
|
{
|
||||||
SetError();
|
SetError();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Now that we've validated that the captures match the outer_ids,
|
||||||
|
// we regenerate the latter to come in the same order as the captures.
|
||||||
|
// This avoids potentially subtle bugs when doing script optimization
|
||||||
|
// where one context uses the outer_ids and another uses the captures.
|
||||||
|
if ( captures )
|
||||||
|
{
|
||||||
|
outer_ids.clear();
|
||||||
|
for ( auto& c : *captures )
|
||||||
|
outer_ids.append(c.Id().get());
|
||||||
|
}
|
||||||
|
|
||||||
// Install a primary version of the function globally. This is used
|
// Install a primary version of the function globally. This is used
|
||||||
// by both broker (for transmitting closures) and script optimization
|
// by both broker (for transmitting closures) and script optimization
|
||||||
// (replacing its AST body with a compiled one).
|
// (replacing its AST body with a compiled one).
|
||||||
|
@ -4673,19 +4685,17 @@ LambdaExpr::LambdaExpr(FunctionIngredientsPtr arg_ing, IDPList arg_outer_ids, st
|
||||||
else
|
else
|
||||||
my_name = name;
|
my_name = name;
|
||||||
|
|
||||||
// Install that in the global_scope
|
// Install that in the current scope.
|
||||||
lambda_id = install_ID(my_name.c_str(), "", true, false);
|
lambda_id = install_ID(my_name.c_str(), current_module.c_str(), true, false);
|
||||||
|
|
||||||
// Update lamb's name
|
// Update lamb's name
|
||||||
primary_func->SetName(my_name.c_str());
|
primary_func->SetName(lambda_id->Name());
|
||||||
|
|
||||||
auto v = make_intrusive<FuncVal>(primary_func);
|
auto v = make_intrusive<FuncVal>(primary_func);
|
||||||
lambda_id->SetVal(std::move(v));
|
lambda_id->SetVal(std::move(v));
|
||||||
lambda_id->SetType(ingr_t);
|
lambda_id->SetType(ingr_t);
|
||||||
lambda_id->SetConst();
|
lambda_id->SetConst();
|
||||||
|
|
||||||
captures = ingr_t->GetCaptures();
|
|
||||||
|
|
||||||
analyze_lambda(this);
|
analyze_lambda(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4714,9 +4724,6 @@ LambdaExpr::LambdaExpr(LambdaExpr* orig) : Expr(EXPR_LAMBDA)
|
||||||
|
|
||||||
bool LambdaExpr::CheckCaptures(StmtPtr when_parent)
|
bool LambdaExpr::CheckCaptures(StmtPtr when_parent)
|
||||||
{
|
{
|
||||||
auto ft = type->AsFuncType();
|
|
||||||
const auto& captures = ft->GetCaptures();
|
|
||||||
|
|
||||||
auto desc = when_parent ? "\"when\" statement" : "lambda";
|
auto desc = when_parent ? "\"when\" statement" : "lambda";
|
||||||
|
|
||||||
if ( ! captures )
|
if ( ! captures )
|
||||||
|
@ -4800,6 +4807,17 @@ void LambdaExpr::BuildName()
|
||||||
ODesc d;
|
ODesc d;
|
||||||
primary_func->Describe(&d);
|
primary_func->Describe(&d);
|
||||||
|
|
||||||
|
if ( captures )
|
||||||
|
for ( auto& c : *captures )
|
||||||
|
{
|
||||||
|
if ( c.IsDeepCopy() )
|
||||||
|
d.AddSP("copy");
|
||||||
|
|
||||||
|
if ( c.Id() )
|
||||||
|
// c.Id() will be nil for some errors
|
||||||
|
c.Id()->Describe(&d);
|
||||||
|
}
|
||||||
|
|
||||||
for ( ;; )
|
for ( ;; )
|
||||||
{
|
{
|
||||||
hash128_t h;
|
hash128_t h;
|
||||||
|
@ -4807,7 +4825,7 @@ void LambdaExpr::BuildName()
|
||||||
|
|
||||||
my_name = "lambda_<" + std::to_string(h[0]) + ">";
|
my_name = "lambda_<" + std::to_string(h[0]) + ">";
|
||||||
auto fullname = make_full_var_name(current_module.data(), my_name.data());
|
auto fullname = make_full_var_name(current_module.data(), my_name.data());
|
||||||
const auto& id = global_scope()->Find(fullname);
|
const auto& id = current_scope()->Find(fullname);
|
||||||
|
|
||||||
if ( id )
|
if ( id )
|
||||||
// Just try again to make a unique lambda name.
|
// Just try again to make a unique lambda name.
|
||||||
|
@ -4873,6 +4891,9 @@ void LambdaExpr::ExprDescribe(ODesc* d) const
|
||||||
if ( &c != &(*captures)[0] )
|
if ( &c != &(*captures)[0] )
|
||||||
d->AddSP(", ");
|
d->AddSP(", ");
|
||||||
|
|
||||||
|
if ( c.IsDeepCopy() )
|
||||||
|
d->AddSP("copy");
|
||||||
|
|
||||||
d->Add(c.Id()->Name());
|
d->Add(c.Id()->Name());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -142,7 +142,7 @@ void Func::AddBody(detail::StmtPtr new_body, size_t new_frame_size)
|
||||||
{
|
{
|
||||||
std::vector<detail::IDPtr> no_inits;
|
std::vector<detail::IDPtr> no_inits;
|
||||||
std::set<EventGroupPtr> no_groups;
|
std::set<EventGroupPtr> no_groups;
|
||||||
AddBody(new_body, no_inits, new_frame_size, 0, no_groups);
|
AddBody(std::move(new_body), no_inits, new_frame_size, 0, no_groups);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Func::AddBody(detail::StmtPtr /* new_body */,
|
void Func::AddBody(detail::StmtPtr /* new_body */,
|
||||||
|
@ -588,7 +588,7 @@ void ScriptFunc::CreateCaptures(std::unique_ptr<std::vector<ZVal>> cvec)
|
||||||
if ( c_i.IsManaged() )
|
if ( c_i.IsManaged() )
|
||||||
ZVal::DeleteManagedType(cv_i);
|
ZVal::DeleteManagedType(cv_i);
|
||||||
|
|
||||||
cv_i = ZVal(new_cv_i, t);
|
cv_i = ZVal(std::move(new_cv_i), t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -725,7 +725,7 @@ FuncPtr ScriptFunc::DoClone()
|
||||||
// Need to clone cv_i.
|
// Need to clone cv_i.
|
||||||
auto& t_i = c.Id()->GetType();
|
auto& t_i = c.Id()->GetType();
|
||||||
auto cv_i_val = cv_i->ToVal(t_i)->Clone();
|
auto cv_i_val = cv_i->ToVal(t_i)->Clone();
|
||||||
other->captures_vec->push_back(ZVal(cv_i_val, t_i));
|
other->captures_vec->push_back(ZVal(std::move(cv_i_val), t_i));
|
||||||
++cv_i;
|
++cv_i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
126
src/Stmt.cc
126
src/Stmt.cc
|
@ -164,6 +164,12 @@ const NullStmt* Stmt::AsNullStmt() const
|
||||||
return (const NullStmt*)this;
|
return (const NullStmt*)this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const AssertStmt* Stmt::AsAssertStmt() const
|
||||||
|
{
|
||||||
|
CHECK_TAG(tag, STMT_ASSERT, "Stmt::AsAssertStmt", stmt_name)
|
||||||
|
return (const AssertStmt*)this;
|
||||||
|
}
|
||||||
|
|
||||||
bool Stmt::SetLocationInfo(const Location* start, const Location* end)
|
bool Stmt::SetLocationInfo(const Location* start, const Location* end)
|
||||||
{
|
{
|
||||||
if ( ! Obj::SetLocationInfo(start, end) )
|
if ( ! Obj::SetLocationInfo(start, end) )
|
||||||
|
@ -1866,6 +1872,13 @@ AssertStmt::AssertStmt(ExprPtr arg_cond, ExprPtr arg_msg)
|
||||||
|
|
||||||
if ( msg && ! IsString(msg->GetType()->Tag()) )
|
if ( msg && ! IsString(msg->GetType()->Tag()) )
|
||||||
msg->Error("message must be string");
|
msg->Error("message must be string");
|
||||||
|
|
||||||
|
zeek::ODesc desc;
|
||||||
|
desc.SetShort(true);
|
||||||
|
desc.SetQuotes(true);
|
||||||
|
cond->Describe(&desc);
|
||||||
|
|
||||||
|
cond_desc = desc.Description();
|
||||||
}
|
}
|
||||||
|
|
||||||
ValPtr AssertStmt::Exec(Frame* f, StmtFlowType& flow)
|
ValPtr AssertStmt::Exec(Frame* f, StmtFlowType& flow)
|
||||||
|
@ -1873,26 +1886,14 @@ ValPtr AssertStmt::Exec(Frame* f, StmtFlowType& flow)
|
||||||
RegisterAccess();
|
RegisterAccess();
|
||||||
flow = FLOW_NEXT;
|
flow = FLOW_NEXT;
|
||||||
|
|
||||||
static auto assertion_failure_hook = id::find_func("assertion_failure");
|
|
||||||
static auto assertion_result_hook = id::find_func("assertion_result");
|
static auto assertion_result_hook = id::find_func("assertion_result");
|
||||||
|
|
||||||
bool run_result_hook = assertion_result_hook && assertion_result_hook->HasEnabledBodies();
|
bool run_result_hook = assertion_result_hook && assertion_result_hook->HasEnabledBodies();
|
||||||
bool run_failure_hook = assertion_failure_hook && assertion_failure_hook->HasEnabledBodies();
|
|
||||||
|
|
||||||
auto assert_result = cond->Eval(f)->AsBool();
|
auto assert_result = cond->Eval(f)->AsBool();
|
||||||
|
|
||||||
if ( assert_result && ! run_result_hook )
|
if ( ! cond->Eval(f)->AsBool() || run_result_hook )
|
||||||
return Val::nil;
|
{
|
||||||
|
|
||||||
// Textual representation of cond from the AST.
|
|
||||||
static zeek::ODesc desc;
|
|
||||||
desc.Clear();
|
|
||||||
desc.SetShort(true);
|
|
||||||
desc.SetQuotes(true);
|
|
||||||
cond->Describe(&desc);
|
|
||||||
auto cond_val = zeek::make_intrusive<zeek::StringVal>(desc.Len(), (const char*)desc.Bytes());
|
|
||||||
|
|
||||||
zeek::StringValPtr msg_val = zeek::val_mgr->EmptyString();
|
zeek::StringValPtr msg_val = zeek::val_mgr->EmptyString();
|
||||||
|
|
||||||
if ( msg )
|
if ( msg )
|
||||||
{
|
{
|
||||||
// Eval() may fail if expression assumes assert
|
// Eval() may fail if expression assumes assert
|
||||||
|
@ -1904,50 +1905,22 @@ ValPtr AssertStmt::Exec(Frame* f, StmtFlowType& flow)
|
||||||
}
|
}
|
||||||
catch ( InterpreterException& e )
|
catch ( InterpreterException& e )
|
||||||
{
|
{
|
||||||
|
static ODesc desc;
|
||||||
desc.Clear();
|
desc.Clear();
|
||||||
|
desc.SetShort(true);
|
||||||
|
desc.SetQuotes(true);
|
||||||
desc.Add("<error eval ");
|
desc.Add("<error eval ");
|
||||||
msg->Describe(&desc);
|
msg->Describe(&desc);
|
||||||
desc.Add(">");
|
desc.Add(">");
|
||||||
msg_val = zeek::make_intrusive<zeek::StringVal>(desc.Len(), (const char*)desc.Bytes());
|
msg_val = zeek::make_intrusive<zeek::StringVal>(desc.Len(),
|
||||||
|
(const char*)desc.Bytes());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VectorValPtr bt = nullptr;
|
report_assert(assert_result, cond_desc, msg_val, GetLocationInfo());
|
||||||
if ( run_result_hook || run_failure_hook )
|
|
||||||
{
|
|
||||||
bt = get_current_script_backtrace();
|
|
||||||
auto assert_elem = make_backtrace_element("assert", MakeEmptyCallArgumentVector(),
|
|
||||||
GetLocationInfo());
|
|
||||||
bt->Insert(0, std::move(assert_elem));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Breaking from either the assertion_failure() or assertion_result()
|
|
||||||
// hook can be used to suppress the default log message.
|
|
||||||
bool report_error = true;
|
|
||||||
|
|
||||||
if ( run_result_hook )
|
|
||||||
report_error &= assertion_result_hook
|
|
||||||
->Invoke(zeek::val_mgr->Bool(assert_result), cond_val, msg_val, bt)
|
|
||||||
->AsBool();
|
|
||||||
|
|
||||||
if ( assert_result )
|
|
||||||
return Val::nil;
|
return Val::nil;
|
||||||
|
|
||||||
if ( run_failure_hook )
|
|
||||||
report_error &= assertion_failure_hook->Invoke(cond_val, msg_val, bt)->AsBool();
|
|
||||||
|
|
||||||
if ( report_error )
|
|
||||||
{
|
|
||||||
std::string reporter_msg = util::fmt("assertion failure: %s", cond_val->CheckString());
|
|
||||||
if ( msg_val->Len() > 0 )
|
|
||||||
reporter_msg += util::fmt(" (%s)", msg_val->CheckString());
|
|
||||||
|
|
||||||
reporter->PushLocation(GetLocationInfo());
|
|
||||||
reporter->Error("%s", reporter_msg.c_str());
|
|
||||||
reporter->PopLocation();
|
|
||||||
}
|
|
||||||
|
|
||||||
throw InterpreterException();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AssertStmt::StmtDescribe(ODesc* d) const
|
void AssertStmt::StmtDescribe(ODesc* d) const
|
||||||
|
@ -1992,6 +1965,59 @@ TraversalCode AssertStmt::Traverse(TraversalCallback* cb) const
|
||||||
HANDLE_TC_STMT_POST(tc);
|
HANDLE_TC_STMT_POST(tc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class AssertException : public InterpreterException
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
AssertException() { }
|
||||||
|
};
|
||||||
|
|
||||||
|
void report_assert(bool cond, std::string_view cond_desc, StringValPtr msg_val, const Location* loc)
|
||||||
|
{
|
||||||
|
static auto assertion_failure_hook = id::find_func("assertion_failure");
|
||||||
|
static auto assertion_result_hook = id::find_func("assertion_result");
|
||||||
|
|
||||||
|
bool run_result_hook = assertion_result_hook && assertion_result_hook->HasEnabledBodies();
|
||||||
|
bool run_failure_hook = assertion_failure_hook && assertion_failure_hook->HasEnabledBodies();
|
||||||
|
|
||||||
|
auto cond_val = zeek::make_intrusive<zeek::StringVal>(cond_desc);
|
||||||
|
|
||||||
|
VectorValPtr bt = nullptr;
|
||||||
|
if ( run_result_hook || run_failure_hook )
|
||||||
|
{
|
||||||
|
bt = get_current_script_backtrace();
|
||||||
|
auto assert_elem = make_backtrace_element("assert", MakeEmptyCallArgumentVector(), loc);
|
||||||
|
bt->Insert(0, std::move(assert_elem));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Breaking from either the assertion_failure() or assertion_result()
|
||||||
|
// hook can be used to suppress the default log message.
|
||||||
|
bool report_error = true;
|
||||||
|
|
||||||
|
if ( run_result_hook )
|
||||||
|
report_error &= assertion_result_hook
|
||||||
|
->Invoke(zeek::val_mgr->Bool(cond), cond_val, msg_val, bt)
|
||||||
|
->AsBool();
|
||||||
|
|
||||||
|
if ( cond )
|
||||||
|
return;
|
||||||
|
|
||||||
|
if ( run_failure_hook )
|
||||||
|
report_error &= assertion_failure_hook->Invoke(cond_val, msg_val, bt)->AsBool();
|
||||||
|
|
||||||
|
if ( report_error )
|
||||||
|
{
|
||||||
|
std::string reporter_msg = util::fmt("assertion failure: %s", cond_val->CheckString());
|
||||||
|
if ( msg_val->Len() > 0 )
|
||||||
|
reporter_msg += util::fmt(" (%s)", msg_val->CheckString());
|
||||||
|
|
||||||
|
reporter->PushLocation(loc);
|
||||||
|
reporter->Error("%s", reporter_msg.c_str());
|
||||||
|
reporter->PopLocation();
|
||||||
|
}
|
||||||
|
|
||||||
|
throw AssertException();
|
||||||
|
}
|
||||||
|
|
||||||
WhenInfo::WhenInfo(ExprPtr arg_cond, FuncType::CaptureList* arg_cl, bool arg_is_return)
|
WhenInfo::WhenInfo(ExprPtr arg_cond, FuncType::CaptureList* arg_cl, bool arg_is_return)
|
||||||
: cond(std::move(arg_cond)), cl(arg_cl), is_return(arg_is_return)
|
: cond(std::move(arg_cond)), cl(arg_cl), is_return(arg_is_return)
|
||||||
{
|
{
|
||||||
|
@ -2079,7 +2105,7 @@ void WhenInfo::BuildProfile()
|
||||||
if ( ! is_present )
|
if ( ! is_present )
|
||||||
{
|
{
|
||||||
IDPtr wl_ptr = {NewRef{}, const_cast<ID*>(wl)};
|
IDPtr wl_ptr = {NewRef{}, const_cast<ID*>(wl)};
|
||||||
cl->emplace_back(wl_ptr, false);
|
cl->emplace_back(std::move(wl_ptr), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// In addition, don't treat them as external locals that
|
// In addition, don't treat them as external locals that
|
||||||
|
|
14
src/Stmt.h
14
src/Stmt.h
|
@ -547,6 +547,10 @@ public:
|
||||||
|
|
||||||
ValPtr Exec(Frame* f, StmtFlowType& flow) override;
|
ValPtr Exec(Frame* f, StmtFlowType& flow) override;
|
||||||
|
|
||||||
|
const auto& Cond() const { return cond; }
|
||||||
|
const auto& CondDesc() const { return cond_desc; }
|
||||||
|
const auto& Msg() const { return msg; }
|
||||||
|
|
||||||
void StmtDescribe(ODesc* d) const override;
|
void StmtDescribe(ODesc* d) const override;
|
||||||
|
|
||||||
TraversalCode Traverse(TraversalCallback* cb) const override;
|
TraversalCode Traverse(TraversalCallback* cb) const override;
|
||||||
|
@ -559,9 +563,17 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ExprPtr cond;
|
ExprPtr cond;
|
||||||
|
std::string cond_desc;
|
||||||
ExprPtr msg;
|
ExprPtr msg;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Helper function for reporting on asserts that either failed, or should
|
||||||
|
// be processed regardless due to the presence of a "assertion_result" hook.
|
||||||
|
//
|
||||||
|
// If "cond" is false, throws an InterpreterException after reporting.
|
||||||
|
extern void report_assert(bool cond, std::string_view cond_desc, StringValPtr msg_val,
|
||||||
|
const Location* loc);
|
||||||
|
|
||||||
// A helper class for tracking all of the information associated with
|
// A helper class for tracking all of the information associated with
|
||||||
// a "when" statement, and constructing the necessary components in support
|
// a "when" statement, and constructing the necessary components in support
|
||||||
// of lambda-style captures.
|
// of lambda-style captures.
|
||||||
|
@ -647,7 +659,7 @@ private:
|
||||||
StmtPtr s;
|
StmtPtr s;
|
||||||
StmtPtr timeout_s;
|
StmtPtr timeout_s;
|
||||||
ExprPtr timeout;
|
ExprPtr timeout;
|
||||||
FuncType::CaptureList* cl;
|
FuncType::CaptureList* cl = nullptr;
|
||||||
|
|
||||||
bool is_return = false;
|
bool is_return = false;
|
||||||
|
|
||||||
|
|
|
@ -1935,7 +1935,7 @@ stmt:
|
||||||
| when_clause
|
| when_clause
|
||||||
{
|
{
|
||||||
std::shared_ptr<WhenInfo> wi($1);
|
std::shared_ptr<WhenInfo> wi($1);
|
||||||
$$ = new WhenStmt(wi);
|
$$ = new WhenStmt(std::move(wi));
|
||||||
script_coverage_mgr.AddStmt($$);
|
script_coverage_mgr.AddStmt($$);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -720,6 +720,8 @@ private:
|
||||||
void GenForOverVector(const ExprPtr& tbl, const IDPtr& value_var, const IDPList* loop_vars);
|
void GenForOverVector(const ExprPtr& tbl, const IDPtr& value_var, const IDPList* loop_vars);
|
||||||
void GenForOverString(const ExprPtr& str, const IDPList* loop_vars);
|
void GenForOverString(const ExprPtr& str, const IDPList* loop_vars);
|
||||||
|
|
||||||
|
void GenAssertStmt(const AssertStmt* a);
|
||||||
|
|
||||||
// Nested level of loops/switches for which "break"'s should be
|
// Nested level of loops/switches for which "break"'s should be
|
||||||
// C++ breaks rather than a "hook" break.
|
// C++ breaks rather than a "hook" break.
|
||||||
int break_level = 0;
|
int break_level = 0;
|
||||||
|
@ -830,7 +832,7 @@ private:
|
||||||
|
|
||||||
// If "all_deep" is true, it means make all of the captures
|
// If "all_deep" is true, it means make all of the captures
|
||||||
// deep copies, not just the ones that were explicitly marked
|
// deep copies, not just the ones that were explicitly marked
|
||||||
// as deep copies. That functionality is used to supporting
|
// as deep copies. That functionality is used to support
|
||||||
// Clone() methods; it's not needed when creating a new lambda
|
// Clone() methods; it's not needed when creating a new lambda
|
||||||
// instance.
|
// instance.
|
||||||
std::string GenLambdaClone(const LambdaExpr* l, bool all_deep);
|
std::string GenLambdaClone(const LambdaExpr* l, bool all_deep);
|
||||||
|
@ -928,7 +930,7 @@ private:
|
||||||
// an IntrusivePtr to such a type.
|
// an IntrusivePtr to such a type.
|
||||||
const char* IntrusiveVal(const TypePtr& t);
|
const char* IntrusiveVal(const TypePtr& t);
|
||||||
|
|
||||||
// Maps types to indices in the global "types__CPP" array.
|
// Maps types to indices in the global "CPP__Type__" array.
|
||||||
CPPTracker<Type> types = {"types", true};
|
CPPTracker<Type> types = {"types", true};
|
||||||
|
|
||||||
// Used to prevent analysis of mutually-referring types from
|
// Used to prevent analysis of mutually-referring types from
|
||||||
|
|
|
@ -77,8 +77,9 @@ void CPPCompile::Compile(bool report_uncompilable)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( is_when_lambda(f) )
|
if ( is_lambda(f) || is_when_lambda(f) )
|
||||||
{
|
{
|
||||||
|
// We deal with these separately.
|
||||||
func.SetSkip(true);
|
func.SetSkip(true);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -123,8 +124,6 @@ void CPPCompile::Compile(bool report_uncompilable)
|
||||||
types.AddKey(tp, pfs.HashType(t));
|
types.AddKey(tp, pfs.HashType(t));
|
||||||
}
|
}
|
||||||
|
|
||||||
Emit("TypePtr types__CPP[%s];", Fmt(static_cast<int>(types.DistinctKeys().size())));
|
|
||||||
|
|
||||||
NL();
|
NL();
|
||||||
|
|
||||||
for ( auto& g : pfs.AllGlobals() )
|
for ( auto& g : pfs.AllGlobals() )
|
||||||
|
|
|
@ -78,6 +78,10 @@ void CPPCompile::GenStmt(const Stmt* s)
|
||||||
GenForStmt(s->AsForStmt());
|
GenForStmt(s->AsForStmt());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case STMT_ASSERT:
|
||||||
|
GenAssertStmt(s->AsAssertStmt());
|
||||||
|
break;
|
||||||
|
|
||||||
case STMT_NEXT:
|
case STMT_NEXT:
|
||||||
Emit("continue;");
|
Emit("continue;");
|
||||||
break;
|
break;
|
||||||
|
@ -89,6 +93,9 @@ void CPPCompile::GenStmt(const Stmt* s)
|
||||||
Emit("return false;");
|
Emit("return false;");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case STMT_FALLTHROUGH:
|
||||||
|
break;
|
||||||
|
|
||||||
case STMT_PRINT:
|
case STMT_PRINT:
|
||||||
{
|
{
|
||||||
auto el = static_cast<const ExprListStmt*>(s)->ExprList();
|
auto el = static_cast<const ExprListStmt*>(s)->ExprList();
|
||||||
|
@ -96,9 +103,6 @@ void CPPCompile::GenStmt(const Stmt* s)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case STMT_FALLTHROUGH:
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
reporter->InternalError("bad statement type in CPPCompile::GenStmt");
|
reporter->InternalError("bad statement type in CPPCompile::GenStmt");
|
||||||
}
|
}
|
||||||
|
@ -567,4 +571,33 @@ void CPPCompile::GenForOverString(const ExprPtr& str, const IDPList* loop_vars)
|
||||||
Emit("%s = std::move(sv__CPP);", IDName(lv0));
|
Emit("%s = std::move(sv__CPP);", IDName(lv0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CPPCompile::GenAssertStmt(const AssertStmt* a)
|
||||||
|
{
|
||||||
|
auto& cond = a->Cond();
|
||||||
|
auto& msg = a->Msg();
|
||||||
|
|
||||||
|
Emit("{ // begin a new scope for internal \"assert\" variables");
|
||||||
|
Emit("static auto assertion_result_hook = id::find_func(\"assertion_result\");");
|
||||||
|
Emit("bool run_result_hook = assertion_result_hook && "
|
||||||
|
"assertion_result_hook->HasEnabledBodies();");
|
||||||
|
Emit("auto assert_result = %s;", GenExpr(cond, GEN_NATIVE));
|
||||||
|
Emit("if ( ! assert_result || run_result_hook )");
|
||||||
|
|
||||||
|
StartBlock();
|
||||||
|
if ( msg )
|
||||||
|
Emit("auto msg_val = %s;", GenExpr(msg, GEN_VAL_PTR));
|
||||||
|
else
|
||||||
|
Emit("auto msg_val = zeek::val_mgr->EmptyString();");
|
||||||
|
|
||||||
|
auto loc = a->GetLocationInfo();
|
||||||
|
Emit("static Location loc(\"%s\", %s, %s, %s, %s);", loc->filename,
|
||||||
|
std::to_string(loc->first_line), std::to_string(loc->last_line),
|
||||||
|
std::to_string(loc->first_column), std::to_string(loc->last_column));
|
||||||
|
Emit("report_assert(assert_result, \"%s\", msg_val, &loc);",
|
||||||
|
CPPEscape(a->CondDesc().c_str()).c_str());
|
||||||
|
EndBlock();
|
||||||
|
|
||||||
|
Emit("} // end of \"assert\" scope");
|
||||||
|
}
|
||||||
|
|
||||||
} // zeek::detail
|
} // zeek::detail
|
||||||
|
|
|
@ -17,6 +17,15 @@ The maintenance workflow:
|
||||||
ninja
|
ninja
|
||||||
src/zeek -O use-C++ -r some.pcap
|
src/zeek -O use-C++ -r some.pcap
|
||||||
|
|
||||||
|
and that it can compile them standalone:
|
||||||
|
|
||||||
|
rm CPP-gen.cc
|
||||||
|
ninja
|
||||||
|
echo | src/zeek -O gen-standalone-C++
|
||||||
|
ninja
|
||||||
|
rm CPP-gen.cc
|
||||||
|
ninja
|
||||||
|
|
||||||
Do this first because if it can't, you'll be making changes to the
|
Do this first because if it can't, you'll be making changes to the
|
||||||
compiler that you'll want to subsequent run against the test suite,
|
compiler that you'll want to subsequent run against the test suite,
|
||||||
per the following.
|
per the following.
|
||||||
|
@ -62,11 +71,7 @@ The maintenance workflow:
|
||||||
(which is Baseline.cpp).
|
(which is Baseline.cpp).
|
||||||
|
|
||||||
FYI:
|
FYI:
|
||||||
There are two tests that in the past have demonstrated possible
|
Tests that have demonstrated variations/failures due to presumed
|
||||||
variations due to presumed race conditions:
|
race conditions:
|
||||||
|
|
||||||
../testing/btest/scripts/base/utils/active-http.test
|
../testing/btest/scripts/base/utils/active-http.test
|
||||||
../testing/btest/supervisor/revive-leaf.zeek
|
|
||||||
|
|
||||||
These haven't shown up in a while, as of May 2023, so we can remove
|
|
||||||
the above if they continue to not show up.
|
|
||||||
|
|
|
@ -309,7 +309,7 @@ StmtPtr Expr::ReduceToSingletons(Reducer* c)
|
||||||
if ( op3 && ! op3->IsSingleton(c) )
|
if ( op3 && ! op3->IsSingleton(c) )
|
||||||
SetOp3(op3->ReduceToSingleton(c, red3_stmt));
|
SetOp3(op3->ReduceToSingleton(c, red3_stmt));
|
||||||
|
|
||||||
return MergeStmts(red1_stmt, red2_stmt, red3_stmt);
|
return MergeStmts(std::move(red1_stmt), std::move(red2_stmt), std::move(red3_stmt));
|
||||||
}
|
}
|
||||||
|
|
||||||
ExprPtr Expr::ReduceToConditional(Reducer* c, StmtPtr& red_stmt)
|
ExprPtr Expr::ReduceToConditional(Reducer* c, StmtPtr& red_stmt)
|
||||||
|
@ -354,7 +354,7 @@ ExprPtr Expr::ReduceToConditional(Reducer* c, StmtPtr& red_stmt)
|
||||||
{
|
{
|
||||||
auto red2_stmt = ReduceToSingletons(c);
|
auto red2_stmt = ReduceToSingletons(c);
|
||||||
auto res = ReduceToConditional(c, red_stmt);
|
auto res = ReduceToConditional(c, red_stmt);
|
||||||
red_stmt = MergeStmts(red2_stmt, red_stmt);
|
red_stmt = MergeStmts(std::move(red2_stmt), red_stmt);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -611,7 +611,7 @@ ExprPtr BinaryExpr::Reduce(Reducer* c, StmtPtr& red_stmt)
|
||||||
if ( ! op2->IsSingleton(c) )
|
if ( ! op2->IsSingleton(c) )
|
||||||
op2 = op2->ReduceToSingleton(c, red2_stmt);
|
op2 = op2->ReduceToSingleton(c, red2_stmt);
|
||||||
|
|
||||||
red_stmt = MergeStmts(red_stmt, red2_stmt);
|
red_stmt = MergeStmts(red_stmt, std::move(red2_stmt));
|
||||||
|
|
||||||
auto op1_fold_val = op1->FoldVal();
|
auto op1_fold_val = op1->FoldVal();
|
||||||
auto op2_fold_val = op2->FoldVal();
|
auto op2_fold_val = op2->FoldVal();
|
||||||
|
@ -1528,7 +1528,8 @@ StmtPtr CondExpr::ReduceToSingletons(Reducer* c)
|
||||||
if ( ! red3_stmt )
|
if ( ! red3_stmt )
|
||||||
red3_stmt = make_intrusive<NullStmt>();
|
red3_stmt = make_intrusive<NullStmt>();
|
||||||
|
|
||||||
if_else = make_intrusive<IfStmt>(op1->Duplicate(), red2_stmt, red3_stmt);
|
if_else = make_intrusive<IfStmt>(op1->Duplicate(), std::move(red2_stmt),
|
||||||
|
std::move(red3_stmt));
|
||||||
}
|
}
|
||||||
|
|
||||||
return MergeStmts(red1_stmt, if_else);
|
return MergeStmts(red1_stmt, if_else);
|
||||||
|
@ -1897,7 +1898,7 @@ StmtPtr IndexExpr::ReduceToSingletons(Reducer* c)
|
||||||
|
|
||||||
StmtPtr red2_stmt = op2->ReduceToSingletons(c);
|
StmtPtr red2_stmt = op2->ReduceToSingletons(c);
|
||||||
|
|
||||||
return MergeStmts(red1_stmt, red2_stmt);
|
return MergeStmts(red1_stmt, std::move(red2_stmt));
|
||||||
}
|
}
|
||||||
|
|
||||||
ExprPtr IndexExprWhen::Duplicate()
|
ExprPtr IndexExprWhen::Duplicate()
|
||||||
|
@ -1927,7 +1928,7 @@ ExprPtr HasFieldExpr::Reduce(Reducer* c, StmtPtr& red_stmt)
|
||||||
if ( ! op->GetType<RecordType>()->FieldHasAttr(field, ATTR_OPTIONAL) )
|
if ( ! op->GetType<RecordType>()->FieldHasAttr(field, ATTR_OPTIONAL) )
|
||||||
{
|
{
|
||||||
auto true_constant = make_intrusive<ConstExpr>(val_mgr->True());
|
auto true_constant = make_intrusive<ConstExpr>(val_mgr->True());
|
||||||
return TransformMe(true_constant, c, red_stmt);
|
return TransformMe(std::move(true_constant), c, red_stmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
return UnaryExpr::Reduce(c, red_stmt);
|
return UnaryExpr::Reduce(c, red_stmt);
|
||||||
|
@ -2334,7 +2335,7 @@ ExprPtr ScheduleExpr::Reduce(Reducer* c, StmtPtr& red_stmt)
|
||||||
// We assume that EventExpr won't transform itself fundamentally.
|
// We assume that EventExpr won't transform itself fundamentally.
|
||||||
(void)event->Reduce(c, red2_stmt);
|
(void)event->Reduce(c, red2_stmt);
|
||||||
|
|
||||||
red_stmt = MergeStmts(red_stmt, red2_stmt);
|
red_stmt = MergeStmts(red_stmt, std::move(red2_stmt));
|
||||||
|
|
||||||
return ThisPtr();
|
return ThisPtr();
|
||||||
}
|
}
|
||||||
|
@ -2419,7 +2420,7 @@ ExprPtr CallExpr::Reduce(Reducer* c, StmtPtr& red_stmt)
|
||||||
// ### could check here for (1) pure function, and (2) all
|
// ### could check here for (1) pure function, and (2) all
|
||||||
// arguments constants, and call it to fold right now.
|
// arguments constants, and call it to fold right now.
|
||||||
|
|
||||||
red_stmt = MergeStmts(red_stmt, red2_stmt);
|
red_stmt = MergeStmts(red_stmt, std::move(red2_stmt));
|
||||||
|
|
||||||
if ( GetType()->Tag() == TYPE_VOID )
|
if ( GetType()->Tag() == TYPE_VOID )
|
||||||
return ThisPtr();
|
return ThisPtr();
|
||||||
|
|
|
@ -58,6 +58,11 @@ void analyze_when_lambda(LambdaExpr* l)
|
||||||
when_lambdas.insert(l->PrimaryFunc().get());
|
when_lambdas.insert(l->PrimaryFunc().get());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool is_lambda(const ScriptFunc* f)
|
||||||
|
{
|
||||||
|
return lambdas.count(f) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
bool is_when_lambda(const ScriptFunc* f)
|
bool is_when_lambda(const ScriptFunc* f)
|
||||||
{
|
{
|
||||||
return when_lambdas.count(f) > 0;
|
return when_lambdas.count(f) > 0;
|
||||||
|
|
|
@ -174,7 +174,8 @@ extern void analyze_lambda(LambdaExpr* f);
|
||||||
// has already been called.
|
// has already been called.
|
||||||
extern void analyze_when_lambda(LambdaExpr* f);
|
extern void analyze_when_lambda(LambdaExpr* f);
|
||||||
|
|
||||||
// Whether a given script function is a "when" lambda.
|
// Whether a given script function is a lambda or (separately) a "when" lambda.
|
||||||
|
extern bool is_lambda(const ScriptFunc* f);
|
||||||
extern bool is_when_lambda(const ScriptFunc* f);
|
extern bool is_when_lambda(const ScriptFunc* f);
|
||||||
|
|
||||||
// Analyze the given top-level statement(s) for optimization. Returns
|
// Analyze the given top-level statement(s) for optimization. Returns
|
||||||
|
|
|
@ -1012,7 +1012,7 @@ StmtPtr WhenStmt::DoReduce(Reducer* c)
|
||||||
if ( red_e_stmt )
|
if ( red_e_stmt )
|
||||||
{
|
{
|
||||||
auto s = make_intrusive<StmtList>(red_e_stmt, ThisPtr());
|
auto s = make_intrusive<StmtList>(red_e_stmt, ThisPtr());
|
||||||
return TransformMe(s, c);
|
return TransformMe(std::move(s), c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -752,7 +752,7 @@ macro EvalVal2InTableCore(op1, op2)
|
||||||
ListValPtr lvp = {NewRef{}, &lv};
|
ListValPtr lvp = {NewRef{}, &lv};
|
||||||
|
|
||||||
macro EvalVal2InTableAssignCore(slot)
|
macro EvalVal2InTableAssignCore(slot)
|
||||||
frame[z.v1].int_val = frame[z.slot].table_val->Find(lvp) != nullptr;
|
frame[z.v1].int_val = frame[z.slot].table_val->Find(std::move(lvp)) != nullptr;
|
||||||
|
|
||||||
macro EvalVal2InTablePre(op1, op2, op3)
|
macro EvalVal2InTablePre(op1, op2, op3)
|
||||||
auto& tt_ind = frame[z.op3].table_val->GetType()->AsTableType()->GetIndexTypes();
|
auto& tt_ind = frame[z.op3].table_val->GetType()->AsTableType()->GetIndexTypes();
|
||||||
|
@ -838,12 +838,12 @@ eval auto op1 = z.c.ToVal(z.t);
|
||||||
internal-op List-Is-In-Table
|
internal-op List-Is-In-Table
|
||||||
type VV
|
type VV
|
||||||
eval auto op1 = z.aux->ToListVal(frame);
|
eval auto op1 = z.aux->ToListVal(frame);
|
||||||
frame[z.v1].int_val = frame[z.v2].table_val->Find(op1) != nullptr;
|
frame[z.v1].int_val = frame[z.v2].table_val->Find(std::move(op1)) != nullptr;
|
||||||
|
|
||||||
internal-op List-Is-In-Table
|
internal-op List-Is-In-Table
|
||||||
type VC
|
type VC
|
||||||
eval auto op1 = z.aux->ToListVal(frame);
|
eval auto op1 = z.aux->ToListVal(frame);
|
||||||
frame[z.v1].int_val = z.c.table_val->Find(op1) != nullptr;
|
frame[z.v1].int_val = z.c.table_val->Find(std::move(op1)) != nullptr;
|
||||||
|
|
||||||
internal-op Val-Is-In-Vector
|
internal-op Val-Is-In-Vector
|
||||||
type VVV
|
type VVV
|
||||||
|
@ -918,7 +918,7 @@ macro EvalIndexVecBoolSelect(op1, op2)
|
||||||
auto vt = cast_intrusive<VectorType>(z.t);
|
auto vt = cast_intrusive<VectorType>(z.t);
|
||||||
auto v2 = op1.vector_val;
|
auto v2 = op1.vector_val;
|
||||||
auto v3 = op2.vector_val;
|
auto v3 = op2.vector_val;
|
||||||
auto v = vector_bool_select(vt, v2, v3);
|
auto v = vector_bool_select(std::move(vt), v2, v3);
|
||||||
Unref(frame[z.v1].vector_val);
|
Unref(frame[z.v1].vector_val);
|
||||||
frame[z.v1].vector_val = v.release();
|
frame[z.v1].vector_val = v.release();
|
||||||
|
|
||||||
|
@ -936,7 +936,7 @@ macro EvalIndexVecIntSelect(op1, op2)
|
||||||
auto vt = cast_intrusive<VectorType>(z.t);
|
auto vt = cast_intrusive<VectorType>(z.t);
|
||||||
auto v2 = op1.vector_val;
|
auto v2 = op1.vector_val;
|
||||||
auto v3 = op2.vector_val;
|
auto v3 = op2.vector_val;
|
||||||
auto v = vector_int_select(vt, v2, v3);
|
auto v = vector_int_select(std::move(vt), v2, v3);
|
||||||
Unref(frame[z.v1].vector_val);
|
Unref(frame[z.v1].vector_val);
|
||||||
frame[z.v1].vector_val = v.release();
|
frame[z.v1].vector_val = v.release();
|
||||||
|
|
||||||
|
@ -1136,7 +1136,7 @@ type VV
|
||||||
op1-read
|
op1-read
|
||||||
eval auto& tbl = frame[z.v1].table_val;
|
eval auto& tbl = frame[z.v1].table_val;
|
||||||
auto lambda = frame[z.v2].ToVal(z.t);
|
auto lambda = frame[z.v2].ToVal(z.t);
|
||||||
tbl->InitDefaultVal(lambda);
|
tbl->InitDefaultVal(std::move(lambda));
|
||||||
|
|
||||||
direct-unary-op Set-Constructor ConstructSet
|
direct-unary-op Set-Constructor ConstructSet
|
||||||
|
|
||||||
|
@ -1294,7 +1294,7 @@ internal-op Record-Coerce
|
||||||
type VV
|
type VV
|
||||||
eval auto rt = cast_intrusive<RecordType>(z.t);
|
eval auto rt = cast_intrusive<RecordType>(z.t);
|
||||||
auto v = frame[z.v2].record_val;
|
auto v = frame[z.v2].record_val;
|
||||||
auto to_r = coerce_to_record(rt, v, z.aux->map);
|
auto to_r = coerce_to_record(std::move(rt), v, z.aux->map);
|
||||||
Unref(frame[z.v1].record_val);
|
Unref(frame[z.v1].record_val);
|
||||||
frame[z.v1].record_val = to_r.release();
|
frame[z.v1].record_val = to_r.release();
|
||||||
|
|
||||||
|
@ -1426,7 +1426,7 @@ eval ValPtr vec = {NewRef{}, frame[z.v1].vector_val};
|
||||||
auto slice = z.aux->ToListVal(frame);
|
auto slice = z.aux->ToListVal(frame);
|
||||||
ValPtr vals = {NewRef{}, frame[z.v2].vector_val};
|
ValPtr vals = {NewRef{}, frame[z.v2].vector_val};
|
||||||
bool iterators_invalidated;
|
bool iterators_invalidated;
|
||||||
auto error = assign_to_index(vec, slice, vals, iterators_invalidated);
|
auto error = assign_to_index(std::move(vec), std::move(slice), std::move(vals), iterators_invalidated);
|
||||||
if ( error )
|
if ( error )
|
||||||
ZAM_run_time_error(z.loc, error);
|
ZAM_run_time_error(z.loc, error);
|
||||||
if ( iterators_invalidated )
|
if ( iterators_invalidated )
|
||||||
|
@ -1442,7 +1442,7 @@ macro EvalTableElemAssign(value)
|
||||||
auto indices = z.aux->ToListVal(frame);
|
auto indices = z.aux->ToListVal(frame);
|
||||||
auto val = value.ToVal(z.t);
|
auto val = value.ToVal(z.t);
|
||||||
bool iterators_invalidated = false;
|
bool iterators_invalidated = false;
|
||||||
frame[z.v1].table_val->Assign(indices, val, true, &iterators_invalidated);
|
frame[z.v1].table_val->Assign(std::move(indices), std::move(val), true, &iterators_invalidated);
|
||||||
if ( iterators_invalidated )
|
if ( iterators_invalidated )
|
||||||
ZAM_run_time_warning(z.loc, "possible loop/iterator invalidation");
|
ZAM_run_time_warning(z.loc, "possible loop/iterator invalidation");
|
||||||
|
|
||||||
|
@ -1999,7 +1999,7 @@ method-post z.aux = v->aux;
|
||||||
macro EvalAddStmt(ind)
|
macro EvalAddStmt(ind)
|
||||||
auto index = ind;
|
auto index = ind;
|
||||||
bool iterators_invalidated = false;
|
bool iterators_invalidated = false;
|
||||||
frame[z.v1].table_val->Assign(index, nullptr, true, &iterators_invalidated);
|
frame[z.v1].table_val->Assign(std::move(index), nullptr, true, &iterators_invalidated);
|
||||||
if ( iterators_invalidated )
|
if ( iterators_invalidated )
|
||||||
ZAM_run_time_warning(z.loc, "possible loop/iterator invalidation");
|
ZAM_run_time_warning(z.loc, "possible loop/iterator invalidation");
|
||||||
|
|
||||||
|
@ -2040,7 +2040,7 @@ eval auto r = new RecordVal(cast_intrusive<RecordType>(z.t));
|
||||||
internal-op Init-Vector
|
internal-op Init-Vector
|
||||||
type V
|
type V
|
||||||
eval auto vt = cast_intrusive<VectorType>(z.t);
|
eval auto vt = cast_intrusive<VectorType>(z.t);
|
||||||
auto vec = new VectorVal(vt);
|
auto vec = new VectorVal(std::move(vt));
|
||||||
Unref(frame[z.v1].vector_val);
|
Unref(frame[z.v1].vector_val);
|
||||||
frame[z.v1].vector_val = vec;
|
frame[z.v1].vector_val = vec;
|
||||||
|
|
||||||
|
@ -2071,7 +2071,7 @@ macro BuildWhen(timeout)
|
||||||
auto wi = aux->wi;
|
auto wi = aux->wi;
|
||||||
FuncPtr func{NewRef{}, frame[z.v1].func_val};
|
FuncPtr func{NewRef{}, frame[z.v1].func_val};
|
||||||
auto lambda = make_intrusive<FuncVal>(func);
|
auto lambda = make_intrusive<FuncVal>(func);
|
||||||
wi->Instantiate(lambda);
|
wi->Instantiate(std::move(lambda));
|
||||||
std::vector<ValPtr> local_aggrs;
|
std::vector<ValPtr> local_aggrs;
|
||||||
for ( int i = 0; i < aux->n; ++i )
|
for ( int i = 0; i < aux->n; ++i )
|
||||||
{
|
{
|
||||||
|
|
|
@ -32,7 +32,9 @@ bool ZAMCompiler::IsCapture(const ID* id) const
|
||||||
|
|
||||||
int ZAMCompiler::CaptureOffset(const ID* id) const
|
int ZAMCompiler::CaptureOffset(const ID* id) const
|
||||||
{
|
{
|
||||||
return pf->CapturesOffsets().find(id)->second;
|
auto id_offset = pf->CapturesOffsets().find(id);
|
||||||
|
ASSERT(id_offset != pf->CapturesOffsets().end());
|
||||||
|
return id_offset->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ZAMCompiler::LoadParam(const ID* id)
|
void ZAMCompiler::LoadParam(const ID* id)
|
||||||
|
|
7
testing/btest/Baseline.cpp/language.assert-misc/out
Normal file
7
testing/btest/Baseline.cpp/language.assert-misc/out
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
|
||||||
|
f, lambda_<505728364269398358>
|
||||||
|
compiled-C++
|
||||||
|
g, lambda_<8496146571423528161>
|
||||||
|
compiled-C++
|
||||||
|
test_function, test_function
|
||||||
|
compiled-C++
|
|
@ -1,9 +1,9 @@
|
||||||
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
|
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
|
||||||
error in <...>/closure-binding-errors.zeek, line 12: a is captured but not used inside lambda (function(){ print no a!})
|
error in <...>/closure-binding-errors.zeek, line 12: a is captured but not used inside lambda (function()[a]{ print no a!})
|
||||||
error in <...>/closure-binding-errors.zeek, line 13: no such local identifier: a2
|
error in <...>/closure-binding-errors.zeek, line 13: no such local identifier: a2
|
||||||
error in <...>/closure-binding-errors.zeek, line 14: b is used inside lambda but not captured (function(){ print b})
|
error in <...>/closure-binding-errors.zeek, line 14: b is used inside lambda but not captured (function()[a]{ print b})
|
||||||
error in <...>/closure-binding-errors.zeek, line 15: a is captured but not used inside lambda (function(){ print b})
|
error in <...>/closure-binding-errors.zeek, line 15: a is captured but not used inside lambda (function()[a, b]{ print b})
|
||||||
error in <...>/closure-binding-errors.zeek, line 16: b listed multiple times in capture (function(){ print b})
|
error in <...>/closure-binding-errors.zeek, line 16: b listed multiple times in capture (function()[b, b]{ print b})
|
||||||
error in <...>/closure-binding-errors.zeek, line 18: cannot specify global in capture: c
|
error in <...>/closure-binding-errors.zeek, line 18: cannot specify global in capture: c
|
||||||
error in <...>/closure-binding-errors.zeek, line 19: cannot specify type in capture: t
|
error in <...>/closure-binding-errors.zeek, line 19: cannot specify type in capture: t
|
||||||
error in <...>/closure-binding-errors.zeek, line 9 and <...>/closure-binding-errors.zeek, line 20: already defined (a)
|
error in <...>/closure-binding-errors.zeek, line 9 and <...>/closure-binding-errors.zeek, line 20: already defined (a)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue