[compiler-rt] r226169 - [sanitizer] Flag parser rewrite.

Evgeniy Stepanov eugeni.stepanov at gmail.com
Thu Jan 15 07:13:44 PST 2015


Author: eugenis
Date: Thu Jan 15 09:13:43 2015
New Revision: 226169

URL: http://llvm.org/viewvc/llvm-project?rev=226169&view=rev
Log:
[sanitizer] Flag parser rewrite.

The new parser is a lot stricter about syntax, reports unrecognized
flags, and will make it easier to implemented some of the planned features.


Added:
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_flag_parser.cc   (with props)
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_flag_parser.h   (with props)
    compiler-rt/trunk/test/asan/TestCases/asan_options-help.cc   (with props)
    compiler-rt/trunk/test/asan/TestCases/asan_options-invalid.cc   (with props)
Modified:
    compiler-rt/trunk/CMakeLists.txt
    compiler-rt/trunk/lib/asan/asan_activation.cc
    compiler-rt/trunk/lib/asan/asan_flags.cc
    compiler-rt/trunk/lib/asan/asan_flags.h
    compiler-rt/trunk/lib/asan/tests/CMakeLists.txt
    compiler-rt/trunk/lib/dfsan/CMakeLists.txt
    compiler-rt/trunk/lib/dfsan/dfsan.cc
    compiler-rt/trunk/lib/dfsan/dfsan.h
    compiler-rt/trunk/lib/lsan/lsan_common.cc
    compiler-rt/trunk/lib/lsan/lsan_common.h
    compiler-rt/trunk/lib/msan/msan.cc
    compiler-rt/trunk/lib/msan/msan_flags.h
    compiler-rt/trunk/lib/sanitizer_common/CMakeLists.txt
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_allocator_internal.h
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_flags.cc
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_flags.h
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_libc.cc
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_libc.h
    compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_flags_test.cc
    compiler-rt/trunk/lib/tsan/dd/dd_rtl.cc
    compiler-rt/trunk/lib/tsan/rtl/tsan_flags.cc
    compiler-rt/trunk/lib/ubsan/ubsan_flags.cc
    compiler-rt/trunk/lib/ubsan/ubsan_flags.h
    compiler-rt/trunk/lib/ubsan/ubsan_init.cc
    compiler-rt/trunk/test/asan/TestCases/default_options.cc
    compiler-rt/trunk/test/lsan/TestCases/ignore_object.cc
    compiler-rt/trunk/test/lsan/TestCases/ignore_object_errors.cc
    compiler-rt/trunk/test/ubsan/TestCases/TypeCheck/vptr.cpp

Modified: compiler-rt/trunk/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/CMakeLists.txt?rev=226169&r1=226168&r2=226169&view=diff
==============================================================================
--- compiler-rt/trunk/CMakeLists.txt (original)
+++ compiler-rt/trunk/CMakeLists.txt Thu Jan 15 09:13:43 2015
@@ -234,7 +234,7 @@ append_list_if(COMPILER_RT_HAS_FUNWIND_T
 append_list_if(COMPILER_RT_HAS_FNO_STACK_PROTECTOR_FLAG -fno-stack-protector SANITIZER_COMMON_CFLAGS)
 append_list_if(COMPILER_RT_HAS_FVISIBILITY_HIDDEN_FLAG -fvisibility=hidden SANITIZER_COMMON_CFLAGS)
 append_list_if(COMPILER_RT_HAS_FNO_FUNCTION_SECTIONS_FLAG -fno-function-sections SANITIZER_COMMON_CFLAGS)
-append_list_if(COMPILER_RT_HAS_FNO_LTO_FLAG -fno-lto SANITIZER_COMMON_CFLAGS)
+# append_list_if(COMPILER_RT_HAS_FNO_LTO_FLAG -fno-lto SANITIZER_COMMON_CFLAGS)
 
 if(MSVC)
   # Replace the /MD[d] flags with /MT.

Modified: compiler-rt/trunk/lib/asan/asan_activation.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_activation.cc?rev=226169&r1=226168&r2=226169&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_activation.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_activation.cc Thu Jan 15 09:13:43 2015
@@ -32,6 +32,9 @@ static struct AsanDeactivatedFlags {
   void OverrideFromActivationFlags() {
     Flags f;
     CommonFlags cf;
+    FlagParser parser;
+    RegisterAsanFlags(&parser, &f);
+    RegisterCommonFlags(&parser, &cf);
 
     // Copy the current activation flags.
     allocator_options.CopyTo(&f, &cf);
@@ -44,15 +47,13 @@ static struct AsanDeactivatedFlags {
     // FIXME: Add diagnostic to check that activation flags string doesn't
     // contain any other flags.
     if (const char *env = GetEnv("ASAN_ACTIVATION_OPTIONS")) {
-      cf.ParseFromString(env);
-      f.ParseFromString(env);
+      parser.ParseString(env);
     }
 
     // Override from getprop asan.options.
     char buf[100];
     GetExtraActivationFlags(buf, sizeof(buf));
-    cf.ParseFromString(buf);
-    f.ParseFromString(buf);
+    parser.ParseString(buf);
 
     allocator_options.SetFrom(&f, &cf);
     malloc_context_size = cf.malloc_context_size;

Modified: compiler-rt/trunk/lib/asan/asan_flags.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_flags.cc?rev=226169&r1=226168&r2=226169&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_flags.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_flags.cc Thu Jan 15 09:13:43 2015
@@ -19,6 +19,7 @@
 #include "lsan/lsan_common.h"
 #include "sanitizer_common/sanitizer_common.h"
 #include "sanitizer_common/sanitizer_flags.h"
+#include "sanitizer_common/sanitizer_flag_parser.h"
 
 namespace __asan {
 
@@ -45,14 +46,18 @@ void Flags::SetDefaults() {
 #undef ASAN_FLAG
 }
 
-void Flags::ParseFromString(const char *str) {
-#define ASAN_FLAG(Type, Name, DefaultValue, Description)                     \
-  ParseFlag(str, &Name, #Name, Description);
+void RegisterAsanFlags(FlagParser *parser, Flags *f) {
+#define ASAN_FLAG(Type, Name, DefaultValue, Description) \
+  RegisterFlag(parser, #Name, Description, &f->Name);
 #include "asan_flags.inc"
 #undef ASAN_FLAG
 }
 
 void InitializeFlags(Flags *f) {
+  FlagParser parser;
+  RegisterAsanFlags(&parser, f);
+  RegisterCommonFlags(&parser);
+
   SetCommonFlagsDefaults();
   {
     CommonFlags cf;
@@ -69,20 +74,17 @@ void InitializeFlags(Flags *f) {
 
   // Override from compile definition.
   const char *compile_def = MaybeUseAsanDefaultOptionsCompileDefinition();
-  ParseCommonFlagsFromString(compile_def);
-  f->ParseFromString(compile_def);
+  parser.ParseString(compile_def);
 
   // Override from user-specified string.
   const char *default_options = MaybeCallAsanDefaultOptions();
-  ParseCommonFlagsFromString(default_options);
-  f->ParseFromString(default_options);
+  parser.ParseString(default_options);
   VReport(1, "Using the defaults from __asan_default_options: %s\n",
           MaybeCallAsanDefaultOptions());
 
   // Override from command line.
   if (const char *env = GetEnv("ASAN_OPTIONS")) {
-    ParseCommonFlagsFromString(env);
-    f->ParseFromString(env);
+    parser.ParseString(env);
     VReport(1, "Parsed ASAN_OPTIONS: %s\n", env);
   }
 
@@ -91,14 +93,13 @@ void InitializeFlags(Flags *f) {
   if (!flags()->start_deactivated) {
     char buf[100];
     GetExtraActivationFlags(buf, sizeof(buf));
-    ParseCommonFlagsFromString(buf);
-    f->ParseFromString(buf);
+    parser.ParseString(buf);
     if (buf[0] != '\0')
       VReport(1, "Parsed activation flags: %s\n", buf);
   }
 
   if (common_flags()->help) {
-    PrintFlagDescriptions();
+    parser.PrintFlagDescriptions();
   }
 
   // Flag validation:

Modified: compiler-rt/trunk/lib/asan/asan_flags.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_flags.h?rev=226169&r1=226168&r2=226169&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_flags.h (original)
+++ compiler-rt/trunk/lib/asan/asan_flags.h Thu Jan 15 09:13:43 2015
@@ -16,6 +16,7 @@
 #define ASAN_FLAGS_H
 
 #include "sanitizer_common/sanitizer_internal_defs.h"
+#include "sanitizer_common/sanitizer_flag_parser.h"
 
 // ASan flag values can be defined in four ways:
 // 1) initialized with default values at startup.
@@ -34,13 +35,13 @@ struct Flags {
 #undef ASAN_FLAG
 
   void SetDefaults();
-  void ParseFromString(const char *str);
 };
 
 extern Flags asan_flags_dont_use_directly;
 inline Flags *flags() {
   return &asan_flags_dont_use_directly;
 }
+void RegisterAsanFlags(FlagParser *parser, Flags *f);
 void InitializeFlags(Flags *f);
 
 }  // namespace __asan

Modified: compiler-rt/trunk/lib/asan/tests/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/tests/CMakeLists.txt?rev=226169&r1=226168&r2=226169&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/tests/CMakeLists.txt (original)
+++ compiler-rt/trunk/lib/asan/tests/CMakeLists.txt Thu Jan 15 09:13:43 2015
@@ -30,7 +30,8 @@ set(ASAN_UNITTEST_COMMON_CFLAGS
   -fno-rtti
   -O2
   -Wno-format
-  -Werror=sign-compare)
+  -Werror=sign-compare
+  -Wno-non-virtual-dtor)
 append_list_if(COMPILER_RT_HAS_WVARIADIC_MACROS_FLAG -Wno-variadic-macros ASAN_UNITTEST_COMMON_CFLAGS)
 
 # -gline-tables-only must be enough for ASan, so use it if possible.

Modified: compiler-rt/trunk/lib/dfsan/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/dfsan/CMakeLists.txt?rev=226169&r1=226168&r2=226169&view=diff
==============================================================================
--- compiler-rt/trunk/lib/dfsan/CMakeLists.txt (original)
+++ compiler-rt/trunk/lib/dfsan/CMakeLists.txt Thu Jan 15 09:13:43 2015
@@ -5,7 +5,7 @@ set(DFSAN_RTL_SOURCES
   dfsan.cc
   dfsan_custom.cc
   dfsan_interceptors.cc)
-set(DFSAN_COMMON_CFLAGS ${SANITIZER_COMMON_CFLAGS})
+set(DFSAN_COMMON_CFLAGS ${SANITIZER_COMMON_CFLAGS} -fno-rtti)
 # Prevent clang from generating libc calls.
 append_list_if(COMPILER_RT_HAS_FFREESTANDING_FLAG -ffreestanding DFSAN_COMMON_CFLAGS)
 

Modified: compiler-rt/trunk/lib/dfsan/dfsan.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/dfsan/dfsan.cc?rev=226169&r1=226168&r2=226169&view=diff
==============================================================================
--- compiler-rt/trunk/lib/dfsan/dfsan.cc (original)
+++ compiler-rt/trunk/lib/dfsan/dfsan.cc Thu Jan 15 09:13:43 2015
@@ -22,6 +22,7 @@
 #include "sanitizer_common/sanitizer_atomic.h"
 #include "sanitizer_common/sanitizer_common.h"
 #include "sanitizer_common/sanitizer_flags.h"
+#include "sanitizer_common/sanitizer_flag_parser.h"
 #include "sanitizer_common/sanitizer_libc.h"
 
 #include "dfsan/dfsan.h"
@@ -316,16 +317,18 @@ void Flags::SetDefaults() {
 #undef DFSAN_FLAG
 }
 
-void Flags::ParseFromString(const char *str) {
-#define DFSAN_FLAG(Type, Name, DefaultValue, Description)                     \
-  ParseFlag(str, &Name, #Name, Description);
+void RegisterDfsanFlags(FlagParser *parser, Flags *f) {
+#define DFSAN_FLAG(Type, Name, DefaultValue, Description) \
+  RegisterFlag(parser, #Name, Description, &f->Name);
 #include "dfsan_flags.inc"
 #undef DFSAN_FLAG
 }
 
 static void InitializeFlags(Flags &f, const char *env) {
+  FlagParser parser;
+  RegisterDfsanFlags(&parser, &f);
   f.SetDefaults();
-  f.ParseFromString(env);
+  parser.ParseString(env);
 }
 
 static void dfsan_fini() {

Modified: compiler-rt/trunk/lib/dfsan/dfsan.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/dfsan/dfsan.h?rev=226169&r1=226168&r2=226169&view=diff
==============================================================================
--- compiler-rt/trunk/lib/dfsan/dfsan.h (original)
+++ compiler-rt/trunk/lib/dfsan/dfsan.h Thu Jan 15 09:13:43 2015
@@ -61,7 +61,6 @@ struct Flags {
 #undef DFSAN_FLAG
 
   void SetDefaults();
-  void ParseFromString(const char *str);
 };
 
 extern Flags flags_data;

Modified: compiler-rt/trunk/lib/lsan/lsan_common.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/lsan/lsan_common.cc?rev=226169&r1=226168&r2=226169&view=diff
==============================================================================
--- compiler-rt/trunk/lib/lsan/lsan_common.cc (original)
+++ compiler-rt/trunk/lib/lsan/lsan_common.cc Thu Jan 15 09:13:43 2015
@@ -16,6 +16,7 @@
 
 #include "sanitizer_common/sanitizer_common.h"
 #include "sanitizer_common/sanitizer_flags.h"
+#include "sanitizer_common/sanitizer_flag_parser.h"
 #include "sanitizer_common/sanitizer_placement_new.h"
 #include "sanitizer_common/sanitizer_procmaps.h"
 #include "sanitizer_common/sanitizer_stackdepot.h"
@@ -42,19 +43,20 @@ void Flags::SetDefaults() {
 #undef LSAN_FLAG
 }
 
-void Flags::ParseFromString(const char *str) {
-#define LSAN_FLAG(Type, Name, DefaultValue, Description)                       \
-  ParseFlag(str, &Name, #Name, Description);
+static void RegisterLsanFlags(FlagParser *parser, Flags *f) {
+#define LSAN_FLAG(Type, Name, DefaultValue, Description) \
+  RegisterFlag(parser, #Name, Description, &f->Name);
 #include "lsan_flags.inc"
 #undef LSAN_FLAG
 }
 
 static void InitializeFlags(bool standalone) {
   Flags *f = flags();
-  f->SetDefaults();
+  FlagParser parser;
+  RegisterLsanFlags(&parser, f);
+  RegisterCommonFlags(&parser);
 
-  const char *options = GetEnv("LSAN_OPTIONS");
-  f->ParseFromString(options);
+  f->SetDefaults();
 
   // Set defaults for common flags (only in standalone mode) and parse
   // them from LSAN_OPTIONS.
@@ -67,7 +69,9 @@ static void InitializeFlags(bool standal
     cf.detect_leaks = true;
     OverrideCommonFlags(cf);
   }
-  ParseCommonFlagsFromString(options);
+
+  const char *options = GetEnv("LSAN_OPTIONS");
+  parser.ParseString(options);
 }
 
 #define LOG_POINTERS(...)                           \

Modified: compiler-rt/trunk/lib/lsan/lsan_common.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/lsan/lsan_common.h?rev=226169&r1=226168&r2=226169&view=diff
==============================================================================
--- compiler-rt/trunk/lib/lsan/lsan_common.h (original)
+++ compiler-rt/trunk/lib/lsan/lsan_common.h Thu Jan 15 09:13:43 2015
@@ -43,7 +43,6 @@ struct Flags {
 #undef LSAN_FLAG
 
   void SetDefaults();
-  void ParseFromString(const char *str);
   uptr pointer_alignment() const {
     return use_unaligned ? 1 : sizeof(uptr);
   }

Modified: compiler-rt/trunk/lib/msan/msan.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/msan/msan.cc?rev=226169&r1=226168&r2=226169&view=diff
==============================================================================
--- compiler-rt/trunk/lib/msan/msan.cc (original)
+++ compiler-rt/trunk/lib/msan/msan.cc Thu Jan 15 09:13:43 2015
@@ -19,13 +19,13 @@
 #include "sanitizer_common/sanitizer_atomic.h"
 #include "sanitizer_common/sanitizer_common.h"
 #include "sanitizer_common/sanitizer_flags.h"
+#include "sanitizer_common/sanitizer_flag_parser.h"
 #include "sanitizer_common/sanitizer_libc.h"
 #include "sanitizer_common/sanitizer_procmaps.h"
 #include "sanitizer_common/sanitizer_stacktrace.h"
 #include "sanitizer_common/sanitizer_symbolizer.h"
 #include "sanitizer_common/sanitizer_stackdepot.h"
 
-
 // ACHTUNG! No system header includes in this file.
 
 using namespace __sanitizer;
@@ -102,20 +102,40 @@ void Flags::SetDefaults() {
 #undef MSAN_FLAG
 }
 
-void Flags::ParseFromString(const char *str) {
-  // keep_going is an old name for halt_on_error,
-  // and it has inverse meaning.
-  halt_on_error = !halt_on_error;
-  ParseFlag(str, &halt_on_error, "keep_going", "");
-  halt_on_error = !halt_on_error;
-
-#define MSAN_FLAG(Type, Name, DefaultValue, Description)                     \
-  ParseFlag(str, &Name, #Name, Description);
+// keep_going is an old name for halt_on_error,
+// and it has inverse meaning.
+class FlagHandlerKeepGoing : public FlagHandlerBase {
+  bool *halt_on_error_;
+
+ public:
+  explicit FlagHandlerKeepGoing(bool *halt_on_error)
+      : halt_on_error_(halt_on_error) {}
+  bool Parse(const char *value) {
+    bool tmp;
+    FlagHandler<bool> h(&tmp);
+    if (!h.Parse(value)) return false;
+    *halt_on_error_ = !tmp;
+    return true;
+  }
+};
+
+void RegisterMsanFlags(FlagParser *parser, Flags *f) {
+#define MSAN_FLAG(Type, Name, DefaultValue, Description) \
+  RegisterFlag(parser, #Name, Description, &f->Name);
 #include "msan_flags.inc"
 #undef MSAN_FLAG
+
+  FlagHandlerKeepGoing *fh_keep_going =
+      new (INTERNAL_ALLOC) FlagHandlerKeepGoing(&f->halt_on_error);  // NOLINT
+  parser->RegisterHandler("keep_going", fh_keep_going,
+                          "deprecated, use halt_on_error");
 }
 
 static void InitializeFlags(Flags *f, const char *options) {
+  FlagParser parser;
+  RegisterMsanFlags(&parser, f);
+  RegisterCommonFlags(&parser);
+
   SetCommonFlagsDefaults();
   {
     CommonFlags cf;
@@ -132,13 +152,12 @@ static void InitializeFlags(Flags *f, co
   f->SetDefaults();
 
   // Override from user-specified string.
-  if (__msan_default_options) {
-    f->ParseFromString(__msan_default_options());
-    ParseCommonFlagsFromString(__msan_default_options());
-  }
+  if (__msan_default_options)
+    parser.ParseString(__msan_default_options());
+
+  parser.ParseString(options);
 
-  f->ParseFromString(options);
-  ParseCommonFlagsFromString(options);
+  if (common_flags()->help) parser.PrintFlagDescriptions();
 
   // Check flag values:
   if (f->exit_code < 0 || f->exit_code > 127) {
@@ -328,7 +347,6 @@ void __msan_init() {
 
   const char *msan_options = GetEnv("MSAN_OPTIONS");
   InitializeFlags(&msan_flags, msan_options);
-  if (common_flags()->help) PrintFlagDescriptions();
   __sanitizer_set_report_path(common_flags()->log_path);
 
   InitializeInterceptors();

Modified: compiler-rt/trunk/lib/msan/msan_flags.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/msan/msan_flags.h?rev=226169&r1=226168&r2=226169&view=diff
==============================================================================
--- compiler-rt/trunk/lib/msan/msan_flags.h (original)
+++ compiler-rt/trunk/lib/msan/msan_flags.h Thu Jan 15 09:13:43 2015
@@ -21,7 +21,6 @@ struct Flags {
 #undef MSAN_FLAG
 
   void SetDefaults();
-  void ParseFromString(const char *str);
 };
 
 Flags *flags();

Modified: compiler-rt/trunk/lib/sanitizer_common/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/CMakeLists.txt?rev=226169&r1=226168&r2=226169&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/CMakeLists.txt (original)
+++ compiler-rt/trunk/lib/sanitizer_common/CMakeLists.txt Thu Jan 15 09:13:43 2015
@@ -7,6 +7,7 @@ set(SANITIZER_SOURCES
   sanitizer_deadlock_detector1.cc
   sanitizer_deadlock_detector2.cc
   sanitizer_flags.cc
+  sanitizer_flag_parser.cc
   sanitizer_libc.cc
   sanitizer_libignore.cc
   sanitizer_linux.cc
@@ -63,6 +64,7 @@ set(SANITIZER_HEADERS
   sanitizer_common_syscalls.inc
   sanitizer_deadlock_detector.h
   sanitizer_deadlock_detector_interface.h
+  sanitizer_flag_parser.h
   sanitizer_flags.h
   sanitizer_flags.inc
   sanitizer_internal_defs.h

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_allocator_internal.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_allocator_internal.h?rev=226169&r1=226168&r2=226169&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_allocator_internal.h (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_allocator_internal.h Thu Jan 15 09:13:43 2015
@@ -49,6 +49,15 @@ void *InternalAlloc(uptr size, InternalA
 void InternalFree(void *p, InternalAllocatorCache *cache = 0);
 InternalAllocator *internal_allocator();
 
+enum InternalAllocEnum {
+  INTERNAL_ALLOC
+};
+
 }  // namespace __sanitizer
 
+inline void *operator new(__sanitizer::operator_new_size_type size,
+                          InternalAllocEnum) {
+  return InternalAlloc(size);
+}
+
 #endif  // SANITIZER_ALLOCATOR_INTERNAL_H

Added: compiler-rt/trunk/lib/sanitizer_common/sanitizer_flag_parser.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_flag_parser.cc?rev=226169&view=auto
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_flag_parser.cc (added)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_flag_parser.cc Thu Jan 15 09:13:43 2015
@@ -0,0 +1,117 @@
+//===-- sanitizer_flag_parser.cc ------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer/AddressSanitizer runtime.
+//
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_flag_parser.h"
+
+#include "sanitizer_common.h"
+#include "sanitizer_libc.h"
+#include "sanitizer_flags.h"
+#include "sanitizer_flag_parser.h"
+#include "sanitizer_allocator_internal.h"
+
+namespace __sanitizer {
+
+void FlagParser::PrintFlagDescriptions() {
+  Printf("Available flags for %s:\n", SanitizerToolName);
+  for (int i = 0; i < n_flags_; ++i)
+    Printf("\t%s\n\t\t- %s\n", flags_[i].name, flags_[i].desc);
+}
+
+void FlagParser::fatal_error(const char *err) {
+  Printf("ERROR: %s\n", err);
+  Die();
+}
+
+bool FlagParser::is_space(char c) {
+  return c == ' ' || c == ',' || c == ':' || c == '\n' || c == '\t' ||
+         c == '\r';
+}
+
+void FlagParser::skip_whitespace() {
+  while (is_space(buf_[pos_])) ++pos_;
+}
+
+void FlagParser::parse_flag() {
+  uptr name_start = pos_;
+  while (buf_[pos_] != 0 && buf_[pos_] != '=' && !is_space(buf_[pos_])) ++pos_;
+  if (buf_[pos_] != '=') fatal_error("expected '='");
+  const char *name = internal_strndup(buf_ + name_start, pos_ - name_start);
+
+  uptr value_start = ++pos_;
+  const char *value;
+  if (buf_[pos_] == '\'' || buf_[pos_] == '"') {
+    char quote = buf_[pos_++];
+    while (buf_[pos_] != 0 && buf_[pos_] != quote) ++pos_;
+    if (buf_[pos_] == 0) fatal_error("unterminated string");
+    value = internal_strndup(buf_ + value_start + 1, pos_ - value_start - 1);
+    ++pos_; // consume the closing quote
+  } else {
+    while (buf_[pos_] != 0 && !is_space(buf_[pos_])) ++pos_;
+    if (buf_[pos_] != 0 && !is_space(buf_[pos_]))
+      fatal_error("expected separator or eol");
+    value = internal_strndup(buf_ + value_start, pos_ - value_start);
+  }
+
+  bool res = run_handler(name, value);
+  if (!res) {
+    Printf("Flag parsing failed.");
+    Die();
+  }
+  InternalFree((void *)name);
+  InternalFree((void *)value);
+}
+
+void FlagParser::ParseString(const char *s) {
+  if (!s) return;
+  buf_ = s;
+  pos_ = 0;
+  while (true) {
+    skip_whitespace();
+    if (buf_[pos_] == 0) break;
+    parse_flag();
+  }
+
+  // Do a sanity check for certain flags.
+  if (common_flags_dont_use.malloc_context_size < 1)
+    common_flags_dont_use.malloc_context_size = 1;
+}
+
+bool FlagParser::run_handler(const char *name, const char *value) {
+  for (int i = 0; i < n_flags_; ++i) {
+    if (internal_strcmp(name, flags_[i].name) == 0)
+      return flags_[i].handler->Parse(value);
+  }
+  Printf("ERROR: Unknown flag: '%s'\n", name);
+  return false;
+}
+
+void FlagParser::RegisterHandler(const char *name, FlagHandlerBase *handler,
+                                 const char *desc) {
+  CHECK(n_flags_ < kMaxFlags);
+  flags_[n_flags_].name = name;
+  flags_[n_flags_].desc = desc;
+  flags_[n_flags_].handler = handler;
+  ++n_flags_;
+}
+
+FlagParser::FlagParser() : n_flags_(0), buf_(nullptr), pos_(0) {
+  flags_ = (Flag *)InternalAlloc(sizeof(Flag) * kMaxFlags);
+}
+
+FlagParser::~FlagParser() {
+  for (int i = 0; i < n_flags_; ++i)
+    InternalFree(flags_[i].handler);
+  InternalFree(flags_);
+}
+
+}  // namespace __sanitizer

Propchange: compiler-rt/trunk/lib/sanitizer_common/sanitizer_flag_parser.cc
------------------------------------------------------------------------------
    svn:eol-style = LF

Added: compiler-rt/trunk/lib/sanitizer_common/sanitizer_flag_parser.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_flag_parser.h?rev=226169&view=auto
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_flag_parser.h (added)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_flag_parser.h Thu Jan 15 09:13:43 2015
@@ -0,0 +1,117 @@
+//===-- sanitizer_flag_parser.h ---------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer/AddressSanitizer runtime.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SANITIZER_FLAG_REGISTRY_H
+#define SANITIZER_FLAG_REGISTRY_H
+
+#include "sanitizer_internal_defs.h"
+#include "sanitizer_libc.h"
+#include "sanitizer_common.h"
+#include "sanitizer_allocator_internal.h"
+
+namespace __sanitizer {
+
+class FlagHandlerBase {
+ public:
+  virtual bool Parse(const char *value) { return false; }
+};
+
+template <typename T>
+class FlagHandler : public FlagHandlerBase {
+  T *t_;
+
+ public:
+  explicit FlagHandler(T *t) : t_(t) {}
+  bool Parse(const char *value);
+};
+
+template <>
+inline bool FlagHandler<bool>::Parse(const char *value) {
+  if (internal_strcmp(value, "0") == 0 ||
+      internal_strcmp(value, "no") == 0 ||
+      internal_strcmp(value, "false") == 0) {
+    *t_ = false;
+    return true;
+  }
+  if (internal_strcmp(value, "1") == 0 ||
+      internal_strcmp(value, "yes") == 0 ||
+      internal_strcmp(value, "true") == 0) {
+    *t_ = true;
+    return true;
+  }
+  Printf("ERROR: Invalid value for bool option: '%s'\n", value);
+  return false;
+}
+
+template <>
+inline bool FlagHandler<const char *>::Parse(const char *value) {
+  *t_ = internal_strdup(value);
+  return true;
+}
+
+template <>
+inline bool FlagHandler<int>::Parse(const char *value) {
+  char *value_end;
+  *t_ = internal_simple_strtoll(value, &value_end, 10);
+  bool ok = *value_end == 0;
+  if (!ok) Printf("ERROR: Invalid value for int option: '%s'\n", value);
+  return ok;
+}
+
+template <>
+inline bool FlagHandler<uptr>::Parse(const char *value) {
+  char *value_end;
+  *t_ = internal_simple_strtoll(value, &value_end, 10);
+  bool ok = *value_end == 0;
+  if (!ok) Printf("ERROR: Invalid value for uptr option: '%s'\n", value);
+  return ok;
+}
+
+class FlagParser {
+  static const int kMaxFlags = 200;
+  struct Flag {
+    const char *name;
+    const char *desc;
+    FlagHandlerBase *handler;
+  } *flags_;
+  int n_flags_;
+
+  const char *buf_;
+  uptr pos_;
+
+ public:
+  FlagParser();
+  ~FlagParser();
+  void RegisterHandler(const char *name, FlagHandlerBase *handler,
+                       const char *desc);
+  void ParseString(const char *s);
+  void PrintFlagDescriptions();
+
+ private:
+  void fatal_error(const char *err);
+  bool is_space(char c);
+  void skip_whitespace();
+  void parse_flag();
+  bool run_handler(const char *name, const char *value);
+};
+
+template <typename T>
+static void RegisterFlag(FlagParser *parser, const char *name, const char *desc,
+                         T *var) {
+  FlagHandler<T> *fh = new (INTERNAL_ALLOC) FlagHandler<T>(var);  // NOLINT
+  parser->RegisterHandler(name, fh, desc);
+}
+
+}  // namespace __sanitizer
+
+#endif  // SANITIZER_FLAG_REGISTRY_H

Propchange: compiler-rt/trunk/lib/sanitizer_common/sanitizer_flag_parser.h
------------------------------------------------------------------------------
    svn:eol-style = LF

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_flags.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_flags.cc?rev=226169&r1=226168&r2=226169&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_flags.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_flags.cc Thu Jan 15 09:13:43 2015
@@ -16,6 +16,7 @@
 #include "sanitizer_common.h"
 #include "sanitizer_libc.h"
 #include "sanitizer_list.h"
+#include "sanitizer_flag_parser.h"
 
 namespace __sanitizer {
 
@@ -40,150 +41,15 @@ void CommonFlags::SetDefaults() {
 #undef COMMON_FLAG
 }
 
-void CommonFlags::ParseFromString(const char *str) {
-#define COMMON_FLAG(Type, Name, DefaultValue, Description)                     \
-  ParseFlag(str, &Name, #Name, Description);
-#include "sanitizer_flags.inc"
-#undef COMMON_FLAG
-  // Do a sanity check for certain flags.
-  if (malloc_context_size < 1)
-    malloc_context_size = 1;
-}
-
 void CommonFlags::CopyFrom(const CommonFlags &other) {
   internal_memcpy(this, &other, sizeof(*this));
 }
 
-static bool GetFlagValue(const char *env, const char *name,
-                         const char **value, int *value_length) {
-  if (env == 0)
-    return false;
-  const char *pos = 0;
-  for (;;) {
-    pos = internal_strstr(env, name);
-    if (pos == 0)
-      return false;
-    const char *name_end = pos + internal_strlen(name);
-    if ((pos != env &&
-         ((pos[-1] >= 'a' && pos[-1] <= 'z') || pos[-1] == '_')) ||
-        *name_end != '=') {
-      // Seems to be middle of another flag name or value.
-      env = pos + 1;
-      continue;
-    }
-    pos = name_end;
-    break;
-  }
-  const char *end;
-  if (pos[0] != '=') {
-    end = pos;
-  } else {
-    pos += 1;
-    if (pos[0] == '"') {
-      pos += 1;
-      end = internal_strchr(pos, '"');
-    } else if (pos[0] == '\'') {
-      pos += 1;
-      end = internal_strchr(pos, '\'');
-    } else {
-      // Read until the next space or colon.
-      end = pos + internal_strcspn(pos, " :\r\n\t");
-    }
-    if (end == 0)
-      end = pos + internal_strlen(pos);
-  }
-  *value = pos;
-  *value_length = end - pos;
-  return true;
-}
-
-static bool StartsWith(const char *flag, int flag_length, const char *value) {
-  if (!flag || !value)
-    return false;
-  int value_length = internal_strlen(value);
-  return (flag_length >= value_length) &&
-         (0 == internal_strncmp(flag, value, value_length));
-}
-
-static LowLevelAllocator allocator_for_flags;
-
-// The linear scan is suboptimal, but the number of flags is relatively small.
-bool FlagInDescriptionList(const char *name) {
-  IntrusiveList<FlagDescription>::Iterator it(&flag_descriptions);
-  while (it.hasNext()) {
-    if (!internal_strcmp(it.next()->name, name)) return true;
-  }
-  return false;
-}
-
-void AddFlagDescription(const char *name, const char *description) {
-  if (FlagInDescriptionList(name)) return;
-  FlagDescription *new_description = new(allocator_for_flags) FlagDescription;
-  new_description->name = name;
-  new_description->description = description;
-  flag_descriptions.push_back(new_description);
-}
-
-// TODO(glider): put the descriptions inside CommonFlags.
-void PrintFlagDescriptions() {
-  IntrusiveList<FlagDescription>::Iterator it(&flag_descriptions);
-  Printf("Available flags for %s:\n", SanitizerToolName);
-  while (it.hasNext()) {
-    FlagDescription *descr = it.next();
-    Printf("\t%s\n\t\t- %s\n", descr->name, descr->description);
-  }
-}
-
-void ParseFlag(const char *env, bool *flag,
-               const char *name, const char *descr) {
-  const char *value;
-  int value_length;
-  AddFlagDescription(name, descr);
-  if (!GetFlagValue(env, name, &value, &value_length))
-    return;
-  if (StartsWith(value, value_length, "0") ||
-      StartsWith(value, value_length, "no") ||
-      StartsWith(value, value_length, "false"))
-    *flag = false;
-  if (StartsWith(value, value_length, "1") ||
-      StartsWith(value, value_length, "yes") ||
-      StartsWith(value, value_length, "true"))
-    *flag = true;
-}
-
-void ParseFlag(const char *env, int *flag,
-               const char *name, const char *descr) {
-  const char *value;
-  int value_length;
-  AddFlagDescription(name, descr);
-  if (!GetFlagValue(env, name, &value, &value_length))
-    return;
-  *flag = static_cast<int>(internal_atoll(value));
-}
-
-void ParseFlag(const char *env, uptr *flag,
-               const char *name, const char *descr) {
-  const char *value;
-  int value_length;
-  AddFlagDescription(name, descr);
-  if (!GetFlagValue(env, name, &value, &value_length))
-    return;
-  *flag = static_cast<uptr>(internal_atoll(value));
-}
-
-void ParseFlag(const char *env, const char **flag,
-               const char *name, const char *descr) {
-  const char *value;
-  int value_length;
-  AddFlagDescription(name, descr);
-  if (!GetFlagValue(env, name, &value, &value_length))
-    return;
-  // Copy the flag value. Don't use locks here, as flags are parsed at
-  // tool startup.
-  char *value_copy = (char*)(allocator_for_flags.Allocate(value_length + 1));
-  internal_memcpy(value_copy, value, value_length);
-  value_copy[value_length] = '\0';
-  *flag = value_copy;
+void RegisterCommonFlags(FlagParser *parser, CommonFlags *cf) {
+#define COMMON_FLAG(Type, Name, DefaultValue, Description) \
+  RegisterFlag(parser, #Name, Description, &cf->Name);
+#include "sanitizer_flags.inc"
+#undef COMMON_FLAG
 }
 
 }  // namespace __sanitizer

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_flags.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_flags.h?rev=226169&r1=226168&r2=226169&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_flags.h (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_flags.h Thu Jan 15 09:13:43 2015
@@ -18,22 +18,12 @@
 
 namespace __sanitizer {
 
-void ParseFlag(const char *env, bool *flag,
-    const char *name, const char *descr);
-void ParseFlag(const char *env, int *flag,
-    const char *name, const char *descr);
-void ParseFlag(const char *env, uptr *flag,
-    const char *name, const char *descr);
-void ParseFlag(const char *env, const char **flag,
-    const char *name, const char *descr);
-
 struct CommonFlags {
 #define COMMON_FLAG(Type, Name, DefaultValue, Description) Type Name;
 #include "sanitizer_flags.inc"
 #undef COMMON_FLAG
 
   void SetDefaults();
-  void ParseFromString(const char *str);
   void CopyFrom(const CommonFlags &other);
 };
 
@@ -47,10 +37,6 @@ inline void SetCommonFlagsDefaults() {
   common_flags_dont_use.SetDefaults();
 }
 
-inline void ParseCommonFlagsFromString(const char *str) {
-  common_flags_dont_use.ParseFromString(str);
-}
-
 // This function can only be used to setup tool-specific overrides for
 // CommonFlags defaults. Generally, it should only be used right after
 // SetCommonFlagsDefaults(), but before ParseCommonFlagsFromString(), and
@@ -60,8 +46,9 @@ inline void OverrideCommonFlags(const Co
   common_flags_dont_use.CopyFrom(cf);
 }
 
-void PrintFlagDescriptions();
-
+class FlagParser;
+void RegisterCommonFlags(FlagParser *parser,
+                         CommonFlags *cf = &common_flags_dont_use);
 }  // namespace __sanitizer
 
 #endif  // SANITIZER_FLAGS_H

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_libc.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_libc.cc?rev=226169&r1=226168&r2=226169&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_libc.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_libc.cc Thu Jan 15 09:13:43 2015
@@ -101,6 +101,14 @@ char* internal_strdup(const char *s) {
   return s2;
 }
 
+char* internal_strndup(const char *s, uptr n) {
+  uptr len = internal_strnlen(s, n);
+  char *s2 = (char*)InternalAlloc(len + 1);
+  internal_memcpy(s2, s, len);
+  s2[len] = 0;
+  return s2;
+}
+
 int internal_strcmp(const char *s1, const char *s2) {
   while (true) {
     unsigned c1 = *s1;

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_libc.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_libc.h?rev=226169&r1=226168&r2=226169&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_libc.h (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_libc.h Thu Jan 15 09:13:43 2015
@@ -38,6 +38,7 @@ char *internal_strchrnul(const char *s,
 int internal_strcmp(const char *s1, const char *s2);
 uptr internal_strcspn(const char *s, const char *reject);
 char *internal_strdup(const char *s);
+char *internal_strndup(const char *s, uptr n);
 uptr internal_strlen(const char *s);
 char *internal_strncat(char *dst, const char *src, uptr n);
 int internal_strncmp(const char *s1, const char *s2, uptr n);

Modified: compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_flags_test.cc
URL: 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
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_flags_test.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_flags_test.cc Thu Jan 15 09:13:43 2015
@@ -12,7 +12,9 @@
 //===----------------------------------------------------------------------===//
 #include "sanitizer_common/sanitizer_common.h"
 #include "sanitizer_common/sanitizer_flags.h"
+#include "sanitizer_common/sanitizer_flag_parser.h"
 #include "sanitizer_common/sanitizer_libc.h"
+#include "sanitizer_common/sanitizer_allocator_internal.h"
 #include "gtest/gtest.h"
 
 #include <string.h>
@@ -20,58 +22,74 @@
 namespace __sanitizer {
 
 static const char kFlagName[] = "flag_name";
+static const char kFlagDesc[] = "flag description";
 
 template <typename T>
 static void TestFlag(T start_value, const char *env, T final_value) {
   T flag = start_value;
-  ParseFlag(env, &flag, kFlagName, "flag description");
+
+  FlagParser parser;
+  RegisterFlag(&parser, kFlagName, kFlagDesc, &flag);
+
+  parser.ParseString(env);
+
   EXPECT_EQ(final_value, flag);
 }
 
-static void TestStrFlag(const char *start_value, const char *env,
-                        const char *final_value) {
+template <>
+void TestFlag(const char *start_value, const char *env,
+                     const char *final_value) {
   const char *flag = start_value;
-  ParseFlag(env, &flag, kFlagName, "flag description");
+
+  FlagParser parser;
+  RegisterFlag(&parser, kFlagName, kFlagDesc, &flag);
+
+  parser.ParseString(env);
+
   EXPECT_EQ(0, internal_strcmp(final_value, flag));
 }
 
 TEST(SanitizerCommon, BooleanFlags) {
-  TestFlag(true, "--flag_name", true);
-  TestFlag(false, "flag_name", false);
-  TestFlag(false, "--flag_name=1", true);
-  TestFlag(true, "asdas flag_name=0 asdas", false);
-  TestFlag(true, "    --flag_name=0   ", false);
+  TestFlag(false, "flag_name=1", true);
   TestFlag(false, "flag_name=yes", true);
   TestFlag(false, "flag_name=true", true);
+  TestFlag(true, "flag_name=0", false);
   TestFlag(true, "flag_name=no", false);
   TestFlag(true, "flag_name=false", false);
 }
 
 TEST(SanitizerCommon, IntFlags) {
   TestFlag(-11, 0, -11);
-  TestFlag(-11, "flag_name", -11);
-  TestFlag(-11, "--flag_name=", 0);
-  TestFlag(-11, "--flag_name=42", 42);
-  TestFlag(-11, "--flag_name=-42", -42);
+  TestFlag(-11, "flag_name=0", 0);
+  TestFlag(-11, "flag_name=42", 42);
+  TestFlag(-11, "flag_name=-42", -42);
+  EXPECT_DEATH(TestFlag(-11, "flag_name", 0), "expected '='");
+  EXPECT_DEATH(TestFlag(-11, "--flag_name=42", 0),
+               "Unknown flag: '--flag_name'");
 }
 
 TEST(SanitizerCommon, StrFlags) {
-  TestStrFlag("zzz", 0, "zzz");
-  TestStrFlag("zzz", "flag_name", "zzz");
-  TestStrFlag("zzz", "--flag_name=", "");
-  TestStrFlag("", "--flag_name=abc", "abc");
-  TestStrFlag("", "--flag_name='abc zxc'", "abc zxc");
-  TestStrFlag("", "--flag_name='abc zxcc'", "abc zxcc");
-  TestStrFlag("", "--flag_name=\"abc qwe\" asd", "abc qwe");
-  TestStrFlag("", "other_flag_name=zzz", "");
+  TestFlag("zzz", 0, "zzz");
+  TestFlag("zzz", "flag_name=", "");
+  TestFlag("zzz", "flag_name=abc", "abc");
+  TestFlag("", "flag_name=abc", "abc");
+  TestFlag("", "flag_name='abc zxc'", "abc zxc");
+  // TestStrFlag("", "flag_name=\"abc qwe\" asd", "abc qwe");
 }
 
 static void TestTwoFlags(const char *env, bool expected_flag1,
-                         const char *expected_flag2) {
+                         const char *expected_flag2,
+                         const char *name1 = "flag1",
+                         const char *name2 = "flag2") {
   bool flag1 = !expected_flag1;
   const char *flag2 = "";
-  ParseFlag(env, &flag1, "flag1", "flag1 description");
-  ParseFlag(env, &flag2, "flag2", "flag2 description");
+
+  FlagParser parser;
+  RegisterFlag(&parser, name1, kFlagDesc, &flag1);
+  RegisterFlag(&parser, name2, kFlagDesc, &flag2);
+
+  parser.ParseString(env);
+
   EXPECT_EQ(expected_flag1, flag1);
   EXPECT_EQ(0, internal_strcmp(flag2, expected_flag2));
 }
@@ -86,8 +104,20 @@ TEST(SanitizerCommon, MultipleFlags) {
   TestTwoFlags("flag2=qxx\tflag1=yes", true, "qxx");
 }
 
+TEST(SanitizerCommon, CommonSuffixFlags) {
+  TestTwoFlags("flag=1 other_flag='zzz'", true, "zzz", "flag", "other_flag");
+  TestTwoFlags("other_flag='zzz' flag=1", true, "zzz", "flag", "other_flag");
+  TestTwoFlags("other_flag=' flag=0 ' flag=1", true, " flag=0 ", "flag",
+               "other_flag");
+  TestTwoFlags("flag=1 other_flag=' flag=0 '", true, " flag=0 ", "flag",
+               "other_flag");
+}
+
 TEST(SanitizerCommon, CommonFlags) {
   CommonFlags cf;
+  FlagParser parser;
+  RegisterCommonFlags(&parser, &cf);
+
   cf.SetDefaults();
   EXPECT_TRUE(cf.symbolize);
   EXPECT_STREQ(".", cf.coverage_dir);
@@ -97,7 +127,7 @@ TEST(SanitizerCommon, CommonFlags) {
   cf.coverage_direct = true;
   cf.log_path = "path/one";
 
-  cf.ParseFromString("symbolize=1:coverage_direct=false log_path='path/two'");
+  parser.ParseString("symbolize=1:coverage_direct=false log_path='path/two'");
   EXPECT_TRUE(cf.symbolize);
   EXPECT_TRUE(cf.coverage);
   EXPECT_FALSE(cf.coverage_direct);

Modified: compiler-rt/trunk/lib/tsan/dd/dd_rtl.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/dd/dd_rtl.cc?rev=226169&r1=226168&r2=226169&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/dd/dd_rtl.cc (original)
+++ compiler-rt/trunk/lib/tsan/dd/dd_rtl.cc Thu Jan 15 09:13:43 2015
@@ -11,6 +11,7 @@
 #include "sanitizer_common/sanitizer_common.h"
 #include "sanitizer_common/sanitizer_placement_new.h"
 #include "sanitizer_common/sanitizer_flags.h"
+#include "sanitizer_common/sanitizer_flag_parser.h"
 #include "sanitizer_common/sanitizer_stacktrace.h"
 #include "sanitizer_common/sanitizer_stackdepot.h"
 
@@ -80,8 +81,10 @@ void InitializeFlags(Flags *f, const cha
   }
 
   // Override from command line.
-  ParseFlag(env, &f->second_deadlock_stack, "second_deadlock_stack", "");
-  ParseCommonFlagsFromString(env);
+  FlagParser parser;
+  RegisterFlag(&parser, "second_deadlock_stack", "", &f->second_deadlock_stack);
+  RegisterCommonFlags(&parser);
+  parser.ParseString(env);
 }
 
 void Initialize() {

Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_flags.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_flags.cc?rev=226169&r1=226168&r2=226169&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_flags.cc (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_flags.cc Thu Jan 15 09:13:43 2015
@@ -12,6 +12,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "sanitizer_common/sanitizer_flags.h"
+#include "sanitizer_common/sanitizer_flag_parser.h"
 #include "sanitizer_common/sanitizer_libc.h"
 #include "tsan_flags.h"
 #include "tsan_rtl.h"
@@ -41,16 +42,18 @@ void Flags::SetDefaults() {
   second_deadlock_stack = false;
 }
 
-void Flags::ParseFromString(const char *str) {
-#define TSAN_FLAG(Type, Name, DefaultValue, Description)                     \
-  ParseFlag(str, &Name, #Name, Description);
+void RegisterTsanFlags(FlagParser *parser, Flags *f) {
+#define TSAN_FLAG(Type, Name, DefaultValue, Description) \
+  RegisterFlag(parser, #Name, Description, &f->Name);
 #include "tsan_flags.inc"
 #undef TSAN_FLAG
-  // DDFlags
-  ParseFlag(str, &second_deadlock_stack, "second_deadlock_stack", "");
 }
 
 void InitializeFlags(Flags *f, const char *env) {
+  FlagParser parser;
+  RegisterTsanFlags(&parser, f);
+  RegisterCommonFlags(&parser);
+
   f->SetDefaults();
 
   SetCommonFlagsDefaults();
@@ -66,11 +69,9 @@ void InitializeFlags(Flags *f, const cha
   }
 
   // Let a frontend override.
-  f->ParseFromString(__tsan_default_options());
-  ParseCommonFlagsFromString(__tsan_default_options());
+  parser.ParseString(__tsan_default_options());
   // Override from command line.
-  f->ParseFromString(env);
-  ParseCommonFlagsFromString(env);
+  parser.ParseString(env);
 
   // Sanity check.
   if (!f->report_bugs) {
@@ -80,7 +81,7 @@ void InitializeFlags(Flags *f, const cha
   }
 
   if (common_flags()->help)
-    PrintFlagDescriptions();
+    parser.PrintFlagDescriptions();
 
   if (f->history_size < 0 || f->history_size > 7) {
     Printf("ThreadSanitizer: incorrect value for history_size"

Modified: compiler-rt/trunk/lib/ubsan/ubsan_flags.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/ubsan/ubsan_flags.cc?rev=226169&r1=226168&r2=226169&view=diff
==============================================================================
--- compiler-rt/trunk/lib/ubsan/ubsan_flags.cc (original)
+++ compiler-rt/trunk/lib/ubsan/ubsan_flags.cc Thu Jan 15 09:13:43 2015
@@ -14,6 +14,7 @@
 #include "ubsan_flags.h"
 #include "sanitizer_common/sanitizer_common.h"
 #include "sanitizer_common/sanitizer_flags.h"
+#include "sanitizer_common/sanitizer_flag_parser.h"
 
 namespace __ubsan {
 
@@ -21,18 +22,6 @@ static const char *MaybeCallUbsanDefault
   return (&__ubsan_default_options) ? __ubsan_default_options() : "";
 }
 
-void InitializeCommonFlags() {
-  SetCommonFlagsDefaults();
-  CommonFlags cf;
-  cf.CopyFrom(*common_flags());
-  cf.print_summary = false;
-  OverrideCommonFlags(cf);
-  // Override from user-specified string.
-  ParseCommonFlagsFromString(MaybeCallUbsanDefaultOptions());
-  // Override from environment variable.
-  ParseCommonFlagsFromString(GetEnv("UBSAN_OPTIONS"));
-}
-
 Flags ubsan_flags;
 
 void Flags::SetDefaults() {
@@ -41,20 +30,42 @@ void Flags::SetDefaults() {
 #undef UBSAN_FLAG
 }
 
-void Flags::ParseFromString(const char *str) {
-#define UBSAN_FLAG(Type, Name, DefaultValue, Description)                      \
-  ParseFlag(str, &Name, #Name, Description);
+void RegisterUbsanFlags(FlagParser *parser, Flags *f) {
+#define UBSAN_FLAG(Type, Name, DefaultValue, Description) \
+  RegisterFlag(parser, #Name, Description, &f->Name);
 #include "ubsan_flags.inc"
 #undef UBSAN_FLAG
 }
 
-void InitializeFlags() {
+void InitializeFlags(bool standalone) {
   Flags *f = flags();
+  FlagParser parser;
+  RegisterUbsanFlags(&parser, f);
+
+  if (standalone) {
+    RegisterCommonFlags(&parser);
+
+    SetCommonFlagsDefaults();
+    CommonFlags cf;
+    cf.CopyFrom(*common_flags());
+    cf.print_summary = false;
+    OverrideCommonFlags(cf);
+  } else {
+    // Ignore common flags if not standalone.
+    // This is inconsistent with LSan, which allows common flags in LSAN_FLAGS.
+    // This is caused by undefined initialization order between ASan and UBsan,
+    // which makes it impossible to make sure that common flags from ASAN_OPTIONS
+    // have not been used (in __asan_init) before they are overwritten with flags
+    // from UBSAN_OPTIONS.
+    CommonFlags cf_ignored;
+    RegisterCommonFlags(&parser, &cf_ignored);
+  }
+
   f->SetDefaults();
   // Override from user-specified string.
-  f->ParseFromString(MaybeCallUbsanDefaultOptions());
+  parser.ParseString(MaybeCallUbsanDefaultOptions());
   // Override from environment variable.
-  f->ParseFromString(GetEnv("UBSAN_OPTIONS"));
+  parser.ParseString(GetEnv("UBSAN_OPTIONS"));
 }
 
 }  // namespace __ubsan

Modified: compiler-rt/trunk/lib/ubsan/ubsan_flags.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/ubsan/ubsan_flags.h?rev=226169&r1=226168&r2=226169&view=diff
==============================================================================
--- compiler-rt/trunk/lib/ubsan/ubsan_flags.h (original)
+++ compiler-rt/trunk/lib/ubsan/ubsan_flags.h Thu Jan 15 09:13:43 2015
@@ -23,14 +23,12 @@ struct Flags {
 #undef UBSAN_FLAG
 
   void SetDefaults();
-  void ParseFromString(const char *str);
 };
 
 extern Flags ubsan_flags;
 inline Flags *flags() { return &ubsan_flags; }
 
-void InitializeCommonFlags();
-void InitializeFlags();
+void InitializeFlags(bool standalone);
 
 }  // namespace __ubsan
 

Modified: compiler-rt/trunk/lib/ubsan/ubsan_init.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/ubsan/ubsan_init.cc?rev=226169&r1=226168&r2=226169&view=diff
==============================================================================
--- compiler-rt/trunk/lib/ubsan/ubsan_init.cc (original)
+++ compiler-rt/trunk/lib/ubsan/ubsan_init.cc Thu Jan 15 09:13:43 2015
@@ -31,6 +31,7 @@ void __ubsan::InitIfNecessary() {
 #endif
   if (LIKELY(ubsan_inited))
    return;
+  bool standalone = false;
   if (0 == internal_strcmp(SanitizerToolName, "SanitizerTool")) {
     // WARNING: If this condition holds, then either UBSan runs in a standalone
     // mode, or initializer for another sanitizer hasn't run yet. In a latter
@@ -38,10 +39,10 @@ void __ubsan::InitIfNecessary() {
     // common flags. It means, that we are not allowed to *use* common flags
     // in this function.
     SanitizerToolName = "UndefinedBehaviorSanitizer";
-    InitializeCommonFlags();
+    standalone = true;
   }
   // Initialize UBSan-specific flags.
-  InitializeFlags();
+  InitializeFlags(standalone);
   SuppressionContext::InitIfNecessary();
   InitializeCoverage(common_flags()->coverage, common_flags()->coverage_dir);
   ubsan_inited = true;

Added: compiler-rt/trunk/test/asan/TestCases/asan_options-help.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/asan/TestCases/asan_options-help.cc?rev=226169&view=auto
==============================================================================
--- compiler-rt/trunk/test/asan/TestCases/asan_options-help.cc (added)
+++ compiler-rt/trunk/test/asan/TestCases/asan_options-help.cc Thu Jan 15 09:13:43 2015
@@ -0,0 +1,9 @@
+// RUN: %clangxx_asan -O0 %s -o %t
+// RUN: ASAN_OPTIONS=help=1 %run %t 2>&1 | FileCheck %s
+
+int main() {
+}
+
+// CHECK: Available flags for AddressSanitizer:
+// CHECK-DAG: handle_segv
+// CHECK-DAG: check_initialization_order

Propchange: compiler-rt/trunk/test/asan/TestCases/asan_options-help.cc
------------------------------------------------------------------------------
    svn:eol-style = LF

Added: compiler-rt/trunk/test/asan/TestCases/asan_options-invalid.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/asan/TestCases/asan_options-invalid.cc?rev=226169&view=auto
==============================================================================
--- compiler-rt/trunk/test/asan/TestCases/asan_options-invalid.cc (added)
+++ compiler-rt/trunk/test/asan/TestCases/asan_options-invalid.cc Thu Jan 15 09:13:43 2015
@@ -0,0 +1,7 @@
+// RUN: %clangxx_asan -O0 %s -o %t
+// RUN: ASAN_OPTIONS=invalid_option_name=10 not %run %t 2>&1 | FileCheck %s
+
+int main() {
+}
+
+// CHECK: Unknown flag{{.*}}invalid_option_name

Propchange: compiler-rt/trunk/test/asan/TestCases/asan_options-invalid.cc
------------------------------------------------------------------------------
    svn:eol-style = LF

Modified: compiler-rt/trunk/test/asan/TestCases/default_options.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/asan/TestCases/default_options.cc?rev=226169&r1=226168&r2=226169&view=diff
==============================================================================
--- compiler-rt/trunk/test/asan/TestCases/default_options.cc (original)
+++ compiler-rt/trunk/test/asan/TestCases/default_options.cc Thu Jan 15 09:13:43 2015
@@ -4,12 +4,12 @@
 // __asan_default_options() are not supported on Windows.
 // XFAIL: win32
 
-const char *kAsanDefaultOptions="verbosity=1 foo=bar";
+const char *kAsanDefaultOptions="verbosity=1 strip_path_prefix=bar";
 
 extern "C"
 __attribute__((no_sanitize_address))
 const char *__asan_default_options() {
-  // CHECK: Using the defaults from __asan_default_options: {{.*}} foo=bar
+  // CHECK: Using the defaults from __asan_default_options: {{.*}} strip_path_prefix=bar
   return kAsanDefaultOptions;
 }
 

Modified: compiler-rt/trunk/test/lsan/TestCases/ignore_object.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/lsan/TestCases/ignore_object.cc?rev=226169&r1=226168&r2=226169&view=diff
==============================================================================
--- compiler-rt/trunk/test/lsan/TestCases/ignore_object.cc (original)
+++ compiler-rt/trunk/test/lsan/TestCases/ignore_object.cc Thu Jan 15 09:13:43 2015
@@ -1,5 +1,5 @@
 // Test for __lsan_ignore_object().
-// RUN: LSAN_BASE="report_objects=1:use_registers=0:use_stacks=0:use_globals=0:use_tls=0:verbosity=2"
+// RUN: LSAN_BASE="report_objects=1:use_registers=0:use_stacks=0:use_globals=0:use_tls=0"
 // RUN: %clangxx_lsan %s -o %t
 // RUN: LSAN_OPTIONS=$LSAN_BASE not %run %t 2>&1 | FileCheck %s
 
@@ -20,5 +20,4 @@ int main() {
   return 0;
 }
 // CHECK: Test alloc: [[ADDR:.*]].
-// CHECK: ignoring heap object at [[ADDR]]
 // CHECK: SUMMARY: {{(Leak|Address)}}Sanitizer: 1337 byte(s) leaked in 1 allocation(s)

Modified: compiler-rt/trunk/test/lsan/TestCases/ignore_object_errors.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/lsan/TestCases/ignore_object_errors.cc?rev=226169&r1=226168&r2=226169&view=diff
==============================================================================
--- compiler-rt/trunk/test/lsan/TestCases/ignore_object_errors.cc (original)
+++ compiler-rt/trunk/test/lsan/TestCases/ignore_object_errors.cc Thu Jan 15 09:13:43 2015
@@ -1,5 +1,4 @@
 // Test for incorrect use of __lsan_ignore_object().
-// RUN: LSAN_BASE="verbosity=2"
 // RUN: %clangxx_lsan %s -o %t
 // RUN: LSAN_OPTIONS=$LSAN_BASE %run %t 2>&1 | FileCheck %s
 
@@ -18,5 +17,4 @@ int main() {
   return 0;
 }
 // CHECK: Test alloc: [[ADDR:.*]].
-// CHECK: heap object at [[ADDR]] is already being ignored
-// CHECK: no heap object found at [[ADDR]]
+// CHECK-NOT: SUMMARY: {{.*}} leaked

Modified: compiler-rt/trunk/test/ubsan/TestCases/TypeCheck/vptr.cpp
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/ubsan/TestCases/TypeCheck/vptr.cpp?rev=226169&r1=226168&r2=226169&view=diff
==============================================================================
--- compiler-rt/trunk/test/ubsan/TestCases/TypeCheck/vptr.cpp (original)
+++ compiler-rt/trunk/test/ubsan/TestCases/TypeCheck/vptr.cpp Thu Jan 15 09:13:43 2015
@@ -12,16 +12,16 @@
 // RUN: %run %t m0 2>&1 | FileCheck %s --check-prefix=CHECK-NULL-MEMBER --strict-whitespace
 
 // RUN: (echo "vptr_check:S"; echo "vptr_check:T"; echo "vptr_check:U") > %t.supp
-// RUN: ASAN_OPTIONS="suppressions='%t.supp':halt_on_error=1" UBSAN_OPTIONS="suppressions='%t.supp':halt_on_error=1" %run %t mS 2>&1
-// RUN: ASAN_OPTIONS="suppressions='%t.supp':halt_on_error=1" UBSAN_OPTIONS="suppressions='%t.supp':halt_on_error=1" %run %t fS 2>&1
-// RUN: ASAN_OPTIONS="suppressions='%t.supp':halt_on_error=1" UBSAN_OPTIONS="suppressions='%t.supp':halt_on_error=1" %run %t cS 2>&1
-// RUN: ASAN_OPTIONS="suppressions='%t.supp':halt_on_error=1" UBSAN_OPTIONS="suppressions='%t.supp':halt_on_error=1" %run %t mV 2>&1
-// RUN: ASAN_OPTIONS="suppressions='%t.supp':halt_on_error=1" UBSAN_OPTIONS="suppressions='%t.supp':halt_on_error=1" %run %t fV 2>&1
-// RUN: ASAN_OPTIONS="suppressions='%t.supp':halt_on_error=1" UBSAN_OPTIONS="suppressions='%t.supp':halt_on_error=1" %run %t cV 2>&1
-// RUN: ASAN_OPTIONS="suppressions='%t.supp':halt_on_error=1" UBSAN_OPTIONS="suppressions='%t.supp':halt_on_error=1" %run %t oU 2>&1
+// RUN: ASAN_OPTIONS="suppressions='%t.supp'" UBSAN_OPTIONS="suppressions='%t.supp':halt_on_error=1" %run %t mS 2>&1
+// RUN: ASAN_OPTIONS="suppressions='%t.supp'" UBSAN_OPTIONS="suppressions='%t.supp':halt_on_error=1" %run %t fS 2>&1
+// RUN: ASAN_OPTIONS="suppressions='%t.supp'" UBSAN_OPTIONS="suppressions='%t.supp':halt_on_error=1" %run %t cS 2>&1
+// RUN: ASAN_OPTIONS="suppressions='%t.supp'" UBSAN_OPTIONS="suppressions='%t.supp':halt_on_error=1" %run %t mV 2>&1
+// RUN: ASAN_OPTIONS="suppressions='%t.supp'" UBSAN_OPTIONS="suppressions='%t.supp':halt_on_error=1" %run %t fV 2>&1
+// RUN: ASAN_OPTIONS="suppressions='%t.supp'" UBSAN_OPTIONS="suppressions='%t.supp':halt_on_error=1" %run %t cV 2>&1
+// RUN: ASAN_OPTIONS="suppressions='%t.supp'" UBSAN_OPTIONS="suppressions='%t.supp':halt_on_error=1" %run %t oU 2>&1
 
 // RUN: echo "vptr_check:S" > %t.loc-supp
-// 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
+// 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
 
 // FIXME: This test produces linker errors on Darwin.
 // XFAIL: darwin





More information about the llvm-commits mailing list