diff options
Diffstat (limited to 'clang/lib/Frontend/CompilerInvocation.cpp')
-rw-r--r-- | clang/lib/Frontend/CompilerInvocation.cpp | 293 |
1 files changed, 282 insertions, 11 deletions
diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 189e7c6..09444b2 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -214,6 +214,7 @@ static void denormalizeStringImpl(SmallVectorImpl<const char *> &Args, Args.push_back(SA(Value)); break; case Option::JoinedClass: + case Option::CommaJoinedClass: Args.push_back(SA(Twine(Spelling) + Value)); break; default: @@ -1212,6 +1213,12 @@ static void parseSanitizerKinds(StringRef FlagName, } } +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) { @@ -2633,19 +2640,231 @@ static const StringRef GetInputKindName(InputKind IK) { 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. @@ -2868,6 +3087,8 @@ bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args, } } + // 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, @@ -3011,6 +3232,7 @@ bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args, // 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(), @@ -3087,6 +3309,55 @@ bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args, 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: @@ -3425,7 +3696,7 @@ bool CompilerInvocation::CreateFromArgs(CompilerInvocation &Res, } 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; @@ -3612,19 +3883,19 @@ void CompilerInvocation::generateCC1CommandLine( 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); } |