xref: /llvm-project/clang/include/clang/Testing/TestClangConfig.h (revision 7dfdca1961aadc75ca397818bfb9bd32f1879248)
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(99); }
63 
64   bool isCOrEarlier(int MaximumStdVersion) const {
65     return isC() && (isC(MaximumStdVersion) || !isCOrLater(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(11); }
101 
102   bool isCXX14OrLater() const { return isCXXOrLater(14); }
103 
104   bool isCXX17OrLater() const { return isCXXOrLater(17); }
105 
106   bool isCXX20OrLater() const { return isCXXOrLater(20); }
107 
108   bool isCXX23OrLater() const { return isCXXOrLater(23); }
109 
110   bool isCXXOrEarlier(int MaximumStdVersion) const {
111     return isCXX() &&
112            (isCXX(MaximumStdVersion) || !isCXXOrLater(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(Language);
126     Result.push_back("-target");
127     Result.push_back(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("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