[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#498708: g++-4.3: internal compiler error with fipa-* optimization options



Package: g++-4.3
Version: 4.3.1-9
Severity: important

I tried to compile the following code with the following options and got the errors mentioned in place:

-fipa-struct-reorg   <-- fast.cc:289: internal compiler error: Segmentation fault

-fipa-pta            <-- /usr/include/c++/4.3/bits/vector.tcc: In member
function 'void std::vector<_Tp,
_Alloc>::_M_insert_aux(__gnu_cxx::__normal_iterator<typename
std::_Vector_base<_Tp, _Alloc>::_Tp_alloc_type::pointer,
std::vector<_Tp, _Alloc> >, const _Tp&) [with _Tp = int, _Alloc =
std::allocator<int>]':
/usr/include/c++/4.3/bits/vector.tcc:283: internal compiler error: in
initialize_flags_in_bb, at tree-into-ssa.c:437

The commandline was (with FOO being one of the above flags)

  g++ \
   -O3 -march=native \
   -FOO
   -fwhole-program -combine \
   -funsafe-loop-optimizations -Wunsafe-loop-optimizations \
   -ftree-loop-linear \
   fast.cc


The source code is:
++
// License: GPLv3
//  -> contact author for use not covered by GPLv3
//
// (C) 2008 Sebastian Mach
//  seb@greenhybrid.net
//  http://greenhybrid.net , http://picogen.org
//-----------------------------------------------------------------------------

#include <cstdlib>
#include <iostream>
#include <fstream>
#include <map>
#include <vector>


//-----------------------------------------------------------------------------
// convenience functions
//-----------------------------------------------------------------------------

// can also be used to check whether c is in ['0'..'9'] ("bool isNum = toInt(c) != -1;")
template <typename C> int toInt (C c) {
    
    // note that the C++ standard does not mandate
    // that the number-chars 0-9 are continous when
    // interpeted as integers, thus this function
    // does the portable way.
    
    // --> trust in constant folding
    // --> check if '0'-'9' are continous when cast to integer
    if ('1'-'0' == 1 
        && '2'-'0' == 2
        && '3'-'0' == 3
        && '4'-'0' == 4
        && '5'-'0' == 5
        && '6'-'0' == 6
        && '7'-'0' == 7
        && '8'-'0' == 8
        && '9'-'0' == 9
       ) {
        static int ret [2] = {-1, -1};
        ret [1] = c - '0';
        return ret [c>('0'-1) & c<('9'+1)];
    } else {
        switch (c) { // not much slower if the compiler emits jump tables
            case '0': return 0;
            case '1': return 1; 
            case '2': return 2;
            case '3': return 3;
            case '4': return 4;
            case '5': return 5;
            case '6': return 6;
            case '7': return 7;
            case '8': return 8;
            case '9': return 9;
        };
        return -1;
    }
}


// compiler should do a good job with it
template <typename A, typename B> class tuple {
        const A a_;
        const B b_;
    public:
        tuple (A a, B b) : a_(a), b_(b) {}
        const A& a () const { return a_; }
        const B& b () const { return b_; }
        operator A () const { return a_; }
        operator B () const { return b_; }
};



//-----------------------------------------------------------------------------
// some enums to be used as typesafe template args
//-----------------------------------------------------------------------------
enum order_t {
    order_in_main_section,
    order_in_ref_section
};

enum safemode_t {
    safe,
    unsafe
};



//-----------------------------------------------------------------------------
// some enums to be used as typesafe template args
//-----------------------------------------------------------------------------
template <typename C, C L, C R, order_t T=order_in_main_section, safemode_t S=safe> class Reorder {
    private:
        
        
        // that function assumes we're already inside the pair of 
        // brackets (i.e. after '[')
        template <class I> tuple <bool, int> scanRefTarget (I &curr, I end) {
            using namespace std;
            I old_curr = curr;
            
            int len = 0;   // used to check validity of reference
            int refID = 0; // the reference-id                
            while (R != *curr) { // <-- until we hit an end-bracket
                if (S == safe) {
                    if (end == curr) { // <-- rudimentary error checking
                        cerr << "found end of file but expected numbers or '" << R << endl;
                        throw;
                    }
                }
                const int d = toInt (*curr);
                if (-1 != d) {
                    refID = refID * 10 + d;                            
                    ++len;
                }
                ++curr;
            }
            if (0 != len) {                    
                return tuple <bool, int> (true, refID);
            }
            curr = old_curr; // <-- was not a reference, so rollback
            return tuple <bool, int> (false, -1);
        }
        
        template <typename I> struct Chunk { // intentionally POD
            I begin, end;
            int ref_target;
            Chunk <I> *next;
        };
        
        template <typename I> struct Reference { // intentionally POD
            I begin, end;
            int order;
        };
        
        template <class I> Chunk<I> *scanText (I &curr, I end) {
            Chunk<I> *chunk = new Chunk<I>;
            Chunk<I> * const first_chunk = chunk;
            chunk->begin = curr;
            chunk->next = 0;
            chunk->ref_target = -1;
            
            while (true) {
                if (L == *curr) { // <-- we've hit a start-bracket
                    ++curr; // <-- eat start-bracket
                    const I old_curr = curr;
                    const tuple <bool, int> refID = scanRefTarget (curr, end);
                    if (refID) {
                        //cout << "hit a ref:" << static_cast <int> (refID) << endl;
                        chunk->ref_target = refID;
                        chunk->end = old_curr-1;
                        chunk->next = new Chunk<I>;
                        chunk = chunk->next;
                        chunk->next = 0;
                        chunk->ref_target = -1;
                        chunk->begin = curr+1;
                    }
                } else if (end == curr) {
                    chunk->end = curr;
                    break;
                } else if ('\n' == *curr) {
                    I old_curr = curr;
                    if ('@' == *++curr
                        && 'f' == *++curr
                        && 'o' == *++curr
                        && 'o' == *++curr
                        && 't' == *++curr
                        && 'n' == *++curr
                        && 'o' == *++curr
                        && 't' == *++curr
                        && 'e' == *++curr
                        && ':' == *++curr
                    ) {
                        chunk->end = old_curr;
                        // eat forward to newline
                        while (curr != end && *curr != '\n')
                            ++curr;
                        ++curr; // eatup newline
                        break;
                    } else {                        
                        curr = old_curr;
                    }
                }
                ++curr;
            };
            return first_chunk;
        }
        
        template <typename I> void scanReferences (std::map <int, Reference <I> > &refs, std::vector<int> &orderedRRefs, I &curr, I end) {
            using namespace std;
            int footnodeID = 0;
            while (true) {
                while (L != *curr && '\n' != *curr && end != curr)
                    ++curr;
                if (L == *curr) {
                    ++curr; // <-- eat start-bracket
                    const I old_curr = curr;
                    const tuple <bool, int> refID = scanRefTarget (curr, end);
                    ++curr;
                    if (refID) {
                        Reference<I> ref;
                        while (' ' == *curr || '\n' == *curr) // <-- eat whitespace
                            ++curr;
                        ref.begin = curr;
                        while (*curr != '\n' && curr != end)
                            ++curr;
                        ref.end = curr;
                        ref.order = footnodeID++;
                        orderedRRefs.push_back (refID);
                        refs [refID] = ref;
                    }
                } else if (end == curr) {
                    break;
                }
                ++curr;
            }
        }
    
    public:
    
        template <class I> Reorder (I begin, I end) {
            using namespace std;            
            
            I curr = begin;
            Chunk<I> *chunk = scanText<I> (curr, end);
            map <int, Reference <I> > refs;
            std::vector<int> orderedRRefs;
            scanReferences <I> (refs, orderedRRefs, curr, end);

            // dump text
            for (const Chunk<I> *it = chunk; 0 != it; it = it->next) {
                for (I a=it->begin; a != it->end; ++a) {
                    cout << *a;
                }
                if (-1 != it->ref_target) {
                    cout << "[" << refs [it->ref_target].order << "]";
                }
            }
            cout << '\n';
            // dump footnotes
            cout << "@footnote:\n";
            for (vector<int>::iterator it=orderedRRefs.begin(); it!=orderedRRefs.end(); ++it) {
                cout << "[" << refs [*it].order << "] ";
                for (I c=refs [*it].begin; c!=refs [*it].end; ++c) {
                    cout << *c;
                }
                cout << "\n";
            }
            
            while (0 != chunk) {
                Chunk <I> *tmp = chunk;
                chunk = chunk->next;
                delete tmp;
            }
        }
};



//-----------------------------------------------------------------------------
// main
//-----------------------------------------------------------------------------
int main (int argc, char *argv []) {   
    using namespace std;
    /*string text = 
        "[66]abc [33] def [99] ghi [33]lalal\n"
        "@footnote:\n"    
        "[66] the lazy dogs\n"
        "[33] the C++ compendium\n"
        "[99] hmm, a footnote\n"
    ;*/    

    char *begin, *end;
    {
        ifstream f ("testfile");
        f.seekg (0, ios::end);
        int len = f.tellg();
        f.seekg (0, ios::beg);
        begin = new char [len];
        end = begin + len;
        f.read (begin, len);
        f.close();
    }
    Reorder <char, '[', ']', order_in_main_section, unsafe> (begin, end);
    
    
    return 0;
}
--


-- System Information:
Debian Release: lenny/sid
  APT prefers testing
  APT policy: (500, 'testing'), (500, 'stable')
Architecture: i386 (i686)

Kernel: Linux 2.6.22-3-k7 (SMP w/1 CPU core)
Locale: LANG=de_DE.UTF-8, LC_CTYPE=de_DE.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/bash

Versions of packages g++-4.3 depends on:
ii  gcc-4.3                   4.3.1-9        The GNU C compiler
ii  gcc-4.3-base              4.3.1-9        The GNU Compiler Collection (base 
ii  libc6                     2.7-13         GNU C Library: Shared libraries
ii  libgmp3c2                 2:4.2.2+dfsg-3 Multiprecision arithmetic library
ii  libmpfr1ldbl              2.3.1.dfsg.1-2 multiple precision floating-point 
ii  libstdc++6-4.3-dev        4.3.1-9        The GNU Standard C++ Library v3 (d

g++-4.3 recommends no packages.

Versions of packages g++-4.3 suggests:
ii  g++-4.3-multilib              4.3.1-9    The GNU C++ compiler (multilib fil
pn  gcc-4.3-doc                   <none>     (no description available)
pn  libstdc++6-4.3-dbg            <none>     (no description available)

-- no debconf information



Reply to: