{"id":1397,"date":"2013-05-01T08:52:48","date_gmt":"2013-04-30T20:52:48","guid":{"rendered":"https:\/\/www.deltics.co.nz\/blog\/?p=1397"},"modified":"2013-05-01T08:56:22","modified_gmt":"2013-04-30T20:56:22","slug":"qualified-enum-reference-that-fails-to-compile-in-xe4-and-rightly-so","status":"publish","type":"post","link":"https:\/\/www.deltics.co.nz\/blog\/posts\/1397\/","title":{"rendered":"Qualified Enum Reference That Fails to Compile in XE4 (and rightly so)"},"content":{"rendered":"<span class=\"rt-reading-time\" style=\"display: block;\"><span class=\"rt-label rt-prefix\">[Estimated Reading Time: <\/span> <span class=\"rt-time\">3<\/span> <span class=\"rt-label rt-postfix\">minutes]<\/span><\/span><p>Running through some of my code last night, putting them through the new XE4 compiler, threw up a real oddity:  Some code that used to compile just fine, which no longer compiles in XE4 <em>and which <strong>should not<\/strong> have compiled before<\/em>!<br \/>\n<!--more--><br \/>\nIt&#8217;s an odd one, because the code previously compiled &#8211; and worked &#8211; as intended, and the old &#8220;bug&#8221; that seems to have now been fixed could well have instead been embraced as a feature (although I can understand why it was not and am not suggesting it should have, just observing).<\/p>\n<p>I have to point out at this juncture that there is nothing much to learn from this post I&#8217;m afraid.  It is a bit of a compiler curiosity, that is all.  But even so, I found it interesting and thought others might as well.  And who knows, someone else might have the same problem lurking in their older library code, unbeknownst to them, in which case this might save a bit of head scratching for them.<\/p>\n<p>It involves the referencing of an enum in a unit that is not referenced in the uses clause, where the reference is qualified by the unit name in which the enum is declared and where the unit containing the reference uses some other unit that in turn <em>does<\/em> use the unit that contains the enum.<\/p>\n<p>Got all that ?  Clear as mud ?  \ud83d\ude42<\/p>\n<p>Ok, here&#8217;s the simplest possible test case that will show what I mean.  3 files &#8211; a DPR and 2 units.  Obviously in the real project the DPR and the units involved were a sight more complex (I suspect that the &#8220;error&#8221; crept in during a refactoring where the unit containing the enum was decomposed into 3 smaller units).<\/p>\n<p>In any event, here&#8217;s the sample DPR.  The code doesn&#8217;t do anything, as such, it just exercises the necessary parts of the compiler:<\/p>\n<pre class=\"brush: delphi; title: ; notranslate\" title=\"\">\r\nprogram unused;\r\n\r\nuses\r\n  Foo.Foo in 'Foo.Foo.pas';\r\n\r\nvar\r\n  c: Integer;\r\nbegin\r\n  c := Ord(Foo.enumBAR);\r\nend.\r\n<\/pre>\n<p>Here we can see that the DPR uses the unit <strong>Foo.Foo<\/strong>, but references an enum member &#8211; <strong>enumBAR<\/strong> &#8211; qualified with a <em>different<\/em> unit name, <strong>Foo<\/strong>, which is not being &#8220;used&#8221; at all.<\/p>\n<p>Here is the <strong>Foo.Foo<\/strong> unit:<\/p>\n<pre class=\"brush: delphi; title: ; notranslate\" title=\"\">\r\nunit Foo.Foo;\r\n\r\ninterface\r\n\r\n  uses\r\n    Foo;\r\n\r\nimplementation\r\n\r\nend.\r\n<\/pre>\n<p>And finally the <strong>Foo<\/strong> unit containing the enum declaration with the <strong>enumBAR<\/strong> member:<\/p>\n<pre class=\"brush: delphi; title: ; notranslate\" title=\"\">\r\nunit Foo;\r\n\r\ninterface\r\n\r\n  type\r\n    TEnum = (enumBAR);\r\n\r\nimplementation\r\n\r\nend.\r\n<\/pre>\n<p>This project compiles just fine in Delphi 2010, but fails in XE4 with the compiler complaining about the undeclared &#8220;Foo&#8221; identifier on the line:<\/p>\n<pre class=\"brush: delphi; title: ; notranslate\" title=\"\">\r\n  c:= Ord(Foo.enumBAR);\r\n<\/pre>\n<p>Again, in the actual case in my actual project, the reference was not in the DPR but in another unit in the project.  All units involved were in the DPR uses list, but other than that, the scenario was the same as illustrated by the sample.<\/p>\n<p>The solution is obviously to simply add the required unit to the <strong>uses<\/strong> list, so no great shakes.<\/p>\n<p>I haven&#8217;t tried the sample specifically in other versions of Delphi, but this project has previously been tested in Delphi versions 7 thru XE2, though I cannot honestly recall if it has been tested in those versions since the refactoring that might have led to this situation.  The point being that I think if I were to do that testing, I would find that the behaviour in this area might have changed as a result of the introduction of <strong>SCOPEDENUMS<\/strong> (since this case involves a qualified enum reference, albeit unit qualified rather than type-name qualified).<\/p>\n<p>Obviously whether it existed in any other version of Delphi besides 2010 or not, the previous behaviour was technically wrong.  It should not have been possible to reference members of units that are not being &#8220;used&#8221;.  But then again, given than &#8220;using&#8221; a unit is a formal declaration that brings the contents of that unit into scope, it is arguable that you could conceivably extend the syntax to allow formal qualification of specific members in a unit <em>without<\/em> requiring that unit to be used to bring <em>all<\/em> it&#8217;s members into scope for <strong>un<\/strong>qualified use.<\/p>\n<p>I don&#8217;t think you <em>should<\/em>.  The declaration of which units are being used is useful self-documentation imho.  As I said at the outset, it is interesting to think that it might not (and apparently did not always used to be :)) necessary.<\/p>\n<p>In any event, this code now compiles correctly.  Or, more accurately, correctly fails to compile.  \ud83d\ude42<\/p>\n","protected":false},"excerpt":{"rendered":"<p><span class=\"rt-reading-time\" style=\"display: block;\"><span class=\"rt-label rt-prefix\">[Estimated Reading Time: <\/span> <span class=\"rt-time\">3<\/span> <span class=\"rt-label rt-postfix\">minutes]<\/span><\/span> Running through some of my code last night, putting them through the new XE4 compiler, threw up a real oddity: Some code that used to compile just fine, which no longer compiles in XE4 and which should not have compiled before!<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"jetpack_publicize_message":"","jetpack_is_tweetstorm":false,"jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":[]},"categories":[4,201],"tags":[71,88,203,202],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/p1TKYv-mx","jetpack_sharing_enabled":true,"jetpack-related-posts":[{"id":1425,"url":"https:\/\/www.deltics.co.nz\/blog\/posts\/1425\/","url_meta":{"origin":1397,"position":0},"title":"Changing Your Delphi License Serial Number","date":"03 May 2013","format":false,"excerpt":"Having installed and activated Delphi XE4 using the license available to me from my employer I decided that, despite the very nasty taste left in my mouth, I would pay the $49 required for the XE4 \"hot-fix\" release, albeit only in order to remain with the valid update window now\u2026","rel":"","context":"In &quot;Delphi&quot;","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":2878,"url":"https:\/\/www.deltics.co.nz\/blog\/posts\/2878\/","url_meta":{"origin":1397,"position":1},"title":"Azure DevOps &#8211; Template for Builds + Running Tests and Capturing Results","date":"12 Sep 2019","format":false,"excerpt":"A more complete build script, re-usable in the form of a template, that caters for different Delphi versions, combined with a demonstration of running unit tests and capturing results for reporting and analysis in Azure DevOps Pipelines.","rel":"","context":"In &quot;automation&quot;","img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.deltics.co.nz\/blog\/wp-content\/uploads\/Screen-Shot-2019-09-12-at-14.25.20.jpg?fit=386%2C386&ssl=1&resize=350%2C200","width":350,"height":200},"classes":[]},{"id":1365,"url":"https:\/\/www.deltics.co.nz\/blog\/posts\/1365\/","url_meta":{"origin":1397,"position":2},"title":"XE4 Pricing Revealed","date":"19 Apr 2013","format":false,"excerpt":"Chris Rolliston just posted a link to a video (from Russia) where-in the pricing for XE4 is revealed. All $ amounts mentioned in this article are US $ prices. Your local price may vary depending on how much exchange rate gouging is added on top of the gouging already built\u2026","rel":"","context":"In &quot;Delphi&quot;","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":1554,"url":"https:\/\/www.deltics.co.nz\/blog\/posts\/1554\/","url_meta":{"origin":1397,"position":3},"title":"Not so Special Upgrade Pricing for XE5","date":"12 Sep 2013","format":false,"excerpt":"XE5 is officially out today, and the online store now has pricing for the new release. Being a scant 6 months since XE4 was released, with a $49 special upgrade price for XE3 Pro customers, I looked to see what special price might be on offer for XE5. $499 is\u2026","rel":"","context":"In &quot;Delphi&quot;","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":1392,"url":"https:\/\/www.deltics.co.nz\/blog\/posts\/1392\/","url_meta":{"origin":1397,"position":4},"title":"Adding Insult to Injury","date":"30 Apr 2013","format":false,"excerpt":"Having just installed Delphi XE4 \"Professional\", provided as part of my employer's current SA, the initial \"Welcome\" to the new version, and seemingly the \"baked in\" Start Here landing page invites me to set-up Delphi for iOS development: And this for a product that doesn't actually include this capability because\u2026","rel":"","context":"In &quot;Delphi&quot;","img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.deltics.co.nz\/blog\/wp-content\/uploads\/Screen-Shot-2013-04-30-at-14.31.41.png?resize=350%2C200&ssl=1","width":350,"height":200},"classes":[]},{"id":1414,"url":"https:\/\/www.deltics.co.nz\/blog\/posts\/1414\/","url_meta":{"origin":1397,"position":5},"title":"It&#8217;s a Good Time for NZ Delphi Users to Cross-Grade","date":"02 May 2013","format":false,"excerpt":"Having lost our Delphi reseller in NZ last year, and with the Kiwi dollar riding high against the US dollar, now is a good time to make purchases from online stores operating in US currency. RemObjects has such a store and they also have a cross-grade offer for Delphi customers\u2026","rel":"","context":"In &quot;Delphi&quot;","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]}],"_links":{"self":[{"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/posts\/1397"}],"collection":[{"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/comments?post=1397"}],"version-history":[{"count":5,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/posts\/1397\/revisions"}],"predecessor-version":[{"id":1401,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/posts\/1397\/revisions\/1401"}],"wp:attachment":[{"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/media?parent=1397"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/categories?post=1397"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/tags?post=1397"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}