Address Richard's review comments on r147561 (Evaluate support for address-of-label...
authorEli Friedman <eli.friedman@gmail.com>
Thu, 5 Jan 2012 23:59:40 +0000 (23:59 +0000)
committerEli Friedman <eli.friedman@gmail.com>
Thu, 5 Jan 2012 23:59:40 +0000 (23:59 +0000)
llvm-svn: 147631

clang/lib/AST/ExprConstant.cpp
clang/lib/CodeGen/CGExprConstant.cpp
clang/test/CodeGenCXX/const-init-cxx11.cpp [new file with mode: 0644]
clang/test/SemaCXX/constexpr-printing.cpp

index fc214bf..949988d 100644 (file)
@@ -3453,7 +3453,7 @@ public:
   }
 
   bool Success(const CCValue &V, const Expr *E) {
-    if (V.isLValue()) {
+    if (V.isLValue() || V.isAddrLabelDiff()) {
       Result = V;
       return true;
     }
@@ -4002,8 +4002,6 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
       if (!HasSameBase(LHSValue, RHSValue)) {
         if (E->getOpcode() == BO_Sub) {
           // Handle &&A - &&B.
-          // FIXME: We're missing a check that both labels have the same
-          // associated function; I'm not sure how to write this check.
           if (!LHSValue.Offset.isZero() || !RHSValue.Offset.isZero())
             return false;
           const Expr *LHSExpr = LHSValue.Base.dyn_cast<const Expr*>();
@@ -4014,6 +4012,10 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
           const AddrLabelExpr *RHSAddrExpr = dyn_cast<AddrLabelExpr>(RHSExpr);
           if (!LHSAddrExpr || !RHSAddrExpr)
             return false;
+          // Make sure both labels come from the same function.
+          if (LHSAddrExpr->getLabel()->getDeclContext() !=
+              RHSAddrExpr->getLabel()->getDeclContext())
+            return false;
           Result = CCValue(LHSAddrExpr, RHSAddrExpr);
           return true;
         }
@@ -4113,8 +4115,6 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
 
   if (E->getOpcode() == BO_Sub && LHSVal.isLValue() && RHSVal.isLValue()) {
     // Handle (intptr_t)&&A - (intptr_t)&&B.
-    // FIXME: We're missing a check that both labels have the same
-    // associated function; I'm not sure how to write this check.
     if (!LHSVal.getLValueOffset().isZero() ||
         !RHSVal.getLValueOffset().isZero())
       return false;
@@ -4126,6 +4126,10 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
     const AddrLabelExpr *RHSAddrExpr = dyn_cast<AddrLabelExpr>(RHSExpr);
     if (!LHSAddrExpr || !RHSAddrExpr)
       return false;
+    // Make sure both labels come from the same function.
+    if (LHSAddrExpr->getLabel()->getDeclContext() !=
+        RHSAddrExpr->getLabel()->getDeclContext())
+      return false;
     Result = CCValue(LHSAddrExpr, RHSAddrExpr);
     return true;
   }
index 2c15132..826a950 100644 (file)
@@ -1034,7 +1034,7 @@ llvm::Constant *CodeGenModule::EmitConstantExpr(const Expr *E,
       RHS = llvm::ConstantExpr::getPtrToInt(RHS, IntPtrTy);
       llvm::Constant *AddrLabelDiff = llvm::ConstantExpr::getSub(LHS, RHS);
 
-      // LLVM os a bit sensitive about the exact format of the
+      // LLVM is a bit sensitive about the exact format of the
       // address-of-label difference; make sure to truncate after
       // the subtraction.
       return llvm::ConstantExpr::getTruncOrBitCast(AddrLabelDiff, ResultType);
diff --git a/clang/test/CodeGenCXX/const-init-cxx11.cpp b/clang/test/CodeGenCXX/const-init-cxx11.cpp
new file mode 100644 (file)
index 0000000..5ec9a69
--- /dev/null
@@ -0,0 +1,9 @@
+// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin -emit-llvm -o - %s -std=c++11 | FileCheck %s
+
+namespace CrossFuncLabelDiff {
+  // Make sure we refuse to constant-fold the variable b.
+  constexpr long a() { return (long)&&lbl + (0 && ({lbl: 0;})); }
+  void test() { static long b = (long)&&lbl - a(); lbl: return; }
+  // CHECK: sub nsw i64 ptrtoint (i8* blockaddress(@_ZN18CrossFuncLabelDiff4testEv, {{.*}}) to i64),
+  // CHECK: store i64 {{.*}}, i64* @_ZZN18CrossFuncLabelDiff4testEvE1b, align 8
+}
index 03768c0..2e0eb9c 100644 (file)
@@ -89,3 +89,10 @@ constexpr wchar_t wc = get(L"test\0\\\"\t\a\b\234\u1234"); // \
   expected-error {{}} expected-note {{L"test\000\\\"\t\a\b\234\u1234"}}
 
 constexpr char32_t c32_err = get(U"\U00110000"); // expected-error {{invalid universal character}}
+
+typedef decltype(sizeof(int)) LabelDiffTy;
+constexpr LabelDiffTy mulBy3(LabelDiffTy x) { return x * 3; } // expected-note {{subexpression}}
+void LabelDiffTest() {
+  static_assert(mulBy3((LabelDiffTy)&&a-(LabelDiffTy)&&b) == 3, ""); // expected-error {{constant expression}} expected-note {{call to 'mulBy3(&&a - &&b)'}}
+  a:b:return;
+}