Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

g++ 6.1 compile time regression?

Tags:

c++

g++

The code below takes forever (well, a long-ish time) to compile in g++ 6.1.0, compared to g++ 4.8.3. Is this a compiler bug ? Or something stupid in the code ? (Stupider than using fixed and showpoint where there are no floating point values...).

g++ 4.8:

$ time ~/dev/compilers/linux-x86_64-2.10.1/gnu4.8.3/bin/g++ -D_REENTRANT -fPIC -Wall -Wextra -Wno-unused-parameter -Werror -Wno-unused-local-typedefs -m64 -Woverloaded-virtual -Wno-deprecated -fvisibility-inlines-hidden -fvisibility=hidden -std=c++11 -c ostreamtest.cpp

real 0m0.451s

g++ 6.1:

$ time ~/dev/compilers/linux-x86_64-2.10.1/gnu6.1.0/bin/g++ -D_REENTRANT -fPIC -Wall -Wextra -Wno-unused-parameter -Werror -Wno-unused-local-typedefs -m64 -Woverloaded-virtual -Wno-deprecated -fvisibility-inlines-hidden -fvisibility=hidden -std=c++11 -c ostreamtest.cpp

real 15m36.033s

ostreamtest.cpp:

#include <iostream>
#include <iomanip>
#include <ostream>

typedef long long int64;

class IOStreamWrapper
{
public:
  /// get/set ALL format flags
  virtual std::ios_base::fmtflags flags() const;
  virtual std::ios_base::fmtflags flags(std::ios_base::fmtflags flags);

  /// set specific format flags
  virtual std::ios_base::fmtflags setf(std::ios_base::fmtflags flags);
  virtual std::ios_base::fmtflags setf(std::ios_base::fmtflags flags, std::ios_base::fmtflags mask);

  /// unset specific format flags
  virtual void unsetf(std::ios_base::fmtflags mask);

  /// get/set precision
  virtual std::streamsize precision() const;
  virtual std::streamsize precision(std::streamsize precision);

  /// get/set width
  virtual std::streamsize width() const;
  virtual std::streamsize width(std::streamsize wide);

  /// get/set fill char
  virtual char fill() const;
  virtual char fill(char c);

  /// stream error states
  virtual bool good();
  virtual bool bad();
  virtual bool fail();
  virtual bool eof();
  virtual void clear();

  // Forward conversion to bool to the real istream.
  virtual operator int();

  // forward operators void* (returns !fail())
  virtual operator void*();

  // forward operator !()  (returns fail() )
  virtual bool operator !();

  /// dummy method which allows use of broadcast and nobroadcast manipulators
  /// in the InputFileStream and OutputFileStream classes. Not perfect but the
  /// only way I could this to work.
  virtual void setBroadcastFlag(bool const &flag = true) { return; }
protected:
  // Construct class to reference a real istream.  All methods and
  // operators will be forwarded.
  IOStreamWrapper(std::ios &ios);
  IOStreamWrapper(IOStreamWrapper const &r);
  virtual ~IOStreamWrapper() {}

  // Reference to the real ostream.
  std::ios       & iostr()       { return _iostr; }
  std::ios const & iostr() const { return _iostr; }
private:
  // Reference to the real iostream.
  std::ios &_iostr;

  IOStreamWrapper &operator=(IOStreamWrapper const &r); // Not Implemented.
};


class Indent;

class OStreamWrapper: public IOStreamWrapper
{
public:
  // Construct class to reference a real ostream.  All methods and
  // operators will be forwarded.
  OStreamWrapper(std::ostream &os);
  OStreamWrapper(OStreamWrapper const &r);
  virtual ~OStreamWrapper() {}

  // Type for a fake endl.
  struct EndlType {};

  // Forward this output operator to the real ostream.
  OStreamWrapper & operator << (EndlType const &);
  OStreamWrapper & operator << (Indent const &);

  // wrappers for ostream global functions
  virtual OStreamWrapper & operator<<(char c);
  virtual OStreamWrapper & operator<<(unsigned char c);
  virtual OStreamWrapper & operator<<(char const * s);
  virtual OStreamWrapper & operator<<(unsigned char const * s);
  virtual OStreamWrapper & operator<<(std::string);

  // wrappers for ostream member functions
  virtual OStreamWrapper & operator << (bool);
  virtual OStreamWrapper & operator << (short);
  virtual OStreamWrapper & operator << (unsigned short);
  virtual OStreamWrapper & operator << (int);
  virtual OStreamWrapper & operator << (unsigned int);
  virtual OStreamWrapper & operator << (long);
  virtual OStreamWrapper & operator << (unsigned long);
  virtual OStreamWrapper & operator << (long long);
  virtual OStreamWrapper & operator << (unsigned long long);
  virtual OStreamWrapper & operator << (float);
  virtual OStreamWrapper & operator << (double);
  virtual OStreamWrapper & operator << (long double);
  virtual OStreamWrapper & operator << (void*);
  virtual OStreamWrapper & operator << (std::streambuf* sb);
  virtual OStreamWrapper & operator << (OStreamWrapper &(*manpip)(OStreamWrapper &));
  virtual OStreamWrapper & operator << (std::ostream &(*manpip)(std::ostream &));
  virtual OStreamWrapper & operator << (std::ios &(*manip)(std::ios &));
  virtual OStreamWrapper & operator << (std::ios_base &(*manip)(std::ios_base &));

  OStreamWrapper & operator << (void        (*)(void*));
  OStreamWrapper & operator << (void*       (*)(void*));
  OStreamWrapper & operator << (int         (*)(void*));
  OStreamWrapper & operator << (int*        (*)(void*));
  OStreamWrapper & operator << (float*      (*)(void*));
  OStreamWrapper & operator << (char const* (*)(void*));
  OStreamWrapper & operator << (void        (*)(void*, int*));

  // Forward ostream methods directly to the ostream
  virtual OStreamWrapper & write(char const*, std::streamsize);
  virtual OStreamWrapper & flush();
  virtual OStreamWrapper & put(char c);
  virtual OStreamWrapper & seekp(std::streampos pos);
  virtual OStreamWrapper & seekp(std::streamoff offset, std::ios_base::seekdir dir);
  virtual std::streampos tellp();

  /// switch for broadcast flag in InputFileStream class
  static OStreamWrapper & broadcast(OStreamWrapper &);
  static OStreamWrapper & nobroadcast(OStreamWrapper &);

  // Get a reference to the real ostream.
  std::ostream & GetOStream();

  // Allow conversion to the real ostream type.  This allows an
  // instance of OStreamWrapper to look like ostream when passing to a
  // function argument.
  operator std::ostream&();

  // Implementation detail to allow macros to provide an endl that may
  // or may not be used.
  static void UseEndl(EndlType const &) {}

  // wrap std manipulators
  class setw{
  public:
    explicit setw(int const &i) : _i(i) {}
  private:
    friend OStreamWrapper & operator<<(OStreamWrapper &ib, setw const &m)
    {
      ib.width(m._i);
      return ib;
    }
    int _i;
  };
  class setprecision{
  public:
    explicit setprecision(int const &i) : _i(i) {}
  private:
    friend OStreamWrapper & operator<<(OStreamWrapper &ib, setprecision const &m)
    {
      ib.precision(m._i);
      return ib;
    }
    int _i;
  };
  class setfill{
  public:
    explicit setfill(char c) : _c(c) {}
  private:
    friend OStreamWrapper & operator<<(OStreamWrapper &ib, setfill const &m)
    {
      ib.fill(m._c);
      return ib;
    }
    char _c;
  };
  class setiosflag{
  public:
    explicit setiosflag(std::ios_base::fmtflags mask) : _mask(mask) {}
  private:
    friend OStreamWrapper & operator<<(OStreamWrapper &ib, setiosflag const &m)
    {
      ib.setf(m._mask);
      return ib;
    }
    std::ios_base::fmtflags _mask;
  };
  class resetiosflag{
  public:
    explicit resetiosflag(std::ios_base::fmtflags mask) : _mask(mask) {}
  private:
    friend OStreamWrapper & operator<<(OStreamWrapper &ib, resetiosflag const &m)
    {
      ib.unsetf(m._mask);
      return ib;
    }
    std::ios_base::fmtflags _mask;
  };
protected:
  // Reference to the real ostream.
  std::ostream       & ostr()       { return _ostr; }
  std::ostream const & ostr() const { return _ostr; }
private:
  // Reference to the real ostream.
  std::ostream &_ostr;

  OStreamWrapper & operator=(OStreamWrapper const &r); // Not Implemented.
};


void
printProcessTableData(OStreamWrapper &out,
    int const maxLen,
    int const columnWidth,
    int const nColumns,
    std::string const &tag,
    double const resMem,
    double const addedResMem,
    double const addedResHWM,
    int const c)
{
  out << OStreamWrapper::setw(maxLen - 2)
      << std::left
      << "| " + tag.substr(0,maxLen-4)
      << std::right
      << OStreamWrapper::setw(2)
      << " |"
      << OStreamWrapper::setw(columnWidth - 19)
      << c
      << OStreamWrapper::setw(2)
      << " |"
      << OStreamWrapper::setw(columnWidth - 8)
      << std::fixed
      << std::showpoint
      << int64(resMem)
      << OStreamWrapper::setw(2)
      << " |"
      << OStreamWrapper::setw(columnWidth - 6)
      << std::fixed
      << std::showpoint
      << int64(addedResMem)
      << OStreamWrapper::setw(2)
      << " |"
      << OStreamWrapper::setw(columnWidth - 2)
      << std::fixed
      << std::showpoint
      << int64(addedResHWM)
      << OStreamWrapper::setw(2)
      << " |"
      << std::endl;
}
like image 678
Chris Morley Avatar asked May 28 '16 01:05

Chris Morley


1 Answers

It was a bug in 6.1.0 and 6.1.1, but has been fixed for 6.2 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71330

like image 161
Chris Morley Avatar answered Nov 12 '22 04:11

Chris Morley