[cfe-commits] r168017 - in /cfe/trunk: test/PCH/thread-safety-attrs.cpp utils/TableGen/ClangAttrEmitter.cpp

Argyrios Kyrtzidis akyrtzi at gmail.com
Wed Nov 14 17:31:39 PST 2012


Author: akirtzidis
Date: Wed Nov 14 19:31:39 2012
New Revision: 168017

URL: http://llvm.org/viewvc/llvm-project?rev=168017&view=rev
Log:
[PCH] Reading expressions from attributes should be done using ReadExpr(),
not ReadExpr().

Also add a test case making sure the thread safety attributes work as expected
when they come from a PCH.

Fixes rdar://12584141 & http://llvm.org/PR13982

Added:
    cfe/trunk/test/PCH/thread-safety-attrs.cpp
Modified:
    cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp

Added: cfe/trunk/test/PCH/thread-safety-attrs.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/thread-safety-attrs.cpp?rev=168017&view=auto
==============================================================================
--- cfe/trunk/test/PCH/thread-safety-attrs.cpp (added)
+++ cfe/trunk/test/PCH/thread-safety-attrs.cpp Wed Nov 14 19:31:39 2012
@@ -0,0 +1,317 @@
+// Test this without pch.
+// RUN: %clang_cc1 -include %s -fsyntax-only -verify -Wthread-safety -std=c++11 %s
+
+// Test with pch.
+// RUN: %clang_cc1 -emit-pch -o %t %s -std=c++11
+// RUN: %clang_cc1 -include-pch %t -fsyntax-only -verify -Wthread-safety -std=c++11 %s
+
+#ifndef HEADER
+#define HEADER
+
+#define LOCKABLE            __attribute__ ((lockable))
+#define SCOPED_LOCKABLE     __attribute__ ((scoped_lockable))
+#define GUARDED_BY(x)       __attribute__ ((guarded_by(x)))
+#define GUARDED_VAR         __attribute__ ((guarded_var))
+#define PT_GUARDED_BY(x)    __attribute__ ((pt_guarded_by(x)))
+#define PT_GUARDED_VAR      __attribute__ ((pt_guarded_var))
+#define ACQUIRED_AFTER(...) __attribute__ ((acquired_after(__VA_ARGS__)))
+#define ACQUIRED_BEFORE(...) __attribute__ ((acquired_before(__VA_ARGS__)))
+#define EXCLUSIVE_LOCK_FUNCTION(...)   __attribute__ ((exclusive_lock_function(__VA_ARGS__)))
+#define SHARED_LOCK_FUNCTION(...)      __attribute__ ((shared_lock_function(__VA_ARGS__)))
+#define EXCLUSIVE_TRYLOCK_FUNCTION(...) __attribute__ ((exclusive_trylock_function(__VA_ARGS__)))
+#define SHARED_TRYLOCK_FUNCTION(...)    __attribute__ ((shared_trylock_function(__VA_ARGS__)))
+#define UNLOCK_FUNCTION(...)            __attribute__ ((unlock_function(__VA_ARGS__)))
+#define LOCK_RETURNED(x)    __attribute__ ((lock_returned(x)))
+#define LOCKS_EXCLUDED(...) __attribute__ ((locks_excluded(__VA_ARGS__)))
+#define EXCLUSIVE_LOCKS_REQUIRED(...) \
+  __attribute__ ((exclusive_locks_required(__VA_ARGS__)))
+#define SHARED_LOCKS_REQUIRED(...) \
+  __attribute__ ((shared_locks_required(__VA_ARGS__)))
+#define NO_THREAD_SAFETY_ANALYSIS  __attribute__ ((no_thread_safety_analysis))
+
+
+class  __attribute__((lockable)) Mutex {
+ public:
+  void Lock() __attribute__((exclusive_lock_function));
+  void ReaderLock() __attribute__((shared_lock_function));
+  void Unlock() __attribute__((unlock_function));
+  bool TryLock() __attribute__((exclusive_trylock_function(true)));
+  bool ReaderTryLock() __attribute__((shared_trylock_function(true)));
+  void LockWhen(const int &cond) __attribute__((exclusive_lock_function));
+};
+
+class __attribute__((scoped_lockable)) MutexLock {
+ public:
+  MutexLock(Mutex *mu) __attribute__((exclusive_lock_function(mu)));
+  ~MutexLock() __attribute__((unlock_function));
+};
+
+class __attribute__((scoped_lockable)) ReaderMutexLock {
+ public:
+  ReaderMutexLock(Mutex *mu) __attribute__((exclusive_lock_function(mu)));
+  ~ReaderMutexLock() __attribute__((unlock_function));
+};
+
+class SCOPED_LOCKABLE ReleasableMutexLock {
+ public:
+  ReleasableMutexLock(Mutex *mu) EXCLUSIVE_LOCK_FUNCTION(mu);
+  ~ReleasableMutexLock() UNLOCK_FUNCTION();
+
+  void Release() UNLOCK_FUNCTION();
+};
+
+
+// The universal lock, written "*", allows checking to be selectively turned
+// off for a particular piece of code.
+void beginNoWarnOnReads()  SHARED_LOCK_FUNCTION("*");
+void endNoWarnOnReads()    UNLOCK_FUNCTION("*");
+void beginNoWarnOnWrites() EXCLUSIVE_LOCK_FUNCTION("*");
+void endNoWarnOnWrites()   UNLOCK_FUNCTION("*");
+
+
+// For testing handling of smart pointers.
+template<class T>
+class SmartPtr {
+public:
+  SmartPtr(T* p) : ptr_(p) { }
+  SmartPtr(const SmartPtr<T>& p) : ptr_(p.ptr_) { }
+  ~SmartPtr();
+
+  T* get()        const { return ptr_; }
+  T* operator->() const { return ptr_; }
+  T& operator*()  const { return *ptr_; }
+
+private:
+  T* ptr_;
+};
+
+
+// For testing destructor calls and cleanup.
+class MyString {
+public:
+  MyString(const char* s);
+  ~MyString();
+};
+
+
+
+Mutex sls_mu;
+
+Mutex sls_mu2 __attribute__((acquired_after(sls_mu)));
+int sls_guard_var __attribute__((guarded_var)) = 0;
+int sls_guardby_var __attribute__((guarded_by(sls_mu))) = 0;
+
+bool getBool();
+
+class MutexWrapper {
+public:
+   Mutex mu;
+   int x __attribute__((guarded_by(mu)));
+   void MyLock() __attribute__((exclusive_lock_function(mu)));
+};
+
+#else
+
+MutexWrapper sls_mw;
+
+void sls_fun_0() {
+  sls_mw.mu.Lock();
+  sls_mw.x = 5;
+  sls_mw.mu.Unlock();
+}
+
+void sls_fun_2() {
+  sls_mu.Lock();
+  int x = sls_guard_var;
+  sls_mu.Unlock();
+}
+
+void sls_fun_3() {
+  sls_mu.Lock();
+  sls_guard_var = 2;
+  sls_mu.Unlock();
+}
+
+void sls_fun_4() {
+  sls_mu2.Lock();
+  sls_guard_var = 2;
+  sls_mu2.Unlock();
+}
+
+void sls_fun_5() {
+  sls_mu.Lock();
+  int x = sls_guardby_var;
+  sls_mu.Unlock();
+}
+
+void sls_fun_6() {
+  sls_mu.Lock();
+  sls_guardby_var = 2;
+  sls_mu.Unlock();
+}
+
+void sls_fun_7() {
+  sls_mu.Lock();
+  sls_mu2.Lock();
+  sls_mu2.Unlock();
+  sls_mu.Unlock();
+}
+
+void sls_fun_8() {
+  sls_mu.Lock();
+  if (getBool())
+    sls_mu.Unlock();
+  else
+    sls_mu.Unlock();
+}
+
+void sls_fun_9() {
+  if (getBool())
+    sls_mu.Lock();
+  else
+    sls_mu.Lock();
+  sls_mu.Unlock();
+}
+
+void sls_fun_good_6() {
+  if (getBool()) {
+    sls_mu.Lock();
+  } else {
+    if (getBool()) {
+      getBool(); // EMPTY
+    } else {
+      getBool(); // EMPTY
+    }
+    sls_mu.Lock();
+  }
+  sls_mu.Unlock();
+}
+
+void sls_fun_good_7() {
+  sls_mu.Lock();
+  while (getBool()) {
+    sls_mu.Unlock();
+    if (getBool()) {
+      if (getBool()) {
+        sls_mu.Lock();
+        continue;
+      }
+    }
+    sls_mu.Lock();
+  }
+  sls_mu.Unlock();
+}
+
+void sls_fun_good_8() {
+  sls_mw.MyLock();
+  sls_mw.mu.Unlock();
+}
+
+void sls_fun_bad_1() {
+  sls_mu.Unlock(); // \
+    // expected-warning{{unlocking 'sls_mu' that was not locked}}
+}
+
+void sls_fun_bad_2() {
+  sls_mu.Lock();
+  sls_mu.Lock(); // \
+    // expected-warning{{locking 'sls_mu' that is already locked}}
+  sls_mu.Unlock();
+}
+
+void sls_fun_bad_3() {
+  sls_mu.Lock(); // expected-note {{mutex acquired here}}
+} // expected-warning{{mutex 'sls_mu' is still locked at the end of function}}
+
+void sls_fun_bad_4() {
+  if (getBool())
+    sls_mu.Lock();  // expected-note{{mutex acquired here}}
+  else
+    sls_mu2.Lock(); // expected-note{{mutex acquired here}}
+} // expected-warning{{mutex 'sls_mu' is not locked on every path through here}}  \
+  // expected-warning{{mutex 'sls_mu2' is not locked on every path through here}}
+
+void sls_fun_bad_5() {
+  sls_mu.Lock(); // expected-note {{mutex acquired here}}
+  if (getBool())
+    sls_mu.Unlock();
+} // expected-warning{{mutex 'sls_mu' is not locked on every path through here}}
+
+void sls_fun_bad_6() {
+  if (getBool()) {
+    sls_mu.Lock(); // expected-note {{mutex acquired here}}
+  } else {
+    if (getBool()) {
+      getBool(); // EMPTY
+    } else {
+      getBool(); // EMPTY
+    }
+  }
+  sls_mu.Unlock(); // \
+    expected-warning{{mutex 'sls_mu' is not locked on every path through here}}\
+    expected-warning{{unlocking 'sls_mu' that was not locked}}
+}
+
+void sls_fun_bad_7() {
+  sls_mu.Lock();
+  while (getBool()) {
+    sls_mu.Unlock();
+    if (getBool()) {
+      if (getBool()) {
+        continue; // \
+        expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}}
+      }
+    }
+    sls_mu.Lock(); // expected-note {{mutex acquired here}}
+  }
+  sls_mu.Unlock();
+}
+
+void sls_fun_bad_8() {
+  sls_mu.Lock(); // expected-note{{mutex acquired here}}
+
+  do {
+    sls_mu.Unlock(); // expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}}
+  } while (getBool());
+}
+
+void sls_fun_bad_9() {
+  do {
+    sls_mu.Lock();  // \
+      // expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}} \
+      // expected-note{{mutex acquired here}}
+  } while (getBool());
+  sls_mu.Unlock();
+}
+
+void sls_fun_bad_10() {
+  sls_mu.Lock();  // expected-note 2{{mutex acquired here}}
+  while(getBool()) {  // expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}}
+    sls_mu.Unlock();
+  }
+} // expected-warning{{mutex 'sls_mu' is still locked at the end of function}}
+
+void sls_fun_bad_11() {
+  while (getBool()) { // \
+      expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}}
+    sls_mu.Lock(); // expected-note {{mutex acquired here}}
+  }
+  sls_mu.Unlock(); // \
+    // expected-warning{{unlocking 'sls_mu' that was not locked}}
+}
+
+void sls_fun_bad_12() {
+  sls_mu.Lock(); // expected-note {{mutex acquired here}}
+  while (getBool()) {
+    sls_mu.Unlock();
+    if (getBool()) {
+      if (getBool()) {
+        break; // expected-warning{{mutex 'sls_mu' is not locked on every path through here}}
+      }
+    }
+    sls_mu.Lock();
+  }
+  sls_mu.Unlock();
+}
+
+#endif

Modified: cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp?rev=168017&r1=168016&r2=168017&view=diff
==============================================================================
--- cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp (original)
+++ cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp Wed Nov 14 19:31:39 2012
@@ -47,7 +47,7 @@
     .EndsWith("Decl *", "GetLocalDeclAs<" 
               + std::string(type, 0, type.size()-1) + ">(F, Record[Idx++])")
     .Case("QualType", "getLocalType(F, Record[Idx++])")
-    .Case("Expr *", "ReadSubExpr()")
+    .Case("Expr *", "ReadExpr(F)")
     .Case("IdentifierInfo *", "GetIdentifierInfo(F, Record, Idx)")
     .Case("SourceLocation", "ReadSourceLocation(F, Record, Idx)")
     .Default("Record[Idx++]");





More information about the cfe-commits mailing list