Args.push_back(SA(Value));
break;
case Option::JoinedClass:
+ case Option::CommaJoinedClass:
Args.push_back(SA(Twine(Spelling) + Value));
break;
default:
}
}
+static SmallVector<StringRef, 4> serializeSanitizerKinds(SanitizerSet S) {
+ SmallVector<StringRef, 4> Values;
+ serializeSanitizerSet(S, Values);
+ return Values;
+}
+
static void parseXRayInstrumentationBundle(StringRef FlagName, StringRef Bundle,
ArgList &Args, DiagnosticsEngine &D,
XRayInstrSet &S) {
llvm_unreachable("unknown input language");
}
-static void GenerateLangArgs(const LangOptions &Opts,
- SmallVectorImpl<const char *> &Args,
- CompilerInvocation::StringAllocator SA) {
+void CompilerInvocation::GenerateLangArgs(const LangOptions &Opts,
+ SmallVectorImpl<const char *> &Args,
+ StringAllocator SA,
+ const llvm::Triple &T) {
+ OptSpecifier StdOpt;
+ switch (Opts.LangStd) {
+ case LangStandard::lang_opencl10:
+ case LangStandard::lang_opencl11:
+ case LangStandard::lang_opencl12:
+ case LangStandard::lang_opencl20:
+ case LangStandard::lang_opencl30:
+ case LangStandard::lang_openclcpp:
+ StdOpt = OPT_cl_std_EQ;
+ break;
+ default:
+ StdOpt = OPT_std_EQ;
+ break;
+ }
+
+ auto LangStandard = LangStandard::getLangStandardForKind(Opts.LangStd);
+ GenerateArg(Args, StdOpt, LangStandard.getName(), SA);
+
if (Opts.IncludeDefaultHeader)
GenerateArg(Args, OPT_finclude_default_header, SA);
if (Opts.DeclareOpenCLBuiltins)
GenerateArg(Args, OPT_fdeclare_opencl_builtins, SA);
+
+ const LangOptions *LangOpts = &Opts;
+
+#define LANG_OPTION_WITH_MARSHALLING( \
+ PREFIX_TYPE, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
+ HELPTEXT, METAVAR, VALUES, SPELLING, SHOULD_PARSE, ALWAYS_EMIT, KEYPATH, \
+ DEFAULT_VALUE, IMPLIED_CHECK, IMPLIED_VALUE, NORMALIZER, DENORMALIZER, \
+ MERGER, EXTRACTOR, TABLE_INDEX) \
+ GENERATE_OPTION_WITH_MARSHALLING( \
+ Args, SA, KIND, FLAGS, SPELLING, ALWAYS_EMIT, KEYPATH, DEFAULT_VALUE, \
+ IMPLIED_CHECK, IMPLIED_VALUE, DENORMALIZER, EXTRACTOR, TABLE_INDEX)
+#include "clang/Driver/Options.inc"
+#undef LANG_OPTION_WITH_MARSHALLING
+
+ // The '-fcf-protection=' option is generated by CodeGenOpts generator.
+
+ if (Opts.ObjC) {
+ std::string Buffer;
+ llvm::raw_string_ostream Stream(Buffer);
+ Stream << Opts.ObjCRuntime;
+ GenerateArg(Args, OPT_fobjc_runtime_EQ, Stream.str(), SA);
+
+ if (Opts.GC == LangOptions::GCOnly)
+ GenerateArg(Args, OPT_fobjc_gc_only, SA);
+ else if (Opts.GC == LangOptions::HybridGC)
+ GenerateArg(Args, OPT_fobjc_gc, SA);
+ else if (Opts.ObjCAutoRefCount == 1)
+ GenerateArg(Args, OPT_fobjc_arc, SA);
+
+ if (Opts.ObjCWeakRuntime)
+ GenerateArg(Args, OPT_fobjc_runtime_has_weak, SA);
+
+ if (Opts.ObjCWeak)
+ GenerateArg(Args, OPT_fobjc_weak, SA);
+
+ if (Opts.ObjCSubscriptingLegacyRuntime)
+ GenerateArg(Args, OPT_fobjc_subscripting_legacy_runtime, SA);
+ }
+
+ if (Opts.GNUCVersion != 0) {
+ unsigned Major = Opts.GNUCVersion / 100 / 100;
+ unsigned Minor = (Opts.GNUCVersion / 100) % 100;
+ unsigned Patch = Opts.GNUCVersion % 100;
+ GenerateArg(Args, OPT_fgnuc_version_EQ,
+ Twine(Major) + "." + Twine(Minor) + "." + Twine(Patch), SA);
+ }
+
+ if (Opts.SignedOverflowBehavior == LangOptions::SOB_Trapping) {
+ GenerateArg(Args, OPT_ftrapv, SA);
+ GenerateArg(Args, OPT_ftrapv_handler, Opts.OverflowHandler, SA);
+ } else if (Opts.SignedOverflowBehavior == LangOptions::SOB_Defined) {
+ GenerateArg(Args, OPT_fwrapv, SA);
+ }
+
+ if (Opts.MSCompatibilityVersion != 0) {
+ unsigned Major = Opts.MSCompatibilityVersion / 10000000;
+ unsigned Minor = (Opts.MSCompatibilityVersion / 100000) % 100;
+ unsigned Subminor = Opts.MSCompatibilityVersion % 100000;
+ GenerateArg(Args, OPT_fms_compatibility_version,
+ Twine(Major) + "." + Twine(Minor) + "." + Twine(Subminor), SA);
+ }
+
+ if ((!Opts.GNUMode && !Opts.MSVCCompat && !Opts.CPlusPlus17) || T.isOSzOS()) {
+ if (!Opts.Trigraphs)
+ GenerateArg(Args, OPT_fno_trigraphs, SA);
+ } else {
+ if (Opts.Trigraphs)
+ GenerateArg(Args, OPT_ftrigraphs, SA);
+ }
+
+ if (Opts.Blocks && !(Opts.OpenCL && Opts.OpenCLVersion == 200))
+ GenerateArg(Args, OPT_fblocks, SA);
+
+ if (Opts.ConvergentFunctions &&
+ !(Opts.OpenCL || (Opts.CUDA && Opts.CUDAIsDevice) || Opts.SYCLIsDevice))
+ GenerateArg(Args, OPT_fconvergent_functions, SA);
+
+ if (Opts.NoBuiltin && !Opts.Freestanding)
+ GenerateArg(Args, OPT_fno_builtin, SA);
+
+ // Not generating '-fno-builtin-xxx'. It's handled for CodeGenOptions, that
+ // also read OPT_fno_builtin_.
+
+ if (Opts.LongDoubleSize == 128)
+ GenerateArg(Args, OPT_mlong_double_128, SA);
+ else if (Opts.LongDoubleSize == 64)
+ GenerateArg(Args, OPT_mlong_double_64, SA);
+
+ // Not generating '-mrtd', it's just an alias for '-fdefault-calling-conv='.
+
+ // OpenMP was requested via '-fopenmp', not implied by '-fopenmp-simd' or
+ // '-fopenmp-targets='.
+ if (Opts.OpenMP && !Opts.OpenMPSimd) {
+ GenerateArg(Args, OPT_fopenmp, SA);
+
+ if (Opts.OpenMP != 50)
+ GenerateArg(Args, OPT_fopenmp_version_EQ, Twine(Opts.OpenMP), SA);
+
+ if (!Opts.OpenMPUseTLS)
+ GenerateArg(Args, OPT_fnoopenmp_use_tls, SA);
+
+ if (Opts.OpenMPIsDevice)
+ GenerateArg(Args, OPT_fopenmp_is_device, SA);
+
+ if (Opts.OpenMPIRBuilder)
+ GenerateArg(Args, OPT_fopenmp_enable_irbuilder, SA);
+ }
+
+ if (Opts.OpenMPSimd) {
+ GenerateArg(Args, OPT_fopenmp_simd, SA);
+
+ if (Opts.OpenMP != 50)
+ GenerateArg(Args, OPT_fopenmp_version_EQ, Twine(Opts.OpenMP), SA);
+ }
+
+ if (Opts.OpenMPCUDANumSMs != 0)
+ GenerateArg(Args, OPT_fopenmp_cuda_number_of_sm_EQ,
+ Twine(Opts.OpenMPCUDANumSMs), SA);
+
+ if (Opts.OpenMPCUDABlocksPerSM != 0)
+ GenerateArg(Args, OPT_fopenmp_cuda_blocks_per_sm_EQ,
+ Twine(Opts.OpenMPCUDABlocksPerSM), SA);
+
+ if (Opts.OpenMPCUDAReductionBufNum != 1024)
+ GenerateArg(Args, OPT_fopenmp_cuda_teams_reduction_recs_num_EQ,
+ Twine(Opts.OpenMPCUDAReductionBufNum), SA);
+
+ if (!Opts.OMPTargetTriples.empty()) {
+ std::string Targets;
+ llvm::raw_string_ostream OS(Targets);
+ llvm::interleave(
+ Opts.OMPTargetTriples, OS,
+ [&OS](const llvm::Triple &T) { OS << T.str(); }, ",");
+ GenerateArg(Args, OPT_fopenmp_targets_EQ, OS.str(), SA);
+ }
+
+ if (!Opts.OMPHostIRFile.empty())
+ GenerateArg(Args, OPT_fopenmp_host_ir_file_path, Opts.OMPHostIRFile, SA);
+
+ if (Opts.OpenMPCUDAMode)
+ GenerateArg(Args, OPT_fopenmp_cuda_mode, SA);
+
+ if (Opts.OpenMPCUDATargetParallel)
+ GenerateArg(Args, OPT_fopenmp_cuda_parallel_target_regions, SA);
+
+ if (Opts.OpenMPCUDAForceFullRuntime)
+ GenerateArg(Args, OPT_fopenmp_cuda_force_full_runtime, SA);
+
+ // The arguments used to set 'Optimize' and 'OptimizeSize' will be generated
+ // by CodeGenOptions.
+
+ if (Opts.NoInlineDefine && Opts.Optimize)
+ GenerateArg(Args, OPT_fno_inline, SA);
+
+ if (Opts.DefaultFPContractMode == LangOptions::FPM_Fast)
+ GenerateArg(Args, OPT_ffp_contract, "fast", SA);
+ else if (Opts.DefaultFPContractMode == LangOptions::FPM_On)
+ GenerateArg(Args, OPT_ffp_contract, "on", SA);
+ else if (Opts.DefaultFPContractMode == LangOptions::FPM_Off)
+ GenerateArg(Args, OPT_ffp_contract, "off", SA);
+ else if (Opts.DefaultFPContractMode == LangOptions::FPM_FastHonorPragmas)
+ GenerateArg(Args, OPT_ffp_contract, "fast-honor-pragmas", SA);
+
+ for (StringRef Sanitizer : serializeSanitizerKinds(Opts.Sanitize))
+ GenerateArg(Args, OPT_fsanitize_EQ, Sanitizer, SA);
+
+ // Conflating '-fsanitize-system-blacklist' and '-fsanitize-blacklist'.
+ for (const std::string &F : Opts.SanitizerBlacklistFiles)
+ GenerateArg(Args, OPT_fsanitize_blacklist, F, SA);
+
+ if (Opts.getClangABICompat() == LangOptions::ClangABI::Ver3_8)
+ GenerateArg(Args, OPT_fclang_abi_compat_EQ, "3.8", SA);
+ else if (Opts.getClangABICompat() == LangOptions::ClangABI::Ver4)
+ GenerateArg(Args, OPT_fclang_abi_compat_EQ, "4.0", SA);
+ else if (Opts.getClangABICompat() == LangOptions::ClangABI::Ver6)
+ GenerateArg(Args, OPT_fclang_abi_compat_EQ, "6.0", SA);
+ else if (Opts.getClangABICompat() == LangOptions::ClangABI::Ver7)
+ GenerateArg(Args, OPT_fclang_abi_compat_EQ, "7.0", SA);
+ else if (Opts.getClangABICompat() == LangOptions::ClangABI::Ver9)
+ GenerateArg(Args, OPT_fclang_abi_compat_EQ, "9.0", SA);
+ else if (Opts.getClangABICompat() == LangOptions::ClangABI::Ver11)
+ GenerateArg(Args, OPT_fclang_abi_compat_EQ, "11.0", SA);
+
+ if (Opts.getSignReturnAddressScope() ==
+ LangOptions::SignReturnAddressScopeKind::All)
+ GenerateArg(Args, OPT_msign_return_address_EQ, "all", SA);
+ else if (Opts.getSignReturnAddressScope() ==
+ LangOptions::SignReturnAddressScopeKind::NonLeaf)
+ GenerateArg(Args, OPT_msign_return_address_EQ, "non-leaf", SA);
+
+ if (Opts.getSignReturnAddressKey() ==
+ LangOptions::SignReturnAddressKeyKind::BKey)
+ GenerateArg(Args, OPT_msign_return_address_key_EQ, "b_key", SA);
}
-bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args,
- InputKind IK, const llvm::Triple &T,
- std::vector<std::string> &Includes,
- DiagnosticsEngine &Diags) {
+bool CompilerInvocation::ParseLangArgsImpl(LangOptions &Opts, ArgList &Args,
+ InputKind IK, const llvm::Triple &T,
+ std::vector<std::string> &Includes,
+ DiagnosticsEngine &Diags) {
unsigned NumErrorsBefore = Diags.getNumErrors();
// FIXME: Cleanup per-file based stuff.
}
}
+ // Check if -fopenmp is specified and set default version to 5.0.
+ Opts.OpenMP = Args.hasArg(OPT_fopenmp) ? 50 : 0;
// Check if -fopenmp-simd is specified.
bool IsSimdSpecified =
Args.hasFlag(options::OPT_fopenmp_simd, options::OPT_fno_openmp_simd,
// Parse -fsanitize= arguments.
parseSanitizerKinds("-fsanitize=", Args.getAllArgValues(OPT_fsanitize_EQ),
Diags, Opts.Sanitize);
+ Opts.SanitizerBlacklistFiles = Args.getAllArgValues(OPT_fsanitize_blacklist);
std::vector<std::string> systemBlacklists =
Args.getAllArgValues(OPT_fsanitize_system_blacklist);
Opts.SanitizerBlacklistFiles.insert(Opts.SanitizerBlacklistFiles.end(),
return Success && Diags.getNumErrors() == NumErrorsBefore;
}
+bool CompilerInvocation::ParseLangArgs(CompilerInvocation &Res,
+ LangOptions &Opts,
+ llvm::opt::ArgList &Args, InputKind IK,
+ const llvm::Triple &T,
+ std::vector<std::string> &Includes,
+ DiagnosticsEngine &Diags) {
+ auto DummyOpts = std::make_shared<LangOptions>();
+
+ // We need to work around inconsistencies related to optimization flags. Their
+ // primary consumer is CodeGenOptions. However, the LangOptions parser also
+ // queries them, which means RoundTrip expects us to generate them. We don't
+ // want to do it in GenerateLangArgs, because it should eventually be the
+ // responsibility of GenerateCodeGenArgs. Until we start doing one big
+ // round-trip, let's do it here.
+ //
+ // Our parser always queries OPT_O_Group. When given -O1, -O2 or -O3, it also
+ // queries OPT_O. To ensure RoundTrip consistently considers us responsible
+ // for generating all of them, we ensure to proactively query them all.
+
+ return RoundTrip(
+ [IK, &T, &Includes](CompilerInvocation &Res, ArgList &Args,
+ DiagnosticsEngine &Diags) {
+ // Proactively query all optimization flags.
+ Args.getLastArg(OPT_O0, OPT_O4, OPT_O, OPT_Ofast);
+ return ParseLangArgsImpl(*Res.getLangOpts(), Args, IK, T, Includes,
+ Diags);
+ },
+ [&T, &Args](CompilerInvocation &Res,
+ SmallVectorImpl<const char *> &GenArgs, StringAllocator SA) {
+ GenerateLangArgs(*Res.getLangOpts(), GenArgs, SA, T);
+ // Generate all optimization flags we queried.
+ if (Arg *A = Args.getLastArg(OPT_O_Group)) {
+ OptSpecifier Opt = A->getOption().getID();
+
+ if (A->getNumValues() > 0)
+ GenerateArg(GenArgs, Opt, A->getValues().back(), SA);
+ else
+ GenerateArg(GenArgs, Opt, SA);
+ }
+
+ // We also queried -fcf-protection, but don't have enough information to
+ // generate it. Eventually, it will be generated from CodeGenOptions.
+ if (const Arg *A = Args.getLastArg(OPT_fcf_protection_EQ))
+ GenerateArg(GenArgs, OPT_fcf_protection_EQ, A->getValue(), SA);
+ },
+ [&DummyOpts](CompilerInvocation &Res) { Res.LangOpts.swap(DummyOpts); },
+ Res, Args, Diags, "LangOptions");
+}
+
static bool isStrictlyPreprocessorAction(frontend::ActionKind Action) {
switch (Action) {
case frontend::ASTDeclList:
} else {
// Other LangOpts are only initialized when the input is not AST or LLVM IR.
// FIXME: Should we really be calling this for an Language::Asm input?
- Success &= ParseLangArgs(LangOpts, Args, DashX, T,
+ Success &= ParseLangArgs(Res, LangOpts, Args, DashX, T,
Res.getPreprocessorOpts().Includes, Diags);
if (Res.getFrontendOpts().ProgramAction == frontend::RewriteObjC)
LangOpts.ObjCExceptions = 1;
EXTRACTOR, TABLE_INDEX)
#define DIAG_OPTION_WITH_MARSHALLING OPTION_WITH_MARSHALLING
-#define LANG_OPTION_WITH_MARSHALLING OPTION_WITH_MARSHALLING
#define CODEGEN_OPTION_WITH_MARSHALLING OPTION_WITH_MARSHALLING
#include "clang/Driver/Options.inc"
#undef CODEGEN_OPTION_WITH_MARSHALLING
-#undef LANG_OPTION_WITH_MARSHALLING
#undef DIAG_OPTION_WITH_MARSHALLING
#undef OPTION_WITH_MARSHALLING
+ llvm::Triple T(TargetOpts->Triple);
+
GenerateAnalyzerArgs(*AnalyzerOpts, Args, SA);
GenerateHeaderSearchArgs(*HeaderSearchOpts, Args, SA);
- GenerateLangArgs(*LangOpts, Args, SA);
+ GenerateLangArgs(*LangOpts, Args, SA, T);
GeneratePreprocessorArgs(*PreprocessorOpts, Args, SA, *LangOpts,
FrontendOpts, CodeGenOpts);
}