// ========================================================= //
//                                                           //
//   File      : pragmatic.h                                 //
//   Purpose   : compiler version dependent pragmas          //
//                                                           //
//   Coded by Ralf Westram (coder@reallysoft.de) in Oct 26   //
//   http://www.arb-home.de/                                 //
//                                                           //
// ========================================================= //

#ifndef PRAGMATIC_H
#define PRAGMATIC_H

#ifndef GCCVER_H
#include "gccver.h"
#endif
#ifndef STRINGIZE_H
#include "stringize.h"
#endif

// arb code often uses pragmas to suppress warnings.
//
// Problem:
// - suppressed warning not known by older compiler -> compiler raises pragma-warning
//
// Solution:
// - do not use #pragma GCC diagnostic ... in arb code. use pragma_GCC_diagnostic_...-macros instead

#define gcc_diagnostic_ignored(warningFlag) concatenate_spaced_pscans(GCC diagnostic ignored, warningFlag)

#define pragma_GCC_diagnostic_push()               _Pragma("GCC diagnostic push")
#define pragma_GCC_diagnostic_ignored(warningFlag) _Pragma(stringize_pscan(gcc_diagnostic_ignored(warningFlag)))
#define pragma_GCC_diagnostic_pop()                _Pragma("GCC diagnostic pop")

#define pragma_GCC_diagnostic_push_and_ignored(warningFlag)     \
    pragma_GCC_diagnostic_push();                               \
    pragma_GCC_diagnostic_ignored(warningFlag)

// --------------------------------------------------------------------------------
// start suppression of warnings with gcc version that introduces that warning

// suppress warnings introduced with gcc 7.x
#if (GCC_VERSION_CODE >= 700)
# define pragma_GCC_diagnostic_push_and_ignored_format_overflow() pragma_GCC_diagnostic_push_and_ignored("-Wformat-overflow")
#else
# define pragma_GCC_diagnostic_push_and_ignored_format_overflow() pragma_GCC_diagnostic_push()
#endif

// suppress warnings introduced with gcc 8.x
#if (GCC_VERSION_CODE >= 800)
# define pragma_GCC_diagnostic_push_and_ignored_stringop_truncation() pragma_GCC_diagnostic_push_and_ignored("-Wstringop-truncation")
#else
# define pragma_GCC_diagnostic_push_and_ignored_stringop_truncation() pragma_GCC_diagnostic_push()
#endif


// suppress warnings introduced with gcc 13.x
#if (GCC_VERSION_CODE >= 1300)
# define pragma_GCC_diagnostic_push_and_ignored_dangling_reference() pragma_GCC_diagnostic_push_and_ignored("-Wdangling-reference")
#else
# define pragma_GCC_diagnostic_push_and_ignored_dangling_reference() pragma_GCC_diagnostic_push()
#endif

// --------------------------------------------------------------------------------
// suppress bogus warnings only with specific gcc versions:

// suppress bogus warnings with gcc 12.x
#if (GCC_VERSION_CODE >= 1200) && (GCC_VERSION_CODE <= 1299)
# define pragma_GCC_diagnostic_push_and_ignored_use_after_free_gcc12() pragma_GCC_diagnostic_push_and_ignored("-Wuse-after-free")
#else
# define pragma_GCC_diagnostic_push_and_ignored_use_after_free_gcc12() pragma_GCC_diagnostic_push()
#endif

// suppress bogus suggestions to use final types with gcc-9++
// (first try to use MARK_NONFINAL_CLASS)
#if defined(GCC_TOO_SMART_TO_MARK_CLASSES_NONFINAL)
# define pragma_GCC_diagnostic_push_and_ignored_suggest_final_type_when_gcc_too_smart() pragma_GCC_diagnostic_push_and_ignored("-Wsuggest-final-types")
#else
# define pragma_GCC_diagnostic_push_and_ignored_suggest_final_type_when_gcc_too_smart() pragma_GCC_diagnostic_push()
#endif

// --------------------------------------------------------------------------------

#else
#error pragmatic.h included twice
#endif // PRAGMATIC_H
