1 | //===--- TestClangConfig.h ------------------------------------------------===// |
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 LLVM_CLANG_TESTING_TESTCLANGCONFIG_H |
10 | #define LLVM_CLANG_TESTING_TESTCLANGCONFIG_H |
11 | |
12 | #include "clang/Testing/CommandLineArgs.h" |
13 | #include "llvm/Support/raw_ostream.h" |
14 | #include <string> |
15 | #include <vector> |
16 | |
17 | namespace clang { |
18 | |
19 | /// A Clang configuration for end-to-end tests that can be converted to |
20 | /// command line arguments for the driver. |
21 | /// |
22 | /// The configuration is represented as typed, named values, making it easier |
23 | /// and safer to work with compared to an array of string command line flags. |
24 | struct TestClangConfig { |
25 | TestLanguage Language; |
26 | |
27 | /// The argument of the `-target` command line flag. |
28 | std::string Target; |
29 | |
30 | bool isC() const { |
31 | return false |
32 | #define TESTLANGUAGE_C(lang, version, std_flag, version_index) \ |
33 | || Language == Lang_##lang##version |
34 | #include "clang/Testing/TestLanguage.def" |
35 | ; |
36 | } |
37 | |
38 | bool isC(int Version) const { |
39 | return false |
40 | #define TESTLANGUAGE_C(lang, version, std_flag, version_index) \ |
41 | || (Version == version && Language == Lang_##lang##version) |
42 | #include "clang/Testing/TestLanguage.def" |
43 | ; |
44 | } |
45 | |
46 | bool isCOrLater(int MinimumStdVersion) const { |
47 | const auto MinimumStdVersionIndex = 0 |
48 | #define TESTLANGUAGE_C(lang, version, std_flag, version_index) \ |
49 | +(MinimumStdVersion == version ? version_index : 0) |
50 | #include "clang/Testing/TestLanguage.def" |
51 | ; |
52 | switch (Language) { |
53 | #define TESTLANGUAGE_C(lang, version, std_flag, version_index) \ |
54 | case Lang_##lang##version: \ |
55 | return MinimumStdVersionIndex <= version_index; |
56 | #include "clang/Testing/TestLanguage.def" |
57 | default: |
58 | return false; |
59 | } |
60 | } |
61 | |
62 | bool isC99OrLater() const { return isCOrLater(MinimumStdVersion: 99); } |
63 | |
64 | bool isCOrEarlier(int MaximumStdVersion) const { |
65 | return isC() && (isC(Version: MaximumStdVersion) || !isCOrLater(MinimumStdVersion: MaximumStdVersion)); |
66 | } |
67 | |
68 | bool isCXX() const { |
69 | return false |
70 | #define TESTLANGUAGE_CXX(lang, version, std_flag, version_index) \ |
71 | || Language == Lang_##lang##version |
72 | #include "clang/Testing/TestLanguage.def" |
73 | ; |
74 | } |
75 | |
76 | bool isCXX(int Version) const { |
77 | return false |
78 | #define TESTLANGUAGE_CXX(lang, version, std_flag, version_index) \ |
79 | || (Version == version && Language == Lang_##lang##version) |
80 | #include "clang/Testing/TestLanguage.def" |
81 | ; |
82 | } |
83 | |
84 | bool isCXXOrLater(int MinimumStdVersion) const { |
85 | const auto MinimumStdVersionIndex = 0 |
86 | #define TESTLANGUAGE_CXX(lang, version, std_flag, version_index) \ |
87 | +(MinimumStdVersion == version ? version_index : 0) |
88 | #include "clang/Testing/TestLanguage.def" |
89 | ; |
90 | switch (Language) { |
91 | #define TESTLANGUAGE_CXX(lang, version, std_flag, version_index) \ |
92 | case Lang_##lang##version: \ |
93 | return MinimumStdVersionIndex <= version_index; |
94 | #include "clang/Testing/TestLanguage.def" |
95 | default: |
96 | return false; |
97 | } |
98 | } |
99 | |
100 | bool isCXX11OrLater() const { return isCXXOrLater(MinimumStdVersion: 11); } |
101 | |
102 | bool isCXX14OrLater() const { return isCXXOrLater(MinimumStdVersion: 14); } |
103 | |
104 | bool isCXX17OrLater() const { return isCXXOrLater(MinimumStdVersion: 17); } |
105 | |
106 | bool isCXX20OrLater() const { return isCXXOrLater(MinimumStdVersion: 20); } |
107 | |
108 | bool isCXX23OrLater() const { return isCXXOrLater(MinimumStdVersion: 23); } |
109 | |
110 | bool isCXXOrEarlier(int MaximumStdVersion) const { |
111 | return isCXX() && |
112 | (isCXX(Version: MaximumStdVersion) || !isCXXOrLater(MinimumStdVersion: MaximumStdVersion)); |
113 | } |
114 | |
115 | bool supportsCXXDynamicExceptionSpecification() const { |
116 | return Language == Lang_CXX03 || Language == Lang_CXX11 || |
117 | Language == Lang_CXX14; |
118 | } |
119 | |
120 | bool hasDelayedTemplateParsing() const { |
121 | return Target == "x86_64-pc-win32-msvc" ; |
122 | } |
123 | |
124 | std::vector<std::string> getCommandLineArgs() const { |
125 | std::vector<std::string> Result = getCommandLineArgsForTesting(Lang: Language); |
126 | Result.push_back(x: "-target" ); |
127 | Result.push_back(x: Target); |
128 | return Result; |
129 | } |
130 | |
131 | std::string toShortString() const { |
132 | std::string Result; |
133 | llvm::raw_string_ostream OS(Result); |
134 | switch (Language) { |
135 | #define TESTLANGUAGE(lang, version, std_flag, version_index) \ |
136 | case Lang_##lang##version: \ |
137 | OS << (#lang #version); \ |
138 | break; |
139 | #include "clang/Testing/TestLanguage.def" |
140 | case Lang_OpenCL: |
141 | OS << "OpenCL" ; |
142 | break; |
143 | case Lang_OBJC: |
144 | OS << "OBJC" ; |
145 | break; |
146 | case Lang_OBJCXX: |
147 | OS << "OBJCXX" ; |
148 | break; |
149 | } |
150 | |
151 | OS << (Target.find(s: "win" ) != std::string::npos ? "_win" : "" ); |
152 | return Result; |
153 | } |
154 | |
155 | std::string toString() const { |
156 | std::string Result; |
157 | llvm::raw_string_ostream OS(Result); |
158 | OS << "{ Language=" << Language << ", Target=" << Target << " }" ; |
159 | return Result; |
160 | } |
161 | |
162 | friend std::ostream &operator<<(std::ostream &OS, |
163 | const TestClangConfig &ClangConfig) { |
164 | return OS << ClangConfig.toString(); |
165 | } |
166 | }; |
167 | |
168 | } // end namespace clang |
169 | |
170 | #endif |
171 | |