Type::isSignedInteger() and isUnsignedInteger() did not properly account for

'char', which varies based on the target.

Instead of spreading target knowledge throughout the compiler, bifurcate char
into Char_S and Char_U, and have ASTContext create the right one based on the
target, when it starts up.

llvm-svn: 39577
This commit is contained in:
Chris Lattner 2007-06-03 07:25:34 +00:00
parent cf25024828
commit b16f455e8c
5 changed files with 61 additions and 30 deletions

View File

@ -110,7 +110,10 @@ void ASTContext::InitBuiltinTypes() {
// C99 6.2.5p2. // C99 6.2.5p2.
InitBuiltinType(BoolTy, BuiltinType::Bool); InitBuiltinType(BoolTy, BuiltinType::Bool);
// C99 6.2.5p3. // C99 6.2.5p3.
InitBuiltinType(CharTy, BuiltinType::Char); if (Target.isCharSigned(SourceLocation()))
InitBuiltinType(CharTy, BuiltinType::Char_S);
else
InitBuiltinType(CharTy, BuiltinType::Char_U);
// C99 6.2.5p4. // C99 6.2.5p4.
InitBuiltinType(SignedCharTy, BuiltinType::SChar); InitBuiltinType(SignedCharTy, BuiltinType::SChar);
InitBuiltinType(ShortTy, BuiltinType::Short); InitBuiltinType(ShortTy, BuiltinType::Short);
@ -347,7 +350,8 @@ unsigned ASTContext::getIntegerBitwidth(QualType T, SourceLocation Loc) {
switch (BT->getKind()) { switch (BT->getKind()) {
default: assert(0 && "getIntegerBitwidth(): not a built-in integer"); default: assert(0 && "getIntegerBitwidth(): not a built-in integer");
case BuiltinType::Bool: return Target.getBoolWidth(Loc); case BuiltinType::Bool: return Target.getBoolWidth(Loc);
case BuiltinType::Char: case BuiltinType::Char_S:
case BuiltinType::Char_U:
case BuiltinType::SChar: case BuiltinType::SChar:
case BuiltinType::UChar: return Target.getCharWidth(Loc); case BuiltinType::UChar: return Target.getCharWidth(Loc);
case BuiltinType::Short: case BuiltinType::Short:
@ -375,7 +379,8 @@ static int getIntegerRank(QualType t) {
assert(0 && "getIntegerRank(): not a built-in integer"); assert(0 && "getIntegerRank(): not a built-in integer");
case BuiltinType::Bool: case BuiltinType::Bool:
return 1; return 1;
case BuiltinType::Char: case BuiltinType::Char_S:
case BuiltinType::Char_U:
case BuiltinType::SChar: case BuiltinType::SChar:
case BuiltinType::UChar: case BuiltinType::UChar:
return 2; return 2;
@ -448,6 +453,8 @@ QualType ASTContext::maxFloatingType(QualType lt, QualType rt) {
// maxIntegerType - Returns the highest ranked integer type. Handles 3 case: // maxIntegerType - Returns the highest ranked integer type. Handles 3 case:
// unsigned/unsigned, signed/signed, signed/unsigned. C99 6.3.1.8p1. // unsigned/unsigned, signed/signed, signed/unsigned. C99 6.3.1.8p1.
QualType ASTContext::maxIntegerType(QualType lhs, QualType rhs) { QualType ASTContext::maxIntegerType(QualType lhs, QualType rhs) {
if (lhs == rhs) return lhs;
bool t1Unsigned = lhs->isUnsignedIntegerType(); bool t1Unsigned = lhs->isUnsignedIntegerType();
bool t2Unsigned = rhs->isUnsignedIntegerType(); bool t2Unsigned = rhs->isUnsignedIntegerType();

View File

@ -15,6 +15,7 @@
#include "clang/AST/Type.h" #include "clang/AST/Type.h"
#include "clang/AST/Decl.h" #include "clang/AST/Decl.h"
#include "clang/AST/Expr.h" #include "clang/AST/Expr.h"
#include "clang/Basic/TargetInfo.h"
#include "llvm/Support/Streams.h" #include "llvm/Support/Streams.h"
using namespace llvm; using namespace llvm;
@ -235,16 +236,18 @@ bool Type::isIntegerType() const {
} }
bool Type::isSignedIntegerType() const { bool Type::isSignedIntegerType() const {
if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) {
return BT->getKind() >= BuiltinType::SChar && return BT->getKind() >= BuiltinType::Char_S &&
BT->getKind() <= BuiltinType::LongLong; BT->getKind() <= BuiltinType::LongLong;
}
return false; return false;
} }
bool Type::isUnsignedIntegerType() const { bool Type::isUnsignedIntegerType() const {
if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) {
return BT->getKind() >= BuiltinType::UChar && return BT->getKind() >= BuiltinType::Bool &&
BT->getKind() <= BuiltinType::ULongLong; BT->getKind() <= BuiltinType::ULongLong;
}
return false; return false;
} }
@ -343,20 +346,20 @@ bool Type::isIncompleteType() const {
} }
bool Type::isPromotableIntegerType() const { bool Type::isPromotableIntegerType() const {
if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) { const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType);
switch (BT->getKind()) { if (!BT) return false;
case BuiltinType::Bool: switch (BT->getKind()) {
case BuiltinType::Char: case BuiltinType::Bool:
case BuiltinType::SChar: case BuiltinType::Char_S:
case BuiltinType::UChar: case BuiltinType::Char_U:
case BuiltinType::Short: case BuiltinType::SChar:
case BuiltinType::UShort: case BuiltinType::UChar:
return true; case BuiltinType::Short:
default: case BuiltinType::UShort:
return false; return true;
} default:
return false;
} }
return false;
} }
const char *BuiltinType::getName() const { const char *BuiltinType::getName() const {
@ -364,7 +367,8 @@ const char *BuiltinType::getName() const {
default: assert(0 && "Unknown builtin type!"); default: assert(0 && "Unknown builtin type!");
case Void: return "void"; case Void: return "void";
case Bool: return "_Bool"; case Bool: return "_Bool";
case Char: return "char"; case Char_S: return "char";
case Char_U: return "char";
case SChar: return "signed char"; case SChar: return "signed char";
case Short: return "short"; case Short: return "short";
case Int: return "int"; case Int: return "int";

View File

@ -37,7 +37,8 @@ Value *CodeGenFunction::EvaluateScalarValueToBool(ExprResult Val, QualType Ty) {
assert(Result->getType() == llvm::Type::Int1Ty && assert(Result->getType() == llvm::Type::Int1Ty &&
"Unexpected bool value type!"); "Unexpected bool value type!");
return Result; return Result;
case BuiltinType::Char: case BuiltinType::Char_S:
case BuiltinType::Char_U:
case BuiltinType::SChar: case BuiltinType::SChar:
case BuiltinType::UChar: case BuiltinType::UChar:
case BuiltinType::Short: case BuiltinType::Short:
@ -190,8 +191,6 @@ ExprResult CodeGenFunction::EmitExprWithUsualUnaryConversions(const Expr *E,
// FIXME: this probably isn't right, pending clarification from Steve. // FIXME: this probably isn't right, pending clarification from Steve.
llvm::Value *Val = EmitExpr(E).getVal(); llvm::Value *Val = EmitExpr(E).getVal();
// FIXME: this doesn't handle 'char'!.
// If the input is a signed integer, sign extend to the destination. // If the input is a signed integer, sign extend to the destination.
if (ResTy->isSignedIntegerType()) { if (ResTy->isSignedIntegerType()) {
Val = Builder.CreateSExt(Val, LLVMIntTy, "promote"); Val = Builder.CreateSExt(Val, LLVMIntTy, "promote");

View File

@ -51,7 +51,8 @@ const llvm::Type *CodeGenFunction::ConvertType(QualType T, SourceLocation Loc) {
case BuiltinType::Void: case BuiltinType::Void:
// LLVM void type can only be used as the result of a function call. Just // LLVM void type can only be used as the result of a function call. Just
// map to the same as char. // map to the same as char.
case BuiltinType::Char: case BuiltinType::Char_S:
case BuiltinType::Char_U:
case BuiltinType::SChar: case BuiltinType::SChar:
case BuiltinType::UChar: case BuiltinType::UChar:
return IntegerType::get(Target.getCharWidth(Loc)); return IntegerType::get(Target.getCharWidth(Loc));

View File

@ -233,8 +233,14 @@ public:
/// More type predicates useful for type checking/promotion /// More type predicates useful for type checking/promotion
bool isPromotableIntegerType() const; // C99 6.3.1.1p2 bool isPromotableIntegerType() const; // C99 6.3.1.1p2
bool isSignedIntegerType() const; // C99 6.2.5p4
bool isUnsignedIntegerType() const; // C99 6.2.5p6 /// isSignedIntegerType - Return true if this is an integer type that is
/// signed, according to C99 6.2.5p4.
bool isSignedIntegerType() const;
/// isUnsignedIntegerType - Return true if this is an integer type that is
/// unsigned, according to C99 6.2.5p6. Note that this returns true for _Bool.
bool isUnsignedIntegerType() const;
/// isConstantSizeType - Return true if this is not a variable sized type, /// isConstantSizeType - Return true if this is not a variable sized type,
/// according to the rules of C99 6.7.5p3. If Loc is non-null, it is set to /// according to the rules of C99 6.7.5p3. If Loc is non-null, it is set to
@ -262,9 +268,23 @@ public:
class BuiltinType : public Type { class BuiltinType : public Type {
public: public:
enum Kind { enum Kind {
Void, Bool, Char, Void,
SChar, Short, Int, Long, LongLong,
UChar, UShort, UInt, ULong, ULongLong, Bool, // This is bool and/or _Bool.
Char_U, // This is 'char' for targets where char is unsigned.
UChar, // This is explicitly qualified unsigned char.
UShort,
UInt,
ULong,
ULongLong,
Char_S, // This is 'char' for targets where char is signed.
SChar, // This is explicitly qualified signed char.
Short,
Int,
Long,
LongLong,
Float, Double, LongDouble, Float, Double, LongDouble,
FloatComplex, DoubleComplex, LongDoubleComplex FloatComplex, DoubleComplex, LongDoubleComplex
}; };