Skip to content

Commit 2caf4c1

Browse files
[AST] Fix an assertion failure in TypeName::getFullyQualifiedName (#159312)
This popped up during our internal integrates of upstream changes. It started happening after ba9d1c4, which started using `TemplateSpecializationType` in this place and the code was not prepared to handle it.
1 parent 6bbf734 commit 2caf4c1

File tree

3 files changed

+63
-3
lines changed

3 files changed

+63
-3
lines changed

clang/lib/AST/QualTypeNames.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,9 +58,9 @@ static bool getFullyQualifiedTemplateName(const ASTContext &Ctx,
5858
NestedNameSpecifier NNS = std::nullopt;
5959

6060
TemplateDecl *ArgTDecl = TName.getAsTemplateDecl();
61-
// ArgTDecl won't be NULL because we asserted that this isn't a
62-
// dependent context very early in the call chain.
63-
assert(ArgTDecl != nullptr);
61+
if (!ArgTDecl) // ArgTDecl can be null in dependent contexts.
62+
return false;
63+
6464
QualifiedTemplateName *QTName = TName.getAsQualifiedTemplateName();
6565

6666
if (QTName &&
@@ -252,6 +252,9 @@ createNestedNameSpecifierForScopeOf(const ASTContext &Ctx, const Decl *Decl,
252252
bool WithGlobalNsPrefix) {
253253
assert(Decl);
254254

255+
// Some declaration cannot be qualified.
256+
if (Decl->isTemplateParameter())
257+
return std::nullopt;
255258
const DeclContext *DC = Decl->getDeclContext()->getRedeclContext();
256259
const auto *Outer = dyn_cast<NamedDecl>(DC);
257260
const auto *OuterNS = dyn_cast<NamespaceDecl>(DC);

clang/unittests/AST/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ add_clang_unittest(ASTTests
2626
ExternalASTSourceTest.cpp
2727
NamedDeclPrinterTest.cpp
2828
ProfilingTest.cpp
29+
QualTypeNamesTest.cpp
2930
RandstructTest.cpp
3031
RawCommentForDeclTest.cpp
3132
RecursiveASTVisitorTest.cpp
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
//===- unittests/AST/QualTypeNamesTest.cpp --------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// This file contains tests for helpers from QualTypeNames.h.
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#include "clang/AST/QualTypeNames.h"
14+
#include "ASTPrint.h"
15+
#include "clang/AST/ASTContext.h"
16+
#include "clang/AST/Decl.h"
17+
#include "clang/AST/DeclarationName.h"
18+
#include "clang/AST/TypeBase.h"
19+
#include "clang/Tooling/Tooling.h"
20+
#include "llvm/ADT/StringRef.h"
21+
#include "llvm/Support/Casting.h"
22+
#include "gtest/gtest.h"
23+
24+
namespace clang {
25+
namespace {
26+
27+
TEST(QualTypeNamesTest, TemplateParameters) {
28+
constexpr llvm::StringLiteral Code = R"cpp(
29+
template <template<class> class T> struct Foo {
30+
using type_of_interest = T<int>;
31+
};
32+
)cpp";
33+
auto AST = tooling::buildASTFromCode(Code);
34+
ASSERT_NE(AST, nullptr);
35+
36+
auto &Ctx = AST->getASTContext();
37+
auto FooLR = Ctx.getTranslationUnitDecl()->lookup(
38+
DeclarationName(AST->getPreprocessor().getIdentifierInfo("Foo")));
39+
ASSERT_TRUE(FooLR.isSingleResult());
40+
41+
auto TypeLR =
42+
llvm::cast<ClassTemplateDecl>(FooLR.front())
43+
->getTemplatedDecl()
44+
->lookup(DeclarationName(
45+
AST->getPreprocessor().getIdentifierInfo("type_of_interest")));
46+
ASSERT_TRUE(TypeLR.isSingleResult());
47+
48+
auto Type = cast<TypeAliasDecl>(TypeLR.front())->getUnderlyingType();
49+
ASSERT_TRUE(isa<TemplateSpecializationType>(Type));
50+
51+
EXPECT_EQ(TypeName::getFullyQualifiedName(Type, Ctx, Ctx.getPrintingPolicy()),
52+
"T<int>");
53+
}
54+
55+
} // namespace
56+
} // namespace clang

0 commit comments

Comments
 (0)