5 Replies Latest reply on Jun 18, 2018 9:18 AM by Maxim Kartashev-Oracle

    Compiler CC corrupts a class, if it contains reinterpret_cast

    Oqelu

      If a class contains a member function that initializes a static variable as
      static const Type Structure={initializer list};
      static const Type & StructureRef = * reinterpret_cast<const Type*>(&Structure)

      then compiler fails:
      Error: Structure must be initialized.
      Although, this is initialization.
      Maybe CC creates an undefined static symbol as a bug, ignores the {initializer list}, and reports that it its not initialized.

      If you remove const as a workaround, then for derived classes CC fails:
      >> Assertion:  (../lnk/irinitializer.cc, line 263)
      This happens if virtual, and override member functions are present in base and derived classes respectively.

      Workarounds:

      • Remove static, or const from the  Structure.
        Try also to remove a trailing const from declaration of the virtual function() const = 0.
      • Create an additional dummy member virtual function()=0, which you do not override.
        This allows to compile overrides in derived classes. But does not solve the the bug with initialization of the Structure. See previous workaround.
      • Replace reinterpret_cast with ordinary explicit cast: (Type&).
        This alone solves both problems at once.

      I did not try to do away with a reference "&", and use the Structure directly. Most probably this would fail anyway, because reinterpret_cast would still be there.

      There are many other errors that report >> Assertion:.
      This kind of error does not report the source. The file irinitializer.cc does not exist. It is hard to find the real source.
      Workaround: remove part of code, so compiler succeeds. There may be more than one piece of problematic code. So, begin to compile with the smallest part, and increase it gradually till compiler fails. Then apply a workaround for the bug itself.
      I did not yet report other errors of this kind. You may find on this web site workarounds by other people for some errors. For others you would have to wait for my further reports, or invent a workaround by yourself.

        • 1. Re: Compiler CC corrupts a class, if it contains reinterpret_cast
          Maxim Kartashev-Oracle

          I was unable to reproduce the problem from the description. This code, for example, compiles fine with CC 5.15 from Studio 12.6:

          struct Type
          {
              int i;
              int j;
              int k;
          };
          
          struct A
          {
              void foo()
              {
              static const Type Structure = { 1, 2, 3};
              static const Type & StructureRef = *reinterpret_cast<const Type*>(&Structure);
              }
          };
          
          int main()
          {
              A a;
              a.foo();
          
              return 0;
          }
          

           

          You also didn't specify the version of the compiler you are using. The assertion failures you see are usually not present in the production version of the compiler, but are sometimes left in betas. BTW, the assertion means an internal compiler error (also known as ICE) and the source location you see refers to compiler source code, not the code it compiles, so it has no value for you as a user.

           

          If possible, please post a complete compilable example that crashed the compiler together with complete CC -V output that would help to identify compiler's version.

           

          Thank you!

          • 2. Re: Compiler CC corrupts a class, if it contains reinterpret_cast
            Oqelu

            My version is same as yours. Not "Beta".

            Some of the most prolific error reports in bugs of this sort in initializer:
            Assertion:  (../lnk/initializer.cc, line 1865)
            Assertion:  (../lnk/irinitializer.cc, line 263)
            ir_get_type_member(): unexpected nested type

            Lines 263, and 1865 are the only ones I encountered. No other lines of Assertion:. The same 2 occur for many different initializers.

            Most such bugs manifest with large code, object files over megabyte in size.

            Small code does compile. Large - not.

            Some bugs manifest only with 64-bit code. I think I saw other people too report that 32-bit code succeeds, and 64-bit code fails to compile.

            The workaround for ir_get_type_member() is to shuffle #include ....cpp within the main .cpp file to list one before others till compiler succeeds. No change in code necessary. Just change the order of files.
            Same files in smaller quantity do compile. Just comment out some #include ....cpp, then others.

            For some I did not find a workaround. I found several dosens of such, and other bugs. This makes CC useless with large programs. They are more likely to contain code that invoke the bugs.

            If it is an internal compiler error, then it would be enough to simply state them, and you would be able to patch the compiler. Then you do not need to know the code it fails to compile.

            If the error is internal to CC, then why in its Assertion: ...initializer.cc, line ... it reports:
            while processing ....cpp at line 0?
            There can not be such line. The report is useless.

            • 3. Re: Compiler CC corrupts a class, if it contains reinterpret_cast
              Maxim Kartashev-Oracle

              My version is same as yours. Not "Beta".

              Still, knowing the exact number may help; CC -V  will give you that.

              Some of the most prolific error reports in bugs of this sort in initializer:

              Assertion:  (../lnk/initializer.cc, line 1865)

              Assertion:  (../lnk/irinitializer.cc, line 263)

              These look familiar; some of those assertions has been fixed, but there might be others. If you have a support contract, you can install the latest patches and see if that helps. Else you can file a bug; if it's impossible to do that here, you can still do it through the support channel.

              ir_get_type_member(): unexpected nested type

              There are might be many reasons for this error and several bugfixes. The above suggestion applies.

              Some bugs manifest only with 64-bit code. I think I saw other people too report that 32-bit code succeeds, and 64-bit code fails to compile.

              -m32 and -m64 compilations actually compile slightly different code because of many #ifdefs in the headers. So occasionally a compiler bug would only manifest itself in one mode, but not the other. Knowing the compilation mode is not enough to reproduce it, though, one needs source code, platform, and exact compilation flags.

              If it is an internal compiler error, then it would be enough to simply state them, and you would be able to patch the compiler.

              Of course, but I need a way to reproduce the problem first; any program large enough contains bugs, some are known to the developers and remain unfixed due to lack of resources, some aren't even known. To debug the compiler, the compiler developers need a way to crash it the same way it crashes at your side. There a very good article on filing compiler bugs; it's about gcc, but the principle applies.

              If the error is internal to CC, then why in its Assertion: ...initializer.cc, line ... it reports:

              while processing ....cpp at line 0?

              There can not be such line. The report is useless.

              That line number is not always 0; sometimes the compiler is able to point to the right spot in the user program and that helps us to debug the problem faster. Other times, the compiler chokes on constructs it created itself based on the original source code, but haven't filled in all the fields yet before it crashed, so the location information is useless. Like I said before, normally these kinds of messages are suppressed in the release compiler and are therefore intended solely for the compiler developer's consumption.

              • 4. Re: Compiler CC corrupts a class, if it contains reinterpret_cast
                Oqelu

                My number is exactly the same as yours.

                The difference is in the size of code. The larger the object file, the greater is the opportunity to hit the bugs.

                You do not need to have the same code as mine. It would not even be possible to post here megabytes of source code. You may hit the bugs with your own code. Just make it large enough, and insert in it objects as I described.

                Try to create an object file of 10MB.

                Line number 0 is very often with those 2 assertions. Perhaps always.

                Why would you suppress a message of error, if a compiler fails? Would it fail silently? But then we would not have any means to identify the problem.

                It is strange that bug reports are locked only to paying users. Reports by everyone should be welcome. A bug for a free user is a bug for a paying user too. If Oracle forbids free users to report bugs, paying users hurt. I post my reports publicly for everyone to benefit.

                In your example put virtual in front of foo(). Then compiler reports:
                Error: Structure must be initialized.
                Then replace *reinterpret_cast... with (const Type&)Structure. - Same error. Although, such cast in my large code succeeds.
                Remove &: (const Type)Structure. - Compiler succeeds.
                (const Type&), and (const Type) have the same meaning. Reaction (bug) to both should be the same too.
                And indeed, without the virtual both succeed.

                In fact, they should have no effect, because the type is the same. No need to cast. Compiler succeeds even if you remove the cast, and simply assign.
                The intent of the code is to cast to another Type2, a derived class from Type. Then removal of & does not work, but for another, legitimate reason:
                Error: Cannot cast. Although, I would argue that compiler should grant such explicit cast (const Type2), as it would (const Type2&).

                • 5. Re: Compiler CC corrupts a class, if it contains reinterpret_cast
                  Maxim Kartashev-Oracle

                  Thanks for correcting my test case, I was able to reproduce the problem and filed bug 28198601. A short test case goes like this:

                  struct Pair
                  {
                      int i, j;
                  };
                  
                  struct A
                  {
                      virtual void foo()
                      {
                      static const Pair p = {42, 43}; // Error: p must be initialized.
                      static const Pair& pr = *reinterpret_cast<const Pair*>(&p);
                      }
                  };
                  
                  int main()
                  {
                      A a;
                      a.foo();
                  }
                  

                   

                  The error issued for line 10 is incorrect and is triggered by the containing function being static and taking the address of a static variable. A workaround is to remove the static keyword, making variables p and pr automatic.