[cfe-commits] r166361 - in /cfe/trunk: lib/CodeGen/CGExpr.cpp lib/Sema/SemaExpr.cpp test/CodeGenCXX/const-init-cxx11.cpp test/CodeGenCXX/for-range.cpp test/CodeGenCXX/lambda-expressions.cpp test/SemaCXX/lambda-expressions.cpp

Richard Smith richard-llvm at metafoo.co.uk
Fri Oct 19 18:38:34 PDT 2012


Author: rsmith
Date: Fri Oct 19 20:38:33 2012
New Revision: 166361

URL: http://llvm.org/viewvc/llvm-project?rev=166361&view=rev
Log:
DR1472: A reference isn't odr-used if it has preceding initialization,
initialized by a reference constant expression.

Our odr-use modeling still needs work here: we don't yet implement the 'set of
potential results of an expression' DR.

Modified:
    cfe/trunk/lib/CodeGen/CGExpr.cpp
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/test/CodeGenCXX/const-init-cxx11.cpp
    cfe/trunk/test/CodeGenCXX/for-range.cpp
    cfe/trunk/test/CodeGenCXX/lambda-expressions.cpp
    cfe/trunk/test/SemaCXX/lambda-expressions.cpp

Modified: cfe/trunk/lib/CodeGen/CGExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExpr.cpp?rev=166361&r1=166360&r2=166361&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExpr.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExpr.cpp Fri Oct 19 20:38:33 2012
@@ -1695,6 +1695,21 @@
   CharUnits Alignment = getContext().getDeclAlign(ND);
   QualType T = E->getType();
 
+  // A DeclRefExpr for a reference initialized by a constant expression can
+  // appear without being odr-used. Directly emit the constant initializer.
+  if (const VarDecl *VD = dyn_cast<VarDecl>(ND)) {
+    const Expr *Init = VD->getAnyInitializer(VD);
+    if (Init && !isa<ParmVarDecl>(VD) && VD->getType()->isReferenceType() &&
+        VD->isUsableInConstantExpressions(getContext()) &&
+        VD->checkInitIsICE()) {
+      llvm::Constant *Val =
+        CGM.EmitConstantValue(*VD->evaluateValue(), VD->getType(), this);
+      assert(Val && "failed to emit reference constant expression");
+      // FIXME: Eventually we will want to emit vector element references.
+      return MakeAddrLValue(Val, T, Alignment);
+    }
+  }
+
   // FIXME: We should be able to assert this for FunctionDecls as well!
   // FIXME: We should be able to assert this for all DeclRefExprs, not just
   // those with a valid source location.
@@ -1705,7 +1720,7 @@
   if (ND->hasAttr<WeakRefAttr>()) {
     const ValueDecl *VD = cast<ValueDecl>(ND);
     llvm::Constant *Aliasee = CGM.GetWeakRefReference(VD);
-    return MakeAddrLValue(Aliasee, E->getType(), Alignment);
+    return MakeAddrLValue(Aliasee, T, Alignment);
   }
 
   if (const VarDecl *VD = dyn_cast<VarDecl>(ND)) {
@@ -1733,9 +1748,8 @@
       }
 
       assert(isa<BlockDecl>(CurCodeDecl) && E->refersToEnclosingLocal());
-      CharUnits alignment = getContext().getDeclAlign(VD);
       return MakeAddrLValue(GetAddrOfBlockDecl(VD, isBlockVariable),
-                            E->getType(), alignment);
+                            T, Alignment);
     }
 
     assert(V && "DeclRefExpr not entered in LocalDeclMap?");

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=166361&r1=166360&r2=166361&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Fri Oct 19 20:38:33 2012
@@ -11010,20 +11010,21 @@
     }
   }
 
-  // Per C++11 [basic.def.odr], a variable is odr-used "unless it is 
-  // an object that satisfies the requirements for appearing in a
-  // constant expression (5.19) and the lvalue-to-rvalue conversion (4.1)
+  // Per C++11 [basic.def.odr], a variable is odr-used "unless it satisfies
+  // the requirements for appearing in a constant expression (5.19) and, if
+  // it is an object, the lvalue-to-rvalue conversion (4.1)
   // is immediately applied."  We check the first part here, and
   // Sema::UpdateMarkingForLValueToRValue deals with the second part.
   // Note that we use the C++11 definition everywhere because nothing in
-  // C++03 depends on whether we get the C++03 version correct. This does not
-  // apply to references, since they are not objects.
+  // C++03 depends on whether we get the C++03 version correct. The second
+  // part does not apply to references, since they are not objects.
   const VarDecl *DefVD;
-  if (E && !isa<ParmVarDecl>(Var) && !Var->getType()->isReferenceType() &&
+  if (E && !isa<ParmVarDecl>(Var) &&
       Var->isUsableInConstantExpressions(SemaRef.Context) &&
-      Var->getAnyInitializer(DefVD) && DefVD->checkInitIsICE())
-    SemaRef.MaybeODRUseExprs.insert(E);
-  else
+      Var->getAnyInitializer(DefVD) && DefVD->checkInitIsICE()) {
+    if (!Var->getType()->isReferenceType())
+      SemaRef.MaybeODRUseExprs.insert(E);
+  } else
     MarkVarDeclODRUsed(SemaRef, Var, Loc);
 }
 

Modified: cfe/trunk/test/CodeGenCXX/const-init-cxx11.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/const-init-cxx11.cpp?rev=166361&r1=166360&r2=166361&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/const-init-cxx11.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/const-init-cxx11.cpp Fri Oct 19 20:38:33 2012
@@ -432,11 +432,7 @@
     // CHECK: call void @_ZN13InitFromConst7consumeIRKNS_1SEEEvT_(%"struct.InitFromConst::S"* @_ZN13InitFromConstL1sE)
     consume<const S&>(s);
 
-    // FIXME CHECK-NOT: call void @_ZN13InitFromConst7consumeIRKNS_1SEEEvT_(%"struct.InitFromConst::S"* @_ZN13InitFromConstL1sE)
-    // There's no lvalue-to-rvalue conversion here, so 'r' is odr-used, and
-    // we're permitted to emit a load of it. This seems likely to be a defect
-    // in the standard. If we start emitting a direct reference to 's', update
-    // this test.
+    // CHECK: call void @_ZN13InitFromConst7consumeIRKNS_1SEEEvT_(%"struct.InitFromConst::S"* @_ZN13InitFromConstL1sE)
     consume<const S&>(r);
 
     // CHECK: call void @_ZN13InitFromConst7consumeIPKNS_1SEEEvT_(%"struct.InitFromConst::S"* @_ZN13InitFromConstL1sE)

Modified: cfe/trunk/test/CodeGenCXX/for-range.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/for-range.cpp?rev=166361&r1=166360&r2=166361&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/for-range.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/for-range.cpp Fri Oct 19 20:38:33 2012
@@ -40,7 +40,7 @@
     // CHECK-NOT: 5begin
     // CHECK-NOT: 3end
     // CHECK: getelementptr {{.*}}, i32 0
-    // CHECK: getelementptr {{.*}}, i64 5
+    // CHECK: getelementptr {{.*}}, i64 1, i64 0
     // CHECK: br label %[[COND:.*]]
 
     // CHECK: [[COND]]:

Modified: cfe/trunk/test/CodeGenCXX/lambda-expressions.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/lambda-expressions.cpp?rev=166361&r1=166360&r2=166361&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/lambda-expressions.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/lambda-expressions.cpp Fri Oct 19 20:38:33 2012
@@ -71,6 +71,15 @@
   int (*fp)(int, int) = [](int x, int y){ return x + y; };
 }
 
+static int k;
+int g() {
+  int &r = k;
+  // CHECK: define internal i32 @"_ZZ1gvENK3$_6clEv"(
+  // CHECK-NOT: }
+  // CHECK: load i32* @_ZL1k,
+  return [] { return r; } ();
+};
+
 // CHECK: define internal i32 @"_ZZ1fvEN3$_58__invokeEii"
 // CHECK: store i32
 // CHECK-NEXT: store i32

Modified: cfe/trunk/test/SemaCXX/lambda-expressions.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/lambda-expressions.cpp?rev=166361&r1=166360&r2=166361&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/lambda-expressions.cpp (original)
+++ cfe/trunk/test/SemaCXX/lambda-expressions.cpp Fri Oct 19 20:38:33 2012
@@ -83,12 +83,15 @@
     const int h = a; // expected-note {{declared}}
     []() { return h; }; // expected-error {{variable 'h' cannot be implicitly captured in a lambda with no capture-default specified}} expected-note {{lambda expression begins here}}
 
-    // The exemption for variables which can appear in constant expressions
-    // applies only to objects (and not to references).
-    // FIXME: This might be a bug in the standard.
-    static int i;
-    constexpr int &ref_i = i; // expected-note {{declared}}
+    // References can appear in constant expressions if they are initialized by
+    // reference constant expressions.
+    int i;
+    int &ref_i = i; // expected-note {{declared}}
     [] { return ref_i; }; // expected-error {{variable 'ref_i' cannot be implicitly captured in a lambda with no capture-default specified}} expected-note {{lambda expression begins here}}
+
+    static int j;
+    int &ref_j = j;
+    [] { return ref_j; }; // ok
   }
 }
 





More information about the cfe-commits mailing list