{"id":110614,"date":"2024-12-06T07:00:00","date_gmt":"2024-12-06T15:00:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/oldnewthing\/?p=110614"},"modified":"2024-12-09T22:30:02","modified_gmt":"2024-12-10T06:30:02","slug":"20241206-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20241206-00\/?p=110614","title":{"rendered":"Learning to read C++ compiler errors: Nonsensical errors from a function declaration"},"content":{"rendered":"<p>A customer wanted to add XAML support to their application, so they included (among other things) the header file <tt>winrt\/Windows.UI.Xaml.h<\/tt>. But the mere act of including that header file produced a horrible series of errors that began with.<\/p>\n<pre style=\"white-space: pre-wrap;\">winrt\\impl\\Windows.UI.Xaml.0.h(4323,28): warning C4003: not enough arguments for function-like macro invocation 'ErrorMessage'\r\nwinrt\\impl\\Windows.UI.Xaml.0.h(4323,28): error C2146: syntax error: missing ')' before identifier 'ErrorMessageString'\r\nwinrt\\impl\\Windows.UI.Xaml.0.h(4323,28): error C3646: 'ErrorMessageString': unknown override specifier\r\nwinrt\\impl\\Windows.UI.Xaml.0.h(4323,28): error C2059: syntax error: ')'\r\nwinrt\\impl\\Windows.UI.Xaml.0.h(4323,48): error C2238: unexpected token(s) preceding ';'\r\n<\/pre>\n<p>What&#8217;s going on?<\/p>\n<p>The errors are coming from the following line of code:<\/p>\n<pre>    template &lt;typename D&gt;\r\n    struct consume_Windows_UI_Xaml_IExceptionRoutedEventArgs\r\n    {\r\n        <span style=\"border: solid 1px currentcolor;\">[[nodiscard]] auto ErrorMessage() const;<\/span>\r\n    };\r\n<\/pre>\n<p>That line of code looks like a perfectly fine method declaration. Why is the compiler upset?<\/p>\n<p>Look closely at the first error message.<\/p>\n<pre style=\"white-space: pre-wrap;\">not enough arguments for function-like macro invocation 'ErrorMessage'\r\n<\/pre>\n<p>Wait a second, &#8220;function-like macro invocation&#8221;? This says that the compiler thinks you&#8217;re trying to use a macro called <code>ErrorMessage<\/code>.\u00b9<\/p>\n<p>We suspected that the developer had a macro named <code>ErrorMessage<\/code> elsewhere in their project, and that was conflicting with the method name. And with some help from the customer, we found it.<\/p>\n<pre>\/\/ Produces the error text for an HRESULT.\r\nstruct ErrorMessageString\r\n{\r\n    ErrorMessageString(HRESULT hr);\r\n    operator PCWSTR() { return (PCWSTR)m_errorMessage; }\r\n    CStringW m_errorMessage;\r\n};\r\n\r\n#define ErrorMessage(hr) ((PCWSTR)ErrorMessageString(hr))\r\n<\/pre>\n<p><b>Bonus reading<\/b>: <a href=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/20211206-00\/?p=106002\"> Compiler error message metaprogramming: Helping to find the conflicting macro definition<\/a><\/p>\n<p>The <code>ErrorMessage<\/code> macro creates an <code>Error\u00adMessage\u00adString<\/code> object whose constructor looks up the error message string associated with the provided <code>HRESULT<\/code>, and then forces it to produce a string pointer. Evidently, the intended purpose is to use it something like this:<\/p>\n<pre>LogMessage(L\"Problem toggling the widget\", ErrorMessage(hr));\r\n<\/pre>\n<p>Macros have no respect for boundaries. The C++\/WinRT header file is trying to declare a method named <code>Error\u00adMessage()<\/code>, and the macro steps in and says &#8220;I&#8217;ll take care of that!&#8221; It then sees that the code provides no parameters, but the macro requires one parameter, so you get the &#8220;not enough arguments&#8221; error. And then the compiler shrugs its shoulders and says, &#8220;Eh, I&#8217;ll just substitute it anyway,&#8221; and you end up with<\/p>\n<pre>    template &lt;typename D&gt;\r\n    struct consume_Windows_UI_Xaml_IExceptionRoutedEventArgs\r\n    {\r\n        [[nodiscard]] auto <span style=\"border: solid 1px currentcolor;\">((PCWSTR)ErrorMessageString())<\/span> const;\r\n    };\r\n<\/pre>\n<p>This is nonsense, and the cascade errors are a bunch of error messages telling you how nonsensical this is.<\/p>\n<p>One solution is to remove the macro when including the troublesome header file.<\/p>\n<pre>#pragma push_macro(\"ErrorMessage\")\r\n#undef ErrorMessage\r\n#pragma push_macro(\"GetCurrentTime\")\r\n#undef GetCurrentTime\r\n#pragma push_macro(\"TRY\")\r\n#undef TRY\r\n#include &lt;winrt\/Windows.UI.Xaml.h&gt;\r\n\u27e6 other C++\/WinRT headers ... \u27e7\r\n#pragma pop_macro(\"TRY\")\r\n#pragma pop_macro(\"GetCurrentTime\")\r\n#pragma pop_macro(\"ErrorMessage\")\r\n<\/pre>\n<p>I pre-emptively added <code>Get\u00adCurrent\u00adTime<\/code> and <code>TRY<\/code> because <a href=\"https:\/\/learn.microsoft.com\/en-us\/windows\/uwp\/cpp-and-winrt-apis\/faq#how-do-i-resolve-ambiguities-with-getcurrenttime-and-or-try-\"> you&#8217;re going to run into that problem really soon<\/a>, so we may as well take care of it now.<\/p>\n<p><b>Bonus reading<\/b>: <a href=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/20190912-00\/?p=102855\"> The Turkish lira&#8217;s currency code is an unexpected source of problems with computer programmers<\/a>.<\/p>\n<p><span style=\"text-decoration: line-through;\">A better solution is simply to get rid of the macro.<\/span><\/p>\n<pre>\/\/ Don't use this. It returns a dangling pointer.\r\n<span style=\"text-decoration: line-through;\">inline PCWSTR ErrorMessage(HRESULT hr) { return (PCWSTR)ErrorMessageString(hr); }<\/span>\r\n<\/pre>\n<p>\u00b9 A &#8220;function-like&#8221; macro is one that is defined with a parenthesized parameter list, possibly empty.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Look closely at what the error message is complaining about.<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[25],"class_list":["post-110614","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Look closely at what the error message is complaining about.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/110614","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=110614"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/110614\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=110614"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=110614"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=110614"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}