aboutsummaryrefslogtreecommitdiff
path: root/libstdc++-v3/include/bits/version.tpl
diff options
context:
space:
mode:
Diffstat (limited to 'libstdc++-v3/include/bits/version.tpl')
-rw-r--r--libstdc++-v3/include/bits/version.tpl210
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