https://github.com/ampandey-1995 updated https://github.com/llvm/llvm-project/pull/137759
>From aa3caaeaa72ab2f0de8beac416875dc466ac1051 Mon Sep 17 00:00:00 2001 From: Amit Pandey <pandey.kumaramit2...@gmail.com> Date: Thu, 1 May 2025 13:51:12 +0530 Subject: [PATCH 1/2] [Flang][Sanitizer] Support sanitizer flag for Flang Driver. Flang Driver currently dosen't support option sanitizer flags such as '-fsanitize='. This patch currently supports enabling sanitizer flags for the flang driver apart from clang independently. --- clang/include/clang/Driver/Options.td | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index e69cd6b833c3a..32cd93f9a5e36 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -1555,11 +1555,15 @@ defm xl_pragma_pack : BoolFOption<"xl-pragma-pack", "Enable IBM XL #pragma pack handling">, NegFlag<SetFalse>>; def shared_libsan : Flag<["-"], "shared-libsan">, + Visibility<[ClangOption, CC1Option, FlangOption, FC1Option]>, HelpText<"Dynamically link the sanitizer runtime">; def static_libsan : Flag<["-"], "static-libsan">, + Visibility<[ClangOption, CC1Option, FlangOption, FC1Option]>, HelpText<"Statically link the sanitizer runtime (Not supported for ASan, TSan or UBSan on darwin)">; -def : Flag<["-"], "shared-libasan">, Alias<shared_libsan>; -def : Flag<["-"], "static-libasan">, Alias<static_libsan>; +def : Flag<["-"], "shared-libasan">, Alias<shared_libsan>, + Visibility<[ClangOption, CC1Option, FlangOption, FC1Option]>; +def : Flag<["-"], "static-libasan">, Alias<static_libsan>, + Visibility<[ClangOption, CC1Option, FlangOption, FC1Option]>; def fasm : Flag<["-"], "fasm">, Group<f_Group>; defm assume_unique_vtables : BoolFOption<"assume-unique-vtables", @@ -2309,7 +2313,7 @@ def fmemory_profile_use_EQ : Joined<["-"], "fmemory-profile-use=">, // Begin sanitizer flags. These should all be core options exposed in all driver // modes. -let Visibility = [ClangOption, CC1Option, CLOption] in { +let Visibility = [ClangOption, CC1Option, CLOption, FlangOption, FC1Option] in { def fsanitize_EQ : CommaJoined<["-"], "fsanitize=">, Group<f_clang_Group>, MetaVarName<"<check>">, >From f938acc7557bd37edac3b7a38ecb32e069a13a97 Mon Sep 17 00:00:00 2001 From: Amit Pandey <pandey.kumaramit2...@gmail.com> Date: Wed, 14 May 2025 21:44:15 +0530 Subject: [PATCH 2/2] Support ASan in LLVM Flang. --- clang/include/clang/Driver/Options.td | 92 +++++++++---------- clang/lib/Driver/ToolChains/Flang.cpp | 13 +++ clang/lib/Driver/ToolChains/Flang.h | 9 ++ .../include/flang/Frontend/CodeGenOptions.def | 67 ++++++++++++++ flang/include/flang/Frontend/CodeGenOptions.h | 47 ++++++++++ flang/include/flang/Support/LangOptions.def | 1 + flang/include/flang/Support/LangOptions.h | 11 ++- flang/lib/Frontend/CodeGenOptions.cpp | 29 ++++++ flang/lib/Frontend/CompilerInvocation.cpp | 82 +++++++++++++++++ flang/lib/Frontend/FrontendActions.cpp | 37 ++++++++ 10 files changed, 341 insertions(+), 47 deletions(-) diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index f4307f02d9175..3e89a1f7b28aa 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -2339,7 +2339,7 @@ def fsanitize_EQ : CommaJoined<["-"], "fsanitize=">, Group<f_clang_Group>, HelpText<"Turn on runtime checks for various forms of undefined " "or suspicious behavior. See user manual for available checks">; def fno_sanitize_EQ : CommaJoined<["-"], "fno-sanitize=">, Group<f_clang_Group>, - Visibility<[ClangOption, CLOption]>; + Visibility<[ClangOption, CLOption, FlangOption]>; def fsanitize_ignorelist_EQ : Joined<["-"], "fsanitize-ignorelist=">, Group<f_clang_Group>, HelpText<"Path to ignorelist file for sanitizers">; @@ -2349,7 +2349,7 @@ def : Joined<["-"], "fsanitize-blacklist=">, def fsanitize_system_ignorelist_EQ : Joined<["-"], "fsanitize-system-ignorelist=">, HelpText<"Path to system ignorelist file for sanitizers">, - Visibility<[ClangOption, CC1Option]>; + Visibility<[ClangOption, CC1Option, FlangOption, FC1Option]>; def fno_sanitize_ignorelist : Flag<["-"], "fno-sanitize-ignorelist">, Group<f_clang_Group>, HelpText<"Don't use ignorelist file for sanitizers">; @@ -2360,17 +2360,17 @@ def fsanitize_coverage : CommaJoined<["-"], "fsanitize-coverage=">, Group<f_clang_Group>, HelpText<"Specify the type of coverage instrumentation for Sanitizers">; def fno_sanitize_coverage : CommaJoined<["-"], "fno-sanitize-coverage=">, - Group<f_clang_Group>, Visibility<[ClangOption, CLOption]>, + Group<f_clang_Group>, Visibility<[ClangOption, CLOption, FlangOption]>, HelpText<"Disable features of coverage instrumentation for Sanitizers">, Values<"func,bb,edge,indirect-calls,trace-bb,trace-cmp,trace-div,trace-gep," "8bit-counters,trace-pc,trace-pc-guard,no-prune,inline-8bit-counters," "inline-bool-flag">; def fsanitize_coverage_allowlist : Joined<["-"], "fsanitize-coverage-allowlist=">, - Group<f_clang_Group>, Visibility<[ClangOption, CLOption]>, + Group<f_clang_Group>, Visibility<[ClangOption, CLOption, FlangOption]>, HelpText<"Restrict sanitizer coverage instrumentation exclusively to modules and functions that match the provided special case list, except the blocked ones">, MarshallingInfoStringVector<CodeGenOpts<"SanitizeCoverageAllowlistFiles">>; def fsanitize_coverage_ignorelist : Joined<["-"], "fsanitize-coverage-ignorelist=">, - Group<f_clang_Group>, Visibility<[ClangOption, CLOption]>, + Group<f_clang_Group>, Visibility<[ClangOption, CLOption, FlangOption]>, HelpText<"Disable sanitizer coverage instrumentation for modules and functions " "that match the provided special case list, even the allowed ones">, MarshallingInfoStringVector<CodeGenOpts<"SanitizeCoverageIgnorelistFiles">>; @@ -2385,10 +2385,10 @@ def fexperimental_sanitize_metadata_EQ : CommaJoined<["-"], "fexperimental-sanit Group<f_Group>, HelpText<"Specify the type of metadata to emit for binary analysis sanitizers">; def fno_experimental_sanitize_metadata_EQ : CommaJoined<["-"], "fno-experimental-sanitize-metadata=">, - Group<f_Group>, Visibility<[ClangOption, CLOption]>, + Group<f_Group>, Visibility<[ClangOption, CLOption,FlangOption]>, HelpText<"Disable emitting metadata for binary analysis sanitizers">; def fexperimental_sanitize_metadata_ignorelist_EQ : Joined<["-"], "fexperimental-sanitize-metadata-ignorelist=">, - Group<f_Group>, Visibility<[ClangOption, CLOption]>, + Group<f_Group>, Visibility<[ClangOption, CLOption, FlangOption]>, HelpText<"Disable sanitizer metadata for modules and functions that match the provided special case list">, MarshallingInfoStringVector<CodeGenOpts<"SanitizeMetadataIgnorelistFiles">>; def fsanitize_memory_track_origins_EQ : Joined<["-"], "fsanitize-memory-track-origins=">, @@ -2401,7 +2401,7 @@ def fsanitize_memory_track_origins : Flag<["-"], "fsanitize-memory-track-origins HelpText<"Enable origins tracking in MemorySanitizer">; def fno_sanitize_memory_track_origins : Flag<["-"], "fno-sanitize-memory-track-origins">, Group<f_clang_Group>, - Visibility<[ClangOption, CLOption]>, + Visibility<[ClangOption, CLOption, FlangOption]>, HelpText<"Disable origins tracking in MemorySanitizer">; def fsanitize_address_outline_instrumentation : Flag<["-"], "fsanitize-address-outline-instrumentation">, Group<f_clang_Group>, @@ -2423,13 +2423,13 @@ def fsanitize_hwaddress_experimental_aliasing def fno_sanitize_hwaddress_experimental_aliasing : Flag<["-"], "fno-sanitize-hwaddress-experimental-aliasing">, Group<f_clang_Group>, - Visibility<[ClangOption, CLOption]>, + Visibility<[ClangOption, CLOption, FlangOption]>, HelpText<"Disable aliasing mode in HWAddressSanitizer">; defm sanitize_memory_use_after_dtor : BoolOption<"f", "sanitize-memory-use-after-dtor", CodeGenOpts<"SanitizeMemoryUseAfterDtor">, DefaultFalse, - PosFlag<SetTrue, [], [ClangOption, CC1Option], "Enable">, - NegFlag<SetFalse, [], [ClangOption], "Disable">, - BothFlags<[], [ClangOption], " use-after-destroy detection in MemorySanitizer">>, + PosFlag<SetTrue, [], [ClangOption, CC1Option, FlangOption, FC1Option], "Enable">, + NegFlag<SetFalse, [], [ClangOption, FlangOption], "Disable">, + BothFlags<[], [ClangOption, FlangOption], " use-after-destroy detection in MemorySanitizer">>, Group<f_clang_Group>; def fsanitize_address_field_padding : Joined<["-"], "fsanitize-address-field-padding=">, Group<f_clang_Group>, @@ -2437,15 +2437,15 @@ def fsanitize_address_field_padding : Joined<["-"], "fsanitize-address-field-pad MarshallingInfoInt<LangOpts<"SanitizeAddressFieldPadding">>; defm sanitize_address_use_after_scope : BoolOption<"f", "sanitize-address-use-after-scope", CodeGenOpts<"SanitizeAddressUseAfterScope">, DefaultFalse, - PosFlag<SetTrue, [], [ClangOption], "Enable">, - NegFlag<SetFalse, [], [ClangOption, CLOption], + PosFlag<SetTrue, [], [ClangOption, FlangOption], "Enable">, + NegFlag<SetFalse, [], [ClangOption, CLOption, FlangOption], "Disable">, - BothFlags<[], [ClangOption], " use-after-scope detection in AddressSanitizer">>, + BothFlags<[], [ClangOption, FlangOption], " use-after-scope detection in AddressSanitizer">>, Group<f_clang_Group>; def sanitize_address_use_after_return_EQ : Joined<["-"], "fsanitize-address-use-after-return=">, MetaVarName<"<mode>">, - Visibility<[ClangOption, CC1Option]>, + Visibility<[ClangOption, CC1Option, FlangOption]>, HelpText<"Select the mode of detecting stack use-after-return in AddressSanitizer">, Group<f_clang_Group>, Values<"never,runtime,always">, @@ -2454,9 +2454,9 @@ def sanitize_address_use_after_return_EQ MarshallingInfoEnum<CodeGenOpts<"SanitizeAddressUseAfterReturn">, "Runtime">; defm sanitize_address_poison_custom_array_cookie : BoolOption<"f", "sanitize-address-poison-custom-array-cookie", CodeGenOpts<"SanitizeAddressPoisonCustomArrayCookie">, DefaultFalse, - PosFlag<SetTrue, [], [ClangOption], "Enable">, - NegFlag<SetFalse, [], [ClangOption], "Disable">, - BothFlags<[], [ClangOption], " poisoning array cookies when using custom operator new[] in AddressSanitizer">>, + PosFlag<SetTrue, [], [ClangOption, FlangOption], "Enable">, + NegFlag<SetFalse, [], [ClangOption, FlangOption], "Disable">, + BothFlags<[], [ClangOption, FlangOption], " poisoning array cookies when using custom operator new[] in AddressSanitizer">>, DocBrief<[{Enable "poisoning" array cookies when allocating arrays with a custom operator new\[\] in Address Sanitizer, preventing accesses to the cookies from user code. An array cookie is a small implementation-defined @@ -2471,18 +2471,18 @@ functions are always poisoned.}]>, Group<f_clang_Group>; defm sanitize_address_globals_dead_stripping : BoolOption<"f", "sanitize-address-globals-dead-stripping", CodeGenOpts<"SanitizeAddressGlobalsDeadStripping">, DefaultFalse, - PosFlag<SetTrue, [], [ClangOption], "Enable linker dead stripping of globals in AddressSanitizer">, - NegFlag<SetFalse, [], [ClangOption], "Disable linker dead stripping of globals in AddressSanitizer">>, + PosFlag<SetTrue, [], [ClangOption, FlangOption], "Enable linker dead stripping of globals in AddressSanitizer">, + NegFlag<SetFalse, [], [ClangOption, FlangOption], "Disable linker dead stripping of globals in AddressSanitizer">>, Group<f_clang_Group>; defm sanitize_address_use_odr_indicator : BoolOption<"f", "sanitize-address-use-odr-indicator", CodeGenOpts<"SanitizeAddressUseOdrIndicator">, DefaultTrue, - PosFlag<SetTrue, [], [ClangOption], "Enable ODR indicator globals to avoid false ODR violation" + PosFlag<SetTrue, [], [ClangOption, FlangOption], "Enable ODR indicator globals to avoid false ODR violation" " reports in partially sanitized programs at the cost of an increase in binary size">, - NegFlag<SetFalse, [], [ClangOption], "Disable ODR indicator globals">>, + NegFlag<SetFalse, [], [ClangOption, FlangOption], "Disable ODR indicator globals">>, Group<f_clang_Group>; def sanitize_address_destructor_EQ : Joined<["-"], "fsanitize-address-destructor=">, - Visibility<[ClangOption, CC1Option]>, + Visibility<[ClangOption, CC1Option, FlangOption, FC1Option]>, HelpText<"Set the kind of module destructors emitted by " "AddressSanitizer instrumentation. These destructors are " "emitted to unregister instrumented global variables when " @@ -2496,9 +2496,9 @@ defm sanitize_memory_param_retval : BoolFOption<"sanitize-memory-param-retval", CodeGenOpts<"SanitizeMemoryParamRetval">, DefaultTrue, - PosFlag<SetTrue, [], [ClangOption, CC1Option], "Enable">, - NegFlag<SetFalse, [], [ClangOption], "Disable">, - BothFlags<[], [ClangOption], " detection of uninitialized parameters and return values">>; + PosFlag<SetTrue, [], [ClangOption, CC1Option, FlangOption, FC1Option], "Enable">, + NegFlag<SetFalse, [], [ClangOption, FlangOption], "Disable">, + BothFlags<[], [ClangOption, FlangOption], " detection of uninitialized parameters and return values">>; //// Note: This flag was introduced when it was necessary to distinguish between // ABI for correct codegen. This is no longer needed, but the flag is // not removed since targeting either ABI will behave the same. @@ -2514,25 +2514,25 @@ def fsanitize_recover_EQ : CommaJoined<["-"], "fsanitize-recover=">, HelpText<"Enable recovery for specified sanitizers">; def fno_sanitize_recover_EQ : CommaJoined<["-"], "fno-sanitize-recover=">, Group<f_clang_Group>, - Visibility<[ClangOption, CLOption]>, + Visibility<[ClangOption, CLOption, FlangOption]>, HelpText<"Disable recovery for specified sanitizers">; def fsanitize_recover : Flag<["-"], "fsanitize-recover">, Group<f_clang_Group>, Alias<fsanitize_recover_EQ>, AliasArgs<["all"]>; def fno_sanitize_recover : Flag<["-"], "fno-sanitize-recover">, - Visibility<[ClangOption, CLOption]>, + Visibility<[ClangOption, CLOption, FlangOption]>, Group<f_clang_Group>, Alias<fno_sanitize_recover_EQ>, AliasArgs<["all"]>; def fsanitize_trap_EQ : CommaJoined<["-"], "fsanitize-trap=">, Group<f_clang_Group>, HelpText<"Enable trapping for specified sanitizers">; def fno_sanitize_trap_EQ : CommaJoined<["-"], "fno-sanitize-trap=">, Group<f_clang_Group>, - Visibility<[ClangOption, CLOption]>, + Visibility<[ClangOption, CLOption, FlangOption]>, HelpText<"Disable trapping for specified sanitizers">; def fsanitize_trap : Flag<["-"], "fsanitize-trap">, Group<f_clang_Group>, Alias<fsanitize_trap_EQ>, AliasArgs<["all"]>, HelpText<"Enable trapping for all sanitizers">; def fno_sanitize_trap : Flag<["-"], "fno-sanitize-trap">, Group<f_clang_Group>, Alias<fno_sanitize_trap_EQ>, AliasArgs<["all"]>, - Visibility<[ClangOption, CLOption]>, + Visibility<[ClangOption, CLOption, FlangOption]>, HelpText<"Disable trapping for all sanitizers">; def fsanitize_merge_handlers_EQ : CommaJoined<["-"], "fsanitize-merge=">, @@ -2547,7 +2547,7 @@ def fsanitize_merge_handlers : Flag<["-"], "fsanitize-merge">, Group<f_clang_Gro HelpText<"Allow compiler to merge handlers for all sanitizers">; def fno_sanitize_merge_handlers : Flag<["-"], "fno-sanitize-merge">, Group<f_clang_Group>, Alias<fno_sanitize_merge_handlers_EQ>, AliasArgs<["all"]>, - Visibility<[ClangOption, CLOption]>, + Visibility<[ClangOption, CLOption, FlangOption]>, HelpText<"Do not allow compiler to merge handlers for any sanitizers">; def fsanitize_annotate_debug_info_EQ : CommaJoined<["-"], "fsanitize-annotate-debug-info=">, @@ -2595,10 +2595,10 @@ def fno_sanitize_link_cxx_runtime : Flag<["-"], "fno-sanitize-link-c++-runtime"> Group<f_clang_Group>; defm sanitize_cfi_cross_dso : BoolOption<"f", "sanitize-cfi-cross-dso", CodeGenOpts<"SanitizeCfiCrossDso">, DefaultFalse, - PosFlag<SetTrue, [], [ClangOption], "Enable">, - NegFlag<SetFalse, [], [ClangOption, CLOption], + PosFlag<SetTrue, [], [ClangOption, FlangOption], "Enable">, + NegFlag<SetFalse, [], [ClangOption, CLOption, FlangOption], "Disable">, - BothFlags<[], [ClangOption], " control flow integrity (CFI) checks for cross-DSO calls.">>, + BothFlags<[], [ClangOption, FlangOption], " control flow integrity (CFI) checks for cross-DSO calls.">>, Group<f_clang_Group>; def fsanitize_cfi_icall_generalize_pointers : Flag<["-"], "fsanitize-cfi-icall-generalize-pointers">, Group<f_clang_Group>, @@ -2610,10 +2610,10 @@ def fsanitize_cfi_icall_normalize_integers : Flag<["-"], "fsanitize-cfi-icall-ex MarshallingInfoFlag<CodeGenOpts<"SanitizeCfiICallNormalizeIntegers">>; defm sanitize_cfi_canonical_jump_tables : BoolOption<"f", "sanitize-cfi-canonical-jump-tables", CodeGenOpts<"SanitizeCfiCanonicalJumpTables">, DefaultFalse, - PosFlag<SetTrue, [], [ClangOption], "Make">, - NegFlag<SetFalse, [], [ClangOption, CLOption], + PosFlag<SetTrue, [], [ClangOption, FlangOption], "Make">, + NegFlag<SetFalse, [], [ClangOption, CLOption, FlangOption], "Do not make">, - BothFlags<[], [ClangOption], " the jump table addresses canonical in the symbol table">>, + BothFlags<[], [ClangOption, FlangOption], " the jump table addresses canonical in the symbol table">>, Group<f_clang_Group>; def fsanitize_kcfi_arity : Flag<["-"], "fsanitize-kcfi-arity">, Group<f_clang_Group>, @@ -2621,14 +2621,14 @@ def fsanitize_kcfi_arity : Flag<["-"], "fsanitize-kcfi-arity">, MarshallingInfoFlag<CodeGenOpts<"SanitizeKcfiArity">>; defm sanitize_stats : BoolOption<"f", "sanitize-stats", CodeGenOpts<"SanitizeStats">, DefaultFalse, - PosFlag<SetTrue, [], [ClangOption], "Enable">, - NegFlag<SetFalse, [], [ClangOption, CLOption], + PosFlag<SetTrue, [], [ClangOption, FlangOption], "Enable">, + NegFlag<SetFalse, [], [ClangOption, CLOption, FlangOption], "Disable">, - BothFlags<[], [ClangOption], " sanitizer statistics gathering.">>, + BothFlags<[], [ClangOption, FlangOption], " sanitizer statistics gathering.">>, Group<f_clang_Group>; def fsanitize_undefined_ignore_overflow_pattern_EQ : CommaJoined<["-"], "fsanitize-undefined-ignore-overflow-pattern=">, HelpText<"Specify the overflow patterns to exclude from arithmetic sanitizer instrumentation">, - Visibility<[ClangOption, CC1Option]>, + Visibility<[ClangOption, CC1Option, FlangOption, FC1Option]>, Values<"none,all,add-unsigned-overflow-test,add-signed-overflow-test,negated-unsigned-const,unsigned-post-decr-while">, MarshallingInfoStringVector<LangOpts<"OverflowPatternExclusionValues">>; def fsanitize_thread_memory_access : Flag<["-"], "fsanitize-thread-memory-access">, @@ -2636,21 +2636,21 @@ def fsanitize_thread_memory_access : Flag<["-"], "fsanitize-thread-memory-access HelpText<"Enable memory access instrumentation in ThreadSanitizer (default)">; def fno_sanitize_thread_memory_access : Flag<["-"], "fno-sanitize-thread-memory-access">, Group<f_clang_Group>, - Visibility<[ClangOption, CLOption]>, + Visibility<[ClangOption, CLOption, FlangOption]>, HelpText<"Disable memory access instrumentation in ThreadSanitizer">; def fsanitize_thread_func_entry_exit : Flag<["-"], "fsanitize-thread-func-entry-exit">, Group<f_clang_Group>, HelpText<"Enable function entry/exit instrumentation in ThreadSanitizer (default)">; def fno_sanitize_thread_func_entry_exit : Flag<["-"], "fno-sanitize-thread-func-entry-exit">, Group<f_clang_Group>, - Visibility<[ClangOption, CLOption]>, + Visibility<[ClangOption, CLOption, FlangOption]>, HelpText<"Disable function entry/exit instrumentation in ThreadSanitizer">; def fsanitize_thread_atomics : Flag<["-"], "fsanitize-thread-atomics">, Group<f_clang_Group>, HelpText<"Enable atomic operations instrumentation in ThreadSanitizer (default)">; def fno_sanitize_thread_atomics : Flag<["-"], "fno-sanitize-thread-atomics">, Group<f_clang_Group>, - Visibility<[ClangOption, CLOption]>, + Visibility<[ClangOption, CLOption, FlangOption]>, HelpText<"Disable atomic operations instrumentation in ThreadSanitizer">; def fsanitize_undefined_strip_path_components_EQ : Joined<["-"], "fsanitize-undefined-strip-path-components=">, Group<f_clang_Group>, MetaVarName<"<number>">, @@ -3448,7 +3448,7 @@ def fno_asm : Flag<["-"], "fno-asm">, Group<f_Group>; def fno_asynchronous_unwind_tables : Flag<["-"], "fno-asynchronous-unwind-tables">, Group<f_Group>; def fno_assume_sane_operator_new : Flag<["-"], "fno-assume-sane-operator-new">, Group<f_Group>, HelpText<"Don't assume that C++'s global operator new can't alias any pointer">, - Visibility<[ClangOption, CC1Option]>, + Visibility<[ClangOption, CC1Option, FlangOption, FC1Option]>, MarshallingInfoNegativeFlag<CodeGenOpts<"AssumeSaneOperatorNew">>; def fno_builtin : Flag<["-"], "fno-builtin">, Group<f_Group>, Visibility<[ClangOption, CC1Option, CLOption, DXCOption]>, diff --git a/clang/lib/Driver/ToolChains/Flang.cpp b/clang/lib/Driver/ToolChains/Flang.cpp index b1ca747e68b89..52608715e7d4f 100644 --- a/clang/lib/Driver/ToolChains/Flang.cpp +++ b/clang/lib/Driver/ToolChains/Flang.cpp @@ -12,6 +12,7 @@ #include "clang/Basic/CodeGenOptions.h" #include "clang/Driver/Options.h" +#include "clang/Driver/SanitizerArgs.h" #include "llvm/Frontend/Debug/Options.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Path.h" @@ -143,6 +144,15 @@ void Flang::addOtherOptions(const ArgList &Args, ArgStringList &CmdArgs) const { addDebugInfoKind(CmdArgs, DebugInfoKind); } +void Flang::addSanitizerOptions(const ToolChain &TC, const ArgList &Args, + ArgStringList &CmdArgs, + types::ID InputType) const { + SanitizerArgs SanArgs = TC.getSanitizerArgs(Args); + SanArgs.addArgs(TC, Args, CmdArgs, InputType); + // If Tc.getTriple() == amdgpu search for only allow -fsanitize=address for + // that target +} + void Flang::addCodegenOptions(const ArgList &Args, ArgStringList &CmdArgs) const { Arg *stackArrays = @@ -869,6 +879,9 @@ void Flang::ConstructJob(Compilation &C, const JobAction &JA, // Add Codegen options addCodegenOptions(Args, CmdArgs); + // Add Sanitizer Options + addSanitizerOptions(TC, Args, CmdArgs, InputType); + // Add R Group options Args.AddAllArgs(CmdArgs, options::OPT_R_Group); diff --git a/clang/lib/Driver/ToolChains/Flang.h b/clang/lib/Driver/ToolChains/Flang.h index 7c24a623af393..2b61955af7764 100644 --- a/clang/lib/Driver/ToolChains/Flang.h +++ b/clang/lib/Driver/ToolChains/Flang.h @@ -117,6 +117,15 @@ class LLVM_LIBRARY_VISIBILITY Flang : public Tool { void addCodegenOptions(const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs) const; + /// Extract sanitizer options for code generation from the driver arguments + /// and add them to the command arguments. + /// + /// \param [in] Args The list of input driver arguments + /// \param [out] CmdArgs The list of output command arguments + void addSanitizerOptions(const ToolChain &TC, const llvm::opt::ArgList &Args, + llvm::opt::ArgStringList &CmdArgs, + types::ID InputType) const; + /// Extract other compilation options from the driver arguments and add them /// to the command arguments. /// diff --git a/flang/include/flang/Frontend/CodeGenOptions.def b/flang/include/flang/Frontend/CodeGenOptions.def index d9dbd274e83e5..fa707c4ddbfcc 100644 --- a/flang/include/flang/Frontend/CodeGenOptions.def +++ b/flang/include/flang/Frontend/CodeGenOptions.def @@ -47,5 +47,72 @@ ENUM_CODEGENOPT(FramePointer, llvm::FramePointerKind, 2, llvm::FramePointerKind: ENUM_CODEGENOPT(DoConcurrentMapping, DoConcurrentMappingKind, 2, DoConcurrentMappingKind::DCMK_None) ///< Map `do concurrent` to OpenMP +CODEGENOPT(SanitizeAddressUseAfterScope , 1, 0) ///< Enable use-after-scope detection + ///< in AddressSanitizer +ENUM_CODEGENOPT(SanitizeAddressUseAfterReturn, + llvm::AsanDetectStackUseAfterReturnMode, 2, + llvm::AsanDetectStackUseAfterReturnMode::Runtime + ) ///< Set detection mode for stack-use-after-return. +CODEGENOPT(SanitizeAddressPoisonCustomArrayCookie, 1, + 0) ///< Enable poisoning operator new[] which is not a replaceable + ///< global allocation function in AddressSanitizer +CODEGENOPT(SanitizeAddressGlobalsDeadStripping, 1, 0) ///< Enable linker dead stripping + ///< of globals in AddressSanitizer +CODEGENOPT(SanitizeAddressUseOdrIndicator, 1, 0) ///< Enable ODR indicator globals +CODEGENOPT(SanitizeMemoryTrackOrigins, 2, 0) ///< Enable tracking origins in + ///< MemorySanitizer +ENUM_CODEGENOPT(SanitizeAddressDtor, llvm::AsanDtorKind, 2, + llvm::AsanDtorKind::Global) ///< Set how ASan global + ///< destructors are emitted. +CODEGENOPT(SanitizeMemoryParamRetval, 1, 0) ///< Enable detection of uninitialized + ///< parameters and return values + ///< in MemorySanitizer +CODEGENOPT(SanitizeMemoryUseAfterDtor, 1, 0) ///< Enable use-after-delete detection + ///< in MemorySanitizer +CODEGENOPT(SanitizeCfiCrossDso, 1, 0) ///< Enable cross-dso support in CFI. +CODEGENOPT(SanitizeMinimalRuntime, 1, 0) ///< Use "_minimal" sanitizer runtime for + ///< diagnostics. +CODEGENOPT(SanitizeCfiICallGeneralizePointers, 1, 0) ///< Generalize pointer types in + ///< CFI icall function signatures +CODEGENOPT(SanitizeCfiICallNormalizeIntegers, 1, 0) ///< Normalize integer types in + ///< CFI icall function signatures +CODEGENOPT(SanitizeCfiCanonicalJumpTables, 1, 0) ///< Make jump table symbols canonical + ///< instead of creating a local jump table. +CODEGENOPT(UniqueSourceFileNames, 1, 0) ///< Allow the compiler to assume that TUs + ///< have unique source file names at link time +CODEGENOPT(SanitizeKcfiArity, 1, 0) ///< Embed arity in KCFI patchable function prefix +CODEGENOPT(SanitizeCoverageType, 2, 0) ///< Type of sanitizer coverage + ///< instrumentation. +CODEGENOPT(SanitizeCoverageIndirectCalls, 1, 0) ///< Enable sanitizer coverage + ///< for indirect calls. +CODEGENOPT(SanitizeCoverageTraceBB, 1, 0) ///< Enable basic block tracing in + ///< in sanitizer coverage. +CODEGENOPT(SanitizeCoverageTraceCmp, 1, 0) ///< Enable cmp instruction tracing + ///< in sanitizer coverage. +CODEGENOPT(SanitizeCoverageTraceDiv, 1, 0) ///< Enable div instruction tracing + ///< in sanitizer coverage. +CODEGENOPT(SanitizeCoverageTraceGep, 1, 0) ///< Enable GEP instruction tracing + ///< in sanitizer coverage. +CODEGENOPT(SanitizeCoverage8bitCounters, 1, 0) ///< Use 8-bit frequency counters + ///< in sanitizer coverage. +CODEGENOPT(SanitizeCoverageTracePC, 1, 0) ///< Enable PC tracing + ///< in sanitizer coverage. +CODEGENOPT(SanitizeCoverageTracePCGuard, 1, 0) ///< Enable PC tracing with guard + ///< in sanitizer coverage. +CODEGENOPT(SanitizeCoverageInline8bitCounters, 1, 0) ///< Use inline 8bit counters. +CODEGENOPT(SanitizeCoverageInlineBoolFlag, 1, 0) ///< Use inline bool flag. +CODEGENOPT(SanitizeCoveragePCTable, 1, 0) ///< Create a PC Table. +CODEGENOPT(SanitizeCoverageControlFlow, 1, 0) ///< Collect control flow +CODEGENOPT(SanitizeCoverageNoPrune, 1, 0) ///< Disable coverage pruning. +CODEGENOPT(SanitizeCoverageStackDepth, 1, 0) ///< Enable max stack depth tracing +CODEGENOPT(SanitizeCoverageTraceLoads, 1, 0) ///< Enable tracing of loads. +CODEGENOPT(SanitizeCoverageTraceStores, 1, 0) ///< Enable tracing of stores. +CODEGENOPT(SanitizeBinaryMetadataCovered, 1, 0) ///< Emit PCs for covered functions. +CODEGENOPT(SanitizeBinaryMetadataAtomics, 1, 0) ///< Emit PCs for atomic operations. +CODEGENOPT(SanitizeBinaryMetadataUAR, 1, 0) ///< Emit PCs for start of functions + ///< that are subject for use-after-return checking. +CODEGENOPT(SanitizeStats , 1, 0) ///< Collect statistics for sanitizers. +CODEGENOPT(DisableIntegratedAS, 1, 0) ///< -no-integrated-as + #undef CODEGENOPT #undef ENUM_CODEGENOPT diff --git a/flang/include/flang/Frontend/CodeGenOptions.h b/flang/include/flang/Frontend/CodeGenOptions.h index 2b4e823b3fef4..b2a799682dfe1 100644 --- a/flang/include/flang/Frontend/CodeGenOptions.h +++ b/flang/include/flang/Frontend/CodeGenOptions.h @@ -16,6 +16,7 @@ #define FORTRAN_FRONTEND_CODEGENOPTIONS_H #include "flang/Optimizer/OpenMP/Utils.h" +#include "clang/Basic/Sanitizers.h" #include "llvm/Frontend/Debug/Options.h" #include "llvm/Frontend/Driver/CodeGenOptions.h" #include "llvm/Support/CodeGen.h" @@ -148,6 +149,50 @@ class CodeGenOptions : public CodeGenOptionsBase { /// OpenMP is enabled. using DoConcurrentMappingKind = flangomp::DoConcurrentMappingKind; + /// Set of sanitizer checks that are non-fatal (i.e. execution should be + /// continued when possible). + clang::SanitizerSet SanitizeRecover; + + /// Set of sanitizer checks that trap rather than diagnose. + clang::SanitizerSet SanitizeTrap; + + /// Set of sanitizer checks that can merge handlers (smaller code size at + /// the expense of debuggability). + clang::SanitizerSet SanitizeMergeHandlers; + + /// Set of thresholds in a range [0.0, 1.0]: the top hottest code responsible + /// for the given fraction of PGO counters will be excluded from sanitization + /// (0.0 [default] to skip none, 1.0 to skip all). + clang::SanitizerMaskCutoffs SanitizeSkipHotCutoffs; + + /// Path to allowlist file specifying which objects + /// (files, functions) should exclusively be instrumented + /// by sanitizer coverage pass. + std::vector<std::string> SanitizeCoverageAllowlistFiles; + + /// Path to ignorelist file specifying which objects + /// (files, functions) listed for instrumentation by sanitizer + /// coverage pass should actually not be instrumented. + std::vector<std::string> SanitizeCoverageIgnorelistFiles; + + /// Path to ignorelist file specifying which objects + /// (files, functions) listed for instrumentation by sanitizer + /// binary metadata pass should not be instrumented. + std::vector<std::string> SanitizeMetadataIgnorelistFiles; + + // Check if any one of SanitizeCoverage* is enabled. + bool hasSanitizeCoverage() const { + return SanitizeCoverageType || SanitizeCoverageIndirectCalls || + SanitizeCoverageTraceCmp || SanitizeCoverageTraceLoads || + SanitizeCoverageTraceStores || SanitizeCoverageControlFlow; + } + + // Check if any one of SanitizeBinaryMetadata* is enabled. + bool hasSanitizeBinaryMetadata() const { + return SanitizeBinaryMetadataCovered || SanitizeBinaryMetadataAtomics || + SanitizeBinaryMetadataUAR; + } + // Define accessors/mutators for code generation options of enumeration type. #define CODEGENOPT(Name, Bits, Default) #define ENUM_CODEGENOPT(Name, Type, Bits, Default) \ @@ -158,6 +203,8 @@ class CodeGenOptions : public CodeGenOptionsBase { CodeGenOptions(); }; +bool asanUseGlobalsGC(const llvm::Triple &T, const CodeGenOptions &CGOpts); + std::optional<llvm::CodeModel::Model> getCodeModel(llvm::StringRef string); } // end namespace Fortran::frontend diff --git a/flang/include/flang/Support/LangOptions.def b/flang/include/flang/Support/LangOptions.def index d5bf7a2ecc036..9bc2c6ca5b10d 100644 --- a/flang/include/flang/Support/LangOptions.def +++ b/flang/include/flang/Support/LangOptions.def @@ -62,5 +62,6 @@ LANGOPT(OpenMPNoNestedParallelism, 1, 0) LANGOPT(VScaleMin, 32, 0) ///< Minimum vscale range value LANGOPT(VScaleMax, 32, 0) ///< Maximum vscale range value +LANGOPT(SanitizeAddressFieldPadding, 2, 0) #undef LANGOPT #undef ENUM_LANGOPT diff --git a/flang/include/flang/Support/LangOptions.h b/flang/include/flang/Support/LangOptions.h index 1dd676e62a9e5..00c6bf743ce60 100644 --- a/flang/include/flang/Support/LangOptions.h +++ b/flang/include/flang/Support/LangOptions.h @@ -18,10 +18,10 @@ #include <string> #include <vector> +#include "clang/Basic/Sanitizers.h" #include "llvm/TargetParser/Triple.h" namespace Fortran::common { - /// Bitfields of LangOptions, split out from LangOptions to ensure /// that this large collection of bitfields is a trivial class type. class LangOptionsBase { @@ -72,6 +72,15 @@ class LangOptions : public LangOptionsBase { /// host code generation. std::string OMPHostIRFile; + /// Set of enabled sanitizers. + clang::SanitizerSet Sanitize; + /// Is at least one coverage instrumentation type enabled. + bool SanitizeCoverage = false; + + /// Paths to files specifying which objects + /// (files, functions, variables) should not be instrumented. + std::vector<std::string> NoSanitizeFiles; + /// List of triples passed in using -fopenmp-targets. std::vector<llvm::Triple> OMPTargetTriples; diff --git a/flang/lib/Frontend/CodeGenOptions.cpp b/flang/lib/Frontend/CodeGenOptions.cpp index 8a9d3c27c8bc3..18988ec5d3f78 100644 --- a/flang/lib/Frontend/CodeGenOptions.cpp +++ b/flang/lib/Frontend/CodeGenOptions.cpp @@ -11,17 +11,46 @@ //===----------------------------------------------------------------------===// #include "flang/Frontend/CodeGenOptions.h" +#include "llvm/TargetParser/Triple.h" #include <optional> #include <string.h> namespace Fortran::frontend { +using namespace llvm; + CodeGenOptions::CodeGenOptions() { #define CODEGENOPT(Name, Bits, Default) Name = Default; #define ENUM_CODEGENOPT(Name, Type, Bits, Default) set##Name(Default); #include "flang/Frontend/CodeGenOptions.def" } +// Check if ASan should use GC-friendly instrumentation for globals. +// First of all, there is no point if -fdata-sections is off (expect for MachO, +// where this is not a factor). Also, on ELF this feature requires an assembler +// extension that only works with -integrated-as at the moment. +bool asanUseGlobalsGC(const Triple &T, const CodeGenOptions &CGOpts) { + if (!CGOpts.SanitizeAddressGlobalsDeadStripping) + return false; + switch (T.getObjectFormat()) { + case Triple::MachO: + case Triple::COFF: + return true; + case Triple::ELF: + return !CGOpts.DisableIntegratedAS; + case Triple::GOFF: + llvm::report_fatal_error("ASan not implemented for GOFF"); + case Triple::XCOFF: + llvm::report_fatal_error("ASan not implemented for XCOFF."); + case Triple::Wasm: + case Triple::DXContainer: + case Triple::SPIRV: + case Triple::UnknownObjectFormat: + break; + } + return false; +} + std::optional<llvm::CodeModel::Model> getCodeModel(llvm::StringRef string) { return llvm::StringSwitch<std::optional<llvm::CodeModel::Model>>(string) .Case("tiny", llvm::CodeModel::Model::Tiny) diff --git a/flang/lib/Frontend/CompilerInvocation.cpp b/flang/lib/Frontend/CompilerInvocation.cpp index 238079a09ef3a..7283cd90843d0 100644 --- a/flang/lib/Frontend/CompilerInvocation.cpp +++ b/flang/lib/Frontend/CompilerInvocation.cpp @@ -23,6 +23,7 @@ #include "clang/Basic/AllDiagnostics.h" #include "clang/Basic/DiagnosticDriver.h" #include "clang/Basic/DiagnosticOptions.h" +#include "clang/Basic/Sanitizers.h" #include "clang/Driver/Driver.h" #include "clang/Driver/DriverDiagnostic.h" #include "clang/Driver/OptionUtils.h" @@ -256,6 +257,82 @@ parseOptimizationRemark(clang::DiagnosticsEngine &diags, return result; } +static void parseSanitizerKinds(llvm::StringRef FlagName, + const std::vector<std::string> &Sanitizers, + clang::DiagnosticsEngine &Diags, + clang::SanitizerSet &S) { + for (const auto &Sanitizer : Sanitizers) { + clang::SanitizerMask K = + clang::parseSanitizerValue(Sanitizer, /*AllowGroups=*/false); + if (K == clang::SanitizerMask()) + Diags.Report(clang::diag::err_drv_invalid_value) << FlagName << Sanitizer; + else + S.set(K, true); + } +} + +static llvm::SmallVector<llvm::StringRef, 4> +serializeSanitizerKinds(clang::SanitizerSet S) { + llvm::SmallVector<llvm::StringRef, 4> Values; + serializeSanitizerSet(S, Values); + return Values; +} + +static clang::SanitizerMaskCutoffs +parseSanitizerWeightedKinds(llvm::StringRef FlagName, + const std::vector<std::string> &Sanitizers, + clang::DiagnosticsEngine &Diags) { + clang::SanitizerMaskCutoffs Cutoffs; + for (const auto &Sanitizer : Sanitizers) { + if (!parseSanitizerWeightedValue(Sanitizer, /*AllowGroups=*/false, Cutoffs)) + Diags.Report(clang::diag::err_drv_invalid_value) << FlagName << Sanitizer; + } + return Cutoffs; +} + +static bool parseSanitizerArgs(CompilerInvocation &res, + llvm::opt::ArgList &args, + clang::DiagnosticsEngine &diags) { + auto &LangOpts = res.getLangOpts(); + auto &CodeGenOpts = res.getCodeGenOpts(); + + parseSanitizerKinds( + "-fsanitize-recover=", + args.getAllArgValues(clang::driver::options::OPT_fsanitize_recover_EQ), + diags, CodeGenOpts.SanitizeRecover); + parseSanitizerKinds( + "-fsanitize-trap=", + args.getAllArgValues(clang::driver::options::OPT_fsanitize_trap_EQ), + diags, CodeGenOpts.SanitizeTrap); + parseSanitizerKinds( + "-fsanitize-merge=", + args.getAllArgValues( + clang::driver::options::OPT_fsanitize_merge_handlers_EQ), + diags, CodeGenOpts.SanitizeMergeHandlers); + + // Parse -fsanitize-skip-hot-cutoff= arguments. + CodeGenOpts.SanitizeSkipHotCutoffs = parseSanitizerWeightedKinds( + "-fsanitize-skip-hot-cutoff=", + args.getAllArgValues( + clang::driver::options::OPT_fsanitize_skip_hot_cutoff_EQ), + diags); + + // Parse -fsanitize= arguments. + parseSanitizerKinds( + "-fsanitize=", + args.getAllArgValues(clang::driver::options::OPT_fsanitize_EQ), diags, + LangOpts.Sanitize); + + LangOpts.NoSanitizeFiles = + args.getAllArgValues(clang::driver::options::OPT_fsanitize_ignorelist_EQ); + std::vector<std::string> systemIgnorelists = args.getAllArgValues( + clang::driver::options::OPT_fsanitize_system_ignorelist_EQ); + LangOpts.NoSanitizeFiles.insert(LangOpts.NoSanitizeFiles.end(), + systemIgnorelists.begin(), + systemIgnorelists.end()); + return true; +} + static void parseCodeGenArgs(Fortran::frontend::CodeGenOptions &opts, llvm::opt::ArgList &args, clang::DiagnosticsEngine &diags) { @@ -395,6 +472,10 @@ static void parseCodeGenArgs(Fortran::frontend::CodeGenOptions &opts, opts.RecordCommandLine = a->getValue(); } + // -mlink-bitcode-file + for (auto *a : args.filtered(clang::driver::options::OPT_mlink_bitcode_file)) + opts.BuiltinBCLibs.push_back(a->getValue()); + // -mlink-builtin-bitcode for (auto *a : args.filtered(clang::driver::options::OPT_mlink_builtin_bitcode)) @@ -1500,6 +1581,7 @@ bool CompilerInvocation::createFromArgs( success &= parseVectorLibArg(invoc.getCodeGenOpts(), args, diags); success &= parseSemaArgs(invoc, args, diags); success &= parseDialectArgs(invoc, args, diags); + success &= parseSanitizerArgs(invoc, args, diags); success &= parseOpenMPArgs(invoc, args, diags); success &= parseDiagArgs(invoc, args, diags); diff --git a/flang/lib/Frontend/FrontendActions.cpp b/flang/lib/Frontend/FrontendActions.cpp index e5a15c555fa5e..e6ab0402ce6b2 100644 --- a/flang/lib/Frontend/FrontendActions.cpp +++ b/flang/lib/Frontend/FrontendActions.cpp @@ -26,6 +26,7 @@ #include "flang/Optimizer/Transforms/Passes.h" #include "flang/Semantics/runtime-type-info.h" #include "flang/Semantics/unparse-with-symbols.h" +#include "flang/Support/LangOptions.h" #include "flang/Support/default-kinds.h" #include "flang/Tools/CrossToolHelpers.h" @@ -67,7 +68,10 @@ #include "llvm/TargetParser/RISCVISAInfo.h" #include "llvm/TargetParser/RISCVTargetParser.h" #include "llvm/Transforms/IPO/Internalize.h" +#include "llvm/Transforms/Instrumentation/AddressSanitizer.h" +#include "llvm/Transforms/Instrumentation/AddressSanitizerOptions.h" #include "llvm/Transforms/Utils/ModuleUtils.h" +#include <clang/Basic/Sanitizers.h> #include <memory> #include <system_error> @@ -714,6 +718,7 @@ void CodeGenAction::generateLLVMIR() { CompilerInstance &ci = this->getInstance(); CompilerInvocation &invoc = ci.getInvocation(); const CodeGenOptions &opts = invoc.getCodeGenOpts(); + const common::LangOptions &langopts = invoc.getLangOpts(); const auto &mathOpts = invoc.getLoweringOpts().getMathOptions(); llvm::OptimizationLevel level = mapToLevel(opts); mlir::DefaultTimingManager &timingMgr = ci.getTimingManager(); @@ -787,6 +792,11 @@ void CodeGenAction::generateLLVMIR() { return; } + for (llvm::Function &F : llvmModule->getFunctionList()) { + if (langopts.Sanitize.has(clang::SanitizerKind::Address)) + F.addFnAttr(llvm::Attribute::SanitizeAddress); + } + // Set PIC/PIE level LLVM module flags. if (opts.PICLevel > 0) { llvmModule->setPICLevel(static_cast<llvm::PICLevel::Level>(opts.PICLevel)); @@ -899,9 +909,34 @@ static void generateMachineCodeOrAssemblyImpl(clang::DiagnosticsEngine &diags, delete tlii; } +void addSanitizers(const llvm::Triple &Triple, + const CodeGenOptions &flangCodeGenOpts, + const Fortran::common::LangOptions &flangLangOpts, + llvm::PassBuilder &PB, llvm::ModulePassManager &MPM) { + auto ASanPass = [&](clang::SanitizerMask Mask, bool CompileKernel) { + if (flangLangOpts.Sanitize.has(Mask)) { + bool UseGlobalGC = asanUseGlobalsGC(Triple, flangCodeGenOpts); + bool UseOdrIndicator = flangCodeGenOpts.SanitizeAddressUseOdrIndicator; + llvm::AsanDtorKind DestructorKind = + flangCodeGenOpts.getSanitizeAddressDtor(); + llvm::AddressSanitizerOptions Opts; + Opts.CompileKernel = CompileKernel; + Opts.Recover = flangCodeGenOpts.SanitizeRecover.has(Mask); + Opts.UseAfterScope = flangCodeGenOpts.SanitizeAddressUseAfterScope; + Opts.UseAfterReturn = flangCodeGenOpts.getSanitizeAddressUseAfterReturn(); + MPM.addPass(llvm::AddressSanitizerPass(Opts, UseGlobalGC, UseOdrIndicator, + DestructorKind)); + } + }; + ASanPass(clang::SanitizerKind::Address, false); + ASanPass(clang::SanitizerKind::KernelAddress, true); +} + void CodeGenAction::runOptimizationPipeline(llvm::raw_pwrite_stream &os) { CompilerInstance &ci = getInstance(); const CodeGenOptions &opts = ci.getInvocation().getCodeGenOpts(); + const Fortran::common::LangOptions &langopts = + ci.getInvocation().getLangOpts(); clang::DiagnosticsEngine &diags = ci.getDiagnostics(); llvm::OptimizationLevel level = mapToLevel(opts); @@ -966,6 +1001,8 @@ void CodeGenAction::runOptimizationPipeline(llvm::raw_pwrite_stream &os) { else mpm = pb.buildPerModuleDefaultPipeline(level); + addSanitizers(triple, opts, langopts, pb, mpm); + if (action == BackendActionTy::Backend_EmitBC) mpm.addPass(llvm::BitcodeWriterPass(os)); else if (action == BackendActionTy::Backend_EmitLL) _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits