[libcxx-commits] [libcxx] [libc++] Add a utility for checking the output of commands (PR #65917)
Nikolas Klauser via libcxx-commits
libcxx-commits at lists.llvm.org
Mon Jan 20 08:56:31 PST 2025
https://github.com/philnik777 updated https://github.com/llvm/llvm-project/pull/65917
>From a6f8e24078f25f2164bf4261e603aa69c492f9ca Mon Sep 17 00:00:00 2001
From: Nikolas Klauser <nikolasklauser at berlin.de>
Date: Wed, 6 Sep 2023 08:31:36 -0700
Subject: [PATCH] [libc++] Add a utility for checking the output of commands
---
libcxx/test/configs/cmake-bridge.cfg.in | 1 +
.../copy_move_codegen.sh.cpp | 21 +++
.../clang_tidy/proper_version_checks.sh.cpp | 29 ++++
.../utility.unreachable.codegen.sh.cpp | 22 +++
libcxx/test/tools/CMakeLists.txt | 6 +-
libcxx/test/tools/check_output/CMakeLists.txt | 15 ++
.../test/tools/check_output/check_output.cpp | 129 ++++++++++++++++++
.../proper_version_checks.cpp | 2 -
8 files changed, 221 insertions(+), 4 deletions(-)
create mode 100644 libcxx/test/libcxx/algorithms/alg.modifying.operations/copy_move_codegen.sh.cpp
create mode 100644 libcxx/test/libcxx/selftest/clang_tidy/proper_version_checks.sh.cpp
create mode 100644 libcxx/test/libcxx/utilities/utility/utility.unreachable.codegen.sh.cpp
create mode 100644 libcxx/test/tools/check_output/CMakeLists.txt
create mode 100644 libcxx/test/tools/check_output/check_output.cpp
diff --git a/libcxx/test/configs/cmake-bridge.cfg.in b/libcxx/test/configs/cmake-bridge.cfg.in
index 61f821a7e4f6b8..3bbd1356ad20da 100644
--- a/libcxx/test/configs/cmake-bridge.cfg.in
+++ b/libcxx/test/configs/cmake-bridge.cfg.in
@@ -31,3 +31,4 @@ config.substitutions.append(('%{lib-dir}', '@LIBCXX_TESTING_INSTALL_PREFIX@/@LIB
config.substitutions.append(('%{module-dir}', '@LIBCXX_TESTING_INSTALL_PREFIX@/@LIBCXX_INSTALL_MODULES_DIR@'))
config.substitutions.append(('%{test-tools-dir}', '@LIBCXX_TEST_TOOLS_PATH@'))
config.substitutions.append(('%{benchmark_flags}', '-I @LIBCXX_BINARY_DIR@/test/benchmarks/google-benchmark/include -L @LIBCXX_BINARY_DIR@/test/benchmarks/google-benchmark/lib -L @LIBCXX_BINARY_DIR@/test/benchmarks/google-benchmark/lib64 -l benchmark'))
+config.substitutions.append(('%{check-output}', os.path.join('@LIBCXX_BINARY_DIR@', 'bin/check_output') + " %s"))
diff --git a/libcxx/test/libcxx/algorithms/alg.modifying.operations/copy_move_codegen.sh.cpp b/libcxx/test/libcxx/algorithms/alg.modifying.operations/copy_move_codegen.sh.cpp
new file mode 100644
index 00000000000000..f1a59c6ab0bc46
--- /dev/null
+++ b/libcxx/test/libcxx/algorithms/alg.modifying.operations/copy_move_codegen.sh.cpp
@@ -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
+//
+//===----------------------------------------------------------------------===//
+
+// This test is checking the LLVM IR
+// REQUIRES: clang
+
+// RUN: %{cxx} %s %{compile_flags} -O3 -c -S -emit-llvm -o - | %{check-output}
+
+#include <algorithm>
+
+int* test1(int* first, int* last, int* out) {
+ // CHECK: define
+ // CHECK-SAME: test1
+ // CHECK: tail call void @llvm.memmove
+ return std::copy(first, last, out);
+}
diff --git a/libcxx/test/libcxx/selftest/clang_tidy/proper_version_checks.sh.cpp b/libcxx/test/libcxx/selftest/clang_tidy/proper_version_checks.sh.cpp
new file mode 100644
index 00000000000000..54071dcc7f1698
--- /dev/null
+++ b/libcxx/test/libcxx/selftest/clang_tidy/proper_version_checks.sh.cpp
@@ -0,0 +1,29 @@
+//===----------------------------------------------------------------------===//
+//
+// 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: has-clang-tidy
+
+// RUN: %{clang-tidy} %s -header-filter=.* --checks='-*,libcpp-cpp-version-check' --load=%{test-tools-dir}/clang_tidy_checks/libcxx-tidy.plugin -- %{compile_flags} -fno-modules 2>&1 | %{check-output}
+
+#include <__config>
+
+// CHECK: warning: _LIBCPP_STD_VER >= version should be used instead of _LIBCPP_STD_VER > prev_version
+#if _LIBCPP_STD_VER > 14
+#endif
+
+// CHECK: warning: Use _LIBCPP_STD_VER instead of __cplusplus to constrain based on the C++ version
+#if __cplusplus >= 201103L
+#endif
+
+// CHECK: warning: _LIBCPP_STD_VER >= 11 is always true. Did you mean '#ifndef _LIBCPP_CXX03_LANG'?
+#if _LIBCPP_STD_VER >= 11
+#endif
+
+// CHECK: warning: Not a valid value for _LIBCPP_STD_VER. Use 14, 17, 20, 23, or 26
+#if _LIBCPP_STD_VER >= 12
+#endif
diff --git a/libcxx/test/libcxx/utilities/utility/utility.unreachable.codegen.sh.cpp b/libcxx/test/libcxx/utilities/utility/utility.unreachable.codegen.sh.cpp
new file mode 100644
index 00000000000000..0003f6734bbdcd
--- /dev/null
+++ b/libcxx/test/libcxx/utilities/utility/utility.unreachable.codegen.sh.cpp
@@ -0,0 +1,22 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// This test is checking the LLVM IR
+// REQUIRES: clang
+
+// RUN: %{cxx} %s %{compile_flags} -Wno-missing-noreturn -O3 -c -S -emit-llvm -o - | %{check-output}
+
+#include <utility>
+
+void test() {
+ // CHECK: define dso_local void
+ // CHECK-SAME: test
+ // CHECK-NEXT: unreachable
+ // CHECK-NEXT: }
+ std::unreachable();
+}
diff --git a/libcxx/test/tools/CMakeLists.txt b/libcxx/test/tools/CMakeLists.txt
index 6d99c53ad46d9f..d1d7442e99d004 100644
--- a/libcxx/test/tools/CMakeLists.txt
+++ b/libcxx/test/tools/CMakeLists.txt
@@ -3,6 +3,8 @@ set(LIBCXX_TEST_TOOLS_PATH ${CMAKE_CURRENT_BINARY_DIR} PARENT_SCOPE)
if(NOT CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
message(STATUS "Clang-tidy tests are disabled due to non-clang based compiler.")
- return()
+else()
+ add_subdirectory(clang_tidy_checks)
endif()
-add_subdirectory(clang_tidy_checks)
+
+add_subdirectory(check_output)
diff --git a/libcxx/test/tools/check_output/CMakeLists.txt b/libcxx/test/tools/check_output/CMakeLists.txt
new file mode 100644
index 00000000000000..3dd3feee298e66
--- /dev/null
+++ b/libcxx/test/tools/check_output/CMakeLists.txt
@@ -0,0 +1,15 @@
+
+add_executable(check_output check_output.cpp)
+
+# put the binary into <build>/bin
+set_target_properties(check_output PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${LIBCXX_BINARY_DIR}/bin")
+
+# set the language mode
+set_target_properties(check_output PROPERTIES
+ CXX_STANDARD 23
+ CXX_STANDARD_REQUIRED YES
+ CXX_EXTENSIONS NO)
+
+target_compile_options(check_output PRIVATE -Werror=missing-prototypes)
+
+add_dependencies(cxx-test-depends check_output)
diff --git a/libcxx/test/tools/check_output/check_output.cpp b/libcxx/test/tools/check_output/check_output.cpp
new file mode 100644
index 00000000000000..94a84a9e40290b
--- /dev/null
+++ b/libcxx/test/tools/check_output/check_output.cpp
@@ -0,0 +1,129 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include <algorithm>
+#include <fstream>
+#include <functional>
+#include <iostream>
+#include <iterator>
+#include <ranges>
+#include <string>
+
+using namespace std::string_view_literals;
+
+enum class Result {
+ success,
+ mismatch,
+ no_match_found,
+ unknown_matcher,
+ invalid_use,
+};
+
+namespace co {
+namespace {
+[[noreturn]] void exit(Result result) { std::exit(static_cast<int>(result)); }
+
+[[noreturn]] void print_failure(int line, std::string_view stdin_content, std::string_view matcher) {
+ std::cout << "Failed to match: `" << matcher << "`\nRemaining data:\n" << stdin_content << '\n';
+ co::exit(Result::mismatch);
+}
+
+bool is_newline(char c) { return c == '\n'; }
+
+bool isblank(char c) { return std::isblank(c); }
+
+bool consume_front(std::string_view& sv, std::string_view start) {
+ if (!sv.starts_with(start))
+ return false;
+ sv.remove_prefix(start.size());
+ return true;
+}
+} // namespace
+} // namespace co
+
+int main(int argc, char** argv) {
+ if (argc != 2) {
+ std::cerr << "check_output has to be used as `<command> | ./check_output %s`\n";
+ co::exit(Result::invalid_use);
+ }
+
+ std::string file_content_data = [&] {
+ std::ifstream file(argv[1]);
+ if (!file) {
+ std::cerr << "Failed to open file: " << argv[1] << '\n';
+ co::exit(Result::invalid_use);
+ }
+ return std::string{std::istreambuf_iterator<char>{file}, {}};
+ }();
+ std::string_view file_content = file_content_data; // Don't copy the data around all the time
+
+ std::string stdin_content_data = [&] {
+ std::cin >> std::noskipws;
+ return std::string{std::istream_iterator<char>{std::cin}, {}};
+ }();
+ std::string_view stdin_content = stdin_content_data; // Don't copy the data around all the time
+
+ size_t match_count = 0;
+ auto drop_blanks = std::views::drop_while(co::isblank);
+
+ while (!file_content.empty()) {
+ auto marker = std::ranges::search(file_content, "// CHECK"sv);
+ if (marker.empty()) {
+ if (match_count == 0) {
+ std::cerr << "No matcher found!\n";
+ co::exit(Result::no_match_found);
+ }
+ co::exit(Result::success);
+ }
+ file_content.remove_prefix(marker.end() - file_content.begin());
+
+ const auto get_match = [&]() {
+ return std::string_view(file_content.begin(), std::ranges::find(file_content, '\n'));
+ };
+
+ if (co::consume_front(file_content, ":")) {
+ auto match = get_match();
+ auto found = std::ranges::search(
+ stdin_content | std::views::drop_while(std::not_fn(co::is_newline)) | std::views::drop(1),
+ match | drop_blanks);
+ if (found.empty()) {
+ co::print_failure(1, stdin_content, match);
+ }
+ ++match_count;
+ stdin_content.remove_prefix(found.end() - stdin_content.begin());
+ } else if (co::consume_front(file_content, "-SAME:")) {
+ auto match = get_match();
+ auto haystack = std::string_view(stdin_content.begin(), std::ranges::find(stdin_content, '\n'));
+ auto found = std::ranges::search(haystack, match | drop_blanks);
+ if (found.empty()) {
+ co::print_failure(1, stdin_content, match);
+ }
+ stdin_content.remove_prefix(found.end() - stdin_content.begin());
+ } else if (co::consume_front(file_content, "-NEXT:")) {
+ auto match = get_match();
+ auto haystack = [&] {
+ auto begin = std::ranges::find(stdin_content, '\n');
+ if (begin == stdin_content.end()) {
+ co::print_failure(1, stdin_content, match);
+ }
+ ++begin;
+ return std::string_view(begin, std::ranges::find(begin, stdin_content.end(), '\n'));
+ }();
+ auto found = std::ranges::search(haystack, match | drop_blanks);
+ if (found.empty())
+ co::print_failure(1, stdin_content, match);
+ stdin_content.remove_prefix(found.end() - stdin_content.begin());
+ } else {
+ std::cerr << "Unkown matcher type "
+ << std::string_view(file_content.begin(), std::ranges::find(file_content, ':')) << " found\n";
+ co::exit(Result::unknown_matcher);
+ }
+ }
+
+ co::exit(Result::success);
+}
diff --git a/libcxx/test/tools/clang_tidy_checks/proper_version_checks.cpp b/libcxx/test/tools/clang_tidy_checks/proper_version_checks.cpp
index ebd0d8892fa94c..44493824944b04 100644
--- a/libcxx/test/tools/clang_tidy_checks/proper_version_checks.cpp
+++ b/libcxx/test/tools/clang_tidy_checks/proper_version_checks.cpp
@@ -36,8 +36,6 @@ class proper_version_checks_callbacks : public clang::PPCallbacks {
clang::CharSourceRange::getTokenRange(condition_range),
preprocessor_.getSourceManager(),
preprocessor_.getLangOpts());
- if (preprocessor_.getSourceManager().isInMainFile(location))
- return;
if (condition == "__cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS)")
return;
More information about the libcxx-commits
mailing list