From d5bbce4382622feb4ca5978c4bb8fcceb7aaec00 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Wed, 29 Aug 2007 17:48:46 +0000 Subject: [PATCH] Teach Type::is[un]SignedIntegerType about enum decls. This allows the code generator to emit signed comparisons when needed for enum decl references. This implements test/CodeGen/enum.c. I think enums should be good now. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@41572 91177308-0d34-0410-b5e6-96231b3b80d8 --- AST/Type.cpp | 18 ++++++++++++++++++ include/clang/AST/Type.h | 10 +++++++--- test/CodeGen/enum.c | 18 ++++++++++++++++++ 3 files changed, 43 insertions(+), 3 deletions(-) create mode 100644 test/CodeGen/enum.c diff --git a/AST/Type.cpp b/AST/Type.cpp index f4c5aa748f..9fca35a66e 100644 --- a/AST/Type.cpp +++ b/AST/Type.cpp @@ -391,21 +391,39 @@ bool Type::isCharType() const { return false; } +/// isSignedIntegerType - Return true if this is an integer type that is +/// signed, according to C99 6.2.5p4 [char, signed char, short, int, long..], +/// an enum decl which has a signed representation, or a vector of signed +/// integer element type. bool Type::isSignedIntegerType() const { if (const BuiltinType *BT = dyn_cast(CanonicalType)) { return BT->getKind() >= BuiltinType::Char_S && BT->getKind() <= BuiltinType::LongLong; } + + if (const TagType *TT = dyn_cast(CanonicalType)) + if (const EnumDecl *ED = dyn_cast(TT->getDecl())) + return ED->getIntegerType()->isSignedIntegerType(); + if (const VectorType *VT = dyn_cast(CanonicalType)) return VT->getElementType()->isSignedIntegerType(); return false; } +/// isUnsignedIntegerType - Return true if this is an integer type that is +/// unsigned, according to C99 6.2.5p6 [which returns true for _Bool], an enum +/// decl which has an unsigned representation, or a vector of unsigned integer +/// element type. bool Type::isUnsignedIntegerType() const { if (const BuiltinType *BT = dyn_cast(CanonicalType)) { return BT->getKind() >= BuiltinType::Bool && BT->getKind() <= BuiltinType::ULongLong; } + + if (const TagType *TT = dyn_cast(CanonicalType)) + if (const EnumDecl *ED = dyn_cast(TT->getDecl())) + return ED->getIntegerType()->isUnsignedIntegerType(); + if (const VectorType *VT = dyn_cast(CanonicalType)) return VT->getElementType()->isUnsignedIntegerType(); return false; diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index 9c72b050c5..54cc77c55b 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -279,13 +279,17 @@ public: bool isPromotableIntegerType() const; // C99 6.3.1.1p2 /// isSignedIntegerType - Return true if this is an integer type that is - /// signed, according to C99 6.2.5p4. + /// signed, according to C99 6.2.5p4 [char, signed char, short, int, long..], + /// an enum decl which has a signed representation, or a vector of signed + /// integer element type. 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. + /// unsigned, according to C99 6.2.5p6 [which returns true for _Bool], an enum + /// decl which has an unsigned representation, or a vector of unsigned integer + /// element type. 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 /// the location of the subexpression that makes it a vla type. It is not diff --git a/test/CodeGen/enum.c b/test/CodeGen/enum.c new file mode 100644 index 0000000000..f671dfca0c --- /dev/null +++ b/test/CodeGen/enum.c @@ -0,0 +1,18 @@ +// RUN: clang %s -emit-llvm | llvm-as | opt -std-compile-opts | llvm-dis | grep 'ret i32 6' + +static enum { foo, bar = 1U } z; + +int main (void) +{ + int r = 0; + + if (bar - 2 < 0) + r += 4; + if (foo - 1 < 0) + r += 2; + if (z - 1 < 0) + r++; + + return r; +} + -- 2.40.0