From 98529ae4ec22a79347932f30563fa6aa960afe21 Mon Sep 17 00:00:00 2001 From: Vern Paxson Date: Mon, 4 Jan 2021 13:40:37 -0800 Subject: [PATCH] no semantic changes: factored some of the complexity of begin_func() into a pair of static functions for clarity --- src/Var.cc | 216 ++++++++++++++++++++++++++++------------------------- 1 file changed, 116 insertions(+), 100 deletions(-) diff --git a/src/Var.cc b/src/Var.cc index 1d8f369b82..48e069e7b0 100644 --- a/src/Var.cc +++ b/src/Var.cc @@ -486,6 +486,119 @@ static bool canonical_arg_types_match(const FuncType* decl, const FuncType* impl return true; } +static auto get_prototype(IDPtr id, FuncTypePtr t) + { + auto decl = id->GetType()->AsFuncType(); + auto prototype = func_type_check(decl, t.get()); + + if ( prototype ) + { + if ( decl->Flavor() == FUNC_FLAVOR_FUNCTION ) + { + // If a previous declaration of the function had + // &default params, automatically transfer any that + // are missing (convenience so that implementations + // don't need to specify the &default expression again). + transfer_arg_defaults(prototype->args.get(), t->Params().get()); + } + else + { + // Warn for trying to use &default parameters in + // hook/event handler body when it already has a + // declaration since only &default in the declaration + // has any effect. + const auto& args = t->Params(); + + for ( int i = 0; i < args->NumFields(); ++i ) + { + auto f = args->FieldDecl(i); + + if ( f->attrs && f->attrs->Find(ATTR_DEFAULT) ) + { + reporter->PushLocation(args->GetLocationInfo()); + reporter->Warning( + "&default on parameter '%s' has no effect (not a %s declaration)", + args->FieldName(i), t->FlavorString().data()); + reporter->PopLocation(); + } + } + } + + if ( prototype->deprecated ) + { + if ( prototype->deprecation_msg.empty() ) + t->Warn(util::fmt("use of deprecated '%s' prototype", id->Name()), + prototype->args.get(), true); + else + t->Warn(util::fmt("use of deprecated '%s' prototype: %s", + id->Name(), prototype->deprecation_msg.data()), + prototype->args.get(), true); + } + } + + else + { + // Allow renaming arguments, but only for the canonical + // prototypes of hooks/events. + if ( canonical_arg_types_match(decl, t.get()) ) + prototype = decl->Prototypes()[0]; + else + t->Error("use of undeclared alternate prototype", id.get()); + } + + return prototype; + } + +static bool check_params(int i, std::optional prototype, + const RecordTypePtr& args, + const RecordTypePtr& canon_args, + const char* module_name) + { + TypeDecl* arg_i; + bool hide = false; + + if ( prototype ) + { + auto it = prototype->offsets.find(i); + + if ( it == prototype->offsets.end() ) + { + // Alternate prototype hides this param + hide = true; + arg_i = canon_args->FieldDecl(i); + } + else + { + // Alternate prototype maps this param to another index + arg_i = args->FieldDecl(it->second); + } + } + else + { + if ( i < args->NumFields() ) + arg_i = args->FieldDecl(i); + else + return false; + } + + auto arg_id = lookup_ID(arg_i->id, module_name); + + if ( arg_id && ! arg_id->IsGlobal() ) + arg_id->Error("argument name used twice"); + + const char* local_name = arg_i->id; + + if ( hide ) + // Note the illegal '-' in hidden name implies we haven't + // clobbered any local variable names. + local_name = util::fmt("%s-hidden", local_name); + + arg_id = install_ID(local_name, module_name, false, false); + arg_id->SetType(arg_i->type); + + return true; + } + void begin_func(IDPtr id, const char* module_name, FunctionFlavor flavor, bool is_redef, FuncTypePtr t, @@ -504,63 +617,7 @@ void begin_func(IDPtr id, const char* module_name, std::optional prototype; if ( id->GetType() ) - { - auto decl = id->GetType()->AsFuncType(); - prototype = func_type_check(decl, t.get()); - - if ( prototype ) - { - if ( decl->Flavor() == FUNC_FLAVOR_FUNCTION ) - { - // If a previous declaration of the function had &default - // params, automatically transfer any that are missing - // (convenience so that implementations don't need to specify - // the &default expression again). - transfer_arg_defaults(prototype->args.get(), t->Params().get()); - } - else - { - // Warn for trying to use &default parameters in hook/event - // handler body when it already has a declaration since only - // &default in the declaration has any effect. - const auto& args = t->Params(); - - for ( int i = 0; i < args->NumFields(); ++i ) - { - auto f = args->FieldDecl(i); - - if ( f->attrs && f->attrs->Find(ATTR_DEFAULT) ) - { - reporter->PushLocation(args->GetLocationInfo()); - reporter->Warning( - "&default on parameter '%s' has no effect (not a %s declaration)", - args->FieldName(i), t->FlavorString().data()); - reporter->PopLocation(); - } - } - } - - if ( prototype->deprecated ) - { - if ( prototype->deprecation_msg.empty() ) - t->Warn(util::fmt("use of deprecated '%s' prototype", id->Name()), - prototype->args.get(), true); - else - t->Warn(util::fmt("use of deprecated '%s' prototype: %s", - id->Name(), prototype->deprecation_msg.data()), - prototype->args.get(), true); - } - } - else - { - // Allow renaming arguments, but only for the canonical - // prototypes of hooks/events. - if ( canonical_arg_types_match(decl, t.get()) ) - prototype = decl->Prototypes()[0]; - else - t->Error("use of undeclared alternate prototype", id.get()); - } - } + prototype = get_prototype(id, t); else if ( is_redef ) id->Error("redef of not-previously-declared value"); @@ -604,49 +661,8 @@ void begin_func(IDPtr id, const char* module_name, push_scope(std::move(id), std::move(attrs)); for ( int i = 0; i < canon_args->NumFields(); ++i ) - { - TypeDecl* arg_i; - bool hide = false; - - if ( prototype ) - { - auto it = prototype->offsets.find(i); - - if ( it == prototype->offsets.end() ) - { - // Alternate prototype hides this param - hide = true; - arg_i = canon_args->FieldDecl(i); - } - else - { - // Alternate prototype maps this param to another index - arg_i = args->FieldDecl(it->second); - } - } - else - { - if ( i < args->NumFields() ) - arg_i = args->FieldDecl(i); - else - break; - } - - auto arg_id = lookup_ID(arg_i->id, module_name); - - if ( arg_id && ! arg_id->IsGlobal() ) - arg_id->Error("argument name used twice"); - - const char* local_name = arg_i->id; - - if ( hide ) - // Note the illegal '-' in hidden name implies we haven't - // clobbered any local variable names. - local_name = util::fmt("%s-hidden", local_name); - - arg_id = install_ID(local_name, module_name, false, false); - arg_id->SetType(arg_i->type); - } + if ( ! check_params(i, prototype, args, canon_args, module_name) ) + break; if ( Attr* depr_attr = find_attr(current_scope()->Attrs().get(), ATTR_DEPRECATED) ) current_scope()->GetID()->MakeDeprecated(depr_attr->GetExpr());