[cfe-commits] r143019 - in /cfe/trunk: lib/AST/ASTContext.cpp lib/AST/Type.cpp test/CXX/conv/conv.prom/p2.cpp

Eli Friedman eli.friedman at gmail.com
Wed Oct 26 00:22:49 PDT 2011


Author: efriedma
Date: Wed Oct 26 02:22:48 2011
New Revision: 143019

URL: http://llvm.org/viewvc/llvm-project?rev=143019&view=rev
Log:
Correctly perform integral promotions on wchar_t/char16_t/char32_t in C++. <rdar://problem/10309088>.


Added:
    cfe/trunk/test/CXX/conv/conv.prom/p2.cpp
Modified:
    cfe/trunk/lib/AST/ASTContext.cpp
    cfe/trunk/lib/AST/Type.cpp

Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=143019&r1=143018&r2=143019&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Wed Oct 26 02:22:48 2011
@@ -3549,18 +3549,6 @@
 /// or if it is not canonicalized.
 unsigned ASTContext::getIntegerRank(const Type *T) const {
   assert(T->isCanonicalUnqualified() && "T should be canonicalized");
-  if (const EnumType* ET = dyn_cast<EnumType>(T))
-    T = ET->getDecl()->getPromotionType().getTypePtr();
-
-  if (T->isSpecificBuiltinType(BuiltinType::WChar_S) ||
-      T->isSpecificBuiltinType(BuiltinType::WChar_U))
-    T = getFromTargetType(Target->getWCharType()).getTypePtr();
-
-  if (T->isSpecificBuiltinType(BuiltinType::Char16))
-    T = getFromTargetType(Target->getChar16Type()).getTypePtr();
-
-  if (T->isSpecificBuiltinType(BuiltinType::Char32))
-    T = getFromTargetType(Target->getChar32Type()).getTypePtr();
 
   switch (cast<BuiltinType>(T)->getKind()) {
   default: llvm_unreachable("getIntegerRank(): not a built-in integer");
@@ -3630,6 +3618,34 @@
   assert(Promotable->isPromotableIntegerType());
   if (const EnumType *ET = Promotable->getAs<EnumType>())
     return ET->getDecl()->getPromotionType();
+
+  if (const BuiltinType *BT = Promotable->getAs<BuiltinType>()) {
+    // C++ [conv.prom]: A prvalue of type char16_t, char32_t, or wchar_t
+    // (3.9.1) can be converted to a prvalue of the first of the following
+    // types that can represent all the values of its underlying type:
+    // int, unsigned int, long int, unsigned long int, long long int, or
+    // unsigned long long int [...]
+    // FIXME: Is there some better way to compute this?
+    if (BT->getKind() == BuiltinType::WChar_S ||
+        BT->getKind() == BuiltinType::WChar_U ||
+        BT->getKind() == BuiltinType::Char16 ||
+        BT->getKind() == BuiltinType::Char32) {
+      bool FromIsSigned = BT->getKind() == BuiltinType::WChar_S;
+      uint64_t FromSize = getTypeSize(BT);
+      QualType PromoteTypes[] = { IntTy, UnsignedIntTy, LongTy, UnsignedLongTy,
+                                  LongLongTy, UnsignedLongLongTy };
+      for (size_t Idx = 0; Idx < llvm::array_lengthof(PromoteTypes); ++Idx) {
+        uint64_t ToSize = getTypeSize(PromoteTypes[Idx]);
+        if (FromSize < ToSize ||
+            (FromSize == ToSize &&
+             FromIsSigned == PromoteTypes[Idx]->isSignedIntegerType()))
+          return PromoteTypes[Idx];
+      }
+      llvm_unreachable("char type should fit into long long");
+    }
+  }
+
+  // At this point, we should have a signed or unsigned integer type.
   if (Promotable->isSignedIntegerType())
     return IntTy;
   uint64_t PromotableSize = getTypeSize(Promotable);

Modified: cfe/trunk/lib/AST/Type.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Type.cpp?rev=143019&r1=143018&r2=143019&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Type.cpp (original)
+++ cfe/trunk/lib/AST/Type.cpp Wed Oct 26 02:22:48 2011
@@ -1272,6 +1272,10 @@
     case BuiltinType::UChar:
     case BuiltinType::Short:
     case BuiltinType::UShort:
+    case BuiltinType::WChar_S:
+    case BuiltinType::WChar_U:
+    case BuiltinType::Char16:
+    case BuiltinType::Char32:
       return true;
     default:
       return false;
@@ -1284,10 +1288,7 @@
         || ET->getDecl()->isScoped())
       return false;
     
-    const BuiltinType *BT
-      = ET->getDecl()->getPromotionType()->getAs<BuiltinType>();
-    return BT->getKind() == BuiltinType::Int
-           || BT->getKind() == BuiltinType::UInt;
+    return true;
   }
   
   return false;

Added: cfe/trunk/test/CXX/conv/conv.prom/p2.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/conv/conv.prom/p2.cpp?rev=143019&view=auto
==============================================================================
--- cfe/trunk/test/CXX/conv/conv.prom/p2.cpp (added)
+++ cfe/trunk/test/CXX/conv/conv.prom/p2.cpp Wed Oct 26 02:22:48 2011
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++0x -ffreestanding %s
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++0x -fshort-wchar -ffreestanding %s
+
+#include <stdint.h>
+
+// In theory, the promoted types vary by platform; however, in reality they
+// are quite consistent across all platforms where clang runs.
+
+extern int promoted_wchar;
+extern decltype(+L'a') promoted_wchar;
+
+extern int promoted_char16;
+extern decltype(+u'a') promoted_char16;
+
+extern unsigned promoted_char32;
+extern decltype(+U'a') promoted_char32;





More information about the cfe-commits mailing list