Re: [PATCH] D14731: [libcxx] Add clang thread safety annotations to mutex and lock_guard

2016-03-11 Thread James Robinson via cfe-commits
jamesr added a comment.

Thank you for posting the LIT changes - that's the part I was unable to figure 
out.  I have a number of additional failure test cases that I will add.

I don't know what sort of code this could break, although I certainly don't 
claim to know more about these annotations than the author.  Do you have a link 
to that discussion handy?  The most obvious way this could break existing code 
would be if existing code was compiling with -Wthread-safety and had its own 
annotations that were inconsistent with these, but as it's a compile error to 
declare thread-safety relationships with types that aren't already annotated I 
can't see how any code that would be broken could compile today.  Concretely, 
if some code is written like this today:

struct Foo {

  int a __attribute__((guarded_by(m)));
  std::mutex m;

};

void Bad(Foo* f) { f->a++; }

will fail to compile without this patch in libc++ with the error:

/tmp/test.cc:4:26: error: 'guarded_by' attribute requires arguments whose type 
is annotated with 'capability' attribute; type here is 'std::mutex'

[-Werror,-Wthread-safety-attributes]
  int a __attribute__((guarded_by(m))


http://reviews.llvm.org/D14731



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D14731: [libcxx] Add clang thread safety annotations to mutex and lock_guard

2016-03-11 Thread James Robinson via cfe-commits
jamesr added a comment.

Ah, that's true.  I didn't think of that case.  With the design of these 
annotations the author of that function would have to disable checks in each 
piece of code that uses these patterns.

What about adding a different guard for these annotations in libc++ that 
consumers could choose to toggle independently of the -Wthread-safety compiler 
option?  That way consumers could choose to enable the libc++ annotations if 
their codebase was compatible with them.  The alternative is that consumers 
have to fully wrap the std:: types in their own types to add the annotations 
which works but makes code reuse very difficult.


http://reviews.llvm.org/D14731



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D14731: [libcxx] Add clang thread safety annotations to mutex and lock_guard

2016-03-11 Thread James Robinson via cfe-commits
jamesr added a comment.

In http://reviews.llvm.org/D14731#373289, @EricWF wrote:

> My suggestion would be to make these annotations OFF by default and allow 
> users to turn them on with a macro.


Our comments crossed streams but suggested the same thing :).  Any suggestions 
on a naming convention for the guard?  Also, would I set this macro 
unconditionally in LIT or is there a way to have it run tests both with and 
without the macro to ensure that when it is off code like the snippet you 
posted continues to build unmodified?


http://reviews.llvm.org/D14731



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D14731: [libcxx] Add clang thread safety annotations to mutex and lock_guard

2016-03-11 Thread James Robinson via cfe-commits
jamesr updated this revision to Diff 50481.
jamesr added a comment.

This patch guards the new annotations with 
_LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS and adds a number of tests to check 
that the annotations produce errors when the annotations are enabled that code 
violates the thread safety rules, that correct code does not produce errors, 
and that code that does not enable the annotations does not produce errors even 
in code that the thread-safety feature in Clang does not understand.

The feature guard is state in the positive as opposed to the negative as the 
annotations may be incompatible with correct code in some situations.


http://reviews.llvm.org/D14731

Files:
  include/__config
  include/__mutex_base
  test/libcxx/test/format.py
  
test/libcxx/thread/thread.mutex/thread_safety_access_guarded_without_lock.fail.cpp
  test/libcxx/thread/thread.mutex/thread_safety_annotations_not_enabled.cpp
  
test/libcxx/thread/thread.mutex/thread_safety_call_requires_capability_without_having.fail.cpp
  test/libcxx/thread/thread.mutex/thread_safety_lock_guard.cpp
  test/libcxx/thread/thread.mutex/thread_safety_lock_unlock.cpp
  test/libcxx/thread/thread.mutex/thread_safety_missing_unlock.fail.cpp
  test/libcxx/thread/thread.mutex/thread_safety_requires_capability.cpp

Index: test/libcxx/thread/thread.mutex/thread_safety_requires_capability.cpp
===
--- /dev/null
+++ test/libcxx/thread/thread.mutex/thread_safety_requires_capability.cpp
@@ -0,0 +1,22 @@
+#if !defined(__clang__) || !__has_attribute(acquire_capability)
+// This test is only meaningful on versions of clang that understand thread
+// safety annotations.
+
+#define _LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS
+
+#include 
+
+std::mutex m;
+int foo __attribute__((guarded_by(m)));
+
+void increment() __attribute__((requires_capability(m))) {
+  foo++;
+}
+
+int main() {
+  m.lock();
+  increment();
+  m.unlock();
+}
+
+#endif
Index: test/libcxx/thread/thread.mutex/thread_safety_missing_unlock.fail.cpp
===
--- /dev/null
+++ test/libcxx/thread/thread.mutex/thread_safety_missing_unlock.fail.cpp
@@ -0,0 +1,15 @@
+#if !defined(__clang__) || !__has_attribute(acquire_capability)
+// This test is only meaningful on versions of clang that understand thread
+// safety annotations.
+#error Test only supported on clang versions that support the acquire_capability annotation
+#endif
+
+#define _LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS
+
+#include 
+
+std::mutex m;
+
+int main() {
+  m.lock();
+} // expected-error {{mutex 'm' is still held at the end of function}}
Index: test/libcxx/thread/thread.mutex/thread_safety_lock_unlock.cpp
===
--- /dev/null
+++ test/libcxx/thread/thread.mutex/thread_safety_lock_unlock.cpp
@@ -0,0 +1,18 @@
+#if !defined(__clang__) || !__has_attribute(acquire_capability)
+// This test is only meaningful on versions of clang that understand thread
+// safety annotations.
+
+#define _LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS
+
+#include 
+
+std::mutex m;
+int foo __attribute__((guarded_by(m)));
+
+int main() {
+  m.lock();
+  foo++;
+  m.unlock();
+}
+
+#endif
Index: test/libcxx/thread/thread.mutex/thread_safety_lock_guard.cpp
===
--- /dev/null
+++ test/libcxx/thread/thread.mutex/thread_safety_lock_guard.cpp
@@ -0,0 +1,17 @@
+#if !defined(__clang__) || !__has_attribute(acquire_capability)
+// This test is only meaningful on versions of clang that understand thread
+// safety annotations.
+
+#define _LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS
+
+#include 
+
+std::mutex m;
+int foo __attribute__((guarded_by(m)));
+
+int main() {
+  std::lock_guard lock(m);
+  foo++;
+}
+
+#endif
Index: test/libcxx/thread/thread.mutex/thread_safety_call_requires_capability_without_having.fail.cpp
===
--- /dev/null
+++ test/libcxx/thread/thread.mutex/thread_safety_call_requires_capability_without_having.fail.cpp
@@ -0,0 +1,20 @@
+#if !defined(__clang__) || !__has_attribute(acquire_capability)
+// This test is only meaningful on versions of clang that understand thread
+// safety annotations.
+#error Test only supported on clang versions that support the acquire_capability annotation
+#endif
+
+#define _LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS
+
+#include 
+
+std::mutex m;
+int foo __attribute__((guarded_by(m)));
+
+void increment() __attribute__((requires_capability(m))) {
+  foo++;
+}
+
+int main() {
+  increment();  // expected-error{{calling function 'increment' requires holding mutex 'm' exclusively}}
+}
Index: test/libcxx/thread/thread.mutex/thread_safety_annotations_not_enabled.cpp
===
--- /dev/null
+++ test/libcxx/thread/thread.mutex/thread_safety_annotations_not_enabled.cpp
@@ -0,0 +1,

Re: [PATCH] D14731: [libcxx] Add clang thread safety annotations to mutex and lock_guard

2016-03-15 Thread James Robinson via cfe-commits
jamesr marked 5 inline comments as done.
jamesr added a comment.

Thank you for the comments, new patch coming.. (is there a way to post comments 
and upload a new patch at the same time?)


http://reviews.llvm.org/D14731



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D14731: [libcxx] Add clang thread safety annotations to mutex and lock_guard

2016-03-15 Thread James Robinson via cfe-commits
jamesr updated this revision to Diff 50788.

http://reviews.llvm.org/D14731

Files:
  include/__config
  include/__mutex_base
  test/libcxx/test/format.py
  test/libcxx/thread/thread.mutex/thread_safety_annotations_not_enabled.pass.cpp
  test/libcxx/thread/thread.mutex/thread_safety_lock_guard.pass.cpp
  test/libcxx/thread/thread.mutex/thread_safety_lock_unlock.pass.cpp
  test/libcxx/thread/thread.mutex/thread_safety_missing_unlock.fail.cpp
  test/libcxx/thread/thread.mutex/thread_safety_requires_capability.pass.cpp

Index: test/libcxx/thread/thread.mutex/thread_safety_requires_capability.pass.cpp
===
--- /dev/null
+++ test/libcxx/thread/thread.mutex/thread_safety_requires_capability.pass.cpp
@@ -0,0 +1,26 @@
+#if !defined(__clang__) || !__has_attribute(acquire_capability)
+// This test is only meaningful on versions of clang that understand thread
+// safety annotations.
+
+#define _LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS
+
+#include 
+
+std::mutex m;
+int foo __attribute__((guarded_by(m)));
+
+void increment() __attribute__((requires_capability(m))) {
+  foo++;
+}
+
+int main() {
+  m.lock();
+  increment();
+  m.unlock();
+}
+
+#else
+
+int main() {}
+
+#endif
Index: test/libcxx/thread/thread.mutex/thread_safety_missing_unlock.fail.cpp
===
--- /dev/null
+++ test/libcxx/thread/thread.mutex/thread_safety_missing_unlock.fail.cpp
@@ -0,0 +1,15 @@
+#if !defined(__clang__) || !__has_attribute(acquire_capability)
+// This test is only meaningful on versions of clang that understand thread
+// safety annotations.
+#error Test only supported on clang versions that support the acquire_capability annotation
+#endif
+
+#define _LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS
+
+#include 
+
+std::mutex m;
+
+int main() {
+  m.lock();
+} // expected-error {{mutex 'm' is still held at the end of function}}
Index: test/libcxx/thread/thread.mutex/thread_safety_lock_unlock.pass.cpp
===
--- /dev/null
+++ test/libcxx/thread/thread.mutex/thread_safety_lock_unlock.pass.cpp
@@ -0,0 +1,22 @@
+#if !defined(__clang__) || !__has_attribute(acquire_capability)
+// This test is only meaningful on versions of clang that understand thread
+// safety annotations.
+
+#define _LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS
+
+#include 
+
+std::mutex m;
+int foo __attribute__((guarded_by(m)));
+
+int main() {
+  m.lock();
+  foo++;
+  m.unlock();
+}
+
+#else
+
+int main() {}
+
+#endif
Index: test/libcxx/thread/thread.mutex/thread_safety_lock_guard.pass.cpp
===
--- /dev/null
+++ test/libcxx/thread/thread.mutex/thread_safety_lock_guard.pass.cpp
@@ -0,0 +1,21 @@
+#if !defined(__clang__) || !__has_attribute(acquire_capability)
+// This test is only meaningful on versions of clang that understand thread
+// safety annotations.
+
+#define _LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS
+
+#include 
+
+std::mutex m;
+int foo __attribute__((guarded_by(m)));
+
+int main() {
+  std::lock_guard lock(m);
+  foo++;
+}
+
+#else
+
+int main() {}
+
+#endif
Index: test/libcxx/thread/thread.mutex/thread_safety_annotations_not_enabled.pass.cpp
===
--- /dev/null
+++ test/libcxx/thread/thread.mutex/thread_safety_annotations_not_enabled.pass.cpp
@@ -0,0 +1,13 @@
+// This test does not define _LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS so it
+// should compile without any warnings or errors even though this pattern is not
+// understood by the thread safety annotations.
+
+#include 
+
+int main() {
+  std::mutex m;
+  m.lock();
+  {
+std::unique_lock g(m, std::adopt_lock);
+  }
+}
Index: test/libcxx/test/format.py
===
--- test/libcxx/test/format.py
+++ test/libcxx/test/format.py
@@ -167,7 +167,7 @@
 # when using Clang.
 extra_flags = []
 if self.cxx.type != 'gcc':
-extra_flags += ['-fsyntax-only']
+extra_flags += ['-fsyntax-only', '-Werror=thread-safety']
 if use_verify:
 extra_flags += ['-Xclang', '-verify',
 '-Xclang', '-verify-ignore-unexpected=note']
Index: include/__mutex_base
===
--- include/__mutex_base
+++ include/__mutex_base
@@ -26,7 +26,15 @@
 
 #ifndef _LIBCPP_HAS_NO_THREADS
 
-class _LIBCPP_TYPE_VIS mutex
+#ifndef _LIBCPP_THREAD_SAFETY_ANNOTATION
+#  ifdef _LIBCPP_HAS_THREAD_SAFETY_ANNOTATIONS
+#define _LIBCPP_THREAD_SAFETY_ANNOTATION(x) __attribute__((x))
+#  else
+#define _LIBCPP_THREAD_SAFETY_ANNOTATION(x)
+#  endif
+#endif  // _LIBCPP_THREAD_SAFETY_ANNOTATION
+
+class _LIBCPP_TYPE_VIS _LIBCPP_THREAD_SAFETY_ANNOTATION(capability("mutex")) mutex
 {
 pthread_mutex_t __m_;
 
@@ -44,9 +52,9 @@
 mutex& operator=(const mut

Re: [PATCH] D14731: [libcxx] Add clang thread safety annotations to mutex and lock_guard

2016-03-15 Thread James Robinson via cfe-commits
jamesr added a comment.

In http://reviews.llvm.org/D14731#376128, @EricWF wrote:

> So I fixed up LIT so that it also adds "-Werror=thread-safety" for both 
> ".pass.cpp" and ".fail.cpp" tests. Could you apply it to your patch?
>  https://gist.github.com/EricWF/8a0bfb6ff02f8c9f9940


Cool! Applied and confirmed that it's set for both.



Comment at: include/__mutex_base:37
@@ -30,1 +36,3 @@
+
+class _LIBCPP_TYPE_VIS _LIBCPP_THREAD_SAFETY_ANNOTATION(capability("mutex")) 
mutex
 {

EricWF wrote:
> Does `capability` have a alternative keyword that's a reserved name? ie 
> `__capability__`? If so we should use that instead.
If I'm reading 
https://github.com/llvm-mirror/clang/blob/master/include/clang/Basic/Attr.td#L1657
 correctly:

def Capability : InheritableAttr {
  let Spellings = [GNU<"capability">, CXX11<"clang", "capability">,
   GNU<"shared_capability">,
   CXX11<"clang", "shared_capability">];

then the answer is unfortunately "no"


http://reviews.llvm.org/D14731



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D14731: [libcxx] Add clang thread safety annotations to mutex and lock_guard

2016-03-15 Thread James Robinson via cfe-commits
jamesr updated this revision to Diff 50790.

http://reviews.llvm.org/D14731

Files:
  include/__config
  include/__mutex_base
  test/libcxx/test/config.py
  test/libcxx/thread/thread.mutex/thread_safety_annotations_not_enabled.pass.cpp
  test/libcxx/thread/thread.mutex/thread_safety_lock_guard.pass.cpp
  test/libcxx/thread/thread.mutex/thread_safety_lock_unlock.pass.cpp
  test/libcxx/thread/thread.mutex/thread_safety_missing_unlock.fail.cpp
  test/libcxx/thread/thread.mutex/thread_safety_requires_capability.pass.cpp

Index: test/libcxx/thread/thread.mutex/thread_safety_requires_capability.pass.cpp
===
--- /dev/null
+++ test/libcxx/thread/thread.mutex/thread_safety_requires_capability.pass.cpp
@@ -0,0 +1,26 @@
+#if !defined(__clang__) || !__has_attribute(acquire_capability)
+// This test is only meaningful on versions of clang that understand thread
+// safety annotations.
+
+#define _LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS
+
+#include 
+
+std::mutex m;
+int foo __attribute__((guarded_by(m)));
+
+void increment() __attribute__((requires_capability(m))) {
+  foo++;
+}
+
+int main() {
+  m.lock();
+  increment();
+  m.unlock();
+}
+
+#else
+
+int main() {}
+
+#endif
Index: test/libcxx/thread/thread.mutex/thread_safety_missing_unlock.fail.cpp
===
--- /dev/null
+++ test/libcxx/thread/thread.mutex/thread_safety_missing_unlock.fail.cpp
@@ -0,0 +1,15 @@
+#if !defined(__clang__) || !__has_attribute(acquire_capability)
+// This test is only meaningful on versions of clang that understand thread
+// safety annotations.
+#error Test only supported on clang versions that support the acquire_capability annotation
+#endif
+
+#define _LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS
+
+#include 
+
+std::mutex m;
+
+int main() {
+  m.lock();
+} // expected-error {{mutex 'm' is still held at the end of function}}
Index: test/libcxx/thread/thread.mutex/thread_safety_lock_unlock.pass.cpp
===
--- /dev/null
+++ test/libcxx/thread/thread.mutex/thread_safety_lock_unlock.pass.cpp
@@ -0,0 +1,22 @@
+#if !defined(__clang__) || !__has_attribute(acquire_capability)
+// This test is only meaningful on versions of clang that understand thread
+// safety annotations.
+
+#define _LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS
+
+#include 
+
+std::mutex m;
+int foo __attribute__((guarded_by(m)));
+
+int main() {
+  m.lock();
+  foo++;
+  m.unlock();
+}
+
+#else
+
+int main() {}
+
+#endif
Index: test/libcxx/thread/thread.mutex/thread_safety_lock_guard.pass.cpp
===
--- /dev/null
+++ test/libcxx/thread/thread.mutex/thread_safety_lock_guard.pass.cpp
@@ -0,0 +1,21 @@
+#if !defined(__clang__) || !__has_attribute(acquire_capability)
+// This test is only meaningful on versions of clang that understand thread
+// safety annotations.
+
+#define _LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS
+
+#include 
+
+std::mutex m;
+int foo __attribute__((guarded_by(m)));
+
+int main() {
+  std::lock_guard lock(m);
+  foo++;
+}
+
+#else
+
+int main() {}
+
+#endif
Index: test/libcxx/thread/thread.mutex/thread_safety_annotations_not_enabled.pass.cpp
===
--- /dev/null
+++ test/libcxx/thread/thread.mutex/thread_safety_annotations_not_enabled.pass.cpp
@@ -0,0 +1,13 @@
+// This test does not define _LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS so it
+// should compile without any warnings or errors even though this pattern is not
+// understood by the thread safety annotations.
+
+#include 
+
+int main() {
+  std::mutex m;
+  m.lock();
+  {
+std::unique_lock g(m, std::adopt_lock);
+  }
+}
Index: test/libcxx/test/config.py
===
--- test/libcxx/test/config.py
+++ test/libcxx/test/config.py
@@ -98,6 +98,7 @@
 self.configure_cxx_library_root()
 self.configure_use_system_cxx_lib()
 self.configure_use_clang_verify()
+self.configure_use_thread_safety()
 self.configure_execute_external()
 self.configure_ccache()
 self.configure_compile_flags()
@@ -218,6 +219,14 @@
 self.lit_config.note(
 "inferred use_clang_verify as: %r" % self.use_clang_verify)
 
+def configure_use_thread_safety(self):
+'''If set, run clang with -verify on failing tests.'''
+has_thread_safety = self.cxx.hasCompileFlag('-Werror=thread-safety')
+if has_thread_safety:
+self.cxx.compile_flags += ['-Werror=thread-safety']
+self.config.available_features.add('thread-safety')
+self.lit_config.note("enabling thread-safety annotations")
+
 def configure_execute_external(self):
 # Choose between lit's internal shell pipeline runner and a real shell.
 # If LIT_USE_INTERNAL_SHELL is in the environmen

Re: [PATCH] D14731: [libcxx] Add clang thread safety annotations to mutex and lock_guard

2016-03-15 Thread James Robinson via cfe-commits
jamesr added a comment.

In http://reviews.llvm.org/D14731#376138, @EricWF wrote:

> So this LGTM except for one last change (I'm sorry). LIT now knows when 
> "-Werror=thread-safety" is being passed. Could you change the tests guarded 
> by "#if !defined(__clang__) || !__has_attribute(aquire_capability)` to say 
> "// REQUIRES: thread-safety" instead? I prefer using LIT to manage when tests 
> run because it can report un-run tests where simply using macros cant.
>
> After that LGTM.


If I do that, does that mean I can omit the extra main()s, etc, and the LIT 
harness will avoid attempting the test at all when the feature bit is set?


http://reviews.llvm.org/D14731



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D14731: [libcxx] Add clang thread safety annotations to mutex and lock_guard

2016-03-15 Thread James Robinson via cfe-commits
jamesr updated this revision to Diff 50791.
jamesr added a comment.

Use // REQUIRES: thread-safety instead of macros to feature guard tests


http://reviews.llvm.org/D14731

Files:
  include/__config
  include/__mutex_base
  test/libcxx/test/config.py
  test/libcxx/thread/thread.mutex/thread_safety_annotations_not_enabled.pass.cpp
  test/libcxx/thread/thread.mutex/thread_safety_lock_guard.pass.cpp
  test/libcxx/thread/thread.mutex/thread_safety_lock_unlock.pass.cpp
  test/libcxx/thread/thread.mutex/thread_safety_missing_unlock.fail.cpp
  test/libcxx/thread/thread.mutex/thread_safety_requires_capability.pass.cpp

Index: test/libcxx/thread/thread.mutex/thread_safety_requires_capability.pass.cpp
===
--- /dev/null
+++ test/libcxx/thread/thread.mutex/thread_safety_requires_capability.pass.cpp
@@ -0,0 +1,18 @@
+// REQUIRES: thread-safety
+
+#define _LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS
+
+#include 
+
+std::mutex m;
+int foo __attribute__((guarded_by(m)));
+
+void increment() __attribute__((requires_capability(m))) {
+  foo++;
+}
+
+int main() {
+  m.lock();
+  increment();
+  m.unlock();
+}
Index: test/libcxx/thread/thread.mutex/thread_safety_missing_unlock.fail.cpp
===
--- /dev/null
+++ test/libcxx/thread/thread.mutex/thread_safety_missing_unlock.fail.cpp
@@ -0,0 +1,11 @@
+// REQUIRES: thread-safety
+
+#define _LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS
+
+#include 
+
+std::mutex m;
+
+int main() {
+  m.lock();
+} // expected-error {{mutex 'm' is still held at the end of function}}
Index: test/libcxx/thread/thread.mutex/thread_safety_lock_unlock.pass.cpp
===
--- /dev/null
+++ test/libcxx/thread/thread.mutex/thread_safety_lock_unlock.pass.cpp
@@ -0,0 +1,14 @@
+// REQUIRES: thread-safety
+
+#define _LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS
+
+#include 
+
+std::mutex m;
+int foo __attribute__((guarded_by(m)));
+
+int main() {
+  m.lock();
+  foo++;
+  m.unlock();
+}
Index: test/libcxx/thread/thread.mutex/thread_safety_lock_guard.pass.cpp
===
--- /dev/null
+++ test/libcxx/thread/thread.mutex/thread_safety_lock_guard.pass.cpp
@@ -0,0 +1,13 @@
+// REQUIRES: thread-safety
+
+#define _LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS
+
+#include 
+
+std::mutex m;
+int foo __attribute__((guarded_by(m)));
+
+int main() {
+  std::lock_guard lock(m);
+  foo++;
+}
Index: test/libcxx/thread/thread.mutex/thread_safety_annotations_not_enabled.pass.cpp
===
--- /dev/null
+++ test/libcxx/thread/thread.mutex/thread_safety_annotations_not_enabled.pass.cpp
@@ -0,0 +1,13 @@
+// This test does not define _LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS so it
+// should compile without any warnings or errors even though this pattern is not
+// understood by the thread safety annotations.
+
+#include 
+
+int main() {
+  std::mutex m;
+  m.lock();
+  {
+std::unique_lock g(m, std::adopt_lock);
+  }
+}
Index: test/libcxx/test/config.py
===
--- test/libcxx/test/config.py
+++ test/libcxx/test/config.py
@@ -98,6 +98,7 @@
 self.configure_cxx_library_root()
 self.configure_use_system_cxx_lib()
 self.configure_use_clang_verify()
+self.configure_use_thread_safety()
 self.configure_execute_external()
 self.configure_ccache()
 self.configure_compile_flags()
@@ -218,6 +219,14 @@
 self.lit_config.note(
 "inferred use_clang_verify as: %r" % self.use_clang_verify)
 
+def configure_use_thread_safety(self):
+'''If set, run clang with -verify on failing tests.'''
+has_thread_safety = self.cxx.hasCompileFlag('-Werror=thread-safety')
+if has_thread_safety:
+self.cxx.compile_flags += ['-Werror=thread-safety']
+self.config.available_features.add('thread-safety')
+self.lit_config.note("enabling thread-safety annotations")
+
 def configure_execute_external(self):
 # Choose between lit's internal shell pipeline runner and a real shell.
 # If LIT_USE_INTERNAL_SHELL is in the environment, we use that as the
Index: include/__mutex_base
===
--- include/__mutex_base
+++ include/__mutex_base
@@ -26,7 +26,15 @@
 
 #ifndef _LIBCPP_HAS_NO_THREADS
 
-class _LIBCPP_TYPE_VIS mutex
+#ifndef _LIBCPP_THREAD_SAFETY_ANNOTATION
+#  ifdef _LIBCPP_HAS_THREAD_SAFETY_ANNOTATIONS
+#define _LIBCPP_THREAD_SAFETY_ANNOTATION(x) __attribute__((x))
+#  else
+#define _LIBCPP_THREAD_SAFETY_ANNOTATION(x)
+#  endif
+#endif  // _LIBCPP_THREAD_SAFETY_ANNOTATION
+
+class _LIBCPP_TYPE_VIS _LIBCPP_THREAD_SAFETY_ANNOTATION(capability("mutex")) mutex
 {
 pthread_mutex_t __m_;
 
@@ -44,9 +52,9 @@
   

Re: [PATCH] D14731: [libcxx] Add clang thread safety annotations to mutex and lock_guard

2016-03-15 Thread James Robinson via cfe-commits
jamesr updated this revision to Diff 50793.
jamesr added a comment.

Add LLVM license headers to new test files


http://reviews.llvm.org/D14731

Files:
  include/__config
  include/__mutex_base
  test/libcxx/test/config.py
  test/libcxx/thread/thread.mutex/thread_safety_annotations_not_enabled.pass.cpp
  test/libcxx/thread/thread.mutex/thread_safety_lock_guard.pass.cpp
  test/libcxx/thread/thread.mutex/thread_safety_lock_unlock.pass.cpp
  test/libcxx/thread/thread.mutex/thread_safety_missing_unlock.fail.cpp
  test/libcxx/thread/thread.mutex/thread_safety_requires_capability.pass.cpp

Index: test/libcxx/thread/thread.mutex/thread_safety_requires_capability.pass.cpp
===
--- /dev/null
+++ test/libcxx/thread/thread.mutex/thread_safety_requires_capability.pass.cpp
@@ -0,0 +1,29 @@
+//===--===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===--===//
+
+// REQUIRES: thread-safety
+
+// 
+
+#define _LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS
+
+#include 
+
+std::mutex m;
+int foo __attribute__((guarded_by(m)));
+
+void increment() __attribute__((requires_capability(m))) {
+  foo++;
+}
+
+int main() {
+  m.lock();
+  increment();
+  m.unlock();
+}
Index: test/libcxx/thread/thread.mutex/thread_safety_missing_unlock.fail.cpp
===
--- /dev/null
+++ test/libcxx/thread/thread.mutex/thread_safety_missing_unlock.fail.cpp
@@ -0,0 +1,22 @@
+//===--===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===--===//
+
+// REQUIRES: thread-safety
+
+// 
+
+#define _LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS
+
+#include 
+
+std::mutex m;
+
+int main() {
+  m.lock();
+} // expected-error {{mutex 'm' is still held at the end of function}}
Index: test/libcxx/thread/thread.mutex/thread_safety_lock_unlock.pass.cpp
===
--- /dev/null
+++ test/libcxx/thread/thread.mutex/thread_safety_lock_unlock.pass.cpp
@@ -0,0 +1,25 @@
+//===--===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===--===//
+
+// REQUIRES: thread-safety
+
+// 
+
+#define _LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS
+
+#include 
+
+std::mutex m;
+int foo __attribute__((guarded_by(m)));
+
+int main() {
+  m.lock();
+  foo++;
+  m.unlock();
+}
Index: test/libcxx/thread/thread.mutex/thread_safety_lock_guard.pass.cpp
===
--- /dev/null
+++ test/libcxx/thread/thread.mutex/thread_safety_lock_guard.pass.cpp
@@ -0,0 +1,24 @@
+//===--===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===--===//
+
+// REQUIRES: thread-safety
+
+// 
+
+#define _LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS
+
+#include 
+
+std::mutex m;
+int foo __attribute__((guarded_by(m)));
+
+int main() {
+  std::lock_guard lock(m);
+  foo++;
+}
Index: test/libcxx/thread/thread.mutex/thread_safety_annotations_not_enabled.pass.cpp
===
--- /dev/null
+++ test/libcxx/thread/thread.mutex/thread_safety_annotations_not_enabled.pass.cpp
@@ -0,0 +1,24 @@
+//===--===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===--===//
+
+// 
+
+// This test does not define _LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS so it
+// should compile without any warnings or errors even though this pattern is not
+// understood by the thread safety annotations.
+
+#include 
+
+int main() {
+  std::mutex m;
+  m.lock();
+  {
+std::unique_lock g(m, std::adopt_lock);
+  }
+}
Index: test/libcxx/test/config.py
===

Re: [PATCH] D18347: [PATCH] Fix thread_annotation negtest for thread safety.

2016-03-23 Thread James Robinson via cfe-commits
jamesr added a comment.

In http://reviews.llvm.org/D18347#380792, @EricWF wrote:

> And looking at the current state of the single-threaded test suite this isn't 
> the only test that needs this fix applied.
>
> http://lab.llvm.org:8011/builders/libcxx-libcxxabi-singlethreaded-x86_64-linux-debian/builds/869


Indeed! I assumed by reading other nearby tests that there was some mechanism 
that disabled the thread/ tests when threads were disabled, but didn't verify 
this. Sorry about the breakage.


http://reviews.llvm.org/D18347



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D14731: [libcxx] Add clang thread safety annotations to mutex and lock_guard

2015-11-16 Thread James Robinson via cfe-commits
jamesr created this revision.
jamesr added a subscriber: cfe-commits.

This adds clang thread safety annotations to std::mutex and
std::lock_guard so code using these types can use these types directly
instead of having to wrap the types to provide annotations. These checks
when enabled by -Wthread-safety provide simple but useful static
checking to detect potential race conditions.
See http://clang.llvm.org/docs/ThreadSafetyAnalysis.html for details.

http://reviews.llvm.org/D14731

Files:
  include/__config
  include/__mutex_base

Index: include/__mutex_base
===
--- include/__mutex_base
+++ include/__mutex_base
@@ -26,7 +26,7 @@
 
 #ifndef _LIBCPP_HAS_NO_THREADS
 
-class _LIBCPP_TYPE_VIS mutex
+class _LIBCPP_TYPE_VIS _LIBCPP_THREAD_ANNOTATION(capability("mutex")) mutex
 {
 pthread_mutex_t __m_;
 
@@ -44,9 +44,9 @@
 mutex& operator=(const mutex&);// = delete;
 
 public:
-void lock();
-bool try_lock() _NOEXCEPT;
-void unlock() _NOEXCEPT;
+void lock() _LIBCPP_THREAD_ANNOTATION(acquire_capability());
+bool try_lock() _NOEXCEPT 
_LIBCPP_THREAD_ANNOTATION(try_acquire_capability(true));
+void unlock() _NOEXCEPT _LIBCPP_THREAD_ANNOTATION(release_capability());
 
 typedef pthread_mutex_t* native_handle_type;
 _LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() {return 
&__m_;}
@@ -71,7 +71,7 @@
 #endif
 
 template 
-class _LIBCPP_TYPE_VIS_ONLY lock_guard
+class _LIBCPP_TYPE_VIS_ONLY _LIBCPP_THREAD_ANNOTATION(scoped_lockable) 
lock_guard
 {
 public:
 typedef _Mutex mutex_type;
@@ -81,13 +81,13 @@
 public:
 
 _LIBCPP_INLINE_VISIBILITY
-explicit lock_guard(mutex_type& __m)
+explicit lock_guard(mutex_type& __m) 
_LIBCPP_THREAD_ANNOTATION(acquire_capability(__m))
 : __m_(__m) {__m_.lock();}
 _LIBCPP_INLINE_VISIBILITY
-lock_guard(mutex_type& __m, adopt_lock_t)
+lock_guard(mutex_type& __m, adopt_lock_t) 
_LIBCPP_THREAD_ANNOTATION(requires_capability(__m))
 : __m_(__m) {}
 _LIBCPP_INLINE_VISIBILITY
-~lock_guard() {__m_.unlock();}
+~lock_guard() _LIBCPP_THREAD_ANNOTATION(release_capability()) 
{__m_.unlock();}
 
 private:
 lock_guard(lock_guard const&);// = delete;
Index: include/__config
===
--- include/__config
+++ include/__config
@@ -825,6 +825,12 @@
 #define _LIBCPP_HAS_NO_ATOMIC_HEADER
 #endif
 
+#if defined(__clang__)
+#define _LIBCPP_THREAD_ANNOTATION(x) __attribute__((x))
+#else
+#define _LIBCPP_THREAD_ANNOTATION(x)
+#endif
+
 #endif // __cplusplus
 
 #endif // _LIBCPP_CONFIG


Index: include/__mutex_base
===
--- include/__mutex_base
+++ include/__mutex_base
@@ -26,7 +26,7 @@
 
 #ifndef _LIBCPP_HAS_NO_THREADS
 
-class _LIBCPP_TYPE_VIS mutex
+class _LIBCPP_TYPE_VIS _LIBCPP_THREAD_ANNOTATION(capability("mutex")) mutex
 {
 pthread_mutex_t __m_;
 
@@ -44,9 +44,9 @@
 mutex& operator=(const mutex&);// = delete;
 
 public:
-void lock();
-bool try_lock() _NOEXCEPT;
-void unlock() _NOEXCEPT;
+void lock() _LIBCPP_THREAD_ANNOTATION(acquire_capability());
+bool try_lock() _NOEXCEPT _LIBCPP_THREAD_ANNOTATION(try_acquire_capability(true));
+void unlock() _NOEXCEPT _LIBCPP_THREAD_ANNOTATION(release_capability());
 
 typedef pthread_mutex_t* native_handle_type;
 _LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() {return &__m_;}
@@ -71,7 +71,7 @@
 #endif
 
 template 
-class _LIBCPP_TYPE_VIS_ONLY lock_guard
+class _LIBCPP_TYPE_VIS_ONLY _LIBCPP_THREAD_ANNOTATION(scoped_lockable) lock_guard
 {
 public:
 typedef _Mutex mutex_type;
@@ -81,13 +81,13 @@
 public:
 
 _LIBCPP_INLINE_VISIBILITY
-explicit lock_guard(mutex_type& __m)
+explicit lock_guard(mutex_type& __m) _LIBCPP_THREAD_ANNOTATION(acquire_capability(__m))
 : __m_(__m) {__m_.lock();}
 _LIBCPP_INLINE_VISIBILITY
-lock_guard(mutex_type& __m, adopt_lock_t)
+lock_guard(mutex_type& __m, adopt_lock_t) _LIBCPP_THREAD_ANNOTATION(requires_capability(__m))
 : __m_(__m) {}
 _LIBCPP_INLINE_VISIBILITY
-~lock_guard() {__m_.unlock();}
+~lock_guard() _LIBCPP_THREAD_ANNOTATION(release_capability()) {__m_.unlock();}
 
 private:
 lock_guard(lock_guard const&);// = delete;
Index: include/__config
===
--- include/__config
+++ include/__config
@@ -825,6 +825,12 @@
 #define _LIBCPP_HAS_NO_ATOMIC_HEADER
 #endif
 
+#if defined(__clang__)
+#define _LIBCPP_THREAD_ANNOTATION(x) __attribute__((x))
+#else
+#define _LIBCPP_THREAD_ANNOTATION(x)
+#endif
+
 #endif // __cplusplus
 
 #endif // _LIBCPP_CONFIG
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D14731: [libcxx] Add clang thread safety annotations to mutex and lock_guard

2015-12-01 Thread James Robinson via cfe-commits
jamesr updated this revision to Diff 41581.
jamesr added a comment.

Updates the macros to avoid defining anything if _LIBCPP_THREAD_ANNOTATION is 
already defined and to define _LIBCPP_THREAD_ANNOTATION to nothing if __clang__ 
is not set, __has_attribute(acquire_capability) is not set, or 
_LIBCPP_HAS_NO_THREAD_ANNOTATIONS is set.

It turns out there's not a clean feature guard for the thread safety 
annotations (i.e. no __has_feature() guard).  The annotations were added over 
time to clang.  I'm not sure at which point the feature was considered stable 
enough for general use.  Looking at clang's history the most recently added 
annotation out of the ones this patch uses is acquire_capability which was 
added in this commit: https://llvm.org/svn/llvm-project/cfe/trunk@201890, so 
I'm testing for that annotation to test for support for the feature as a whole. 
 It's quite possible that there are revisions of clang after the annotation 
support was added that contain bugs that make the annotations not very useful 
but the fix for any users trying to use such versions of clang is easy - just 
avoid passing -Wthread-safety to these versions of clang.


http://reviews.llvm.org/D14731

Files:
  include/__config
  include/__mutex_base

Index: include/__mutex_base
===
--- include/__mutex_base
+++ include/__mutex_base
@@ -26,7 +26,15 @@
 
 #ifndef _LIBCPP_HAS_NO_THREADS
 
-class _LIBCPP_TYPE_VIS mutex
+#ifndef _LIBCPP_THREAD_ANNOTATION
+#  ifndef _LIBCPP_HAS_NO_THREAD_ANNOTATIONS
+#define _LIBCPP_THREAD_ANNOTATION(x) __attribute__((x))
+#  else
+#define _LIBCPP_THREAD_ANNOTATION(x)
+#  endif
+#endif  // _LIBCPP_THREAD_ANNOTATION
+
+class _LIBCPP_TYPE_VIS _LIBCPP_THREAD_ANNOTATION(capability("mutex")) mutex
 {
 pthread_mutex_t __m_;
 
@@ -44,9 +52,9 @@
 mutex& operator=(const mutex&);// = delete;
 
 public:
-void lock();
-bool try_lock() _NOEXCEPT;
-void unlock() _NOEXCEPT;
+void lock() _LIBCPP_THREAD_ANNOTATION(acquire_capability());
+bool try_lock() _NOEXCEPT 
_LIBCPP_THREAD_ANNOTATION(try_acquire_capability(true));
+void unlock() _NOEXCEPT _LIBCPP_THREAD_ANNOTATION(release_capability());
 
 typedef pthread_mutex_t* native_handle_type;
 _LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() {return 
&__m_;}
@@ -71,7 +79,7 @@
 #endif
 
 template 
-class _LIBCPP_TYPE_VIS_ONLY lock_guard
+class _LIBCPP_TYPE_VIS_ONLY _LIBCPP_THREAD_ANNOTATION(scoped_lockable) 
lock_guard
 {
 public:
 typedef _Mutex mutex_type;
@@ -81,13 +89,13 @@
 public:
 
 _LIBCPP_INLINE_VISIBILITY
-explicit lock_guard(mutex_type& __m)
+explicit lock_guard(mutex_type& __m) 
_LIBCPP_THREAD_ANNOTATION(acquire_capability(__m))
 : __m_(__m) {__m_.lock();}
 _LIBCPP_INLINE_VISIBILITY
-lock_guard(mutex_type& __m, adopt_lock_t)
+lock_guard(mutex_type& __m, adopt_lock_t) 
_LIBCPP_THREAD_ANNOTATION(requires_capability(__m))
 : __m_(__m) {}
 _LIBCPP_INLINE_VISIBILITY
-~lock_guard() {__m_.unlock();}
+~lock_guard() _LIBCPP_THREAD_ANNOTATION(release_capability()) 
{__m_.unlock();}
 
 private:
 lock_guard(lock_guard const&);// = delete;
Index: include/__config
===
--- include/__config
+++ include/__config
@@ -825,6 +825,11 @@
 #define _LIBCPP_HAS_NO_ATOMIC_HEADER
 #endif
 
+#if (!defined(_LIBCPP_HAS_NO_THREAD_ANNOTATIONS) && (!defined(__clang__) \
+  || !__has_attribute(acquire_capability)))
+#define _LIBCPP_HAS_NO_THREAD_ANNOTATIONS
+#endif
+
 #endif // __cplusplus
 
 #endif // _LIBCPP_CONFIG


Index: include/__mutex_base
===
--- include/__mutex_base
+++ include/__mutex_base
@@ -26,7 +26,15 @@
 
 #ifndef _LIBCPP_HAS_NO_THREADS
 
-class _LIBCPP_TYPE_VIS mutex
+#ifndef _LIBCPP_THREAD_ANNOTATION
+#  ifndef _LIBCPP_HAS_NO_THREAD_ANNOTATIONS
+#define _LIBCPP_THREAD_ANNOTATION(x) __attribute__((x))
+#  else
+#define _LIBCPP_THREAD_ANNOTATION(x)
+#  endif
+#endif  // _LIBCPP_THREAD_ANNOTATION
+
+class _LIBCPP_TYPE_VIS _LIBCPP_THREAD_ANNOTATION(capability("mutex")) mutex
 {
 pthread_mutex_t __m_;
 
@@ -44,9 +52,9 @@
 mutex& operator=(const mutex&);// = delete;
 
 public:
-void lock();
-bool try_lock() _NOEXCEPT;
-void unlock() _NOEXCEPT;
+void lock() _LIBCPP_THREAD_ANNOTATION(acquire_capability());
+bool try_lock() _NOEXCEPT _LIBCPP_THREAD_ANNOTATION(try_acquire_capability(true));
+void unlock() _NOEXCEPT _LIBCPP_THREAD_ANNOTATION(release_capability());
 
 typedef pthread_mutex_t* native_handle_type;
 _LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() {return &__m_;}
@@ -71,7 +79,7 @@
 #endif
 
 template 
-class _LIBCPP_TYPE_VIS_ONLY lock_guard
+class _LIBCPP_TYPE_VIS_ONLY _LIBCPP_THREAD_ANNOTATION(scoped_lockable) lock_guard
 {
 public:
 typedef _Mutex mutex_type;
@@ -81,13 +89,13 @@
 public:
 
 _

Re: [PATCH] D14731: [libcxx] Add clang thread safety annotations to mutex and lock_guard

2015-12-01 Thread James Robinson via cfe-commits
jamesr added a comment.

In http://reviews.llvm.org/D14731#299152, @mclow.lists wrote:

> Where are the tests?


There aren't any yet.  I investigated a few avenues for testing but none seem 
very useful.

The most obvious testing strategy would be to write some code that fails the 
-Wthread-safety checks such as

  std::mutex m; m.lock(); m.lock();

and verify that this generates the expected warning.  There's a harness for 
expected warnings that does this in the clang repo but no such harness exists 
in libcxx.  Depending on the text of warnings from clang in libcxx tests seems 
like a layering violation, anyway.  Another check would be to test that such 
code fails to compile with -Wthread-safety -Werror set.  libcxx's test suite 
does support negative compilation tests but I can't find any way to specify 
that particular tests should be compiled with particular flags.  I tried 
enabling -Wthread-safety for all tests, but other tests fail because they do 
things that the annotations do not understand (deliberately, the annotations 
are for static checking not dynamic code analysis).  I could add suppressions 
to all of these tests but that seems backwards.  This also hits the problem 
that such annotations would only have meaning for new-enough versions of clang 
and there's no way for the driver to cleanly tell if the cxx being used 
supports the annotations or not.

The annotations are (by design) not supposed to have an influence on the 
program other than generating warnings in non-default configs so there isn't 
any  other testing hook I can think of.


http://reviews.llvm.org/D14731



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D14731: [libcxx] Add clang thread safety annotations to mutex and lock_guard

2015-12-01 Thread James Robinson via cfe-commits
jamesr added a subscriber: aaron.ballman.
jamesr added a comment.

It looks like Aaron Ballman was involved with adding parsing for these 
attributes in clang - perhaps he has an idea of a better way to detect these 
than __has_attribute(acquire_capability).


http://reviews.llvm.org/D14731



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D14731: [libcxx] Add clang thread safety annotations to mutex and lock_guard

2015-12-08 Thread James Robinson via cfe-commits
jamesr added a comment.

Marshall - friendly ping.  If you know a way to test functionality guarded by a 
compile-time flag in the libcxx test suite I'd be happy to wire in tests for 
this, but if that doesn't exist (and I think it does not currently) then I 
think the only way to verify this is by inspection.  Let me know what you'd 
prefer when you get a chance.  Thanks!


http://reviews.llvm.org/D14731



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits