
The weirdest bug I’ve found in a compiler: MSVC 2017 - ingve
https://medium.com/@ryanhaining/the-weirdest-error-ive-found-in-a-compiler-msvc-2017-ade2e9da0e20
======
TwoBit
I found years ago that (at least with older versions) VC++ implemented
templates essentially as internally generated macros. All the non-standard
behaviour they had could be explainined by considering how they would act if
they were macros. This bug strikes me as being consistent with that. T is
leaking across structs because it is internally #defined and seen by another
struct.

I think Microsoft has managed to prop up this massive template-as-macro hack
all the way through VS 2017.

~~~
TwoBit
I just found this statement from Microsoft:

[https://blogs.msdn.microsoft.com/vcblog/2017/09/11/two-
phase...](https://blogs.msdn.microsoft.com/vcblog/2017/09/11/two-phase-name-
lookup-support-comes-to-msvc/)

"MSVC previously recorded the body of the template as a stream of tokens and
stored that stream away to be replayed at instantiation time. The behavior of
MSVC’s template substitution from a recorded token stream somewhat resembled
the behavior of macro substitution in that limited analysis was done of a
template’s body."

~~~
userbinator
As someone who is admittedly not an expert in template metaprogramming by any
means, thinking of templates as an extension of macros feels like the
intuitive and simpler way compared to the more complex two-phase algorithm, so
it's no surprise that MSVC did it too... then again, I prefer simpler
languages (like C) and see the difficulty of implementing the standard as a
sign that its complexity may be too high.

~~~
TwoBit
There's a reason why templates work like this. If they didn't work like this
then template specializations that you write can break somebody else's code
which is dependent on the template behaving a certain way.

------
multani
I tried remember reading an article on HN a couple of years ago about how MSVC
got initial C++ support and added more and more features over time, despite
having _not_ being designed with C++ in mind originally. The result was a
combination of clever hacks after clever hacks, with the consequence being the
reputation MSVC got over time (I'm not saying this is one the consequence
shown in the OP)

Anyway, does anybody still have this article somewhere? I couldn't find it
anymore :(

~~~
scarface74
I'm a two decade Windows developer so this isn't a "M$ Sucks" comment, but
Windows itself is a series of hack on top of hack because Microsoft refuses to
break backwards compatibility.

As much as MS had the reputation of "Windows isn't done until Lotus won't run"
back in the day. If you follow some of the MSDN blogs, you'll find the
extraordinary hacks that MS has done over the years to keep the most obscure
programs running.

People complain about how Apple will drop support for backwards compatibility
but this a consequence of the MS culture of doing just the opposite.

~~~
justonepost
There’s a very good business in maintaining backwards compatibility. Any large
enterprise is not going to buy from a company that they can’t rely on having a
roadmap that will fix security issues but won’t break their deployed software.

~~~
realusername
Most software on Linux is backward compatible as well, you can get some 90s
software, compile it and run it, however it does not have as many hacks as
Windows has at the moment to achieve that.

~~~
userbinator
_you can get some 90s software, compile it and run it,_

The "compile" is the tricky part; with Windows, you can get a binary from the
early 90s and it will just run. My experience with Linux software is that
while the kernel-userspace interface remains stable, userspace is itself full
of breaking changes, and software has so many dependencies that trying to
compile it quickly turns hairy.

~~~
iforgotpassword
Make that 1985 for windows 1.0

Can't find the site again, but someone figured out you can use an older
version of the Borland resource editor to convert the embedded resources to a
newer format, than patch the exe header to say it's a windows 2.0 binary and
it will run even on windows 10 (32bit version only since of obviously needs
the 16bit subsystem).

I was seriously impressed when I saw that.

~~~
digi_owl
> 32bit version only since of obviously needs the 16bit subsystem

And afaik, MS only retired the 16-bit subsystem because AMD64 can't switch
between 64 and 16 bit modes. You can either run it in 16/32 or 32/64 modes,
but not 16/32/64.

~~~
userbinator
Not really: [https://www.dkia.at/en/node/180](https://www.dkia.at/en/node/180)

 _Interesting enough you can still mark a code segment as 16 Bit and the CPU
will execute it in 16 Bit mode._

[https://www.wine-staging.com/news/2016-02-10-blog-
wine-16bit...](https://www.wine-staging.com/news/2016-02-10-blog-
wine-16bit.html)

 _The tricky part is that a LDT entry also contains flags which define if a
segment contains 16 bit, 32 bit or 64 bit code. If you change to a segment,
the CPU will automatically start interpreting the code inside the segment
according to this value._

In other words, 16, 32, and 64-bit code can all coexist simultaneously and the
CPU can switch between those automatically --- MS just decided not to
implement it. Linux with WINE does, however.

------
acqq

       template <typename U>
       using func_type = decltype(U{}.func());
    

I admit I'm not following all the new stuff that is added to C++. What are
that two lines supposed to mean? I don't know what the U{}.func() and using x
= decltype() constructs should mean or their names.

The names of these and links highly appreciated. Thanks.

Moreover, regarding the "bug": if "U" is actually special as an identifier
(e.g. some predefined macro or something) it's a pity that the author hasn't
investigated a little more. Even not knowing the meaning of the lines I've
quoted, the symptoms look somewhat familiar to me with these "special
behaviors" of identifiers.

~~~
jchw
Didn't you read the rest of the article? They tested with arguments with
different names. Further they showed that T was accessible from within the
other template when it didn't have a template parameter T, making this even
more bizarre.

Also, just to be completely sure, I tested it myself.

Using X: [https://godbolt.org/g/B9YEgZ](https://godbolt.org/g/B9YEgZ)

Showing the template parameter leaking with neither T nor U:
[https://godbolt.org/g/CKe2wG](https://godbolt.org/g/CKe2wG)

~~~
jchw
Sheesh, I'm not exactly obsessed with internet points but I am kinda curious
why I got so downvoted. I wasn't really trying to be condescending, but the
article kinda does answer this concern (regarding U being reserved) in a
couple ways.

~~~
mdip
At risk of being downvoted, myself, as this is off-topic, but since there is
no 'meta' and you're clearly looking to understand what happened, I suspect
the issue originates in the first statement made from the original comment,
which was posed in the form of a question:

    
    
        Didn't you read the rest of the article?
    

My rule of thumb is that if a question can have ", moron?"[0] appended to it
and _both_ the meaning and tone remain unchanged, then it's going to be taken
as condescending. You'll probably find that people who are particularly
sensitive to keeping Hacker News a "civil place" (among which I count myself)
will read that sentence and skip the rest of the comment before hitting the
downvote button. Had it been left off, the rest of your comment offered
clarity to anyone who simply skimmed the article or otherwise wasn't
understanding what was being presented and might have missed that point.
Removing the sentence also doesn't affect the information being conveyed[1].

While I'll take you at your word that it wasn't meant as condescending, a
variant of Hanlon's Razor[2] applies which I had shared with me as "Where
there are gaps of understanding, people tend to jump to the worst possible
conclusion." and this serves as a pretty good example. You assumed the reader
didn't bother to read the article, when it was equally likely that they simply
didn't understand what was being presented -- a fair estimate since this is
C++ templates, which is not something everyone encounters in their day-to-day.
And folks who are able to downvote likely did so because they assumed you were
being condescending, when it's equally likely that you may have simply written
the comment hastily or meant the question in a less-sarcastically sounding
manner -- a fair estimate since verbal queues are missing from written text
and most of us type near the speed that we think.

[0] Or "dumba$$" or "?, God!" (followed by a gesture of hands being thrown
down in disgust)

[1] I once had a great manager who, at a yearly feedback session, told me
rather bluntly that I am too verbose and worked with me on how to convey a
message by learning what is _unnecessary_ for conveying it. As you can tell if
you glance through my comment history, the lesson was _entirely_ lost on me.
While I'm much better at eliminating things that add negativity to my intent
(often by adding _more_ to my statements), I'm pretty terrible at identifying
when brevity has higher value than precision and completeness. Though, when it
really matters, I can pull it together if I take enough time... and on and on
and on.

[2]
[https://en.wikipedia.org/wiki/Hanlon%27s_razor](https://en.wikipedia.org/wiki/Hanlon%27s_razor)

~~~
jchw
Fair enough, I can just remove that sentence I suppose. ¯\\_(ツ)_/¯

The internet is a fickle mistress.

edit: Nevermind, I can't. Guess the edit threshold is somewhere under 2 hours.
Oh well.

~~~
jacquesm
It's one hour. And deletions work until someone comments or one hour has
passed.

------
jwilk
Copy of the article that works with JS disabled:

[https://gist.github.com/jwilk/b9f9142f204dfa634d3ec338af9172...](https://gist.github.com/jwilk/b9f9142f204dfa634d3ec338af917232)

------
TillE
I've crashed MSVC 15.7 repeatedly while writing templates - usually due to an
error in my code, but sometimes on valid code. I really do appreciate that
Microsoft has been developing their C++ compiler a lot faster than in the
past, but this seems like a buggy release.

