sammccall updated this revision to Diff 398991. sammccall added a comment. Revert hover changes, only use for code complete
Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D116387/new/ https://reviews.llvm.org/D116387 Files: clang-tools-extra/clangd/Hover.cpp clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp clang/include/clang/AST/PrettyPrinter.h clang/include/clang/Basic/IdentifierTable.h clang/lib/AST/DeclPrinter.cpp clang/lib/AST/StmtPrinter.cpp clang/lib/AST/TemplateName.cpp clang/lib/AST/TypePrinter.cpp clang/lib/Basic/IdentifierTable.cpp clang/lib/Sema/SemaCodeComplete.cpp clang/test/CodeCompletion/deuglify.cpp clang/unittests/AST/DeclPrinterTest.cpp clang/unittests/AST/StmtPrinterTest.cpp clang/unittests/AST/TypePrinterTest.cpp
Index: clang/unittests/AST/TypePrinterTest.cpp =================================================================== --- clang/unittests/AST/TypePrinterTest.cpp +++ clang/unittests/AST/TypePrinterTest.cpp @@ -62,4 +62,21 @@ ASSERT_TRUE(PrintedTypeMatches( Code, {}, Matcher, "const N::Type<T> &", [](PrintingPolicy &Policy) { Policy.FullyQualifiedName = true; })); -} \ No newline at end of file +} + +TEST(TypePrinter, ParamsUglified) { + llvm::StringLiteral Code = R"cpp( + template <typename _Tp, template <typename> class __f> + const __f<_Tp&> *A = nullptr; + )cpp"; + auto Clean = [](PrintingPolicy &Policy) { + Policy.CleanUglifiedParameters = true; + }; + + ASSERT_TRUE(PrintedTypeMatches(Code, {}, + varDecl(hasType(qualType().bind("id"))), + "const __f<_Tp &> *", nullptr)); + ASSERT_TRUE(PrintedTypeMatches(Code, {}, + varDecl(hasType(qualType().bind("id"))), + "const f<Tp &> *", Clean)); +} Index: clang/unittests/AST/StmtPrinterTest.cpp =================================================================== --- clang/unittests/AST/StmtPrinterTest.cpp +++ clang/unittests/AST/StmtPrinterTest.cpp @@ -263,3 +263,22 @@ [](PrintingPolicy &PP) { PP.TerseOutput = true; })); } + +TEST(StmtPrinter, ParamsUglified) { + llvm::StringLiteral Code = R"cpp( + template <typename _T, int _I, template <typename> class _C> + auto foo(int __j) { + return typename _C<_T>::_F(_I, __j); + } + )cpp"; + auto Clean = [](PrintingPolicy &Policy) { + Policy.CleanUglifiedParameters = true; + }; + + ASSERT_TRUE(PrintedStmtCXXMatches(StdVer::CXX14, Code, + returnStmt().bind("id"), + "return typename _C<_T>::_F(_I, __j);\n")); + ASSERT_TRUE( + PrintedStmtCXXMatches(StdVer::CXX14, Code, returnStmt().bind("id"), + "return typename C<T>::_F(I, j);\n", Clean)); +} Index: clang/unittests/AST/DeclPrinterTest.cpp =================================================================== --- clang/unittests/AST/DeclPrinterTest.cpp +++ clang/unittests/AST/DeclPrinterTest.cpp @@ -1336,6 +1336,41 @@ ASSERT_TRUE(PrintedDeclCXX11Matches(Code, "NT2", "int NT2 = 5")); } +TEST(DeclPrinter, TestFunctionParamUglified) { + llvm::StringLiteral Code = R"cpp( + class __c; + void _A(__c *__param); + )cpp"; + auto Clean = [](PrintingPolicy &Policy) { + Policy.CleanUglifiedParameters = true; + }; + + ASSERT_TRUE(PrintedDeclCXX17Matches(Code, namedDecl(hasName("_A")).bind("id"), + "void _A(__c *__param)")); + ASSERT_TRUE(PrintedDeclCXX17Matches(Code, namedDecl(hasName("_A")).bind("id"), + "void _A(__c *param)", Clean)); +} + +TEST(DeclPrinter, TestTemplateParamUglified) { + llvm::StringLiteral Code = R"cpp( + template <typename _Tp, int __n, template <typename> class _Container> + struct _A{}; + )cpp"; + auto Clean = [](PrintingPolicy &Policy) { + Policy.CleanUglifiedParameters = true; + }; + + ASSERT_TRUE(PrintedDeclCXX17Matches( + Code, classTemplateDecl(hasName("_A")).bind("id"), + "template <typename _Tp, int __n, template <typename> class _Container> " + "struct _A {}")); + ASSERT_TRUE(PrintedDeclCXX17Matches( + Code, classTemplateDecl(hasName("_A")).bind("id"), + "template <typename Tp, int n, template <typename> class Container> " + "struct _A {}", + Clean)); +} + TEST(DeclPrinter, TestStaticAssert1) { ASSERT_TRUE(PrintedDeclCXX17Matches("static_assert(true);", staticAssertDecl().bind("id"), Index: clang/test/CodeCompletion/deuglify.cpp =================================================================== --- /dev/null +++ clang/test/CodeCompletion/deuglify.cpp @@ -0,0 +1,25 @@ +// Fake standard library with uglified names. +// Parameters (including template params) get ugliness stripped. +namespace std { + +template <typename _Tp> +class __vector_base {}; + +template <typename _Tp> +class vector : private __vector_base<_Tp> { +public: + _Tp &at(unsigned __index) const; + int __stays_ugly(); +}; + +} // namespace std + +int x = std::vector<int>{}.at(42); +// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:17:14 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s +// CHECK-CC1: COMPLETION: __vector_base : __vector_base<<#typename Tp#>> +// CHECK-CC1: COMPLETION: vector : vector<<#typename Tp#>> +// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:17:28 %s -o - | FileCheck -check-prefix=CHECK-CC2 %s +// CHECK-CC2: COMPLETION: __stays_ugly : [#int#]__stays_ugly() +// CHECK-CC2: COMPLETION: at : [#int &#]at(<#unsigned int index#>)[# const#] +// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:17:31 %s -o - | FileCheck -check-prefix=CHECK-CC3 %s +// CHECK-CC3: OVERLOAD: [#int &#]at(<#unsigned int index#>) Index: clang/lib/Sema/SemaCodeComplete.cpp =================================================================== --- clang/lib/Sema/SemaCodeComplete.cpp +++ clang/lib/Sema/SemaCodeComplete.cpp @@ -1896,6 +1896,7 @@ Policy.SuppressStrongLifetime = true; Policy.SuppressUnwrittenScope = true; Policy.SuppressScope = true; + Policy.CleanUglifiedParameters = true; return Policy; } @@ -2837,7 +2838,7 @@ std::string Result; if (Param->getIdentifier() && !ObjCMethodParam && !SuppressName) - Result = std::string(Param->getIdentifier()->getName()); + Result = std::string(Param->getIdentifier()->deuglifiedName()); QualType Type = Param->getType(); if (ObjCSubsts) @@ -2847,7 +2848,7 @@ Result = "(" + formatObjCParamQualifiers(ObjCQual, Type); Result += Type.getAsString(Policy) + ")"; if (Param->getIdentifier() && !SuppressName) - Result += Param->getIdentifier()->getName(); + Result += Param->getIdentifier()->deuglifiedName(); } else { Type.getAsStringInternal(Result, Policy); } @@ -2875,7 +2876,7 @@ // for the block; just use the parameter type as a placeholder. std::string Result; if (!ObjCMethodParam && Param->getIdentifier()) - Result = std::string(Param->getIdentifier()->getName()); + Result = std::string(Param->getIdentifier()->deuglifiedName()); QualType Type = Param->getType().getUnqualifiedType(); @@ -2887,7 +2888,7 @@ if (Result.back() != ')') Result += " "; if (Param->getIdentifier()) - Result += Param->getIdentifier()->getName(); + Result += Param->getIdentifier()->deuglifiedName(); } else { Type.getAsStringInternal(Result, Policy); } @@ -3082,14 +3083,14 @@ if (TTP->getIdentifier()) { PlaceholderStr += ' '; - PlaceholderStr += TTP->getIdentifier()->getName(); + PlaceholderStr += TTP->getIdentifier()->deuglifiedName(); } HasDefaultArg = TTP->hasDefaultArgument(); } else if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(*P)) { if (NTTP->getIdentifier()) - PlaceholderStr = std::string(NTTP->getIdentifier()->getName()); + PlaceholderStr = std::string(NTTP->getIdentifier()->deuglifiedName()); NTTP->getType().getAsStringInternal(PlaceholderStr, Policy); HasDefaultArg = NTTP->hasDefaultArgument(); } else { @@ -3101,7 +3102,7 @@ PlaceholderStr = "template<...> class"; if (TTP->getIdentifier()) { PlaceholderStr += ' '; - PlaceholderStr += TTP->getIdentifier()->getName(); + PlaceholderStr += TTP->getIdentifier()->deuglifiedName(); } HasDefaultArg = TTP->hasDefaultArgument(); Index: clang/lib/Basic/IdentifierTable.cpp =================================================================== --- clang/lib/Basic/IdentifierTable.cpp +++ clang/lib/Basic/IdentifierTable.cpp @@ -309,6 +309,14 @@ return ReservedIdentifierStatus::NotReserved; } +StringRef IdentifierInfo::deuglifiedName() const { + StringRef Name = getName(); + if (Name.size() >= 2 && Name.front() == '_' && + (Name[1] == '_' || (Name[1] >= 'A' && Name[1] <= 'Z'))) + return Name.ltrim('_'); + return Name; +} + tok::PPKeywordKind IdentifierInfo::getPPKeywordID() const { // We use a perfect hash function here involving the length of the keyword, // the first and third character. For preprocessor ID's there are no Index: clang/lib/AST/TypePrinter.cpp =================================================================== --- clang/lib/AST/TypePrinter.cpp +++ clang/lib/AST/TypePrinter.cpp @@ -1418,7 +1418,8 @@ } OS << "auto"; } else if (IdentifierInfo *Id = T->getIdentifier()) - OS << Id->getName(); + OS << (Policy.CleanUglifiedParameters ? Id->deuglifiedName() + : Id->getName()); else OS << "type-parameter-" << T->getDepth() << '-' << T->getIndex(); Index: clang/lib/AST/TemplateName.cpp =================================================================== --- clang/lib/AST/TemplateName.cpp +++ clang/lib/AST/TemplateName.cpp @@ -223,8 +223,12 @@ void TemplateName::print(raw_ostream &OS, const PrintingPolicy &Policy, Qualified Qual) const { if (TemplateDecl *Template = Storage.dyn_cast<TemplateDecl *>()) - if (Qual == Qualified::Fully && - getDependence() != TemplateNameDependenceScope::DependentInstantiation) + if (Policy.CleanUglifiedParameters && + isa<TemplateTemplateParmDecl>(Template) && Template->getIdentifier()) + OS << Template->getIdentifier()->deuglifiedName(); + else if (Qual == Qualified::Fully && + getDependence() != + TemplateNameDependenceScope::DependentInstantiation) Template->printQualifiedName(OS, Policy); else OS << *Template; Index: clang/lib/AST/StmtPrinter.cpp =================================================================== --- clang/lib/AST/StmtPrinter.cpp +++ clang/lib/AST/StmtPrinter.cpp @@ -1030,7 +1030,12 @@ Qualifier->print(OS, Policy); if (Node->hasTemplateKeyword()) OS << "template "; - OS << Node->getNameInfo(); + if (Policy.CleanUglifiedParameters && + isa<ParmVarDecl, NonTypeTemplateParmDecl>(Node->getDecl()) && + Node->getDecl()->getIdentifier()) + OS << Node->getDecl()->getIdentifier()->deuglifiedName(); + else + Node->getNameInfo().printName(OS, Policy); if (Node->hasExplicitTemplateArgs()) { const TemplateParameterList *TPL = nullptr; if (!Node->hadMultipleCandidates()) @@ -2069,7 +2074,10 @@ } else { NeedComma = true; } - std::string ParamStr = P->getNameAsString(); + std::string ParamStr = + (Policy.CleanUglifiedParameters && P->getIdentifier()) + ? P->getIdentifier()->deuglifiedName().str() + : P->getNameAsString(); P->getOriginalType().print(OS, Policy, ParamStr); } if (Method->isVariadic()) { Index: clang/lib/AST/DeclPrinter.cpp =================================================================== --- clang/lib/AST/DeclPrinter.cpp +++ clang/lib/AST/DeclPrinter.cpp @@ -885,7 +885,10 @@ } } - printDeclType(T, D->getName()); + printDeclType(T, (isa<ParmVarDecl>(D) && Policy.CleanUglifiedParameters && + D->getIdentifier()) + ? D->getIdentifier()->deuglifiedName() + : D->getName()); Expr *Init = D->getInit(); if (!Policy.SuppressInitializers && Init) { bool ImplicitInit = false; @@ -1131,8 +1134,13 @@ else if (TTP->getDeclName()) Out << ' '; - if (TTP->getDeclName()) - Out << TTP->getDeclName(); + if (TTP->getDeclName()) { + if (Policy.CleanUglifiedParameters && isa<TemplateTemplateParmDecl>(D) && + TTP->getIdentifier()) + Out << TTP->getIdentifier()->deuglifiedName(); + else + Out << TTP->getDeclName(); + } } else if (auto *TD = D->getTemplatedDecl()) Visit(TD); else if (const auto *Concept = dyn_cast<ConceptDecl>(D)) { @@ -1742,8 +1750,12 @@ else if (TTP->getDeclName()) Out << ' '; - if (TTP->getDeclName()) - Out << TTP->getDeclName(); + if (TTP->getDeclName()) { + if (Policy.CleanUglifiedParameters && TTP->getIdentifier()) + Out << TTP->getIdentifier()->deuglifiedName(); + else + Out << TTP->getDeclName(); + } if (TTP->hasDefaultArgument()) { Out << " = "; @@ -1755,7 +1767,8 @@ const NonTypeTemplateParmDecl *NTTP) { StringRef Name; if (IdentifierInfo *II = NTTP->getIdentifier()) - Name = II->getName(); + Name = + Policy.CleanUglifiedParameters ? II->deuglifiedName() : II->getName(); printDeclType(NTTP->getType(), Name, NTTP->isParameterPack()); if (NTTP->hasDefaultArgument()) { Index: clang/include/clang/Basic/IdentifierTable.h =================================================================== --- clang/include/clang/Basic/IdentifierTable.h +++ clang/include/clang/Basic/IdentifierTable.h @@ -458,6 +458,10 @@ /// 7.1.3, C++ [lib.global.names]). ReservedIdentifierStatus isReserved(const LangOptions &LangOpts) const; + /// If the identifier is an "uglified" reserved name, return a cleaned form. + /// e.g. _Foo => Foo. Otherwise, just returns the name. + StringRef deuglifiedName() const; + /// Provide less than operator for lexicographical sorting. bool operator<(const IdentifierInfo &RHS) const { return getName() < RHS.getName(); Index: clang/include/clang/AST/PrettyPrinter.h =================================================================== --- clang/include/clang/AST/PrettyPrinter.h +++ clang/include/clang/AST/PrettyPrinter.h @@ -73,7 +73,8 @@ MSVCFormatting(false), ConstantsAsWritten(false), SuppressImplicitBase(false), FullyQualifiedName(false), PrintCanonicalTypes(false), PrintInjectedClassNameWithArguments(true), - UsePreferredNames(true), AlwaysIncludeTypeForTemplateArgument(false) {} + UsePreferredNames(true), AlwaysIncludeTypeForTemplateArgument(false), + CleanUglifiedParameters(false) {} /// Adjust this printing policy for cases where it's known that we're /// printing C++ code (for instance, if AST dumping reaches a C++-only @@ -280,6 +281,11 @@ /// parameters. unsigned AlwaysIncludeTypeForTemplateArgument : 1; + /// Whether to strip underscores when printing reserved parameter names. + /// e.g. std::vector<class _Tp> becomes std::vector<class Tp>. + /// This only affects parameter names, and so describes a compatible API. + unsigned CleanUglifiedParameters : 1; + /// Callbacks to use to allow the behavior of printing to be customized. const PrintingCallbacks *Callbacks = nullptr; }; Index: clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp =================================================================== --- clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp +++ clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp @@ -1457,8 +1457,8 @@ namespace std { class string {}; // Move overloads have special handling. - template <typename T> T&& move(T&&); - template <typename I, typename O> O move(I, I, O); + template <typename _T> T&& move(_T&& __value); + template <typename _I, typename _O> _O move(_I, _I, _O); } )cpp", /*Main=*/""); @@ -1468,7 +1468,8 @@ QName("std"), AllOf(QName("std::string"), DeclURI(TestHeaderURI), IncludeHeader("<string>")), - AllOf(Labeled("move(T &&)"), IncludeHeader("<utility>")), + // Parameter names are demangled. + AllOf(Labeled("move(T &&value)"), IncludeHeader("<utility>")), AllOf(Labeled("move(I, I, O)"), IncludeHeader("<algorithm>")))); } Index: clang-tools-extra/clangd/Hover.cpp =================================================================== --- clang-tools-extra/clangd/Hover.cpp +++ clang-tools-extra/clangd/Hover.cpp @@ -62,13 +62,14 @@ Base.PolishForDeclaration = true; Base.ConstantsAsWritten = true; Base.SuppressTemplateArgsInCXXConstructors = true; + Base.CleanUglifiedParameters = true; return Base; } /// Given a declaration \p D, return a human-readable string representing the /// local scope in which it is declared, i.e. class(es) and method name. Returns /// an empty string if it is not local. -std::string getLocalScope(const Decl *D) { +std::string getLocalScope(const Decl *D, const PrintingPolicy &PP) { std::vector<std::string> Scopes; const DeclContext *DC = D->getDeclContext(); @@ -80,9 +81,9 @@ if (const ObjCContainerDecl *CD = dyn_cast<ObjCContainerDecl>(DC)) return printObjCContainer(*CD); - auto GetName = [](const TypeDecl *D) { + auto GetName = [&](const TypeDecl *D) { if (!D->getDeclName().isEmpty()) { - PrintingPolicy Policy = D->getASTContext().getPrintingPolicy(); + PrintingPolicy Policy = PP; Policy.SuppressScope = true; return declaredType(D).getAsString(Policy); } @@ -224,8 +225,8 @@ if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(Param)) { P.Type = printType(TTP); - if (!TTP->getName().empty()) - P.Name = TTP->getNameAsString(); + if (IdentifierInfo *II = TTP->getIdentifier()) + P.Name = II->deuglifiedName().str(); if (TTP->hasDefaultArgument()) P.Default = TTP->getDefaultArgument().getAsString(PP); @@ -233,7 +234,7 @@ P.Type = printType(NTTP, PP); if (IdentifierInfo *II = NTTP->getIdentifier()) - P.Name = II->getName().str(); + P.Name = II->deuglifiedName().str(); if (NTTP->hasDefaultArgument()) { P.Default.emplace(); @@ -243,8 +244,8 @@ } else if (const auto *TTPD = dyn_cast<TemplateTemplateParmDecl>(Param)) { P.Type = printType(TTPD, PP); - if (!TTPD->getName().empty()) - P.Name = TTPD->getNameAsString(); + if (IdentifierInfo *II = TTPD->getIdentifier()) + P.Name = II->deuglifiedName().str(); if (TTPD->hasDefaultArgument()) { P.Default.emplace(); @@ -347,8 +348,8 @@ const PrintingPolicy &PP) { HoverInfo::Param Out; Out.Type = printType(PVD->getType(), PVD->getASTContext(), PP); - if (!PVD->getName().empty()) - Out.Name = PVD->getNameAsString(); + if (const IdentifierInfo *II = PVD->getIdentifier()) + Out.Name = II->deuglifiedName().str(); if (const Expr *DefArg = getDefaultArg(PVD)) { Out.Default.emplace(); llvm::raw_string_ostream OS(*Out.Default); @@ -576,7 +577,7 @@ HI.NamespaceScope = getNamespaceScope(D); if (!HI.NamespaceScope->empty()) HI.NamespaceScope->append("::"); - HI.LocalScope = getLocalScope(D); + HI.LocalScope = getLocalScope(D, PP); if (!HI.LocalScope.empty()) HI.LocalScope.append("::");
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits