/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/Basic/LangOptions.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===- LangOptions.cpp - C Language Family Language Options ---------------===// |
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 | | // This file defines the LangOptions class. |
10 | | // |
11 | | //===----------------------------------------------------------------------===// |
12 | | |
13 | | #include "clang/Basic/LangOptions.h" |
14 | | #include "llvm/ADT/SmallString.h" |
15 | | #include "llvm/Support/Path.h" |
16 | | |
17 | | using namespace clang; |
18 | | |
19 | 4.44M | LangOptions::LangOptions() : LangStd(LangStandard::lang_unspecified) { |
20 | 1.14G | #define LANGOPT(Name, Bits, Default, Description) Name = Default; |
21 | 142M | #define ENUM_LANGOPT(Name, Type, Bits, Default, Description) set##Name(Default); |
22 | 4.44M | #include "clang/Basic/LangOptions.def" |
23 | 4.44M | } |
24 | | |
25 | 3.11k | void LangOptions::resetNonModularOptions() { |
26 | 3.11k | #define LANGOPT(Name, Bits, Default, Description) |
27 | 177k | #define BENIGN_LANGOPT(Name, Bits, Default, Description) Name = Default; |
28 | 3.11k | #define BENIGN_ENUM_LANGOPT(Name, Type, Bits, Default, Description) \ |
29 | 15.5k | Name = static_cast<unsigned>(Default); |
30 | 3.11k | #include "clang/Basic/LangOptions.def" |
31 | | |
32 | | // Reset "benign" options with implied values (Options.td ImpliedBy relations) |
33 | | // rather than their defaults. This avoids unexpected combinations and |
34 | | // invocations that cannot be round-tripped to arguments. |
35 | | // FIXME: we should derive this automatically from ImpliedBy in tablegen. |
36 | 3.11k | AllowFPReassoc = UnsafeFPMath; |
37 | 3.11k | NoHonorNaNs = FiniteMathOnly; |
38 | 3.11k | NoHonorInfs = FiniteMathOnly; |
39 | | |
40 | | // These options do not affect AST generation. |
41 | 3.11k | NoSanitizeFiles.clear(); |
42 | 3.11k | XRayAlwaysInstrumentFiles.clear(); |
43 | 3.11k | XRayNeverInstrumentFiles.clear(); |
44 | | |
45 | 3.11k | CurrentModule.clear(); |
46 | 3.11k | IsHeaderFile = false; |
47 | 3.11k | } |
48 | | |
49 | 308k | bool LangOptions::isNoBuiltinFunc(StringRef FuncName) const { |
50 | 309k | for (unsigned i = 0, e = NoBuiltinFuncs.size(); i != e; ++i400 ) |
51 | 438 | if (FuncName.equals(NoBuiltinFuncs[i])) |
52 | 38 | return true; |
53 | 308k | return false; |
54 | 308k | } |
55 | | |
56 | 374 | VersionTuple LangOptions::getOpenCLVersionTuple() const { |
57 | 374 | const int Ver = OpenCLCPlusPlus ? OpenCLCPlusPlusVersion97 : OpenCLVersion277 ; |
58 | 374 | if (OpenCLCPlusPlus && Ver != 10097 ) |
59 | 89 | return VersionTuple(Ver / 100); |
60 | 285 | return VersionTuple(Ver / 100, (Ver % 100) / 10); |
61 | 374 | } |
62 | | |
63 | 395M | unsigned LangOptions::getOpenCLCompatibleVersion() const { |
64 | 395M | if (!OpenCLCPlusPlus) |
65 | 394M | return OpenCLVersion; |
66 | 610k | if (OpenCLCPlusPlusVersion == 100) |
67 | 356k | return 200; |
68 | 254k | if (OpenCLCPlusPlusVersion == 202100) |
69 | 254k | return 300; |
70 | 18.4E | llvm_unreachable("Unknown OpenCL version"); |
71 | 18.4E | } |
72 | | |
73 | 2.09k | void LangOptions::remapPathPrefix(SmallVectorImpl<char> &Path) const { |
74 | 2.09k | for (const auto &Entry : MacroPrefixMap) |
75 | 54 | if (llvm::sys::path::replace_path_prefix(Path, Entry.first, Entry.second)) |
76 | 26 | break; |
77 | 2.09k | } |
78 | | |
79 | 60 | std::string LangOptions::getOpenCLVersionString() const { |
80 | 60 | std::string Result; |
81 | 60 | { |
82 | 60 | llvm::raw_string_ostream Out(Result); |
83 | 60 | Out << (OpenCLCPlusPlus ? "C++ for OpenCL"21 : "OpenCL C"39 ) << " version " |
84 | 60 | << getOpenCLVersionTuple().getAsString(); |
85 | 60 | } |
86 | 60 | return Result; |
87 | 60 | } |
88 | | |
89 | | void LangOptions::setLangDefaults(LangOptions &Opts, Language Lang, |
90 | | const llvm::Triple &T, |
91 | | std::vector<std::string> &Includes, |
92 | 155k | LangStandard::Kind LangStd) { |
93 | | // Set some properties which depend solely on the input kind; it would be nice |
94 | | // to move these to the language standard, and have the driver resolve the |
95 | | // input kind + language standard. |
96 | | // |
97 | | // FIXME: Perhaps a better model would be for a single source file to have |
98 | | // multiple language standards (C / C++ std, ObjC std, OpenCL std, OpenMP std) |
99 | | // simultaneously active? |
100 | 155k | if (Lang == Language::Asm) { |
101 | 92 | Opts.AsmPreprocessor = 1; |
102 | 155k | } else if (Lang == Language::ObjC || Lang == Language::ObjCXX147k ) { |
103 | 12.7k | Opts.ObjC = 1; |
104 | 12.7k | } |
105 | | |
106 | 155k | if (LangStd == LangStandard::lang_unspecified) |
107 | 34.3k | LangStd = getDefaultLanguageStandard(Lang, T); |
108 | 155k | const LangStandard &Std = LangStandard::getLangStandardForKind(LangStd); |
109 | 155k | Opts.LangStd = LangStd; |
110 | 155k | Opts.LineComment = Std.hasLineComments(); |
111 | 155k | Opts.C99 = Std.isC99(); |
112 | 155k | Opts.C11 = Std.isC11(); |
113 | 155k | Opts.C17 = Std.isC17(); |
114 | 155k | Opts.C23 = Std.isC23(); |
115 | 155k | Opts.CPlusPlus = Std.isCPlusPlus(); |
116 | 155k | Opts.CPlusPlus11 = Std.isCPlusPlus11(); |
117 | 155k | Opts.CPlusPlus14 = Std.isCPlusPlus14(); |
118 | 155k | Opts.CPlusPlus17 = Std.isCPlusPlus17(); |
119 | 155k | Opts.CPlusPlus20 = Std.isCPlusPlus20(); |
120 | 155k | Opts.CPlusPlus23 = Std.isCPlusPlus23(); |
121 | 155k | Opts.CPlusPlus26 = Std.isCPlusPlus26(); |
122 | 155k | Opts.GNUMode = Std.isGNUMode(); |
123 | 155k | Opts.GNUCVersion = 0; |
124 | 155k | Opts.HexFloats = Std.hasHexFloats(); |
125 | 155k | Opts.WChar = Std.isCPlusPlus(); |
126 | 155k | Opts.Digraphs = Std.hasDigraphs(); |
127 | | |
128 | 155k | Opts.HLSL = Lang == Language::HLSL; |
129 | 155k | if (Opts.HLSL && Opts.IncludeDefaultHeader290 ) |
130 | 112 | Includes.push_back("hlsl.h"); |
131 | | |
132 | | // Set OpenCL Version. |
133 | 155k | Opts.OpenCL = Std.isOpenCL(); |
134 | 155k | if (LangStd == LangStandard::lang_opencl10) |
135 | 68 | Opts.OpenCLVersion = 100; |
136 | 155k | else if (LangStd == LangStandard::lang_opencl11) |
137 | 48 | Opts.OpenCLVersion = 110; |
138 | 155k | else if (LangStd == LangStandard::lang_opencl12) |
139 | 1.00k | Opts.OpenCLVersion = 120; |
140 | 154k | else if (LangStd == LangStandard::lang_opencl20) |
141 | 396 | Opts.OpenCLVersion = 200; |
142 | 154k | else if (LangStd == LangStandard::lang_opencl30) |
143 | 202 | Opts.OpenCLVersion = 300; |
144 | 153k | else if (LangStd == LangStandard::lang_openclcpp10) |
145 | 214 | Opts.OpenCLCPlusPlusVersion = 100; |
146 | 153k | else if (LangStd == LangStandard::lang_openclcpp2021) |
147 | 108 | Opts.OpenCLCPlusPlusVersion = 202100; |
148 | 153k | else if (LangStd == LangStandard::lang_hlsl2015) |
149 | 2 | Opts.HLSLVersion = (unsigned)LangOptions::HLSL_2015; |
150 | 153k | else if (LangStd == LangStandard::lang_hlsl2016) |
151 | 2 | Opts.HLSLVersion = (unsigned)LangOptions::HLSL_2016; |
152 | 153k | else if (LangStd == LangStandard::lang_hlsl2017) |
153 | 2 | Opts.HLSLVersion = (unsigned)LangOptions::HLSL_2017; |
154 | 153k | else if (LangStd == LangStandard::lang_hlsl2018) |
155 | 2 | Opts.HLSLVersion = (unsigned)LangOptions::HLSL_2018; |
156 | 153k | else if (LangStd == LangStandard::lang_hlsl2021) |
157 | 270 | Opts.HLSLVersion = (unsigned)LangOptions::HLSL_2021; |
158 | 153k | else if (LangStd == LangStandard::lang_hlsl202x) |
159 | 12 | Opts.HLSLVersion = (unsigned)LangOptions::HLSL_202x; |
160 | | |
161 | | // OpenCL has some additional defaults. |
162 | 155k | if (Opts.OpenCL) { |
163 | 2.03k | Opts.AltiVec = 0; |
164 | 2.03k | Opts.ZVector = 0; |
165 | 2.03k | Opts.setDefaultFPContractMode(LangOptions::FPM_On); |
166 | 2.03k | Opts.OpenCLCPlusPlus = Opts.CPlusPlus; |
167 | 2.03k | Opts.OpenCLPipes = Opts.getOpenCLCompatibleVersion() == 200; |
168 | 2.03k | Opts.OpenCLGenericAddressSpace = Opts.getOpenCLCompatibleVersion() == 200; |
169 | | |
170 | | // Include default header file for OpenCL. |
171 | 2.03k | if (Opts.IncludeDefaultHeader) { |
172 | 350 | if (Opts.DeclareOpenCLBuiltins) { |
173 | | // Only include base header file for builtin types and constants. |
174 | 318 | Includes.push_back("opencl-c-base.h"); |
175 | 318 | } else { |
176 | 32 | Includes.push_back("opencl-c.h"); |
177 | 32 | } |
178 | 350 | } |
179 | 2.03k | } |
180 | | |
181 | 155k | Opts.HIP = Lang == Language::HIP; |
182 | 155k | Opts.CUDA = Lang == Language::CUDA || Opts.HIP155k ; |
183 | 155k | if (Opts.HIP) { |
184 | | // HIP toolchain does not support 'Fast' FPOpFusion in backends since it |
185 | | // fuses multiplication/addition instructions without contract flag from |
186 | | // device library functions in LLVM bitcode, which causes accuracy loss in |
187 | | // certain math functions, e.g. tan(-1e20) becomes -0.933 instead of 0.8446. |
188 | | // For device library functions in bitcode to work, 'Strict' or 'Standard' |
189 | | // FPOpFusion options in backends is needed. Therefore 'fast-honor-pragmas' |
190 | | // FP contract option is used to allow fuse across statements in frontend |
191 | | // whereas respecting contract flag in backend. |
192 | 498 | Opts.setDefaultFPContractMode(LangOptions::FPM_FastHonorPragmas); |
193 | 155k | } else if (Opts.CUDA) { |
194 | 612 | if (T.isSPIRV()) { |
195 | | // Emit OpenCL version metadata in LLVM IR when targeting SPIR-V. |
196 | 24 | Opts.OpenCLVersion = 200; |
197 | 24 | } |
198 | | // Allow fuse across statements disregarding pragmas. |
199 | 612 | Opts.setDefaultFPContractMode(LangOptions::FPM_Fast); |
200 | 612 | } |
201 | | |
202 | 155k | Opts.RenderScript = Lang == Language::RenderScript; |
203 | | |
204 | | // OpenCL, C++ and C23 have bool, true, false keywords. |
205 | 155k | Opts.Bool = Opts.OpenCL || Opts.CPlusPlus153k || Opts.C2341.2k ; |
206 | | |
207 | | // OpenCL and HLSL have half keyword |
208 | 155k | Opts.Half = Opts.OpenCL || Opts.HLSL153k ; |
209 | 155k | } |
210 | | |
211 | 2.21M | FPOptions FPOptions::defaultWithoutTrailingStorage(const LangOptions &LO) { |
212 | 2.21M | FPOptions result(LO); |
213 | 2.21M | return result; |
214 | 2.21M | } |
215 | | |
216 | 300k | FPOptionsOverride FPOptions::getChangesSlow(const FPOptions &Base) const { |
217 | 300k | FPOptions::storage_type OverrideMask = 0; |
218 | 300k | #define OPTION(NAME, TYPE, WIDTH, PREVIOUS) \ |
219 | 4.50M | if (get##NAME() != Base.get##NAME()) \ |
220 | 4.50M | OverrideMask |= NAME301k ##Mask; |
221 | 300k | #include "clang/Basic/FPOptions.def" |
222 | 300k | return FPOptionsOverride(*this, OverrideMask); |
223 | 300k | } |
224 | | |
225 | 0 | LLVM_DUMP_METHOD void FPOptions::dump() { |
226 | 0 | #define OPTION(NAME, TYPE, WIDTH, PREVIOUS) \ |
227 | 0 | llvm::errs() << "\n " #NAME " " << get##NAME(); |
228 | 0 | #include "clang/Basic/FPOptions.def" |
229 | 0 | llvm::errs() << "\n"; |
230 | 0 | } |
231 | | |
232 | 0 | LLVM_DUMP_METHOD void FPOptionsOverride::dump() { |
233 | 0 | #define OPTION(NAME, TYPE, WIDTH, PREVIOUS) \ |
234 | 0 | if (has##NAME##Override()) \ |
235 | 0 | llvm::errs() << "\n " #NAME " Override is " << get##NAME##Override(); |
236 | 0 | #include "clang/Basic/FPOptions.def" |
237 | 0 | llvm::errs() << "\n"; |
238 | 0 | } |