Warning: This file is not a C or C++ file. It does not have highlighting.

1//===-- include/flang/Common/idioms.h ---------------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef FORTRAN_COMMON_IDIOMS_H_
10#define FORTRAN_COMMON_IDIOMS_H_
11
12// Defines anything that might ever be useful in more than one source file
13// or that is too weird or too specific to the host C++ compiler to be
14// exposed elsewhere.
15
16#ifndef __cplusplus
17#error this is a C++ program
18#endif
19#if __cplusplus < 201703L
20#error this is a C++17 program
21#endif
22#if !__clang__ && defined __GNUC__ && __GNUC__ < 7
23#error g++ >= 7.2 is required
24#endif
25
26#include "enum-class.h"
27#include "variant.h"
28#include "visit.h"
29#include <array>
30#include <functional>
31#include <list>
32#include <memory>
33#include <optional>
34#include <string>
35#include <tuple>
36#include <type_traits>
37
38#if __GNUC__ == 7
39// Avoid a deduction bug in GNU 7.x headers by forcing the answer.
40namespace std {
41template <typename A>
42struct is_trivially_copy_constructible<list<A>> : false_type {};
43template <typename A>
44struct is_trivially_copy_constructible<optional<list<A>>> : false_type {};
45} // namespace std
46#endif
47
48// enable "this is a std::string"s with the 's' suffix
49using namespace std::literals::string_literals;
50
51namespace Fortran::common {
52
53// Helper templates for combining a list of lambdas into an anonymous
54// struct for use with common::visit() on a std::variant<> sum type.
55// E.g.: common::visit(visitors{
56// [&](const firstType &x) { ... },
57// [&](const secondType &x) { ... },
58// ...
59// [&](const auto &catchAll) { ... }}, variantObject);
60
61template <typename... LAMBDAS> struct visitors : LAMBDAS... {
62 using LAMBDAS::operator()...;
63};
64
65template <typename... LAMBDAS> visitors(LAMBDAS... x) -> visitors<LAMBDAS...>;
66
67// Calls std::fprintf(stderr, ...), then abort().
68[[noreturn]] void die(const char *, ...);
69
70#define DIE(x) Fortran::common::die(x " at " __FILE__ "(%d)", __LINE__)
71
72// For switch statement default: labels.
73#define CRASH_NO_CASE DIE("no case")
74
75// clang-format off
76// For switch statements whose cases have return statements for
77// all possibilities. Clang emits warnings if the default: is
78// present, gcc emits warnings if it is absent.
79#if __clang__
80#define SWITCH_COVERS_ALL_CASES
81#else
82#define SWITCH_COVERS_ALL_CASES default: CRASH_NO_CASE;
83#endif
84// clang-format on
85
86// For cheap assertions that should be applied in production.
87// To disable, compile with '-DCHECK=(void)'
88#ifndef CHECK
89#define CHECK(x) ((x) || (DIE("CHECK(" #x ") failed"), false))
90// Same as above, but with a custom error message.
91#define CHECK_MSG(x, y) ((x) || (DIE("CHECK(" #x ") failed: " #y), false))
92#endif
93
94// User-defined type traits that default to false:
95// Invoke CLASS_TRAIT(traitName) to define a trait, then put
96// using traitName = std::true_type; (or false_type)
97// into the appropriate class definitions. You can then use
98// typename std::enable_if_t<traitName<...>, ...>
99// in template specialization definitions.
100#define CLASS_TRAIT(T) \
101 namespace class_trait_ns_##T { \
102 template <typename A> std::true_type test(typename A::T *); \
103 template <typename A> std::false_type test(...); \
104 template <typename A> \
105 constexpr bool has_trait{decltype(test<A>(nullptr))::value}; \
106 template <typename A> constexpr bool trait_value() { \
107 if constexpr (has_trait<A>) { \
108 using U = typename A::T; \
109 return U::value; \
110 } else { \
111 return false; \
112 } \
113 } \
114 } \
115 template <typename A> constexpr bool T{class_trait_ns_##T::trait_value<A>()};
116
117// Check that a pointer is non-null and dereference it
118#define DEREF(p) Fortran::common::Deref(p, __FILE__, __LINE__)
119
120template <typename T> constexpr T &Deref(T *p, const char *file, int line) {
121 if (!p) {
122 Fortran::common::die("nullptr dereference at %s(%d)", file, line);
123 }
124 return *p;
125}
126
127template <typename T>
128constexpr T &Deref(const std::unique_ptr<T> &p, const char *file, int line) {
129 if (!p) {
130 Fortran::common::die("nullptr dereference at %s(%d)", file, line);
131 }
132 return *p;
133}
134
135// Given a const reference to a value, return a copy of the value.
136template <typename A> A Clone(const A &x) { return x; }
137
138// C++ does a weird and dangerous thing when deducing template type parameters
139// from function arguments: lvalue references are allowed to match rvalue
140// reference arguments. Template function declarations like
141// template<typename A> int foo(A &&);
142// need to be protected against this C++ language feature when functions
143// may modify such arguments. Use these type functions to invoke SFINAE
144// on a result type via
145// template<typename A> common::IfNoLvalue<int, A> foo(A &&);
146// or, for constructors,
147// template<typename A, typename = common::NoLvalue<A>> int foo(A &&);
148// This works with parameter packs too.
149template <typename A, typename... B>
150using IfNoLvalue = std::enable_if_t<(... && !std::is_lvalue_reference_v<B>), A>;
151template <typename... RVREF> using NoLvalue = IfNoLvalue<void, RVREF...>;
152} // namespace Fortran::common
153#endif // FORTRAN_COMMON_IDIOMS_H_
154

Warning: This file is not a C or C++ file. It does not have highlighting.

source code of flang/include/flang/Common/idioms.h