From 19e984ef8f49bc3ccced15621989fa9703b2cd5b Mon Sep 17 00:00:00 2001 From: Aaron Ballman Date: Fri, 14 Oct 2022 08:17:16 -0400 Subject: [PATCH] Properly print unnamed TagDecl objects in diagnostics The diagnostics engine is very smart about being passed a NamedDecl to print as part of a diagnostic; it gets the "right" form of the name, quotes it properly, etc. However, the result of using an unnamed tag declaration was to print '' instead of anything useful. This patch causes us to print the same information we'd have gotten if we had printed the type of the declaration rather than the name of it, as that's the most relevant information we can display. Differential Revision: https://reviews.llvm.org/D134813 --- .../clangd/unittests/FindTargetTests.cpp | 2 +- clang/include/clang/AST/Decl.h | 6 +++- clang/include/clang/AST/DeclCXX.h | 8 +++-- clang/include/clang/AST/DeclTemplate.h | 3 +- clang/lib/AST/ASTDiagnostic.cpp | 2 +- clang/lib/AST/Decl.cpp | 31 ++++++++++++++++--- clang/lib/AST/DeclCXX.cpp | 17 +++++----- clang/lib/AST/DeclPrinter.cpp | 4 +-- clang/lib/AST/DeclTemplate.cpp | 5 +-- clang/lib/AST/NestedNameSpecifier.cpp | 2 +- clang/lib/AST/TemplateName.cpp | 2 +- clang/lib/CodeGen/CodeGenTypes.cpp | 2 +- clang/lib/Sema/SemaTemplateInstantiate.cpp | 6 ++-- .../ast-dump-record-definition-data-json.cpp | 4 +-- clang/test/ExtractAPI/enum.c | 16 +++++----- clang/test/Index/annotate-comments-typedef.m | 2 +- clang/test/Index/c-index-api-loadTU-test.m | 2 +- clang/test/Index/c-index-getCursor-test.m | 4 +-- clang/test/Index/print-type.c | 8 ++--- clang/test/Index/print-type.cpp | 8 ++--- clang/test/Index/targeted-annotation.c | 10 +++--- clang/test/Index/targeted-cursor.c | 2 +- clang/test/Index/usrs.m | 6 ++-- clang/test/Sema/address-packed.c | 8 ++--- clang/test/Sema/attr-flag-enum.c | 2 +- clang/test/SemaCXX/attr-unused.cpp | 2 +- clang/test/SemaCXX/lambda-expressions.cpp | 20 ++++++------ clang/test/SemaCXX/ms-interface.cpp | 2 +- clang/test/SemaObjCXX/arc-0x.mm | 12 +++---- .../Templight/templight-empty-entries-fix.cpp | 16 +++++----- clang/unittests/AST/ASTTraverserTest.cpp | 2 +- llvm/utils/lit/lit/TestRunner.py | 1 + 32 files changed, 125 insertions(+), 92 deletions(-) diff --git a/clang-tools-extra/clangd/unittests/FindTargetTests.cpp b/clang-tools-extra/clangd/unittests/FindTargetTests.cpp index 57838eafd651..336572aede2a 100644 --- a/clang-tools-extra/clangd/unittests/FindTargetTests.cpp +++ b/clang-tools-extra/clangd/unittests/FindTargetTests.cpp @@ -1640,7 +1640,7 @@ TEST_F(FindExplicitReferencesTest, All) { int (*$2^fptr)(int $3^a, int) = nullptr; } )cpp", - "0: targets = {}\n" + "0: targets = {(unnamed)}\n" "1: targets = {x}, decl\n" "2: targets = {fptr}, decl\n" "3: targets = {a}, decl\n"}, diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h index d566564ee7d0..1e05d1e425a2 100644 --- a/clang/include/clang/AST/Decl.h +++ b/clang/include/clang/AST/Decl.h @@ -291,7 +291,9 @@ public: /// Pretty-print the unqualified name of this declaration. Can be overloaded /// by derived classes to provide a more user-friendly name when appropriate. - virtual void printName(raw_ostream &os) const; + virtual void printName(raw_ostream &OS, const PrintingPolicy &Policy) const; + /// Calls printName() with the ASTContext printing policy from the decl. + void printName(raw_ostream &OS) const; /// Get the actual, stored name of the declaration, which may be a special /// name. @@ -3654,6 +3656,8 @@ public: return getExtInfo()->TemplParamLists[i]; } + void printName(raw_ostream &OS, const PrintingPolicy &Policy) const override; + void setTemplateParameterListsInfo(ASTContext &Context, ArrayRef TPLists); diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h index 126d51133ac9..ce83424dd207 100644 --- a/clang/include/clang/AST/DeclCXX.h +++ b/clang/include/clang/AST/DeclCXX.h @@ -4100,7 +4100,7 @@ public: return llvm::makeArrayRef(getTrailingObjects(), NumBindings); } - void printName(raw_ostream &os) const override; + void printName(raw_ostream &OS, const PrintingPolicy &Policy) const override; static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == Decomposition; } @@ -4213,7 +4213,8 @@ private: public: /// Print this UUID in a human-readable format. - void printName(llvm::raw_ostream &OS) const override; + void printName(llvm::raw_ostream &OS, + const PrintingPolicy &Policy) const override; /// Get the decomposed parts of this declaration. Parts getParts() const { return PartVal; } @@ -4266,7 +4267,8 @@ class UnnamedGlobalConstantDecl : public ValueDecl, public: /// Print this in a human-readable format. - void printName(llvm::raw_ostream &OS) const override; + void printName(llvm::raw_ostream &OS, + const PrintingPolicy &Policy) const override; const APValue &getValue() const { return Value; } diff --git a/clang/include/clang/AST/DeclTemplate.h b/clang/include/clang/AST/DeclTemplate.h index 78e99f8335b9..648a3a250a33 100644 --- a/clang/include/clang/AST/DeclTemplate.h +++ b/clang/include/clang/AST/DeclTemplate.h @@ -3343,7 +3343,8 @@ private: public: /// Print this template parameter object in a human-readable format. - void printName(llvm::raw_ostream &OS) const override; + void printName(llvm::raw_ostream &OS, + const PrintingPolicy &Policy) const override; /// Print this object as an equivalent expression. void printAsExpr(llvm::raw_ostream &OS) const; diff --git a/clang/lib/AST/ASTDiagnostic.cpp b/clang/lib/AST/ASTDiagnostic.cpp index 079fc8bd1505..079fd268f4d3 100644 --- a/clang/lib/AST/ASTDiagnostic.cpp +++ b/clang/lib/AST/ASTDiagnostic.cpp @@ -1893,7 +1893,7 @@ class TemplateDiff { TPO->printAsInit(OS, Policy); return; } - VD->printName(OS); + VD->printName(OS, Policy); return; } diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index b326933b1d7d..d1dd93b0a5b6 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -1602,8 +1602,12 @@ Module *Decl::getOwningModuleForLinkage(bool IgnoreLinkage) const { llvm_unreachable("unknown module kind"); } -void NamedDecl::printName(raw_ostream &os) const { - os << Name; +void NamedDecl::printName(raw_ostream &OS, const PrintingPolicy&) const { + OS << Name; +} + +void NamedDecl::printName(raw_ostream &OS) const { + printName(OS, getASTContext().getPrintingPolicy()); } std::string NamedDecl::getQualifiedNameAsString() const { @@ -1621,7 +1625,7 @@ void NamedDecl::printQualifiedName(raw_ostream &OS, const PrintingPolicy &P) const { if (getDeclContext()->isFunctionOrMethod()) { // We do not print '(anonymous)' for function parameters without name. - printName(OS); + printName(OS, P); return; } printNestedNameSpecifier(OS, P); @@ -1632,7 +1636,7 @@ void NamedDecl::printQualifiedName(raw_ostream &OS, // fall back to "(anonymous)". SmallString<64> NameBuffer; llvm::raw_svector_ostream NameOS(NameBuffer); - printName(NameOS); + printName(NameOS, P); if (NameBuffer.empty()) OS << "(anonymous)"; else @@ -1755,7 +1759,7 @@ void NamedDecl::getNameForDiagnostic(raw_ostream &OS, if (Qualified) printQualifiedName(OS, Policy); else - printName(OS); + printName(OS, Policy); } template static bool isRedeclarableImpl(Redeclarable *) { @@ -4470,6 +4474,23 @@ void TagDecl::setQualifierInfo(NestedNameSpecifierLoc QualifierLoc) { } } +void TagDecl::printName(raw_ostream &OS, const PrintingPolicy &Policy) const { + DeclarationName Name = getDeclName(); + // If the name is supposed to have an identifier but does not have one, then + // the tag is anonymous and we should print it differently. + if (Name.isIdentifier() && !Name.getAsIdentifierInfo()) { + // If the caller wanted to print a qualified name, they've already printed + // the scope. And if the caller doesn't want that, the scope information + // is already printed as part of the type. + PrintingPolicy Copy(Policy); + Copy.SuppressScope = true; + getASTContext().getTagDeclType(this).print(OS, Copy); + return; + } + // Otherwise, do the normal printing. + Name.print(OS, Policy); +} + void TagDecl::setTemplateParameterListsInfo( ASTContext &Context, ArrayRef TPLists) { assert(!TPLists.empty()); diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp index 40a7ae80b61a..b92210996fdb 100644 --- a/clang/lib/AST/DeclCXX.cpp +++ b/clang/lib/AST/DeclCXX.cpp @@ -3269,16 +3269,17 @@ DecompositionDecl *DecompositionDecl::CreateDeserialized(ASTContext &C, return Result; } -void DecompositionDecl::printName(llvm::raw_ostream &os) const { - os << '['; +void DecompositionDecl::printName(llvm::raw_ostream &OS, + const PrintingPolicy &Policy) const { + OS << '['; bool Comma = false; for (const auto *B : bindings()) { if (Comma) - os << ", "; - B->printName(os); + OS << ", "; + B->printName(OS, Policy); Comma = true; } - os << ']'; + OS << ']'; } void MSPropertyDecl::anchor() {} @@ -3314,7 +3315,8 @@ MSGuidDecl *MSGuidDecl::CreateDeserialized(ASTContext &C, unsigned ID) { return new (C, ID) MSGuidDecl(nullptr, QualType(), Parts()); } -void MSGuidDecl::printName(llvm::raw_ostream &OS) const { +void MSGuidDecl::printName(llvm::raw_ostream &OS, + const PrintingPolicy &) const { OS << llvm::format("GUID{%08" PRIx32 "-%04" PRIx16 "-%04" PRIx16 "-", PartVal.Part1, PartVal.Part2, PartVal.Part3); unsigned I = 0; @@ -3423,7 +3425,8 @@ UnnamedGlobalConstantDecl::CreateDeserialized(ASTContext &C, unsigned ID) { UnnamedGlobalConstantDecl(C, nullptr, QualType(), APValue()); } -void UnnamedGlobalConstantDecl::printName(llvm::raw_ostream &OS) const { +void UnnamedGlobalConstantDecl::printName(llvm::raw_ostream &OS, + const PrintingPolicy &) const { OS << "unnamed-global-constant"; } diff --git a/clang/lib/AST/DeclPrinter.cpp b/clang/lib/AST/DeclPrinter.cpp index ad90e536c0de..0071f9b00137 100644 --- a/clang/lib/AST/DeclPrinter.cpp +++ b/clang/lib/AST/DeclPrinter.cpp @@ -1711,7 +1711,7 @@ void DeclPrinter::VisitOMPDeclareReductionDecl(OMPDeclareReductionDecl *D) { Out << OpName; } else { assert(D->getDeclName().isIdentifier()); - D->printName(Out); + D->printName(Out, Policy); } Out << " : "; D->getType().print(Out, Policy); @@ -1741,7 +1741,7 @@ void DeclPrinter::VisitOMPDeclareReductionDecl(OMPDeclareReductionDecl *D) { void DeclPrinter::VisitOMPDeclareMapperDecl(OMPDeclareMapperDecl *D) { if (!D->isInvalidDecl()) { Out << "#pragma omp declare mapper ("; - D->printName(Out); + D->printName(Out, Policy); Out << " : "; D->getType().print(Out, Policy); Out << " "; diff --git a/clang/lib/AST/DeclTemplate.cpp b/clang/lib/AST/DeclTemplate.cpp index 7159a87a6927..5fa8229cba96 100644 --- a/clang/lib/AST/DeclTemplate.cpp +++ b/clang/lib/AST/DeclTemplate.cpp @@ -1532,9 +1532,10 @@ TemplateParamObjectDecl::CreateDeserialized(ASTContext &C, unsigned ID) { return TPOD; } -void TemplateParamObjectDecl::printName(llvm::raw_ostream &OS) const { +void TemplateParamObjectDecl::printName(llvm::raw_ostream &OS, + const PrintingPolicy &Policy) const { OS << "