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
|
||||
|
||||
* 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>();
|
||||
SetType(ingr_t);
|
||||
captures = ingr_t->GetCaptures();
|
||||
|
||||
if ( ! CheckCaptures(when_parent) )
|
||||
if ( ! CheckCaptures(std::move(when_parent)) )
|
||||
{
|
||||
SetError();
|
||||
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
|
||||
// by both broker (for transmitting closures) and script optimization
|
||||
// (replacing its AST body with a compiled one).
|
||||
|
@ -4673,19 +4685,17 @@ LambdaExpr::LambdaExpr(FunctionIngredientsPtr arg_ing, IDPList arg_outer_ids, st
|
|||
else
|
||||
my_name = name;
|
||||
|
||||
// Install that in the global_scope
|
||||
lambda_id = install_ID(my_name.c_str(), "", true, false);
|
||||
// Install that in the current scope.
|
||||
lambda_id = install_ID(my_name.c_str(), current_module.c_str(), true, false);
|
||||
|
||||
// Update lamb's name
|
||||
primary_func->SetName(my_name.c_str());
|
||||
primary_func->SetName(lambda_id->Name());
|
||||
|
||||
auto v = make_intrusive<FuncVal>(primary_func);
|
||||
lambda_id->SetVal(std::move(v));
|
||||
lambda_id->SetType(ingr_t);
|
||||
lambda_id->SetConst();
|
||||
|
||||
captures = ingr_t->GetCaptures();
|
||||
|
||||
analyze_lambda(this);
|
||||
}
|
||||
|
||||
|
@ -4714,9 +4724,6 @@ LambdaExpr::LambdaExpr(LambdaExpr* orig) : Expr(EXPR_LAMBDA)
|
|||
|
||||
bool LambdaExpr::CheckCaptures(StmtPtr when_parent)
|
||||
{
|
||||
auto ft = type->AsFuncType();
|
||||
const auto& captures = ft->GetCaptures();
|
||||
|
||||
auto desc = when_parent ? "\"when\" statement" : "lambda";
|
||||
|
||||
if ( ! captures )
|
||||
|
@ -4800,6 +4807,17 @@ void LambdaExpr::BuildName()
|
|||
ODesc 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 ( ;; )
|
||||
{
|
||||
hash128_t h;
|
||||
|
@ -4807,7 +4825,7 @@ void LambdaExpr::BuildName()
|
|||
|
||||
my_name = "lambda_<" + std::to_string(h[0]) + ">";
|
||||
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 )
|
||||
// Just try again to make a unique lambda name.
|
||||
|
@ -4873,6 +4891,9 @@ void LambdaExpr::ExprDescribe(ODesc* d) const
|
|||
if ( &c != &(*captures)[0] )
|
||||
d->AddSP(", ");
|
||||
|
||||
if ( c.IsDeepCopy() )
|
||||
d->AddSP("copy");
|
||||
|
||||
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::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 */,
|
||||
|
@ -588,7 +588,7 @@ void ScriptFunc::CreateCaptures(std::unique_ptr<std::vector<ZVal>> cvec)
|
|||
if ( c_i.IsManaged() )
|
||||
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.
|
||||
auto& t_i = c.Id()->GetType();
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
126
src/Stmt.cc
126
src/Stmt.cc
|
@ -164,6 +164,12 @@ const NullStmt* Stmt::AsNullStmt() const
|
|||
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)
|
||||
{
|
||||
if ( ! Obj::SetLocationInfo(start, end) )
|
||||
|
@ -1866,6 +1872,13 @@ AssertStmt::AssertStmt(ExprPtr arg_cond, ExprPtr arg_msg)
|
|||
|
||||
if ( msg && ! IsString(msg->GetType()->Tag()) )
|
||||
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)
|
||||
|
@ -1873,26 +1886,14 @@ ValPtr AssertStmt::Exec(Frame* f, StmtFlowType& flow)
|
|||
RegisterAccess();
|
||||
flow = FLOW_NEXT;
|
||||
|
||||
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 assert_result = cond->Eval(f)->AsBool();
|
||||
|
||||
if ( assert_result && ! 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());
|
||||
|
||||
if ( ! cond->Eval(f)->AsBool() || run_result_hook )
|
||||
{
|
||||
zeek::StringValPtr msg_val = zeek::val_mgr->EmptyString();
|
||||
|
||||
if ( msg )
|
||||
{
|
||||
// Eval() may fail if expression assumes assert
|
||||
|
@ -1904,50 +1905,22 @@ ValPtr AssertStmt::Exec(Frame* f, StmtFlowType& flow)
|
|||
}
|
||||
catch ( InterpreterException& e )
|
||||
{
|
||||
static ODesc desc;
|
||||
desc.Clear();
|
||||
desc.SetShort(true);
|
||||
desc.SetQuotes(true);
|
||||
desc.Add("<error eval ");
|
||||
msg->Describe(&desc);
|
||||
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;
|
||||
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));
|
||||
report_assert(assert_result, cond_desc, msg_val, GetLocationInfo());
|
||||
}
|
||||
|
||||
// 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;
|
||||
|
||||
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
|
||||
|
@ -1992,6 +1965,59 @@ TraversalCode AssertStmt::Traverse(TraversalCallback* cb) const
|
|||
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)
|
||||
: cond(std::move(arg_cond)), cl(arg_cl), is_return(arg_is_return)
|
||||
{
|
||||
|
@ -2079,7 +2105,7 @@ void WhenInfo::BuildProfile()
|
|||
if ( ! is_present )
|
||||
{
|
||||
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
|
||||
|
|
14
src/Stmt.h
14
src/Stmt.h
|
@ -547,6 +547,10 @@ public:
|
|||
|
||||
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;
|
||||
|
||||
TraversalCode Traverse(TraversalCallback* cb) const override;
|
||||
|
@ -559,9 +563,17 @@ public:
|
|||
|
||||
private:
|
||||
ExprPtr cond;
|
||||
std::string cond_desc;
|
||||
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 "when" statement, and constructing the necessary components in support
|
||||
// of lambda-style captures.
|
||||
|
@ -647,7 +659,7 @@ private:
|
|||
StmtPtr s;
|
||||
StmtPtr timeout_s;
|
||||
ExprPtr timeout;
|
||||
FuncType::CaptureList* cl;
|
||||
FuncType::CaptureList* cl = nullptr;
|
||||
|
||||
bool is_return = false;
|
||||
|
||||
|
|
|
@ -1935,7 +1935,7 @@ stmt:
|
|||
| when_clause
|
||||
{
|
||||
std::shared_ptr<WhenInfo> wi($1);
|
||||
$$ = new WhenStmt(wi);
|
||||
$$ = new WhenStmt(std::move(wi));
|
||||
script_coverage_mgr.AddStmt($$);
|
||||
}
|
||||
|
||||
|
|
|
@ -720,6 +720,8 @@ private:
|
|||
void GenForOverVector(const ExprPtr& tbl, const IDPtr& value_var, 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
|
||||
// C++ breaks rather than a "hook" break.
|
||||
int break_level = 0;
|
||||
|
@ -830,7 +832,7 @@ private:
|
|||
|
||||
// If "all_deep" is true, it means make all of the captures
|
||||
// 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
|
||||
// instance.
|
||||
std::string GenLambdaClone(const LambdaExpr* l, bool all_deep);
|
||||
|
@ -928,7 +930,7 @@ private:
|
|||
// an IntrusivePtr to such a type.
|
||||
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};
|
||||
|
||||
// Used to prevent analysis of mutually-referring types from
|
||||
|
|
|
@ -77,8 +77,9 @@ void CPPCompile::Compile(bool report_uncompilable)
|
|||
continue;
|
||||
}
|
||||
|
||||
if ( is_when_lambda(f) )
|
||||
if ( is_lambda(f) || is_when_lambda(f) )
|
||||
{
|
||||
// We deal with these separately.
|
||||
func.SetSkip(true);
|
||||
continue;
|
||||
}
|
||||
|
@ -123,8 +124,6 @@ void CPPCompile::Compile(bool report_uncompilable)
|
|||
types.AddKey(tp, pfs.HashType(t));
|
||||
}
|
||||
|
||||
Emit("TypePtr types__CPP[%s];", Fmt(static_cast<int>(types.DistinctKeys().size())));
|
||||
|
||||
NL();
|
||||
|
||||
for ( auto& g : pfs.AllGlobals() )
|
||||
|
|
|
@ -78,6 +78,10 @@ void CPPCompile::GenStmt(const Stmt* s)
|
|||
GenForStmt(s->AsForStmt());
|
||||
break;
|
||||
|
||||
case STMT_ASSERT:
|
||||
GenAssertStmt(s->AsAssertStmt());
|
||||
break;
|
||||
|
||||
case STMT_NEXT:
|
||||
Emit("continue;");
|
||||
break;
|
||||
|
@ -89,6 +93,9 @@ void CPPCompile::GenStmt(const Stmt* s)
|
|||
Emit("return false;");
|
||||
break;
|
||||
|
||||
case STMT_FALLTHROUGH:
|
||||
break;
|
||||
|
||||
case STMT_PRINT:
|
||||
{
|
||||
auto el = static_cast<const ExprListStmt*>(s)->ExprList();
|
||||
|
@ -96,9 +103,6 @@ void CPPCompile::GenStmt(const Stmt* s)
|
|||
}
|
||||
break;
|
||||
|
||||
case STMT_FALLTHROUGH:
|
||||
break;
|
||||
|
||||
default:
|
||||
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));
|
||||
}
|
||||
|
||||
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
|
||||
|
|
|
@ -17,6 +17,15 @@ The maintenance workflow:
|
|||
ninja
|
||||
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
|
||||
compiler that you'll want to subsequent run against the test suite,
|
||||
per the following.
|
||||
|
@ -62,11 +71,7 @@ The maintenance workflow:
|
|||
(which is Baseline.cpp).
|
||||
|
||||
FYI:
|
||||
There are two tests that in the past have demonstrated possible
|
||||
variations due to presumed race conditions:
|
||||
Tests that have demonstrated variations/failures due to presumed
|
||||
race conditions:
|
||||
|
||||
../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) )
|
||||
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)
|
||||
|
@ -354,7 +354,7 @@ ExprPtr Expr::ReduceToConditional(Reducer* c, StmtPtr& red_stmt)
|
|||
{
|
||||
auto red2_stmt = ReduceToSingletons(c);
|
||||
auto res = ReduceToConditional(c, red_stmt);
|
||||
red_stmt = MergeStmts(red2_stmt, red_stmt);
|
||||
red_stmt = MergeStmts(std::move(red2_stmt), red_stmt);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -611,7 +611,7 @@ ExprPtr BinaryExpr::Reduce(Reducer* c, StmtPtr& red_stmt)
|
|||
if ( ! op2->IsSingleton(c) )
|
||||
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 op2_fold_val = op2->FoldVal();
|
||||
|
@ -1528,7 +1528,8 @@ StmtPtr CondExpr::ReduceToSingletons(Reducer* c)
|
|||
if ( ! red3_stmt )
|
||||
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);
|
||||
|
@ -1897,7 +1898,7 @@ StmtPtr IndexExpr::ReduceToSingletons(Reducer* c)
|
|||
|
||||
StmtPtr red2_stmt = op2->ReduceToSingletons(c);
|
||||
|
||||
return MergeStmts(red1_stmt, red2_stmt);
|
||||
return MergeStmts(red1_stmt, std::move(red2_stmt));
|
||||
}
|
||||
|
||||
ExprPtr IndexExprWhen::Duplicate()
|
||||
|
@ -1927,7 +1928,7 @@ ExprPtr HasFieldExpr::Reduce(Reducer* c, StmtPtr& red_stmt)
|
|||
if ( ! op->GetType<RecordType>()->FieldHasAttr(field, ATTR_OPTIONAL) )
|
||||
{
|
||||
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);
|
||||
|
@ -2334,7 +2335,7 @@ ExprPtr ScheduleExpr::Reduce(Reducer* c, StmtPtr& red_stmt)
|
|||
// We assume that EventExpr won't transform itself fundamentally.
|
||||
(void)event->Reduce(c, red2_stmt);
|
||||
|
||||
red_stmt = MergeStmts(red_stmt, red2_stmt);
|
||||
red_stmt = MergeStmts(red_stmt, std::move(red2_stmt));
|
||||
|
||||
return ThisPtr();
|
||||
}
|
||||
|
@ -2419,7 +2420,7 @@ ExprPtr CallExpr::Reduce(Reducer* c, StmtPtr& red_stmt)
|
|||
// ### could check here for (1) pure function, and (2) all
|
||||
// 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 )
|
||||
return ThisPtr();
|
||||
|
|
|
@ -58,6 +58,11 @@ void analyze_when_lambda(LambdaExpr* l)
|
|||
when_lambdas.insert(l->PrimaryFunc().get());
|
||||
}
|
||||
|
||||
bool is_lambda(const ScriptFunc* f)
|
||||
{
|
||||
return lambdas.count(f) > 0;
|
||||
}
|
||||
|
||||
bool is_when_lambda(const ScriptFunc* f)
|
||||
{
|
||||
return when_lambdas.count(f) > 0;
|
||||
|
|
|
@ -174,7 +174,8 @@ extern void analyze_lambda(LambdaExpr* f);
|
|||
// has already been called.
|
||||
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);
|
||||
|
||||
// Analyze the given top-level statement(s) for optimization. Returns
|
||||
|
|
|
@ -1012,7 +1012,7 @@ StmtPtr WhenStmt::DoReduce(Reducer* c)
|
|||
if ( red_e_stmt )
|
||||
{
|
||||
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};
|
||||
|
||||
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)
|
||||
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
|
||||
type VV
|
||||
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
|
||||
type VC
|
||||
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
|
||||
type VVV
|
||||
|
@ -918,7 +918,7 @@ macro EvalIndexVecBoolSelect(op1, op2)
|
|||
auto vt = cast_intrusive<VectorType>(z.t);
|
||||
auto v2 = op1.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);
|
||||
frame[z.v1].vector_val = v.release();
|
||||
|
||||
|
@ -936,7 +936,7 @@ macro EvalIndexVecIntSelect(op1, op2)
|
|||
auto vt = cast_intrusive<VectorType>(z.t);
|
||||
auto v2 = op1.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);
|
||||
frame[z.v1].vector_val = v.release();
|
||||
|
||||
|
@ -1136,7 +1136,7 @@ type VV
|
|||
op1-read
|
||||
eval auto& tbl = frame[z.v1].table_val;
|
||||
auto lambda = frame[z.v2].ToVal(z.t);
|
||||
tbl->InitDefaultVal(lambda);
|
||||
tbl->InitDefaultVal(std::move(lambda));
|
||||
|
||||
direct-unary-op Set-Constructor ConstructSet
|
||||
|
||||
|
@ -1294,7 +1294,7 @@ internal-op Record-Coerce
|
|||
type VV
|
||||
eval auto rt = cast_intrusive<RecordType>(z.t);
|
||||
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);
|
||||
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);
|
||||
ValPtr vals = {NewRef{}, frame[z.v2].vector_val};
|
||||
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 )
|
||||
ZAM_run_time_error(z.loc, error);
|
||||
if ( iterators_invalidated )
|
||||
|
@ -1442,7 +1442,7 @@ macro EvalTableElemAssign(value)
|
|||
auto indices = z.aux->ToListVal(frame);
|
||||
auto val = value.ToVal(z.t);
|
||||
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 )
|
||||
ZAM_run_time_warning(z.loc, "possible loop/iterator invalidation");
|
||||
|
||||
|
@ -1999,7 +1999,7 @@ method-post z.aux = v->aux;
|
|||
macro EvalAddStmt(ind)
|
||||
auto index = ind;
|
||||
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 )
|
||||
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
|
||||
type V
|
||||
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);
|
||||
frame[z.v1].vector_val = vec;
|
||||
|
||||
|
@ -2071,7 +2071,7 @@ macro BuildWhen(timeout)
|
|||
auto wi = aux->wi;
|
||||
FuncPtr func{NewRef{}, frame[z.v1].func_val};
|
||||
auto lambda = make_intrusive<FuncVal>(func);
|
||||
wi->Instantiate(lambda);
|
||||
wi->Instantiate(std::move(lambda));
|
||||
std::vector<ValPtr> local_aggrs;
|
||||
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
|
||||
{
|
||||
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)
|
||||
|
|
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.
|
||||
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 14: b is used inside lambda but not captured (function(){ 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 16: b listed multiple times in capture (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()[a, b]{ 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 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)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue