r186053 - Add a __builtin_addressof that performs the same functionality as the built-in

Richard Smith richard-llvm at metafoo.co.uk
Wed Jul 10 19:27:57 PDT 2013


Author: rsmith
Date: Wed Jul 10 21:27:57 2013
New Revision: 186053

URL: http://llvm.org/viewvc/llvm-project?rev=186053&view=rev
Log:
Add a __builtin_addressof that performs the same functionality as the built-in
& operator (ignoring any overloaded operator& for the type). The purpose of
this builtin is for use in std::addressof, to allow it to be made constexpr;
the existing implementation technique (reinterpret_cast to some reference type,
take address, reinterpert_cast back) does not permit this because
reinterpret_cast between reference types is not permitted in a constant
expression in C++11 onwards.

Modified:
    cfe/trunk/docs/LanguageExtensions.rst
    cfe/trunk/include/clang/Basic/Builtins.def
    cfe/trunk/lib/AST/ExprConstant.cpp
    cfe/trunk/lib/CodeGen/CGBuiltin.cpp
    cfe/trunk/lib/Sema/SemaChecking.cpp
    cfe/trunk/test/CodeGenCXX/builtins.cpp
    cfe/trunk/test/SemaCXX/builtins.cpp

Modified: cfe/trunk/docs/LanguageExtensions.rst
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/LanguageExtensions.rst?rev=186053&r1=186052&r2=186053&view=diff
==============================================================================
--- cfe/trunk/docs/LanguageExtensions.rst (original)
+++ cfe/trunk/docs/LanguageExtensions.rst Wed Jul 10 21:27:57 2013
@@ -1533,6 +1533,22 @@ correct code by avoiding expensive loops
 implementation details of ``__sync_lock_test_and_set()``.  The
 ``__sync_swap()`` builtin is a full barrier.
 
+``__builtin_addressof``
+-----------------------
+
+``__builtin_addressof`` performs the functionality of the built-in ``&``
+operator, ignoring any ``operator&`` overload.  This is useful in constant
+expressions in C++11, where there is no other way to take the address of an
+object that overloads ``operator&``.
+
+**Example of use**:
+
+.. code-block:: c++
+
+  template<typename T> constexpr T *addressof(T &value) {
+    return __builtin_addressof(value);
+  }
+
 Multiprecision Arithmetic Builtins
 ----------------------------------
 

Modified: cfe/trunk/include/clang/Basic/Builtins.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Builtins.def?rev=186053&r1=186052&r2=186053&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/Builtins.def (original)
+++ cfe/trunk/include/clang/Basic/Builtins.def Wed Jul 10 21:27:57 2013
@@ -959,5 +959,8 @@ BUILTIN(__builtin_smul_overflow, "bSiCSi
 BUILTIN(__builtin_smull_overflow, "bSLiCSLiCSLi*", "n")
 BUILTIN(__builtin_smulll_overflow, "bSLLiCSLLiCSLLi*", "n")
 
+// Clang builtins (not available in GCC).
+BUILTIN(__builtin_addressof, "v*v&", "nct")
+
 #undef BUILTIN
 #undef LIBBUILTIN

Modified: cfe/trunk/lib/AST/ExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=186053&r1=186052&r2=186053&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ExprConstant.cpp (original)
+++ cfe/trunk/lib/AST/ExprConstant.cpp Wed Jul 10 21:27:57 2013
@@ -4513,7 +4513,13 @@ bool PointerExprEvaluator::VisitCallExpr
   if (IsStringLiteralCall(E))
     return Success(E);
 
-  return ExprEvaluatorBaseTy::VisitCallExpr(E);
+  switch (E->isBuiltinCall()) {
+  case Builtin::BI__builtin_addressof:
+    return EvaluateLValue(E->getArg(0), Result, Info);
+
+  default:
+    return ExprEvaluatorBaseTy::VisitCallExpr(E);
+  }
 }
 
 //===----------------------------------------------------------------------===//

Modified: cfe/trunk/lib/CodeGen/CGBuiltin.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGBuiltin.cpp?rev=186053&r1=186052&r2=186053&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGBuiltin.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGBuiltin.cpp Wed Jul 10 21:27:57 2013
@@ -1489,6 +1489,8 @@ RValue CodeGenFunction::EmitBuiltinExpr(
 
     return RValue::get(Carry);
   }
+  case Builtin::BI__builtin_addressof:
+    return RValue::get(EmitLValue(E->getArg(0)).getAddress());
   case Builtin::BI__noop:
     return RValue::get(0);
   }

Modified: cfe/trunk/lib/Sema/SemaChecking.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=186053&r1=186052&r2=186053&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaChecking.cpp (original)
+++ cfe/trunk/lib/Sema/SemaChecking.cpp Wed Jul 10 21:27:57 2013
@@ -95,6 +95,22 @@ static bool SemaBuiltinAnnotation(Sema &
   return false;
 }
 
+/// Check that the argument to __builtin_addressof is a glvalue, and set the
+/// result type to the corresponding pointer type.
+static bool SemaBuiltinAddressof(Sema &S, CallExpr *TheCall) {
+  if (checkArgCount(S, TheCall, 1))
+    return true;
+
+  ExprResult Arg(S.Owned(TheCall->getArg(0)));
+  QualType ResultType = S.CheckAddressOfOperand(Arg, TheCall->getLocStart());
+  if (ResultType.isNull())
+    return true;
+
+  TheCall->setArg(0, Arg.take());
+  TheCall->setType(ResultType);
+  return false;
+}
+
 ExprResult
 Sema::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
   ExprResult TheCallResult(Owned(TheCall));
@@ -275,6 +291,10 @@ Sema::CheckBuiltinFunctionCall(unsigned
     if (SemaBuiltinAnnotation(*this, TheCall))
       return ExprError();
     break;
+  case Builtin::BI__builtin_addressof:
+    if (SemaBuiltinAddressof(*this, TheCall))
+      return ExprError();
+    break;
   }
   
   // Since the target specific builtins for each arch overlap, only check those

Modified: cfe/trunk/test/CodeGenCXX/builtins.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/builtins.cpp?rev=186053&r1=186052&r2=186053&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/builtins.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/builtins.cpp Wed Jul 10 21:27:57 2013
@@ -7,3 +7,11 @@ int main() {
   // CHECK: call {{signext i8|i8}} @memmove()
   return memmove();
 }
+
+struct S;
+// CHECK: define {{.*}} @_Z9addressofbR1SS0_(
+S *addressof(bool b, S &s, S &t) {
+  // CHECK: %[[LVALUE:.*]] = phi
+  // CHECK: ret {{.*}}* %[[LVALUE]]
+  return __builtin_addressof(b ? s : t);
+}

Modified: cfe/trunk/test/SemaCXX/builtins.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/builtins.cpp?rev=186053&r1=186052&r2=186053&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/builtins.cpp (original)
+++ cfe/trunk/test/SemaCXX/builtins.cpp Wed Jul 10 21:27:57 2013
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 %s -fsyntax-only -verify
+// RUN: %clang_cc1 %s -fsyntax-only -verify -std=c++11
 typedef const struct __CFString * CFStringRef;
 #define CFSTR __builtin___CFStringMakeConstantString
 
@@ -24,3 +24,17 @@ void f2() {
 // pr14895
 typedef __typeof(sizeof(int)) size_t;
 extern "C" void *__builtin_alloca (size_t);
+
+namespace addressof {
+  struct S {} s;
+  static_assert(__builtin_addressof(s) == &s, "");
+
+  struct T { constexpr T *operator&() const { return nullptr; } int n; } t;
+  constexpr T *pt = __builtin_addressof(t);
+  static_assert(&pt->n == &t.n, "");
+
+  struct U { int n : 5; } u;
+  int *pbf = __builtin_addressof(u.n); // expected-error {{address of bit-field requested}}
+
+  S *ptmp = __builtin_addressof(S{}); // expected-error {{taking the address of a temporary}}
+}





More information about the cfe-commits mailing list