[tint] Wrap accessing argc & argv to remove suppressions
This adds in an utility for converting argc & argv passed into main()
into a tint::Vector of the arguments.
This is done because it is a known issue that accessing the c-style
argv will always cause `-Wunsafe-buffer-usage` to fire, and this
wrapper isolates this known needed suppression into a single location
instead of being scattered across the code base.
This CL cleans up a bunch of main.cc files using this new utility,
though there is a couple exceptions. In remote_compile/main.cc the
suppression is just narrowed, since there is non-main related issues
in that file. There are some other main.cc files, like for the
benchmark tool, that use a different broader suppression that are not
touched.
Bug: 394825124
Change-Id: I92ea0fbc0012ef0900214a1eaefc9fb89a63553d
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/224915
Reviewed-by: dan sinclair <dsinclair@chromium.org>
Auto-Submit: Ryan Harrison <rharrison@chromium.org>
Reviewed-by: James Price <jrprice@google.com>
Commit-Queue: Ryan Harrison <rharrison@chromium.org>
diff --git a/src/tint/cmd/fuzz/ir/as/main.cc b/src/tint/cmd/fuzz/ir/as/main.cc
index a9b6f2b..6d62e38 100644
--- a/src/tint/cmd/fuzz/ir/as/main.cc
+++ b/src/tint/cmd/fuzz/ir/as/main.cc
@@ -39,6 +39,7 @@
#include "src/tint/lang/wgsl/ast/module.h"
#include "src/tint/lang/wgsl/helpers/apply_substitute_overrides.h"
#include "src/tint/lang/wgsl/reader/reader.h"
+#include "src/tint/utils/command/args.h"
#include "src/tint/utils/command/cli.h"
#include "src/tint/utils/containers/transform.h"
#include "src/tint/utils/macros/defer.h"
@@ -51,8 +52,6 @@
#include "src/tint/utils/protos/ir_fuzz/ir_fuzz.pb.h"
TINT_END_DISABLE_PROTOBUF_WARNINGS();
-TINT_BEGIN_DISABLE_WARNING(UNSAFE_BUFFER_USAGE);
-
namespace {
struct Options {
@@ -280,14 +279,7 @@
} // namespace
int main(int argc, const char** argv) {
- tint::Vector<std::string_view, 8> arguments;
- for (int i = 1; i < argc; i++) {
- std::string_view arg(argv[i]);
- if (!arg.empty()) {
- arguments.Push(argv[i]);
- }
- }
-
+ tint::Vector<std::string_view, 8> arguments = tint::args::Vectorize(argc, argv);
Options options;
tint::Initialize();
@@ -341,5 +333,3 @@
return EXIT_SUCCESS;
}
-
-TINT_END_DISABLE_WARNING(UNSAFE_BUFFER_USAGE);
diff --git a/src/tint/cmd/fuzz/ir/dis/main.cc b/src/tint/cmd/fuzz/ir/dis/main.cc
index 9b2e5e5..4923a3e 100644
--- a/src/tint/cmd/fuzz/ir/dis/main.cc
+++ b/src/tint/cmd/fuzz/ir/dis/main.cc
@@ -36,6 +36,7 @@
#include "src/tint/lang/core/ir/disassembler.h"
#include "src/tint/lang/spirv/writer/writer.h"
#include "src/tint/lang/wgsl/writer/writer.h"
+#include "src/tint/utils/command/args.h"
#include "src/tint/utils/command/cli.h"
#include "src/tint/utils/containers/transform.h"
#include "src/tint/utils/macros/defer.h"
@@ -50,8 +51,6 @@
#include "src/tint/utils/protos/ir_fuzz/ir_fuzz.pb.h"
TINT_END_DISABLE_PROTOBUF_WARNINGS();
-TINT_BEGIN_DISABLE_WARNING(UNSAFE_BUFFER_USAGE);
-
namespace {
/// @param data spriv shader to be converted
@@ -386,14 +385,7 @@
} // namespace
int main(int argc, const char** argv) {
- tint::Vector<std::string_view, 8> arguments;
- for (int i = 1; i < argc; i++) {
- std::string_view arg(argv[i]);
- if (!arg.empty()) {
- arguments.Push(argv[i]);
- }
- }
-
+ tint::Vector<std::string_view, 8> arguments = tint::args::Vectorize(argc, argv);
Options options;
tint::Initialize();
@@ -413,5 +405,3 @@
return EXIT_SUCCESS;
}
-
-TINT_END_DISABLE_WARNING(UNSAFE_BUFFER_USAGE);
diff --git a/src/tint/cmd/info/BUILD.bazel b/src/tint/cmd/info/BUILD.bazel
index 36573a1..532bc65 100644
--- a/src/tint/cmd/info/BUILD.bazel
+++ b/src/tint/cmd/info/BUILD.bazel
@@ -55,6 +55,7 @@
"//src/tint/lang/wgsl/program",
"//src/tint/lang/wgsl/sem",
"//src/tint/utils",
+ "//src/tint/utils/command",
"//src/tint/utils/containers",
"//src/tint/utils/diagnostic",
"//src/tint/utils/ice",
diff --git a/src/tint/cmd/info/BUILD.cmake b/src/tint/cmd/info/BUILD.cmake
index c7b8af0..4d83eb8 100644
--- a/src/tint/cmd/info/BUILD.cmake
+++ b/src/tint/cmd/info/BUILD.cmake
@@ -56,6 +56,7 @@
tint_lang_wgsl_program
tint_lang_wgsl_sem
tint_utils
+ tint_utils_command
tint_utils_containers
tint_utils_diagnostic
tint_utils_ice
diff --git a/src/tint/cmd/info/BUILD.gn b/src/tint/cmd/info/BUILD.gn
index 8d245c3..53efac9 100644
--- a/src/tint/cmd/info/BUILD.gn
+++ b/src/tint/cmd/info/BUILD.gn
@@ -57,6 +57,7 @@
"${tint_src_dir}/lang/wgsl/program",
"${tint_src_dir}/lang/wgsl/sem",
"${tint_src_dir}/utils",
+ "${tint_src_dir}/utils/command",
"${tint_src_dir}/utils/containers",
"${tint_src_dir}/utils/diagnostic",
"${tint_src_dir}/utils/ice",
diff --git a/src/tint/cmd/info/main.cc b/src/tint/cmd/info/main.cc
index 7943cb6..73dd517 100644
--- a/src/tint/cmd/info/main.cc
+++ b/src/tint/cmd/info/main.cc
@@ -33,10 +33,9 @@
#include "src/tint/cmd/common/helper.h"
#include "src/tint/lang/core/type/struct.h"
#include "src/tint/lang/wgsl/inspector/entry_point.h"
+#include "src/tint/utils/command/args.h"
#include "src/tint/utils/text/string.h"
-TINT_BEGIN_DISABLE_WARNING(UNSAFE_BUFFER_USAGE);
-
namespace {
struct Options {
@@ -58,9 +57,8 @@
)";
-bool ParseArgs(const std::vector<std::string>& args, Options* opts) {
- for (size_t i = 1; i < args.size(); ++i) {
- const std::string& arg = args[i];
+bool ParseArgs(tint::VectorRef<std::string_view> args, Options* opts) {
+ for (auto arg : args) {
if (arg == "-h" || arg == "--help") {
opts->show_help = true;
} else if (arg == "--json") {
@@ -295,7 +293,7 @@
} // namespace
int main(int argc, const char** argv) {
- std::vector<std::string> args(argv, argv + argc);
+ tint::Vector<std::string_view, 8> args = tint::args::Vectorize(argc, argv);
Options options;
tint::SetInternalCompilerErrorReporter(&tint::cmd::TintInternalCompilerErrorReporter);
@@ -326,5 +324,3 @@
return 0;
}
-
-TINT_END_DISABLE_WARNING(UNSAFE_BUFFER_USAGE);
diff --git a/src/tint/cmd/loopy/BUILD.bazel b/src/tint/cmd/loopy/BUILD.bazel
index 362258f..b4c774c 100644
--- a/src/tint/cmd/loopy/BUILD.bazel
+++ b/src/tint/cmd/loopy/BUILD.bazel
@@ -62,6 +62,7 @@
"//src/tint/lang/wgsl/sem",
"//src/tint/lang/wgsl/writer/ir_to_program",
"//src/tint/utils",
+ "//src/tint/utils/command",
"//src/tint/utils/containers",
"//src/tint/utils/diagnostic",
"//src/tint/utils/ice",
diff --git a/src/tint/cmd/loopy/BUILD.cmake b/src/tint/cmd/loopy/BUILD.cmake
index c1dddb7..d45bb63 100644
--- a/src/tint/cmd/loopy/BUILD.cmake
+++ b/src/tint/cmd/loopy/BUILD.cmake
@@ -63,6 +63,7 @@
tint_lang_wgsl_sem
tint_lang_wgsl_writer_ir_to_program
tint_utils
+ tint_utils_command
tint_utils_containers
tint_utils_diagnostic
tint_utils_ice
diff --git a/src/tint/cmd/loopy/BUILD.gn b/src/tint/cmd/loopy/BUILD.gn
index 28abd46..6eb72be 100644
--- a/src/tint/cmd/loopy/BUILD.gn
+++ b/src/tint/cmd/loopy/BUILD.gn
@@ -64,6 +64,7 @@
"${tint_src_dir}/lang/wgsl/sem",
"${tint_src_dir}/lang/wgsl/writer/ir_to_program",
"${tint_src_dir}/utils",
+ "${tint_src_dir}/utils/command",
"${tint_src_dir}/utils/containers",
"${tint_src_dir}/utils/diagnostic",
"${tint_src_dir}/utils/ice",
diff --git a/src/tint/cmd/loopy/main.cc b/src/tint/cmd/loopy/main.cc
index 57a90e5..19dbef7 100644
--- a/src/tint/cmd/loopy/main.cc
+++ b/src/tint/cmd/loopy/main.cc
@@ -29,6 +29,7 @@
#include "src/tint/api/tint.h"
#include "src/tint/cmd/common/helper.h"
+#include "src/tint/utils/command/args.h"
#if TINT_BUILD_GLSL_WRITER
#include "src/tint/lang/glsl/writer/helpers/generate_bindings.h"
@@ -64,8 +65,6 @@
#include "src/tint/lang/wgsl/writer/writer.h"
#endif // TINT_BUILD_WGSL_WRITER
-TINT_BEGIN_DISABLE_WARNING(UNSAFE_BUFFER_USAGE);
-
namespace {
enum class Format {
@@ -102,7 +101,7 @@
--loop-count <num> -- Number of loops to run, default 100.
)";
-Format parse_format(const std::string& fmt) {
+Format parse_format(const std::string_view fmt) {
(void)fmt;
#if TINT_BUILD_SPV_WRITER
@@ -142,12 +141,12 @@
return Format::kUnknown;
}
-bool ParseArgs(const std::vector<std::string>& args, Options* opts) {
- for (size_t i = 1; i < args.size(); ++i) {
- const std::string& arg = args[i];
+bool ParseArgs(tint::VectorRef<std::string_view> args, Options* opts) {
+ for (size_t i = 1; i < args.Length(); ++i) {
+ auto arg = args[i];
if (arg == "--format") {
++i;
- if (i >= args.size()) {
+ if (i >= args.Length()) {
std::cerr << "Missing value for --format argument.\n";
return false;
}
@@ -161,7 +160,7 @@
opts->show_help = true;
} else if (arg == "--loop") {
++i;
- if (i >= args.size()) {
+ if (i >= args.Length()) {
std::cerr << "Missing value for --loop argument.\n";
return false;
}
@@ -177,11 +176,11 @@
}
} else if (arg == "--loop-count") {
++i;
- if (i >= args.size()) {
+ if (i >= args.Length()) {
std::cerr << "Missing value for --loop-count argument.\n";
return false;
}
- int32_t val = atoi(args[i].c_str());
+ int32_t val = atoi(std::string(args[i]).c_str());
if (val <= 0) {
std::cerr << "Loop count must be greater then 0\n";
return false;
@@ -353,7 +352,7 @@
} // namespace
int main(int argc, const char** argv) {
- std::vector<std::string> args(argv, argv + argc);
+ tint::Vector<std::string_view, 8> args = tint::args::Vectorize(argc, argv);
Options options;
tint::Initialize();
@@ -481,5 +480,3 @@
return 0;
}
-
-TINT_END_DISABLE_WARNING(UNSAFE_BUFFER_USAGE);
diff --git a/src/tint/cmd/remote_compile/BUILD.bazel b/src/tint/cmd/remote_compile/BUILD.bazel
index 7abc45c..ba232a4 100644
--- a/src/tint/cmd/remote_compile/BUILD.bazel
+++ b/src/tint/cmd/remote_compile/BUILD.bazel
@@ -43,7 +43,13 @@
],
deps = [
"//src/tint/utils",
+ "//src/tint/utils/command",
+ "//src/tint/utils/containers",
+ "//src/tint/utils/ice",
"//src/tint/utils/macros",
+ "//src/tint/utils/math",
+ "//src/tint/utils/memory",
+ "//src/tint/utils/rtti",
"//src/utils",
] + select({
diff --git a/src/tint/cmd/remote_compile/BUILD.cmake b/src/tint/cmd/remote_compile/BUILD.cmake
index 0d00547..23ea113 100644
--- a/src/tint/cmd/remote_compile/BUILD.cmake
+++ b/src/tint/cmd/remote_compile/BUILD.cmake
@@ -44,7 +44,13 @@
tint_target_add_dependencies(tint_cmd_remote_compile_cmd cmd
tint_utils
+ tint_utils_command
+ tint_utils_containers
+ tint_utils_ice
tint_utils_macros
+ tint_utils_math
+ tint_utils_memory
+ tint_utils_rtti
)
tint_target_add_external_dependencies(tint_cmd_remote_compile_cmd cmd
diff --git a/src/tint/cmd/remote_compile/BUILD.gn b/src/tint/cmd/remote_compile/BUILD.gn
index 2f22f2d..dc1f904 100644
--- a/src/tint/cmd/remote_compile/BUILD.gn
+++ b/src/tint/cmd/remote_compile/BUILD.gn
@@ -46,7 +46,13 @@
"${dawn_root}/src/utils:utils",
"${tint_src_dir}:thread",
"${tint_src_dir}/utils",
+ "${tint_src_dir}/utils/command",
+ "${tint_src_dir}/utils/containers",
+ "${tint_src_dir}/utils/ice",
"${tint_src_dir}/utils/macros",
+ "${tint_src_dir}/utils/math",
+ "${tint_src_dir}/utils/memory",
+ "${tint_src_dir}/utils/rtti",
]
if (tint_build_msl_writer) {
diff --git a/src/tint/cmd/remote_compile/main.cc b/src/tint/cmd/remote_compile/main.cc
index 38aa37a..962cc86 100644
--- a/src/tint/cmd/remote_compile/main.cc
+++ b/src/tint/cmd/remote_compile/main.cc
@@ -40,11 +40,10 @@
#include "src/tint/lang/msl/validate/validate.h"
#endif
+#include "src/tint/utils/command/args.h"
#include "src/tint/utils/macros/compiler.h"
#include "src/tint/utils/socket.h"
-TINT_BEGIN_DISABLE_WARNING(UNSAFE_BUFFER_USAGE);
-
namespace {
/// The return structure of a compile function
@@ -158,6 +157,7 @@
return error.empty();
}
+ TINT_BEGIN_DISABLE_WARNING(UNSAFE_BUFFER_USAGE);
bool Read(void* data, size_t size) {
auto buf = reinterpret_cast<uint8_t*>(data);
while (size > 0 && error.empty()) {
@@ -174,6 +174,7 @@
}
return error.empty();
}
+ TINT_END_DISABLE_WARNING(UNSAFE_BUFFER_USAGE);
};
////////////////////////////////////////////////////////////////////////////////
@@ -309,7 +310,7 @@
int version_minor,
bool verbose);
-int main(int argc, char* argv[]) {
+int main(int argc, const char** argv) {
bool run_server = false;
bool verbose = false;
int version_major = 0;
@@ -318,17 +319,18 @@
std::regex metal_version_re{"^-?-std=macos-metal([0-9]+)\\.([0-9]+)"};
- std::vector<std::string> args;
- for (int i = 1; i < argc; i++) {
- std::string arg = argv[i];
+ auto args = tint::args::Vectorize(argc, argv);
+ std::vector<std::string> parsed_args;
+ for (size_t i = 0; i < args.Length(); i++) {
+ std::string arg = std::string(args[i]);
if (arg == "-s" || arg == "--server") {
run_server = true;
continue;
}
if (arg == "-p" || arg == "--port") {
- if (i < argc - 1) {
+ if (i < args.Length() - 1) {
i++;
- port = argv[i];
+ port = args[i];
} else {
printf("expected port number");
exit(1);
@@ -341,13 +343,13 @@
}
// xcrun flags are ignored so this executable can be used as a replacement for xcrun.
- if ((arg == "-x" || arg == "-sdk") && (i < argc - 1)) {
+ if ((arg == "-x" || arg == "-sdk") && (i < args.Length() - 1)) {
i++;
continue;
}
if (arg == "metal") {
- for (; i < argc; i++) {
- arg = argv[i];
+ for (; i < args.Length(); i++) {
+ arg = args[i];
// metal_version_re
std::smatch metal_version_match;
if (std::regex_match(arg, metal_version_match, metal_version_re)) {
@@ -362,7 +364,7 @@
continue;
}
- args.emplace_back(arg);
+ parsed_args.emplace_back(arg);
}
bool success = false;
@@ -372,21 +374,21 @@
} else {
std::string address;
std::string file;
- switch (args.size()) {
+ switch (parsed_args.size()) {
case 1:
TINT_BEGIN_DISABLE_WARNING(DEPRECATED);
if (auto* addr = getenv("TINT_REMOTE_COMPILE_ADDRESS")) {
address = addr;
}
TINT_END_DISABLE_WARNING(DEPRECATED);
- file = args[0];
+ file = parsed_args[0];
break;
case 2:
- address = args[0];
- file = args[1];
+ address = parsed_args[0];
+ file = parsed_args[1];
break;
default:
- std::cerr << "Expected 1 or 2 arguments, got " << args.size() << "\n\n";
+ std::cerr << "Expected 1 or 2 arguments, got " << parsed_args.size() << "\n\n";
ShowUsage();
}
if (address.empty() || file.empty()) {
@@ -532,5 +534,3 @@
}
return true;
}
-
-TINT_END_DISABLE_WARNING(UNSAFE_BUFFER_USAGE);
diff --git a/src/tint/cmd/tint/main.cc b/src/tint/cmd/tint/main.cc
index 7946de5..59057b6 100644
--- a/src/tint/cmd/tint/main.cc
+++ b/src/tint/cmd/tint/main.cc
@@ -33,6 +33,7 @@
#include <unordered_map>
#include <vector>
#include "src/tint/lang/wgsl/sem/variable.h"
+#include "src/tint/utils/command/args.h"
#include "src/tint/utils/text/color_mode.h"
#if TINT_BUILD_SPV_READER || TINT_BUILD_SPV_WRITER
@@ -98,8 +99,6 @@
#include "src/tint/lang/glsl/validate/validate.h"
#endif // TINT_BUILD_GLSL_VALIDATOR
-TINT_BEGIN_DISABLE_WARNING(UNSAFE_BUFFER_USAGE);
-
namespace {
/// Prints the given hash value in a format string that the end-to-end test runner can parse.
@@ -220,6 +219,9 @@
return Format::kUnknown;
}
+// The actual warning occurs on `std::from_chars(hash.data(), hash.data() + hash.size(), value,
+// base);`, but disabling/enabling warnings cannot be done within function scope
+TINT_BEGIN_DISABLE_WARNING(UNSAFE_BUFFER_USAGE);
bool ParseArgs(tint::VectorRef<std::string_view> arguments, Options* opts) {
using namespace tint::cli; // NOLINT(build/namespaces)
@@ -366,6 +368,7 @@
hash = hash.substr(2);
base = 16;
}
+
std::from_chars(hash.data(), hash.data() + hash.size(), value, base);
opts->skip_hash.emplace(value);
}
@@ -589,6 +592,7 @@
return true;
}
+TINT_END_DISABLE_WARNING(UNSAFE_BUFFER_USAGE);
[[maybe_unused]] void AddRenamer(Options& options,
tint::ast::transform::Manager& transform_manager,
@@ -1290,14 +1294,7 @@
} // namespace
int main(int argc, const char** argv) {
- tint::Vector<std::string_view, 8> arguments;
- for (int i = 1; i < argc; i++) {
- std::string_view arg(argv[i]);
- if (!arg.empty()) {
- arguments.Push(argv[i]);
- }
- }
-
+ tint::Vector<std::string_view, 8> arguments = tint::args::Vectorize(argc, argv);
Options options;
tint::Initialize();
@@ -1434,5 +1431,3 @@
}
return success ? 0 : 1;
}
-
-TINT_END_DISABLE_WARNING(UNSAFE_BUFFER_USAGE);
diff --git a/src/tint/utils/command/BUILD.bazel b/src/tint/utils/command/BUILD.bazel
index 95d839e..4d8aecb 100644
--- a/src/tint/utils/command/BUILD.bazel
+++ b/src/tint/utils/command/BUILD.bazel
@@ -39,6 +39,7 @@
cc_library(
name = "command",
srcs = [
+ "args.cc",
"cli.cc",
] + select({
":_not_tint_build_is_linux__and__not_tint_build_is_mac__and__not_tint_build_is_win_": [
@@ -57,6 +58,7 @@
"//conditions:default": [],
}),
hdrs = [
+ "args.h",
"cli.h",
"command.h",
],
diff --git a/src/tint/utils/command/BUILD.cmake b/src/tint/utils/command/BUILD.cmake
index 6724b16..8d730ef 100644
--- a/src/tint/utils/command/BUILD.cmake
+++ b/src/tint/utils/command/BUILD.cmake
@@ -39,6 +39,8 @@
# Kind: lib
################################################################################
tint_add_target(tint_utils_command lib
+ utils/command/args.cc
+ utils/command/args.h
utils/command/cli.cc
utils/command/cli.h
utils/command/command.h
diff --git a/src/tint/utils/command/BUILD.gn b/src/tint/utils/command/BUILD.gn
index 03e801a..86a0acb 100644
--- a/src/tint/utils/command/BUILD.gn
+++ b/src/tint/utils/command/BUILD.gn
@@ -45,6 +45,8 @@
libtint_source_set("command") {
sources = [
+ "args.cc",
+ "args.h",
"cli.cc",
"cli.h",
"command.h",
diff --git a/src/tint/utils/command/args.cc b/src/tint/utils/command/args.cc
new file mode 100644
index 0000000..fb91a47
--- /dev/null
+++ b/src/tint/utils/command/args.cc
@@ -0,0 +1,46 @@
+// Copyright 2025 The Dawn & Tint Authors
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this
+// list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+//
+// 3. Neither the name of the copyright holder nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "src/tint/utils/command/args.h"
+
+namespace tint::args {
+
+// Working with argv is known to always cause this warning to fire
+TINT_BEGIN_DISABLE_WARNING(UNSAFE_BUFFER_USAGE);
+tint::Vector<std::string_view, 8> Vectorize(int argc, const char** argv) {
+ tint::Vector<std::string_view, 8> arguments;
+ for (int i = 1; i < argc; i++) {
+ std::string_view arg(argv[i]);
+ if (!arg.empty()) {
+ arguments.Push(argv[i]);
+ }
+ }
+ return arguments;
+}
+TINT_END_DISABLE_WARNING(UNSAFE_BUFFER_USAGE);
+
+} // namespace tint::args
diff --git a/src/tint/utils/command/args.h b/src/tint/utils/command/args.h
new file mode 100644
index 0000000..dceb4e5
--- /dev/null
+++ b/src/tint/utils/command/args.h
@@ -0,0 +1,46 @@
+// Copyright 2025 The Dawn & Tint Authors
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this
+// list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+//
+// 3. Neither the name of the copyright holder nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef SRC_TINT_UTILS_COMMAND_ARGS_H_
+#define SRC_TINT_UTILS_COMMAND_ARGS_H_
+
+#include <string>
+
+#include "src/tint/utils/containers/vector.h"
+
+namespace tint::args {
+
+/// Converts the c-style program arguments into a safer C++ style vector.
+/// Note: This is done to isolate code that is known to cause compiler warnings to a single location
+/// @param argc number of arguments supplied to program, |argc| in main()
+/// @param argv array of argument strings supplied to program, |argv| in main()
+/// @returns a vector of string_views containing the argument strings
+tint::Vector<std::string_view, 8> Vectorize(int argc, const char** argv);
+
+} // namespace tint::args
+
+#endif // SRC_TINT_UTILS_COMMAND_ARGS_H_