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/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 ++++----- .../test/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 57838ea..336572a 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 d566564..1e05d1e 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 126d511..ce83424 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 78e99f8..648a3a2 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 079fc8b..079fd26 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 b326933..d1dd93b 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 40a7ae8..b922109 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 ad90e53..0071f9b 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 7159a87..5fa8229 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 << "