[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