diff --git a/clang/include/clang/Basic/LangOptions.h b/clang/include/clang/Basic/LangOptions.h --- a/clang/include/clang/Basic/LangOptions.h +++ b/clang/include/clang/Basic/LangOptions.h @@ -508,6 +508,18 @@ void remapPathPrefix(SmallString<256> &Path) const; }; +/// s language defaults for the given input language and language standard in +/// the given LangOptions object. +/// +/// \param Opts - The LangOptions object to set up. +/// \param Lang - The input language. +/// \param T - The target triple. +/// \param Includes - The affected list of included files. +/// \param LangStd - The input language standard. +void setLangDefaults(LangOptions &Opts, Language Lang, const llvm::Triple &T, + std::vector &Includes, + LangStandard::Kind LangStd); + /// Floating point control options class FPOptionsOverride; class FPOptions { diff --git a/clang/include/clang/Frontend/CompilerInvocation.h b/clang/include/clang/Frontend/CompilerInvocation.h --- a/clang/include/clang/Frontend/CompilerInvocation.h +++ b/clang/include/clang/Frontend/CompilerInvocation.h @@ -219,14 +219,7 @@ /// executable), for finding the builtin compiler path. static std::string GetResourcesPath(const char *Argv0, void *MainAddr); - /// Set language defaults for the given input language and - /// language standard in the given LangOptions object. - /// - /// \param Opts - The LangOptions object to set up. - /// \param IK - The input language. - /// \param T - The target triple. - /// \param Includes - The affected list of included files. - /// \param LangStd - The input language standard. + /// This is deprecated. Please use `clang::setLangDefaults` instead. static void setLangDefaults(LangOptions &Opts, InputKind IK, const llvm::Triple &T, std::vector &Includes, diff --git a/clang/lib/Basic/LangOptions.cpp b/clang/lib/Basic/LangOptions.cpp --- a/clang/lib/Basic/LangOptions.cpp +++ b/clang/lib/Basic/LangOptions.cpp @@ -11,6 +11,7 @@ //===----------------------------------------------------------------------===// #include "clang/Basic/LangOptions.h" +#include "clang/Basic/LangStandard.h" #include "llvm/ADT/SmallString.h" #include "llvm/Support/Path.h" @@ -83,6 +84,155 @@ return result; } +void clang::setLangDefaults(LangOptions &Opts, Language Lang, + const llvm::Triple &T, + std::vector &Includes, + LangStandard::Kind LangStd) { + // Set some properties which depend solely on the input kind; it would be nice + // to move these to the language standard, and have the driver resolve the + // input kind + language standard. + // + // FIXME: Perhaps a better model would be for a single source file to have + // multiple language standards (C / C++ std, ObjC std, OpenCL std, OpenMP std) + // simultaneously active? + if (Lang == Language::Asm) { + Opts.AsmPreprocessor = 1; + } else if (Lang == Language::ObjC || Lang == Language::ObjCXX) { + Opts.ObjC = 1; + } + + if (LangStd == LangStandard::lang_unspecified) { + // Based on the base language, pick one. + switch (Lang) { + case Language::Unknown: + case Language::LLVM_IR: + llvm_unreachable("Invalid input kind!"); + case Language::OpenCL: + LangStd = LangStandard::lang_opencl12; + break; + case Language::OpenCLCXX: + LangStd = LangStandard::lang_openclcpp10; + break; + case Language::CUDA: + LangStd = LangStandard::lang_cuda; + break; + case Language::Asm: + case Language::C: +#if defined(CLANG_DEFAULT_STD_C) + LangStd = CLANG_DEFAULT_STD_C; +#else + // The PS4 uses C99 as the default C standard. + if (T.isPS4()) + LangStd = LangStandard::lang_gnu99; + else + LangStd = LangStandard::lang_gnu17; +#endif + break; + case Language::ObjC: +#if defined(CLANG_DEFAULT_STD_C) + LangStd = CLANG_DEFAULT_STD_C; +#else + LangStd = LangStandard::lang_gnu11; +#endif + break; + case Language::CXX: + case Language::ObjCXX: +#if defined(CLANG_DEFAULT_STD_CXX) + LangStd = CLANG_DEFAULT_STD_CXX; +#else + LangStd = LangStandard::lang_gnucxx14; +#endif + break; + case Language::RenderScript: + LangStd = LangStandard::lang_c99; + break; + case Language::HIP: + LangStd = LangStandard::lang_hip; + break; + } + } + + const LangStandard &Std = LangStandard::getLangStandardForKind(LangStd); + Opts.LangStd = LangStd; + Opts.LineComment = Std.hasLineComments(); + Opts.C99 = Std.isC99(); + Opts.C11 = Std.isC11(); + Opts.C17 = Std.isC17(); + Opts.C2x = Std.isC2x(); + Opts.CPlusPlus = Std.isCPlusPlus(); + Opts.CPlusPlus11 = Std.isCPlusPlus11(); + Opts.CPlusPlus14 = Std.isCPlusPlus14(); + Opts.CPlusPlus17 = Std.isCPlusPlus17(); + Opts.CPlusPlus20 = Std.isCPlusPlus20(); + Opts.CPlusPlus2b = Std.isCPlusPlus2b(); + Opts.GNUMode = Std.isGNUMode(); + Opts.GNUCVersion = 0; + Opts.HexFloats = Std.hasHexFloats(); + Opts.ImplicitInt = Std.hasImplicitInt(); + + // Set OpenCL Version. + Opts.OpenCL = Std.isOpenCL(); + if (LangStd == LangStandard::lang_opencl10) + Opts.OpenCLVersion = 100; + else if (LangStd == LangStandard::lang_opencl11) + Opts.OpenCLVersion = 110; + else if (LangStd == LangStandard::lang_opencl12) + Opts.OpenCLVersion = 120; + else if (LangStd == LangStandard::lang_opencl20) + Opts.OpenCLVersion = 200; + else if (LangStd == LangStandard::lang_opencl30) + Opts.OpenCLVersion = 300; + else if (LangStd == LangStandard::lang_openclcpp10) + Opts.OpenCLCPlusPlusVersion = 100; + else if (LangStd == LangStandard::lang_openclcpp2021) + Opts.OpenCLCPlusPlusVersion = 202100; + + // OpenCL has some additional defaults. + if (Opts.OpenCL) { + Opts.AltiVec = 0; + Opts.ZVector = 0; + Opts.setDefaultFPContractMode(LangOptions::FPM_On); + Opts.OpenCLCPlusPlus = Opts.CPlusPlus; + Opts.OpenCLPipes = Opts.getOpenCLCompatibleVersion() == 200; + Opts.OpenCLGenericAddressSpace = Opts.getOpenCLCompatibleVersion() == 200; + + // Include default header file for OpenCL. + if (Opts.IncludeDefaultHeader) { + if (Opts.DeclareOpenCLBuiltins) { + // Only include base header file for builtin types and constants. + Includes.push_back("opencl-c-base.h"); + } else { + Includes.push_back("opencl-c.h"); + } + } + } + + Opts.HIP = Lang == Language::HIP; + Opts.CUDA = Lang == Language::CUDA || Opts.HIP; + if (Opts.HIP) { + // HIP toolchain does not support 'Fast' FPOpFusion in backends since it + // fuses multiplication/addition instructions without contract flag from + // device library functions in LLVM bitcode, which causes accuracy loss in + // certain math functions, e.g. tan(-1e20) becomes -0.933 instead of 0.8446. + // For device library functions in bitcode to work, 'Strict' or 'Standard' + // FPOpFusion options in backends is needed. Therefore 'fast-honor-pragmas' + // FP contract option is used to allow fuse across statements in frontend + // whereas respecting contract flag in backend. + Opts.setDefaultFPContractMode(LangOptions::FPM_FastHonorPragmas); + } else if (Opts.CUDA) { + // Allow fuse across statements disregarding pragmas. + Opts.setDefaultFPContractMode(LangOptions::FPM_Fast); + } + + Opts.RenderScript = Lang == Language::RenderScript; + + // OpenCL and C++ both have bool, true, false keywords. + Opts.Bool = Opts.OpenCL || Opts.CPlusPlus; + + // OpenCL has half keyword + Opts.Half = Opts.OpenCL; +} + LLVM_DUMP_METHOD void FPOptions::dump() { #define OPTION(NAME, TYPE, WIDTH, PREVIOUS) \ llvm::errs() << "\n " #NAME " " << get##NAME(); diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -3111,149 +3111,7 @@ const llvm::Triple &T, std::vector &Includes, LangStandard::Kind LangStd) { - // Set some properties which depend solely on the input kind; it would be nice - // to move these to the language standard, and have the driver resolve the - // input kind + language standard. - // - // FIXME: Perhaps a better model would be for a single source file to have - // multiple language standards (C / C++ std, ObjC std, OpenCL std, OpenMP std) - // simultaneously active? - if (IK.getLanguage() == Language::Asm) { - Opts.AsmPreprocessor = 1; - } else if (IK.isObjectiveC()) { - Opts.ObjC = 1; - } - - if (LangStd == LangStandard::lang_unspecified) { - // Based on the base language, pick one. - switch (IK.getLanguage()) { - case Language::Unknown: - case Language::LLVM_IR: - llvm_unreachable("Invalid input kind!"); - case Language::OpenCL: - LangStd = LangStandard::lang_opencl12; - break; - case Language::OpenCLCXX: - LangStd = LangStandard::lang_openclcpp10; - break; - case Language::CUDA: - LangStd = LangStandard::lang_cuda; - break; - case Language::Asm: - case Language::C: -#if defined(CLANG_DEFAULT_STD_C) - LangStd = CLANG_DEFAULT_STD_C; -#else - // The PS4 uses C99 as the default C standard. - if (T.isPS4()) - LangStd = LangStandard::lang_gnu99; - else - LangStd = LangStandard::lang_gnu17; -#endif - break; - case Language::ObjC: -#if defined(CLANG_DEFAULT_STD_C) - LangStd = CLANG_DEFAULT_STD_C; -#else - LangStd = LangStandard::lang_gnu11; -#endif - break; - case Language::CXX: - case Language::ObjCXX: -#if defined(CLANG_DEFAULT_STD_CXX) - LangStd = CLANG_DEFAULT_STD_CXX; -#else - LangStd = LangStandard::lang_gnucxx14; -#endif - break; - case Language::RenderScript: - LangStd = LangStandard::lang_c99; - break; - case Language::HIP: - LangStd = LangStandard::lang_hip; - break; - } - } - - const LangStandard &Std = LangStandard::getLangStandardForKind(LangStd); - Opts.LangStd = LangStd; - Opts.LineComment = Std.hasLineComments(); - Opts.C99 = Std.isC99(); - Opts.C11 = Std.isC11(); - Opts.C17 = Std.isC17(); - Opts.C2x = Std.isC2x(); - Opts.CPlusPlus = Std.isCPlusPlus(); - Opts.CPlusPlus11 = Std.isCPlusPlus11(); - Opts.CPlusPlus14 = Std.isCPlusPlus14(); - Opts.CPlusPlus17 = Std.isCPlusPlus17(); - Opts.CPlusPlus20 = Std.isCPlusPlus20(); - Opts.CPlusPlus2b = Std.isCPlusPlus2b(); - Opts.GNUMode = Std.isGNUMode(); - Opts.GNUCVersion = 0; - Opts.HexFloats = Std.hasHexFloats(); - Opts.ImplicitInt = Std.hasImplicitInt(); - - // Set OpenCL Version. - Opts.OpenCL = Std.isOpenCL(); - if (LangStd == LangStandard::lang_opencl10) - Opts.OpenCLVersion = 100; - else if (LangStd == LangStandard::lang_opencl11) - Opts.OpenCLVersion = 110; - else if (LangStd == LangStandard::lang_opencl12) - Opts.OpenCLVersion = 120; - else if (LangStd == LangStandard::lang_opencl20) - Opts.OpenCLVersion = 200; - else if (LangStd == LangStandard::lang_opencl30) - Opts.OpenCLVersion = 300; - else if (LangStd == LangStandard::lang_openclcpp10) - Opts.OpenCLCPlusPlusVersion = 100; - else if (LangStd == LangStandard::lang_openclcpp2021) - Opts.OpenCLCPlusPlusVersion = 202100; - - // OpenCL has some additional defaults. - if (Opts.OpenCL) { - Opts.AltiVec = 0; - Opts.ZVector = 0; - Opts.setDefaultFPContractMode(LangOptions::FPM_On); - Opts.OpenCLCPlusPlus = Opts.CPlusPlus; - Opts.OpenCLPipes = Opts.getOpenCLCompatibleVersion() == 200; - Opts.OpenCLGenericAddressSpace = Opts.getOpenCLCompatibleVersion() == 200; - - // Include default header file for OpenCL. - if (Opts.IncludeDefaultHeader) { - if (Opts.DeclareOpenCLBuiltins) { - // Only include base header file for builtin types and constants. - Includes.push_back("opencl-c-base.h"); - } else { - Includes.push_back("opencl-c.h"); - } - } - } - - Opts.HIP = IK.getLanguage() == Language::HIP; - Opts.CUDA = IK.getLanguage() == Language::CUDA || Opts.HIP; - if (Opts.HIP) { - // HIP toolchain does not support 'Fast' FPOpFusion in backends since it - // fuses multiplication/addition instructions without contract flag from - // device library functions in LLVM bitcode, which causes accuracy loss in - // certain math functions, e.g. tan(-1e20) becomes -0.933 instead of 0.8446. - // For device library functions in bitcode to work, 'Strict' or 'Standard' - // FPOpFusion options in backends is needed. Therefore 'fast-honor-pragmas' - // FP contract option is used to allow fuse across statements in frontend - // whereas respecting contract flag in backend. - Opts.setDefaultFPContractMode(LangOptions::FPM_FastHonorPragmas); - } else if (Opts.CUDA) { - // Allow fuse across statements disregarding pragmas. - Opts.setDefaultFPContractMode(LangOptions::FPM_Fast); - } - - Opts.RenderScript = IK.getLanguage() == Language::RenderScript; - - // OpenCL and C++ both have bool, true, false keywords. - Opts.Bool = Opts.OpenCL || Opts.CPlusPlus; - - // OpenCL has half keyword - Opts.Half = Opts.OpenCL; + clang::setLangDefaults(Opts, IK.getLanguage(), T, Includes, LangStd); } /// Check if input file kind and language standard are compatible. @@ -3685,7 +3543,7 @@ Opts.IncludeDefaultHeader = Args.hasArg(OPT_finclude_default_header); Opts.DeclareOpenCLBuiltins = Args.hasArg(OPT_fdeclare_opencl_builtins); - CompilerInvocation::setLangDefaults(Opts, IK, T, Includes, LangStd); + clang::setLangDefaults(Opts, IK.getLanguage(), T, Includes, LangStd); // The key paths of codegen options defined in Options.td start with // "LangOpts->". Let's provide the expected variable name and type.