[clang] [clang] Add __builtin_start_object_lifetime builtin. (PR #82776)

2024-05-16 Thread Ilya Biryukov via cfe-commits

ilya-biryukov wrote:

I second @cor3ntin's concern here. We are adding a builtin that is named very 
similarly to the one from C++23 standard, but not actually having the semantics 
that is desired.

I believe we do need the effect that __builtin_launder provides to allow memcpy 
for types that have vtables, which was original motivation for this change and 
#86512. However, we could get those guarantees by using __builtin_launder 
directly.
Looking at the code, the __builtin_launder currently has a sole effect of 
preventing optimizations that would load an incorrect vtable when 
-fstrict-vtable-pointers is passed and same storage is reused for different 
types.

I feel it's better to just go with std::launder on our end at this point and 
instead focus on preventing misoptimizations from TBAA to get a proper 
implementation of start_lifetime_as. It carries a risk of hitting a 
misoptimization in the future on our end, but seems very unlikely unless we 
start using TBAA or LLVM starts optimizing much more aggressively based on C++ 
notion of object lifetimes, neither of which should go unnoticed.

@hokein WDYT?

https://github.com/llvm/llvm-project/pull/82776
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Add __builtin_start_object_lifetime builtin. (PR #82776)

2024-04-29 Thread via cfe-commits

cor3ntin wrote:

@sam-mccall Are you referring to https://reviews.llvm.org/D147020 or something 
more recent?

https://github.com/llvm/llvm-project/pull/82776
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Add __builtin_start_object_lifetime builtin. (PR #82776)

2024-04-29 Thread Haojian Wu via cfe-commits

hokein wrote:

Friendly ping.

https://github.com/llvm/llvm-project/pull/82776
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Add __builtin_start_object_lifetime builtin. (PR #82776)

2024-04-29 Thread Haojian Wu via cfe-commits

https://github.com/hokein updated 
https://github.com/llvm/llvm-project/pull/82776

>From 3ab1a074592f85715c061007c56c69c24794a556 Mon Sep 17 00:00:00 2001
From: Haojian Wu 
Date: Fri, 23 Feb 2024 10:03:16 +0100
Subject: [PATCH 1/2] [clang] Add __builtin_start_object_lifetime builtin.

This patch implements a clang built `__builtin_start_object_lifetime`,
it has the same semantics as C++23's `std::start_lifetime_as`, but
without the implicit-lifetime type restriction, it can be used for
implementing `std::start_lifetime_as` in the future.

Due to the current clang lowering, the builtin reuses the existing 
`__builtin_launder` implementation:
- it is a no-op for the most part;
- with `-fstrict-vtable-pointers` flag, we update the vtpr assumption correctly
  (mark the load/store vptr with appropriate invariant group intrinsics)
  to prevent incorrect vptr load folding;
- for now, the builtin is non-constant, cannot be executed in constant 
evaluation;

CAVEAT:
- this builtin may cause TBAA miscomplies without the `-fno-strict-alias`
  flag. These TBAA miscompiles are known issues and may need more LLVM
  IR support for the fix, fixing them is orthogonal to the implementaton of the
  builtin.

Context: 
https://discourse.llvm.org/t/extension-for-creating-objects-via-memcpy/76961
---
 clang/include/clang/Basic/Builtins.td |  6 +++
 clang/lib/CodeGen/CGBuiltin.cpp   |  1 +
 clang/lib/Sema/SemaChecking.cpp   |  2 +
 clang/test/CodeGen/builtins.c | 10 
 .../builtin-start-object-life-time.cpp| 49 +++
 clang/test/SemaCXX/builtins.cpp   | 33 -
 6 files changed, 100 insertions(+), 1 deletion(-)
 create mode 100644 clang/test/CodeGenCXX/builtin-start-object-life-time.cpp

diff --git a/clang/include/clang/Basic/Builtins.td 
b/clang/include/clang/Basic/Builtins.td
index de721a87b3341d..399fabe53d9fa0 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -926,6 +926,12 @@ def Launder : Builtin {
   let Prototype = "void*(void*)";
 }
 
+def StartObjectLifeTime : Builtin {
+  let Spellings = ["__builtin_start_object_lifetime"];
+  let Attributes = [NoThrow, CustomTypeChecking];
+  let Prototype = "void*(void*)";
+}
+
 def IsConstantEvaluated : LangBuiltin<"CXX_LANG"> {
   let Spellings = ["__builtin_is_constant_evaluated"];
   let Attributes = [NoThrow, Constexpr];
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 7e5f2edfc732cc..e81f39149bfbc9 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -4521,6 +4521,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl 
GD, unsigned BuiltinID,
 
 return RValue::get(nullptr);
   }
+  case Builtin::BI__builtin_start_object_lifetime:
   case Builtin::BI__builtin_launder: {
 const Expr *Arg = E->getArg(0);
 QualType ArgTy = Arg->getType()->getPointeeType();
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 51757f4cf727d6..f16a9a53857154 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -38,6 +38,7 @@
 #include "clang/AST/TypeLoc.h"
 #include "clang/AST/UnresolvedSet.h"
 #include "clang/Basic/AddressSpaces.h"
+#include "clang/Basic/Builtins.h"
 #include "clang/Basic/CharInfo.h"
 #include "clang/Basic/Diagnostic.h"
 #include "clang/Basic/IdentifierTable.h"
@@ -2641,6 +2642,7 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, 
unsigned BuiltinID,
 TheCall->setType(Context.IntTy);
 break;
   }
+  case Builtin::BI__builtin_start_object_lifetime:
   case Builtin::BI__builtin_launder:
 return BuiltinLaunder(*this, TheCall);
   case Builtin::BI__sync_fetch_and_add:
diff --git a/clang/test/CodeGen/builtins.c b/clang/test/CodeGen/builtins.c
index 407e0857d22311..00c81c23d0ed02 100644
--- a/clang/test/CodeGen/builtins.c
+++ b/clang/test/CodeGen/builtins.c
@@ -143,6 +143,7 @@ int main(void) {
   P(signbit, (1.0));
 
   R(launder, ());
+  R(start_object_lifetime, ());
 
   return 0;
 }
@@ -511,6 +512,15 @@ void test_builtin_launder(int *p) {
   int *d = __builtin_launder(p);
 }
 
+/// It should be a NOP in C since there are no vtables.
+// CHECK-LABEL: define{{.*}} void @test_builtin_start_object_lifetime
+void test_builtin_start_object_lifetime(int *p) {
+  // CHECK: [[TMP:%.*]] = load ptr,
+  // CHECK-NOT: @llvm.launder
+  // CHECK: store ptr [[TMP]],
+  int *d = __builtin_start_object_lifetime(p);
+}
+
 // __warn_memset_zero_len should be NOP, see 
https://sourceware.org/bugzilla/show_bug.cgi?id=25399
 // CHECK-LABEL: define{{.*}} void @test___warn_memset_zero_len
 void test___warn_memset_zero_len(void) {
diff --git a/clang/test/CodeGenCXX/builtin-start-object-life-time.cpp 
b/clang/test/CodeGenCXX/builtin-start-object-life-time.cpp
new file mode 100644
index 00..58012f52cc0ef5
--- /dev/null
+++ b/clang/test/CodeGenCXX/builtin-start-object-life-time.cpp
@@ -0,0 

[clang] [clang] Add __builtin_start_object_lifetime builtin. (PR #82776)

2024-04-02 Thread Haojian Wu via cfe-commits

https://github.com/hokein updated 
https://github.com/llvm/llvm-project/pull/82776

>From 7fcd58b750872221aa754e81e17ab9068e144a44 Mon Sep 17 00:00:00 2001
From: Haojian Wu 
Date: Fri, 23 Feb 2024 10:03:16 +0100
Subject: [PATCH 1/2] [clang] Add __builtin_start_object_lifetime builtin.

This patch implements a clang built `__builtin_start_object_lifetime`,
it has the same semantics as C++23's `std::start_lifetime_as`, but
without the implicit-lifetime type restriction, it can be used for
implementing `std::start_lifetime_as` in the future.

Due to the current clang lowering, the builtin reuses the existing 
`__builtin_launder` implementation:
- it is a no-op for the most part;
- with `-fstrict-vtable-pointers` flag, we update the vtpr assumption correctly
  (mark the load/store vptr with appropriate invariant group intrinsics)
  to prevent incorrect vptr load folding;
- for now, the builtin is non-constant, cannot be executed in constant 
evaluation;

CAVEAT:
- this builtin may cause TBAA miscomplies without the `-fno-strict-alias`
  flag. These TBAA miscompiles are known issues and may need more LLVM
  IR support for the fix, fixing them is orthogonal to the implementaton of the
  builtin.

Context: 
https://discourse.llvm.org/t/extension-for-creating-objects-via-memcpy/76961
---
 clang/include/clang/Basic/Builtins.td |  6 +++
 clang/lib/CodeGen/CGBuiltin.cpp   |  1 +
 clang/lib/Sema/SemaChecking.cpp   |  2 +
 clang/test/CodeGen/builtins.c | 10 
 .../builtin-start-object-life-time.cpp| 49 +++
 clang/test/SemaCXX/builtins.cpp   | 33 -
 6 files changed, 100 insertions(+), 1 deletion(-)
 create mode 100644 clang/test/CodeGenCXX/builtin-start-object-life-time.cpp

diff --git a/clang/include/clang/Basic/Builtins.td 
b/clang/include/clang/Basic/Builtins.td
index f421223ff087de..2c2e0eb58b15a1 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -926,6 +926,12 @@ def Launder : Builtin {
   let Prototype = "void*(void*)";
 }
 
+def StartObjectLifeTime : Builtin {
+  let Spellings = ["__builtin_start_object_lifetime"];
+  let Attributes = [NoThrow, CustomTypeChecking];
+  let Prototype = "void*(void*)";
+}
+
 def IsConstantEvaluated : LangBuiltin<"CXX_LANG"> {
   let Spellings = ["__builtin_is_constant_evaluated"];
   let Attributes = [NoThrow, Constexpr];
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 483f9c26859923..6cdb602f8bb07d 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -4509,6 +4509,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl 
GD, unsigned BuiltinID,
 
 return RValue::get(nullptr);
   }
+  case Builtin::BI__builtin_start_object_lifetime:
   case Builtin::BI__builtin_launder: {
 const Expr *Arg = E->getArg(0);
 QualType ArgTy = Arg->getType()->getPointeeType();
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 11401b6f56c0ea..356765609f694b 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -37,6 +37,7 @@
 #include "clang/AST/TypeLoc.h"
 #include "clang/AST/UnresolvedSet.h"
 #include "clang/Basic/AddressSpaces.h"
+#include "clang/Basic/Builtins.h"
 #include "clang/Basic/CharInfo.h"
 #include "clang/Basic/Diagnostic.h"
 #include "clang/Basic/IdentifierTable.h"
@@ -2642,6 +2643,7 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, 
unsigned BuiltinID,
 TheCall->setType(Context.IntTy);
 break;
   }
+  case Builtin::BI__builtin_start_object_lifetime:
   case Builtin::BI__builtin_launder:
 return SemaBuiltinLaunder(*this, TheCall);
   case Builtin::BI__sync_fetch_and_add:
diff --git a/clang/test/CodeGen/builtins.c b/clang/test/CodeGen/builtins.c
index 407e0857d22311..00c81c23d0ed02 100644
--- a/clang/test/CodeGen/builtins.c
+++ b/clang/test/CodeGen/builtins.c
@@ -143,6 +143,7 @@ int main(void) {
   P(signbit, (1.0));
 
   R(launder, ());
+  R(start_object_lifetime, ());
 
   return 0;
 }
@@ -511,6 +512,15 @@ void test_builtin_launder(int *p) {
   int *d = __builtin_launder(p);
 }
 
+/// It should be a NOP in C since there are no vtables.
+// CHECK-LABEL: define{{.*}} void @test_builtin_start_object_lifetime
+void test_builtin_start_object_lifetime(int *p) {
+  // CHECK: [[TMP:%.*]] = load ptr,
+  // CHECK-NOT: @llvm.launder
+  // CHECK: store ptr [[TMP]],
+  int *d = __builtin_start_object_lifetime(p);
+}
+
 // __warn_memset_zero_len should be NOP, see 
https://sourceware.org/bugzilla/show_bug.cgi?id=25399
 // CHECK-LABEL: define{{.*}} void @test___warn_memset_zero_len
 void test___warn_memset_zero_len(void) {
diff --git a/clang/test/CodeGenCXX/builtin-start-object-life-time.cpp 
b/clang/test/CodeGenCXX/builtin-start-object-life-time.cpp
new file mode 100644
index 00..58012f52cc0ef5
--- /dev/null
+++ b/clang/test/CodeGenCXX/builtin-start-object-life-time.cpp
@@ -0,0 

[clang] [clang] Add __builtin_start_object_lifetime builtin. (PR #82776)

2024-04-02 Thread Haojian Wu via cfe-commits


@@ -156,6 +156,37 @@ void test_noexcept(int *i) {
 #undef TEST_TYPE
 } // end namespace test_launder
 
+namespace test_start_object_lifetime {
+// The builtin is non-constant.
+constexpr int test_non_constexpr(int i) { // expected-error {{constexpr 
function never produces a constant expression}}
+  __builtin_start_object_lifetime(); // expected-note {{subexpression not 
valid in a constant expression}}
+#ifdef CXX11
+  // expected-warning@-2 {{use of this statement in a constexpr function is a 
C++14 extension}}
+#endif
+  return 0;
+}
+
+struct Incomplete; // expected-note {{forward declaration}}
+void test_incomplete(Incomplete *i) {
+   // Requires a complete type
+   __builtin_start_object_lifetime(i); // expected-error {{incomplete type 
'Incomplete' where a complete type is required}}
+}
+
+// The builtin is type-generic.
+#define TEST_TYPE(Ptr, Type) \
+  static_assert(__is_same(decltype(__builtin_launder(Ptr)), Type), "expected 
same type")

hokein wrote:

oops, yeah, it should be `__builtin_start_object_lifetime `.

https://github.com/llvm/llvm-project/pull/82776
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Add __builtin_start_object_lifetime builtin. (PR #82776)

2024-04-02 Thread Haojian Wu via cfe-commits


@@ -896,6 +896,12 @@ def Launder : Builtin {
   let Prototype = "void*(void*)";
 }
 
+def StartObjectLifeTime : Builtin {
+  let Spellings = ["__builtin_start_object_lifetime"];

hokein wrote:

I don't have strong opinion on the name. Since this builtin doesn't strictly 
align with std::start_lifetime_as, I think it's better to have some divergence 
in the name.

https://github.com/llvm/llvm-project/pull/82776
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Add __builtin_start_object_lifetime builtin. (PR #82776)

2024-04-02 Thread Haojian Wu via cfe-commits


@@ -4386,6 +4386,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl 
GD, unsigned BuiltinID,
 
 return RValue::get(nullptr);
   }
+  case Builtin::BI__builtin_start_object_lifetime:

hokein wrote:

Added a comment for it, please take a look.

https://github.com/llvm/llvm-project/pull/82776
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Add __builtin_start_object_lifetime builtin. (PR #82776)

2024-04-02 Thread Haojian Wu via cfe-commits


@@ -896,6 +896,12 @@ def Launder : Builtin {
   let Prototype = "void*(void*)";
 }
 
+def StartObjectLifeTime : Builtin {

hokein wrote:

Done.

https://github.com/llvm/llvm-project/pull/82776
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Add __builtin_start_object_lifetime builtin. (PR #82776)

2024-04-02 Thread Haojian Wu via cfe-commits


@@ -4386,6 +4386,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl 
GD, unsigned BuiltinID,
 
 return RValue::get(nullptr);
   }
+  case Builtin::BI__builtin_start_object_lifetime:
   case Builtin::BI__builtin_launder: {

hokein wrote:

I think the name is fine, we're in the CodeGen, and the BuiltinLaunder in 
`TypeRequiresBuiltinLaunder` means the LLVM IR `llvm.launder` 
[intrinsics](https://llvm.org/docs/LangRef.html#llvm-launder-invariant-group-intrinsic).

https://github.com/llvm/llvm-project/pull/82776
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Add __builtin_start_object_lifetime builtin. (PR #82776)

2024-04-02 Thread Haojian Wu via cfe-commits

https://github.com/hokein updated 
https://github.com/llvm/llvm-project/pull/82776

>From 7fcd58b750872221aa754e81e17ab9068e144a44 Mon Sep 17 00:00:00 2001
From: Haojian Wu 
Date: Fri, 23 Feb 2024 10:03:16 +0100
Subject: [PATCH 1/2] [clang] Add __builtin_start_object_lifetime builtin.

This patch implements a clang built `__builtin_start_object_lifetime`,
it has the same semantics as C++23's `std::start_lifetime_as`, but
without the implicit-lifetime type restriction, it can be used for
implementing `std::start_lifetime_as` in the future.

Due to the current clang lowering, the builtin reuses the existing 
`__builtin_launder` implementation:
- it is a no-op for the most part;
- with `-fstrict-vtable-pointers` flag, we update the vtpr assumption correctly
  (mark the load/store vptr with appropriate invariant group intrinsics)
  to prevent incorrect vptr load folding;
- for now, the builtin is non-constant, cannot be executed in constant 
evaluation;

CAVEAT:
- this builtin may cause TBAA miscomplies without the `-fno-strict-alias`
  flag. These TBAA miscompiles are known issues and may need more LLVM
  IR support for the fix, fixing them is orthogonal to the implementaton of the
  builtin.

Context: 
https://discourse.llvm.org/t/extension-for-creating-objects-via-memcpy/76961
---
 clang/include/clang/Basic/Builtins.td |  6 +++
 clang/lib/CodeGen/CGBuiltin.cpp   |  1 +
 clang/lib/Sema/SemaChecking.cpp   |  2 +
 clang/test/CodeGen/builtins.c | 10 
 .../builtin-start-object-life-time.cpp| 49 +++
 clang/test/SemaCXX/builtins.cpp   | 33 -
 6 files changed, 100 insertions(+), 1 deletion(-)
 create mode 100644 clang/test/CodeGenCXX/builtin-start-object-life-time.cpp

diff --git a/clang/include/clang/Basic/Builtins.td 
b/clang/include/clang/Basic/Builtins.td
index f421223ff087de..2c2e0eb58b15a1 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -926,6 +926,12 @@ def Launder : Builtin {
   let Prototype = "void*(void*)";
 }
 
+def StartObjectLifeTime : Builtin {
+  let Spellings = ["__builtin_start_object_lifetime"];
+  let Attributes = [NoThrow, CustomTypeChecking];
+  let Prototype = "void*(void*)";
+}
+
 def IsConstantEvaluated : LangBuiltin<"CXX_LANG"> {
   let Spellings = ["__builtin_is_constant_evaluated"];
   let Attributes = [NoThrow, Constexpr];
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 483f9c26859923..6cdb602f8bb07d 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -4509,6 +4509,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl 
GD, unsigned BuiltinID,
 
 return RValue::get(nullptr);
   }
+  case Builtin::BI__builtin_start_object_lifetime:
   case Builtin::BI__builtin_launder: {
 const Expr *Arg = E->getArg(0);
 QualType ArgTy = Arg->getType()->getPointeeType();
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 11401b6f56c0ea..356765609f694b 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -37,6 +37,7 @@
 #include "clang/AST/TypeLoc.h"
 #include "clang/AST/UnresolvedSet.h"
 #include "clang/Basic/AddressSpaces.h"
+#include "clang/Basic/Builtins.h"
 #include "clang/Basic/CharInfo.h"
 #include "clang/Basic/Diagnostic.h"
 #include "clang/Basic/IdentifierTable.h"
@@ -2642,6 +2643,7 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, 
unsigned BuiltinID,
 TheCall->setType(Context.IntTy);
 break;
   }
+  case Builtin::BI__builtin_start_object_lifetime:
   case Builtin::BI__builtin_launder:
 return SemaBuiltinLaunder(*this, TheCall);
   case Builtin::BI__sync_fetch_and_add:
diff --git a/clang/test/CodeGen/builtins.c b/clang/test/CodeGen/builtins.c
index 407e0857d22311..00c81c23d0ed02 100644
--- a/clang/test/CodeGen/builtins.c
+++ b/clang/test/CodeGen/builtins.c
@@ -143,6 +143,7 @@ int main(void) {
   P(signbit, (1.0));
 
   R(launder, ());
+  R(start_object_lifetime, ());
 
   return 0;
 }
@@ -511,6 +512,15 @@ void test_builtin_launder(int *p) {
   int *d = __builtin_launder(p);
 }
 
+/// It should be a NOP in C since there are no vtables.
+// CHECK-LABEL: define{{.*}} void @test_builtin_start_object_lifetime
+void test_builtin_start_object_lifetime(int *p) {
+  // CHECK: [[TMP:%.*]] = load ptr,
+  // CHECK-NOT: @llvm.launder
+  // CHECK: store ptr [[TMP]],
+  int *d = __builtin_start_object_lifetime(p);
+}
+
 // __warn_memset_zero_len should be NOP, see 
https://sourceware.org/bugzilla/show_bug.cgi?id=25399
 // CHECK-LABEL: define{{.*}} void @test___warn_memset_zero_len
 void test___warn_memset_zero_len(void) {
diff --git a/clang/test/CodeGenCXX/builtin-start-object-life-time.cpp 
b/clang/test/CodeGenCXX/builtin-start-object-life-time.cpp
new file mode 100644
index 00..58012f52cc0ef5
--- /dev/null
+++ b/clang/test/CodeGenCXX/builtin-start-object-life-time.cpp
@@ -0,0 

[clang] [clang] Add __builtin_start_object_lifetime builtin. (PR #82776)

2024-03-27 Thread A. Jiang via cfe-commits

frederick-vs-ja wrote:

> This does something both useful and correct with `-fno-strict-aliasing`.

I'm not sure whether an instrinsic is even needed with `-fno-strict-aliasing`. 
IIUC `std::start_lifetime_as` mainly tells the compiler that the types of data 
in the storage can be changed (indeterminately) with the object representations 
unchanged. This behaves like some fence for TBAA.

> we can now observe them and use them to validate e.g. the `llvm.tbaa.fence` 
> proposal.

Yeah. I guess we need to implement `std::start_lifetime_as(_array)` with 
`llvm.tbaa.fence`.

https://github.com/llvm/llvm-project/pull/82776
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Add __builtin_start_object_lifetime builtin. (PR #82776)

2024-03-27 Thread Sam McCall via cfe-commits


@@ -156,6 +156,37 @@ void test_noexcept(int *i) {
 #undef TEST_TYPE
 } // end namespace test_launder
 
+namespace test_start_object_lifetime {
+// The builtin is non-constant.
+constexpr int test_non_constexpr(int i) { // expected-error {{constexpr 
function never produces a constant expression}}
+  __builtin_start_object_lifetime(); // expected-note {{subexpression not 
valid in a constant expression}}
+#ifdef CXX11
+  // expected-warning@-2 {{use of this statement in a constexpr function is a 
C++14 extension}}
+#endif
+  return 0;
+}
+
+struct Incomplete; // expected-note {{forward declaration}}
+void test_incomplete(Incomplete *i) {
+   // Requires a complete type
+   __builtin_start_object_lifetime(i); // expected-error {{incomplete type 
'Incomplete' where a complete type is required}}
+}
+
+// The builtin is type-generic.
+#define TEST_TYPE(Ptr, Type) \
+  static_assert(__is_same(decltype(__builtin_launder(Ptr)), Type), "expected 
same type")

sam-mccall wrote:

should this be `__builtin_start_object_lifetime`?

https://github.com/llvm/llvm-project/pull/82776
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Add __builtin_start_object_lifetime builtin. (PR #82776)

2024-03-27 Thread Sam McCall via cfe-commits


@@ -896,6 +896,12 @@ def Launder : Builtin {
   let Prototype = "void*(void*)";
 }
 
+def StartObjectLifeTime : Builtin {

sam-mccall wrote:

https://github.com/llvm/llvm-project/pull/86512 is the answer here, I think.

https://github.com/llvm/llvm-project/pull/82776
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Add __builtin_start_object_lifetime builtin. (PR #82776)

2024-03-27 Thread Sam McCall via cfe-commits

sam-mccall wrote:

This has been dormant in part while thinking about the memcpy half, I think.
Something like https://github.com/llvm/llvm-project/pull/86512 solves that well 
but likely needs this change too.

> I am a bit concerned that this does not actually have the desired semantics 
> at all, but @zygoloid seemed to be "happy" with it. I will admit I struggle 
> understanding the motivation of adding a builtin that does...less than it 
> should.

This does something both useful and correct with `-fno-strict-aliasing`. I 
think we're far from alone in building in this mode (in part precisely because 
of existing TBAA soundness questions!)[1].

I think it gets us incrementally closer to fully supporting 
std::start_lifetime_as: if there are specific miscompiles this would produce 
with strict-aliasing enabled, we can now observe them and use them to validate 
e.g. the `llvm.tbaa.fence` proposal. (It looks like what we need here but I 
also don't understand the LLVM change deeply).

> Similarly, do you have plans for the array version of start_lifetime_as?

I think we need a similar parallel version of this, e.g.: 
`__start_dynamic_array_lifetime(T*, size_t) -> T*`.
This seems like a purely mechanical extension that could be done in this patch 
or subsequently. Preferences?

[1] I hope this is the year we can put some work into strict-aliasing and turn 
it on. By coincidence, our best estimate of the overall performance win is 
roughly the same as applying this optimization to one widely-used library...

https://github.com/llvm/llvm-project/pull/82776
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Add __builtin_start_object_lifetime builtin. (PR #82776)

2024-03-03 Thread via cfe-commits

cor3ntin wrote:

I am a bit concerned that this does not actually have the desired semantics at 
all, but @zygoloid seemed to be "happy" with it.  I will admit I struggle 
understanding the motivation of adding a builtin that does...less than it 
should (when it should do something).

Similarly, do you have plans for the array version of start_lifetime_as?

https://github.com/llvm/llvm-project/pull/82776
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Add __builtin_start_object_lifetime builtin. (PR #82776)

2024-02-25 Thread A. Jiang via cfe-commits


@@ -896,6 +896,12 @@ def Launder : Builtin {
   let Prototype = "void*(void*)";
 }
 
+def StartObjectLifeTime : Builtin {
+  let Spellings = ["__builtin_start_object_lifetime"];

frederick-vs-ja wrote:

IMO if the intent of this intrinsic is to handle polymorphic classes (which is 
not covered by `std::start_lifetime_as`), its name should diverge from "plain" 
`start_lifetime`.

https://github.com/llvm/llvm-project/pull/82776
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Add __builtin_start_object_lifetime builtin. (PR #82776)

2024-02-23 Thread Richard Smith via cfe-commits


@@ -896,6 +896,12 @@ def Launder : Builtin {
   let Prototype = "void*(void*)";
 }
 
+def StartObjectLifeTime : Builtin {

zygoloid wrote:

Nit: lifetime is one word not two, so the `T` should not be capitalized.

https://github.com/llvm/llvm-project/pull/82776
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Add __builtin_start_object_lifetime builtin. (PR #82776)

2024-02-23 Thread Sam McCall via cfe-commits


@@ -896,6 +896,12 @@ def Launder : Builtin {
   let Prototype = "void*(void*)";
 }
 
+def StartObjectLifeTime : Builtin {

sam-mccall wrote:

For creating-objects-via-memcpy, what are we planning to do about the memcpy 
part being UB and the start_lifetime part being correspondingly hard to specify 
(what's the relationship between the bytes and the new objects?)

I thought a combined memcpy + start_object_lifetime intrinsic would solve this 
neatly (values of new objects are the values of the old objects), but certainly 
we want the start-lifetime-only part to support start_lifetime_as.  

I don't see a great way out for non-implicit-lifetime types though...

https://github.com/llvm/llvm-project/pull/82776
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Add __builtin_start_object_lifetime builtin. (PR #82776)

2024-02-23 Thread Sam McCall via cfe-commits


@@ -896,6 +896,12 @@ def Launder : Builtin {
   let Prototype = "void*(void*)";
 }
 
+def StartObjectLifeTime : Builtin {
+  let Spellings = ["__builtin_start_object_lifetime"];

sam-mccall wrote:

nit, I'd consider `__builtin_start_lifetime` both for brevity and to parallel 
`std::start_lifetime_as`.
I don't think it's really ambiguous what we're starting the lifetime of.

https://github.com/llvm/llvm-project/pull/82776
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Add __builtin_start_object_lifetime builtin. (PR #82776)

2024-02-23 Thread Sam McCall via cfe-commits


@@ -4386,6 +4386,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl 
GD, unsigned BuiltinID,
 
 return RValue::get(nullptr);
   }
+  case Builtin::BI__builtin_start_object_lifetime:

sam-mccall wrote:

is there something to be commented here about why what we do here is sufficient?
It seems surprising to my very-untrained eye that start_lifetime is the same as 
launder, and we don't need any extra TBAA metadata or so...

https://github.com/llvm/llvm-project/pull/82776
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Add __builtin_start_object_lifetime builtin. (PR #82776)

2024-02-23 Thread Sam McCall via cfe-commits

https://github.com/sam-mccall edited 
https://github.com/llvm/llvm-project/pull/82776
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Add __builtin_start_object_lifetime builtin. (PR #82776)

2024-02-23 Thread Sam McCall via cfe-commits

https://github.com/sam-mccall commented:

Thanks for working on this! I'm far from an expert on the LLVM side so we'll 
need someone to weigh in.


We need to specify specify the behavior somewhere. I think we should add a 
description to `docs/LanguageExtensions.html`, which describes various other 
`__builtin_*`.

I'm not sure defining this in terms of "like start_lifetime_as but..." is ideal 
because:

 - implicit object creation recurses into only implicit-lifetimes subobjects, 
where this will recurse into everything. (Whether this is the same or different 
depends on your persepctive.
 - Unlike start_lifetime_as, it's clearly more useful to say "this starts an 
object's lifetime" than "this may start an object's lifetime as needed to avoid 
UB", I think this clarifies when you can/must call destructors. In this sense 
it's more like placement-new than start-lifetime-as.

https://github.com/llvm/llvm-project/pull/82776
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Add __builtin_start_object_lifetime builtin. (PR #82776)

2024-02-23 Thread A. Jiang via cfe-commits

frederick-vs-ja wrote:

> * with `-fstrict-vtable-pointers` flag, we update the vtpr assumption 
> correctly (mark the load/store vptr with appropriate invariant group 
> intrinsics) to prevent incorrect vptr load folding;

I _guess_ we want a variant of this intrinsic which doesn't affect analyzation 
for devirtualization. Such an intrinsic should be sufficient for **C++23** 
`std::start_lifetime_as(_array)`.

> * for now, it is non-constant, thus cannot be executed in constant evaluation;

It seems intended that `std::start_lifetime_as(_array)` is not usable in 
constant evaluation, as the indeterminism of implicit object creation doesn't 
seem compatible with constant evaluation.


https://github.com/llvm/llvm-project/pull/82776
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Add __builtin_start_object_lifetime builtin. (PR #82776)

2024-02-23 Thread Erich Keane via cfe-commits


@@ -4386,6 +4386,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl 
GD, unsigned BuiltinID,
 
 return RValue::get(nullptr);
   }
+  case Builtin::BI__builtin_start_object_lifetime:
   case Builtin::BI__builtin_launder: {

erichkeane wrote:

Should the `TypeRequiresBuiltinLaunder` function be generalized, at least in 
name?

https://github.com/llvm/llvm-project/pull/82776
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Add __builtin_start_object_lifetime builtin. (PR #82776)

2024-02-23 Thread Erich Keane via cfe-commits

https://github.com/erichkeane commented:

This would also need a release note I believe. I don't have the codegen 
expertise to review this with high confidence, but it looks right to me.

https://github.com/llvm/llvm-project/pull/82776
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Add __builtin_start_object_lifetime builtin. (PR #82776)

2024-02-23 Thread Erich Keane via cfe-commits

https://github.com/erichkeane edited 
https://github.com/llvm/llvm-project/pull/82776
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Add __builtin_start_object_lifetime builtin. (PR #82776)

2024-02-23 Thread via cfe-commits

llvmbot wrote:




@llvm/pr-subscribers-clang

Author: Haojian Wu (hokein)


Changes

This patch implements a clang builtin `__builtin_start_object_lifetime`, it has 
the same semantics as C++23's `std::start_lifetime_as`, but without the 
implicit-lifetime type restriction, it could be used for implementing 
`std::start_lifetime_as` in the future.

Due to the current clang lowering, the builtin reuses the existing 
`__builtin_launder` implementation:
- it is a no-op for the most part;
- with `-fstrict-vtable-pointers` flag, we update the vtpr assumption correctly 
(mark the load/store vptr with appropriate invariant group intrinsics) to 
prevent incorrect vptr load folding;
- for now, it is non-constant, thus cannot be executed in constant evaluation;

CAVEAT:
- this builtin may cause TBAA miscomplies without the `-fno-strict-aliasing` 
flag. These TBAA miscompiles are known issues and may need more LLVM IR support 
for the fix, fixing them is orthogonal to the implementation of the builtin.

Context: https://discourse.llvm.org/t/extension-for-creating-objects-via-memcpy

---
Full diff: https://github.com/llvm/llvm-project/pull/82776.diff


6 Files Affected:

- (modified) clang/include/clang/Basic/Builtins.td (+6) 
- (modified) clang/lib/CodeGen/CGBuiltin.cpp (+1) 
- (modified) clang/lib/Sema/SemaChecking.cpp (+2) 
- (modified) clang/test/CodeGen/builtins.c (+10) 
- (added) clang/test/CodeGenCXX/builtin-start-object-life-time.cpp (+49) 
- (modified) clang/test/SemaCXX/builtins.cpp (+32-1) 


``diff
diff --git a/clang/include/clang/Basic/Builtins.td 
b/clang/include/clang/Basic/Builtins.td
index df74026c5d2d50..70361afe69a980 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -896,6 +896,12 @@ def Launder : Builtin {
   let Prototype = "void*(void*)";
 }
 
+def StartObjectLifeTime : Builtin {
+  let Spellings = ["__builtin_start_object_lifetime"];
+  let Attributes = [NoThrow, CustomTypeChecking];
+  let Prototype = "void*(void*)";
+}
+
 def IsConstantEvaluated : LangBuiltin<"CXX_LANG"> {
   let Spellings = ["__builtin_is_constant_evaluated"];
   let Attributes = [NoThrow, Constexpr];
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index d454ccc1dd8613..7a98f734f32ada 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -4386,6 +4386,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl 
GD, unsigned BuiltinID,
 
 return RValue::get(nullptr);
   }
+  case Builtin::BI__builtin_start_object_lifetime:
   case Builtin::BI__builtin_launder: {
 const Expr *Arg = E->getArg(0);
 QualType ArgTy = Arg->getType()->getPointeeType();
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 8e76338477..f79cb7e0445260 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -37,6 +37,7 @@
 #include "clang/AST/TypeLoc.h"
 #include "clang/AST/UnresolvedSet.h"
 #include "clang/Basic/AddressSpaces.h"
+#include "clang/Basic/Builtins.h"
 #include "clang/Basic/CharInfo.h"
 #include "clang/Basic/Diagnostic.h"
 #include "clang/Basic/IdentifierTable.h"
@@ -2386,6 +2387,7 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, 
unsigned BuiltinID,
 TheCall->setType(Context.IntTy);
 break;
   }
+  case Builtin::BI__builtin_start_object_lifetime:
   case Builtin::BI__builtin_launder:
 return SemaBuiltinLaunder(*this, TheCall);
   case Builtin::BI__sync_fetch_and_add:
diff --git a/clang/test/CodeGen/builtins.c b/clang/test/CodeGen/builtins.c
index 88282120283b8a..f46d6eb7632afc 100644
--- a/clang/test/CodeGen/builtins.c
+++ b/clang/test/CodeGen/builtins.c
@@ -143,6 +143,7 @@ int main(void) {
   P(signbit, (1.0));
 
   R(launder, ());
+  R(start_object_lifetime, ());
 
   return 0;
 }
@@ -511,6 +512,15 @@ void test_builtin_launder(int *p) {
   int *d = __builtin_launder(p);
 }
 
+/// It should be a NOP in C since there are no vtables.
+// CHECK-LABEL: define{{.*}} void @test_builtin_start_object_lifetime
+void test_builtin_start_object_lifetime(int *p) {
+  // CHECK: [[TMP:%.*]] = load ptr,
+  // CHECK-NOT: @llvm.launder
+  // CHECK: store ptr [[TMP]],
+  int *d = __builtin_start_object_lifetime(p);
+}
+
 // __warn_memset_zero_len should be NOP, see 
https://sourceware.org/bugzilla/show_bug.cgi?id=25399
 // CHECK-LABEL: define{{.*}} void @test___warn_memset_zero_len
 void test___warn_memset_zero_len(void) {
diff --git a/clang/test/CodeGenCXX/builtin-start-object-life-time.cpp 
b/clang/test/CodeGenCXX/builtin-start-object-life-time.cpp
new file mode 100644
index 00..58012f52cc0ef5
--- /dev/null
+++ b/clang/test/CodeGenCXX/builtin-start-object-life-time.cpp
@@ -0,0 +1,49 @@
+// RUN: %clang_cc1 -triple=x86_64-linux-gnu -emit-llvm 
-fstrict-vtable-pointers -o - %s \
+// RUN: | FileCheck --check-prefixes=CHECK,CHECK-STRICT %s
+// RUN: %clang_cc1 -triple=x86_64-linux-gnu -emit-llvm -o - %s \
+// RUN: | FileCheck 

[clang] [clang] Add __builtin_start_object_lifetime builtin. (PR #82776)

2024-02-23 Thread Haojian Wu via cfe-commits

https://github.com/hokein created 
https://github.com/llvm/llvm-project/pull/82776

This patch implements a clang builtin `__builtin_start_object_lifetime`, it has 
the same semantics as C++23's `std::start_lifetime_as`, but without the 
implicit-lifetime type restriction, it could be used for implementing 
`std::start_lifetime_as` in the future.

Due to the current clang lowering, the builtin reuses the existing 
`__builtin_launder` implementation:
- it is a no-op for the most part;
- with `-fstrict-vtable-pointers` flag, we update the vtpr assumption correctly 
(mark the load/store vptr with appropriate invariant group intrinsics) to 
prevent incorrect vptr load folding;
- for now, it is non-constant, thus cannot be executed in constant evaluation;

CAVEAT:
- this builtin may cause TBAA miscomplies without the `-fno-strict-aliasing` 
flag. These TBAA miscompiles are known issues and may need more LLVM IR support 
for the fix, fixing them is orthogonal to the implementation of the builtin.

Context: https://discourse.llvm.org/t/extension-for-creating-objects-via-memcpy

>From baf6f2eeda35182fcc1e04adf7334b513160419c Mon Sep 17 00:00:00 2001
From: Haojian Wu 
Date: Fri, 23 Feb 2024 10:03:16 +0100
Subject: [PATCH] [clang] Add __builtin_start_object_lifetime builtin.

This patch implements a clang built `__builtin_start_object_lifetime`,
it has the same semantics as C++23's `std::start_lifetime_as`, but
without the implicit-lifetime type restriction, it can be used for
implementing `std::start_lifetime_as` in the future.

Due to the current clang lowering, the builtin reuses the existing 
`__builtin_launder` implementation:
- it is a no-op for the most part;
- with `-fstrict-vtable-pointers` flag, we update the vtpr assumption correctly
  (mark the load/store vptr with appropriate invariant group intrinsics)
  to prevent incorrect vptr load folding;
- for now, the builtin is non-constant, cannot be executed in constant 
evaluation;

CAVEAT:
- this builtin may cause TBAA miscomplies without the `-fno-strict-alias`
  flag. These TBAA miscompiles are known issues and may need more LLVM
  IR support for the fix, fixing them is orthogonal to the implementaton of the
  builtin.

Context: 
https://discourse.llvm.org/t/extension-for-creating-objects-via-memcpy/76961
---
 clang/include/clang/Basic/Builtins.td |  6 +++
 clang/lib/CodeGen/CGBuiltin.cpp   |  1 +
 clang/lib/Sema/SemaChecking.cpp   |  2 +
 clang/test/CodeGen/builtins.c | 10 
 .../builtin-start-object-life-time.cpp| 49 +++
 clang/test/SemaCXX/builtins.cpp   | 33 -
 6 files changed, 100 insertions(+), 1 deletion(-)
 create mode 100644 clang/test/CodeGenCXX/builtin-start-object-life-time.cpp

diff --git a/clang/include/clang/Basic/Builtins.td 
b/clang/include/clang/Basic/Builtins.td
index df74026c5d2d50..70361afe69a980 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -896,6 +896,12 @@ def Launder : Builtin {
   let Prototype = "void*(void*)";
 }
 
+def StartObjectLifeTime : Builtin {
+  let Spellings = ["__builtin_start_object_lifetime"];
+  let Attributes = [NoThrow, CustomTypeChecking];
+  let Prototype = "void*(void*)";
+}
+
 def IsConstantEvaluated : LangBuiltin<"CXX_LANG"> {
   let Spellings = ["__builtin_is_constant_evaluated"];
   let Attributes = [NoThrow, Constexpr];
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index d454ccc1dd8613..7a98f734f32ada 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -4386,6 +4386,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl 
GD, unsigned BuiltinID,
 
 return RValue::get(nullptr);
   }
+  case Builtin::BI__builtin_start_object_lifetime:
   case Builtin::BI__builtin_launder: {
 const Expr *Arg = E->getArg(0);
 QualType ArgTy = Arg->getType()->getPointeeType();
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 8e76338477..f79cb7e0445260 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -37,6 +37,7 @@
 #include "clang/AST/TypeLoc.h"
 #include "clang/AST/UnresolvedSet.h"
 #include "clang/Basic/AddressSpaces.h"
+#include "clang/Basic/Builtins.h"
 #include "clang/Basic/CharInfo.h"
 #include "clang/Basic/Diagnostic.h"
 #include "clang/Basic/IdentifierTable.h"
@@ -2386,6 +2387,7 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, 
unsigned BuiltinID,
 TheCall->setType(Context.IntTy);
 break;
   }
+  case Builtin::BI__builtin_start_object_lifetime:
   case Builtin::BI__builtin_launder:
 return SemaBuiltinLaunder(*this, TheCall);
   case Builtin::BI__sync_fetch_and_add:
diff --git a/clang/test/CodeGen/builtins.c b/clang/test/CodeGen/builtins.c
index 88282120283b8a..f46d6eb7632afc 100644
--- a/clang/test/CodeGen/builtins.c
+++ b/clang/test/CodeGen/builtins.c
@@ -143,6 +143,7 @@ int main(void) {