<div dir="ltr"><div class="gmail_extra"><br><div class="gmail_quote">On Thu, Mar 20, 2014 at 4:52 PM, Alexander Potapenko <span dir="ltr"><<a href="mailto:glider@google.com" target="_blank">glider@google.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: glider<br>
Date: Thu Mar 20 07:52:52 2014<br>
New Revision: 204339<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=204339&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=204339&view=rev</a><br>
Log:<br>
[libsanitizer] Introduce flag descriptions.<br>
Extend ParseFlag to accept the |description| parameter, add dummy values for all existing flags.<br>
As the flags are parsed their descriptions are stored in a global linked list.<br>
The tool can later call __sanitizer::PrintFlagDescriptions() to dump all the flag names and their descriptions.<br>
Add the 'help' flag and make ASan, TSan and MSan print the flags if 'help' is set to 1.<br>
<br>
Modified:<br>
    compiler-rt/trunk/lib/asan/asan_rtl.cc<br>
    compiler-rt/trunk/lib/dfsan/dfsan.cc<br>
    compiler-rt/trunk/lib/lsan/lsan_common.cc<br>
    compiler-rt/trunk/lib/msan/msan.cc<br>
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_flags.cc<br>
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_flags.h<br>
    compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_flags_test.cc<br>
    compiler-rt/trunk/lib/tsan/dd/dd_rtl.cc<br>
    compiler-rt/trunk/lib/tsan/rtl/tsan_flags.cc<br>
<br>
Modified: compiler-rt/trunk/lib/asan/asan_rtl.cc<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_rtl.cc?rev=204339&r1=204338&r2=204339&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_rtl.cc?rev=204339&r1=204338&r2=204339&view=diff</a><br>

==============================================================================<br>
--- compiler-rt/trunk/lib/asan/asan_rtl.cc (original)<br>
+++ compiler-rt/trunk/lib/asan/asan_rtl.cc Thu Mar 20 07:52:52 2014<br>
@@ -95,50 +95,52 @@ static void ParseFlagsFromString(Flags *<br>
   ParseCommonFlagsFromString(cf, str);<br>
   CHECK((uptr)cf->malloc_context_size <= kStackTraceMax);<br>
<br>
-  ParseFlag(str, &f->quarantine_size, "quarantine_size");<br>
-  ParseFlag(str, &f->redzone, "redzone");<br>
-  ParseFlag(str, &f->max_redzone, "max_redzone");<br>
+  ParseFlag(str, &f->quarantine_size, "quarantine_size", "");<br>
+  ParseFlag(str, &f->redzone, "redzone", "");<br>
+  ParseFlag(str, &f->max_redzone, "max_redzone", "");<br>
   CHECK_GE(f->redzone, 16);<br>
   CHECK_GE(f->max_redzone, f->redzone);<br>
   CHECK_LE(f->max_redzone, 2048);<br>
   CHECK(IsPowerOfTwo(f->redzone));<br>
   CHECK(IsPowerOfTwo(f->max_redzone));<br>
<br>
-  ParseFlag(str, &f->debug, "debug");<br>
-  ParseFlag(str, &f->report_globals, "report_globals");<br>
-  ParseFlag(str, &f->check_initialization_order, "check_initialization_order");<br>
-<br>
-  ParseFlag(str, &f->replace_str, "replace_str");<br>
-  ParseFlag(str, &f->replace_intrin, "replace_intrin");<br>
-  ParseFlag(str, &f->mac_ignore_invalid_free, "mac_ignore_invalid_free");<br>
+  ParseFlag(str, &f->debug, "debug", "");<br>
+  ParseFlag(str, &f->report_globals, "report_globals", "");<br>
+  ParseFlag(str, &f->check_initialization_order,<br>
+            "check_initialization_order", "");<br>
+<br>
+  ParseFlag(str, &f->replace_str, "replace_str", "");<br>
+  ParseFlag(str, &f->replace_intrin, "replace_intrin", "");<br>
+  ParseFlag(str, &f->mac_ignore_invalid_free, "mac_ignore_invalid_free", "");<br>
   ParseFlag(str, &f->detect_stack_use_after_return,<br>
-            "detect_stack_use_after_return");<br>
-  ParseFlag(str, &f->min_uar_stack_size_log, "min_uar_stack_size_log");<br>
-  ParseFlag(str, &f->max_uar_stack_size_log, "max_uar_stack_size_log");<br>
-  ParseFlag(str, &f->uar_noreserve, "uar_noreserve");<br>
-  ParseFlag(str, &f->max_malloc_fill_size, "max_malloc_fill_size");<br>
-  ParseFlag(str, &f->malloc_fill_byte, "malloc_fill_byte");<br>
-  ParseFlag(str, &f->exitcode, "exitcode");<br>
-  ParseFlag(str, &f->allow_user_poisoning, "allow_user_poisoning");<br>
-  ParseFlag(str, &f->sleep_before_dying, "sleep_before_dying");<br>
-  ParseFlag(str, &f->check_malloc_usable_size, "check_malloc_usable_size");<br>
-  ParseFlag(str, &f->unmap_shadow_on_exit, "unmap_shadow_on_exit");<br>
-  ParseFlag(str, &f->abort_on_error, "abort_on_error");<br>
-  ParseFlag(str, &f->print_stats, "print_stats");<br>
-  ParseFlag(str, &f->print_legend, "print_legend");<br>
-  ParseFlag(str, &f->atexit, "atexit");<br>
-  ParseFlag(str, &f->coverage, "coverage");<br>
-  ParseFlag(str, &f->disable_core, "disable_core");<br>
-  ParseFlag(str, &f->allow_reexec, "allow_reexec");<br>
-  ParseFlag(str, &f->print_full_thread_history, "print_full_thread_history");<br>
-  ParseFlag(str, &f->poison_heap, "poison_heap");<br>
-  ParseFlag(str, &f->poison_partial, "poison_partial");<br>
-  ParseFlag(str, &f->alloc_dealloc_mismatch, "alloc_dealloc_mismatch");<br>
-  ParseFlag(str, &f->strict_memcmp, "strict_memcmp");<br>
-  ParseFlag(str, &f->strict_init_order, "strict_init_order");<br>
-  ParseFlag(str, &f->start_deactivated, "start_deactivated");<br>
+            "detect_stack_use_after_return", "");<br>
+  ParseFlag(str, &f->min_uar_stack_size_log, "min_uar_stack_size_log", "");<br>
+  ParseFlag(str, &f->max_uar_stack_size_log, "max_uar_stack_size_log", "");<br>
+  ParseFlag(str, &f->uar_noreserve, "uar_noreserve", "");<br>
+  ParseFlag(str, &f->max_malloc_fill_size, "max_malloc_fill_size", "");<br>
+  ParseFlag(str, &f->malloc_fill_byte, "malloc_fill_byte", "");<br>
+  ParseFlag(str, &f->exitcode, "exitcode", "");<br>
+  ParseFlag(str, &f->allow_user_poisoning, "allow_user_poisoning", "");<br>
+  ParseFlag(str, &f->sleep_before_dying, "sleep_before_dying", "");<br>
+  ParseFlag(str, &f->check_malloc_usable_size, "check_malloc_usable_size", "");<br>
+  ParseFlag(str, &f->unmap_shadow_on_exit, "unmap_shadow_on_exit", "");<br>
+  ParseFlag(str, &f->abort_on_error, "abort_on_error", "");<br>
+  ParseFlag(str, &f->print_stats, "print_stats", "");<br>
+  ParseFlag(str, &f->print_legend, "print_legend", "");<br>
+  ParseFlag(str, &f->atexit, "atexit", "");<br>
+  ParseFlag(str, &f->coverage, "coverage", "");<br>
+  ParseFlag(str, &f->disable_core, "disable_core", "");<br>
+  ParseFlag(str, &f->allow_reexec, "allow_reexec", "");<br>
+  ParseFlag(str, &f->print_full_thread_history,<br>
+            "print_full_thread_history", "");<br>
+  ParseFlag(str, &f->poison_heap, "poison_heap", "");<br>
+  ParseFlag(str, &f->poison_partial, "poison_partial", "");<br>
+  ParseFlag(str, &f->alloc_dealloc_mismatch, "alloc_dealloc_mismatch", "");<br>
+  ParseFlag(str, &f->strict_memcmp, "strict_memcmp", "");<br>
+  ParseFlag(str, &f->strict_init_order, "strict_init_order", "");<br>
+  ParseFlag(str, &f->start_deactivated, "start_deactivated", "");<br>
   ParseFlag(str, &f->detect_invalid_pointer_pairs,<br>
-            "detect_invalid_pointer_pairs");<br>
+            "detect_invalid_pointer_pairs", "");<br>
 }<br>
<br>
 void InitializeFlags(Flags *f, const char *env) {<br>
@@ -196,6 +198,9 @@ void InitializeFlags(Flags *f, const cha<br>
<br>
   // Override from command line.<br>
   ParseFlagsFromString(f, env);<br>
+  if (common_flags()->help) {<br>
+    PrintFlagDescriptions();<br>
+  }<br>
<br>
 #if !CAN_SANITIZE_LEAKS<br>
   if (cf->detect_leaks) {<br>
<br>
Modified: compiler-rt/trunk/lib/dfsan/dfsan.cc<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/dfsan/dfsan.cc?rev=204339&r1=204338&r2=204339&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/dfsan/dfsan.cc?rev=204339&r1=204338&r2=204339&view=diff</a><br>

==============================================================================<br>
--- compiler-rt/trunk/lib/dfsan/dfsan.cc (original)<br>
+++ compiler-rt/trunk/lib/dfsan/dfsan.cc Thu Mar 20 07:52:52 2014<br>
@@ -235,9 +235,9 @@ static void InitializeFlags(Flags &f, co<br>
   f.warn_nonzero_labels = false;<br>
   f.strict_data_dependencies = true;<br>
<br>
-  ParseFlag(env, &f.warn_unimplemented, "warn_unimplemented");<br>
-  ParseFlag(env, &f.warn_nonzero_labels, "warn_nonzero_labels");<br>
-  ParseFlag(env, &f.strict_data_dependencies, "strict_data_dependencies");<br>
+  ParseFlag(env, &f.warn_unimplemented, "warn_unimplemented", "");<br>
+  ParseFlag(env, &f.warn_nonzero_labels, "warn_nonzero_labels", "");<br>
+  ParseFlag(env, &f.strict_data_dependencies, "strict_data_dependencies", "");<br>
 }<br>
<br>
 #ifdef DFSAN_NOLIBC<br>
<br>
Modified: compiler-rt/trunk/lib/lsan/lsan_common.cc<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/lsan/lsan_common.cc?rev=204339&r1=204338&r2=204339&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/lsan/lsan_common.cc?rev=204339&r1=204338&r2=204339&view=diff</a><br>

==============================================================================<br>
--- compiler-rt/trunk/lib/lsan/lsan_common.cc (original)<br>
+++ compiler-rt/trunk/lib/lsan/lsan_common.cc Thu Mar 20 07:52:52 2014<br>
@@ -57,23 +57,23 @@ static void InitializeFlags() {<br>
<br>
   const char *options = GetEnv("LSAN_OPTIONS");<br>
   if (options) {<br>
-    ParseFlag(options, &f->use_registers, "use_registers");<br>
-    ParseFlag(options, &f->use_globals, "use_globals");<br>
-    ParseFlag(options, &f->use_stacks, "use_stacks");<br>
-    ParseFlag(options, &f->use_tls, "use_tls");<br>
-    ParseFlag(options, &f->use_root_regions, "use_root_regions");<br>
-    ParseFlag(options, &f->use_unaligned, "use_unaligned");<br>
-    ParseFlag(options, &f->use_poisoned, "use_poisoned");<br>
-    ParseFlag(options, &f->report_objects, "report_objects");<br>
-    ParseFlag(options, &f->resolution, "resolution");<br>
+    ParseFlag(options, &f->use_registers, "use_registers", "");<br>
+    ParseFlag(options, &f->use_globals, "use_globals", "");<br>
+    ParseFlag(options, &f->use_stacks, "use_stacks", "");<br>
+    ParseFlag(options, &f->use_tls, "use_tls", "");<br>
+    ParseFlag(options, &f->use_root_regions, "use_root_regions", "");<br>
+    ParseFlag(options, &f->use_unaligned, "use_unaligned", "");<br>
+    ParseFlag(options, &f->use_poisoned, "use_poisoned", "");<br>
+    ParseFlag(options, &f->report_objects, "report_objects", "");<br>
+    ParseFlag(options, &f->resolution, "resolution", "");<br>
     CHECK_GE(&f->resolution, 0);<br>
-    ParseFlag(options, &f->max_leaks, "max_leaks");<br>
+    ParseFlag(options, &f->max_leaks, "max_leaks", "");<br>
     CHECK_GE(&f->max_leaks, 0);<br>
-    ParseFlag(options, &f->log_pointers, "log_pointers");<br>
-    ParseFlag(options, &f->log_threads, "log_threads");<br>
-    ParseFlag(options, &f->exitcode, "exitcode");<br>
-    ParseFlag(options, &f->print_suppressions, "print_suppressions");<br>
-    ParseFlag(options, &f->suppressions, "suppressions");<br>
+    ParseFlag(options, &f->log_pointers, "log_pointers", "");<br>
+    ParseFlag(options, &f->log_threads, "log_threads", "");<br>
+    ParseFlag(options, &f->exitcode, "exitcode", "");<br>
+    ParseFlag(options, &f->print_suppressions, "print_suppressions", "");<br>
+    ParseFlag(options, &f->suppressions, "suppressions", "");<br>
   }<br>
 }<br>
<br>
<br>
Modified: compiler-rt/trunk/lib/msan/msan.cc<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/msan/msan.cc?rev=204339&r1=204338&r2=204339&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/msan/msan.cc?rev=204339&r1=204338&r2=204339&view=diff</a><br>

==============================================================================<br>
--- compiler-rt/trunk/lib/msan/msan.cc (original)<br>
+++ compiler-rt/trunk/lib/msan/msan.cc Thu Mar 20 07:52:52 2014<br>
@@ -107,24 +107,24 @@ static atomic_uint32_t NumStackOriginDes<br>
 static void ParseFlagsFromString(Flags *f, const char *str) {<br>
   CommonFlags *cf = common_flags();<br>
   ParseCommonFlagsFromString(cf, str);<br>
-  ParseFlag(str, &f->poison_heap_with_zeroes, "poison_heap_with_zeroes");<br>
-  ParseFlag(str, &f->poison_stack_with_zeroes, "poison_stack_with_zeroes");<br>
-  ParseFlag(str, &f->poison_in_malloc, "poison_in_malloc");<br>
-  ParseFlag(str, &f->poison_in_free, "poison_in_free");<br>
-  ParseFlag(str, &f->exit_code, "exit_code");<br>
+  ParseFlag(str, &f->poison_heap_with_zeroes, "poison_heap_with_zeroes", "");<br>
+  ParseFlag(str, &f->poison_stack_with_zeroes, "poison_stack_with_zeroes", "");<br>
+  ParseFlag(str, &f->poison_in_malloc, "poison_in_malloc", "");<br>
+  ParseFlag(str, &f->poison_in_free, "poison_in_free", "");<br>
+  ParseFlag(str, &f->exit_code, "exit_code", "");<br>
   if (f->exit_code < 0 || f->exit_code > 127) {<br>
     Printf("Exit code not in [0, 128) range: %d\n", f->exit_code);<br>
     Die();<br>
   }<br>
-  ParseFlag(str, &f->report_umrs, "report_umrs");<br>
-  ParseFlag(str, &f->wrap_signals, "wrap_signals");<br>
+  ParseFlag(str, &f->report_umrs, "report_umrs", "");<br>
+  ParseFlag(str, &f->wrap_signals, "wrap_signals", "");<br>
<br>
   // keep_going is an old name for halt_on_error,<br>
   // and it has inverse meaning.<br>
   f->halt_on_error = !f->halt_on_error;<br>
-  ParseFlag(str, &f->halt_on_error, "keep_going");<br>
+  ParseFlag(str, &f->halt_on_error, "keep_going", "");<br>
   f->halt_on_error = !f->halt_on_error;<br>
-  ParseFlag(str, &f->halt_on_error, "halt_on_error");<br>
+  ParseFlag(str, &f->halt_on_error, "halt_on_error", "");<br>
 }<br>
<br>
 static void InitializeFlags(Flags *f, const char *options) {<br>
@@ -277,6 +277,7 @@ void __msan_init() {<br>
<br>
   const char *msan_options = GetEnv("MSAN_OPTIONS");<br>
   InitializeFlags(&msan_flags, msan_options);<br>
+  if (common_flags()->help) PrintFlagDescriptions();<br>
   __sanitizer_set_report_path(common_flags()->log_path);<br>
<br>
   InitializeInterceptors();<br>
<br>
Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_flags.cc<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_flags.cc?rev=204339&r1=204338&r2=204339&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_flags.cc?rev=204339&r1=204338&r2=204339&view=diff</a><br>

==============================================================================<br>
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_flags.cc (original)<br>
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_flags.cc Thu Mar 20 07:52:52 2014<br>
@@ -20,6 +20,14 @@ namespace __sanitizer {<br>
<br>
 CommonFlags common_flags_dont_use;<br>
<br>
+struct FlagDescriptionList {<br>
+  const char *name;<br>
+  const char *description;<br>
+  FlagDescriptionList *next;<br>
+};<br>
+<br>
+FlagDescriptionList *flag_descriptions = 0, *last_flag_description = 0;<br></blockquote><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">+<br>
 void SetCommonFlagsDefaults(CommonFlags *f) {<br>
   f->symbolize = true;<br>
   f->external_symbolizer_path = 0;<br>
@@ -47,29 +55,31 @@ void SetCommonFlagsDefaults(CommonFlags<br>
 }<br>
<br>
 void ParseCommonFlagsFromString(CommonFlags *f, const char *str) {<br>
-  ParseFlag(str, &f->symbolize, "symbolize");<br>
-  ParseFlag(str, &f->external_symbolizer_path, "external_symbolizer_path");<br>
-  ParseFlag(str, &f->allow_addr2line, "allow_addr2line");<br>
-  ParseFlag(str, &f->strip_path_prefix, "strip_path_prefix");<br>
-  ParseFlag(str, &f->fast_unwind_on_fatal, "fast_unwind_on_fatal");<br>
-  ParseFlag(str, &f->fast_unwind_on_malloc, "fast_unwind_on_malloc");<br>
-  ParseFlag(str, &f->handle_ioctl, "handle_ioctl");<br>
-  ParseFlag(str, &f->malloc_context_size, "malloc_context_size");<br>
-  ParseFlag(str, &f->log_path, "log_path");<br>
-  ParseFlag(str, &f->verbosity, "verbosity");<br>
-  ParseFlag(str, &f->detect_leaks, "detect_leaks");<br>
-  ParseFlag(str, &f->leak_check_at_exit, "leak_check_at_exit");<br>
-  ParseFlag(str, &f->allocator_may_return_null, "allocator_may_return_null");<br>
-  ParseFlag(str, &f->print_summary, "print_summary");<br>
-  ParseFlag(str, &f->check_printf, "check_printf");<br>
-  ParseFlag(str, &f->handle_segv, "handle_segv");<br>
-  ParseFlag(str, &f->allow_user_segv_handler, "allow_user_segv_handler");<br>
-  ParseFlag(str, &f->use_sigaltstack, "use_sigaltstack");<br>
-  ParseFlag(str, &f->detect_deadlocks, "detect_deadlocks");<br>
+  ParseFlag(str, &f->symbolize, "symbolize", "");<br>
+  ParseFlag(str, &f->external_symbolizer_path, "external_symbolizer_path", "");<br>
+  ParseFlag(str, &f->allow_addr2line, "allow_addr2line", "");<br>
+  ParseFlag(str, &f->strip_path_prefix, "strip_path_prefix", "");<br>
+  ParseFlag(str, &f->fast_unwind_on_fatal, "fast_unwind_on_fatal", "");<br>
+  ParseFlag(str, &f->fast_unwind_on_malloc, "fast_unwind_on_malloc", "");<br>
+  ParseFlag(str, &f->handle_ioctl, "handle_ioctl", "");<br>
+  ParseFlag(str, &f->malloc_context_size, "malloc_context_size", "");<br>
+  ParseFlag(str, &f->log_path, "log_path", "");<br>
+  ParseFlag(str, &f->verbosity, "verbosity", "");<br>
+  ParseFlag(str, &f->detect_leaks, "detect_leaks", "");<br>
+  ParseFlag(str, &f->leak_check_at_exit, "leak_check_at_exit", "");<br>
+  ParseFlag(str, &f->allocator_may_return_null, "allocator_may_return_null",<br>
+            "");<br>
+  ParseFlag(str, &f->print_summary, "print_summary", "");<br>
+  ParseFlag(str, &f->check_printf, "check_printf", "");<br>
+  ParseFlag(str, &f->handle_segv, "handle_segv", "");<br>
+  ParseFlag(str, &f->allow_user_segv_handler, "allow_user_segv_handler", "");<br>
+  ParseFlag(str, &f->use_sigaltstack, "use_sigaltstack", "");<br>
+  ParseFlag(str, &f->detect_deadlocks, "detect_deadlocks", "");<br>
   ParseFlag(str, &f->clear_shadow_mmap_threshold,<br>
-            "clear_shadow_mmap_threshold");<br>
-  ParseFlag(str, &f->color, "color");<br>
-  ParseFlag(str, &f->legacy_pthread_cond, "legacy_pthread_cond");<br>
+            "clear_shadow_mmap_threshold", "");<br>
+  ParseFlag(str, &f->color, "color", "");<br>
+  ParseFlag(str, &f->legacy_pthread_cond, "legacy_pthread_cond", "");<br>
+  ParseFlag(str, &f->help, "help", "");<br>
<br>
   // Do a sanity check for certain flags.<br>
   if (f->malloc_context_size < 1)<br>
@@ -124,9 +134,49 @@ static bool StartsWith(const char *flag,<br>
          (0 == internal_strncmp(flag, value, value_length));<br>
 }<br>
<br>
-void ParseFlag(const char *env, bool *flag, const char *name) {<br>
+static LowLevelAllocator allocator_for_flags;<br>
+<br>
+// The linear scan is suboptimal, but the number of flags is relatively small.<br>
+bool FlagInDescriptionList(const char *name) {<br>
+  FlagDescriptionList *descr = flag_descriptions;<br>
+  while (descr) {<br>
+    if (!internal_strcmp(descr->name, name)) return true;<br>
+    descr = descr->next;<br>
+  }<br>
+  return false;<br>
+}<br>
+<br>
+void AddFlagDescription(const char *name, const char *description) {<br>
+  if (FlagInDescriptionList(name)) return;<br>
+  FlagDescriptionList *new_description =<br>
+      (FlagDescriptionList*)allocator_for_flags.Allocate(<br>
+          sizeof(FlagDescriptionList));<br></blockquote><div><br></div><div>We have automagic for that:</div><div>new_description = new(allocator_for_flags) FlagDescriptionList;</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">

+  if (!last_flag_description) {<br>
+    flag_descriptions = new_description;<br>
+  } else {<br>
+    last_flag_description->next = new_description;<br>
+  }<br></blockquote><div><br></div><div>Consider re-using IntrusiveList<FlagDescription> instead of re-implementing it.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">

+  new_description->name = name;<br>
+  new_description->description = description;<br>
+  new_description->next = 0;<br>
+  last_flag_description = new_description;<br>
+}<br>
+<br>
+// TODO(glider): put the descriptions inside CommonFlags.<br>
+void PrintFlagDescriptions() {<br>
+  FlagDescriptionList *descr = flag_descriptions;<br>
+  Printf("Available flags for %s:\n", SanitizerToolName);<br>
+  while (descr) {<br>
+    Printf("\t%s - %s\n", descr->name, descr->description);<br>
+    descr = descr->next;<br>
+  }<br>
+}<br>
+<br>
+void ParseFlag(const char *env, bool *flag,<br>
+               const char *name, const char *descr) {<br>
   const char *value;<br>
   int value_length;<br>
+  AddFlagDescription(name, descr);<br>
   if (!GetFlagValue(env, name, &value, &value_length))<br>
     return;<br>
   if (StartsWith(value, value_length, "0") ||<br>
@@ -139,27 +189,31 @@ void ParseFlag(const char *env, bool *fl<br>
     *flag = true;<br>
 }<br>
<br>
-void ParseFlag(const char *env, int *flag, const char *name) {<br>
+void ParseFlag(const char *env, int *flag,<br>
+               const char *name, const char *descr) {<br>
   const char *value;<br>
   int value_length;<br>
+  AddFlagDescription(name, descr);<br>
   if (!GetFlagValue(env, name, &value, &value_length))<br>
     return;<br>
   *flag = static_cast<int>(internal_atoll(value));<br>
 }<br>
<br>
-void ParseFlag(const char *env, uptr *flag, const char *name) {<br>
+void ParseFlag(const char *env, uptr *flag,<br>
+               const char *name, const char *descr) {<br>
   const char *value;<br>
   int value_length;<br>
+  AddFlagDescription(name, descr);<br>
   if (!GetFlagValue(env, name, &value, &value_length))<br>
     return;<br>
   *flag = static_cast<uptr>(internal_atoll(value));<br>
 }<br>
<br>
-static LowLevelAllocator allocator_for_flags;<br>
-<br>
-void ParseFlag(const char *env, const char **flag, const char *name) {<br>
+void ParseFlag(const char *env, const char **flag,<br>
+               const char *name, const char *descr) {<br>
   const char *value;<br>
   int value_length;<br>
+  AddFlagDescription(name, descr);<br>
   if (!GetFlagValue(env, name, &value, &value_length))<br>
     return;<br>
   // Copy the flag value. Don't use locks here, as flags are parsed at<br>
<br>
Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_flags.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_flags.h?rev=204339&r1=204338&r2=204339&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_flags.h?rev=204339&r1=204338&r2=204339&view=diff</a><br>

==============================================================================<br>
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_flags.h (original)<br>
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_flags.h Thu Mar 20 07:52:52 2014<br>
@@ -18,10 +18,14 @@<br>
<br>
 namespace __sanitizer {<br>
<br>
-void ParseFlag(const char *env, bool *flag, const char *name);<br>
-void ParseFlag(const char *env, int *flag, const char *name);<br>
-void ParseFlag(const char *env, uptr *flag, const char *name);<br>
-void ParseFlag(const char *env, const char **flag, const char *name);<br>
+void ParseFlag(const char *env, bool *flag,<br>
+    const char *name, const char *descr);<br>
+void ParseFlag(const char *env, int *flag,<br>
+    const char *name, const char *descr);<br>
+void ParseFlag(const char *env, uptr *flag,<br>
+    const char *name, const char *descr);<br>
+void ParseFlag(const char *env, const char **flag,<br>
+    const char *name, const char *descr);<br>
<br>
 struct CommonFlags {<br>
   // If set, use the online symbolizer from common sanitizer runtime to turn<br>
@@ -80,6 +84,8 @@ struct CommonFlags {<br>
   const char *color;<br>
   // Enables support for dynamic libraries linked with libpthread 2.2.5.<br>
   bool legacy_pthread_cond;<br>
+  // Print help and exit.<br>
+  bool help;<br>
 };<br>
<br>
 inline CommonFlags *common_flags() {<br>
@@ -89,6 +95,7 @@ inline CommonFlags *common_flags() {<br>
<br>
 void SetCommonFlagsDefaults(CommonFlags *f);<br>
 void ParseCommonFlagsFromString(CommonFlags *f, const char *str);<br>
+void PrintFlagDescriptions();<br>
<br>
 }  // namespace __sanitizer<br>
<br>
<br>
Modified: compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_flags_test.cc<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_flags_test.cc?rev=204339&r1=204338&r2=204339&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_flags_test.cc?rev=204339&r1=204338&r2=204339&view=diff</a><br>

==============================================================================<br>
--- compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_flags_test.cc (original)<br>
+++ compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_flags_test.cc Thu Mar 20 07:52:52 2014<br>
@@ -24,14 +24,14 @@ static const char kFlagName[] = "flag_na<br>
 template <typename T><br>
 static void TestFlag(T start_value, const char *env, T final_value) {<br>
   T flag = start_value;<br>
-  ParseFlag(env, &flag, kFlagName);<br>
+  ParseFlag(env, &flag, kFlagName, "flag description");<br>
   EXPECT_EQ(final_value, flag);<br>
 }<br>
<br>
 static void TestStrFlag(const char *start_value, const char *env,<br>
                         const char *final_value) {<br>
   const char *flag = start_value;<br>
-  ParseFlag(env, &flag, kFlagName);<br>
+  ParseFlag(env, &flag, kFlagName, "flag description");<br>
   EXPECT_EQ(0, internal_strcmp(final_value, flag));<br>
 }<br>
<br>
@@ -70,8 +70,8 @@ static void TestTwoFlags(const char *env<br>
                          const char *expected_flag2) {<br>
   bool flag1 = !expected_flag1;<br>
   const char *flag2 = "";<br>
-  ParseFlag(env, &flag1, "flag1");<br>
-  ParseFlag(env, &flag2, "flag2");<br>
+  ParseFlag(env, &flag1, "flag1", "flag1 description");<br>
+  ParseFlag(env, &flag2, "flag2", "flag2 description");<br>
   EXPECT_EQ(expected_flag1, flag1);<br>
   EXPECT_EQ(0, internal_strcmp(flag2, expected_flag2));<br>
 }<br>
<br>
Modified: compiler-rt/trunk/lib/tsan/dd/dd_rtl.cc<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/dd/dd_rtl.cc?rev=204339&r1=204338&r2=204339&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/dd/dd_rtl.cc?rev=204339&r1=204338&r2=204339&view=diff</a><br>

==============================================================================<br>
--- compiler-rt/trunk/lib/tsan/dd/dd_rtl.cc (original)<br>
+++ compiler-rt/trunk/lib/tsan/dd/dd_rtl.cc Thu Mar 20 07:52:52 2014<br>
@@ -76,7 +76,7 @@ void InitializeFlags(Flags *f, const cha<br>
   f->allow_addr2line = true;<br>
<br>
   // Override from command line.<br>
-  ParseFlag(env, &f->second_deadlock_stack, "second_deadlock_stack");<br>
+  ParseFlag(env, &f->second_deadlock_stack, "second_deadlock_stack", "");<br>
   ParseCommonFlagsFromString(f, env);<br>
<br>
   // Copy back to common flags.<br>
<br>
Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_flags.cc<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_flags.cc?rev=204339&r1=204338&r2=204339&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_flags.cc?rev=204339&r1=204338&r2=204339&view=diff</a><br>

==============================================================================<br>
--- compiler-rt/trunk/lib/tsan/rtl/tsan_flags.cc (original)<br>
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_flags.cc Thu Mar 20 07:52:52 2014<br>
@@ -34,34 +34,34 @@ const char *WEAK __tsan_default_options(<br>
 #endif<br>
<br>
 static void ParseFlags(Flags *f, const char *env) {<br>
-  ParseFlag(env, &f->enable_annotations, "enable_annotations");<br>
-  ParseFlag(env, &f->suppress_equal_stacks, "suppress_equal_stacks");<br>
-  ParseFlag(env, &f->suppress_equal_addresses, "suppress_equal_addresses");<br>
-  ParseFlag(env, &f->suppress_java, "suppress_java");<br>
-  ParseFlag(env, &f->report_bugs, "report_bugs");<br>
-  ParseFlag(env, &f->report_thread_leaks, "report_thread_leaks");<br>
-  ParseFlag(env, &f->report_destroy_locked, "report_destroy_locked");<br>
-  ParseFlag(env, &f->report_signal_unsafe, "report_signal_unsafe");<br>
-  ParseFlag(env, &f->report_atomic_races, "report_atomic_races");<br>
-  ParseFlag(env, &f->force_seq_cst_atomics, "force_seq_cst_atomics");<br>
-  ParseFlag(env, &f->suppressions, "suppressions");<br>
-  ParseFlag(env, &f->print_suppressions, "print_suppressions");<br>
-  ParseFlag(env, &f->print_benign, "print_benign");<br>
-  ParseFlag(env, &f->exitcode, "exitcode");<br>
-  ParseFlag(env, &f->halt_on_error, "halt_on_error");<br>
-  ParseFlag(env, &f->atexit_sleep_ms, "atexit_sleep_ms");<br>
-  ParseFlag(env, &f->profile_memory, "profile_memory");<br>
-  ParseFlag(env, &f->flush_memory_ms, "flush_memory_ms");<br>
-  ParseFlag(env, &f->flush_symbolizer_ms, "flush_symbolizer_ms");<br>
-  ParseFlag(env, &f->memory_limit_mb, "memory_limit_mb");<br>
-  ParseFlag(env, &f->stop_on_start, "stop_on_start");<br>
-  ParseFlag(env, &f->running_on_valgrind, "running_on_valgrind");<br>
-  ParseFlag(env, &f->history_size, "history_size");<br>
-  ParseFlag(env, &f->io_sync, "io_sync");<br>
-  ParseFlag(env, &f->die_after_fork, "die_after_fork");<br>
+  ParseFlag(env, &f->enable_annotations, "enable_annotations", "");<br>
+  ParseFlag(env, &f->suppress_equal_stacks, "suppress_equal_stacks", "");<br>
+  ParseFlag(env, &f->suppress_equal_addresses, "suppress_equal_addresses", "");<br>
+  ParseFlag(env, &f->suppress_java, "suppress_java", "");<br>
+  ParseFlag(env, &f->report_bugs, "report_bugs", "");<br>
+  ParseFlag(env, &f->report_thread_leaks, "report_thread_leaks", "");<br>
+  ParseFlag(env, &f->report_destroy_locked, "report_destroy_locked", "");<br>
+  ParseFlag(env, &f->report_signal_unsafe, "report_signal_unsafe", "");<br>
+  ParseFlag(env, &f->report_atomic_races, "report_atomic_races", "");<br>
+  ParseFlag(env, &f->force_seq_cst_atomics, "force_seq_cst_atomics", "");<br>
+  ParseFlag(env, &f->suppressions, "suppressions", "");<br>
+  ParseFlag(env, &f->print_suppressions, "print_suppressions", "");<br>
+  ParseFlag(env, &f->print_benign, "print_benign", "");<br>
+  ParseFlag(env, &f->exitcode, "exitcode", "");<br>
+  ParseFlag(env, &f->halt_on_error, "halt_on_error", "");<br>
+  ParseFlag(env, &f->atexit_sleep_ms, "atexit_sleep_ms", "");<br>
+  ParseFlag(env, &f->profile_memory, "profile_memory", "");<br>
+  ParseFlag(env, &f->flush_memory_ms, "flush_memory_ms", "");<br>
+  ParseFlag(env, &f->flush_symbolizer_ms, "flush_symbolizer_ms", "");<br>
+  ParseFlag(env, &f->memory_limit_mb, "memory_limit_mb", "");<br>
+  ParseFlag(env, &f->stop_on_start, "stop_on_start", "");<br>
+  ParseFlag(env, &f->running_on_valgrind, "running_on_valgrind", "");<br>
+  ParseFlag(env, &f->history_size, "history_size", "");<br>
+  ParseFlag(env, &f->io_sync, "io_sync", "");<br>
+  ParseFlag(env, &f->die_after_fork, "die_after_fork", "");<br>
<br>
   // DDFlags<br>
-  ParseFlag(env, &f->second_deadlock_stack, "second_deadlock_stack");<br>
+  ParseFlag(env, &f->second_deadlock_stack, "second_deadlock_stack", "");<br>
 }<br>
<br>
 void InitializeFlags(Flags *f, const char *env) {<br>
@@ -118,6 +118,8 @@ void InitializeFlags(Flags *f, const cha<br>
     f->report_signal_unsafe = false;<br>
   }<br>
<br>
+  if (f->help) PrintFlagDescriptions();<br>
+<br>
   if (f->history_size < 0 || f->history_size > 7) {<br>
     Printf("ThreadSanitizer: incorrect value for history_size"<br>
            " (must be [0..7])\n");<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@cs.uiuc.edu">llvm-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a><br>
</blockquote></div><br><br clear="all"><div><br></div>-- <br><div>Alexey Samsonov, MSK</div>
</div></div>