1 //===- LangOptions.cpp - C Language Family Language Options ---------------===//
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
7 //===----------------------------------------------------------------------===//
9 // This file defines the LangOptions class.
11 //===----------------------------------------------------------------------===//
13 #include "clang/Basic/LangOptions.h"
14 #include "llvm/ADT/SmallString.h"
15 #include "llvm/Support/Path.h"
17 using namespace clang
;
19 LangOptions::LangOptions() : LangStd(LangStandard::lang_unspecified
) {
20 #define LANGOPT(Name, Bits, Default, Description) Name = Default;
21 #define ENUM_LANGOPT(Name, Type, Bits, Default, Description) set##Name(Default);
22 #include "clang/Basic/LangOptions.def"
25 void LangOptions::resetNonModularOptions() {
26 #define LANGOPT(Name, Bits, Default, Description)
27 #define BENIGN_LANGOPT(Name, Bits, Default, Description) Name = Default;
28 #define BENIGN_ENUM_LANGOPT(Name, Type, Bits, Default, Description) \
29 Name = static_cast<unsigned>(Default);
30 #include "clang/Basic/LangOptions.def"
32 // These options do not affect AST generation.
33 NoSanitizeFiles
.clear();
34 XRayAlwaysInstrumentFiles
.clear();
35 XRayNeverInstrumentFiles
.clear();
37 CurrentModule
.clear();
41 bool LangOptions::isNoBuiltinFunc(StringRef FuncName
) const {
42 for (unsigned i
= 0, e
= NoBuiltinFuncs
.size(); i
!= e
; ++i
)
43 if (FuncName
.equals(NoBuiltinFuncs
[i
]))
48 VersionTuple
LangOptions::getOpenCLVersionTuple() const {
49 const int Ver
= OpenCLCPlusPlus
? OpenCLCPlusPlusVersion
: OpenCLVersion
;
50 if (OpenCLCPlusPlus
&& Ver
!= 100)
51 return VersionTuple(Ver
/ 100);
52 return VersionTuple(Ver
/ 100, (Ver
% 100) / 10);
55 unsigned LangOptions::getOpenCLCompatibleVersion() const {
58 if (OpenCLCPlusPlusVersion
== 100)
60 if (OpenCLCPlusPlusVersion
== 202100)
62 llvm_unreachable("Unknown OpenCL version");
65 void LangOptions::remapPathPrefix(SmallVectorImpl
<char> &Path
) const {
66 for (const auto &Entry
: MacroPrefixMap
)
67 if (llvm::sys::path::replace_path_prefix(Path
, Entry
.first
, Entry
.second
))
71 std::string
LangOptions::getOpenCLVersionString() const {
74 llvm::raw_string_ostream
Out(Result
);
75 Out
<< (OpenCLCPlusPlus
? "C++ for OpenCL" : "OpenCL C") << " version "
76 << getOpenCLVersionTuple().getAsString();
81 void LangOptions::setLangDefaults(LangOptions
&Opts
, Language Lang
,
82 const llvm::Triple
&T
,
83 std::vector
<std::string
> &Includes
,
84 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.
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 if (Lang
== Language::Asm
) {
93 Opts
.AsmPreprocessor
= 1;
94 } else if (Lang
== Language::ObjC
|| Lang
== Language::ObjCXX
) {
98 if (LangStd
== LangStandard::lang_unspecified
)
99 LangStd
= getDefaultLanguageStandard(Lang
, T
);
100 const LangStandard
&Std
= LangStandard::getLangStandardForKind(LangStd
);
101 Opts
.LangStd
= LangStd
;
102 Opts
.LineComment
= Std
.hasLineComments();
103 Opts
.C99
= Std
.isC99();
104 Opts
.C11
= Std
.isC11();
105 Opts
.C17
= Std
.isC17();
106 Opts
.C2x
= Std
.isC2x();
107 Opts
.CPlusPlus
= Std
.isCPlusPlus();
108 Opts
.CPlusPlus11
= Std
.isCPlusPlus11();
109 Opts
.CPlusPlus14
= Std
.isCPlusPlus14();
110 Opts
.CPlusPlus17
= Std
.isCPlusPlus17();
111 Opts
.CPlusPlus20
= Std
.isCPlusPlus20();
112 Opts
.CPlusPlus2b
= Std
.isCPlusPlus2b();
113 Opts
.GNUMode
= Std
.isGNUMode();
114 Opts
.GNUCVersion
= 0;
115 Opts
.HexFloats
= Std
.hasHexFloats();
116 Opts
.WChar
= Std
.isCPlusPlus();
117 Opts
.Digraphs
= Std
.hasDigraphs();
119 Opts
.HLSL
= Lang
== Language::HLSL
;
120 if (Opts
.HLSL
&& Opts
.IncludeDefaultHeader
)
121 Includes
.push_back("hlsl.h");
123 // Set OpenCL Version.
124 Opts
.OpenCL
= Std
.isOpenCL();
125 if (LangStd
== LangStandard::lang_opencl10
)
126 Opts
.OpenCLVersion
= 100;
127 else if (LangStd
== LangStandard::lang_opencl11
)
128 Opts
.OpenCLVersion
= 110;
129 else if (LangStd
== LangStandard::lang_opencl12
)
130 Opts
.OpenCLVersion
= 120;
131 else if (LangStd
== LangStandard::lang_opencl20
)
132 Opts
.OpenCLVersion
= 200;
133 else if (LangStd
== LangStandard::lang_opencl30
)
134 Opts
.OpenCLVersion
= 300;
135 else if (LangStd
== LangStandard::lang_openclcpp10
)
136 Opts
.OpenCLCPlusPlusVersion
= 100;
137 else if (LangStd
== LangStandard::lang_openclcpp2021
)
138 Opts
.OpenCLCPlusPlusVersion
= 202100;
139 else if (LangStd
== LangStandard::lang_hlsl2015
)
140 Opts
.HLSLVersion
= (unsigned)LangOptions::HLSL_2015
;
141 else if (LangStd
== LangStandard::lang_hlsl2016
)
142 Opts
.HLSLVersion
= (unsigned)LangOptions::HLSL_2016
;
143 else if (LangStd
== LangStandard::lang_hlsl2017
)
144 Opts
.HLSLVersion
= (unsigned)LangOptions::HLSL_2017
;
145 else if (LangStd
== LangStandard::lang_hlsl2018
)
146 Opts
.HLSLVersion
= (unsigned)LangOptions::HLSL_2018
;
147 else if (LangStd
== LangStandard::lang_hlsl2021
)
148 Opts
.HLSLVersion
= (unsigned)LangOptions::HLSL_2021
;
149 else if (LangStd
== LangStandard::lang_hlsl202x
)
150 Opts
.HLSLVersion
= (unsigned)LangOptions::HLSL_202x
;
152 // OpenCL has some additional defaults.
156 Opts
.setDefaultFPContractMode(LangOptions::FPM_On
);
157 Opts
.OpenCLCPlusPlus
= Opts
.CPlusPlus
;
158 Opts
.OpenCLPipes
= Opts
.getOpenCLCompatibleVersion() == 200;
159 Opts
.OpenCLGenericAddressSpace
= Opts
.getOpenCLCompatibleVersion() == 200;
161 // Include default header file for OpenCL.
162 if (Opts
.IncludeDefaultHeader
) {
163 if (Opts
.DeclareOpenCLBuiltins
) {
164 // Only include base header file for builtin types and constants.
165 Includes
.push_back("opencl-c-base.h");
167 Includes
.push_back("opencl-c.h");
172 Opts
.HIP
= Lang
== Language::HIP
;
173 Opts
.CUDA
= Lang
== Language::CUDA
|| 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 Opts
.setDefaultFPContractMode(LangOptions::FPM_FastHonorPragmas
);
184 } else if (Opts
.CUDA
) {
186 // Emit OpenCL version metadata in LLVM IR when targeting SPIR-V.
187 Opts
.OpenCLVersion
= 200;
189 // Allow fuse across statements disregarding pragmas.
190 Opts
.setDefaultFPContractMode(LangOptions::FPM_Fast
);
193 Opts
.RenderScript
= Lang
== Language::RenderScript
;
195 // OpenCL, C++ and C2x have bool, true, false keywords.
196 Opts
.Bool
= Opts
.OpenCL
|| Opts
.CPlusPlus
|| Opts
.C2x
;
198 // OpenCL and HLSL have half keyword
199 Opts
.Half
= Opts
.OpenCL
|| Opts
.HLSL
;
202 FPOptions
FPOptions::defaultWithoutTrailingStorage(const LangOptions
&LO
) {
203 FPOptions
result(LO
);
207 FPOptionsOverride
FPOptions::getChangesSlow(const FPOptions
&Base
) const {
208 FPOptions::storage_type OverrideMask
= 0;
209 #define OPTION(NAME, TYPE, WIDTH, PREVIOUS) \
210 if (get##NAME() != Base.get##NAME()) \
211 OverrideMask |= NAME##Mask;
212 #include "clang/Basic/FPOptions.def"
213 return FPOptionsOverride(*this, OverrideMask
);
216 LLVM_DUMP_METHOD
void FPOptions::dump() {
217 #define OPTION(NAME, TYPE, WIDTH, PREVIOUS) \
218 llvm::errs() << "\n " #NAME " " << get##NAME();
219 #include "clang/Basic/FPOptions.def"
220 llvm::errs() << "\n";
223 LLVM_DUMP_METHOD
void FPOptionsOverride::dump() {
224 #define OPTION(NAME, TYPE, WIDTH, PREVIOUS) \
225 if (has##NAME##Override()) \
226 llvm::errs() << "\n " #NAME " Override is " << get##NAME##Override();
227 #include "clang/Basic/FPOptions.def"
228 llvm::errs() << "\n";