<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Jan 16, 2015 at 7:32 PM, Alexey Samsonov <span dir="ltr"><<a href="mailto:vonosmas@gmail.com" target="_blank">vonosmas@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div class="gmail_extra">Thanks for doing this!</div><div class="gmail_extra"><br><div class="gmail_quote"><div><div class="h5">On Thu, Jan 15, 2015 at 8:13 PM, Evgeniy Stepanov <span dir="ltr"><<a href="mailto:eugeni.stepanov@gmail.com" target="_blank">eugeni.stepanov@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">Author: eugenis<br>
Date: Thu Jan 15 09:13:43 2015<br>
New Revision: 226169<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=226169&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=226169&view=rev</a><br>
Log:<br>
[sanitizer] Flag parser rewrite.<br>
<br>
The new parser is a lot stricter about syntax, reports unrecognized<br>
flags, and will make it easier to implemented some of the planned features.<br>
<br>
<br>
Added:<br>
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_flag_parser.cc   (with props)<br>
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_flag_parser.h   (with props)<br>
    compiler-rt/trunk/test/asan/TestCases/asan_options-help.cc   (with props)<br>
    compiler-rt/trunk/test/asan/TestCases/asan_options-invalid.cc   (with props)<br>
Modified:<br>
    compiler-rt/trunk/CMakeLists.txt<br>
    compiler-rt/trunk/lib/asan/asan_activation.cc<br>
    compiler-rt/trunk/lib/asan/asan_flags.cc<br>
    compiler-rt/trunk/lib/asan/asan_flags.h<br>
    compiler-rt/trunk/lib/asan/tests/CMakeLists.txt<br>
    compiler-rt/trunk/lib/dfsan/CMakeLists.txt<br>
    compiler-rt/trunk/lib/dfsan/dfsan.cc<br>
    compiler-rt/trunk/lib/dfsan/dfsan.h<br>
    compiler-rt/trunk/lib/lsan/lsan_common.cc<br>
    compiler-rt/trunk/lib/lsan/lsan_common.h<br>
    compiler-rt/trunk/lib/msan/msan.cc<br>
    compiler-rt/trunk/lib/msan/msan_flags.h<br>
    compiler-rt/trunk/lib/sanitizer_common/CMakeLists.txt<br>
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_allocator_internal.h<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/sanitizer_libc.cc<br>
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_libc.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>
    compiler-rt/trunk/lib/ubsan/ubsan_flags.cc<br>
    compiler-rt/trunk/lib/ubsan/ubsan_flags.h<br>
    compiler-rt/trunk/lib/ubsan/ubsan_init.cc<br>
    compiler-rt/trunk/test/asan/TestCases/default_options.cc<br>
    compiler-rt/trunk/test/lsan/TestCases/ignore_object.cc<br>
    compiler-rt/trunk/test/lsan/TestCases/ignore_object_errors.cc<br>
    compiler-rt/trunk/test/ubsan/TestCases/TypeCheck/vptr.cpp<br>
<br>
Modified: compiler-rt/trunk/CMakeLists.txt<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/CMakeLists.txt?rev=226169&r1=226168&r2=226169&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/CMakeLists.txt?rev=226169&r1=226168&r2=226169&view=diff</a><br>
==============================================================================<br>
--- compiler-rt/trunk/CMakeLists.txt (original)<br>
+++ compiler-rt/trunk/CMakeLists.txt Thu Jan 15 09:13:43 2015<br>
@@ -234,7 +234,7 @@ append_list_if(COMPILER_RT_HAS_FUNWIND_T<br>
 append_list_if(COMPILER_RT_HAS_FNO_STACK_PROTECTOR_FLAG -fno-stack-protector SANITIZER_COMMON_CFLAGS)<br>
 append_list_if(COMPILER_RT_HAS_FVISIBILITY_HIDDEN_FLAG -fvisibility=hidden SANITIZER_COMMON_CFLAGS)<br>
 append_list_if(COMPILER_RT_HAS_FNO_FUNCTION_SECTIONS_FLAG -fno-function-sections SANITIZER_COMMON_CFLAGS)<br>
-append_list_if(COMPILER_RT_HAS_FNO_LTO_FLAG -fno-lto SANITIZER_COMMON_CFLAGS)<br>
+# append_list_if(COMPILER_RT_HAS_FNO_LTO_FLAG -fno-lto SANITIZER_COMMON_CFLAGS)<br>
<br>
 if(MSVC)<br>
   # Replace the /MD[d] flags with /MT.<br>
<br>
Modified: compiler-rt/trunk/lib/asan/asan_activation.cc<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_activation.cc?rev=226169&r1=226168&r2=226169&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_activation.cc?rev=226169&r1=226168&r2=226169&view=diff</a><br>
==============================================================================<br>
--- compiler-rt/trunk/lib/asan/asan_activation.cc (original)<br>
+++ compiler-rt/trunk/lib/asan/asan_activation.cc Thu Jan 15 09:13:43 2015<br>
@@ -32,6 +32,9 @@ static struct AsanDeactivatedFlags {<br>
   void OverrideFromActivationFlags() {<br>
     Flags f;<br>
     CommonFlags cf;<br>
+    FlagParser parser;<br>
+    RegisterAsanFlags(&parser, &f);<br>
+    RegisterCommonFlags(&parser, &cf);<br>
<br>
     // Copy the current activation flags.<br>
     allocator_options.CopyTo(&f, &cf);<br>
@@ -44,15 +47,13 @@ static struct AsanDeactivatedFlags {<br>
     // FIXME: Add diagnostic to check that activation flags string doesn't<br>
     // contain any other flags.<br>
     if (const char *env = GetEnv("ASAN_ACTIVATION_OPTIONS")) {<br>
-      cf.ParseFromString(env);<br>
-      f.ParseFromString(env);<br>
+      parser.ParseString(env);<br>
     }<br>
<br>
     // Override from getprop asan.options.<br>
     char buf[100];<br>
     GetExtraActivationFlags(buf, sizeof(buf));<br>
-    cf.ParseFromString(buf);<br>
-    f.ParseFromString(buf);<br>
+    parser.ParseString(buf);<br>
<br>
     allocator_options.SetFrom(&f, &cf);<br>
     malloc_context_size = cf.malloc_context_size;<br>
<br>
Modified: compiler-rt/trunk/lib/asan/asan_flags.cc<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_flags.cc?rev=226169&r1=226168&r2=226169&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_flags.cc?rev=226169&r1=226168&r2=226169&view=diff</a><br>
==============================================================================<br>
--- compiler-rt/trunk/lib/asan/asan_flags.cc (original)<br>
+++ compiler-rt/trunk/lib/asan/asan_flags.cc Thu Jan 15 09:13:43 2015<br>
@@ -19,6 +19,7 @@<br>
 #include "lsan/lsan_common.h"<br>
 #include "sanitizer_common/sanitizer_common.h"<br>
 #include "sanitizer_common/sanitizer_flags.h"<br>
+#include "sanitizer_common/sanitizer_flag_parser.h"<br>
<br>
 namespace __asan {<br>
<br>
@@ -45,14 +46,18 @@ void Flags::SetDefaults() {<br>
 #undef ASAN_FLAG<br>
 }<br>
<br>
-void Flags::ParseFromString(const char *str) {<br>
-#define ASAN_FLAG(Type, Name, DefaultValue, Description)                     \<br>
-  ParseFlag(str, &Name, #Name, Description);<br>
+void RegisterAsanFlags(FlagParser *parser, Flags *f) {<br>
+#define ASAN_FLAG(Type, Name, DefaultValue, Description) \<br>
+  RegisterFlag(parser, #Name, Description, &f->Name);<br>
 #include "asan_flags.inc"<br>
 #undef ASAN_FLAG<br>
 }<br>
<br>
 void InitializeFlags(Flags *f) {<br>
+  FlagParser parser;<br>
+  RegisterAsanFlags(&parser, f);<br>
+  RegisterCommonFlags(&parser);<br>
+<br>
   SetCommonFlagsDefaults();<br>
   {<br>
     CommonFlags cf;<br>
@@ -69,20 +74,17 @@ void InitializeFlags(Flags *f) {<br>
<br>
   // Override from compile definition.<br>
   const char *compile_def = MaybeUseAsanDefaultOptionsCompileDefinition();<br>
-  ParseCommonFlagsFromString(compile_def);<br>
-  f->ParseFromString(compile_def);<br>
+  parser.ParseString(compile_def);<br>
<br>
   // Override from user-specified string.<br>
   const char *default_options = MaybeCallAsanDefaultOptions();<br>
-  ParseCommonFlagsFromString(default_options);<br>
-  f->ParseFromString(default_options);<br>
+  parser.ParseString(default_options);<br>
   VReport(1, "Using the defaults from __asan_default_options: %s\n",<br>
           MaybeCallAsanDefaultOptions());<br>
<br>
   // Override from command line.<br>
   if (const char *env = GetEnv("ASAN_OPTIONS")) {<br>
-    ParseCommonFlagsFromString(env);<br>
-    f->ParseFromString(env);<br>
+    parser.ParseString(env);<br>
     VReport(1, "Parsed ASAN_OPTIONS: %s\n", env);<br>
   }<br>
<br>
@@ -91,14 +93,13 @@ void InitializeFlags(Flags *f) {<br>
   if (!flags()->start_deactivated) {<br>
     char buf[100];<br>
     GetExtraActivationFlags(buf, sizeof(buf));<br>
-    ParseCommonFlagsFromString(buf);<br>
-    f->ParseFromString(buf);<br>
+    parser.ParseString(buf);<br>
     if (buf[0] != '\0')<br>
       VReport(1, "Parsed activation flags: %s\n", buf);<br>
   }<br>
<br>
   if (common_flags()->help) {<br>
-    PrintFlagDescriptions();<br>
+    parser.PrintFlagDescriptions();<br>
   }<br>
<br>
   // Flag validation:<br>
<br>
Modified: compiler-rt/trunk/lib/asan/asan_flags.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_flags.h?rev=226169&r1=226168&r2=226169&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_flags.h?rev=226169&r1=226168&r2=226169&view=diff</a><br>
==============================================================================<br>
--- compiler-rt/trunk/lib/asan/asan_flags.h (original)<br>
+++ compiler-rt/trunk/lib/asan/asan_flags.h Thu Jan 15 09:13:43 2015<br>
@@ -16,6 +16,7 @@<br>
 #define ASAN_FLAGS_H<br>
<br>
 #include "sanitizer_common/sanitizer_internal_defs.h"<br>
+#include "sanitizer_common/sanitizer_flag_parser.h"<br>
<br>
 // ASan flag values can be defined in four ways:<br>
 // 1) initialized with default values at startup.<br>
@@ -34,13 +35,13 @@ struct Flags {<br>
 #undef ASAN_FLAG<br>
<br>
   void SetDefaults();<br>
-  void ParseFromString(const char *str);<br>
 };<br>
<br>
 extern Flags asan_flags_dont_use_directly;<br>
 inline Flags *flags() {<br>
   return &asan_flags_dont_use_directly;<br>
 }<br>
+void RegisterAsanFlags(FlagParser *parser, Flags *f);<br>
 void InitializeFlags(Flags *f);<br>
<br>
 }  // namespace __asan<br>
<br>
Modified: compiler-rt/trunk/lib/asan/tests/CMakeLists.txt<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/tests/CMakeLists.txt?rev=226169&r1=226168&r2=226169&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/tests/CMakeLists.txt?rev=226169&r1=226168&r2=226169&view=diff</a><br>
==============================================================================<br>
--- compiler-rt/trunk/lib/asan/tests/CMakeLists.txt (original)<br>
+++ compiler-rt/trunk/lib/asan/tests/CMakeLists.txt Thu Jan 15 09:13:43 2015<br>
@@ -30,7 +30,8 @@ set(ASAN_UNITTEST_COMMON_CFLAGS<br>
   -fno-rtti<br>
   -O2<br>
   -Wno-format<br>
-  -Werror=sign-compare)<br>
+  -Werror=sign-compare<br>
+  -Wno-non-virtual-dtor)<br>
 append_list_if(COMPILER_RT_HAS_WVARIADIC_MACROS_FLAG -Wno-variadic-macros ASAN_UNITTEST_COMMON_CFLAGS)<br>
<br>
 # -gline-tables-only must be enough for ASan, so use it if possible.<br>
<br>
Modified: compiler-rt/trunk/lib/dfsan/CMakeLists.txt<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/dfsan/CMakeLists.txt?rev=226169&r1=226168&r2=226169&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/dfsan/CMakeLists.txt?rev=226169&r1=226168&r2=226169&view=diff</a><br>
==============================================================================<br>
--- compiler-rt/trunk/lib/dfsan/CMakeLists.txt (original)<br>
+++ compiler-rt/trunk/lib/dfsan/CMakeLists.txt Thu Jan 15 09:13:43 2015<br>
@@ -5,7 +5,7 @@ set(DFSAN_RTL_SOURCES<br>
   dfsan.cc<br>
   dfsan_custom.cc<br>
   dfsan_interceptors.cc)<br>
-set(DFSAN_COMMON_CFLAGS ${SANITIZER_COMMON_CFLAGS})<br>
+set(DFSAN_COMMON_CFLAGS ${SANITIZER_COMMON_CFLAGS} -fno-rtti)<br></blockquote><div><br></div></div></div><div>append_no_rtti_flag(DFSAN_COMMON_CFLAGS)<br></div><div><div class="h5"><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
 # Prevent clang from generating libc calls.<br>
 append_list_if(COMPILER_RT_HAS_FFREESTANDING_FLAG -ffreestanding DFSAN_COMMON_CFLAGS)<br>
<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=226169&r1=226168&r2=226169&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/dfsan/dfsan.cc?rev=226169&r1=226168&r2=226169&view=diff</a><br>
==============================================================================<br>
--- compiler-rt/trunk/lib/dfsan/dfsan.cc (original)<br>
+++ compiler-rt/trunk/lib/dfsan/dfsan.cc Thu Jan 15 09:13:43 2015<br>
@@ -22,6 +22,7 @@<br>
 #include "sanitizer_common/sanitizer_atomic.h"<br>
 #include "sanitizer_common/sanitizer_common.h"<br>
 #include "sanitizer_common/sanitizer_flags.h"<br>
+#include "sanitizer_common/sanitizer_flag_parser.h"<br>
 #include "sanitizer_common/sanitizer_libc.h"<br>
<br>
 #include "dfsan/dfsan.h"<br>
@@ -316,16 +317,18 @@ void Flags::SetDefaults() {<br>
 #undef DFSAN_FLAG<br>
 }<br>
<br>
-void Flags::ParseFromString(const char *str) {<br>
-#define DFSAN_FLAG(Type, Name, DefaultValue, Description)                     \<br>
-  ParseFlag(str, &Name, #Name, Description);<br>
+void RegisterDfsanFlags(FlagParser *parser, Flags *f) {<br>
+#define DFSAN_FLAG(Type, Name, DefaultValue, Description) \<br>
+  RegisterFlag(parser, #Name, Description, &f->Name);<br>
 #include "dfsan_flags.inc"<br>
 #undef DFSAN_FLAG<br>
 }<br>
<br>
 static void InitializeFlags(Flags &f, const char *env) {<br>
+  FlagParser parser;<br>
+  RegisterDfsanFlags(&parser, &f);<br>
   f.SetDefaults();<br>
-  f.ParseFromString(env);<br>
+  parser.ParseString(env);<br>
 }<br>
<br>
 static void dfsan_fini() {<br>
<br>
Modified: compiler-rt/trunk/lib/dfsan/dfsan.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/dfsan/dfsan.h?rev=226169&r1=226168&r2=226169&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/dfsan/dfsan.h?rev=226169&r1=226168&r2=226169&view=diff</a><br>
==============================================================================<br>
--- compiler-rt/trunk/lib/dfsan/dfsan.h (original)<br>
+++ compiler-rt/trunk/lib/dfsan/dfsan.h Thu Jan 15 09:13:43 2015<br>
@@ -61,7 +61,6 @@ struct Flags {<br>
 #undef DFSAN_FLAG<br>
<br>
   void SetDefaults();<br>
-  void ParseFromString(const char *str);<br>
 };<br>
<br>
 extern Flags flags_data;<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=226169&r1=226168&r2=226169&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/lsan/lsan_common.cc?rev=226169&r1=226168&r2=226169&view=diff</a><br>
==============================================================================<br>
--- compiler-rt/trunk/lib/lsan/lsan_common.cc (original)<br>
+++ compiler-rt/trunk/lib/lsan/lsan_common.cc Thu Jan 15 09:13:43 2015<br>
@@ -16,6 +16,7 @@<br>
<br>
 #include "sanitizer_common/sanitizer_common.h"<br>
 #include "sanitizer_common/sanitizer_flags.h"<br>
+#include "sanitizer_common/sanitizer_flag_parser.h"<br>
 #include "sanitizer_common/sanitizer_placement_new.h"<br>
 #include "sanitizer_common/sanitizer_procmaps.h"<br>
 #include "sanitizer_common/sanitizer_stackdepot.h"<br>
@@ -42,19 +43,20 @@ void Flags::SetDefaults() {<br>
 #undef LSAN_FLAG<br>
 }<br>
<br>
-void Flags::ParseFromString(const char *str) {<br>
-#define LSAN_FLAG(Type, Name, DefaultValue, Description)                       \<br>
-  ParseFlag(str, &Name, #Name, Description);<br>
+static void RegisterLsanFlags(FlagParser *parser, Flags *f) {<br>
+#define LSAN_FLAG(Type, Name, DefaultValue, Description) \<br>
+  RegisterFlag(parser, #Name, Description, &f->Name);<br>
 #include "lsan_flags.inc"<br>
 #undef LSAN_FLAG<br>
 }<br>
<br>
 static void InitializeFlags(bool standalone) {<br>
   Flags *f = flags();<br>
-  f->SetDefaults();<br>
+  FlagParser parser;<br>
+  RegisterLsanFlags(&parser, f);<br>
+  RegisterCommonFlags(&parser);<br>
<br>
-  const char *options = GetEnv("LSAN_OPTIONS");<br>
-  f->ParseFromString(options);<br>
+  f->SetDefaults();<br>
<br>
   // Set defaults for common flags (only in standalone mode) and parse<br>
   // them from LSAN_OPTIONS.<br>
@@ -67,7 +69,9 @@ static void InitializeFlags(bool standal<br>
     cf.detect_leaks = true;<br>
     OverrideCommonFlags(cf);<br>
   }<br>
-  ParseCommonFlagsFromString(options);<br>
+<br>
+  const char *options = GetEnv("LSAN_OPTIONS");<br>
+  parser.ParseString(options);<br>
 }<br>
<br>
 #define LOG_POINTERS(...)                           \<br>
<br>
Modified: compiler-rt/trunk/lib/lsan/lsan_common.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/lsan/lsan_common.h?rev=226169&r1=226168&r2=226169&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/lsan/lsan_common.h?rev=226169&r1=226168&r2=226169&view=diff</a><br>
==============================================================================<br>
--- compiler-rt/trunk/lib/lsan/lsan_common.h (original)<br>
+++ compiler-rt/trunk/lib/lsan/lsan_common.h Thu Jan 15 09:13:43 2015<br>
@@ -43,7 +43,6 @@ struct Flags {<br>
 #undef LSAN_FLAG<br>
<br>
   void SetDefaults();<br>
-  void ParseFromString(const char *str);<br>
   uptr pointer_alignment() const {<br>
     return use_unaligned ? 1 : sizeof(uptr);<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=226169&r1=226168&r2=226169&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/msan/msan.cc?rev=226169&r1=226168&r2=226169&view=diff</a><br>
==============================================================================<br>
--- compiler-rt/trunk/lib/msan/msan.cc (original)<br>
+++ compiler-rt/trunk/lib/msan/msan.cc Thu Jan 15 09:13:43 2015<br>
@@ -19,13 +19,13 @@<br>
 #include "sanitizer_common/sanitizer_atomic.h"<br>
 #include "sanitizer_common/sanitizer_common.h"<br>
 #include "sanitizer_common/sanitizer_flags.h"<br>
+#include "sanitizer_common/sanitizer_flag_parser.h"<br>
 #include "sanitizer_common/sanitizer_libc.h"<br>
 #include "sanitizer_common/sanitizer_procmaps.h"<br>
 #include "sanitizer_common/sanitizer_stacktrace.h"<br>
 #include "sanitizer_common/sanitizer_symbolizer.h"<br>
 #include "sanitizer_common/sanitizer_stackdepot.h"<br>
<br>
-<br>
 // ACHTUNG! No system header includes in this file.<br>
<br>
 using namespace __sanitizer;<br>
@@ -102,20 +102,40 @@ void Flags::SetDefaults() {<br>
 #undef MSAN_FLAG<br>
 }<br>
<br>
-void Flags::ParseFromString(const char *str) {<br>
-  // keep_going is an old name for halt_on_error,<br>
-  // and it has inverse meaning.<br>
-  halt_on_error = !halt_on_error;<br>
-  ParseFlag(str, &halt_on_error, "keep_going", "");<br>
-  halt_on_error = !halt_on_error;<br>
-<br>
-#define MSAN_FLAG(Type, Name, DefaultValue, Description)                     \<br>
-  ParseFlag(str, &Name, #Name, Description);<br>
+// keep_going is an old name for halt_on_error,<br>
+// and it has inverse meaning.<br>
+class FlagHandlerKeepGoing : public FlagHandlerBase {<br>
+  bool *halt_on_error_;<br>
+<br>
+ public:<br>
+  explicit FlagHandlerKeepGoing(bool *halt_on_error)<br>
+      : halt_on_error_(halt_on_error) {}<br>
+  bool Parse(const char *value) {<br>
+    bool tmp;<br>
+    FlagHandler<bool> h(&tmp);<br>
+    if (!h.Parse(value)) return false;<br>
+    *halt_on_error_ = !tmp;<br>
+    return true;<br>
+  }<br>
+};<br>
+<br>
+void RegisterMsanFlags(FlagParser *parser, Flags *f) {<br>
+#define MSAN_FLAG(Type, Name, DefaultValue, Description) \<br>
+  RegisterFlag(parser, #Name, Description, &f->Name);<br>
 #include "msan_flags.inc"<br>
 #undef MSAN_FLAG<br>
+<br>
+  FlagHandlerKeepGoing *fh_keep_going =<br>
+      new (INTERNAL_ALLOC) FlagHandlerKeepGoing(&f->halt_on_error);  // NOLINT<br>
+  parser->RegisterHandler("keep_going", fh_keep_going,<br>
+                          "deprecated, use halt_on_error");<br>
 }<br>
<br>
 static void InitializeFlags(Flags *f, const char *options) {<br>
+  FlagParser parser;<br>
+  RegisterMsanFlags(&parser, f);<br>
+  RegisterCommonFlags(&parser);<br>
+<br>
   SetCommonFlagsDefaults();<br>
   {<br>
     CommonFlags cf;<br>
@@ -132,13 +152,12 @@ static void InitializeFlags(Flags *f, co<br>
   f->SetDefaults();<br>
<br>
   // Override from user-specified string.<br>
-  if (__msan_default_options) {<br>
-    f->ParseFromString(__msan_default_options());<br>
-    ParseCommonFlagsFromString(__msan_default_options());<br>
-  }<br>
+  if (__msan_default_options)<br>
+    parser.ParseString(__msan_default_options());<br>
+<br>
+  parser.ParseString(options);<br>
<br>
-  f->ParseFromString(options);<br>
-  ParseCommonFlagsFromString(options);<br>
+  if (common_flags()->help) parser.PrintFlagDescriptions();<br>
<br>
   // Check flag values:<br>
   if (f->exit_code < 0 || f->exit_code > 127) {<br>
@@ -328,7 +347,6 @@ 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/msan/msan_flags.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/msan/msan_flags.h?rev=226169&r1=226168&r2=226169&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/msan/msan_flags.h?rev=226169&r1=226168&r2=226169&view=diff</a><br>
==============================================================================<br>
--- compiler-rt/trunk/lib/msan/msan_flags.h (original)<br>
+++ compiler-rt/trunk/lib/msan/msan_flags.h Thu Jan 15 09:13:43 2015<br>
@@ -21,7 +21,6 @@ struct Flags {<br>
 #undef MSAN_FLAG<br>
<br>
   void SetDefaults();<br>
-  void ParseFromString(const char *str);<br>
 };<br>
<br>
 Flags *flags();<br>
<br>
Modified: compiler-rt/trunk/lib/sanitizer_common/CMakeLists.txt<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/CMakeLists.txt?rev=226169&r1=226168&r2=226169&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/CMakeLists.txt?rev=226169&r1=226168&r2=226169&view=diff</a><br>
==============================================================================<br>
--- compiler-rt/trunk/lib/sanitizer_common/CMakeLists.txt (original)<br>
+++ compiler-rt/trunk/lib/sanitizer_common/CMakeLists.txt Thu Jan 15 09:13:43 2015<br>
@@ -7,6 +7,7 @@ set(SANITIZER_SOURCES<br>
   sanitizer_deadlock_detector1.cc<br>
   sanitizer_deadlock_detector2.cc<br>
   sanitizer_flags.cc<br>
+  sanitizer_flag_parser.cc<br>
   sanitizer_libc.cc<br>
   sanitizer_libignore.cc<br>
   sanitizer_linux.cc<br>
@@ -63,6 +64,7 @@ set(SANITIZER_HEADERS<br>
   sanitizer_common_syscalls.inc<br>
   sanitizer_deadlock_detector.h<br>
   sanitizer_deadlock_detector_interface.h<br>
+  sanitizer_flag_parser.h<br>
   sanitizer_flags.h<br>
   sanitizer_flags.inc<br>
   sanitizer_internal_defs.h<br>
<br>
Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_allocator_internal.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_allocator_internal.h?rev=226169&r1=226168&r2=226169&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_allocator_internal.h?rev=226169&r1=226168&r2=226169&view=diff</a><br>
==============================================================================<br>
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_allocator_internal.h (original)<br>
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_allocator_internal.h Thu Jan 15 09:13:43 2015<br>
@@ -49,6 +49,15 @@ void *InternalAlloc(uptr size, InternalA<br>
 void InternalFree(void *p, InternalAllocatorCache *cache = 0);<br>
 InternalAllocator *internal_allocator();<br>
<br>
+enum InternalAllocEnum {<br>
+  INTERNAL_ALLOC<br>
+};<br>
+<br>
 }  // namespace __sanitizer<br>
<br>
+inline void *operator new(__sanitizer::operator_new_size_type size,<br>
+                          InternalAllocEnum) {<br>
+  return InternalAlloc(size);<br>
+}<br>
+<br>
 #endif  // SANITIZER_ALLOCATOR_INTERNAL_H<br>
<br>
Added: compiler-rt/trunk/lib/sanitizer_common/sanitizer_flag_parser.cc<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_flag_parser.cc?rev=226169&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_flag_parser.cc?rev=226169&view=auto</a><br>
==============================================================================<br>
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_flag_parser.cc (added)<br>
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_flag_parser.cc Thu Jan 15 09:13:43 2015<br>
@@ -0,0 +1,117 @@<br>
+//===-- sanitizer_flag_parser.cc ------------------------------------------===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+//<br>
+// This file is a part of ThreadSanitizer/AddressSanitizer runtime.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#include "sanitizer_flag_parser.h"<br>
+<br>
+#include "sanitizer_common.h"<br>
+#include "sanitizer_libc.h"<br>
+#include "sanitizer_flags.h"<br>
+#include "sanitizer_flag_parser.h"<br>
+#include "sanitizer_allocator_internal.h"<br>
+<br>
+namespace __sanitizer {<br>
+<br>
+void FlagParser::PrintFlagDescriptions() {<br>
+  Printf("Available flags for %s:\n", SanitizerToolName);<br>
+  for (int i = 0; i < n_flags_; ++i)<br>
+    Printf("\t%s\n\t\t- %s\n", flags_[i].name, flags_[i].desc);<br>
+}<br>
+<br>
+void FlagParser::fatal_error(const char *err) {<br>
+  Printf("ERROR: %s\n", err);<br>
+  Die();<br>
+}<br>
+<br>
+bool FlagParser::is_space(char c) {<br>
+  return c == ' ' || c == ',' || c == ':' || c == '\n' || c == '\t' ||<br>
+         c == '\r';<br>
+}<br>
+<br>
+void FlagParser::skip_whitespace() {<br>
+  while (is_space(buf_[pos_])) ++pos_;<br>
+}<br>
+<br>
+void FlagParser::parse_flag() {<br>
+  uptr name_start = pos_;<br>
+  while (buf_[pos_] != 0 && buf_[pos_] != '=' && !is_space(buf_[pos_])) ++pos_;<br>
+  if (buf_[pos_] != '=') fatal_error("expected '='");<br>
+  const char *name = internal_strndup(buf_ + name_start, pos_ - name_start);<br>
+<br>
+  uptr value_start = ++pos_;<br>
+  const char *value;<br>
+  if (buf_[pos_] == '\'' || buf_[pos_] == '"') {<br>
+    char quote = buf_[pos_++];<br>
+    while (buf_[pos_] != 0 && buf_[pos_] != quote) ++pos_;<br>
+    if (buf_[pos_] == 0) fatal_error("unterminated string");<br>
+    value = internal_strndup(buf_ + value_start + 1, pos_ - value_start - 1);<br>
+    ++pos_; // consume the closing quote<br>
+  } else {<br>
+    while (buf_[pos_] != 0 && !is_space(buf_[pos_])) ++pos_;<br>
+    if (buf_[pos_] != 0 && !is_space(buf_[pos_]))<br>
+      fatal_error("expected separator or eol");<br>
+    value = internal_strndup(buf_ + value_start, pos_ - value_start);<br>
+  }<br>
+<br>
+  bool res = run_handler(name, value);<br>
+  if (!res) {<br>
+    Printf("Flag parsing failed.");<br>
+    Die();<br></blockquote><div><br></div></div></div><div>fatal_error("Flag parsing failed!"); ?</div><div><div class="h5"><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
+  }<br>
+  InternalFree((void *)name);<br>
+  InternalFree((void *)value);<br>
+}<br>
+<br>
+void FlagParser::ParseString(const char *s) {<br>
+  if (!s) return;<br>
+  buf_ = s;<br>
+  pos_ = 0;<br>
+  while (true) {<br>
+    skip_whitespace();<br>
+    if (buf_[pos_] == 0) break;<br>
+    parse_flag();<br>
+  }<br>
+<br>
+  // Do a sanity check for certain flags.<br>
+  if (common_flags_dont_use.malloc_context_size < 1)<br>
+    common_flags_dont_use.malloc_context_size = 1;<br>
+}<br>
+<br>
+bool FlagParser::run_handler(const char *name, const char *value) {<br>
+  for (int i = 0; i < n_flags_; ++i) {<br>
+    if (internal_strcmp(name, flags_[i].name) == 0)<br>
+      return flags_[i].handler->Parse(value);<br>
+  }<br>
+  Printf("ERROR: Unknown flag: '%s'\n", name);<br></blockquote><div><br></div></div></div><div>Do you think we should demote it to warning, or optionally disable this message?</div><div>Sometimes our user add values for new runtime flags before they update the runtime</div><div>to the one that supports these flags.</div><span class=""><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
+  return false;<br>
+}<br>
+<br>
+void FlagParser::RegisterHandler(const char *name, FlagHandlerBase *handler,<br>
+                                 const char *desc) {<br>
+  CHECK(n_flags_ < kMaxFlags);<br></blockquote></span><div>CHECK_LE?</div><span class=""><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
+  flags_[n_flags_].name = name;<br>
+  flags_[n_flags_].desc = desc;<br>
+  flags_[n_flags_].handler = handler;<br>
+  ++n_flags_;<br>
+}<br>
+<br>
+FlagParser::FlagParser() : n_flags_(0), buf_(nullptr), pos_(0) {<br>
+  flags_ = (Flag *)InternalAlloc(sizeof(Flag) * kMaxFlags);<br>
+}<br></blockquote><div><br></div></span><div>Any reason to not make it a resizable InternalMmapVector? Although, see below.</div><span class=""><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
+<br>
+FlagParser::~FlagParser() {<br>
+  for (int i = 0; i < n_flags_; ++i)<br>
+    InternalFree(flags_[i].handler);<br></blockquote><div><br></div></span><div>I'm mildly concerned by the extensive usage of InternalAllocator this early during initialization</div><div>It probably works because we initialize internal allocator lazily, but what if at some point</div><div>internal allocator will itself depend on some flag values? Older version of this code used</div><div>LowLevelAllocator, which doesn't allow you to deallocate memory, but is more simple and lightweight.</div><div>Why did you decide to switch from it?</div><div><div class="h5"><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
+  InternalFree(flags_);<br>
+}<br>
+<br>
+}  // namespace __sanitizer<br>
<br>
Propchange: compiler-rt/trunk/lib/sanitizer_common/sanitizer_flag_parser.cc<br>
------------------------------------------------------------------------------<br>
    svn:eol-style = LF<br>
<br>
Added: compiler-rt/trunk/lib/sanitizer_common/sanitizer_flag_parser.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_flag_parser.h?rev=226169&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_flag_parser.h?rev=226169&view=auto</a><br>
==============================================================================<br>
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_flag_parser.h (added)<br>
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_flag_parser.h Thu Jan 15 09:13:43 2015<br>
@@ -0,0 +1,117 @@<br>
+//===-- sanitizer_flag_parser.h ---------------------------------*- C++ -*-===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+//<br>
+// This file is a part of ThreadSanitizer/AddressSanitizer runtime.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#ifndef SANITIZER_FLAG_REGISTRY_H<br>
+#define SANITIZER_FLAG_REGISTRY_H<br>
+<br>
+#include "sanitizer_internal_defs.h"<br>
+#include "sanitizer_libc.h"<br>
+#include "sanitizer_common.h"<br>
+#include "sanitizer_allocator_internal.h"<br>
+<br>
+namespace __sanitizer {<br>
+<br>
+class FlagHandlerBase {<br>
+ public:<br>
+  virtual bool Parse(const char *value) { return false; }<br>
+};<br>
+<br>
+template <typename T><br>
+class FlagHandler : public FlagHandlerBase {<br>
+  T *t_;<br>
+<br>
+ public:<br>
+  explicit FlagHandler(T *t) : t_(t) {}<br>
+  bool Parse(const char *value);<br>
+};<br>
+<br>
+template <><br>
+inline bool FlagHandler<bool>::Parse(const char *value) {<br>
+  if (internal_strcmp(value, "0") == 0 ||<br>
+      internal_strcmp(value, "no") == 0 ||<br>
+      internal_strcmp(value, "false") == 0) {<br>
+    *t_ = false;<br>
+    return true;<br>
+  }<br>
+  if (internal_strcmp(value, "1") == 0 ||<br>
+      internal_strcmp(value, "yes") == 0 ||<br>
+      internal_strcmp(value, "true") == 0) {<br>
+    *t_ = true;<br>
+    return true;<br>
+  }<br>
+  Printf("ERROR: Invalid value for bool option: '%s'\n", value);<br>
+  return false;<br>
+}<br>
+<br>
+template <><br>
+inline bool FlagHandler<const char *>::Parse(const char *value) {<br>
+  *t_ = internal_strdup(value);<br>
+  return true;<br>
+}<br>
+<br>
+template <><br>
+inline bool FlagHandler<int>::Parse(const char *value) {<br>
+  char *value_end;<br>
+  *t_ = internal_simple_strtoll(value, &value_end, 10);<br>
+  bool ok = *value_end == 0;<br>
+  if (!ok) Printf("ERROR: Invalid value for int option: '%s'\n", value);<br>
+  return ok;<br>
+}<br>
+<br>
+template <><br>
+inline bool FlagHandler<uptr>::Parse(const char *value) {<br>
+  char *value_end;<br>
+  *t_ = internal_simple_strtoll(value, &value_end, 10);<br>
+  bool ok = *value_end == 0;<br>
+  if (!ok) Printf("ERROR: Invalid value for uptr option: '%s'\n", value);<br>
+  return ok;<br>
+}<br>
+<br>
+class FlagParser {<br>
+  static const int kMaxFlags = 200;<br>
+  struct Flag {<br>
+    const char *name;<br>
+    const char *desc;<br>
+    FlagHandlerBase *handler;<br>
+  } *flags_;<br>
+  int n_flags_;<br>
+<br>
+  const char *buf_;<br>
+  uptr pos_;<br>
+<br>
+ public:<br>
+  FlagParser();<br>
+  ~FlagParser();<br>
+  void RegisterHandler(const char *name, FlagHandlerBase *handler,<br>
+                       const char *desc);<br>
+  void ParseString(const char *s);<br>
+  void PrintFlagDescriptions();<br>
+<br>
+ private:<br>
+  void fatal_error(const char *err);<br>
+  bool is_space(char c);<br>
+  void skip_whitespace();<br>
+  void parse_flag();<br>
+  bool run_handler(const char *name, const char *value);<br>
+};<br>
+<br>
+template <typename T><br>
+static void RegisterFlag(FlagParser *parser, const char *name, const char *desc,<br>
+                         T *var) {<br>
+  FlagHandler<T> *fh = new (INTERNAL_ALLOC) FlagHandler<T>(var);  // NOLINT<br>
+  parser->RegisterHandler(name, fh, desc);<br>
+}<br>
+<br>
+}  // namespace __sanitizer<br>
+<br>
+#endif  // SANITIZER_FLAG_REGISTRY_H<br>
<br>
Propchange: compiler-rt/trunk/lib/sanitizer_common/sanitizer_flag_parser.h<br>
------------------------------------------------------------------------------<br>
    svn:eol-style = LF<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=226169&r1=226168&r2=226169&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_flags.cc?rev=226169&r1=226168&r2=226169&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 Jan 15 09:13:43 2015<br>
@@ -16,6 +16,7 @@<br>
 #include "sanitizer_common.h"<br>
 #include "sanitizer_libc.h"<br>
 #include "sanitizer_list.h"<br>
+#include "sanitizer_flag_parser.h"<br>
<br>
 namespace __sanitizer {<br>
<br>
@@ -40,150 +41,15 @@ void CommonFlags::SetDefaults() {<br>
 #undef COMMON_FLAG<br>
 }<br>
<br>
-void CommonFlags::ParseFromString(const char *str) {<br>
-#define COMMON_FLAG(Type, Name, DefaultValue, Description)                     \<br>
-  ParseFlag(str, &Name, #Name, Description);<br>
-#include "sanitizer_flags.inc"<br>
-#undef COMMON_FLAG<br>
-  // Do a sanity check for certain flags.<br>
-  if (malloc_context_size < 1)<br>
-    malloc_context_size = 1;<br>
-}<br>
-<br>
 void CommonFlags::CopyFrom(const CommonFlags &other) {<br>
   internal_memcpy(this, &other, sizeof(*this));<br>
 }<br>
<br>
-static bool GetFlagValue(const char *env, const char *name,<br>
-                         const char **value, int *value_length) {<br>
-  if (env == 0)<br>
-    return false;<br>
-  const char *pos = 0;<br>
-  for (;;) {<br>
-    pos = internal_strstr(env, name);<br>
-    if (pos == 0)<br>
-      return false;<br>
-    const char *name_end = pos + internal_strlen(name);<br>
-    if ((pos != env &&<br>
-         ((pos[-1] >= 'a' && pos[-1] <= 'z') || pos[-1] == '_')) ||<br>
-        *name_end != '=') {<br>
-      // Seems to be middle of another flag name or value.<br>
-      env = pos + 1;<br>
-      continue;<br>
-    }<br>
-    pos = name_end;<br>
-    break;<br>
-  }<br>
-  const char *end;<br>
-  if (pos[0] != '=') {<br>
-    end = pos;<br>
-  } else {<br>
-    pos += 1;<br>
-    if (pos[0] == '"') {<br>
-      pos += 1;<br>
-      end = internal_strchr(pos, '"');<br>
-    } else if (pos[0] == '\'') {<br>
-      pos += 1;<br>
-      end = internal_strchr(pos, '\'');<br>
-    } else {<br>
-      // Read until the next space or colon.<br>
-      end = pos + internal_strcspn(pos, " :\r\n\t");<br>
-    }<br>
-    if (end == 0)<br>
-      end = pos + internal_strlen(pos);<br>
-  }<br>
-  *value = pos;<br>
-  *value_length = end - pos;<br>
-  return true;<br>
-}<br>
-<br>
-static bool StartsWith(const char *flag, int flag_length, const char *value) {<br>
-  if (!flag || !value)<br>
-    return false;<br>
-  int value_length = internal_strlen(value);<br>
-  return (flag_length >= value_length) &&<br>
-         (0 == internal_strncmp(flag, value, value_length));<br>
-}<br>
-<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>
-  IntrusiveList<FlagDescription>::Iterator it(&flag_descriptions);<br>
-  while (it.hasNext()) {<br>
-    if (!internal_strcmp(it.next()->name, name)) return true;<br>
-  }<br>
-  return false;<br>
-}<br>
-<br>
-void AddFlagDescription(const char *name, const char *description) {<br>
-  if (FlagInDescriptionList(name)) return;<br>
-  FlagDescription *new_description = new(allocator_for_flags) FlagDescription;<br>
-  new_description->name = name;<br>
-  new_description->description = description;<br>
-  flag_descriptions.push_back(new_description);<br>
-}<br>
-<br>
-// TODO(glider): put the descriptions inside CommonFlags.<br>
-void PrintFlagDescriptions() {<br>
-  IntrusiveList<FlagDescription>::Iterator it(&flag_descriptions);<br>
-  Printf("Available flags for %s:\n", SanitizerToolName);<br>
-  while (it.hasNext()) {<br>
-    FlagDescription *descr = it.next();<br>
-    Printf("\t%s\n\t\t- %s\n", descr->name, descr->description);<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>
-      StartsWith(value, value_length, "no") ||<br>
-      StartsWith(value, value_length, "false"))<br>
-    *flag = false;<br>
-  if (StartsWith(value, value_length, "1") ||<br>
-      StartsWith(value, value_length, "yes") ||<br>
-      StartsWith(value, value_length, "true"))<br>
-    *flag = true;<br>
-}<br>
-<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,<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>
-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>
-  // tool startup.<br>
-  char *value_copy = (char*)(allocator_for_flags.Allocate(value_length + 1));<br>
-  internal_memcpy(value_copy, value, value_length);<br>
-  value_copy[value_length] = '\0';<br>
-  *flag = value_copy;<br>
+void RegisterCommonFlags(FlagParser *parser, CommonFlags *cf) {<br>
+#define COMMON_FLAG(Type, Name, DefaultValue, Description) \<br>
+  RegisterFlag(parser, #Name, Description, &cf->Name);<br>
+#include "sanitizer_flags.inc"<br>
+#undef COMMON_FLAG<br>
 }<br>
<br>
 }  // namespace __sanitizer<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=226169&r1=226168&r2=226169&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_flags.h?rev=226169&r1=226168&r2=226169&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 Jan 15 09:13:43 2015<br>
@@ -18,22 +18,12 @@<br>
<br>
 namespace __sanitizer {<br>
<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>
 #define COMMON_FLAG(Type, Name, DefaultValue, Description) Type Name;<br>
 #include "sanitizer_flags.inc"<br>
 #undef COMMON_FLAG<br>
<br>
   void SetDefaults();<br>
-  void ParseFromString(const char *str);<br>
   void CopyFrom(const CommonFlags &other);<br>
 };<br>
<br>
@@ -47,10 +37,6 @@ inline void SetCommonFlagsDefaults() {<br>
   common_flags_dont_use.SetDefaults();<br>
 }<br>
<br>
-inline void ParseCommonFlagsFromString(const char *str) {<br>
-  common_flags_dont_use.ParseFromString(str);<br>
-}<br>
-<br>
 // This function can only be used to setup tool-specific overrides for<br>
 // CommonFlags defaults. Generally, it should only be used right after<br>
 // SetCommonFlagsDefaults(), but before ParseCommonFlagsFromString(), and<br>
@@ -60,8 +46,9 @@ inline void OverrideCommonFlags(const Co<br>
   common_flags_dont_use.CopyFrom(cf);<br>
 }<br>
<br>
-void PrintFlagDescriptions();<br>
-<br>
+class FlagParser;<br>
+void RegisterCommonFlags(FlagParser *parser,<br>
+                         CommonFlags *cf = &common_flags_dont_use);<br>
 }  // namespace __sanitizer<br>
<br>
 #endif  // SANITIZER_FLAGS_H<br>
<br>
Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_libc.cc<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_libc.cc?rev=226169&r1=226168&r2=226169&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_libc.cc?rev=226169&r1=226168&r2=226169&view=diff</a><br>
==============================================================================<br>
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_libc.cc (original)<br>
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_libc.cc Thu Jan 15 09:13:43 2015<br>
@@ -101,6 +101,14 @@ char* internal_strdup(const char *s) {<br>
   return s2;<br>
 }<br>
<br>
+char* internal_strndup(const char *s, uptr n) {<br>
+  uptr len = internal_strnlen(s, n);<br>
+  char *s2 = (char*)InternalAlloc(len + 1);<br>
+  internal_memcpy(s2, s, len);<br>
+  s2[len] = 0;<br>
+  return s2;<br>
+}<br>
+<br>
 int internal_strcmp(const char *s1, const char *s2) {<br>
   while (true) {<br>
     unsigned c1 = *s1;<br>
<br>
Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_libc.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_libc.h?rev=226169&r1=226168&r2=226169&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_libc.h?rev=226169&r1=226168&r2=226169&view=diff</a><br>
==============================================================================<br>
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_libc.h (original)<br>
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_libc.h Thu Jan 15 09:13:43 2015<br>
@@ -38,6 +38,7 @@ char *internal_strchrnul(const char *s,<br>
 int internal_strcmp(const char *s1, const char *s2);<br>
 uptr internal_strcspn(const char *s, const char *reject);<br>
 char *internal_strdup(const char *s);<br>
+char *internal_strndup(const char *s, uptr n);<br>
 uptr internal_strlen(const char *s);<br>
 char *internal_strncat(char *dst, const char *src, uptr n);<br>
 int internal_strncmp(const char *s1, const char *s2, uptr n);<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=226169&r1=226168&r2=226169&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_flags_test.cc?rev=226169&r1=226168&r2=226169&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 Jan 15 09:13:43 2015<br>
@@ -12,7 +12,9 @@<br>
 //===----------------------------------------------------------------------===//<br>
 #include "sanitizer_common/sanitizer_common.h"<br>
 #include "sanitizer_common/sanitizer_flags.h"<br>
+#include "sanitizer_common/sanitizer_flag_parser.h"<br>
 #include "sanitizer_common/sanitizer_libc.h"<br>
+#include "sanitizer_common/sanitizer_allocator_internal.h"<br>
 #include "gtest/gtest.h"<br>
<br>
 #include <string.h><br>
@@ -20,58 +22,74 @@<br>
 namespace __sanitizer {<br>
<br>
 static const char kFlagName[] = "flag_name";<br>
+static const char kFlagDesc[] = "flag description";<br>
<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, "flag description");<br>
+<br>
+  FlagParser parser;<br>
+  RegisterFlag(&parser, kFlagName, kFlagDesc, &flag);<br>
+<br>
+  parser.ParseString(env);<br>
+<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>
+template <><br>
+void TestFlag(const char *start_value, const char *env,<br>
+                     const char *final_value) {<br>
   const char *flag = start_value;<br>
-  ParseFlag(env, &flag, kFlagName, "flag description");<br>
+<br>
+  FlagParser parser;<br>
+  RegisterFlag(&parser, kFlagName, kFlagDesc, &flag);<br>
+<br>
+  parser.ParseString(env);<br>
+<br>
   EXPECT_EQ(0, internal_strcmp(final_value, flag));<br>
 }<br>
<br>
 TEST(SanitizerCommon, BooleanFlags) {<br>
-  TestFlag(true, "--flag_name", true);<br>
-  TestFlag(false, "flag_name", false);<br>
-  TestFlag(false, "--flag_name=1", true);<br>
-  TestFlag(true, "asdas flag_name=0 asdas", false);<br>
-  TestFlag(true, "    --flag_name=0   ", false);<br>
+  TestFlag(false, "flag_name=1", true);<br>
   TestFlag(false, "flag_name=yes", true);<br>
   TestFlag(false, "flag_name=true", true);<br>
+  TestFlag(true, "flag_name=0", false);<br>
   TestFlag(true, "flag_name=no", false);<br>
   TestFlag(true, "flag_name=false", false);<br>
 }<br>
<br>
 TEST(SanitizerCommon, IntFlags) {<br>
   TestFlag(-11, 0, -11);<br>
-  TestFlag(-11, "flag_name", -11);<br>
-  TestFlag(-11, "--flag_name=", 0);<br>
-  TestFlag(-11, "--flag_name=42", 42);<br>
-  TestFlag(-11, "--flag_name=-42", -42);<br>
+  TestFlag(-11, "flag_name=0", 0);<br>
+  TestFlag(-11, "flag_name=42", 42);<br>
+  TestFlag(-11, "flag_name=-42", -42);<br>
+  EXPECT_DEATH(TestFlag(-11, "flag_name", 0), "expected '='");<br>
+  EXPECT_DEATH(TestFlag(-11, "--flag_name=42", 0),<br>
+               "Unknown flag: '--flag_name'");<br>
 }<br>
<br>
 TEST(SanitizerCommon, StrFlags) {<br>
-  TestStrFlag("zzz", 0, "zzz");<br>
-  TestStrFlag("zzz", "flag_name", "zzz");<br>
-  TestStrFlag("zzz", "--flag_name=", "");<br>
-  TestStrFlag("", "--flag_name=abc", "abc");<br>
-  TestStrFlag("", "--flag_name='abc zxc'", "abc zxc");<br>
-  TestStrFlag("", "--flag_name='abc zxcc'", "abc zxcc");<br>
-  TestStrFlag("", "--flag_name=\"abc qwe\" asd", "abc qwe");<br>
-  TestStrFlag("", "other_flag_name=zzz", "");<br>
+  TestFlag("zzz", 0, "zzz");<br>
+  TestFlag("zzz", "flag_name=", "");<br>
+  TestFlag("zzz", "flag_name=abc", "abc");<br>
+  TestFlag("", "flag_name=abc", "abc");<br>
+  TestFlag("", "flag_name='abc zxc'", "abc zxc");<br>
+  // TestStrFlag("", "flag_name=\"abc qwe\" asd", "abc qwe");<br>
 }<br>
<br>
 static void TestTwoFlags(const char *env, bool expected_flag1,<br>
-                         const char *expected_flag2) {<br>
+                         const char *expected_flag2,<br>
+                         const char *name1 = "flag1",<br>
+                         const char *name2 = "flag2") {<br>
   bool flag1 = !expected_flag1;<br>
   const char *flag2 = "";<br>
-  ParseFlag(env, &flag1, "flag1", "flag1 description");<br>
-  ParseFlag(env, &flag2, "flag2", "flag2 description");<br>
+<br>
+  FlagParser parser;<br>
+  RegisterFlag(&parser, name1, kFlagDesc, &flag1);<br>
+  RegisterFlag(&parser, name2, kFlagDesc, &flag2);<br>
+<br>
+  parser.ParseString(env);<br>
+<br>
   EXPECT_EQ(expected_flag1, flag1);<br>
   EXPECT_EQ(0, internal_strcmp(flag2, expected_flag2));<br>
 }<br>
@@ -86,8 +104,20 @@ TEST(SanitizerCommon, MultipleFlags) {<br>
   TestTwoFlags("flag2=qxx\tflag1=yes", true, "qxx");<br>
 }<br>
<br>
+TEST(SanitizerCommon, CommonSuffixFlags) {<br>
+  TestTwoFlags("flag=1 other_flag='zzz'", true, "zzz", "flag", "other_flag");<br>
+  TestTwoFlags("other_flag='zzz' flag=1", true, "zzz", "flag", "other_flag");<br>
+  TestTwoFlags("other_flag=' flag=0 ' flag=1", true, " flag=0 ", "flag",<br>
+               "other_flag");<br>
+  TestTwoFlags("flag=1 other_flag=' flag=0 '", true, " flag=0 ", "flag",<br>
+               "other_flag");<br>
+}<br>
+<br>
 TEST(SanitizerCommon, CommonFlags) {<br>
   CommonFlags cf;<br>
+  FlagParser parser;<br>
+  RegisterCommonFlags(&parser, &cf);<br>
+<br>
   cf.SetDefaults();<br>
   EXPECT_TRUE(cf.symbolize);<br>
   EXPECT_STREQ(".", cf.coverage_dir);<br>
@@ -97,7 +127,7 @@ TEST(SanitizerCommon, CommonFlags) {<br>
   cf.coverage_direct = true;<br>
   cf.log_path = "path/one";<br>
<br>
-  cf.ParseFromString("symbolize=1:coverage_direct=false log_path='path/two'");<br>
+  parser.ParseString("symbolize=1:coverage_direct=false log_path='path/two'");<br>
   EXPECT_TRUE(cf.symbolize);<br>
   EXPECT_TRUE(cf.coverage);<br>
   EXPECT_FALSE(cf.coverage_direct);<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=226169&r1=226168&r2=226169&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/dd/dd_rtl.cc?rev=226169&r1=226168&r2=226169&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 Jan 15 09:13:43 2015<br>
@@ -11,6 +11,7 @@<br>
 #include "sanitizer_common/sanitizer_common.h"<br>
 #include "sanitizer_common/sanitizer_placement_new.h"<br>
 #include "sanitizer_common/sanitizer_flags.h"<br>
+#include "sanitizer_common/sanitizer_flag_parser.h"<br>
 #include "sanitizer_common/sanitizer_stacktrace.h"<br>
 #include "sanitizer_common/sanitizer_stackdepot.h"<br>
<br>
@@ -80,8 +81,10 @@ void InitializeFlags(Flags *f, const cha<br>
   }<br>
<br>
   // Override from command line.<br>
-  ParseFlag(env, &f->second_deadlock_stack, "second_deadlock_stack", "");<br>
-  ParseCommonFlagsFromString(env);<br>
+  FlagParser parser;<br>
+  RegisterFlag(&parser, "second_deadlock_stack", "", &f->second_deadlock_stack);<br>
+  RegisterCommonFlags(&parser);<br>
+  parser.ParseString(env);<br>
 }<br>
<br>
 void Initialize() {<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=226169&r1=226168&r2=226169&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_flags.cc?rev=226169&r1=226168&r2=226169&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 Jan 15 09:13:43 2015<br>
@@ -12,6 +12,7 @@<br>
 //===----------------------------------------------------------------------===//<br>
<br>
 #include "sanitizer_common/sanitizer_flags.h"<br>
+#include "sanitizer_common/sanitizer_flag_parser.h"<br>
 #include "sanitizer_common/sanitizer_libc.h"<br>
 #include "tsan_flags.h"<br>
 #include "tsan_rtl.h"<br>
@@ -41,16 +42,18 @@ void Flags::SetDefaults() {<br>
   second_deadlock_stack = false;<br>
 }<br>
<br>
-void Flags::ParseFromString(const char *str) {<br>
-#define TSAN_FLAG(Type, Name, DefaultValue, Description)                     \<br>
-  ParseFlag(str, &Name, #Name, Description);<br>
+void RegisterTsanFlags(FlagParser *parser, Flags *f) {<br>
+#define TSAN_FLAG(Type, Name, DefaultValue, Description) \<br>
+  RegisterFlag(parser, #Name, Description, &f->Name);<br>
 #include "tsan_flags.inc"<br>
 #undef TSAN_FLAG<br>
-  // DDFlags<br>
-  ParseFlag(str, &second_deadlock_stack, "second_deadlock_stack", "");<br>
 }<br>
<br>
 void InitializeFlags(Flags *f, const char *env) {<br>
+  FlagParser parser;<br>
+  RegisterTsanFlags(&parser, f);<br>
+  RegisterCommonFlags(&parser);<br>
+<br>
   f->SetDefaults();<br>
<br>
   SetCommonFlagsDefaults();<br>
@@ -66,11 +69,9 @@ void InitializeFlags(Flags *f, const cha<br>
   }<br>
<br>
   // Let a frontend override.<br>
-  f->ParseFromString(__tsan_default_options());<br>
-  ParseCommonFlagsFromString(__tsan_default_options());<br>
+  parser.ParseString(__tsan_default_options());<br>
   // Override from command line.<br>
-  f->ParseFromString(env);<br>
-  ParseCommonFlagsFromString(env);<br>
+  parser.ParseString(env);<br>
<br>
   // Sanity check.<br>
   if (!f->report_bugs) {<br>
@@ -80,7 +81,7 @@ void InitializeFlags(Flags *f, const cha<br>
   }<br>
<br>
   if (common_flags()->help)<br>
-    PrintFlagDescriptions();<br>
+    parser.PrintFlagDescriptions();<br>
<br>
   if (f->history_size < 0 || f->history_size > 7) {<br>
     Printf("ThreadSanitizer: incorrect value for history_size"<br>
<br>
Modified: compiler-rt/trunk/lib/ubsan/ubsan_flags.cc<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/ubsan/ubsan_flags.cc?rev=226169&r1=226168&r2=226169&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/ubsan/ubsan_flags.cc?rev=226169&r1=226168&r2=226169&view=diff</a><br>
==============================================================================<br>
--- compiler-rt/trunk/lib/ubsan/ubsan_flags.cc (original)<br>
+++ compiler-rt/trunk/lib/ubsan/ubsan_flags.cc Thu Jan 15 09:13:43 2015<br>
@@ -14,6 +14,7 @@<br>
 #include "ubsan_flags.h"<br>
 #include "sanitizer_common/sanitizer_common.h"<br>
 #include "sanitizer_common/sanitizer_flags.h"<br>
+#include "sanitizer_common/sanitizer_flag_parser.h"<br>
<br>
 namespace __ubsan {<br>
<br>
@@ -21,18 +22,6 @@ static const char *MaybeCallUbsanDefault<br>
   return (&__ubsan_default_options) ? __ubsan_default_options() : "";<br>
 }<br>
<br>
-void InitializeCommonFlags() {<br>
-  SetCommonFlagsDefaults();<br>
-  CommonFlags cf;<br>
-  cf.CopyFrom(*common_flags());<br>
-  cf.print_summary = false;<br>
-  OverrideCommonFlags(cf);<br>
-  // Override from user-specified string.<br>
-  ParseCommonFlagsFromString(MaybeCallUbsanDefaultOptions());<br>
-  // Override from environment variable.<br>
-  ParseCommonFlagsFromString(GetEnv("UBSAN_OPTIONS"));<br>
-}<br>
-<br>
 Flags ubsan_flags;<br>
<br>
 void Flags::SetDefaults() {<br>
@@ -41,20 +30,42 @@ void Flags::SetDefaults() {<br>
 #undef UBSAN_FLAG<br>
 }<br>
<br>
-void Flags::ParseFromString(const char *str) {<br>
-#define UBSAN_FLAG(Type, Name, DefaultValue, Description)                      \<br>
-  ParseFlag(str, &Name, #Name, Description);<br>
+void RegisterUbsanFlags(FlagParser *parser, Flags *f) {<br>
+#define UBSAN_FLAG(Type, Name, DefaultValue, Description) \<br>
+  RegisterFlag(parser, #Name, Description, &f->Name);<br>
 #include "ubsan_flags.inc"<br>
 #undef UBSAN_FLAG<br>
 }<br>
<br>
-void InitializeFlags() {<br>
+void InitializeFlags(bool standalone) {<br>
   Flags *f = flags();<br>
+  FlagParser parser;<br>
+  RegisterUbsanFlags(&parser, f);<br>
+<br>
+  if (standalone) {<br>
+    RegisterCommonFlags(&parser);<br>
+<br>
+    SetCommonFlagsDefaults();<br>
+    CommonFlags cf;<br>
+    cf.CopyFrom(*common_flags());<br>
+    cf.print_summary = false;<br>
+    OverrideCommonFlags(cf);<br>
+  } else {<br>
+    // Ignore common flags if not standalone.<br>
+    // This is inconsistent with LSan, which allows common flags in LSAN_FLAGS.<br>
+    // This is caused by undefined initialization order between ASan and UBsan,<br>
+    // which makes it impossible to make sure that common flags from ASAN_OPTIONS<br>
+    // have not been used (in __asan_init) before they are overwritten with flags<br>
+    // from UBSAN_OPTIONS.<br>
+    CommonFlags cf_ignored;<br>
+    RegisterCommonFlags(&parser, &cf_ignored);<br>
+  }<br>
+<br>
   f->SetDefaults();<br>
   // Override from user-specified string.<br>
-  f->ParseFromString(MaybeCallUbsanDefaultOptions());<br>
+  parser.ParseString(MaybeCallUbsanDefaultOptions());<br>
   // Override from environment variable.<br>
-  f->ParseFromString(GetEnv("UBSAN_OPTIONS"));<br>
+  parser.ParseString(GetEnv("UBSAN_OPTIONS"));<br>
 }<br>
<br>
 }  // namespace __ubsan<br>
<br>
Modified: compiler-rt/trunk/lib/ubsan/ubsan_flags.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/ubsan/ubsan_flags.h?rev=226169&r1=226168&r2=226169&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/ubsan/ubsan_flags.h?rev=226169&r1=226168&r2=226169&view=diff</a><br>
==============================================================================<br>
--- compiler-rt/trunk/lib/ubsan/ubsan_flags.h (original)<br>
+++ compiler-rt/trunk/lib/ubsan/ubsan_flags.h Thu Jan 15 09:13:43 2015<br>
@@ -23,14 +23,12 @@ struct Flags {<br>
 #undef UBSAN_FLAG<br>
<br>
   void SetDefaults();<br>
-  void ParseFromString(const char *str);<br>
 };<br>
<br>
 extern Flags ubsan_flags;<br>
 inline Flags *flags() { return &ubsan_flags; }<br>
<br>
-void InitializeCommonFlags();<br>
-void InitializeFlags();<br>
+void InitializeFlags(bool standalone);<br>
<br>
 }  // namespace __ubsan<br>
<br>
<br>
Modified: compiler-rt/trunk/lib/ubsan/ubsan_init.cc<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/ubsan/ubsan_init.cc?rev=226169&r1=226168&r2=226169&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/ubsan/ubsan_init.cc?rev=226169&r1=226168&r2=226169&view=diff</a><br>
==============================================================================<br>
--- compiler-rt/trunk/lib/ubsan/ubsan_init.cc (original)<br>
+++ compiler-rt/trunk/lib/ubsan/ubsan_init.cc Thu Jan 15 09:13:43 2015<br>
@@ -31,6 +31,7 @@ void __ubsan::InitIfNecessary() {<br>
 #endif<br>
   if (LIKELY(ubsan_inited))<br>
    return;<br>
+  bool standalone = false;<br>
   if (0 == internal_strcmp(SanitizerToolName, "SanitizerTool")) {<br>
     // WARNING: If this condition holds, then either UBSan runs in a standalone<br>
     // mode, or initializer for another sanitizer hasn't run yet. In a latter<br>
@@ -38,10 +39,10 @@ void __ubsan::InitIfNecessary() {<br>
     // common flags. It means, that we are not allowed to *use* common flags<br>
     // in this function.<br>
     SanitizerToolName = "UndefinedBehaviorSanitizer";<br>
-    InitializeCommonFlags();<br>
+    standalone = true;<br>
   }<br>
   // Initialize UBSan-specific flags.<br>
-  InitializeFlags();<br>
+  InitializeFlags(standalone);<br>
   SuppressionContext::InitIfNecessary();<br>
   InitializeCoverage(common_flags()->coverage, common_flags()->coverage_dir);<br>
   ubsan_inited = true;<br>
<br>
Added: compiler-rt/trunk/test/asan/TestCases/asan_options-help.cc<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/asan/TestCases/asan_options-help.cc?rev=226169&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/asan/TestCases/asan_options-help.cc?rev=226169&view=auto</a><br>
==============================================================================<br>
--- compiler-rt/trunk/test/asan/TestCases/asan_options-help.cc (added)<br>
+++ compiler-rt/trunk/test/asan/TestCases/asan_options-help.cc Thu Jan 15 09:13:43 2015<br>
@@ -0,0 +1,9 @@<br>
+// RUN: %clangxx_asan -O0 %s -o %t<br>
+// RUN: ASAN_OPTIONS=help=1 %run %t 2>&1 | FileCheck %s<br>
+<br>
+int main() {<br>
+}<br>
+<br>
+// CHECK: Available flags for AddressSanitizer:<br>
+// CHECK-DAG: handle_segv<br>
+// CHECK-DAG: check_initialization_order</blockquote><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
<br>
Propchange: compiler-rt/trunk/test/asan/TestCases/asan_options-help.cc<br>
------------------------------------------------------------------------------<br>
    svn:eol-style = LF<br>
<br>
Added: compiler-rt/trunk/test/asan/TestCases/asan_options-invalid.cc<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/asan/TestCases/asan_options-invalid.cc?rev=226169&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/asan/TestCases/asan_options-invalid.cc?rev=226169&view=auto</a><br>
==============================================================================<br>
--- compiler-rt/trunk/test/asan/TestCases/asan_options-invalid.cc (added)<br>
+++ compiler-rt/trunk/test/asan/TestCases/asan_options-invalid.cc Thu Jan 15 09:13:43 2015<br>
@@ -0,0 +1,7 @@<br>
+// RUN: %clangxx_asan -O0 %s -o %t<br>
+// RUN: ASAN_OPTIONS=invalid_option_name=10 not %run %t 2>&1 | FileCheck %s<br>
+<br>
+int main() {<br>
+}<br>
+<br>
+// CHECK: Unknown flag{{.*}}invalid_option_name<br></blockquote><div><br></div></div></div><div>Shouldn't this (and maybe similar tests) go into tests/sanitizer_common?</div><div><div class="h5"><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
<br>
Propchange: compiler-rt/trunk/test/asan/TestCases/asan_options-invalid.cc<br>
------------------------------------------------------------------------------<br>
    svn:eol-style = LF<br>
<br>
Modified: compiler-rt/trunk/test/asan/TestCases/default_options.cc<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/asan/TestCases/default_options.cc?rev=226169&r1=226168&r2=226169&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/asan/TestCases/default_options.cc?rev=226169&r1=226168&r2=226169&view=diff</a><br>
==============================================================================<br>
--- compiler-rt/trunk/test/asan/TestCases/default_options.cc (original)<br>
+++ compiler-rt/trunk/test/asan/TestCases/default_options.cc Thu Jan 15 09:13:43 2015<br>
@@ -4,12 +4,12 @@<br>
 // __asan_default_options() are not supported on Windows.<br>
 // XFAIL: win32<br>
<br>
-const char *kAsanDefaultOptions="verbosity=1 foo=bar";<br>
+const char *kAsanDefaultOptions="verbosity=1 strip_path_prefix=bar";<br>
<br>
 extern "C"<br>
 __attribute__((no_sanitize_address))<br>
 const char *__asan_default_options() {<br>
-  // CHECK: Using the defaults from __asan_default_options: {{.*}} foo=bar<br>
+  // CHECK: Using the defaults from __asan_default_options: {{.*}} strip_path_prefix=bar<br>
   return kAsanDefaultOptions;<br>
 }<br>
<br>
<br>
Modified: compiler-rt/trunk/test/lsan/TestCases/ignore_object.cc<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/lsan/TestCases/ignore_object.cc?rev=226169&r1=226168&r2=226169&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/lsan/TestCases/ignore_object.cc?rev=226169&r1=226168&r2=226169&view=diff</a><br>
==============================================================================<br>
--- compiler-rt/trunk/test/lsan/TestCases/ignore_object.cc (original)<br>
+++ compiler-rt/trunk/test/lsan/TestCases/ignore_object.cc Thu Jan 15 09:13:43 2015<br>
@@ -1,5 +1,5 @@<br>
 // Test for __lsan_ignore_object().<br>
-// RUN: LSAN_BASE="report_objects=1:use_registers=0:use_stacks=0:use_globals=0:use_tls=0:verbosity=2"<br>
+// RUN: LSAN_BASE="report_objects=1:use_registers=0:use_stacks=0:use_globals=0:use_tls=0"<br>
 // RUN: %clangxx_lsan %s -o %t<br>
 // RUN: LSAN_OPTIONS=$LSAN_BASE not %run %t 2>&1 | FileCheck %s<br>
<br>
@@ -20,5 +20,4 @@ int main() {<br>
   return 0;<br>
 }<br>
 // CHECK: Test alloc: [[ADDR:.*]].<br>
-// CHECK: ignoring heap object at [[ADDR]]<br>
 // CHECK: SUMMARY: {{(Leak|Address)}}Sanitizer: 1337 byte(s) leaked in 1 allocation(s)<br></blockquote><div><br></div></div></div><div>Why was this test changed?</div></div></div></div></blockquote><div>That's a great way to fix tests.</div><div><br></div><div>Let's just delete them all so they won't get in the way of future changes.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div><div class="h5"><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
<br>
Modified: compiler-rt/trunk/test/lsan/TestCases/ignore_object_errors.cc<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/lsan/TestCases/ignore_object_errors.cc?rev=226169&r1=226168&r2=226169&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/lsan/TestCases/ignore_object_errors.cc?rev=226169&r1=226168&r2=226169&view=diff</a><br>
==============================================================================<br>
--- compiler-rt/trunk/test/lsan/TestCases/ignore_object_errors.cc (original)<br>
+++ compiler-rt/trunk/test/lsan/TestCases/ignore_object_errors.cc Thu Jan 15 09:13:43 2015<br>
@@ -1,5 +1,4 @@<br>
 // Test for incorrect use of __lsan_ignore_object().<br>
-// RUN: LSAN_BASE="verbosity=2"<br>
 // RUN: %clangxx_lsan %s -o %t<br>
 // RUN: LSAN_OPTIONS=$LSAN_BASE %run %t 2>&1 | FileCheck %s<br>
<br>
@@ -18,5 +17,4 @@ int main() {<br>
   return 0;<br>
 }<br>
 // CHECK: Test alloc: [[ADDR:.*]].<br>
-// CHECK: heap object at [[ADDR]] is already being ignored<br>
-// CHECK: no heap object found at [[ADDR]]<br>
+// CHECK-NOT: SUMMARY: {{.*}} leaked<br>
<br>
Modified: compiler-rt/trunk/test/ubsan/TestCases/TypeCheck/vptr.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/ubsan/TestCases/TypeCheck/vptr.cpp?rev=226169&r1=226168&r2=226169&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/ubsan/TestCases/TypeCheck/vptr.cpp?rev=226169&r1=226168&r2=226169&view=diff</a><br>
==============================================================================<br>
--- compiler-rt/trunk/test/ubsan/TestCases/TypeCheck/vptr.cpp (original)<br>
+++ compiler-rt/trunk/test/ubsan/TestCases/TypeCheck/vptr.cpp Thu Jan 15 09:13:43 2015<br>
@@ -12,16 +12,16 @@<br>
 // RUN: %run %t m0 2>&1 | FileCheck %s --check-prefix=CHECK-NULL-MEMBER --strict-whitespace<br>
<br>
 // RUN: (echo "vptr_check:S"; echo "vptr_check:T"; echo "vptr_check:U") > %t.supp<br>
-// RUN: ASAN_OPTIONS="suppressions='%t.supp':halt_on_error=1" UBSAN_OPTIONS="suppressions='%t.supp':halt_on_error=1" %run %t mS 2>&1<br>
-// RUN: ASAN_OPTIONS="suppressions='%t.supp':halt_on_error=1" UBSAN_OPTIONS="suppressions='%t.supp':halt_on_error=1" %run %t fS 2>&1<br>
-// RUN: ASAN_OPTIONS="suppressions='%t.supp':halt_on_error=1" UBSAN_OPTIONS="suppressions='%t.supp':halt_on_error=1" %run %t cS 2>&1<br>
-// RUN: ASAN_OPTIONS="suppressions='%t.supp':halt_on_error=1" UBSAN_OPTIONS="suppressions='%t.supp':halt_on_error=1" %run %t mV 2>&1<br>
-// RUN: ASAN_OPTIONS="suppressions='%t.supp':halt_on_error=1" UBSAN_OPTIONS="suppressions='%t.supp':halt_on_error=1" %run %t fV 2>&1<br>
-// RUN: ASAN_OPTIONS="suppressions='%t.supp':halt_on_error=1" UBSAN_OPTIONS="suppressions='%t.supp':halt_on_error=1" %run %t cV 2>&1<br>
-// RUN: ASAN_OPTIONS="suppressions='%t.supp':halt_on_error=1" UBSAN_OPTIONS="suppressions='%t.supp':halt_on_error=1" %run %t oU 2>&1<br>
+// RUN: ASAN_OPTIONS="suppressions='%t.supp'" UBSAN_OPTIONS="suppressions='%t.supp':halt_on_error=1" %run %t mS 2>&1<br>
+// RUN: ASAN_OPTIONS="suppressions='%t.supp'" UBSAN_OPTIONS="suppressions='%t.supp':halt_on_error=1" %run %t fS 2>&1<br>
+// RUN: ASAN_OPTIONS="suppressions='%t.supp'" UBSAN_OPTIONS="suppressions='%t.supp':halt_on_error=1" %run %t cS 2>&1<br>
+// RUN: ASAN_OPTIONS="suppressions='%t.supp'" UBSAN_OPTIONS="suppressions='%t.supp':halt_on_error=1" %run %t mV 2>&1<br>
+// RUN: ASAN_OPTIONS="suppressions='%t.supp'" UBSAN_OPTIONS="suppressions='%t.supp':halt_on_error=1" %run %t fV 2>&1<br>
+// RUN: ASAN_OPTIONS="suppressions='%t.supp'" UBSAN_OPTIONS="suppressions='%t.supp':halt_on_error=1" %run %t cV 2>&1<br>
+// RUN: ASAN_OPTIONS="suppressions='%t.supp'" UBSAN_OPTIONS="suppressions='%t.supp':halt_on_error=1" %run %t oU 2>&1<br>
<br>
 // RUN: echo "vptr_check:S" > %t.loc-supp<br>
-// RUN: ASAN_OPTIONS="suppressions='%t.loc-supp':halt_on_error=1" UBSAN_OPTIONS="suppressions='%t.loc-supp':halt_on_error=1" not %run %t x- 2>&1 | FileCheck %s --check-prefix=CHECK-LOC-SUPPRESS<br>
+// RUN: ASAN_OPTIONS="suppressions='%t.loc-supp'" UBSAN_OPTIONS="suppressions='%t.loc-supp':halt_on_error=1" not %run %t x- 2>&1 | FileCheck %s --check-prefix=CHECK-LOC-SUPPRESS<br>
<br>
 // FIXME: This test produces linker errors on Darwin.<br>
 // XFAIL: darwin<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@cs.uiuc.edu" target="_blank">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></div></div><span class="HOEnZb"><font color="#888888"><br><br clear="all"><div><br></div>-- <br><div><div dir="ltr">Alexey Samsonov<br><a href="mailto:vonosmas@gmail.com" target="_blank">vonosmas@gmail.com</a></div></div>
</font></span></div></div>
<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>
<br></blockquote></div><br></div></div>