From 30ae1ed71dc99a396b7ddba9cabe9846a0c4449d Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Sun, 5 May 2013 16:40:13 +0000 Subject: [PATCH] Handle parens properly when initializing a char array from a string literal. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@181159 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaInit.cpp | 17 ++++++++++++++--- test/SemaCXX/constant-expression-cxx11.cpp | 13 +++++++++++++ test/SemaCXX/pascal-strings.cpp | 2 ++ 3 files changed, 29 insertions(+), 3 deletions(-) diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index 9200c181aa..affb061467 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -82,6 +82,17 @@ static Expr *IsStringInit(Expr *init, QualType declType, ASTContext &Context) { return IsStringInit(init, arrayType, Context); } +/// Update the type of a string literal, including any surrounding parentheses, +/// to match the type of the object which it is initializing. +static void updateStringLiteralType(Expr *E, QualType Ty) { + while (ParenExpr *PE = dyn_cast(E)) { + E->setType(Ty); + E = PE->getSubExpr(); + } + assert(isa(E) || isa(E)); + E->setType(Ty); +} + static void CheckStringInit(Expr *Str, QualType &DeclT, const ArrayType *AT, Sema &S) { // Get the length of the string as parsed. @@ -97,7 +108,7 @@ static void CheckStringInit(Expr *Str, QualType &DeclT, const ArrayType *AT, DeclT = S.Context.getConstantArrayType(IAT->getElementType(), ConstVal, ArrayType::Normal, 0); - Str->setType(DeclT); + updateStringLiteralType(Str, DeclT); return; } @@ -107,7 +118,7 @@ static void CheckStringInit(Expr *Str, QualType &DeclT, const ArrayType *AT, // the size may be smaller or larger than the string we are initializing. // FIXME: Avoid truncation for 64-bit length strings. if (S.getLangOpts().CPlusPlus) { - if (StringLiteral *SL = dyn_cast(Str)) { + if (StringLiteral *SL = dyn_cast(Str->IgnoreParens())) { // For Pascal strings it's OK to strip off the terminating null character, // so the example below is valid: // @@ -133,7 +144,7 @@ static void CheckStringInit(Expr *Str, QualType &DeclT, const ArrayType *AT, // something like: // char x[1] = "foo"; // then this will set the string literal's type to char[1]. - Str->setType(DeclT); + updateStringLiteralType(Str, DeclT); } //===----------------------------------------------------------------------===// diff --git a/test/SemaCXX/constant-expression-cxx11.cpp b/test/SemaCXX/constant-expression-cxx11.cpp index 1d377eb81d..09a9cb5dd8 100644 --- a/test/SemaCXX/constant-expression-cxx11.cpp +++ b/test/SemaCXX/constant-expression-cxx11.cpp @@ -414,6 +414,19 @@ struct V { }; static_assert(V().c[1] == "i"[0], ""); +namespace Parens { + constexpr unsigned char a[] = ("foo"), b[] = {"foo"}, c[] = {("foo")}, + d[4] = ("foo"), e[5] = {"foo"}, f[6] = {("foo")}; + static_assert(a[0] == 'f', ""); + static_assert(b[1] == 'o', ""); + static_assert(c[2] == 'o', ""); + static_assert(d[0] == 'f', ""); + static_assert(e[1] == 'o', ""); + static_assert(f[2] == 'o', ""); + static_assert(f[5] == 0, ""); + static_assert(f[6] == 0, ""); // expected-error {{constant expression}} expected-note {{one-past-the-end}} +} + } namespace Array { diff --git a/test/SemaCXX/pascal-strings.cpp b/test/SemaCXX/pascal-strings.cpp index 89194b54aa..f4c692db58 100644 --- a/test/SemaCXX/pascal-strings.cpp +++ b/test/SemaCXX/pascal-strings.cpp @@ -4,3 +4,5 @@ const wchar_t *pascalString = L"\pThis is a Pascal string"; unsigned char a[3] = "\pa"; unsigned char b[3] = "\pab"; unsigned char c[3] = "\pabc"; // expected-error {{initializer-string for char array is too long}} +unsigned char d[3] = ("\pab"); +unsigned char e[3] = ("\pabc"); // expected-error {{initializer-string for char array is too long}} -- 2.40.0