I would strongly prefer option 1, and would even go beyond just automatically stripping quotes with the current quoting behavior. In particular I’d want to reduce pass specific behavior in argument parsing and instead provide a uniform way that allows you to pass any possible list of strings as arguments to any pass (i.e. any std::vector<std::string>, so including empty strings or strings containing quotes and backslashes). That list of strings should also be the only information the pass gets about the arguments, i.e. any use of quoting or escaping should be invisible to the pass itself.
If the pass interprets the argument in a way that can be a string or something else (e.g. a numeric value or glob pattern), the pass should provide an internal way to disambiguate it (e.g. by using different flags or by using and documenting how to escape strings that would otherwise be interpreted). I do think we should also strive to keep this uniform and share code for handling the list of arguments across passes where it makes sense, but if we clean up how the command line gets turned into a list of arguments, we can address that separately.
From a developers perspective, this reduces complexity because the problem of how to pass a list of strings and the problem of how to interpret that list are entirely decoupled, and the first problem is solved in the same way across all passes. This would also end up simplifying the logic and/or improving the robustness for all code that generates Yosys scripts programmatically, which we have a lot of in the FV tools that build on top of Yosys.
This is also how we deal with this when using TCL scripts. There, the arguments that TCL provides as a const char *argv[] get turned into a std::vector<std::string> which the pass receives as is. I think this is another argument in favor of fully handling basic quoting and escaping for arguments in Yosys scripts outside of a pass, allowing the pass-internal command line handling to make sense for both TCL and Yosys scripts. (It is also possible for a TCL script to provide a full command line as a single string using yosys "pass_name -some arguments", which gets parsed like a Yosys script, but that seems mostly relevant for interpreting user provided commands in a Yosys script compatible way.)
From a users perspective, this is also how it works in Unix shells and in TCL. I expect the vast majority of Yosys users to be quite familiar with either of them and a significant portion even with both. I think that makes a strong UX argument that Yosys should behave similarly. This doesn’t mean we have to use the same rules for quoting and escaping, shell and TCL don’t agree here either, instead we should consider what avoids unnecessary quoting and escaping for commonly used arguments while still handling all corner cases and is easy to remember once you learned about it.
We should also avoid breaking the majority of existing scripts without good reason, but I don’t think concerns about that should get in the way of uniform and complete quoting and escaping of pass arguments. I also expect the things that would break to be relatively easy and straightforward to fix.
Finally, a related anecdote: Windows leaves the command line parsing to the individual program, but the strong influence of Unix on everything of course meant that there was the need to provide APIs that represent the command line arguments as a list of strings. After all even C expects an int main(int argc, char *argv[]).
Windows ended up with at least two APIs providing incompatible implementations of that, but no API to turn a list of strings back into a command line. There’s a ton of code that starts with the assumption that things work as they do in unix or that there is at least something conceptionally equivalent. Eventually such code runs into bugs related to this, often with no good ways to fix things. E.g. Rust’s #91991, #29494, #82227, #44650 and that is with Rust being serious about Windows support, so it’s not for a lack of trying or paying attention to it.
I think any change we make to this that isn’t a complete and well defined way to quote and escape arbitrary string arguments, and that isn’t parsed externally to passes, will lead to just more and more special cases and diverging behavior over time, and we would most likely end up in a similar mess.