1212#include < cstdlib>
1313#include < fmt/core.h>
1414#include < optional>
15+ #include < ranges>
1516#include < spdlog/spdlog.h>
1617#include < string>
1718#include < string_view>
@@ -72,22 +73,27 @@ validateOptLevel(const std::uint8_t optLevel) noexcept {
7273
7374static Result<void >
7475validateFlag (const char * type, const std::string_view flag) noexcept {
75- // cxxflag must start with `-`
76- if (flag.empty () || flag[0 ] != ' -' ) {
77- Bail (" {} must start with `-`" , type);
78- }
76+ Ensure (!flag.empty () && flag[0 ] == ' -' , " {} must start with `-`" , type);
7977
80- // cxxflag only contains alphanumeric characters, `-`, `_`, `=`, `+`, `:`,
81- // or `.`.
78+ static const std::unordered_set<char > allowed{
79+ ' -' , ' _' , ' =' , ' +' , ' :' , ' .' , ' ,' // `-fsanitize=address,undefined`
80+ };
81+ std::unordered_map<char , bool > allowedOnce{
82+ { ' ' , false }, // `-framework Metal`
83+ };
8284 for (const char c : flag) {
83- if (!std::isalnum (c) && c != ' -' && c != ' _' && c != ' =' && c != ' +'
84- && c != ' :' && c != ' .' ) {
85- Bail (
86- " {} must only contain alphanumeric characters, `-`, `_`, `=`, "
87- " `+`, `:`, or `.`" ,
88- type
85+ if (allowedOnce.contains (c)) {
86+ Ensure (
87+ !allowedOnce[c], " {} must only contain {} once" , type,
88+ allowedOnce | std::views::keys
8989 );
90+ allowedOnce[c] = true ;
91+ continue ;
9092 }
93+ Ensure (
94+ std::isalnum (c) || allowed.contains (c),
95+ " {} must only contain {} or alphanumeric characters" , type, allowed
96+ );
9197 }
9298
9399 return Ok ();
@@ -990,6 +996,24 @@ testValidateDepName() {
990996 pass ();
991997}
992998
999+ static void
1000+ testValidateFlag () {
1001+ assertTrue (validateFlag (" cxxflags" , " -fsanitize=address,undefined" ).is_ok ());
1002+
1003+ // issue #1183
1004+ assertTrue (validateFlag (" ldflags" , " -framework Metal" ).is_ok ());
1005+ assertEq (
1006+ validateFlag (" ldflags" , " -framework Metal" ).unwrap_err ()->what (),
1007+ " ldflags must only contain [' '] once"
1008+ );
1009+ assertEq (
1010+ validateFlag (" ldflags" , " -framework Metal && bash" ).unwrap_err ()->what (),
1011+ " ldflags must only contain [' '] once"
1012+ );
1013+
1014+ pass ();
1015+ }
1016+
9931017} // namespace tests
9941018
9951019int
@@ -1002,6 +1026,7 @@ main() {
10021026 tests::testParseProfiles ();
10031027 tests::testLintTryFromToml ();
10041028 tests::testValidateDepName ();
1029+ tests::testValidateFlag ();
10051030}
10061031
10071032#endif
0 commit comments