]> granicus.if.org Git - clang/commitdiff
isEvaluatable() implies a constant context.
authorBill Wendling <isanbard@gmail.com>
Sat, 24 Nov 2018 10:45:55 +0000 (10:45 +0000)
committerBill Wendling <isanbard@gmail.com>
Sat, 24 Nov 2018 10:45:55 +0000 (10:45 +0000)
Assume that we're in a constant context if we're asking if the expression can
be compiled into a constant initializer. This fixes the issue where a
__builtin_constant_p() in a compound literal was diagnosed as not being
constant, even though it's always possible to convert the builtin into a
constant.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@347512 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/Expr.h
lib/AST/ExprConstant.cpp
lib/Sema/SemaExpr.cpp
test/CodeGen/builtin-constant-p.c
test/SemaCXX/compound-literal.cpp

index 9b769079d39e9db8b8ebcb71d755143f9aaf107f..7df7b56ca1f451da2ab7097394937289fa421208 100644 (file)
@@ -583,7 +583,8 @@ public:
   /// this function returns true, it returns the folded constant in Result. If
   /// the expression is a glvalue, an lvalue-to-rvalue conversion will be
   /// applied.
-  bool EvaluateAsRValue(EvalResult &Result, const ASTContext &Ctx) const;
+  bool EvaluateAsRValue(EvalResult &Result, const ASTContext &Ctx,
+                        bool InConstantContext = false) const;
 
   /// EvaluateAsBooleanCondition - Return true if this is a constant
   /// which we can fold and convert to a boolean condition using
index 4ad25b9685621661d5cf757aced41feb5884b8c1..29508368d756c5f2b8ae1b4a208d46e759e0149f 100644 (file)
@@ -10807,8 +10807,10 @@ static bool EvaluateAsInt(const Expr *E, Expr::EvalResult &ExprResult,
 /// we want to.  If this function returns true, it returns the folded constant
 /// in Result. If this expression is a glvalue, an lvalue-to-rvalue conversion
 /// will be applied to the result.
-bool Expr::EvaluateAsRValue(EvalResult &Result, const ASTContext &Ctx) const {
+bool Expr::EvaluateAsRValue(EvalResult &Result, const ASTContext &Ctx,
+                            bool InConstantContext) const {
   EvalInfo Info(Ctx, Result, EvalInfo::EM_IgnoreSideEffects);
+  Info.InConstantContext = InConstantContext;
   return ::EvaluateAsRValue(this, Result, Ctx, Info);
 }
 
@@ -10909,7 +10911,7 @@ bool Expr::EvaluateAsInitializer(APValue &Value, const ASTContext &Ctx,
 /// constant folded, but discard the result.
 bool Expr::isEvaluatable(const ASTContext &Ctx, SideEffectsKind SEK) const {
   EvalResult Result;
-  return EvaluateAsRValue(Result, Ctx) &&
+  return EvaluateAsRValue(Result, Ctx, /* in constant context */ true) &&
          !hasUnacceptableSideEffect(Result, SEK);
 }
 
index 5d99a7ed69a5ada275c98b26b1f7c15bfb887932..925988e4a7f7511c5c1a5db3ac2675dc26a90031 100644 (file)
@@ -5798,7 +5798,12 @@ Sema::BuildCompoundLiteralExpr(SourceLocation LParenLoc, TypeSourceInfo *TInfo,
           : VK_LValue;
 
   if (isFileScope)
-    LiteralExpr = ConstantExpr::Create(Context, LiteralExpr);
+    if (auto ILE = dyn_cast<InitListExpr>(LiteralExpr))
+      for (unsigned i = 0, j = ILE->getNumInits(); i != j; i++) {
+        Expr *Init = ILE->getInit(i);
+        ILE->setInit(i, ConstantExpr::Create(Context, Init));
+      }
+
   Expr *E = new (Context) CompoundLiteralExpr(LParenLoc, TInfo, literalType,
                                               VK, LiteralExpr, isFileScope);
   if (isFileScope) {
index 3f1225fb8b29a896b083d3d7f16de80f8261dca4..5cdcc721235ace212046a427381822f2ed3eb5c1 100644 (file)
@@ -10,6 +10,9 @@ inline int bcp(int x) {
 
 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)
index 5ada9e72f97783c0668627c2ba693906a4b552cd..353be2cf48e4f57848593e2a035b4439b3f9ae4e 100644 (file)
@@ -37,9 +37,10 @@ namespace brace_initializers {
   POD p = (POD){1, 2};\r
   // CHECK-NOT: CXXBindTemporaryExpr {{.*}} 'brace_initializers::POD'\r
   // CHECK: CompoundLiteralExpr {{.*}} 'brace_initializers::POD'\r
-  // CHECK-NEXT: ConstantExpr {{.*}} 'brace_initializers::POD'\r
   // CHECK-NEXT: InitListExpr {{.*}} 'brace_initializers::POD'\r
+  // CHECK-NEXT: ConstantExpr {{.*}}\r
   // CHECK-NEXT: IntegerLiteral {{.*}} 1{{$}}\r
+  // CHECK-NEXT: ConstantExpr {{.*}}\r
   // CHECK-NEXT: IntegerLiteral {{.*}} 2{{$}}\r
 \r
   void test() {\r