forked from OSchip/llvm-project
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. llvm-svn: 186053
This commit is contained in:
parent
af9de91fd2
commit
6cbd65d84d
|
@ -1533,6 +1533,22 @@ correct code by avoiding expensive loops around
|
|||
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
|
||||
----------------------------------
|
||||
|
||||
|
|
|
@ -959,5 +959,8 @@ BUILTIN(__builtin_smul_overflow, "bSiCSiCSi*", "n")
|
|||
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
|
||||
|
|
|
@ -4513,7 +4513,13 @@ bool PointerExprEvaluator::VisitCallExpr(const CallExpr *E) {
|
|||
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);
|
||||
}
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
|
@ -1489,6 +1489,8 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
|
|||
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -95,6 +95,22 @@ static bool SemaBuiltinAnnotation(Sema &S, CallExpr *TheCall) {
|
|||
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 BuiltinID, CallExpr *TheCall) {
|
|||
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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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}}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue