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
|
implementation details of ``__sync_lock_test_and_set()``. The
|
||||||
``__sync_swap()`` builtin is a full barrier.
|
``__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
|
Multiprecision Arithmetic Builtins
|
||||||
----------------------------------
|
----------------------------------
|
||||||
|
|
||||||
|
|
|
@ -959,5 +959,8 @@ BUILTIN(__builtin_smul_overflow, "bSiCSiCSi*", "n")
|
||||||
BUILTIN(__builtin_smull_overflow, "bSLiCSLiCSLi*", "n")
|
BUILTIN(__builtin_smull_overflow, "bSLiCSLiCSLi*", "n")
|
||||||
BUILTIN(__builtin_smulll_overflow, "bSLLiCSLLiCSLLi*", "n")
|
BUILTIN(__builtin_smulll_overflow, "bSLLiCSLLiCSLLi*", "n")
|
||||||
|
|
||||||
|
// Clang builtins (not available in GCC).
|
||||||
|
BUILTIN(__builtin_addressof, "v*v&", "nct")
|
||||||
|
|
||||||
#undef BUILTIN
|
#undef BUILTIN
|
||||||
#undef LIBBUILTIN
|
#undef LIBBUILTIN
|
||||||
|
|
|
@ -4513,7 +4513,13 @@ bool PointerExprEvaluator::VisitCallExpr(const CallExpr *E) {
|
||||||
if (IsStringLiteralCall(E))
|
if (IsStringLiteralCall(E))
|
||||||
return Success(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);
|
return RValue::get(Carry);
|
||||||
}
|
}
|
||||||
|
case Builtin::BI__builtin_addressof:
|
||||||
|
return RValue::get(EmitLValue(E->getArg(0)).getAddress());
|
||||||
case Builtin::BI__noop:
|
case Builtin::BI__noop:
|
||||||
return RValue::get(0);
|
return RValue::get(0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -95,6 +95,22 @@ static bool SemaBuiltinAnnotation(Sema &S, CallExpr *TheCall) {
|
||||||
return false;
|
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
|
ExprResult
|
||||||
Sema::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
|
Sema::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
|
||||||
ExprResult TheCallResult(Owned(TheCall));
|
ExprResult TheCallResult(Owned(TheCall));
|
||||||
|
@ -275,6 +291,10 @@ Sema::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
|
||||||
if (SemaBuiltinAnnotation(*this, TheCall))
|
if (SemaBuiltinAnnotation(*this, TheCall))
|
||||||
return ExprError();
|
return ExprError();
|
||||||
break;
|
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
|
// Since the target specific builtins for each arch overlap, only check those
|
||||||
|
|
|
@ -7,3 +7,11 @@ int main() {
|
||||||
// CHECK: call {{signext i8|i8}} @memmove()
|
// CHECK: call {{signext i8|i8}} @memmove()
|
||||||
return 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;
|
typedef const struct __CFString * CFStringRef;
|
||||||
#define CFSTR __builtin___CFStringMakeConstantString
|
#define CFSTR __builtin___CFStringMakeConstantString
|
||||||
|
|
||||||
|
@ -24,3 +24,17 @@ void f2() {
|
||||||
// pr14895
|
// pr14895
|
||||||
typedef __typeof(sizeof(int)) size_t;
|
typedef __typeof(sizeof(int)) size_t;
|
||||||
extern "C" void *__builtin_alloca (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