From 941ecee692045f90a9c35c95fed5902ecc8cdb6c Mon Sep 17 00:00:00 2001 From: Vern Paxson Date: Sat, 27 Sep 2025 22:23:57 -0700 Subject: [PATCH] fixes for re-declaring type identifiers in inconsistent ways - addresses GH-2686 --- src/Var.cc | 29 +++++++++++++++++++ .../out | 2 ++ .../out | 2 ++ .../redeclaration-redefinition-errors.zeek | 8 +++++ 4 files changed, 41 insertions(+) create mode 100644 testing/btest/Baseline/language.redeclaration-redefinition-errors-12/out create mode 100644 testing/btest/Baseline/language.redeclaration-redefinition-errors-13/out diff --git a/src/Var.cc b/src/Var.cc index f719a4f2ec..b83aef545b 100644 --- a/src/Var.cc +++ b/src/Var.cc @@ -348,6 +348,35 @@ extern ExprPtr add_and_assign_local(IDPtr id, ExprPtr init, ValPtr val) { } void add_type(ID* id, TypePtr t, std::unique_ptr> attr) { + if ( const auto& old_t = id->GetType() ) { + // The identifier already has a type associated with it. This can + // be okay if (1) it's already been marked as a Type identifier, + // (2) the previous type is a stub, or an equivalent enum. + if ( ! id->IsType() ) { + reporter->Error("Identifier %s has already been declared and is not a type", id->Name()); + return; + } + + if ( old_t->Tag() == t->Tag() && ((old_t->Tag() == TYPE_RECORD && old_t->AsRecordType()->NumFields() == 0) || + (t->Tag() == TYPE_ENUM && same_type(t, old_t))) ) + // It has a consistent tag and is either redeclaring a stub + // record (used in init-bare.zeek) or an equivalent enum + // (which can appear due to specifiers in BiFs, for example). + ; + + else { + std::string loc; + auto li = id->GetLocationInfo(); + auto fn = li->FileName(); + int ln = li->FirstLine(); + if ( fn && fn[0] != '\0' ) + loc = " at " + std::string(fn) + ":" + std::to_string(ln); + + reporter->Error("Type %s has already been declared%s", id->Name(), loc.c_str()); + return; + } + } + std::string new_type_name = id->Name(); std::string old_type_name = t->GetName(); diff --git a/testing/btest/Baseline/language.redeclaration-redefinition-errors-12/out b/testing/btest/Baseline/language.redeclaration-redefinition-errors-12/out new file mode 100644 index 0000000000..e45adfd2bf --- /dev/null +++ b/testing/btest/Baseline/language.redeclaration-redefinition-errors-12/out @@ -0,0 +1,2 @@ +### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63. +error in <...>/redeclaration-redefinition-errors.zeek, line 2: Identifier f has already been declared and is not a type diff --git a/testing/btest/Baseline/language.redeclaration-redefinition-errors-13/out b/testing/btest/Baseline/language.redeclaration-redefinition-errors-13/out new file mode 100644 index 0000000000..2bf4d1f641 --- /dev/null +++ b/testing/btest/Baseline/language.redeclaration-redefinition-errors-13/out @@ -0,0 +1,2 @@ +### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63. +error in <...>/redeclaration-redefinition-errors.zeek, line 2: Type f has already been declared at <...>/redeclaration-redefinition-errors.zeek:1 diff --git a/testing/btest/language/redeclaration-redefinition-errors.zeek b/testing/btest/language/redeclaration-redefinition-errors.zeek index 5c44f2b9d6..0efb0d7341 100644 --- a/testing/btest/language/redeclaration-redefinition-errors.zeek +++ b/testing/btest/language/redeclaration-redefinition-errors.zeek @@ -59,3 +59,11 @@ global f: function(); global f = function() { }; global f: hook(); global f: event(); + +# @TEST-START-NEXT +global f = function() { }; +type f: bool; + +# @TEST-START-NEXT +type f: record {}; +type f: bool;