[cfe-commits] r138715 - in /cfe/trunk: lib/Sema/SemaExpr.cpp test/CXX/special/class.temporary/p1.cpp

John McCall rjmccall at apple.com
Sat Aug 27 15:06:17 PDT 2011


Author: rjmccall
Date: Sat Aug 27 17:06:17 2011
New Revision: 138715

URL: http://llvm.org/viewvc/llvm-project?rev=138715&view=rev
Log:
Disable the l-value to r-value conversion on C++ class types passed
to varargs functions in unevaluated contexts.  AFAICT, there is no
standards justification for this, but it matches what other compilers do
and therefore preserves compatibility with certain template metaprogramming
idioms.

Should fix self-host.


Modified:
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/test/CXX/special/class.temporary/p1.cpp

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=138715&r1=138714&r2=138715&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Sat Aug 27 17:06:17 2011
@@ -443,9 +443,15 @@
   if (Ty->isSpecificBuiltinType(BuiltinType::Float))
     E = ImpCastExprToType(E, Context.DoubleTy, CK_FloatingCast).take();
 
-  // C++ includes lvalue-to-rvalue conversion as a default argument
-  // promotion.  If we have a gl-value, initialize a temporary.
-  if (getLangOptions().CPlusPlus && E->isGLValue()) {
+  // C++ performs lvalue-to-rvalue conversion as a default argument
+  // promotion.  If we still have a gl-value after usual unary
+  // conversion, we must have an l-value of class type, so we need to
+  // initialize a temporary.  For compatibility reasons, however, we
+  // don't want to do this in unevaluated contexts; otherwise we
+  // reject metaprograms which work by passing uncopyable l-values to
+  // variadic functions.
+  if (getLangOptions().CPlusPlus && E->isGLValue() && 
+      ExprEvalContexts.back().Context != Unevaluated) {
     ExprResult Temp = PerformCopyInitialization(
                        InitializedEntity::InitializeTemporary(E->getType()),
                                                 E->getExprLoc(),

Modified: cfe/trunk/test/CXX/special/class.temporary/p1.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/special/class.temporary/p1.cpp?rev=138715&r1=138714&r2=138715&view=diff
==============================================================================
--- cfe/trunk/test/CXX/special/class.temporary/p1.cpp (original)
+++ cfe/trunk/test/CXX/special/class.temporary/p1.cpp Sat Aug 27 17:06:17 2011
@@ -35,3 +35,24 @@
     foo(a); // expected-error {{calling a private constructor of class 'test1::A'}} expected-error {{cannot pass object of non-trivial type 'test1::A' through variadic function}}
   }
 }
+
+// Don't enforce this in an unevaluated context.
+namespace test2 {
+  struct A {
+    A(const A&) = delete; // expected-note {{marked deleted here}}
+  };
+
+  typedef char one[1];
+  typedef char two[2];
+
+  one &meta(bool);
+  two &meta(...);
+
+  void a(A &a) {
+    char check[sizeof(meta(a)) == 2 ? 1 : -1];
+  }
+
+  void b(A &a) {
+    meta(a); // expected-error {{call to deleted constructor}}
+  }
+}





More information about the cfe-commits mailing list