Package: llvm-gcc-4.2 Version: 2.5-1 Severity: normal
I have found a case where llvm-gcc-4.2 miscompiles code on amd64/sid. The testcase is attached. Unfortunately, the testcase requires Qt 4 (I used 4.5.0 from experimental; I don't know if the version from sid will work.) I tried to remove the last dependency on QString from Token, but when I did, the code no longer failed. Thus, to compile it, you'll need to use: /usr/lib/llvm/llvm/gcc-4.2/bin/x86_64-linux-gnu-llvm-g++ -O2 -D_REENTRANT -DQT_NO_DEBUG -DQT_CORE_LIB -DQT_SHARED -I/usr/share/qt4/mkspecs/linux-g++ -I/usr/include/qt4/QtCore -I/usr/include/qt4 -o troff foo.cxx -lQtCore -lpthread I apologize in advance for this problem. The bug occurs in TroffReadxer::parseRequestName. m_compat is set to 4 by the TroffReader constructor. Therefore, m_compat.getMode() returns 4. CompatibilityMode::AllowLongNames is 8. Therefore, maxtoke should be 2, since (4 & 8) is false. Instead, maxtoke is set to (size_t)-1. A couple of lines down, the code checks for this case and calls abort(3). If you need anything else, please let me know. -- System Information: Debian Release: squeeze/sid APT prefers unstable APT policy: (500, 'unstable'), (1, 'experimental') Architecture: amd64 (x86_64) Kernel: Linux 2.6.29-1-amd64 (SMP w/2 CPU cores) Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8) Shell: /bin/sh linked to /bin/bash Versions of packages llvm-gcc-4.2 depends on: ii libc6 2.9-6 GNU C Library: Shared libraries ii libgcc1 1:4.3.3-5 GCC support library ii libstdc++6 4.3.3-5 The GNU Standard C++ Library v3 ii llvm 2.5-2 Low-Level Virtual Machine (LLVM) c ii llvm-dev 2.5-2 common libraries and headers for L llvm-gcc-4.2 recommends no packages. Versions of packages llvm-gcc-4.2 suggests: pn gcc-4.2-doc <none> (no description available) -- no debconf information -- brian m. carlson / brian with sandals: Houston, Texas, US +1 713 440 7475 | http://crustytoothpaste.ath.cx/~bmc | My opinion only troff on top of XML: http://crustytoothpaste.ath.cx/~bmc/code/thwack OpenPGP: RSA v4 4096b 88AC E9B2 9196 305B A994 7552 F1BA 225C 0223 B187
#ifndef THWACK_TROFF_READER_HH
#define THWACK_TROFF_READER_HH
#include <vector>
#ifndef THWACK_TROFF_LEXER_HH
#define THWACK_TROFF_LEXER_HH
#include <cwctype>
#ifndef THWACK_INTERNAL_HH
#define THWACK_INTERNAL_HH
#include <tr1/memory>
#define THWACK_PTR(x) std::tr1::shared_ptr<x>
#define THWACK_CAST(x) std::tr1::dynamic_pointer_cast<x>
#endif
#ifndef THWACK_TROFF_ENVIRONMENT_HH
#define THWACK_TROFF_ENVIRONMENT_HH
#ifndef THWACK_TROFF_TOKEN_HH
#define THWACK_TROFF_TOKEN_HH
#include <QString>
class Token
{
public:
enum Type
{
Token_Character,
Token_EOF,
Token_Escape,
Token_Newline,
Token_EOL=Token_Newline,
Token_Space,
Token_Whitespace,
Token_BOL,
Token_Compatibility
};
Token() : m_type(Token_EOF), m_c(0), m_flags(0) {}
explicit Token(Type t) : m_type(t), m_c(0), m_flags(0) {}
explicit Token(wchar_t c);
Token(Type t, int c);
bool isEOF() const;
bool isNewline() const;
bool isSpace() const;
bool isWhitespace() const;
bool isTerminal() const;
bool isEscape() const;
wchar_t getCharacter() const;
wchar_t getTextEquivalent() const;
bool isCharacter() const;
bool operator==(const Token &a) const;
bool operator!=(const Token &a) const;
Type getType() const;
wchar_t getEscapeType() const;
int getFlags() const;
protected:
private:
Type m_type;
wchar_t m_c;
QString m_name;
int m_flags;
};
typedef std::vector<Token> TokenString;
#endif
Token::Token(wchar_t c) : m_c(c), m_flags(0)
{
m_type=std::iswspace(c)?Token_Whitespace:Token_Character;
}
Token::Token(Type t, int c)
{
if ((m_type=t)==Token_Compatibility)
m_flags=c;
}
bool Token::isEOF() const
{
return m_type==Token_EOF;
}
bool Token::isNewline() const
{
return m_type==Token_Newline || m_type==Token_BOL;
}
bool Token::isSpace() const
{
return m_type==Token_Space;
}
bool Token::isWhitespace() const
{
return m_type==Token_Whitespace || isSpace();
}
bool Token::isTerminal() const
{
return isNewline() || isEOF();
}
bool Token::isEscape() const
{
return m_type==Token_Escape;
}
wchar_t Token::getCharacter() const
{
return isCharacter() ? m_c : 0;
}
wchar_t Token::getTextEquivalent() const
{
return isCharacter() ? m_c :
(isWhitespace() ? L' ' :
(isNewline() ? L'\n' : 0));
}
bool Token::isCharacter() const
{
return m_type==Token_Character;
}
Token::Type Token::getType() const
{
return m_type;
}
wchar_t Token::getEscapeType() const
{
return m_c;
}
#endif
class CompatibilityMode
{
public:
// GroffCompatibility means compatibility with groff, not groff
// compatibility mode.
enum
{
XFlag0=0,
AllowDo=4,
XFlag1=AllowDo,
AllowLongNames=8,
XFlag2=XFlag1|AllowLongNames,
NoFallback=16,
XFlag3=XFlag2|NoFallback,
GroffCompatibility=32,
Groff=XFlag3|GroffCompatibility,
All=Groff
};
CompatibilityMode(int thwack=All) : m_cp(thwack) {}
void setMode(int thwack) { m_cp=thwack; }
static int lookupGroff(bool val)
{
return val ? Groff : XFlag1;
}
int getGroff() const { return (m_cp&Groff)==Groff; }
void setGroff(bool val) { m_cp = lookupGroff(val); }
static int lookupXFlag(int val)
{
const int masks[] = {
XFlag0, XFlag1, XFlag2, XFlag3
};
return masks[(val > 3) ? 3 : ((val < 0) ? 0 : val)];
}
int getXFlag() const
{
for (int i = 3; i >= 0; i--)
if ((m_cp & lookupXFlag(i)) == lookupXFlag(i))
return i;
return 0;
}
void setXFlag(int val)
{
m_cp = lookupXFlag(val);
}
int getMode() const { return m_cp; }
int has(int mode) const { return m_cp&mode; }
private:
int m_cp;
};
#endif
class Location
{
public:
Location(TokenString::iterator c, TokenString::iterator l,
TokenString::iterator f) :
m_cur(c), m_eol(l), m_eof(f) {}
virtual TokenString::iterator &cur()
{
return m_cur;
}
virtual TokenString::iterator &eol()
{
return m_eol;
}
virtual TokenString::iterator &eof()
{
return m_eof;
}
protected:
Location() {}
TokenString::iterator m_cur, m_eol, m_eof;
private:
};
class TroffReader
{
public:
TroffReader();
void parse(void);
protected:
void switchCompatibilityMode(CompatibilityMode cm);
void parseOneLine(Location &);
void parseRequestName(Location &loc);
private:
CompatibilityMode m_compat;
};
#endif
int main(void)
{
TroffReader rdr;
rdr.parse();
return 0;
}
TroffReader::TroffReader()
{
m_compat = CompatibilityMode(4);
switchCompatibilityMode(m_compat);
}
/* This function looks up strings, macros, and diversions; they are all handled
* similarly.
*/
void TroffReader::switchCompatibilityMode(CompatibilityMode cm)
{
m_compat=cm;
}
void TroffReader::parseOneLine(Location &loc)
{
wchar_t c=loc.cur()->getCharacter();
if (c == '.') {
loc.cur()++;
parseRequestName(loc);
}
}
// XXX: This is pure.
void TroffReader::parseRequestName(Location &loc)
{
const size_t maxtoke=
(m_compat.getMode()&m_compat.AllowLongNames?static_cast<size_t>(-1):2);
wchar_t c=0;
Token t;
if (m_compat.getMode() == 4 && maxtoke != 2)
abort();
for (size_t ntoke=0; ntoke<maxtoke && loc.cur()!=loc.eol() &&
loc.cur() != loc.eof(); ntoke++)
{
t=*loc.cur()++;
c=t.getCharacter();
if (t.isNewline() || t.isEscape()) {
// This form of escape handling is for groff compatibility. For
// Unix troff compatibility, we should allow this. Producing
// sensible semantics may not be easy, though.
--loc.cur();
break;
}
else if (t.isWhitespace()) {
break;
}
}
}
void TroffReader::parse()
{
TokenString ts;
ts.push_back(Token('.'));
ts.push_back(Token('d'));
ts.push_back(Token('o'));
ts.push_back(Token(Token::Token_Whitespace));
ts.push_back(Token('B'));
ts.push_back(Token('B'));
ts.push_back(Token('B'));
ts.push_back(Token(Token::Token_Newline));
THWACK_PTR(Location) loc(new Location(ts.begin(), ts.end() , ts.end()));
for (; loc->cur() != loc->eof();)
parseOneLine(*loc);
}
signature.asc
Description: Digital signature

