<div dir="auto">This seems is wrong way to handle this, and seems likely to be unsound in C++. We should be creating a ConstantExpr node wrapped around the initializer instead.</div><br><div class="gmail_quote"><div dir="ltr">On Sat, 1 Dec 2018, 00:32 Bill Wendling via cfe-commits <<a href="mailto:cfe-commits@lists.llvm.org">cfe-commits@lists.llvm.org</a> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: void<br>
Date: Sat Dec  1 00:29:36 2018<br>
New Revision: 348070<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=348070&view=rev" rel="noreferrer noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=348070&view=rev</a><br>
Log:<br>
Specify constant context in constant emitter<br>
<br>
The constant emitter may need to evaluate the expression in a constant context.<br>
For exasmple, global initializer lists.<br>
<br>
Added:<br>
    cfe/trunk/test/CodeGen/builtin-constant-p.c<br>
Modified:<br>
    cfe/trunk/lib/AST/ExprConstant.cpp<br>
    cfe/trunk/lib/CodeGen/CGExprConstant.cpp<br>
    cfe/trunk/lib/CodeGen/ConstantEmitter.h<br>
    cfe/trunk/test/Analysis/builtin-functions.cpp<br>
<br>
Modified: cfe/trunk/lib/AST/ExprConstant.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=348070&r1=348069&r2=348070&view=diff" rel="noreferrer noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=348070&r1=348069&r2=348070&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/AST/ExprConstant.cpp (original)<br>
+++ cfe/trunk/lib/AST/ExprConstant.cpp Sat Dec  1 00:29:36 2018<br>
@@ -8199,6 +8199,7 @@ bool IntExprEvaluator::VisitBuiltinCallE<br>
       // We can delay calculation of __builtin_constant_p until after<br>
       // inlining. Note: This diagnostic won't be shown to the user.<br>
       Info.FFDiag(E, diag::note_invalid_subexpr_in_const_expr);<br>
+      return false;<br>
     }<br>
     return Success(false, E);<br>
   }<br>
<br>
Modified: cfe/trunk/lib/CodeGen/CGExprConstant.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprConstant.cpp?rev=348070&r1=348069&r2=348070&view=diff" rel="noreferrer noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprConstant.cpp?rev=348070&r1=348069&r2=348070&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/CodeGen/CGExprConstant.cpp (original)<br>
+++ cfe/trunk/lib/CodeGen/CGExprConstant.cpp Sat Dec  1 00:29:36 2018<br>
@@ -1455,6 +1455,7 @@ llvm::Constant *ConstantEmitter::tryEmit<br>
         if (CD->isTrivial() && CD->isDefaultConstructor())<br>
           return CGM.EmitNullConstant(D.getType());<br>
       }<br>
+      InConstantContext = true;<br>
   }<br>
<br>
   QualType destType = D.getType();<br>
@@ -1552,7 +1553,7 @@ llvm::Constant *ConstantEmitter::tryEmit<br>
   if (destType->isReferenceType())<br>
     Success = E->EvaluateAsLValue(Result, CGM.getContext());<br>
   else<br>
-    Success = E->EvaluateAsRValue(Result, CGM.getContext());<br>
+    Success = E->EvaluateAsRValue(Result, CGM.getContext(), InConstantContext);<br>
<br>
   llvm::Constant *C;<br>
   if (Success && !Result.HasSideEffects)<br>
<br>
Modified: cfe/trunk/lib/CodeGen/ConstantEmitter.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/ConstantEmitter.h?rev=348070&r1=348069&r2=348070&view=diff" rel="noreferrer noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/ConstantEmitter.h?rev=348070&r1=348069&r2=348070&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/CodeGen/ConstantEmitter.h (original)<br>
+++ cfe/trunk/lib/CodeGen/ConstantEmitter.h Sat Dec  1 00:29:36 2018<br>
@@ -38,6 +38,9 @@ private:<br>
   /// Whether the constant-emission failed.<br>
   bool Failed = false;<br>
<br>
+  /// Whether we're in a constant context.<br>
+  bool InConstantContext = false;<br>
+<br>
   /// The AST address space where this (non-abstract) initializer is going.<br>
   /// Used for generating appropriate placeholders.<br>
   LangAS DestAddressSpace;<br>
<br>
Modified: cfe/trunk/test/Analysis/builtin-functions.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/builtin-functions.cpp?rev=348070&r1=348069&r2=348070&view=diff" rel="noreferrer noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/builtin-functions.cpp?rev=348070&r1=348069&r2=348070&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/test/Analysis/builtin-functions.cpp (original)<br>
+++ cfe/trunk/test/Analysis/builtin-functions.cpp Sat Dec  1 00:29:36 2018<br>
@@ -70,14 +70,14 @@ void test_constant_p() {<br>
   const int j = 2;<br>
   constexpr int k = 3;<br>
   clang_analyzer_eval(__builtin_constant_p(42) == 1); // expected-warning {{TRUE}}<br>
-  clang_analyzer_eval(__builtin_constant_p(i) == 0); // expected-warning {{TRUE}}<br>
+  clang_analyzer_eval(__builtin_constant_p(i) == 0); // expected-warning {{UNKNOWN}}<br>
   clang_analyzer_eval(__builtin_constant_p(j) == 1); // expected-warning {{TRUE}}<br>
   clang_analyzer_eval(__builtin_constant_p(k) == 1); // expected-warning {{TRUE}}<br>
-  clang_analyzer_eval(__builtin_constant_p(i + 42) == 0); // expected-warning {{TRUE}}<br>
+  clang_analyzer_eval(__builtin_constant_p(i + 42) == 0); // expected-warning {{UNKNOWN}}<br>
   clang_analyzer_eval(__builtin_constant_p(j + 42) == 1); // expected-warning {{TRUE}}<br>
   clang_analyzer_eval(__builtin_constant_p(k + 42) == 1); // expected-warning {{TRUE}}<br>
   clang_analyzer_eval(__builtin_constant_p(" ") == 1); // expected-warning {{TRUE}}<br>
-  clang_analyzer_eval(__builtin_constant_p(test_constant_p) == 0); // expected-warning {{TRUE}}<br>
+  clang_analyzer_eval(__builtin_constant_p(test_constant_p) == 0); // expected-warning {{UNKNOWN}}<br>
   clang_analyzer_eval(__builtin_constant_p(k - 3) == 0); // expected-warning {{FALSE}}<br>
   clang_analyzer_eval(__builtin_constant_p(k - 3) == 1); // expected-warning {{TRUE}}<br>
 }<br>
<br>
Added: cfe/trunk/test/CodeGen/builtin-constant-p.c<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/builtin-constant-p.c?rev=348070&view=auto" rel="noreferrer noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/builtin-constant-p.c?rev=348070&view=auto</a><br>
==============================================================================<br>
--- cfe/trunk/test/CodeGen/builtin-constant-p.c (added)<br>
+++ cfe/trunk/test/CodeGen/builtin-constant-p.c Sat Dec  1 00:29:36 2018<br>
@@ -0,0 +1,168 @@<br>
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -o - %s -O2 | FileCheck %s<br>
+<br>
+int a = 42;<br>
+<br>
+inline int bcp(int x) {<br>
+  return __builtin_constant_p(x);<br>
+}<br>
+<br>
+/* --- Compound literals */<br>
+<br>
+struct foo { int x, y; };<br>
+<br>
+int y;<br>
+struct foo f = (struct foo){ __builtin_constant_p(y), 42 };<br>
+<br>
+struct foo test0(int expr) {<br>
+  // CHECK: define i64 @test0(i32 %expr)<br>
+  // CHECK: call i1 @llvm.is.constant.i32(i32 %expr)<br>
+  struct foo f = (struct foo){ __builtin_constant_p(expr), 42 };<br>
+  return f;<br>
+}<br>
+<br>
+/* --- Pointer types */<br>
+<br>
+inline int test1_i(int *x) {<br>
+  return *x;<br>
+}<br>
+<br>
+int test1() {<br>
+  // CHECK: define i32 @test1<br>
+  // CHECK: add nsw i32 %0, -13<br>
+  // CHECK-NEXT: call i1 @llvm.is.constant.i32(i32 %sub)<br>
+  return bcp(test1_i(&a) - 13);<br>
+}<br>
+<br>
+int test2() {<br>
+  // CHECK: define i32 @test2<br>
+  // CHECK: ret i32 0<br>
+  return __builtin_constant_p(&a - 13);<br>
+}<br>
+<br>
+inline int test3_i(int *x) {<br>
+  return 42;<br>
+}<br>
+<br>
+int test3() {<br>
+  // CHECK: define i32 @test3<br>
+  // CHECK: ret i32 1<br>
+  return bcp(test3_i(&a) - 13);<br>
+}<br>
+<br>
+/* --- Aggregate types */<br>
+<br>
+int b[] = {1, 2, 3};<br>
+<br>
+int test4() {<br>
+  // CHECK: define i32 @test4<br>
+  // CHECK: ret i32 0<br>
+  return __builtin_constant_p(b);<br>
+}<br>
+<br>
+const char test5_c[] = {1, 2, 3, 0};<br>
+<br>
+int test5() {<br>
+  // CHECK: define i32 @test5<br>
+  // CHECK: ret i32 0<br>
+  return __builtin_constant_p(test5_c);<br>
+}<br>
+<br>
+inline char test6_i(const char *x) {<br>
+  return x[1];<br>
+}<br>
+<br>
+int test6() {<br>
+  // CHECK: define i32 @test6<br>
+  // CHECK: ret i32 0<br>
+  return __builtin_constant_p(test6_i(test5_c));<br>
+}<br>
+<br>
+/* --- Non-constant global variables */<br>
+<br>
+int test7() {<br>
+  // CHECK: define i32 @test7<br>
+  // CHECK: call i1 @llvm.is.constant.i32(i32 %0)<br>
+  return bcp(a);<br>
+}<br>
+<br>
+/* --- Constant global variables */<br>
+<br>
+const int c = 42;<br>
+<br>
+int test8() {<br>
+  // CHECK: define i32 @test8<br>
+  // CHECK: ret i32 1<br>
+  return bcp(c);<br>
+}<br>
+<br>
+/* --- Array types */<br>
+<br>
+int arr[] = { 1, 2, 3 };<br>
+const int c_arr[] = { 1, 2, 3 };<br>
+<br>
+int test9() {<br>
+  // CHECK: define i32 @test9<br>
+  // CHECK: call i1 @llvm.is.constant.i32(i32 %0)<br>
+  return __builtin_constant_p(arr[2]);<br>
+}<br>
+<br>
+int test10() {<br>
+  // CHECK: define i32 @test10<br>
+  // CHECK: ret i32 1<br>
+  return __builtin_constant_p(c_arr[2]);<br>
+}<br>
+<br>
+int test11() {<br>
+  // CHECK: define i32 @test11<br>
+  // CHECK: ret i32 0<br>
+  return __builtin_constant_p(c_arr);<br>
+}<br>
+<br>
+/* --- Function pointers */<br>
+<br>
+int test12() {<br>
+  // CHECK: define i32 @test12<br>
+  // CHECK: ret i32 0<br>
+  return __builtin_constant_p(&test10);<br>
+}<br>
+<br>
+int test13() {<br>
+  // CHECK: define i32 @test13<br>
+  // CHECK: ret i32 1<br>
+  return __builtin_constant_p(&test10 != 0);<br>
+}<br>
+<br>
+typedef unsigned long uintptr_t;<br>
+#define assign(p, v) ({ \<br>
+  uintptr_t _r_a_p__v = (uintptr_t)(v);                           \<br>
+  if (__builtin_constant_p(v) && _r_a_p__v == (uintptr_t)0) {     \<br>
+    union {                                                       \<br>
+      uintptr_t __val;                                            \<br>
+      char __c[1];                                                \<br>
+    } __u = {                                                     \<br>
+      .__val = (uintptr_t)_r_a_p__v                               \<br>
+    };                                                            \<br>
+    *(volatile unsigned int*)&p = *(unsigned int*)(__u.__c);      \<br>
+    __u.__val;                                                    \<br>
+  }                                                               \<br>
+  _r_a_p__v;                                                      \<br>
+})<br>
+<br>
+typedef void fn_p(void);<br>
+extern fn_p *dest_p;<br>
+<br>
+static void src_fn(void) {<br>
+}<br>
+<br>
+void test14() {<br>
+  assign(dest_p, src_fn);<br>
+}<br>
+<br>
+extern int test15_v;<br>
+<br>
+struct { const char *t; int a; } test15[] = {<br>
+    { "tag", __builtin_constant_p(test15_v) && !test15_v ? 1 : 0 }<br>
+};<br>
+<br>
+extern char test16_v;<br>
+struct { int a; } test16 = { __builtin_constant_p(test16_v) };<br>
<br>
<br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@lists.llvm.org" target="_blank" rel="noreferrer">cfe-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits" rel="noreferrer noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits</a><br>
</blockquote></div>