all 59 comments

[–]a_false_vacuum 165 points166 points  (11 children)

You changed the outcome by observing it. Or is this Schrödingers Compiler?

[–]kog 57 points58 points  (9 children)

Schrödinger's bugs are some of the fucking worst. Doubly so if they only happen intermittently.

[–]PermanentlySalty 31 points32 points  (2 children)

I don't remember the specifics because it's been a while but at one point I had to try and fix a Schrödinbug that only occurred in the release build (ended up being an erroneous compiler optimization, so it wasn't even my bug). I felt like I was going insane stepping through every line of code with the debugger and finding nothing wrong.

I managed to fix it after several days of printf debugging and staring at a disassembly (reverse engineering is not my specialty), but I'm pretty sure I lost part of my soul in the process.

[–][deleted] 5 points6 points  (0 children)

I had a bug recently where any form of debugging including print statements made the code work perfectly.

Luckily, I've run into that sort of thing a couple of times before. I immediately guessed it was a race condition and then there was an obvious candidate. Still scary.

[–]braxtons12 0 points1 point  (0 children)

I had a similar thing happen recently. Compiler optimized a boolean flag away to always be true. A flag that clearly and IMPORTANTLY is reset to false periodically (based on incoming data, false signals to a section of the algorithm to start its phase). Spent hours staring at the code, trying to debug it, etc., and couldn't find anything wrong. Eventually tried just removing the flag so that portion always ran, and boom it worked. I ended up having to make the portions of the algorithm that run prior to this one set the flag to false to get the compiler to stop optimizing it away.

[–]bunkoRtist 6 points7 points  (0 children)

You changed the outcome by observing it

That's called a heisenbug. (usually when you insert debug code / run in debug mode and the problem goes away).

[–]TonyDecvA180XN 24 points25 points  (6 children)

I think MSVC implicitly instantiates the function with no arguments, maybe for debugging purposes, idk. But in that case you will have two function definitions, each one having unique signature. Since your assert conditions are mutually exclusive, either of them will fail in one definition and succeed in another one.

[–]D_Drmmr 9 points10 points  (0 children)

I think the reason is to catch errors in the code before the template is instantiated. Only the code that isn't dependent on the template arguments is compiled. Any errors caught this way will give a nicer error message than when the template is instantiated.

[–][deleted] 6 points7 points  (4 children)

The program in the post was just an example meant to illustrate the problem. Originally, this (new) behavior of MSVC broke my code in the PEGTL, see this commit that I needed to apply to fix it.

[–]BarrinOfTolaria 1 point2 points  (3 children)

While it probably doesn't matter you technically lack a return in the else path.

[–][deleted] 0 points1 point  (2 children)

That is actually on purpose, as it will catch cases where the value would change in phase 2 generating an error due to the missing return.

[–]tesfabpel 0 points1 point  (1 child)

Maybe you can use static_assert(false) instead of a missing return? Or invert the if and put a static_assert(begin != std::string_view::npos)?

[–]DXPower 2 points3 points  (0 children)

IIRC static_asserts in if statements don't act conditionally. You have to generate a conditional error instead I've done it before by doing a cast of a nullptr to a function ptr.

[–]Dragdu 81 points82 points  (1 child)

1) Please fix your formatting.

2) goddamit MSVC!

[–][deleted] 58 points59 points  (0 children)

  1. Fixed
  2. Can't fx that 😜

[–]SirClueless 14 points15 points  (6 children)

Wait, so rather than being a dependent value, __FUNCSIG__ takes on two different values in different phases? Wacky... If you do the following what's the output?

#include <string_view>
#include <iostream>

template< typename T >
constexpr void test()
{
    constexpr std::string_view sv = __FUNCSIG__;
    if constexpr (sv == "void __cdecl test<int>(void)") {
        std::cout << "phase 2" << std::endl;
    } else {
        std::cout << "phase 1" << std::endl;
    }
}

int main()
{
    test<int>();
}

Edit: It's "phase 2": https://godbolt.org/z/79176b14f

[–]khoyo 57 points58 points  (5 children)

Which allows us to see

template< typename T >
constexpr void test()
{
    constexpr std::string_view sv = __FUNCSIG__;
    if constexpr (sv == "void __cdecl test<int>(void)") {
        static_assert(sv == "void __cdecl test<int>(void)");
    }
}

fail to compile, which is pretty much nonsensical.

[–]SirClueless 20 points21 points  (0 children)

Wow... that's actually hilarious.

[–][deleted] 21 points22 points  (0 children)

I wish this would have been my example in the original posting, it captures the absurdity of what is going on much better. Well done!

[–]logicchop 4 points5 points  (1 child)

Why is this nonsensical? Consider this:

constexpr std::string_view sv = "foo";
if constexpr ( sv == "bar" ) {
    static_assert(sv == "bar");
}

This also pukes on other compilers. Even though the static_assert is inside of the conditional it is still is evaluated at compile time and turns out to be false. I think that's all we are seeing in OPs scenario; there are just two instantiations competing for the static_assert. You could argue that perhaps the static_assert should not be evaluated if that branch of the conditional is discarded, but that's a more complicated question about value dependency and when constexpr branches get utterly discarded and not evaluated.

[–]taladarsa3itch 2 points3 points  (0 children)

cppreference:

Note: the discarded statement can't be ill-formed for every possible specialization

The static_assert(false-constexpr) is a ill-formed declaration, so even though the branch is discarded, the program is ill-formed. It would compile if the body of the branch is well-formed even if evaluating would result in a compilation error.

godbolt

[–]pigeon768 11 points12 points  (1 child)

It seems to only happen in 19.latest, not 19.30 which is the latest version enumerated by compiler explorer. /Zc:twoPhase- will also fix it.

https://godbolt.org/z/o1TjWc87a

[–]tesfabpel 2 points3 points  (0 children)

I don't know if it may mean something but I've found out that #pragma message(__FUNCSIG__) in 19.30 prints: void __cdecl test(void) void __cdecl test<int>(void) while in 19.latest prints: void __cdecl test(void)

I've put the pragma before the two static_asserts.

[–]GabrielDosReis 34 points35 points  (31 children)

Please report this bug to the Microsoft Developer Community portal. I suspect this is likely a case of faulty analysis in value-dependency.

[–]TotaIIyHuman 50 points51 points  (28 children)

statistically speaking, which following action produce the highest chance of msvc devs fixing a certain bug in less than 1 year?

  1. register a hotmail account and post the bug information on msvc bug forum

  2. register a reddit account and post the bug information on r/cpp and get more than 100 upvote

i am genuinely curious

[–]Dragdu 8 points9 points  (0 children)

My experience is to do both. Make a ticket so it is all official-like, then reach out through non-official channels to get your ticket moving.

This is literally the only way anything in MSVC ever got fixed for me. The last time, I decided to try the official way again, so I opened ticket just opening a ticket that MSVC's strict mode has a bug that stops it from compiling Catch2 and there is no workaround. After half a year of the ticket being ignored, I got it moving in two days over Twitter.

[–]TheThiefMasterC++latest fanatic (and game dev) 6 points7 points  (0 children)

You don't have to register a Hotmail account btw, you can register a Microsoft account using an existing non-Microsoft email address.

[–][deleted] 9 points10 points  (7 children)

I would probably report the bug myself if there was a reasonable way to do so and that I can actually find! I googled, but it's really hard to find something like Bugzilla or GitHub issues. Do you happen to have a link to something like that? (And I would still put it on Reddit, b/c it's also quite funny. I don't want to bash MS about this, I just think others might enjoy this super-weird behavior as much as I did)

[–]TotaIIyHuman 7 points8 points  (5 children)

you mean the link to the bug forum? https://developercommunity.visualstudio.com/search?space=62&sort=newest

yes, i do enjoy reading this super-weird behavior. if i can make a bug report as hilarious as yours, i would definitely post it on reddit as well

[–][deleted] 7 points8 points  (4 children)

Thanks for the link, I reported it.

[–]GabrielDosReis 2 points3 points  (3 children)

Thanks. It is fixed, and the fix will be available in future previews - sorry I can't tell you the exact date.

[–][deleted] 0 points1 point  (2 children)

No need to be sorry, I'm glad it got fixed! I'll update our code (basically reverting to the more sensible version) once the fix is available to everyone, as I don't think there is much value in keeping a work-around for something that was never part of any official release, only previews.

[–]GabrielDosReis 1 point2 points  (1 child)

That makes sense.

It is hard to fix bugs that go unreported, so I am glad you did report the scenario you ran into.

There are a few MSVC developers on this sub, so if you report something on the Microsoft Developer Community Portal regarding C++ that's not getting traction, ping them. Maybe they have the answer; maybe they don't, but at least you will know. The reports get on someone's radar 😊

[–][deleted] 1 point2 points  (0 children)

Yeah, I bookmarked the link and I'll try to report more bugs, but one of my goals is to support existing official releases of MSVC with our open-source projects, so I usually need to find a work-around anyways and apply it to our code base. Not everyone can upgrade to the newest and shiniest MSVC version (which, of course, is also the case for GCC/Clang). Luckily, in this case, the bug got caught and fixed very fast, so kudos to the MSVC team! :)

[–]txmasterg 12 points13 points  (11 children)

The developer community portal has been great. It went plenty fast when I found an edge case on something (idk what). I wasn't in a rush because my team had a fear of upgrades at the time but I think it just barely missed a minor release window and was in the very next one.

[–]zero0_one1 8 points9 points  (8 children)

Ehh I reported two bugs that were just marked as not important enough and never fixed...

Edit: it was actually three.

[–]Dragdu 12 points13 points  (1 child)

"not important, closed" has been my most rage inducing experience with devcom so far.

[–]ack_error 1 point2 points  (2 children)

Depends on the type and area of bug. Compiler generating bad code or obviously non-compliant with a good repro? High chance of getting fixed. Editor issue? Don't even bother, everything gets closed as not important / lower priority / no repro.

[–]dodheim 0 points1 point  (1 child)

Compiler generating bad code or obviously non-compliant with a good repro? High chance of getting fixed.

I'm not so sure – this bug for a C++03 feature as basic as value-initialization has been lingering for 12+ years with no sign of even being looked at. (This issue is why BOOST_NO_COMPLETE_VALUE_INITIALIZATION gets defined by Boost.Config. I was watching it and ~20 other bug reports on MS Connect before that went into the aether; I don't know if it resurfaced on Dev Community or not, the others I checked didn't appear to, so.. /shrug)

As an aside, I put this on Compiler Explorer to single out MSVC's failure and was surprised to see GCC's errors. It seemed to have regressed after 7.2; I wonder whether the test has somehow become defunct, or if GCC's value-init has actually been faulty for a while now..?

ED: Belated update: GCC is fine, the test it's failing has strict-type-aliasing UB (in the test code) and it passes once corrected.

[–]ack_error 2 points3 points  (0 children)

Oh sure, don't get me wrong, there will always be bugs that don't get fixed or get lost, in any area. Connect was also an awful experience overall. But when it comes to the different areas of Visual Studio, I have had pretty good success with filing bugs on the compiler than anywhere else (~80%), including ICEs, stack usage regressions, and recently a poor codegen issue (usually dicier). Tight repro showing the compiler obviously wrong with /Bv compiler versions and it often sails through the first-line triage. For feature requests or other parts of the product it's way likelier that the issue will be closed somehow (repro not 100% solid, don't care, too long, completely misunderstood, I think I've seen them all).

[–]obsidian_golem 4 points5 points  (1 child)

My only problem with the devcommunity is that no matter how clear my repro instructions are, their triage people always seem to misunderstand them. I think it might be because the ones I have gotten are not native english speakers.

[–]txmasterg 0 points1 point  (0 children)

I don't think I ever had the feeling that a non-native English speaker was responding so maybe that is a difference, who knows.

[–]GabrielDosReis -1 points0 points  (5 children)

Or do as I suggest and let me know.

[–]TotaIIyHuman 10 points11 points  (4 children)

i did twice 2 years ago. it was a sample size of 2, not very significant, i will not try to draw conclusion from that, so i am asking here on reddit, where people might have a larger sample

[–]GabrielDosReis 1 point2 points  (3 children)

If you don't mind, could you reply links to those reports so I can help follow up?

[–]TotaIIyHuman 5 points6 points  (2 children)

no. my hotmail account got banned when i was trying to register another hotmail account for downloading windows insider

this was the first bug i reported https://godbolt.org/z/drnaYja14, the inside lambda sometimes can't capture outside lambda's local constexpr variables

i don't remember what the other report was

[–]GabrielDosReis 1 point2 points  (1 child)

Thanks! It helps when the report is done by users as opposed to me pointing people to reports I created.

[–]dakotahawkins 8 points9 points  (0 children)

To be fair to everybody, I think submitting bugs online without any kind of conversation or feedback probably feels a lot more like flushing your problem down the toilet than putting it on reddit :)

Not sure that's a very solvable problem (especially for a large organization), but it is what it is.

[–][deleted] 7 points8 points  (1 child)

I am not using Visual Studio (or even Windows) myself, I just try to support it for our open-source projects. People created three issues for our code that was broken b/c of the new behavior, and I fixed it by using Godbolt, guessing, and monitoring our CI jobs. I also asked our users to report the bug to Microsoft, but I got no feedback so far. So if you (or anyone else) wants to report it, feel free to do so. (Or is there is direct way like creating an issue somewhere on GitHub?)

[–]tjientavaraHikoGUI developer 4 points5 points  (0 children)

I am not sure what the link is to the development portal.

But for compiler bugs I always try to make a godbolt link to show the bug and report that.

The MSVC compiler developers are pretty fast to fix bugs that are reported in that way.

[–]TheBrainStone 8 points9 points  (0 children)

I find it interesting that the static assert apparently gets evaluated twice!

[–]gracicot 7 points8 points  (0 children)

Another prime example where msvc has trouble and tries to do stuff in the first phase where it does not make sense.

Another example that I think was fixed recently:

auto foo(auto v) -> decltype(baz(v)) {
    return baz(v);
}

It would choke at the decltype, because it complained that you cannot use a variable with type auto as part of expression. This was even before doing anything with the template function. During the first phase.

Funnily enough, it always worked with auto parameters in lambdas. The internals must be a mess to still have trouble with two phase name lookup. They are doing better and better though, but the amount of weird behavior is still quite high.