[clang] [AST] Fix an assertion failure in TypeName::getFullyQualifiedName (PR #159312)

via cfe-commits cfe-commits at lists.llvm.org
Wed Sep 17 03:21:21 PDT 2025


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: Ilya Biryukov (ilya-biryukov)

<details>
<summary>Changes</summary>

This popped up during our internal integrates of upstream changes. It started happening after ba9d1c41c41d568a798e0a8c38a89d294647c28d, which started using `TemplateSpecializationType` in this place and the code was not prepared to handle it.

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


3 Files Affected:

- (modified) clang/lib/AST/QualTypeNames.cpp (+6-3) 
- (modified) clang/unittests/AST/CMakeLists.txt (+1) 
- (added) clang/unittests/AST/QualTypeNamesTest.cpp (+55) 


``````````diff
diff --git a/clang/lib/AST/QualTypeNames.cpp b/clang/lib/AST/QualTypeNames.cpp
index ee7fec3372fcf..b0e9a600f41a3 100644
--- a/clang/lib/AST/QualTypeNames.cpp
+++ b/clang/lib/AST/QualTypeNames.cpp
@@ -58,9 +58,9 @@ static bool getFullyQualifiedTemplateName(const ASTContext &Ctx,
   NestedNameSpecifier NNS = std::nullopt;
 
   TemplateDecl *ArgTDecl = TName.getAsTemplateDecl();
-  // ArgTDecl won't be NULL because we asserted that this isn't a
-  // dependent context very early in the call chain.
-  assert(ArgTDecl != nullptr);
+  if (!ArgTDecl)  // ArgTDecl can be null in dependent contexts.
+    return false;
+
   QualifiedTemplateName *QTName = TName.getAsQualifiedTemplateName();
 
   if (QTName &&
@@ -252,6 +252,9 @@ createNestedNameSpecifierForScopeOf(const ASTContext &Ctx, const Decl *Decl,
                                     bool WithGlobalNsPrefix) {
   assert(Decl);
 
+  // Some declaration cannot be qualified.
+  if (Decl->isTemplateParameter())
+    return std::nullopt;
   const DeclContext *DC = Decl->getDeclContext()->getRedeclContext();
   const auto *Outer = dyn_cast<NamedDecl>(DC);
   const auto *OuterNS = dyn_cast<NamespaceDecl>(DC);
diff --git a/clang/unittests/AST/CMakeLists.txt b/clang/unittests/AST/CMakeLists.txt
index f27d34e8a0719..3a12a4a06a33a 100644
--- a/clang/unittests/AST/CMakeLists.txt
+++ b/clang/unittests/AST/CMakeLists.txt
@@ -26,6 +26,7 @@ add_clang_unittest(ASTTests
   ExternalASTSourceTest.cpp
   NamedDeclPrinterTest.cpp
   ProfilingTest.cpp
+  QualTypeNamesTest.cpp
   RandstructTest.cpp
   RawCommentForDeclTest.cpp
   RecursiveASTVisitorTest.cpp
diff --git a/clang/unittests/AST/QualTypeNamesTest.cpp b/clang/unittests/AST/QualTypeNamesTest.cpp
new file mode 100644
index 0000000000000..71e4c87cedc72
--- /dev/null
+++ b/clang/unittests/AST/QualTypeNamesTest.cpp
@@ -0,0 +1,55 @@
+//===- unittests/AST/QualTypeNamesTest.cpp --------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains tests for helpers from QualTypeNames.h.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/QualTypeNames.h"
+#include "ASTPrint.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclarationName.h"
+#include "clang/AST/TypeBase.h"
+#include "clang/Tooling/Tooling.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Casting.h"
+#include "gtest/gtest.h"
+
+namespace clang {
+namespace {
+
+TEST(QualTypeNamesTest, TemplateParameters) {
+  constexpr llvm::StringLiteral Code = R"cpp(
+    template <template<class> class T> struct Foo {
+      using type_of_interest = T<int>;
+    };
+  )cpp";
+  auto AST = tooling::buildASTFromCode(Code);
+  ASSERT_NE(AST, nullptr);
+
+  auto &Ctx = AST->getASTContext();
+  auto FooLR = Ctx.getTranslationUnitDecl()->lookup(
+      DeclarationName(AST->getPreprocessor().getIdentifierInfo("Foo")));
+  ASSERT_TRUE(FooLR.isSingleResult());
+
+  auto TypeLR =
+      llvm::cast<ClassTemplateDecl>(FooLR.front())
+          ->getTemplatedDecl()
+          ->lookup(DeclarationName(
+              AST->getPreprocessor().getIdentifierInfo("type_of_interest")));
+  ASSERT_TRUE(TypeLR.isSingleResult());
+
+  auto Type = cast<TypeAliasDecl>(TypeLR.front())->getUnderlyingType();
+  ASSERT_TRUE(isa<TemplateSpecializationType>(Type));
+
+  EXPECT_EQ(TypeName::getFullyQualifiedName(Type, Ctx, Ctx.getPrintingPolicy()), "T<int>");
+}
+
+} // namespace
+} // namespace clang

``````````

</details>


https://github.com/llvm/llvm-project/pull/159312


More information about the cfe-commits mailing list