mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 14:48:21 +00:00
GH-725: fix logic for finding a lambda's usage of outer IDs
This commit is contained in:
parent
f032885085
commit
1ca11f11c7
6 changed files with 43 additions and 22 deletions
|
@ -4366,6 +4366,11 @@ LambdaExpr::LambdaExpr(std::unique_ptr<function_ingredients> arg_ing,
|
||||||
id->SetConst();
|
id->SetConst();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Scope* LambdaExpr::GetScope() const
|
||||||
|
{
|
||||||
|
return ingredients->scope.get();
|
||||||
|
}
|
||||||
|
|
||||||
IntrusivePtr<Val> LambdaExpr::Eval(Frame* f) const
|
IntrusivePtr<Val> LambdaExpr::Eval(Frame* f) const
|
||||||
{
|
{
|
||||||
auto lamb = make_intrusive<BroFunc>(
|
auto lamb = make_intrusive<BroFunc>(
|
||||||
|
|
|
@ -61,6 +61,7 @@ extern const char* expr_name(BroExprTag t);
|
||||||
template <class T> class IntrusivePtr;
|
template <class T> class IntrusivePtr;
|
||||||
class Stmt;
|
class Stmt;
|
||||||
class Frame;
|
class Frame;
|
||||||
|
class Scope;
|
||||||
class ListExpr;
|
class ListExpr;
|
||||||
class NameExpr;
|
class NameExpr;
|
||||||
class IndexExpr;
|
class IndexExpr;
|
||||||
|
@ -813,6 +814,8 @@ public:
|
||||||
IntrusivePtr<Val> Eval(Frame* f) const override;
|
IntrusivePtr<Val> Eval(Frame* f) const override;
|
||||||
TraversalCode Traverse(TraversalCallback* cb) const override;
|
TraversalCode Traverse(TraversalCallback* cb) const override;
|
||||||
|
|
||||||
|
Scope* GetScope() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void ExprDescribe(ODesc* d) const override;
|
void ExprDescribe(ODesc* d) const override;
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,6 @@
|
||||||
#include "Scope.h"
|
#include "Scope.h"
|
||||||
#include "Type.h"
|
#include "Type.h"
|
||||||
#include "File.h"
|
#include "File.h"
|
||||||
#include "Scope.h"
|
|
||||||
#include "Traverse.h"
|
#include "Traverse.h"
|
||||||
#include "Val.h"
|
#include "Val.h"
|
||||||
#include "zeekygen/Manager.h"
|
#include "zeekygen/Manager.h"
|
||||||
|
|
31
src/Var.cc
31
src/Var.cc
|
@ -419,32 +419,25 @@ void begin_func(ID* id, const char* module_name, function_flavor flavor,
|
||||||
class OuterIDBindingFinder : public TraversalCallback {
|
class OuterIDBindingFinder : public TraversalCallback {
|
||||||
public:
|
public:
|
||||||
OuterIDBindingFinder(Scope* s)
|
OuterIDBindingFinder(Scope* s)
|
||||||
: scope(s) { }
|
{
|
||||||
|
scopes.emplace_back(s);
|
||||||
|
}
|
||||||
|
|
||||||
virtual TraversalCode PreExpr(const Expr*);
|
virtual TraversalCode PreExpr(const Expr*);
|
||||||
virtual TraversalCode PostExpr(const Expr*);
|
virtual TraversalCode PostExpr(const Expr*);
|
||||||
|
|
||||||
Scope* scope;
|
std::vector<Scope*> scopes;
|
||||||
vector<const NameExpr*> outer_id_references;
|
vector<const NameExpr*> outer_id_references;
|
||||||
int lambda_depth = 0;
|
|
||||||
// Note: think we really ought to toggle this to false to prevent
|
|
||||||
// considering locals within inner-lambdas as "outer", but other logic
|
|
||||||
// for "selective cloning" and locating IDs in the closure chain may
|
|
||||||
// depend on current behavior and also needs to be changed.
|
|
||||||
bool search_inner_lambdas = true;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
TraversalCode OuterIDBindingFinder::PreExpr(const Expr* expr)
|
TraversalCode OuterIDBindingFinder::PreExpr(const Expr* expr)
|
||||||
{
|
{
|
||||||
if ( expr->Tag() == EXPR_LAMBDA )
|
if ( expr->Tag() == EXPR_LAMBDA )
|
||||||
++lambda_depth;
|
{
|
||||||
|
auto le = static_cast<const LambdaExpr*>(expr);
|
||||||
if ( lambda_depth > 0 && ! search_inner_lambdas )
|
scopes.emplace_back(le->GetScope());
|
||||||
// Don't inspect the bodies of inner lambdas as they will have their
|
|
||||||
// own traversal to find outer IDs and we don't want to detect
|
|
||||||
// references to local IDs inside and accidentally treat them as
|
|
||||||
// "outer" since they can't be found in current scope.
|
|
||||||
return TC_CONTINUE;
|
return TC_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
if ( expr->Tag() != EXPR_NAME )
|
if ( expr->Tag() != EXPR_NAME )
|
||||||
return TC_CONTINUE;
|
return TC_CONTINUE;
|
||||||
|
@ -454,7 +447,10 @@ TraversalCode OuterIDBindingFinder::PreExpr(const Expr* expr)
|
||||||
if ( e->Id()->IsGlobal() )
|
if ( e->Id()->IsGlobal() )
|
||||||
return TC_CONTINUE;
|
return TC_CONTINUE;
|
||||||
|
|
||||||
|
for ( const auto& scope : scopes )
|
||||||
if ( scope->Lookup(e->Id()->Name()) )
|
if ( scope->Lookup(e->Id()->Name()) )
|
||||||
|
// Shadowing is not allowed, so if it's found at inner scope, it's
|
||||||
|
// not something we have to worry about also being at outer scope.
|
||||||
return TC_CONTINUE;
|
return TC_CONTINUE;
|
||||||
|
|
||||||
outer_id_references.push_back(e);
|
outer_id_references.push_back(e);
|
||||||
|
@ -464,10 +460,7 @@ TraversalCode OuterIDBindingFinder::PreExpr(const Expr* expr)
|
||||||
TraversalCode OuterIDBindingFinder::PostExpr(const Expr* expr)
|
TraversalCode OuterIDBindingFinder::PostExpr(const Expr* expr)
|
||||||
{
|
{
|
||||||
if ( expr->Tag() == EXPR_LAMBDA )
|
if ( expr->Tag() == EXPR_LAMBDA )
|
||||||
{
|
scopes.pop_back();
|
||||||
--lambda_depth;
|
|
||||||
assert(lambda_depth >= 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
return TC_CONTINUE;
|
return TC_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
2
testing/btest/Baseline/language.lambda-nested-copy/out
Normal file
2
testing/btest/Baseline/language.lambda-nested-copy/out
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
106
|
||||||
|
106
|
19
testing/btest/language/lambda-nested-copy.zeek
Normal file
19
testing/btest/language/lambda-nested-copy.zeek
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
# @TEST-EXEC: zeek -b %INPUT >out
|
||||||
|
# @TEST-EXEC: btest-diff out
|
||||||
|
|
||||||
|
local outer = 100;
|
||||||
|
|
||||||
|
local lambda = function()
|
||||||
|
{
|
||||||
|
local inner = function(a: count, b: count, c: count, d: count, e: count, f: count)
|
||||||
|
{
|
||||||
|
print outer + f;
|
||||||
|
};
|
||||||
|
|
||||||
|
inner(1, 2, 3, 4, 5, 6);
|
||||||
|
};
|
||||||
|
|
||||||
|
lambda();
|
||||||
|
|
||||||
|
local copyLambda = copy(copy(copy(lambda)));
|
||||||
|
copyLambda();
|
Loading…
Add table
Add a link
Reference in a new issue