/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 | 11.3M | LangOptions::LangOptions() : LangStd(LangStandard::lang_unspecified) { |
20 | 2.76G | #define LANGOPT(Name, Bits, Default, Description) Name = Default; |
21 | 328M | #define ENUM_LANGOPT(Name, Type, Bits, Default, Description) set##Name(Default); |
22 | 11.3M | #include "clang/Basic/LangOptions.def" |
23 | 11.3M | } |
24 | | |
25 | 1.87k | void LangOptions::resetNonModularOptions() { |
26 | 1.87k | #define LANGOPT(Name, Bits, Default, Description) |
27 | 105k | #define BENIGN_LANGOPT(Name, Bits, Default, Description) Name = Default; |
28 | 1.87k | #define BENIGN_ENUM_LANGOPT(Name, Type, Bits, Default, Description) \ |
29 | 9.39k | Name = static_cast<unsigned>(Default); |
30 | 1.87k | #include "clang/Basic/LangOptions.def" |
31 | | |
32 | | // These options do not affect AST generation. |
33 | 1.87k | NoSanitizeFiles.clear(); |
34 | 1.87k | XRayAlwaysInstrumentFiles.clear(); |
35 | 1.87k | XRayNeverInstrumentFiles.clear(); |
36 | | |
37 | 1.87k | CurrentModule.clear(); |
38 | 1.87k | IsHeaderFile = false; |
39 | 1.87k | } |
40 | | |
41 | 342k | bool LangOptions::isNoBuiltinFunc(StringRef FuncName) const { |
42 | 342k | for (unsigned i = 0, e = NoBuiltinFuncs.size(); i != e; ++i400 ) |
43 | 438 | if (FuncName.equals(NoBuiltinFuncs[i])) |
44 | 38 | return true; |
45 | 342k | return false; |
46 | 342k | } |
47 | | |
48 | 374 | VersionTuple LangOptions::getOpenCLVersionTuple() const { |
49 | 374 | const int Ver = OpenCLCPlusPlus ? OpenCLCPlusPlusVersion97 : OpenCLVersion277 ; |
50 | 374 | if (OpenCLCPlusPlus && Ver != 10097 ) |
51 | 89 | return VersionTuple(Ver / 100); |
52 | 285 | return VersionTuple(Ver / 100, (Ver % 100) / 10); |
53 | 374 | } |
54 | | |
55 | 361M | unsigned LangOptions::getOpenCLCompatibleVersion() const { |
56 | 361M | if (!OpenCLCPlusPlus) |
57 | 360M | return OpenCLVersion; |
58 | 614k | if (OpenCLCPlusPlusVersion == 100) |
59 | 356k | return 200; |
60 | 258k | if (OpenCLCPlusPlusVersion == 202100) |
61 | 258k | return 300; |
62 | 18.4E | llvm_unreachable("Unknown OpenCL version"); |
63 | 18.4E | } |
64 | | |
65 | 530 | void LangOptions::remapPathPrefix(SmallVectorImpl<char> &Path) const { |
66 | 530 | for (const auto &Entry : MacroPrefixMap) |
67 | 53 | if (llvm::sys::path::replace_path_prefix(Path, Entry.first, Entry.second)) |
68 | 25 | break; |
69 | 530 | } |
70 | | |
71 | 60 | std::string LangOptions::getOpenCLVersionString() const { |
72 | 60 | std::string Result; |
73 | 60 | { |
74 | 60 | llvm::raw_string_ostream Out(Result); |
75 | 60 | Out << (OpenCLCPlusPlus ? "C++ for OpenCL"21 : "OpenCL C"39 ) << " version " |
76 | 60 | << getOpenCLVersionTuple().getAsString(); |
77 | 60 | } |
78 | 60 | return Result; |
79 | 60 | } |
80 | | |
81 | | void LangOptions::setLangDefaults(LangOptions &Opts, Language Lang, |
82 | | const llvm::Triple &T, |
83 | | std::vector<std::string> &Includes, |
84 | 143k | LangStandard::Kind LangStd) { |
85 | | // Set some properties which depend solely on the input kind; it would be nice |
86 | | // to move these to the language standard, and have the driver resolve the |
87 | | // input kind + language standard. |
88 | | // |
89 | | // FIXME: Perhaps a better model would be for a single source file to have |
90 | | // multiple language standards (C / C++ std, ObjC std, OpenCL std, OpenMP std) |
91 | | // simultaneously active? |
92 | 143k | if (Lang == Language::Asm) { |
93 | 88 | Opts.AsmPreprocessor = 1; |
94 | 143k | } else if (Lang == Language::ObjC || Lang == Language::ObjCXX135k ) { |
95 | 13.0k | Opts.ObjC = 1; |
96 | 13.0k | } |
97 | | |
98 | 143k | if (LangStd == LangStandard::lang_unspecified) |
99 | 31.7k | LangStd = getDefaultLanguageStandard(Lang, T); |
100 | 143k | const LangStandard &Std = LangStandard::getLangStandardForKind(LangStd); |
101 | 143k | Opts.LangStd = LangStd; |
102 | 143k | Opts.LineComment = Std.hasLineComments(); |
103 | 143k | Opts.C99 = Std.isC99(); |
104 | 143k | Opts.C11 = Std.isC11(); |
105 | 143k | Opts.C17 = Std.isC17(); |
106 | 143k | Opts.C2x = Std.isC2x(); |
107 | 143k | Opts.CPlusPlus = Std.isCPlusPlus(); |
108 | 143k | Opts.CPlusPlus11 = Std.isCPlusPlus11(); |
109 | 143k | Opts.CPlusPlus14 = Std.isCPlusPlus14(); |
110 | 143k | Opts.CPlusPlus17 = Std.isCPlusPlus17(); |
111 | 143k | Opts.CPlusPlus20 = Std.isCPlusPlus20(); |
112 | 143k | Opts.CPlusPlus2b = Std.isCPlusPlus2b(); |
113 | 143k | Opts.GNUMode = Std.isGNUMode(); |
114 | 143k | Opts.GNUCVersion = 0; |
115 | 143k | Opts.HexFloats = Std.hasHexFloats(); |
116 | 143k | Opts.WChar = Std.isCPlusPlus(); |
117 | 143k | Opts.Digraphs = Std.hasDigraphs(); |
118 | | |
119 | 143k | Opts.HLSL = Lang == Language::HLSL; |
120 | 143k | if (Opts.HLSL && Opts.IncludeDefaultHeader92 ) |
121 | 10 | Includes.push_back("hlsl.h"); |
122 | | |
123 | | // Set OpenCL Version. |
124 | 143k | Opts.OpenCL = Std.isOpenCL(); |
125 | 143k | if (LangStd == LangStandard::lang_opencl10) |
126 | 68 | Opts.OpenCLVersion = 100; |
127 | 143k | else if (LangStd == LangStandard::lang_opencl11) |
128 | 48 | Opts.OpenCLVersion = 110; |
129 | 143k | else if (LangStd == LangStandard::lang_opencl12) |
130 | 872 | Opts.OpenCLVersion = 120; |
131 | 142k | else if (LangStd == LangStandard::lang_opencl20) |
132 | 358 | Opts.OpenCLVersion = 200; |
133 | 142k | else if (LangStd == LangStandard::lang_opencl30) |
134 | 196 | Opts.OpenCLVersion = 300; |
135 | 142k | else if (LangStd == LangStandard::lang_openclcpp10) |
136 | 208 | Opts.OpenCLCPlusPlusVersion = 100; |
137 | 141k | else if (LangStd == LangStandard::lang_openclcpp2021) |
138 | 108 | Opts.OpenCLCPlusPlusVersion = 202100; |
139 | 141k | else if (LangStd == LangStandard::lang_hlsl2015) |
140 | 2 | Opts.HLSLVersion = (unsigned)LangOptions::HLSL_2015; |
141 | 141k | else if (LangStd == LangStandard::lang_hlsl2016) |
142 | 2 | Opts.HLSLVersion = (unsigned)LangOptions::HLSL_2016; |
143 | 141k | else if (LangStd == LangStandard::lang_hlsl2017) |
144 | 2 | Opts.HLSLVersion = (unsigned)LangOptions::HLSL_2017; |
145 | 141k | else if (LangStd == LangStandard::lang_hlsl2018) |
146 | 2 | Opts.HLSLVersion = (unsigned)LangOptions::HLSL_2018; |
147 | 141k | else if (LangStd == LangStandard::lang_hlsl2021) |
148 | 82 | Opts.HLSLVersion = (unsigned)LangOptions::HLSL_2021; |
149 | 141k | else if (LangStd == LangStandard::lang_hlsl202x) |
150 | 2 | Opts.HLSLVersion = (unsigned)LangOptions::HLSL_202x; |
151 | | |
152 | | // OpenCL has some additional defaults. |
153 | 143k | if (Opts.OpenCL) { |
154 | 1.85k | Opts.AltiVec = 0; |
155 | 1.85k | Opts.ZVector = 0; |
156 | 1.85k | Opts.setDefaultFPContractMode(LangOptions::FPM_On); |
157 | 1.85k | Opts.OpenCLCPlusPlus = Opts.CPlusPlus; |
158 | 1.85k | Opts.OpenCLPipes = Opts.getOpenCLCompatibleVersion() == 200; |
159 | 1.85k | Opts.OpenCLGenericAddressSpace = Opts.getOpenCLCompatibleVersion() == 200; |
160 | | |
161 | | // Include default header file for OpenCL. |
162 | 1.85k | if (Opts.IncludeDefaultHeader) { |
163 | 310 | if (Opts.DeclareOpenCLBuiltins) { |
164 | | // Only include base header file for builtin types and constants. |
165 | 286 | Includes.push_back("opencl-c-base.h"); |
166 | 286 | } else { |
167 | 24 | Includes.push_back("opencl-c.h"); |
168 | 24 | } |
169 | 310 | } |
170 | 1.85k | } |
171 | | |
172 | 143k | Opts.HIP = Lang == Language::HIP; |
173 | 143k | Opts.CUDA = Lang == Language::CUDA || Opts.HIP143k ; |
174 | 143k | if (Opts.HIP) { |
175 | | // HIP toolchain does not support 'Fast' FPOpFusion in backends since it |
176 | | // fuses multiplication/addition instructions without contract flag from |
177 | | // device library functions in LLVM bitcode, which causes accuracy loss in |
178 | | // certain math functions, e.g. tan(-1e20) becomes -0.933 instead of 0.8446. |
179 | | // For device library functions in bitcode to work, 'Strict' or 'Standard' |
180 | | // FPOpFusion options in backends is needed. Therefore 'fast-honor-pragmas' |
181 | | // FP contract option is used to allow fuse across statements in frontend |
182 | | // whereas respecting contract flag in backend. |
183 | 316 | Opts.setDefaultFPContractMode(LangOptions::FPM_FastHonorPragmas); |
184 | 143k | } else if (Opts.CUDA) { |
185 | 518 | if (T.isSPIRV()) { |
186 | | // Emit OpenCL version metadata in LLVM IR when targeting SPIR-V. |
187 | 10 | Opts.OpenCLVersion = 200; |
188 | 10 | } |
189 | | // Allow fuse across statements disregarding pragmas. |
190 | 518 | Opts.setDefaultFPContractMode(LangOptions::FPM_Fast); |
191 | 518 | } |
192 | | |
193 | 143k | Opts.RenderScript = Lang == Language::RenderScript; |
194 | | |
195 | | // OpenCL, C++ and C2x have bool, true, false keywords. |
196 | 143k | Opts.Bool = Opts.OpenCL || Opts.CPlusPlus141k || Opts.C2x37.6k ; |
197 | | |
198 | | // OpenCL and HLSL have half keyword |
199 | 143k | Opts.Half = Opts.OpenCL || Opts.HLSL141k ; |
200 | 143k | } |
201 | | |
202 | 747k | FPOptions FPOptions::defaultWithoutTrailingStorage(const LangOptions &LO) { |
203 | 747k | FPOptions result(LO); |
204 | 747k | return result; |
205 | 747k | } |
206 | | |
207 | 277k | FPOptionsOverride FPOptions::getChangesSlow(const FPOptions &Base) const { |
208 | 277k | FPOptions::storage_type OverrideMask = 0; |
209 | 277k | #define OPTION(NAME, TYPE, WIDTH, PREVIOUS) \ |
210 | 3.32M | if (get##NAME() != Base.get##NAME()) \ |
211 | 3.32M | OverrideMask |= NAME277k ##Mask; |
212 | 277k | #include "clang/Basic/FPOptions.def" |
213 | 277k | return FPOptionsOverride(*this, OverrideMask); |
214 | 277k | } |
215 | | |
216 | 0 | LLVM_DUMP_METHOD void FPOptions::dump() { |
217 | 0 | #define OPTION(NAME, TYPE, WIDTH, PREVIOUS) \ |
218 | 0 | llvm::errs() << "\n " #NAME " " << get##NAME(); |
219 | 0 | #include "clang/Basic/FPOptions.def" |
220 | 0 | llvm::errs() << "\n"; |
221 | 0 | } |
222 | | |
223 | 0 | LLVM_DUMP_METHOD void FPOptionsOverride::dump() { |
224 | 0 | #define OPTION(NAME, TYPE, WIDTH, PREVIOUS) \ |
225 | 0 | if (has##NAME##Override()) \ |
226 | 0 | llvm::errs() << "\n " #NAME " Override is " << get##NAME##Override(); |
227 | 0 | #include "clang/Basic/FPOptions.def" |
228 | 0 | llvm::errs() << "\n"; |
229 | 0 | } |