r353762 - [Sema] Mark GNU compound literal array init as an rvalue.

Eli Friedman via cfe-commits cfe-commits at lists.llvm.org
Mon Feb 11 14:54:27 PST 2019


Author: efriedma
Date: Mon Feb 11 14:54:27 2019
New Revision: 353762

URL: http://llvm.org/viewvc/llvm-project?rev=353762&view=rev
Log:
[Sema] Mark GNU compound literal array init as an rvalue.

Basically the same issue as string init, except it didn't really have
any visible consequences before I removed the implicit lvalue-to-rvalue
conversion from CodeGen.

While I'm here, a couple minor drive-by cleanups: IgnoreParens never
returns a ConstantExpr, and there was a potential crash with string init
involving a ChooseExpr.

The analyzer test change maybe indicates we could simplify the analyzer
code a little with this fix?  Apparently a hack was added to support
lvalues in initializers in r315750, but I'm not really familiar with the
relevant code.

Fixes regression reported in the kernel build at
https://bugs.llvm.org/show_bug.cgi?id=40430#c6 .

Differential Revision: https://reviews.llvm.org/D58069


Modified:
    cfe/trunk/lib/Sema/SemaInit.cpp
    cfe/trunk/test/Analysis/compound-literals.c
    cfe/trunk/test/CodeGen/compound-literal.c

Modified: cfe/trunk/lib/Sema/SemaInit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=353762&r1=353761&r2=353762&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaInit.cpp (original)
+++ cfe/trunk/lib/Sema/SemaInit.cpp Mon Feb 11 14:54:27 2019
@@ -145,16 +145,42 @@ static void updateStringLiteralType(Expr
   while (true) {
     E->setType(Ty);
     E->setValueKind(VK_RValue);
-    if (isa<StringLiteral>(E) || isa<ObjCEncodeExpr>(E))
+    if (isa<StringLiteral>(E) || isa<ObjCEncodeExpr>(E)) {
       break;
-    else if (ParenExpr *PE = dyn_cast<ParenExpr>(E))
+    } else if (ParenExpr *PE = dyn_cast<ParenExpr>(E)) {
       E = PE->getSubExpr();
-    else if (UnaryOperator *UO = dyn_cast<UnaryOperator>(E))
+    } else if (UnaryOperator *UO = dyn_cast<UnaryOperator>(E)) {
+      assert(UO->getOpcode() == UO_Extension);
       E = UO->getSubExpr();
-    else if (GenericSelectionExpr *GSE = dyn_cast<GenericSelectionExpr>(E))
+    } else if (GenericSelectionExpr *GSE = dyn_cast<GenericSelectionExpr>(E)) {
       E = GSE->getResultExpr();
-    else
+    } else if (ChooseExpr *CE = dyn_cast<ChooseExpr>(E)) {
+      E = CE->getChosenSubExpr();
+    } else {
       llvm_unreachable("unexpected expr in string literal init");
+    }
+  }
+}
+
+/// Fix a compound literal initializing an array so it's correctly marked
+/// as an rvalue.
+static void updateGNUCompoundLiteralRValue(Expr *E) {
+  while (true) {
+    E->setValueKind(VK_RValue);
+    if (isa<CompoundLiteralExpr>(E)) {
+      break;
+    } else if (ParenExpr *PE = dyn_cast<ParenExpr>(E)) {
+      E = PE->getSubExpr();
+    } else if (UnaryOperator *UO = dyn_cast<UnaryOperator>(E)) {
+      assert(UO->getOpcode() == UO_Extension);
+      E = UO->getSubExpr();
+    } else if (GenericSelectionExpr *GSE = dyn_cast<GenericSelectionExpr>(E)) {
+      E = GSE->getResultExpr();
+    } else if (ChooseExpr *CE = dyn_cast<ChooseExpr>(E)) {
+      E = CE->getChosenSubExpr();
+    } else {
+      llvm_unreachable("unexpected expr in array compound literal init");
+    }
   }
 }
 
@@ -5542,8 +5568,7 @@ void InitializationSequence::InitializeF
     // array from a compound literal that creates an array of the same
     // type, so long as the initializer has no side effects.
     if (!S.getLangOpts().CPlusPlus && Initializer &&
-        (isa<ConstantExpr>(Initializer->IgnoreParens()) ||
-         isa<CompoundLiteralExpr>(Initializer->IgnoreParens())) &&
+        isa<CompoundLiteralExpr>(Initializer->IgnoreParens()) &&
         Initializer->getType()->isArrayType()) {
       const ArrayType *SourceAT
         = Context.getAsArrayType(Initializer->getType());
@@ -7956,6 +7981,7 @@ ExprResult InitializationSequence::Perfo
       S.Diag(Kind.getLocation(), diag::ext_array_init_copy)
         << Step->Type << CurInit.get()->getType()
         << CurInit.get()->getSourceRange();
+      updateGNUCompoundLiteralRValue(CurInit.get());
       LLVM_FALLTHROUGH;
     case SK_ArrayInit:
       // If the destination type is an incomplete array type, update the

Modified: cfe/trunk/test/Analysis/compound-literals.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/compound-literals.c?rev=353762&r1=353761&r2=353762&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/compound-literals.c (original)
+++ cfe/trunk/test/Analysis/compound-literals.c Mon Feb 11 14:54:27 2019
@@ -4,6 +4,5 @@ void clang_analyzer_eval(int);
 // pr28449: Used to crash.
 void foo(void) {
   static const unsigned short array[] = (const unsigned short[]){0x0F00};
-  // FIXME: Should be true.
-  clang_analyzer_eval(array[0] == 0x0F00); // expected-warning{{UNKNOWN}}
+  clang_analyzer_eval(array[0] == 0x0F00); // expected-warning{{TRUE}}
 }

Modified: cfe/trunk/test/CodeGen/compound-literal.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/compound-literal.c?rev=353762&r1=353761&r2=353762&view=diff
==============================================================================
--- cfe/trunk/test/CodeGen/compound-literal.c (original)
+++ cfe/trunk/test/CodeGen/compound-literal.c Mon Feb 11 14:54:27 2019
@@ -11,6 +11,11 @@ _Complex double * x = &(_Complex double)
 typedef int v4i32 __attribute((vector_size(16)));
 v4i32 *y = &(v4i32){1,2,3,4};
 
+// Check generated code for GNU constant array init from compound literal,
+// for a global variable.
+// CHECK: @compound_array = global [8 x i32] [i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8]
+int compound_array[] = __extension__(__builtin_choose_expr(0, 0, _Generic(1, int: (int[]){1, 2, 3, 4, 5, 6, 7, 8})));
+
 void xxx() {
 int* a = &(int){1};
 struct s {int a, b, c;} * b = &(struct s) {1, 2, 3};
@@ -82,3 +87,13 @@ int compareMyCLH() {
   const void *b = MyCLH;
   return a == b;
 }
+
+// Check generated code for GNU constant array init from compound literal,
+// for a local variable.
+// CHECK-LABEL: define i32 @compound_array_fn()
+// CHECK: [[COMPOUND_ARRAY:%.*]] = alloca [8 x i32]
+// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}, i64 32, i1 false)
+int compound_array_fn() {
+  int compound_array[] = (int[]){1,2,3,4,5,6,7,8};
+  return compound_array[0];
+}




More information about the cfe-commits mailing list