diff --git a/libcxx/test/libcxx/selftest/compile.pass.mm/compile-error.compile.pass.mm b/libcxx/test/libcxx/selftest/compile.pass.mm/compile-error.compile.pass.mm
new file mode 100644
--- /dev/null
+++ b/libcxx/test/libcxx/selftest/compile.pass.mm/compile-error.compile.pass.mm
@@ -0,0 +1,18 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: objective-c++
+
+// XFAIL: *
+
+// Make sure the test DOES NOT pass if it fails at compile-time
+
+struct Foo { };
+typedef Foo::x x;
+
+int main(int, char**) { return 0; }
diff --git a/libcxx/test/libcxx/selftest/compile.pass.mm/compile-success.compile.pass.mm b/libcxx/test/libcxx/selftest/compile.pass.mm/compile-success.compile.pass.mm
new file mode 100644
--- /dev/null
+++ b/libcxx/test/libcxx/selftest/compile.pass.mm/compile-success.compile.pass.mm
@@ -0,0 +1,16 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: objective-c++
+
+// Make sure the test passes if it succeeds to compile
+
+@interface I;
+@end
+
+int main(int, char**) { return 0; }
diff --git a/libcxx/test/libcxx/selftest/compile.pass.mm/link-error.compile.pass.mm b/libcxx/test/libcxx/selftest/compile.pass.mm/link-error.compile.pass.mm
new file mode 100644
--- /dev/null
+++ b/libcxx/test/libcxx/selftest/compile.pass.mm/link-error.compile.pass.mm
@@ -0,0 +1,21 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: objective-c++
+
+// Make sure the test passes even if there's a link error, i.e. it isn't linked.
+
+@interface I;
+@end
+
+extern void this_is_an_undefined_symbol();
+
+int main(int, char**) {
+    this_is_an_undefined_symbol();
+    return 0;
+}
diff --git a/libcxx/test/libcxx/selftest/compile.pass.mm/run-error.compile.pass.mm b/libcxx/test/libcxx/selftest/compile.pass.mm/run-error.compile.pass.mm
new file mode 100644
--- /dev/null
+++ b/libcxx/test/libcxx/selftest/compile.pass.mm/run-error.compile.pass.mm
@@ -0,0 +1,18 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: objective-c++
+
+// Make sure the test passes even if there's a runtime error, i.e. it isn't run.
+
+@interface I;
+@end
+
+int main(int, char**) {
+    return 1;
+}
diff --git a/libcxx/test/libcxx/selftest/link.pass.mm/compile-error.link.pass.mm b/libcxx/test/libcxx/selftest/link.pass.mm/compile-error.link.pass.mm
new file mode 100644
--- /dev/null
+++ b/libcxx/test/libcxx/selftest/link.pass.mm/compile-error.link.pass.mm
@@ -0,0 +1,18 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: objective-c++
+
+// XFAIL: *
+
+// Make sure the test DOES NOT pass if it fails at compile-time.
+
+struct Foo { };
+typedef Foo::x x;
+
+int main(int, char**) { return 0; }
diff --git a/libcxx/test/libcxx/selftest/link.pass.mm/link-error.link.pass.mm b/libcxx/test/libcxx/selftest/link.pass.mm/link-error.link.pass.mm
new file mode 100644
--- /dev/null
+++ b/libcxx/test/libcxx/selftest/link.pass.mm/link-error.link.pass.mm
@@ -0,0 +1,20 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: objective-c++
+
+// XFAIL: *
+
+// Make sure the test DOES NOT pass if it fails to link.
+
+extern void this_is_an_undefined_symbol();
+
+int main(int, char**) {
+    this_is_an_undefined_symbol();
+    return 0;
+}
diff --git a/libcxx/test/libcxx/selftest/link.pass.mm/link-success.link.pass.mm b/libcxx/test/libcxx/selftest/link.pass.mm/link-success.link.pass.mm
new file mode 100644
--- /dev/null
+++ b/libcxx/test/libcxx/selftest/link.pass.mm/link-success.link.pass.mm
@@ -0,0 +1,16 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: objective-c++
+
+// Make sure the test passes if it succeeds to link.
+
+@interface I;
+@end
+
+int main(int, char**) { return 0; }
diff --git a/libcxx/test/libcxx/selftest/link.pass.mm/run-error.link.pass.mm b/libcxx/test/libcxx/selftest/link.pass.mm/run-error.link.pass.mm
new file mode 100644
--- /dev/null
+++ b/libcxx/test/libcxx/selftest/link.pass.mm/run-error.link.pass.mm
@@ -0,0 +1,19 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: objective-c++
+
+// Make sure the test passes if it succeeds to link, even though it would have
+// failed at runtime.
+
+@interface I;
+@end
+
+int main(int, char**) {
+    return 1;
+}
diff --git a/libcxx/test/std/utilities/meta/meta.trans/objc_support.pass.mm b/libcxx/test/std/utilities/meta/meta.trans/objc_support.compile.pass.mm
rename from libcxx/test/std/utilities/meta/meta.trans/objc_support.pass.mm
rename to libcxx/test/std/utilities/meta/meta.trans/objc_support.compile.pass.mm
diff --git a/libcxx/utils/libcxx/test/format.py b/libcxx/utils/libcxx/test/format.py
--- a/libcxx/utils/libcxx/test/format.py
+++ b/libcxx/utils/libcxx/test/format.py
@@ -115,9 +115,11 @@
     FOO.pass.mm             - Same as .pass.cpp, but for Objective-C++
 
     FOO.compile.pass.cpp    - Compiles successfully, link and run not attempted
+    FOO.compile.pass.mm     - Same as .compile.pass.cpp, but for Objective-C++
     FOO.compile.fail.cpp    - Does not compile successfully
 
     FOO.link.pass.cpp       - Compiles and links successfully, run not attempted
+    FOO.link.pass.mm        - Same as .link.pass.cpp, but for Objective-C++
     FOO.link.fail.cpp       - Compiles successfully, but fails to link
 
     FOO.sh.<anything>       - A builtin Lit Shell test
@@ -187,8 +189,10 @@
     """
     def getTestsInDirectory(self, testSuite, pathInSuite, litConfig, localConfig):
         SUPPORTED_SUFFIXES = ['[.]pass[.]cpp$', '[.]pass[.]mm$',
-                              '[.]compile[.]pass[.]cpp$', '[.]compile[.]fail[.]cpp$',
-                              '[.]link[.]pass[.]cpp$', '[.]link[.]fail[.]cpp$',
+                              '[.]compile[.]pass[.]cpp$', '[.]compile[.]pass[.]mm$',
+                              '[.]compile[.]fail[.]cpp$',
+                              '[.]link[.]pass[.]cpp$', '[.]link[.]pass[.]mm$',
+                              '[.]link[.]fail[.]cpp$',
                               '[.]sh[.][^.]+$',
                               '[.]verify[.]cpp$',
                               '[.]fail[.]cpp$']
@@ -211,7 +215,7 @@
         if re.search('[.]sh[.][^.]+$', filename):
             steps = [ ] # The steps are already in the script
             return self._executeShTest(test, litConfig, steps)
-        elif filename.endswith('.compile.pass.cpp'):
+        elif filename.endswith('.compile.pass.cpp') or filename.endswith('.compile.pass.mm'):
             steps = [
                 "%dbg(COMPILED WITH) %{cxx} %s %{flags} %{compile_flags} -fsyntax-only"
             ]
@@ -221,7 +225,7 @@
                 "%dbg(COMPILED WITH) ! %{cxx} %s %{flags} %{compile_flags} -fsyntax-only"
             ]
             return self._executeShTest(test, litConfig, steps)
-        elif filename.endswith('.link.pass.cpp'):
+        elif filename.endswith('.link.pass.cpp') or filename.endswith('.link.pass.mm'):
             steps = [
                 "%dbg(COMPILED WITH) %{cxx} %s %{flags} %{compile_flags} %{link_flags} -o %t.exe"
             ]