//--------------------------------------------------------------------------- // Greenplum Database // Copyright (c) 2020-Present VMware, Inc. or its affiliates //--------------------------------------------------------------------------- #ifndef GPOS_DbgPrintMixin_H #define GPOS_DbgPrintMixin_H #include "gpos/error/CAutoTrace.h" #include "gpos/io/COstreamStdString.h" namespace gpos { // A Mixin class that adds debug printing to a type. // // To use it to add DbgStr() and friends to a type U, simply add this as a // public base: // namespace ns { // class U : public gpos::DbgPrintMixin { ... }; // } // // Also drop this snippet into the U.cpp file at the top level: // // FORCE_GENERATE_DBGSTR(ns::U); // // The FORCE_GENERATE_DBGSTR macro ensures code generation for the unused // functions so that we can call them in a debugger // // Use the following printing multi-line messages in your favorite debugger: // // (lldb) setting set escape-non-printables false // (lldb) p x->DbgStr() // // (gdb) printf x->DbgStr() template struct DbgPrintMixin { #ifdef GPOS_DEBUG // debug print for interactive debugging sessions only void DbgPrint() const { CMemoryPool *mp = CMemoryPoolManager::GetGlobalMemoryPool(); CAutoTrace at(mp); static_cast(this)->OsPrint(at.Os()); } std::wstring DbgStr() const GPOS_UNUSED { COstreamStdString oss; static_cast(this)->OsPrint(oss); return oss.Str(); } #endif }; } // namespace gpos // DbgStr() is designed to be unused until evaluated in a debugger. The "used" // attribute usually does the trick to convince a mainstream compiler (GCC and // upstream LLVM Clang) to generate code for DbgStr(). There are two issues with // the "used" attribute, however: // // 1. It slows down compilation. Every translation unit that includes the // declaration of a derived class will take a hit generating DbgPrint() and // DbgStr(). But we really only need one copy of them. This is a fairly minor // issue. // // 2. Not so minor, However, is that AppleClang insists to omit code generation // for unused functions in a class template (this is borderline bug, and there // isn't a flag to disable such a "feature"). // // The best remedy is for each derived type, explicitly instantiate the base // template in the translation unit. This forces code generation even in Apple // Clang, and it speeds up compilation because we only emit code for each // explicit instantiation once. #if defined(GPOS_DEBUG) #define FORCE_GENERATE_DBGSTR(Type) template struct ::gpos::DbgPrintMixin #else #define FORCE_GENERATE_DBGSTR(Type) GPOS_CPL_ASSERT(true, "") #endif #endif