mirror of
https://gcc.gnu.org/git/gcc.git
synced 2026-02-22 03:46:53 -05:00
This is useful to provide libstdc++-internal-only macros. libstdc++-v3/ChangeLog: * include/bits/version.tpl: Implement no_stdname. * include/bits/version.def: Document no_stdname.
214 lines
7.2 KiB
Smarty
214 lines
7.2 KiB
Smarty
/*{ AutoGen5 template -*- C++ -*-
|
|
h
|
|
(use-modules (srfi srfi-1))
|
|
}*/
|
|
// Copyright (C) 2023-2025 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.
|
|
|
|
#ifdef _GLIBCXX_SYSHDR
|
|
#pragma GCC system_header
|
|
#endif
|
|
|
|
#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
|
|
}*/#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}*/)/*{
|
|
IF (not (exist? "no_stdname")) }*/
|
|
# 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 no_std_name }*/
|
|
# 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
|