[lifetime_annotations] Treat function type aliases consistently with other aliases.
This fixes a crash repro recently added to rs_bindings_from_cc.
The crash ultimately resulted from `Importer::ConvertType()` trying to descend
into the defintion of the type alias while the `ValueLifetimes` in the
`lifetimes` parameter did not contain lifetimes for the definition of the type
alias. As defense in depth, add an assertion to `Importer::ConvertType()` that
would have caught this inconsistency at an earlier stage.
PiperOrigin-RevId: 546825633
Change-Id: Ife2d4f12dfe41bae635d7c1516604cfb49d5df19
diff --git a/lifetime_annotations/function_lifetimes.cc b/lifetime_annotations/function_lifetimes.cc
index 0221e66..8fc4080 100644
--- a/lifetime_annotations/function_lifetimes.cc
+++ b/lifetime_annotations/function_lifetimes.cc
@@ -154,7 +154,7 @@
ret.param_lifetimes_.reserve(type->getNumParams());
for (size_t i = 0; i < type->getNumParams(); i++) {
clang::TypeLoc param_type_loc;
- if (type_loc) {
+ if (func_type_loc) {
const clang::ParmVarDecl* param = func_type_loc.getParam(i);
if (param && param->getTypeSourceInfo()) {
param_type_loc = param->getTypeSourceInfo()->getTypeLoc();
diff --git a/lifetime_annotations/lifetime_annotations_test.cc b/lifetime_annotations/lifetime_annotations_test.cc
index fe513c5..648138e 100644
--- a/lifetime_annotations/lifetime_annotations_test.cc
+++ b/lifetime_annotations/lifetime_annotations_test.cc
@@ -370,6 +370,28 @@
IsOkAndHolds(LifetimesAre({{"f", "()"}})));
}
+TEST_F(LifetimeAnnotationsTest, LifetimeElision_PointerAlias) {
+ EXPECT_THAT(GetNamedLifetimeAnnotations(R"_(
+ #pragma clang lifetime_elision
+ using Alias = int *;
+ void f(Alias* alias);
+ )_"),
+ // TODO(b/290574080): Do we want elision to "see into" the type
+ // alias? See bug for details.
+ IsOkAndHolds(LifetimesAre({{"f", "(a, b)"}})));
+}
+
+TEST_F(LifetimeAnnotationsTest, LifetimeElision_FunctionAlias) {
+ EXPECT_THAT(GetNamedLifetimeAnnotations(R"_(
+ #pragma clang lifetime_elision
+ using Alias = void(int*);
+ void f(Alias* alias);
+ )_"),
+ // TODO(b/290574080): Do we want elision to "see into" the type
+ // alias? See bug for details.
+ IsOkAndHolds(LifetimesAre({{"f", "(a)"}})));
+}
+
TEST_F(LifetimeAnnotationsTest, LifetimeElision_FailureTooFewInputLifetimes) {
EXPECT_THAT(GetNamedLifetimeAnnotations(R"(
#pragma clang lifetime_elision
diff --git a/lifetime_annotations/type_lifetimes.cc b/lifetime_annotations/type_lifetimes.cc
index 2ac4e22..47f3363 100644
--- a/lifetime_annotations/type_lifetimes.cc
+++ b/lifetime_annotations/type_lifetimes.cc
@@ -311,7 +311,7 @@
ValueLifetimes ret(type);
- if (const auto* fn = clang::dyn_cast<clang::FunctionProtoType>(type)) {
+ if (const auto* fn = type->getAs<clang::FunctionProtoType>()) {
// TODO(veluca): this will not correctly handle the distinction between
// parameter and return lifetimes.
FunctionLifetimeFactorySingleCallback factory(lifetime_factory);
@@ -474,7 +474,7 @@
assert(pointee_lifetimes_);
return pointee_lifetimes_->DebugString(formatter);
}
- if (clang::isa<clang::FunctionProtoType>(Type())) {
+ if (Type()->getAs<clang::FunctionProtoType>()) {
assert(function_lifetimes_);
std::string fn_lifetimes = function_lifetimes_->DebugString(formatter);
if (fn_lifetimes.empty()) return "";
@@ -536,6 +536,7 @@
const ObjectLifetimes& ValueLifetimes::GetPointeeLifetimes() const {
assert(!PointeeType(type_).isNull());
+ assert(pointee_lifetimes_);
return *pointee_lifetimes_;
}
diff --git a/rs_bindings_from_cc/importer_test.cc b/rs_bindings_from_cc/importer_test.cc
index 88e024a..7896e71 100644
--- a/rs_bindings_from_cc/importer_test.cc
+++ b/rs_bindings_from_cc/importer_test.cc
@@ -863,8 +863,7 @@
Contains(VariantWith<Func>(IdentifierIs("baz")))));
}
-// This test currently results in a crash, see b/290329656.
-TEST(ImporterTest, DISABLED_CrashDueToAssertionInGetPointeeLifetimes) {
+TEST(ImporterTest, CrashRepro_FunctionTypeAlias) {
absl::string_view file = R"cc(
using Callback = void(const int&);
void SetHook(Callback* cb);