diff options
Diffstat (limited to 'libstdc++-v3/include/bits/version.tpl')
-rw-r--r-- | libstdc++-v3/include/bits/version.tpl | 210 |
1 files changed, 210 insertions, 0 deletions
diff --git a/libstdc++-v3/include/bits/version.tpl b/libstdc++-v3/include/bits/version.tpl new file mode 100644 index 0000000..0b15eed --- /dev/null +++ b/libstdc++-v3/include/bits/version.tpl @@ -0,0 +1,210 @@ +/*{ AutoGen5 template -*- C++ -*- +h +(use-modules (srfi srfi-1)) +}*/ +// Copyright (C) 2023 Free Software Foundation, Inc. + +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// <http://www.gnu.org/licenses/>. + +/*{ (dne "// ") }*/ + +/** @file bits/version.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{version} + */ + +// Usage guide: +// +// In your usual header, do something like: +// +// #define __glibcxx_want_ranges +// #define __glibcxx_want_concepts +// #include <bits/version.h> +// +// This will generate the FTMs you named, and let you use them in your code as +// if it was user code. All macros are also exposed under __glibcxx_NAME even +// if unwanted, to permit bits and other FTMs to depend on them for condtional +// computation without exposing extra FTMs to user code. + +#pragma GCC system_header + +#include <bits/c++config.h> +/*{ + +;; Helper for dealing with autogens redefined (error) +(define (ferror msg . args) + (error (apply format (cons* #f msg args)))) + + ;; Helper function that, in the context of a single FTM value, generates the +;; condition expression that fulfills the specification of this value. See the +;; comment block in version.def for an explanation of the format this +;; function parses. +(define (generate-cond) + (define c++min #f) + (define gnu++min #f) + (define gthread #f) + (define hosted #f) + (define c++11-abi #f) + (define extra-cond (get "extra_cond")) + + (define conds '()) + (define (prepend x) + (if x (set! conds (cons x conds)))) + + (if (string-null? extra-cond) + (set! extra-cond #f)) + + (let ((cxxmin (get "cxxmin")) + (gnuxxmin (get "gnuxxmin")) + (getstdcond + (lambda (var) + (let ((ver (get var))) + (if (not (string-null? ver)) + (let ((std-cond (get (format #f "stds[~a]" ver)))) + (if (string-null? std-cond) + (ferror "Standard ~s invalid." ver)) + std-cond) + #f))))) + (set! c++min (getstdcond "cxxmin")) + (set! gnu++min (getstdcond "gnuxxmin"))) + + (let ((process-tristate + (lambda (name) + (let ((val (get name))) + (cond + ((equal? val "") #f) ; Don't test + ((equal? val "yes") "") ; Test directly + ((equal? val "no") "!") ; Invert + (else (ferror "Bad ~a value ~a." name val))))))) + (set! gthread (process-tristate "gthread")) + (set! c++11-abi (process-tristate "cxx11abi")) + (set! hosted (process-tristate "hosted"))) + + (prepend (if extra-cond (format #f "(~a)" extra-cond) #f)) + (prepend (if hosted (format #f "~a~a" hosted "_GLIBCXX_HOSTED") #f)) + (prepend (if gthread (format #f "~a~a" gthread "defined(_GLIBCXX_HAS_GTHREADS)") #f)) + (prepend (if c++11-abi (format #f "~a~a" c++11-abi "_GLIBCXX_USE_CXX11_ABI") #f)) + + (prepend + (let ((strict "defined(__STRICT_ANSI__)") + (c++ "__cplusplus")) + (cond + ((or (and (equal? c++min gnu++min) c++min) + (and (not gnu++min) c++min)) + ;; If we have both values, and they are equal, or we only have gnu++min, + ;; we want to output a simple check. + (format #f "(~a ~a)" c++ c++min)) + ((and gnu++min c++min) + ;; We have differing cases for strict and non-strict modes. + (format #f "((~a && ~a ~a) || (!~a && ~a ~a))" + strict c++ c++min + strict c++ gnu++min)) + ((and gnu++min (not c++min)) + (format #f "(!~a && (~a ~a))" strict c++ gnu++min)) + (else #f)))) + (string-join conds " && " 'strict-infix)) + + + }*/ +/*{ FOR ftms + }*/// /*{ (def-file-line "name") }*/ +#if !defined(__cpp_lib_/*{name}*/) +/*{ FOR values }*//*{ # + + This macro block defines two versions of each FTM: + + 1. __glibcxx_NAME, which is defined unconditionally, and + 2. __cpp_lib_NAME, which is defined only if marked as wanted. + + This allows FTMs to depend on eachother in their definitions without messing + with the exported values. + + This can also be used by bits that do not want to expose FTMs that they can't + implement. + +}*/# /*{(unless (first-for?) "el")}*/if /*{(generate-cond)}*/ +# define __glibcxx_/*{name}*/ /*{v}*/L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_/*{name}*/) +# define /*{ +;; Compute the name for this FTM based on stdname/name. +(if (exist? "stdname") + (get "stdname") + (format #f "__cpp_lib_~a" (get "name"))) +}*/ /*{v}*/L +# endif +/*{ ENDFOR values + }*/# endif +#endif /* !defined(__cpp_lib_/*{name}*/) && defined(__glibcxx_want_/*{name}*/) */ +#undef __glibcxx_want_/*{name +}*//*{ (unless (last-for?) "\n\n" "\n")}*/ +/*{ ENDFOR ftms }*//*{ + +;; Helper that generates [LO, HI]. +(define (closed-int-set lo hi) + (iota (+ (- hi lo) 1) lo)) + +;; Sanity checking for duplicates and for value order. +(let ((ht (make-hash-table (count "ftms")))) + (for-each + (lambda (idx) + (let ((name (get (format #f "ftms[~a].name" idx)))) + (if (string-null? name) (ferror "No name for FTM ~a" idx)) + (let ((cur (cdr (or (hash-get-handle ht name) '(1 . 0))))) + (hash-set! ht name (+ cur 1))))) + (closed-int-set (low-lim "ftms") (high-lim "ftms"))) + (if (hash-fold + (lambda (name count prior) + (if (= 1 count) + prior + (begin + (printf "FTM %s appears %d times.\n" name count) + #t))) + #f ht) + (error "Duplicates found."))) + +(define (check-value-order ftm key order) + (let ((valmin 999999)) ; TODO(arsen): bump before year 10000 + (for-each + (lambda (vidx) + (let* ((sval (get (format #f "values[~a].~a" vidx key))) + (val (string->number sval))) + (unless (string-null? sval) + (unless val (ferror "Bad value in FTM ~a" ftm)) + (if (order val valmin) + (ferror "Found inverted ~s value in FTM ~a: ~a" key ftm sval)) + (set! valmin val)))) + (closed-int-set (low-lim "values") (high-lim "values"))))) + +}*//*{ FOR ftms }*//*{# + Check for values that are in ascending order. Because it is generally the + case that FTMs increase as the values of tests they probe for do, we check + them to prevent simple, silly errors. + + We're iterating in a separate FOR block rather than in pure Guile since, for + some reason, high-lim and low-lim do not work with complex names that include + periods and indices (whereas exist? and others do). +}*//*{ +(let ((ftm (get "name"))) + (check-value-order (get "name") "v" >) + (check-value-order (get "name") "cxxmin" >) + (check-value-order (get "name") "gnuxxmin" >)) +}*//*{ ENDFOR ftms }*/ +#undef __glibcxx_want_all |