diff --git a/clang/lib/AST/QualTypeNames.cpp b/clang/lib/AST/QualTypeNames.cpp index d8ab1092d3ea..5c151254c36e 100644 --- a/clang/lib/AST/QualTypeNames.cpp +++ b/clang/lib/AST/QualTypeNames.cpp @@ -10,6 +10,7 @@ #include "clang/AST/DeclTemplate.h" #include "clang/AST/DeclarationName.h" #include "clang/AST/Mangle.h" +#include "clang/AST/Type.h" namespace clang { @@ -416,6 +417,18 @@ QualType getFullyQualifiedType(QualType QT, const ASTContext &Ctx, return QT; } + // Handle types with attributes such as `unique_ptr _Nonnull`. + if (auto *AT = dyn_cast(QT.getTypePtr())) { + QualType NewModified = + getFullyQualifiedType(AT->getModifiedType(), Ctx, WithGlobalNsPrefix); + QualType NewEquivalent = + getFullyQualifiedType(AT->getEquivalentType(), Ctx, WithGlobalNsPrefix); + Qualifiers Qualifiers = QT.getLocalQualifiers(); + return Ctx.getQualifiedType( + Ctx.getAttributedType(AT->getAttrKind(), NewModified, NewEquivalent), + Qualifiers); + } + // Remove the part of the type related to the type being a template // parameter (we won't report it as part of the 'type name' and it // is actually make the code below to be more complex (to handle diff --git a/clang/unittests/Tooling/QualTypeNamesTest.cpp b/clang/unittests/Tooling/QualTypeNamesTest.cpp index 5ded64d4fcc8..dc81f0188b4f 100644 --- a/clang/unittests/Tooling/QualTypeNamesTest.cpp +++ b/clang/unittests/Tooling/QualTypeNamesTest.cpp @@ -297,4 +297,31 @@ TEST(QualTypeNameTest, ConstUsing) { using ::A::S; void foo(const S& param1, const S param2);)"); } + +TEST(QualTypeNameTest, NullableAttributesWithGlobalNs) { + TypeNameVisitor Visitor; + Visitor.WithGlobalNsPrefix = true; + Visitor.ExpectedQualTypeNames["param1"] = "::std::unique_ptr _Nullable"; + Visitor.ExpectedQualTypeNames["param2"] = "::std::unique_ptr _Nonnull"; + Visitor.ExpectedQualTypeNames["param3"] = + "::std::unique_ptr< ::std::unique_ptr _Nullable> _Nonnull"; + Visitor.ExpectedQualTypeNames["param4"] = + "::std::unique_ptr _Nullable const *"; + Visitor.ExpectedQualTypeNames["param5"] = + "::std::unique_ptr _Nullable const *"; + Visitor.ExpectedQualTypeNames["param6"] = + "::std::unique_ptr _Nullable const *"; + Visitor.runOver(R"(namespace std { + template class unique_ptr {}; + } + void foo( + std::unique_ptr _Nullable param1, + _Nonnull std::unique_ptr param2, + std::unique_ptr _Nullable> _Nonnull param3, + const std::unique_ptr _Nullable *param4, + _Nullable std::unique_ptr const *param5, + std::unique_ptr _Nullable const *param6 + ); + )"); +} } // end anonymous namespace