diff --git a/src/Attr.cc b/src/Attr.cc index a32cc89668..c464be6f54 100644 --- a/src/Attr.cc +++ b/src/Attr.cc @@ -40,6 +40,18 @@ Attr::Attr(AttrTag t) void Attr::SetAttrExpr(ExprPtr e) { expr = std::move(e); } +std::string Attr::DeprecationMessage() const + { + if ( tag != ATTR_DEPRECATED ) + return ""; + + if ( ! expr ) + return ""; + + auto ce = static_cast(expr.get()); + return ce->Value()->AsStringVal()->CheckString(); + } + void Attr::Describe(ODesc* d) const { AddTag(d); diff --git a/src/Attr.h b/src/Attr.h index 4439701f86..2c9d278a73 100644 --- a/src/Attr.h +++ b/src/Attr.h @@ -3,6 +3,7 @@ #pragma once #include +#include #include "Obj.h" #include "BroList.h" @@ -73,6 +74,12 @@ public: void Describe(ODesc* d) const override; void DescribeReST(ODesc* d, bool shorten = false) const; + /** + * Returns the deprecation string associated with a &deprecated attribute + * or an empty string if this is not such an attribute. + */ + std::string DeprecationMessage() const; + bool operator==(const Attr& other) const { if ( tag != other.tag ) diff --git a/src/ID.cc b/src/ID.cc index ba184ccaec..1b8c3fef58 100644 --- a/src/ID.cc +++ b/src/ID.cc @@ -294,14 +294,7 @@ std::string ID::GetDeprecationWarning() const const auto& depr_attr = GetAttr(ATTR_DEPRECATED); if ( depr_attr ) - { - auto expr = static_cast(depr_attr->GetExpr().get()); - if ( expr ) - { - StringVal* text = expr->Value()->AsStringVal(); - result = text->CheckString(); - } - } + result = depr_attr->DeprecationMessage(); if ( result.empty() ) return fmt("deprecated (%s)", Name()); diff --git a/src/Type.cc b/src/Type.cc index 6a833ddb9e..cb4b1d793f 100644 --- a/src/Type.cc +++ b/src/Type.cc @@ -563,7 +563,7 @@ FuncType::FuncType(RecordTypePtr arg_args, offsets[i] = i; } - prototypes.emplace_back(Prototype{false, args, std::move(offsets)}); + prototypes.emplace_back(Prototype{false, "", args, std::move(offsets)}); } TypePtr FuncType::ShallowClone() @@ -1120,14 +1120,7 @@ string RecordType::GetFieldDeprecationWarning(int field, bool has_check) const { string result; if ( const auto& deprecation = decl->GetAttr(zeek::detail::ATTR_DEPRECATED) ) - { - auto expr = static_cast(deprecation->GetExpr().get()); - if ( expr ) - { - StringVal* text = expr->Value()->AsStringVal(); - result = text->CheckString(); - } - } + result = deprecation->DeprecationMessage(); if ( result.empty() ) return fmt("deprecated (%s%s$%s)", GetName().c_str(), has_check ? "?" : "", diff --git a/src/Type.h b/src/Type.h index b5d58a633c..a2054473d3 100644 --- a/src/Type.h +++ b/src/Type.h @@ -427,6 +427,7 @@ public: */ struct Prototype { bool deprecated; + std::string deprecation_msg; RecordTypePtr args; std::map offsets; }; diff --git a/src/Var.cc b/src/Var.cc index f7722064f4..535c9ab096 100644 --- a/src/Var.cc +++ b/src/Var.cc @@ -100,13 +100,23 @@ static bool add_prototype(const zeek::detail::IDPtr& id, zeek::Type* t, } auto deprecated = false; + std::string depr_msg; if ( attrs ) for ( const auto& a : *attrs ) if ( a->Tag() == zeek::detail::ATTR_DEPRECATED ) + { deprecated = true; + depr_msg = a->DeprecationMessage(); + break; + } + + zeek::FuncType::Prototype p; + p.deprecated = deprecated; + p.deprecation_msg = std::move(depr_msg); + p.args = alt_args; + p.offsets = std::move(offsets); - zeek::FuncType::Prototype p{deprecated, alt_args, std::move(offsets)}; canon_ft->AddPrototype(std::move(p)); return true; } @@ -454,9 +464,19 @@ static std::optional func_type_check(const zeek::Func if ( rval ) for ( auto i = 0; i < rval->args->NumFields(); ++i ) - if ( rval->args->FieldDecl(i)->GetAttr(zeek::detail::ATTR_DEPRECATED) ) - impl->Warn(fmt("use of deprecated parameter '%s'", - rval->args->FieldName(i)), decl, true); + if ( auto ad = rval->args->FieldDecl(i)->GetAttr(zeek::detail::ATTR_DEPRECATED) ) + { + auto msg = ad->DeprecationMessage(); + + if ( msg.empty() ) + impl->Warn(fmt("use of deprecated parameter '%s'", + rval->args->FieldName(i)), + decl, true); + else + impl->Warn(fmt("use of deprecated parameter '%s': %s", + rval->args->FieldName(i), msg.data()), + decl, true); + } return rval; } @@ -531,8 +551,15 @@ void begin_func(zeek::detail::IDPtr id, const char* module_name, } if ( prototype->deprecated ) - t->Warn(fmt("use of deprecated '%s' prototype", id->Name()), - prototype->args.get(), true); + { + if ( prototype->deprecation_msg.empty() ) + t->Warn(fmt("use of deprecated '%s' prototype", id->Name()), + prototype->args.get(), true); + else + t->Warn(fmt("use of deprecated '%s' prototype: %s", + id->Name(), prototype->deprecation_msg.data()), + prototype->args.get(), true); + } } else { diff --git a/testing/btest/Baseline/language.alternate-prototypes-deprecated-args/out b/testing/btest/Baseline/language.alternate-prototypes-deprecated-args/out index 0f67248592..8a8d8e5b88 100644 --- a/testing/btest/Baseline/language.alternate-prototypes-deprecated-args/out +++ b/testing/btest/Baseline/language.alternate-prototypes-deprecated-args/out @@ -1,5 +1,5 @@ -warning in /home/jon/pro/zeek/zeek/testing/btest/.tmp/language.alternate-prototypes-deprecated-args/alternate-prototypes-deprecated-args.zeek, line 9 and /home/jon/pro/zeek/zeek/testing/btest/.tmp/language.alternate-prototypes-deprecated-args/alternate-prototypes-deprecated-args.zeek, line 5: use of deprecated parameter 'b' (event(a:string; b:string; c:string;)) -warning in /home/jon/pro/zeek/zeek/testing/btest/.tmp/language.alternate-prototypes-deprecated-args/alternate-prototypes-deprecated-args.zeek, line 19 and /home/jon/pro/zeek/zeek/testing/btest/.tmp/language.alternate-prototypes-deprecated-args/alternate-prototypes-deprecated-args.zeek, line 7: use of deprecated 'myev' prototype (event(a:string; b:string;)) +warning in /home/jon/pro/zeek/zeek/testing/btest/.tmp/language.alternate-prototypes-deprecated-args/alternate-prototypes-deprecated-args.zeek, line 9 and /home/jon/pro/zeek/zeek/testing/btest/.tmp/language.alternate-prototypes-deprecated-args/alternate-prototypes-deprecated-args.zeek, line 5: use of deprecated parameter 'b': Don't use 'b' (event(a:string; b:string; c:string;)) +warning in /home/jon/pro/zeek/zeek/testing/btest/.tmp/language.alternate-prototypes-deprecated-args/alternate-prototypes-deprecated-args.zeek, line 19 and /home/jon/pro/zeek/zeek/testing/btest/.tmp/language.alternate-prototypes-deprecated-args/alternate-prototypes-deprecated-args.zeek, line 7: use of deprecated 'myev' prototype: Don't use this prototype (event(a:string; b:string;)) myev (canon), one, two, three myev (new), one, three myev (old), one, two