forked from OSchip/llvm-project
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:
parent
cf25024828
commit
b16f455e8c
|
@ -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();
|
||||||
|
|
||||||
|
|
|
@ -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";
|
||||||
|
|
|
@ -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");
|
||||||
|
|
|
@ -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));
|
||||||
|
|
|
@ -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
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue