Why `ARGV` got `aa;"bb"` when I call `func("aa";"bb")`?

Why the following code outputs aa;”bb”, instead of aa;bb or “aa”;”bb”?

function(func)
    message("${ARGV}")
endfunction()

func("aa";"bb")

It’s for legacy reasons. Refer the CMake grammar symbol unquoted_argument and the note below it for details. In short, quotes should not be written this way in new CMake code.

What is the logic that makes it aa;"bb" (not expanded as a list, at that!) and not e.g. aa";"bb though? The unquoted_legacy production isn’t actually in the docs except as fairly vague prose, so it’s kind of difficult to tell what actually qualifies and how it gets interpreted. (I get that the idea is that I wouldn’t need to when doing things properly, but I do mess up on, uh, occasion, so it’d be nice to know what to expect.)

It can’t be that any argument that has quotes anywhere that’s not the start or the end (is always treated as a single argument and) has the first matching pair of quotes stripped: I tried a="${B}" by mistake at one point and got a="" for my troubles, so all the quotes that were in the original got passed through.

This is deep in CMake’s history…probably difficult to change it at this point. CMake is not Bash and does not support inner quoting. It’s unclear if the function gets it as two arguments and pastes them together because it is expanded in quotes or it comes as a single argument.