summaryrefslogtreecommitdiffstats
path: root/test/PCH
diff options
context:
space:
mode:
Diffstat (limited to 'test/PCH')
-rw-r--r--test/PCH/Inputs/cxx-method.h3
-rw-r--r--test/PCH/chain-late-anonymous-namespace.cpp2
-rw-r--r--test/PCH/crash-12631281.cpp40
-rw-r--r--test/PCH/cxx-constexpr.cpp3
-rw-r--r--test/PCH/cxx-method.cpp6
-rw-r--r--test/PCH/cxx-templates.cpp8
-rw-r--r--test/PCH/cxx-templates.h49
-rw-r--r--test/PCH/cxx0x-default-delete.cpp12
-rw-r--r--test/PCH/floating-literal.c18
-rw-r--r--test/PCH/irgen-rdar13114142.mm39
-rw-r--r--test/PCH/macro-redef.c28
-rw-r--r--test/PCH/missing-file.cpp1
-rw-r--r--test/PCH/modified-header-crash.c5
-rw-r--r--test/PCH/modified-header-error.c2
-rw-r--r--test/PCH/multiple-include-pch.c18
-rw-r--r--test/PCH/objc_container.m5
-rw-r--r--test/PCH/objc_stmts.m10
-rw-r--r--test/PCH/ocl_types.cl26
-rw-r--r--test/PCH/ocl_types.h25
-rw-r--r--test/PCH/thread-safety-attrs.cpp317
-rw-r--r--test/PCH/undefined-internal.c15
21 files changed, 623 insertions, 9 deletions
diff --git a/test/PCH/Inputs/cxx-method.h b/test/PCH/Inputs/cxx-method.h
index 6adb859..d5d56fe 100644
--- a/test/PCH/Inputs/cxx-method.h
+++ b/test/PCH/Inputs/cxx-method.h
@@ -1,6 +1,9 @@
struct S {
void m(int x);
+ S();
+ S(const S&);
+
operator const char*();
operator char*();
};
diff --git a/test/PCH/chain-late-anonymous-namespace.cpp b/test/PCH/chain-late-anonymous-namespace.cpp
index 87205c6..edae285 100644
--- a/test/PCH/chain-late-anonymous-namespace.cpp
+++ b/test/PCH/chain-late-anonymous-namespace.cpp
@@ -2,6 +2,8 @@
// RUN: %clang_cc1 -include %s -include %s -fsyntax-only %s
// with PCH
// RUN: %clang_cc1 -chain-include %s -chain-include %s -fsyntax-only %s
+// with PCH, with modules enabled
+// RUN: %clang_cc1 -chain-include %s -chain-include %s -fsyntax-only -fmodules %s
#if !defined(PASS1)
#define PASS1
diff --git a/test/PCH/crash-12631281.cpp b/test/PCH/crash-12631281.cpp
new file mode 100644
index 0000000..f309bca
--- /dev/null
+++ b/test/PCH/crash-12631281.cpp
@@ -0,0 +1,40 @@
+// RUN: %clang_cc1 -std=c++11 %s -emit-pch -o %t.pch
+// RUN: %clang_cc1 -fsyntax-only -std=c++11 %s -include-pch %t.pch -verify
+// expected-no-diagnostics
+
+// rdar://12631281
+// This reduced test case exposed a use-after-free memory bug, which was reliable
+// reproduced only on guarded malloc (and probably valgrind).
+
+#ifndef HEADER
+#define HEADER
+
+template < class _T2> struct is_convertible;
+template <> struct is_convertible<int> { typedef int type; };
+
+template <class _T1, class _T2> struct pair {
+ typedef _T1 first_type;
+ typedef _T2 second_type;
+ template <class _U1, class _U2, class = typename is_convertible< first_type>::type>
+ pair(_U1&& , _U2&& ); // expected-note {{candidate}}
+};
+
+template <class _ForwardIterator>
+pair<_ForwardIterator, _ForwardIterator> __equal_range(_ForwardIterator) {
+ return pair<_ForwardIterator, _ForwardIterator>(0, 0); // expected-error {{no matching constructor}}
+}
+
+template <class _ForwardIterator>
+pair<_ForwardIterator, _ForwardIterator> equal_range( _ForwardIterator a) {
+ return __equal_range(a); // expected-note {{instantiation}}
+}
+
+class A {
+ pair<int, int> range() {
+ return equal_range(0); // expected-note {{instantiation}}
+ }
+};
+
+#else
+
+#endif
diff --git a/test/PCH/cxx-constexpr.cpp b/test/PCH/cxx-constexpr.cpp
index 8fe48f7..13f04a7 100644
--- a/test/PCH/cxx-constexpr.cpp
+++ b/test/PCH/cxx-constexpr.cpp
@@ -4,6 +4,9 @@
// RUN: %clang_cc1 -pedantic-errors -std=c++11 -emit-pch %s -o %t-cxx11
// RUN: %clang_cc1 -pedantic-errors -std=c++11 -include-pch %t-cxx11 -verify %s
+// RUN: %clang_cc1 -pedantic-errors -std=c++98 -emit-pch %s -o %t -fmodules
+// RUN: %clang_cc1 -pedantic-errors -std=c++98 -include-pch %t -verify %s -fmodules
+
#ifndef HEADER_INCLUDED
#define HEADER_INCLUDED
diff --git a/test/PCH/cxx-method.cpp b/test/PCH/cxx-method.cpp
index 40490ea..c24ad92 100644
--- a/test/PCH/cxx-method.cpp
+++ b/test/PCH/cxx-method.cpp
@@ -1,3 +1,4 @@
+// RUN: %clang_cc1 -x c++ -include %S/Inputs/cxx-method.h -verify %s
// RUN: %clang_cc1 -x c++ -emit-pch %S/Inputs/cxx-method.h -o %t
// RUN: %clang_cc1 -include-pch %t -verify %s
// expected-no-diagnostics
@@ -7,3 +8,8 @@ void S::m(int x) { }
S::operator char *() { return 0; }
S::operator const char *() { return 0; }
+
+struct T : S {};
+
+const T a = T();
+T b(a);
diff --git a/test/PCH/cxx-templates.cpp b/test/PCH/cxx-templates.cpp
index d27e9ca..58c4c17 100644
--- a/test/PCH/cxx-templates.cpp
+++ b/test/PCH/cxx-templates.cpp
@@ -5,7 +5,7 @@
// Test with pch.
// RUN: %clang_cc1 -std=c++11 -fcxx-exceptions -fexceptions -x c++-header -emit-pch -o %t %S/cxx-templates.h
// RUN: %clang_cc1 -std=c++11 -fcxx-exceptions -fexceptions -include-pch %t -verify %s -ast-dump -o -
-// RUN: %clang_cc1 -std=c++11 -fcxx-exceptions -fexceptions -include-pch %t %s -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 -std=c++11 -fcxx-exceptions -fexceptions -include-pch %t %s -emit-llvm -o - -error-on-deserialized-decl doNotDeserialize | FileCheck %s
// expected-no-diagnostics
@@ -79,3 +79,9 @@ namespace TestNestedExpansion {
Int &g(Int, int, double);
Int &test = NestedExpansion<char, char, char>().f(0, 1, 2, Int(3), 4, 5.0);
}
+
+namespace rdar13135282 {
+ void test() {
+ __mt_alloc<> mt = __mt_alloc<>();
+ }
+}
diff --git a/test/PCH/cxx-templates.h b/test/PCH/cxx-templates.h
index 756f208..e672b0b 100644
--- a/test/PCH/cxx-templates.h
+++ b/test/PCH/cxx-templates.h
@@ -220,3 +220,52 @@ template<typename...A> struct NestedExpansion {
template<typename...B> auto f(A...a, B...b) -> decltype(g(a + b...));
};
template struct NestedExpansion<char, char, char>;
+
+namespace rdar13135282 {
+template < typename _Alloc >
+void foo(_Alloc = _Alloc());
+
+template < bool > class __pool;
+
+template < template < bool > class _PoolTp >
+struct __common_pool {
+ typedef _PoolTp < 0 > pool_type;
+};
+
+template < template < bool > class _PoolTp >
+struct __common_pool_base : __common_pool < _PoolTp > {};
+
+template < template < bool > class _PoolTp >
+struct A : __common_pool_base < _PoolTp > {};
+
+template < typename _Poolp = A < __pool > >
+struct __mt_alloc {
+ typedef typename _Poolp::pool_type __pool_type;
+ __mt_alloc() {
+ foo<__mt_alloc<> >();
+ }
+};
+}
+
+namespace PR13020 {
+template<typename T>
+void f() {
+ enum E {
+ enumerator
+ };
+
+ T t = enumerator;
+}
+
+template void f<int>();
+}
+
+template<typename T> void doNotDeserialize() {}
+template<typename T> struct ContainsDoNotDeserialize {
+ static int doNotDeserialize;
+};
+template<typename T> struct ContainsDoNotDeserialize2 {
+ static void doNotDeserialize();
+};
+template<typename T> int ContainsDoNotDeserialize<T>::doNotDeserialize = 0;
+template<typename T> void ContainsDoNotDeserialize2<T>::doNotDeserialize() {}
diff --git a/test/PCH/cxx0x-default-delete.cpp b/test/PCH/cxx0x-default-delete.cpp
index 39a90b8..230f6a6 100644
--- a/test/PCH/cxx0x-default-delete.cpp
+++ b/test/PCH/cxx0x-default-delete.cpp
@@ -20,6 +20,11 @@ class quux {
~quux() = default;
};
+struct A {
+ A(const A&) = default;
+ template<typename T> A(T&&);
+};
+
#else
foo::foo() { } // expected-error{{definition of explicitly defaulted default constructor}}
@@ -31,4 +36,11 @@ void fn() {
baz bz; // expected-error{{deleted function}} expected-note@16{{deleted here}}
quux qx; // expected-error{{private destructor}} expected-note@20{{private here}}
+struct B { A a; };
+struct C { mutable A a; };
+static_assert(__is_trivially_constructible(B, const B&), "");
+static_assert(!__is_trivially_constructible(B, B&&), "");
+static_assert(!__is_trivially_constructible(C, const C&), "");
+static_assert(!__is_trivially_constructible(C, C&&), "");
+
#endif
diff --git a/test/PCH/floating-literal.c b/test/PCH/floating-literal.c
new file mode 100644
index 0000000..7bf10d4
--- /dev/null
+++ b/test/PCH/floating-literal.c
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -triple mips64-none-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -x ast -ast-print %t | FileCheck %s
+
+// Make sure the semantics of FloatingLiterals are stored correctly in
+// the AST. Previously, the ASTWriter didn't store anything and the
+// reader assumed PPC 128-bit float semantics, which is incorrect for
+// targets with 128-bit IEEE long doubles.
+
+long double foo = 1.0E4000L;
+// CHECK: long double foo = 1.0E+4000L;
+
+// Just as well check the others are still sane while we're here...
+
+double bar = 1.0E300;
+// CHECK: double bar = 1.0E+300;
+
+float wibble = 1.0E40;
+// CHECK: float wibble = 1.0E+40;
diff --git a/test/PCH/irgen-rdar13114142.mm b/test/PCH/irgen-rdar13114142.mm
new file mode 100644
index 0000000..bd523c2
--- /dev/null
+++ b/test/PCH/irgen-rdar13114142.mm
@@ -0,0 +1,39 @@
+// RUN: %clang_cc1 %s -emit-pch -o %t.pch
+// RUN: %clang_cc1 %s -emit-llvm %s -include-pch %t.pch -o - | FileCheck %s
+
+#ifndef HEADER
+#define HEADER
+
+class OOArray{
+public:
+ ~OOArray();
+};
+
+class OOString {
+public:
+ OOString();
+ OOString(char *);
+};
+
+class OOPattern {
+public:
+ OOArray matchAll(const OOString &)const {
+ __attribute__((__blocks__(byref))) OOArray out;
+ }
+};
+
+OOArray operator & (const OOPattern & pattern) {
+ pattern.matchAll(0);
+}
+OOArray operator & (OOString, OOString);
+
+#else
+
+// We just make sure there is no crash on IRGen (rdar://13114142)
+// CHECK: _Z3foov()
+void foo() {
+ OOString str;
+ str & "o";
+}
+
+#endif
diff --git a/test/PCH/macro-redef.c b/test/PCH/macro-redef.c
new file mode 100644
index 0000000..7e25d7f
--- /dev/null
+++ b/test/PCH/macro-redef.c
@@ -0,0 +1,28 @@
+// RUN: %clang_cc1 %s -emit-pch -o %t1.pch -verify
+// RUN: %clang_cc1 %s -emit-pch -o %t2.pch -include-pch %t1.pch -verify
+// RUN: %clang_cc1 -fsyntax-only %s -include-pch %t2.pch -verify
+
+// Test that a redefinition inside the PCH won't manifest as an ambiguous macro.
+// rdar://13016031
+
+#ifndef HEADER1
+#define HEADER1
+
+#define M1 0 // expected-note {{previous}}
+#define M1 1 // expected-warning {{redefined}}
+
+#define M2 3
+
+#elif !defined(HEADER2)
+#define HEADER2
+
+#define M2 4 // expected-warning {{redefined}}
+ // expected-note@-6 {{previous}}
+
+#else
+
+// Use the error to verify it was parsed.
+int x = M1; // expected-note {{previous}}
+int x = M2; // expected-error {{redefinition}}
+
+#endif
diff --git a/test/PCH/missing-file.cpp b/test/PCH/missing-file.cpp
index 7dd11d4..502a9db 100644
--- a/test/PCH/missing-file.cpp
+++ b/test/PCH/missing-file.cpp
@@ -7,6 +7,7 @@
// %t.h might be touched by scanners as a hot file on Windows,
// to fail to remove %.h with single run.
+// FIXME: Do we really want to work around bugs in virus checkers here?
// RUN: rm %t.h || rm %t.h || rm %t.h
// Check diagnostic with location in original source:
diff --git a/test/PCH/modified-header-crash.c b/test/PCH/modified-header-crash.c
index c74ce22..4c21a8c 100644
--- a/test/PCH/modified-header-crash.c
+++ b/test/PCH/modified-header-crash.c
@@ -2,9 +2,12 @@
// RUN: cp %S/modified-header-crash.h %t.h
// RUN: %clang_cc1 -DCAKE -x c-header %t.h -emit-pch -o %t
-// RUN: echo >> %t.h
+// RUN: echo 'int foobar;' >> %t.h
// RUN: not %clang_cc1 %s -include-pch %t -fsyntax-only
+// FIXME: It is intended to suppress this on win32.
+// REQUIRES: ansi-escape-sequences
+
void f(void) {
foo = 3;
}
diff --git a/test/PCH/modified-header-error.c b/test/PCH/modified-header-error.c
index ef92494..4ad3faf 100644
--- a/test/PCH/modified-header-error.c
+++ b/test/PCH/modified-header-error.c
@@ -8,5 +8,5 @@
#include "header2.h"
-// CHECK: fatal error: file {{.*}} has been modified since the precompiled header was built
+// CHECK: fatal error: file {{.*}} has been modified since the precompiled header {{.*}} was built
// REQUIRES: shell
diff --git a/test/PCH/multiple-include-pch.c b/test/PCH/multiple-include-pch.c
new file mode 100644
index 0000000..1ef17b9
--- /dev/null
+++ b/test/PCH/multiple-include-pch.c
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -emit-pch -o %t1.pch %s
+// RUN: %clang_cc1 -emit-pch -o %t2.pch %s
+// RUN: %clang_cc1 %s -include-pch %t1.pch -include-pch %t2.pch -verify
+
+#ifndef HEADER
+#define HEADER
+
+extern int x;
+
+#else
+
+#warning parsed this
+// expected-warning@-1 {{parsed this}}
+int foo() {
+ return x;
+}
+
+#endif
diff --git a/test/PCH/objc_container.m b/test/PCH/objc_container.m
index 07371ca..aafe6a9 100644
--- a/test/PCH/objc_container.m
+++ b/test/PCH/objc_container.m
@@ -14,9 +14,12 @@
// CHECK-PRINT: oldObject = dictionary[key];
// CHECK-PRINT: dictionary[key] = newObject;
-// CHECK-IR: define void @all() nounwind
+// CHECK-IR: define void @all() #0
// CHECK-IR: {{call.*objc_msgSend}}
// CHECK-IR: {{call.*objc_msgSend}}
// CHECK-IR: {{call.*objc_msgSend}}
// CHECK-IR: {{call.*objc_msgSend}}
// CHECK-IR: ret void
+
+// CHECK: attributes #0 = { nounwind {{.*}} }
+// CHECK: attributes #1 = { nonlazybind }
diff --git a/test/PCH/objc_stmts.m b/test/PCH/objc_stmts.m
index b9b10c5..8deb14a 100644
--- a/test/PCH/objc_stmts.m
+++ b/test/PCH/objc_stmts.m
@@ -1,12 +1,12 @@
// Test this without pch.
// RUN: %clang_cc1 -include %S/objc_stmts.h -emit-llvm -fobjc-exceptions -o - %s
-// RUN: %clang_cc1 -include %S/objc_stmts.h -ast-dump -fobjc-exceptions -o - %s | FileCheck %s
+// RUN: %clang_cc1 -include %S/objc_stmts.h -ast-print -fobjc-exceptions -o - %s | FileCheck %s
// Test with pch.
// RUN: %clang_cc1 -x objective-c -emit-pch -fobjc-exceptions -o %t %S/objc_stmts.h
// RUN: %clang_cc1 -include-pch %t -emit-llvm -fobjc-exceptions -o - %s
-// RUN: %clang_cc1 -include-pch %t -ast-dump -fobjc-exceptions -o - %s | FileCheck %s
+// RUN: %clang_cc1 -include-pch %t -ast-print -fobjc-exceptions -o - %s | FileCheck %s
-// CHECK: catch parm = "A *a"
-// CHECK: catch parm = "B *b"
-// CHECK: catch all
+// CHECK: @catch(A *a)
+// CHECK: @catch(B *b)
+// CHECK: @catch()
diff --git a/test/PCH/ocl_types.cl b/test/PCH/ocl_types.cl
new file mode 100644
index 0000000..d788a32
--- /dev/null
+++ b/test/PCH/ocl_types.cl
@@ -0,0 +1,26 @@
+// Test this without pch.
+// RUN: %clang_cc1 -include %S/ocl_types.h -fsyntax-only %s
+
+// Test with pch.
+// RUN: %clang_cc1 -x cl -emit-pch -o %t %S/ocl_types.h
+// RUN: %clang_cc1 -include-pch %t -fsyntax-only %s -ast-print
+
+void foo1(img1d_t img);
+
+void foo2(img1darr_t img);
+
+void foo3(img1dbuff_t img);
+
+void foo4(img2d_t img);
+
+void foo5(img2darr_t img);
+
+void foo6(img3d_t img);
+
+void foo7(smp_t smp) {
+ smp_t loc_smp;
+}
+
+void foo8(evt_t evt) {
+ evt_t loc_evt;
+}
diff --git a/test/PCH/ocl_types.h b/test/PCH/ocl_types.h
new file mode 100644
index 0000000..65c6acb
--- /dev/null
+++ b/test/PCH/ocl_types.h
@@ -0,0 +1,25 @@
+/* Used with the ocl_types.cl test */
+
+// image1d_t
+typedef image1d_t img1d_t;
+
+// image1d_array_t
+typedef image1d_array_t img1darr_t;
+
+// image1d_buffer_t
+typedef image1d_buffer_t img1dbuff_t;
+
+// image2d_t
+typedef image2d_t img2d_t;
+
+// image2d_array_t
+typedef image2d_array_t img2darr_t;
+
+// image3d_t
+typedef image3d_t img3d_t;
+
+// sampler_t
+typedef sampler_t smp_t;
+
+// event_t
+typedef event_t evt_t;
diff --git a/test/PCH/thread-safety-attrs.cpp b/test/PCH/thread-safety-attrs.cpp
new file mode 100644
index 0000000..a588c0e
--- /dev/null
+++ b/test/PCH/thread-safety-attrs.cpp
@@ -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
diff --git a/test/PCH/undefined-internal.c b/test/PCH/undefined-internal.c
new file mode 100644
index 0000000..ef51460
--- /dev/null
+++ b/test/PCH/undefined-internal.c
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 -emit-pch %s -o %t
+// RUN: %clang_cc1 -include-pch %t %s -verify
+#ifndef HEADER_H
+#define HEADER_H
+static void f();
+static void g();
+void h() {
+ f();
+ g();
+}
+#else
+static void g() {}
+// expected-warning@5{{function 'f' has internal linkage but is not defined}}
+// expected-note@8{{used here}}
+#endif
OpenPOWER on IntegriCloud