diff options
author | Douglas Gregor <dgregor@apple.com> | 2011-07-27 05:40:30 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2011-07-27 05:40:30 +0000 |
commit | fb65e592e05a83eaa3e9cbd645bace6c68438500 (patch) | |
tree | 612eead4ecf3e89b777c0e6b8456282be228d535 /clang/lib/Sema | |
parent | fdafb7f7e6827b95c04b465a6b28ad819c0d0909 (diff) | |
download | bcm5719-llvm-fb65e592e05a83eaa3e9cbd645bace6c68438500.tar.gz bcm5719-llvm-fb65e592e05a83eaa3e9cbd645bace6c68438500.zip |
Add support for C++0x unicode string and character literals, from Craig Topper!
llvm-svn: 136210
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r-- | clang/lib/Sema/SemaChecking.cpp | 4 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclAttr.cpp | 12 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 39 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExprCXX.cpp | 20 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExprObjC.cpp | 6 | ||||
-rw-r--r-- | clang/lib/Sema/SemaInit.cpp | 32 | ||||
-rw-r--r-- | clang/lib/Sema/SemaStmt.cpp | 8 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplate.cpp | 18 |
8 files changed, 97 insertions, 42 deletions
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 2e4198b5202..28085ef6eab 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -605,7 +605,7 @@ bool Sema::CheckObjCString(Expr *Arg) { Arg = Arg->IgnoreParenCasts(); StringLiteral *Literal = dyn_cast<StringLiteral>(Arg); - if (!Literal || Literal->isWide()) { + if (!Literal || !Literal->isAscii()) { Diag(Arg->getLocStart(), diag::err_cfstring_literal_not_string_constant) << Arg->getSourceRange(); return true; @@ -1805,7 +1805,7 @@ void Sema::CheckFormatString(const StringLiteral *FExpr, bool isPrintf) { // CHECK: is the format string a wide literal? - if (FExpr->isWide()) { + if (!FExpr->isAscii()) { Diag(FExpr->getLocStart(), diag::warn_format_string_is_wide_literal) << OrigFormatExpr->getSourceRange(); diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 9e20bc90184..2cbd83a8fd8 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -712,7 +712,7 @@ static void handleWeakRefAttr(Sema &S, Decl *D, const AttributeList &Attr) { Arg = Arg->IgnoreParenCasts(); StringLiteral *Str = dyn_cast<StringLiteral>(Arg); - if (Str == 0 || Str->isWide()) { + if (!Str || !Str->isAscii()) { S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string) << "weakref" << 1; return; @@ -737,7 +737,7 @@ static void handleAliasAttr(Sema &S, Decl *D, const AttributeList &Attr) { Arg = Arg->IgnoreParenCasts(); StringLiteral *Str = dyn_cast<StringLiteral>(Arg); - if (Str == 0 || Str->isWide()) { + if (!Str || !Str->isAscii()) { S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string) << "alias" << 1; return; @@ -1162,7 +1162,7 @@ static void handleVisibilityAttr(Sema &S, Decl *D, const AttributeList &Attr) { Arg = Arg->IgnoreParenCasts(); StringLiteral *Str = dyn_cast<StringLiteral>(Arg); - if (Str == 0 || Str->isWide()) { + if (!Str || !Str->isAscii()) { S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string) << "visibility" << 1; return; @@ -2464,7 +2464,7 @@ static void handleCallConvAttr(Sema &S, Decl *D, const AttributeList &Attr) { case AttributeList::AT_pcs: { Expr *Arg = Attr.getArg(0); StringLiteral *Str = dyn_cast<StringLiteral>(Arg); - if (Str == 0 || Str->isWide()) { + if (!Str || !Str->isAscii()) { S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string) << "pcs" << 1; Attr.setInvalid(); @@ -2519,7 +2519,7 @@ bool Sema::CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC) { case AttributeList::AT_pcs: { Expr *Arg = attr.getArg(0); StringLiteral *Str = dyn_cast<StringLiteral>(Arg); - if (Str == 0 || Str->isWide()) { + if (!Str || !Str->isAscii()) { Diag(attr.getLoc(), diag::err_attribute_argument_n_not_string) << "pcs" << 1; attr.setInvalid(); @@ -2868,7 +2868,7 @@ static void handleUuidAttr(Sema &S, Decl *D, const AttributeList &Attr) { Expr *Arg = Attr.getArg(0); StringLiteral *Str = dyn_cast<StringLiteral>(Arg); - if (Str == 0 || Str->isWide()) { + if (!Str || !Str->isAscii()) { S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string) << "uuid" << 1; return; diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 4a9b4bcfdf0..dedf7b0d778 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -997,11 +997,25 @@ Sema::ActOnStringLiteral(const Token *StringToks, unsigned NumStringToks) { StringTokLocs.push_back(StringToks[i].getLocation()); QualType StrTy = Context.CharTy; - if (Literal.AnyWide) + if (Literal.isWide()) StrTy = Context.getWCharType(); + else if (Literal.isUTF16()) + StrTy = Context.Char16Ty; + else if (Literal.isUTF32()) + StrTy = Context.Char32Ty; else if (Literal.Pascal) StrTy = Context.UnsignedCharTy; + StringLiteral::StringKind Kind = StringLiteral::Ascii; + if (Literal.isWide()) + Kind = StringLiteral::Wide; + else if (Literal.isUTF8()) + Kind = StringLiteral::UTF8; + else if (Literal.isUTF16()) + Kind = StringLiteral::UTF16; + else if (Literal.isUTF32()) + Kind = StringLiteral::UTF32; + // A C++ string literal has a const-qualified element type (C++ 2.13.4p1). if (getLangOptions().CPlusPlus || getLangOptions().ConstStrings) StrTy.addConst(); @@ -1015,7 +1029,7 @@ Sema::ActOnStringLiteral(const Token *StringToks, unsigned NumStringToks) { // Pass &StringTokLocs[0], StringTokLocs.size() to factory! return Owned(StringLiteral::Create(Context, Literal.GetString(), - Literal.AnyWide, Literal.Pascal, StrTy, + Kind, Literal.Pascal, StrTy, &StringTokLocs[0], StringTokLocs.size())); } @@ -2412,7 +2426,7 @@ ExprResult Sema::ActOnCharacterConstant(const Token &Tok) { return ExprError(); CharLiteralParser Literal(ThisTok.begin(), ThisTok.end(), Tok.getLocation(), - PP); + PP, Tok.getKind()); if (Literal.hadError()) return ExprError(); @@ -2421,14 +2435,25 @@ ExprResult Sema::ActOnCharacterConstant(const Token &Tok) { Ty = Context.IntTy; // 'x' and L'x' -> int in C. else if (Literal.isWide()) Ty = Context.WCharTy; // L'x' -> wchar_t in C++. + else if (Literal.isUTF16()) + Ty = Context.Char16Ty; // u'x' -> char16_t in C++0x. + else if (Literal.isUTF32()) + Ty = Context.Char32Ty; // U'x' -> char32_t in C++0x. else if (Literal.isMultiChar()) Ty = Context.IntTy; // 'wxyz' -> int in C++. else Ty = Context.CharTy; // 'x' -> char in C++ - return Owned(new (Context) CharacterLiteral(Literal.getValue(), - Literal.isWide(), - Ty, Tok.getLocation())); + CharacterLiteral::CharacterKind Kind = CharacterLiteral::Ascii; + if (Literal.isWide()) + Kind = CharacterLiteral::Wide; + else if (Literal.isUTF16()) + Kind = CharacterLiteral::UTF16; + else if (Literal.isUTF32()) + Kind = CharacterLiteral::UTF32; + + return Owned(new (Context) CharacterLiteral(Literal.getValue(), Kind, Ty, + Tok.getLocation())); } ExprResult Sema::ActOnNumericConstant(const Token &Tok) { @@ -8624,7 +8649,7 @@ static void MakeObjCStringLiteralFixItHint(Sema& SemaRef, QualType DstType, // Strip off any parens and casts. StringLiteral *SL = dyn_cast<StringLiteral>(SrcExpr->IgnoreParenCasts()); - if (!SL || SL->isWide()) + if (!SL || !SL->isAscii()) return; Hint = FixItHint::CreateInsertion(SL->getLocStart(), "@"); diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 94a5bafa7c7..1812510942e 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -2041,12 +2041,20 @@ Sema::IsStringLiteralToNonConstPointerConversion(Expr *From, QualType ToType) { = ToPtrType->getPointeeType()->getAs<BuiltinType>()) { // This conversion is considered only when there is an // explicit appropriate pointer target type (C++ 4.2p2). - if (!ToPtrType->getPointeeType().hasQualifiers() && - ((StrLit->isWide() && ToPointeeType->isWideCharType()) || - (!StrLit->isWide() && - (ToPointeeType->getKind() == BuiltinType::Char_U || - ToPointeeType->getKind() == BuiltinType::Char_S)))) - return true; + if (!ToPtrType->getPointeeType().hasQualifiers()) { + switch (StrLit->getKind()) { + case StringLiteral::UTF8: + case StringLiteral::UTF16: + case StringLiteral::UTF32: + // We don't allow UTF literals to be implicitly converted + break; + case StringLiteral::Ascii: + return (ToPointeeType->getKind() == BuiltinType::Char_U || + ToPointeeType->getKind() == BuiltinType::Char_S); + case StringLiteral::Wide: + return ToPointeeType->isWideCharType(); + } + } } return false; diff --git a/clang/lib/Sema/SemaExprObjC.cpp b/clang/lib/Sema/SemaExprObjC.cpp index fccea7c0e1b..e88726b6d2a 100644 --- a/clang/lib/Sema/SemaExprObjC.cpp +++ b/clang/lib/Sema/SemaExprObjC.cpp @@ -47,8 +47,8 @@ ExprResult Sema::ParseObjCStringLiteral(SourceLocation *AtLocs, for (unsigned i = 0; i != NumStrings; ++i) { S = Strings[i]; - // ObjC strings can't be wide. - if (S->isWide()) { + // ObjC strings can't be wide or UTF. + if (!S->isAscii()) { Diag(S->getLocStart(), diag::err_cfstring_literal_not_string_constant) << S->getSourceRange(); return true; @@ -64,7 +64,7 @@ ExprResult Sema::ParseObjCStringLiteral(SourceLocation *AtLocs, // Create the aggregate string with the appropriate content and location // information. S = StringLiteral::Create(Context, StrBuf, - /*Wide=*/false, /*Pascal=*/false, + StringLiteral::Ascii, /*Pascal=*/false, Context.getPointerType(Context.CharTy), &StrLocs[0], StrLocs.size()); } diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index adf88c62ccd..c406ad98405 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -49,20 +49,30 @@ static Expr *IsStringInit(Expr *Init, const ArrayType *AT, if (SL == 0) return 0; QualType ElemTy = Context.getCanonicalType(AT->getElementType()); - // char array can be initialized with a narrow string. - // Only allow char x[] = "foo"; not char x[] = L"foo"; - if (!SL->isWide()) + + switch (SL->getKind()) { + case StringLiteral::Ascii: + case StringLiteral::UTF8: + // char array can be initialized with a narrow string. + // Only allow char x[] = "foo"; not char x[] = L"foo"; return ElemTy->isCharType() ? Init : 0; + case StringLiteral::UTF16: + return ElemTy->isChar16Type() ? Init : 0; + case StringLiteral::UTF32: + return ElemTy->isChar32Type() ? Init : 0; + case StringLiteral::Wide: + // wchar_t array can be initialized with a wide string: C99 6.7.8p15 (with + // correction from DR343): "An array with element type compatible with a + // qualified or unqualified version of wchar_t may be initialized by a wide + // string literal, optionally enclosed in braces." + if (Context.typesAreCompatible(Context.getWCharType(), + ElemTy.getUnqualifiedType())) + return Init; - // wchar_t array can be initialized with a wide string: C99 6.7.8p15 (with - // correction from DR343): "An array with element type compatible with a - // qualified or unqualified version of wchar_t may be initialized by a wide - // string literal, optionally enclosed in braces." - if (Context.typesAreCompatible(Context.getWCharType(), - ElemTy.getUnqualifiedType())) - return Init; + return 0; + } - return 0; + llvm_unreachable("missed a StringLiteral kind?"); } static Expr *IsStringInit(Expr *init, QualType declType, ASTContext &Context) { diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index 0fd3f039823..56161ed9b45 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -1952,13 +1952,13 @@ StmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc, bool IsSimple, SmallVector<TargetInfo::ConstraintInfo, 4> OutputConstraintInfos; // The parser verifies that there is a string literal here. - if (AsmString->isWide()) + if (!AsmString->isAscii()) return StmtError(Diag(AsmString->getLocStart(),diag::err_asm_wide_character) << AsmString->getSourceRange()); for (unsigned i = 0; i != NumOutputs; i++) { StringLiteral *Literal = Constraints[i]; - if (Literal->isWide()) + if (!Literal->isAscii()) return StmtError(Diag(Literal->getLocStart(),diag::err_asm_wide_character) << Literal->getSourceRange()); @@ -1987,7 +1987,7 @@ StmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc, bool IsSimple, for (unsigned i = NumOutputs, e = NumOutputs + NumInputs; i != e; i++) { StringLiteral *Literal = Constraints[i]; - if (Literal->isWide()) + if (!Literal->isAscii()) return StmtError(Diag(Literal->getLocStart(),diag::err_asm_wide_character) << Literal->getSourceRange()); @@ -2034,7 +2034,7 @@ StmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc, bool IsSimple, // Check that the clobbers are valid. for (unsigned i = 0; i != NumClobbers; i++) { StringLiteral *Literal = Clobbers[i]; - if (Literal->isWide()) + if (!Literal->isAscii()) return StmtError(Diag(Literal->getLocStart(),diag::err_asm_wide_character) << Literal->getSourceRange()); diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index ceab7e93ac6..006017f5a47 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -4131,10 +4131,22 @@ Sema::BuildExpressionFromIntegralTemplateArgument(const TemplateArgument &Arg, assert(Arg.getKind() == TemplateArgument::Integral && "Operation is only valid for integral template arguments"); QualType T = Arg.getIntegralType(); - if (T->isCharType() || T->isWideCharType()) + if (T->isAnyCharacterType()) { + CharacterLiteral::CharacterKind Kind; + if (T->isWideCharType()) + Kind = CharacterLiteral::Wide; + else if (T->isChar16Type()) + Kind = CharacterLiteral::UTF16; + else if (T->isChar32Type()) + Kind = CharacterLiteral::UTF32; + else + Kind = CharacterLiteral::Ascii; + return Owned(new (Context) CharacterLiteral( - Arg.getAsIntegral()->getZExtValue(), - T->isWideCharType(), T, Loc)); + Arg.getAsIntegral()->getZExtValue(), + Kind, T, Loc)); + } + if (T->isBooleanType()) return Owned(new (Context) CXXBoolLiteralExpr( Arg.getAsIntegral()->getBoolValue(), |