From: Alex Rousskov Date: Thu, 22 Dec 2022 02:12:12 +0000 (+0000) Subject: Fix GCC v12 build errors related to ADL in "printing" code (#1215) X-Git-Tag: SQUID_6_0_1~51 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=83afc53d04870edc069581bea1ab699dd7d92088;p=thirdparty%2Fsquid.git Fix GCC v12 build errors related to ADL in "printing" code (#1215) This change contains three fixes/adjustments described below. ### Fix Store::SwapMetaView printing src/sbuf/Stream.h:66:20: error: no match for 'operator<<' (operand types are 'std::basic_ostream' and 'const Store::SwapMetaView'): (out << ... << args); Disclaimer: This explanation omits many details that become important in some other contexts. Most Argument-Dependent Lookup details are documented at https://en.cppreference.com/w/cpp/language/adl // In some printer.h, we define a printing function for any type A. // This is similar to an ToSBuf() declaration in sbuf/Stream.h. template void print(ostream &os, const A &argument) { os << argument; } // In some n/t.h, we define how to print objects of type N::T. // This is similar to store/SwapMetaView.h. operator <<(ostream &os, const N::T &argument); // In some caller1.cc, we include both headers and call print(): #include "printer.h" #include "n/t.h" void caller1(const N::T &argument) { print(std::cout, argument); } // In some caller2.cc, we do the same but change #include order: #include "n/t.h" #include "printer.h" void caller2(const N::T &argument) { print(std::cout, argument); } When looking at "os << argument", the compiler considers two sets of argument printing operators, formed by the following two sources: * The usual unqualified name lookup. This set includes N::T printing operator if that operator is declared in global namespace somewhere above the print() _template declaration_. In the example above, only caller2() will have that printing operator in this set, provided that operator is declared in global namespace (as it used to be). None of the callers will have that printing operator in this set otherwise. * ADL. This set is computed from the caller point of view. It includes N::T printing operator if that operator is declared inside namespace N somewhere above the print() _caller_. In the example above, both caller1() and caller2() will have that printing operator in this set, provided that operator is declared in namespace N (as it is now). None of the callers will have that printing operator in this set otherwise. For code to compile, one of the sets must contain the printing operator. Given the above outcomes, there is only one sane solution that allows any caller to instantiate print() with an N::T argument: The argument printing operator must be declared inside namaspace N! Declaring in global namespace would require maintaining certain #include order (that will cause headaches and, eventually, circular dependencies). In other words, we must rely on ADL, and that means declaring operators in the namespace of one of their argument types. ### Fix std::optional printing (in src/icap/Xaction.cc) src/base/AsyncJobCalls.h:115:61: error: no match for 'operator<<' (operand types are 'std::basic_ostream' and 'const std::optional'): void print(std::ostream &os) const { os << '(' << arg1 << ')'; } In this context, both printing operator argument types are in std, but ADL also looks at template parameters of argument types (if an argument type is a template). That recursion adds the Ip namespace to the search. This is a minimal fix. We should move both Ip::Address printers into ip/print.h or similar, away from Ip::Address users that print nothing. ### Do not declare an overly general std::optional printer The removed declaration: * evidently became unused (after the other changes described above); * places std::optional printers in the wrong namespace (global instead of N), where ADL cannot find them; * exposes all I/O manipulators to a, technically, unrelated std::optional interface. Co-authored-by: Amos Jeffries --- diff --git a/src/adaptation/icap/Xaction.cc b/src/adaptation/icap/Xaction.cc index 2fdabcb34d..2b7103adde 100644 --- a/src/adaptation/icap/Xaction.cc +++ b/src/adaptation/icap/Xaction.cc @@ -134,6 +134,22 @@ void Adaptation::Icap::Xaction::start() Adaptation::Initiate::start(); } +// TODO: Make reusable by moving this (and the printing operator from +// ip/Address.h that this code is calling) into ip/print.h or similar. +namespace Ip { + +inline std::ostream & +operator <<(std::ostream &os, const std::optional
&optional) +{ + if (optional.has_value()) + os << optional.value(); + else + os << "[no IP]"; + return os; +} + +} + static void icapLookupDnsResults(const ipcache_addrs *ia, const Dns::LookupDetails &, void *data) { diff --git a/src/base/IoManip.h b/src/base/IoManip.h index 241d01bb1f..bb60a8b673 100644 --- a/src/base/IoManip.h +++ b/src/base/IoManip.h @@ -13,7 +13,6 @@ #include #include -#include /// Safely prints an object pointed to by the given pointer: [label] /// Prints nothing at all if the pointer is nil. @@ -102,17 +101,5 @@ inline AsHex asHex(const Integer n) { return AsHex(n); } /// Prints the first n data bytes using hex notation. Does nothing if n is 0. void PrintHex(std::ostream &, const char *data, size_t n); -/// prints the value stored inside std::optional (if any) -template -inline std::ostream & -operator <<(std::ostream &os, const std::optional &optional) -{ - if (optional.has_value()) - os << optional.value(); - else - os << "[no value]"; - return os; -} - #endif /* SQUID_SRC_BASE_IO_MANIP_H */ diff --git a/src/store/SwapMetaView.cc b/src/store/SwapMetaView.cc index 42ca271569..d9f6954fbc 100644 --- a/src/store/SwapMetaView.cc +++ b/src/store/SwapMetaView.cc @@ -88,7 +88,7 @@ Store::SwapMetaView::checkExpectedLength(const size_t expectedLength) const } std::ostream & -operator <<(std::ostream &os, const Store::SwapMetaView &meta) +Store::operator <<(std::ostream &os, const SwapMetaView &meta) { os << "type=" << int(meta.rawType); // XXX: Change Raw constructor to take void* data instead of casting here. diff --git a/src/store/SwapMetaView.h b/src/store/SwapMetaView.h index 8d066a00b3..c0afa4a3b2 100644 --- a/src/store/SwapMetaView.h +++ b/src/store/SwapMetaView.h @@ -72,10 +72,10 @@ SwapMetaExtract(Item &item, const char * &input, const void *end) input += sizeof(item); } -} // namespace Store - /// writes a short human-readable summary of the given SwapMetaView object -std::ostream &operator <<(std::ostream &, const Store::SwapMetaView &); +std::ostream &operator <<(std::ostream &, const SwapMetaView &); + +} // namespace Store #endif /* SQUID_SRC_STORE_SWAPMETAVIEW_H */