diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -1170,6 +1170,22 @@ } } + // std::addressof and variants. + if (auto *Call = dyn_cast(E)) { + switch (Call->getBuiltinCallee()) { + default: + break; + case Builtin::BIaddressof: + case Builtin::BI__addressof: + case Builtin::BI__builtin_addressof: { + LValue LV = EmitLValue(Call->getArg(0)); + if (BaseInfo) *BaseInfo = LV.getBaseInfo(); + if (TBAAInfo) *TBAAInfo = LV.getTBAAInfo(); + return LV.getAddress(*this); + } + } + } + // TODO: conditional operators, comma. // Otherwise, use the alignment of the type. diff --git a/clang/test/CodeGenCXX/atomic-align.cpp b/clang/test/CodeGenCXX/atomic-align.cpp --- a/clang/test/CodeGenCXX/atomic-align.cpp +++ b/clang/test/CodeGenCXX/atomic-align.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -std=c++11 -emit-llvm -o - -triple=x86_64-linux-gnu | FileCheck %s +// RUN: %clang_cc1 %s -std=c++14 -emit-llvm -o - -triple=x86_64-linux-gnu | FileCheck %s struct AM { int f1, f2; @@ -28,3 +28,23 @@ __atomic_load(&bm.f2, &am, 0); return am; } + +namespace std { + template + inline constexpr + __attribute__ ((__visibility__("hidden"), __internal_linkage__)) + _Tp* __addressof(_Tp& __x) noexcept + { + return __builtin_addressof(__x); + } +} + +AM load3() { + AM am; + // m is declared to align to 8bytes, so generate load atomic instead + // of libcall. + // CHECK-LABEL: @_Z5load3v + // CHECK: load atomic {{.*}} monotonic, align 8 + __atomic_load(std::__addressof(m), &am, 0); + return am; +}