Skip to content

Commit 226d732

Browse files
Googlercopybara-github
authored andcommitted
Fix a crash while traversing base classes
After llvm/llvm-project#158109 we started seeing cases that were previously `DependentTemplateSpecializationType` become `TemplateSpecializationType` where the `getAsTemplateDecl` returns nullptr. The documentation had always said that getAsTemplateDecl could be nullptr, but perhaps it was harder to see when diverted to the separate `DependentTemplateSpecializationType` type. PiperOrigin-RevId: 810993821 Change-Id: Ic59d9775617d4ebb12df85381d5b1f072d856dc5
1 parent cc9c103 commit 226d732

File tree

2 files changed

+29
-6
lines changed

2 files changed

+29
-6
lines changed

nullability/type_nullability.cc

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -79,13 +79,16 @@ static const CXXRecordDecl *absl_nullable getSmartPointerBaseClass(
7979
// return the `CXXRecordDecl` of the underlying template -- it's the
8080
// best we can do.
8181
if (BaseClass == nullptr) {
82-
if (const auto *TST =
82+
if (const auto* TST =
8383
Base.getType()->getAs<TemplateSpecializationType>()) {
84-
// If the base class is a template template parameter, we can
85-
// retrieve the template decl, but not the templated decl, so don't
86-
// assert presence during the cast.
87-
BaseClass = dyn_cast_if_present<CXXRecordDecl>(
88-
TST->getTemplateName().getAsTemplateDecl()->getTemplatedDecl());
84+
// If the base class template name is a dependent name, the template
85+
// decl will be null.
86+
if (const auto* TD = TST->getTemplateName().getAsTemplateDecl())
87+
// And, if the base class is a template template parameter, we can
88+
// retrieve the template decl, but not the templated decl, so
89+
// don't assert presence during the cast.
90+
BaseClass =
91+
dyn_cast_if_present<CXXRecordDecl>(TD->getTemplatedDecl());
8992

9093
// We need to be careful here: Once we start looking at underlying
9194
// templates, we may walk into cycles, as a template may derive from

nullability/type_nullability_test.cc

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,26 @@ TEST_F(UnderlyingRawPointerTest, BaseClassIsTemplateTemplateParameter) {
340340
EXPECT_EQ(underlyingRawPointerType(Target->getUnderlyingType()), QualType());
341341
}
342342

343+
TEST_F(UnderlyingRawPointerTest, BaseClassIsDependentOnUnresolvedParameter) {
344+
// This is a crash repro for b/447116132.
345+
TestAST AST(R"cc(
346+
template <typename T>
347+
struct Other {
348+
template <typename U>
349+
struct With {};
350+
};
351+
352+
template <typename Base>
353+
struct Derived : public Other<Base>::template With<Base> {
354+
using Target = Derived;
355+
};
356+
)cc");
357+
358+
const auto* Target = selectFirst<TypeAliasDecl>(
359+
"T", match(typeAliasDecl(hasName("Target")).bind("T"), AST.context()));
360+
EXPECT_EQ(underlyingRawPointerType(Target->getUnderlyingType()), QualType());
361+
}
362+
343363
TEST_F(UnderlyingRawPointerTest, BaseClassIsTemplateInstantation) {
344364
// This is a regression test. We did not recognize `target` as a smart pointer
345365
// type because we did not check the template argument of the smart pointer

0 commit comments

Comments
 (0)