diff --git a/src/Type.cc b/src/Type.cc index 2591b7992e..8de62e7266 100644 --- a/src/Type.cc +++ b/src/Type.cc @@ -1783,6 +1783,39 @@ BroType* merge_types(const BroType* t1, const BroType* t2) case TYPE_ERROR: return base_type(tg1); + case TYPE_ENUM: + { + // Could compare pointers t1 == t2, but maybe there's someone out + // there creating clones of the type, so safer to compare name. + if ( t1->GetName() != t2->GetName() ) + { + std::string msg = fmt("incompatible enum types: '%s' and '%s'", + t1->GetName().data(), t2->GetName().data()); + + t1->Error(msg.data(), t2); + return 0; + } + + // Doing a lookup here as a roundabout way of ref-ing t1, without + // changing the function params which has t1 as const and also + // (potentially) avoiding a pitfall mentioned earlier about clones. + auto id = global_scope()->Lookup(t1->GetName().data()); + + if ( id && id->AsType() && id->AsType()->Tag() == TYPE_ENUM ) + // It should make most sense to return the real type here rather + // than a copy since it may be redef'd later in parsing. If we + // return a copy, then whoever is using this return value won't + // actually see those changes from the redef. + return id->AsType()->Ref(); + + std::string msg = fmt("incompatible enum types: '%s' and '%s'" + " ('%s' enum type ID is invalid)", + t1->GetName().data(), t2->GetName().data(), + t1->GetName().data()); + t1->Error(msg.data(), t2); + return 0; + } + case TYPE_TABLE: { const IndexType* it1 = (const IndexType*) t1; diff --git a/testing/btest/Baseline/language.vector-of-enum-mismatch/out b/testing/btest/Baseline/language.vector-of-enum-mismatch/out new file mode 100644 index 0000000000..0129d04b1f --- /dev/null +++ b/testing/btest/Baseline/language.vector-of-enum-mismatch/out @@ -0,0 +1,2 @@ +error in /home/jon/pro/zeek/zeek/testing/btest/.tmp/language.vector-of-enum-mismatch/vector-of-enum-mismatch.zeek, line 7 and /home/jon/pro/zeek/zeek/testing/btest/.tmp/language.vector-of-enum-mismatch/vector-of-enum-mismatch.zeek, line 8: incompatible enum types: 'color' and 'number' (enum and enum) +error in /home/jon/pro/zeek/zeek/testing/btest/.tmp/language.vector-of-enum-mismatch/vector-of-enum-mismatch.zeek, line 9: inconsistent types in list diff --git a/testing/btest/Baseline/language.vector-of-enum/out b/testing/btest/Baseline/language.vector-of-enum/out new file mode 100644 index 0000000000..b783ab2a48 --- /dev/null +++ b/testing/btest/Baseline/language.vector-of-enum/out @@ -0,0 +1 @@ +vector of enum, [Red, Green, Blue] diff --git a/testing/btest/language/vector-of-enum-mismatch.zeek b/testing/btest/language/vector-of-enum-mismatch.zeek new file mode 100644 index 0000000000..5df1e0201f --- /dev/null +++ b/testing/btest/language/vector-of-enum-mismatch.zeek @@ -0,0 +1,9 @@ +# @TEST-EXEC-FAIL: zeek -b %INPUT >out 2>&1 +# @TEST-EXEC: TEST_DIFF_CANONIFIER=$SCRIPTS/diff-remove-abspath btest-diff out + +# Type inference for vector constructor comprised of disparate enum types +# should raise an error message about the types being incompatible. + +type color: enum { Red, Green, Blue }; +type number: enum { One, Two, Three, Four}; +global v = vector(Red, Four, Blue); diff --git a/testing/btest/language/vector-of-enum.zeek b/testing/btest/language/vector-of-enum.zeek new file mode 100644 index 0000000000..a6e34e4da8 --- /dev/null +++ b/testing/btest/language/vector-of-enum.zeek @@ -0,0 +1,9 @@ +# @TEST-EXEC: zeek -b %INPUT >out +# @TEST-EXEC: btest-diff out + +# Type inference for vector constructor comprised of enums should work fine +# (previously the internal merge_types code did not handle enums). + +type color: enum { Red, Green, Blue }; +global v = vector(Red, Green, Blue); +print type_name(v), v;