Index: test/libcxx/selftest/test.fail.mm =================================================================== --- test/libcxx/selftest/test.fail.mm +++ test/libcxx/selftest/test.fail.mm @@ -0,0 +1,13 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: no-objective-cxx + +#error This test should not compile. Index: test/libcxx/selftest/test.pass.mm =================================================================== --- test/libcxx/selftest/test.pass.mm +++ test/libcxx/selftest/test.pass.mm @@ -0,0 +1,15 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: no-objective-cxx + +int main() +{ +} Index: utils/libcxx/compiler.py =================================================================== --- utils/libcxx/compiler.py +++ utils/libcxx/compiler.py @@ -98,7 +98,7 @@ self.version = (major_ver, minor_ver, patchlevel) def _basicCmd(self, source_files, out, mode=CM_Default, flags=[], - input_is_cxx=False): + input_is_text=False, is_objcxx=False): cmd = [] if self.use_ccache \ and not mode == self.CM_Link \ @@ -107,8 +107,11 @@ cmd += [self.path] if out is not None: cmd += ['-o', out] - if input_is_cxx: - cmd += ['-x', 'c++'] + if input_is_text: + if is_objcxx: + cmd += ['-x', 'objective-c++', '-fobjc-arc'] + else: + cmd += ['-x', 'c++'] if isinstance(source_files, list): cmd += source_files elif isinstance(source_files, str): @@ -131,22 +134,25 @@ cmd += self.warning_flags if mode != self.CM_PreProcess and mode != self.CM_Compile: cmd += self.link_flags + if is_objcxx: + cmd += ['-framework', 'Foundation'] cmd += flags return cmd def preprocessCmd(self, source_files, out=None, flags=[]): return self._basicCmd(source_files, out, flags=flags, - mode=self.CM_PreProcess, - input_is_cxx=True) + mode=self.CM_PreProcess, + input_is_text=True) - def compileCmd(self, source_files, out=None, flags=[]): + def compileCmd(self, source_files, out=None, flags=[], is_objcxx=False): return self._basicCmd(source_files, out, flags=flags, - mode=self.CM_Compile, - input_is_cxx=True) + ['-c'] + mode=self.CM_Compile, + input_is_text=True, + is_objcxx=is_objcxx) + ['-c'] - def linkCmd(self, source_files, out=None, flags=[]): + def linkCmd(self, source_files, out=None, flags=[], is_objcxx=False): return self._basicCmd(source_files, out, flags=flags, - mode=self.CM_Link) + mode=self.CM_Link, is_objcxx=is_objcxx) def compileLinkCmd(self, source_files, out=None, flags=[]): return self._basicCmd(source_files, out, flags=flags) @@ -157,14 +163,15 @@ cwd=cwd) return cmd, out, err, rc - def compile(self, source_files, out=None, flags=[], cwd=None): - cmd = self.compileCmd(source_files, out, flags) + def compile(self, source_files, out=None, flags=[], cwd=None, + is_objcxx=False): + cmd = self.compileCmd(source_files, out, flags, is_objcxx) out, err, rc = libcxx.util.executeCommand(cmd, env=self.compile_env, cwd=cwd) return cmd, out, err, rc - def link(self, source_files, out=None, flags=[], cwd=None): - cmd = self.linkCmd(source_files, out, flags) + def link(self, source_files, out=None, flags=[], cwd=None, is_objcxx=False): + cmd = self.linkCmd(source_files, out, flags, is_objcxx) out, err, rc = libcxx.util.executeCommand(cmd, env=self.compile_env, cwd=cwd) return cmd, out, err, rc @@ -176,8 +183,8 @@ cwd=cwd) return cmd, out, err, rc - def compileLinkTwoSteps(self, source_file, out=None, object_file=None, - flags=[], cwd=None): + def compileLinkTwoSteps(self, source_file, is_objcxx, out=None, + object_file=None, flags=[], cwd=None): if not isinstance(source_file, str): raise TypeError('This function only accepts a single input file') if object_file is None: @@ -188,12 +195,13 @@ with_fn = lambda: libcxx.util.nullContext(object_file) with with_fn() as object_file: cc_cmd, cc_stdout, cc_stderr, rc = self.compile( - source_file, object_file, flags=flags, cwd=cwd) + source_file, object_file, flags=flags, cwd=cwd, + is_objcxx=is_objcxx) if rc != 0: return cc_cmd, cc_stdout, cc_stderr, rc link_cmd, link_stdout, link_stderr, rc = self.link( - object_file, out=out, flags=flags, cwd=cwd) + object_file, out=out, flags=flags, cwd=cwd, is_objcxx=is_objcxx) return (cc_cmd + ['&&'] + link_cmd, cc_stdout + link_stdout, cc_stderr + link_stderr, rc) Index: utils/libcxx/test/config.py =================================================================== --- utils/libcxx/test/config.py +++ utils/libcxx/test/config.py @@ -462,6 +462,12 @@ self.config.available_features.add('glibc-%s' % maj_v) self.config.available_features.add('glibc-%s.%s' % (maj_v, min_v)) + # Support Objective-C++ only on MacOS and if the compiler supports it. + if not self.target_info.platform() == "darwin" or \ + not self.target_info.is_host_macosx() or \ + not self.cxx.hasCompileFlag(["-x", "objective-c++", "-fobjc-arc"]): + self.config.available_features.add("no-objective-cxx") + def configure_compile_flags(self): no_default_flags = self.get_lit_bool('no_default_flags', False) if not no_default_flags: Index: utils/libcxx/test/format.py =================================================================== --- utils/libcxx/test/format.py +++ utils/libcxx/test/format.py @@ -87,9 +87,10 @@ name_root, name_ext = os.path.splitext(name) is_libcxx_test = test.path_in_suite[0] == 'libcxx' is_sh_test = name_root.endswith('.sh') - is_pass_test = name.endswith('.pass.cpp') - is_fail_test = name.endswith('.fail.cpp') - assert is_sh_test or name_ext == '.cpp', 'non-cpp file must be sh test' + is_pass_test = name.endswith('.pass.cpp') or name.endswith('.pass.mm') + is_fail_test = name.endswith('.fail.cpp') or name.endswith('.fail.mm') + assert is_sh_test or name_ext == '.cpp' or name_ext == '.mm', \ + 'non-cpp file must be sh test' if test.config.unsupported: return (lit.Test.UNSUPPORTED, @@ -133,6 +134,8 @@ if '#define _LIBCPP_ASSERT' in contents: test_cxx.useModules(False) + is_objcxx = name_ext == '.mm' + # Dispatch the test based on its suffix. if is_sh_test: if not isinstance(self.executor, LocalExecutor): @@ -144,10 +147,10 @@ self.execute_external, script, tmpBase) elif is_fail_test: - return self._evaluate_fail_test(test, test_cxx, parsers) + return self._evaluate_fail_test(test, test_cxx, parsers, is_objcxx) elif is_pass_test: return self._evaluate_pass_test(test, tmpBase, lit_config, - test_cxx, parsers) + test_cxx, parsers, is_objcxx) else: # No other test type is supported assert False @@ -156,7 +159,7 @@ libcxx.util.cleanFile(exec_path) def _evaluate_pass_test(self, test, tmpBase, lit_config, - test_cxx, parsers): + test_cxx, parsers, is_objcxx): execDir = os.path.dirname(test.getExecPath()) source_path = test.getSourcePath() exec_path = tmpBase + '.exe' @@ -166,8 +169,8 @@ try: # Compile the test cmd, out, err, rc = test_cxx.compileLinkTwoSteps( - source_path, out=exec_path, object_file=object_path, - cwd=execDir) + source_path, is_objcxx=is_objcxx, out=exec_path, + object_file=object_path, cwd=execDir) compile_cmd = cmd if rc != 0: report = libcxx.util.makeReport(cmd, out, err, rc) @@ -206,7 +209,7 @@ libcxx.util.cleanFile(object_path) self._clean(exec_path) - def _evaluate_fail_test(self, test, test_cxx, parsers): + def _evaluate_fail_test(self, test, test_cxx, parsers, is_objcxx): source_path = test.getSourcePath() # FIXME: lift this detection into LLVM/LIT. with open(source_path, 'r') as f: @@ -227,7 +230,8 @@ if '-Wuser-defined-warnings' in test_cxx.warning_flags: test_cxx.warning_flags += ['-Wno-error=user-defined-warnings'] - cmd, out, err, rc = test_cxx.compile(source_path, out=os.devnull) + cmd, out, err, rc = test_cxx.compile(source_path, out=os.devnull, + is_objcxx=is_objcxx) expected_rc = 0 if use_verify else 1 if rc == expected_rc: return lit.Test.PASS, ''