diff --git a/clang/AST/ASTContext.cpp b/clang/AST/ASTContext.cpp index 8c4e7c3905b2..36eda88ed177 100644 --- a/clang/AST/ASTContext.cpp +++ b/clang/AST/ASTContext.cpp @@ -110,7 +110,10 @@ void ASTContext::InitBuiltinTypes() { // C99 6.2.5p2. InitBuiltinType(BoolTy, BuiltinType::Bool); // 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. InitBuiltinType(SignedCharTy, BuiltinType::SChar); InitBuiltinType(ShortTy, BuiltinType::Short); @@ -347,7 +350,8 @@ unsigned ASTContext::getIntegerBitwidth(QualType T, SourceLocation Loc) { switch (BT->getKind()) { default: assert(0 && "getIntegerBitwidth(): not a built-in integer"); case BuiltinType::Bool: return Target.getBoolWidth(Loc); - case BuiltinType::Char: + case BuiltinType::Char_S: + case BuiltinType::Char_U: case BuiltinType::SChar: case BuiltinType::UChar: return Target.getCharWidth(Loc); case BuiltinType::Short: @@ -375,7 +379,8 @@ static int getIntegerRank(QualType t) { assert(0 && "getIntegerRank(): not a built-in integer"); case BuiltinType::Bool: return 1; - case BuiltinType::Char: + case BuiltinType::Char_S: + case BuiltinType::Char_U: case BuiltinType::SChar: case BuiltinType::UChar: return 2; @@ -448,6 +453,8 @@ QualType ASTContext::maxFloatingType(QualType lt, QualType rt) { // maxIntegerType - Returns the highest ranked integer type. Handles 3 case: // unsigned/unsigned, signed/signed, signed/unsigned. C99 6.3.1.8p1. QualType ASTContext::maxIntegerType(QualType lhs, QualType rhs) { + if (lhs == rhs) return lhs; + bool t1Unsigned = lhs->isUnsignedIntegerType(); bool t2Unsigned = rhs->isUnsignedIntegerType(); diff --git a/clang/AST/Type.cpp b/clang/AST/Type.cpp index 4eb9b2657db4..36f312ef795d 100644 --- a/clang/AST/Type.cpp +++ b/clang/AST/Type.cpp @@ -15,6 +15,7 @@ #include "clang/AST/Type.h" #include "clang/AST/Decl.h" #include "clang/AST/Expr.h" +#include "clang/Basic/TargetInfo.h" #include "llvm/Support/Streams.h" using namespace llvm; @@ -235,16 +236,18 @@ bool Type::isIntegerType() const { } bool Type::isSignedIntegerType() const { - if (const BuiltinType *BT = dyn_cast(CanonicalType)) - return BT->getKind() >= BuiltinType::SChar && + if (const BuiltinType *BT = dyn_cast(CanonicalType)) { + return BT->getKind() >= BuiltinType::Char_S && BT->getKind() <= BuiltinType::LongLong; + } return false; } bool Type::isUnsignedIntegerType() const { - if (const BuiltinType *BT = dyn_cast(CanonicalType)) - return BT->getKind() >= BuiltinType::UChar && + if (const BuiltinType *BT = dyn_cast(CanonicalType)) { + return BT->getKind() >= BuiltinType::Bool && BT->getKind() <= BuiltinType::ULongLong; + } return false; } @@ -343,20 +346,20 @@ bool Type::isIncompleteType() const { } bool Type::isPromotableIntegerType() const { - if (const BuiltinType *BT = dyn_cast(CanonicalType)) { - switch (BT->getKind()) { - case BuiltinType::Bool: - case BuiltinType::Char: - case BuiltinType::SChar: - case BuiltinType::UChar: - case BuiltinType::Short: - case BuiltinType::UShort: - return true; - default: - return false; - } + const BuiltinType *BT = dyn_cast(CanonicalType); + if (!BT) return false; + switch (BT->getKind()) { + case BuiltinType::Bool: + case BuiltinType::Char_S: + case BuiltinType::Char_U: + case BuiltinType::SChar: + case BuiltinType::UChar: + case BuiltinType::Short: + case BuiltinType::UShort: + return true; + default: + return false; } - return false; } const char *BuiltinType::getName() const { @@ -364,7 +367,8 @@ const char *BuiltinType::getName() const { default: assert(0 && "Unknown builtin type!"); case Void: return "void"; case Bool: return "_Bool"; - case Char: return "char"; + case Char_S: return "char"; + case Char_U: return "char"; case SChar: return "signed char"; case Short: return "short"; case Int: return "int"; diff --git a/clang/CodeGen/CGExpr.cpp b/clang/CodeGen/CGExpr.cpp index 87cfd1d82b22..17c7c016743b 100644 --- a/clang/CodeGen/CGExpr.cpp +++ b/clang/CodeGen/CGExpr.cpp @@ -37,7 +37,8 @@ Value *CodeGenFunction::EvaluateScalarValueToBool(ExprResult Val, QualType Ty) { assert(Result->getType() == llvm::Type::Int1Ty && "Unexpected bool value type!"); return Result; - case BuiltinType::Char: + case BuiltinType::Char_S: + case BuiltinType::Char_U: case BuiltinType::SChar: case BuiltinType::UChar: case BuiltinType::Short: @@ -190,8 +191,6 @@ ExprResult CodeGenFunction::EmitExprWithUsualUnaryConversions(const Expr *E, // FIXME: this probably isn't right, pending clarification from Steve. 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 (ResTy->isSignedIntegerType()) { Val = Builder.CreateSExt(Val, LLVMIntTy, "promote"); diff --git a/clang/CodeGen/CodeGenFunction.cpp b/clang/CodeGen/CodeGenFunction.cpp index 9da66c635bdd..57d9e8be660c 100644 --- a/clang/CodeGen/CodeGenFunction.cpp +++ b/clang/CodeGen/CodeGenFunction.cpp @@ -51,7 +51,8 @@ const llvm::Type *CodeGenFunction::ConvertType(QualType T, SourceLocation Loc) { case BuiltinType::Void: // LLVM void type can only be used as the result of a function call. Just // map to the same as char. - case BuiltinType::Char: + case BuiltinType::Char_S: + case BuiltinType::Char_U: case BuiltinType::SChar: case BuiltinType::UChar: return IntegerType::get(Target.getCharWidth(Loc)); diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h index 3f7f1bb46f26..9b50b89c9e55 100644 --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -233,8 +233,14 @@ public: /// More type predicates useful for type checking/promotion 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, /// 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 { public: enum Kind { - Void, Bool, Char, - SChar, Short, Int, Long, LongLong, - UChar, UShort, UInt, ULong, ULongLong, + Void, + + 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, FloatComplex, DoubleComplex, LongDoubleComplex };