r348070 - Specify constant context in constant emitter

Bill Wendling via cfe-commits cfe-commits at lists.llvm.org
Sat Dec 1 00:29:36 PST 2018


Author: void
Date: Sat Dec  1 00:29:36 2018
New Revision: 348070

URL: http://llvm.org/viewvc/llvm-project?rev=348070&view=rev
Log:
Specify constant context in constant emitter

The constant emitter may need to evaluate the expression in a constant context.
For exasmple, global initializer lists.

Added:
    cfe/trunk/test/CodeGen/builtin-constant-p.c
Modified:
    cfe/trunk/lib/AST/ExprConstant.cpp
    cfe/trunk/lib/CodeGen/CGExprConstant.cpp
    cfe/trunk/lib/CodeGen/ConstantEmitter.h
    cfe/trunk/test/Analysis/builtin-functions.cpp

Modified: cfe/trunk/lib/AST/ExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=348070&r1=348069&r2=348070&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ExprConstant.cpp (original)
+++ cfe/trunk/lib/AST/ExprConstant.cpp Sat Dec  1 00:29:36 2018
@@ -8199,6 +8199,7 @@ bool IntExprEvaluator::VisitBuiltinCallE
       // We can delay calculation of __builtin_constant_p until after
       // inlining. Note: This diagnostic won't be shown to the user.
       Info.FFDiag(E, diag::note_invalid_subexpr_in_const_expr);
+      return false;
     }
     return Success(false, E);
   }

Modified: cfe/trunk/lib/CodeGen/CGExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprConstant.cpp?rev=348070&r1=348069&r2=348070&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprConstant.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprConstant.cpp Sat Dec  1 00:29:36 2018
@@ -1455,6 +1455,7 @@ llvm::Constant *ConstantEmitter::tryEmit
         if (CD->isTrivial() && CD->isDefaultConstructor())
           return CGM.EmitNullConstant(D.getType());
       }
+      InConstantContext = true;
   }
 
   QualType destType = D.getType();
@@ -1552,7 +1553,7 @@ llvm::Constant *ConstantEmitter::tryEmit
   if (destType->isReferenceType())
     Success = E->EvaluateAsLValue(Result, CGM.getContext());
   else
-    Success = E->EvaluateAsRValue(Result, CGM.getContext());
+    Success = E->EvaluateAsRValue(Result, CGM.getContext(), InConstantContext);
 
   llvm::Constant *C;
   if (Success && !Result.HasSideEffects)

Modified: cfe/trunk/lib/CodeGen/ConstantEmitter.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/ConstantEmitter.h?rev=348070&r1=348069&r2=348070&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/ConstantEmitter.h (original)
+++ cfe/trunk/lib/CodeGen/ConstantEmitter.h Sat Dec  1 00:29:36 2018
@@ -38,6 +38,9 @@ private:
   /// Whether the constant-emission failed.
   bool Failed = false;
 
+  /// Whether we're in a constant context.
+  bool InConstantContext = false;
+
   /// The AST address space where this (non-abstract) initializer is going.
   /// Used for generating appropriate placeholders.
   LangAS DestAddressSpace;

Modified: cfe/trunk/test/Analysis/builtin-functions.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/builtin-functions.cpp?rev=348070&r1=348069&r2=348070&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/builtin-functions.cpp (original)
+++ cfe/trunk/test/Analysis/builtin-functions.cpp Sat Dec  1 00:29:36 2018
@@ -70,14 +70,14 @@ void test_constant_p() {
   const int j = 2;
   constexpr int k = 3;
   clang_analyzer_eval(__builtin_constant_p(42) == 1); // expected-warning {{TRUE}}
-  clang_analyzer_eval(__builtin_constant_p(i) == 0); // expected-warning {{TRUE}}
+  clang_analyzer_eval(__builtin_constant_p(i) == 0); // expected-warning {{UNKNOWN}}
   clang_analyzer_eval(__builtin_constant_p(j) == 1); // expected-warning {{TRUE}}
   clang_analyzer_eval(__builtin_constant_p(k) == 1); // expected-warning {{TRUE}}
-  clang_analyzer_eval(__builtin_constant_p(i + 42) == 0); // expected-warning {{TRUE}}
+  clang_analyzer_eval(__builtin_constant_p(i + 42) == 0); // expected-warning {{UNKNOWN}}
   clang_analyzer_eval(__builtin_constant_p(j + 42) == 1); // expected-warning {{TRUE}}
   clang_analyzer_eval(__builtin_constant_p(k + 42) == 1); // expected-warning {{TRUE}}
   clang_analyzer_eval(__builtin_constant_p(" ") == 1); // expected-warning {{TRUE}}
-  clang_analyzer_eval(__builtin_constant_p(test_constant_p) == 0); // expected-warning {{TRUE}}
+  clang_analyzer_eval(__builtin_constant_p(test_constant_p) == 0); // expected-warning {{UNKNOWN}}
   clang_analyzer_eval(__builtin_constant_p(k - 3) == 0); // expected-warning {{FALSE}}
   clang_analyzer_eval(__builtin_constant_p(k - 3) == 1); // expected-warning {{TRUE}}
 }

Added: cfe/trunk/test/CodeGen/builtin-constant-p.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/builtin-constant-p.c?rev=348070&view=auto
==============================================================================
--- cfe/trunk/test/CodeGen/builtin-constant-p.c (added)
+++ cfe/trunk/test/CodeGen/builtin-constant-p.c Sat Dec  1 00:29:36 2018
@@ -0,0 +1,168 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -o - %s -O2 | FileCheck %s
+
+int a = 42;
+
+inline int bcp(int x) {
+  return __builtin_constant_p(x);
+}
+
+/* --- Compound literals */
+
+struct foo { int x, y; };
+
+int y;
+struct foo f = (struct foo){ __builtin_constant_p(y), 42 };
+
+struct foo test0(int expr) {
+  // CHECK: define i64 @test0(i32 %expr)
+  // CHECK: call i1 @llvm.is.constant.i32(i32 %expr)
+  struct foo f = (struct foo){ __builtin_constant_p(expr), 42 };
+  return f;
+}
+
+/* --- Pointer types */
+
+inline int test1_i(int *x) {
+  return *x;
+}
+
+int test1() {
+  // CHECK: define i32 @test1
+  // CHECK: add nsw i32 %0, -13
+  // CHECK-NEXT: call i1 @llvm.is.constant.i32(i32 %sub)
+  return bcp(test1_i(&a) - 13);
+}
+
+int test2() {
+  // CHECK: define i32 @test2
+  // CHECK: ret i32 0
+  return __builtin_constant_p(&a - 13);
+}
+
+inline int test3_i(int *x) {
+  return 42;
+}
+
+int test3() {
+  // CHECK: define i32 @test3
+  // CHECK: ret i32 1
+  return bcp(test3_i(&a) - 13);
+}
+
+/* --- Aggregate types */
+
+int b[] = {1, 2, 3};
+
+int test4() {
+  // CHECK: define i32 @test4
+  // CHECK: ret i32 0
+  return __builtin_constant_p(b);
+}
+
+const char test5_c[] = {1, 2, 3, 0};
+
+int test5() {
+  // CHECK: define i32 @test5
+  // CHECK: ret i32 0
+  return __builtin_constant_p(test5_c);
+}
+
+inline char test6_i(const char *x) {
+  return x[1];
+}
+
+int test6() {
+  // CHECK: define i32 @test6
+  // CHECK: ret i32 0
+  return __builtin_constant_p(test6_i(test5_c));
+}
+
+/* --- Non-constant global variables */
+
+int test7() {
+  // CHECK: define i32 @test7
+  // CHECK: call i1 @llvm.is.constant.i32(i32 %0)
+  return bcp(a);
+}
+
+/* --- Constant global variables */
+
+const int c = 42;
+
+int test8() {
+  // CHECK: define i32 @test8
+  // CHECK: ret i32 1
+  return bcp(c);
+}
+
+/* --- Array types */
+
+int arr[] = { 1, 2, 3 };
+const int c_arr[] = { 1, 2, 3 };
+
+int test9() {
+  // CHECK: define i32 @test9
+  // CHECK: call i1 @llvm.is.constant.i32(i32 %0)
+  return __builtin_constant_p(arr[2]);
+}
+
+int test10() {
+  // CHECK: define i32 @test10
+  // CHECK: ret i32 1
+  return __builtin_constant_p(c_arr[2]);
+}
+
+int test11() {
+  // CHECK: define i32 @test11
+  // CHECK: ret i32 0
+  return __builtin_constant_p(c_arr);
+}
+
+/* --- Function pointers */
+
+int test12() {
+  // CHECK: define i32 @test12
+  // CHECK: ret i32 0
+  return __builtin_constant_p(&test10);
+}
+
+int test13() {
+  // CHECK: define i32 @test13
+  // CHECK: ret i32 1
+  return __builtin_constant_p(&test10 != 0);
+}
+
+typedef unsigned long uintptr_t;
+#define assign(p, v) ({ \
+  uintptr_t _r_a_p__v = (uintptr_t)(v);                           \
+  if (__builtin_constant_p(v) && _r_a_p__v == (uintptr_t)0) {     \
+    union {                                                       \
+      uintptr_t __val;                                            \
+      char __c[1];                                                \
+    } __u = {                                                     \
+      .__val = (uintptr_t)_r_a_p__v                               \
+    };                                                            \
+    *(volatile unsigned int*)&p = *(unsigned int*)(__u.__c);      \
+    __u.__val;                                                    \
+  }                                                               \
+  _r_a_p__v;                                                      \
+})
+
+typedef void fn_p(void);
+extern fn_p *dest_p;
+
+static void src_fn(void) {
+}
+
+void test14() {
+  assign(dest_p, src_fn);
+}
+
+extern int test15_v;
+
+struct { const char *t; int a; } test15[] = {
+    { "tag", __builtin_constant_p(test15_v) && !test15_v ? 1 : 0 }
+};
+
+extern char test16_v;
+struct { int a; } test16 = { __builtin_constant_p(test16_v) };




More information about the cfe-commits mailing list