Test((dynamic)"abc") is evaluated in its entirety as a dynamic statement. More completely, you could have:
public static string Test(string s) { return s; }
This would be a better overload, so would be selected and executed in preference to the other method.
Or in other words: it can't know whether the return is void without resolving the method-group to a particular signature. And overload resolution is by definition deferred until runtime for a dynamic invoke.
Could it do more analysis? Probably. But the specification does not require it to, so at the absolute most it could be a warning (not an error).