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
diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp
index 9200c18..affb061 100644
--- a/lib/Sema/SemaInit.cpp
+++ b/lib/Sema/SemaInit.cpp
@@ -82,6 +82,17 @@
   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<ParenExpr>(E)) {
+    E->setType(Ty);
+    E = PE->getSubExpr();
+  }
+  assert(isa<StringLiteral>(E) || isa<ObjCEncodeExpr>(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 @@
     DeclT = S.Context.getConstantArrayType(IAT->getElementType(),
                                            ConstVal,
                                            ArrayType::Normal, 0);
-    Str->setType(DeclT);
+    updateStringLiteralType(Str, DeclT);
     return;
   }
 
@@ -107,7 +118,7 @@
   // 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<StringLiteral>(Str)) {
+    if (StringLiteral *SL = dyn_cast<StringLiteral>(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 @@
   // 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 1d377eb..09a9cb5 100644
--- a/test/SemaCXX/constant-expression-cxx11.cpp
+++ b/test/SemaCXX/constant-expression-cxx11.cpp
@@ -414,6 +414,19 @@
 };
 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 89194b5..f4c692d 100644
--- a/test/SemaCXX/pascal-strings.cpp
+++ b/test/SemaCXX/pascal-strings.cpp
@@ -4,3 +4,5 @@
 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}}