diff --git a/clang-tools-extra/clangd/Hover.h b/clang-tools-extra/clangd/Hover.h --- a/clang-tools-extra/clangd/Hover.h +++ b/clang-tools-extra/clangd/Hover.h @@ -22,15 +22,23 @@ /// embedding clients can use the structured information to provide their own /// UI. struct HoverInfo { + /// Contains pretty-printed type and desugared type + struct PrintedType { + /// Pretty-printed type + std::string Type; + /// Desugared type + Optional AKA; + }; + /// Represents parameters of a function, a template or a macro. /// For example: /// - void foo(ParamType Name = DefaultValue) /// - #define FOO(Name) /// - template class Foo {}; struct Param { - /// The pretty-printed parameter type, e.g. "int", or "typename" (in + /// The printable parameter type, e.g. "int", or "typename" (in /// TemplateParameters), might be None for macro parameters. - llvm::Optional Type; + llvm::Optional Type; /// None for unnamed parameters. llvm::Optional Name; /// None if no default is provided. @@ -62,11 +70,11 @@ /// Access specifier for declarations inside class/struct/unions, empty for /// others. std::string AccessSpecifier; - /// Pretty-printed variable type. + /// Printable variable type. /// Set only for variables. - llvm::Optional Type; + llvm::Optional Type; /// Set for functions and lambdas. - llvm::Optional ReturnType; + llvm::Optional ReturnType; /// Set for functions, lambdas and macros with parameters. llvm::Optional> Parameters; /// Set for all templates(function, class, variable). @@ -98,6 +106,11 @@ markup::Document present() const; }; +inline bool operator==(const HoverInfo::PrintedType &LHS, + const HoverInfo::PrintedType &RHS) { + return std::tie(LHS.Type, LHS.AKA) == std::tie(RHS.Type, RHS.AKA); +} + inline bool operator==(const HoverInfo::PassType &LHS, const HoverInfo::PassType &RHS) { return std::tie(LHS.PassBy, LHS.Converted) == @@ -108,6 +121,8 @@ // FIXME: move to another file so CodeComplete doesn't depend on Hover. void parseDocumentation(llvm::StringRef Input, markup::Document &Output); +llvm::raw_ostream &operator<<(llvm::raw_ostream &, + const HoverInfo::PrintedType &); llvm::raw_ostream &operator<<(llvm::raw_ostream &, const HoverInfo::Param &); inline bool operator==(const HoverInfo::Param &LHS, const HoverInfo::Param &RHS) { diff --git a/clang-tools-extra/clangd/Hover.cpp b/clang-tools-extra/clangd/Hover.cpp --- a/clang-tools-extra/clangd/Hover.cpp +++ b/clang-tools-extra/clangd/Hover.cpp @@ -18,6 +18,7 @@ #include "support/Logger.h" #include "support/Markup.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/ASTDiagnostic.h" #include "clang/AST/ASTTypeTraits.h" #include "clang/AST/Attr.h" #include "clang/AST/Decl.h" @@ -138,7 +139,8 @@ return LangOpts.ObjC ? "objective-c" : "cpp"; } -std::string printType(QualType QT, const PrintingPolicy &PP) { +HoverInfo::PrintedType printType(QualType QT, ASTContext &Context, + const PrintingPolicy &PP) { // TypePrinter doesn't resolve decltypes, so resolve them here. // FIXME: This doesn't handle composite types that contain a decltype in them. // We should rather have a printing policy for that. @@ -155,45 +157,65 @@ OS << TT->getDecl()->getKindName() << " "; } OS.flush(); - QT.print(OS, PP); - return Result; + std::string Type = Result + QT.getAsString(PP); + llvm::Optional AKA; + if (!QT.isNull()) { + bool ShouldAKA = false; + QualType DesugaredTy = clang::Desugar(Context, QT, ShouldAKA); + if (ShouldAKA) + AKA = Result + DesugaredTy.getAsString(PP); + } + return {Type, AKA}; } -std::string printType(const TemplateTypeParmDecl *TTP) { +HoverInfo::PrintedType printType(const TemplateTypeParmDecl *TTP) { std::string Res = TTP->wasDeclaredWithTypename() ? "typename" : "class"; if (TTP->isParameterPack()) Res += "..."; - return Res; + return {Res, llvm::None}; } -std::string printType(const NonTypeTemplateParmDecl *NTTP, - const PrintingPolicy &PP) { - std::string Res = printType(NTTP->getType(), PP); - if (NTTP->isParameterPack()) - Res += "..."; - return Res; +HoverInfo::PrintedType printType(const NonTypeTemplateParmDecl *NTTP, + const PrintingPolicy &PP) { + auto PrintedType = printType(NTTP->getType(), NTTP->getASTContext(), PP); + if (NTTP->isParameterPack()) { + PrintedType.Type += "..."; + if (PrintedType.AKA) + *PrintedType.AKA += "..."; + } + return PrintedType; } -std::string printType(const TemplateTemplateParmDecl *TTP, - const PrintingPolicy &PP) { - std::string Res; - llvm::raw_string_ostream OS(Res); - OS << "template <"; - llvm::StringRef Sep = ""; +HoverInfo::PrintedType printType(const TemplateTemplateParmDecl *TTP, + const PrintingPolicy &PP) { + bool ShouldAKA = false; + llvm::SmallVector TypeParams; + llvm::SmallVector AKATypeParams; for (const Decl *Param : *TTP->getTemplateParameters()) { - OS << Sep; - Sep = ", "; + llvm::Optional PType; if (const auto *TTP = dyn_cast(Param)) - OS << printType(TTP); + PType = printType(TTP); else if (const auto *NTTP = dyn_cast(Param)) - OS << printType(NTTP, PP); + PType = printType(NTTP, PP); else if (const auto *TTPD = dyn_cast(Param)) - OS << printType(TTPD, PP); + PType = printType(TTPD, PP); + if (!PType) + continue; + TypeParams.push_back(PType->Type); + if (PType->AKA) { + ShouldAKA = true; + AKATypeParams.push_back(*PType->AKA); + } else + AKATypeParams.push_back(PType->Type); } // FIXME: TemplateTemplateParameter doesn't store the info on whether this // param was a "typename" or "class". - OS << "> class"; - return OS.str(); + const char *FMT = "template <{0}> class"; + std::string Type = llvm::formatv(FMT, llvm::join(TypeParams, ", ")); + llvm::Optional AKA; + if (ShouldAKA) + AKA = llvm::formatv(FMT, llvm::join(AKATypeParams, ", ")); + return {Type, AKA}; } std::vector @@ -329,7 +351,7 @@ HoverInfo::Param toHoverInfoParam(const ParmVarDecl *PVD, const PrintingPolicy &PP) { HoverInfo::Param Out; - Out.Type = printType(PVD->getType(), PP); + Out.Type = printType(PVD->getType(), PVD->getASTContext(), PP); if (!PVD->getName().empty()) Out.Name = PVD->getNameAsString(); if (const Expr *DefArg = getDefaultArg(PVD)) { @@ -356,11 +378,11 @@ NK == DeclarationName::CXXConversionFunctionName) return; - HI.ReturnType = printType(FD->getReturnType(), PP); + HI.ReturnType = printType(FD->getReturnType(), FD->getASTContext(), PP); QualType QT = FD->getType(); if (const VarDecl *VD = llvm::dyn_cast(D)) // Lambdas QT = VD->getType().getDesugaredType(D->getASTContext()); - HI.Type = printType(QT, PP); + HI.Type = printType(QT, D->getASTContext(), PP); // FIXME: handle variadics. } @@ -589,11 +611,17 @@ if (const FunctionDecl *FD = getUnderlyingFunction(D)) fillFunctionTypeAndParams(HI, D, FD, PP); else if (const auto *VD = dyn_cast(D)) - HI.Type = printType(VD->getType(), PP); + HI.Type = printType(VD->getType(), VD->getASTContext(), PP); else if (const auto *TTP = dyn_cast(D)) - HI.Type = TTP->wasDeclaredWithTypename() ? "typename" : "class"; + HI.Type = {TTP->wasDeclaredWithTypename() ? "typename" : "class", + llvm::None}; else if (const auto *TTP = dyn_cast(D)) HI.Type = printType(TTP, PP); + else if (const auto *TN = dyn_cast(D)) + HI.Type = printType(TN->getUnderlyingType(), TN->getASTContext(), PP); + else if (const auto *TAT = dyn_cast(D)) + HI.Type = printType(TAT->getTemplatedDecl()->getUnderlyingType(), + TAT->getASTContext(), PP); // Fill in value with evaluated initializer if possible. if (const auto *Var = dyn_cast(D)) { @@ -604,7 +632,6 @@ if (!ECD->getType()->isDependentType()) HI.Value = toString(ECD->getInitVal(), 10); } - HI.Definition = printDefinition(D, PP); return HI; } @@ -658,7 +685,10 @@ HoverInfo HI; HI.Name = "this"; - HI.Definition = printType(PrettyThisType, PP); + auto PType = printType(PrettyThisType, ASTCtx, PP); + HI.Definition = llvm::formatv("{0}", PType.Type); + if (PType.AKA) + HI.Definition += llvm::formatv(" // aka: {0}", *PType.AKA); return HI; } @@ -675,7 +705,10 @@ if (QT->isUndeducedAutoType()) { HI.Definition = "/* not deduced */"; } else { - HI.Definition = printType(QT, PP); + auto PType = printType(QT, ASTCtx, PP); + HI.Definition = llvm::formatv("{0}", PType.Type); + if (PType.AKA) + HI.Definition += llvm::formatv(" // aka: {0}", *PType.AKA); if (const auto *D = QT->getAsTagDecl()) { const auto *CommentD = getDeclForComment(D); @@ -726,7 +759,7 @@ // For expressions we currently print the type and the value, iff it is // evaluatable. if (auto Val = printExprValue(E, AST.getASTContext())) { - HI.Type = printType(E->getType(), PP); + HI.Type = printType(E->getType(), AST.getASTContext(), PP); HI.Value = *Val; HI.Name = std::string(getNameForExpr(E)); return HI; @@ -1057,7 +1090,10 @@ // Parameters: // - `bool param1` // - `int param2 = 5` - Output.addParagraph().appendText("→ ").appendCode(*ReturnType); + std::string Buffer; + llvm::raw_string_ostream OS(Buffer); + OS << ReturnType; + Output.addParagraph().appendText("→ ").appendCode(OS.str()); if (Parameters && !Parameters->empty()) { Output.addParagraph().appendText("Parameters: "); markup::BulletList &L = Output.addBulletList(); @@ -1069,7 +1105,10 @@ } } } else if (Type) { - Output.addParagraph().appendText("Type: ").appendCode(*Type); + std::string Buffer; + llvm::raw_string_ostream OS(Buffer); + OS << Type; + Output.addParagraph().appendText("Type: ").appendCode(OS.str()); } if (Value) { @@ -1103,7 +1142,7 @@ if (CalleeArgInfo->Name) OS << "as " << CalleeArgInfo->Name; if (CallPassType->Converted && CalleeArgInfo->Type) - OS << " (converted to " << CalleeArgInfo->Type << ")"; + OS << " (converted to " << CalleeArgInfo->Type->Type << ")"; Output.addParagraph().appendText(OS.str()); } @@ -1212,15 +1251,25 @@ } llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, + const HoverInfo::PrintedType &T) { + OS << T.Type; + if (T.AKA) + OS << " (aka " << *T.AKA << ")"; + return OS; +} + +llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const HoverInfo::Param &P) { std::vector Output; if (P.Type) - Output.push_back(*P.Type); + Output.push_back(P.Type->Type); if (P.Name) Output.push_back(*P.Name); OS << llvm::join(Output, " "); if (P.Default) OS << " = " << *P.Default; + if (P.Type && P.Type->AKA) + OS << llvm::formatv(" (aka {0})", *P.Type->AKA); return OS; } diff --git a/clang-tools-extra/clangd/unittests/HoverTests.cpp b/clang-tools-extra/clangd/unittests/HoverTests.cpp --- a/clang-tools-extra/clangd/unittests/HoverTests.cpp +++ b/clang-tools-extra/clangd/unittests/HoverTests.cpp @@ -45,8 +45,8 @@ HI.Kind = index::SymbolKind::Function; HI.Documentation = "Best foo ever."; HI.Definition = "void foo()"; - HI.ReturnType = "void"; - HI.Type = "void ()"; + HI.ReturnType = {"void", llvm::None}; + HI.Type = {"void ()", llvm::None}; HI.Parameters.emplace(); }}, // Inside namespace @@ -62,8 +62,8 @@ HI.Kind = index::SymbolKind::Function; HI.Documentation = "Best foo ever."; HI.Definition = "void foo()"; - HI.ReturnType = "void"; - HI.Type = "void ()"; + HI.ReturnType = {"void", llvm::None}; + HI.Type = {"void ()", llvm::None}; HI.Parameters.emplace(); }}, // Field @@ -81,7 +81,7 @@ HI.Name = "bar"; HI.Kind = index::SymbolKind::Field; HI.Definition = "char bar"; - HI.Type = "char"; + HI.Type = {"char", llvm::None}; HI.Offset = 0; HI.Size = 1; HI.Padding = 7; @@ -100,7 +100,7 @@ HI.Name = "bar"; HI.Kind = index::SymbolKind::Field; HI.Definition = "char bar"; - HI.Type = "char"; + HI.Type = {"char", llvm::None}; HI.Size = 1; HI.Padding = 15; HI.AccessSpecifier = "public"; @@ -118,7 +118,7 @@ HI.Name = "x"; HI.Kind = index::SymbolKind::Field; HI.Definition = "int x : 1"; - HI.Type = "int"; + HI.Type = {"int", llvm::None}; HI.AccessSpecifier = "public"; }}, // Local to class method. @@ -137,7 +137,7 @@ HI.Name = "bar"; HI.Kind = index::SymbolKind::Variable; HI.Definition = "int bar"; - HI.Type = "int"; + HI.Type = {"int", llvm::None}; }}, // Anon namespace and local scope. {R"cpp( @@ -153,7 +153,7 @@ HI.Name = "bar"; HI.Kind = index::SymbolKind::Field; HI.Definition = "char bar"; - HI.Type = "char"; + HI.Type = {"char", llvm::None}; HI.Offset = 0; HI.Size = 1; HI.AccessSpecifier = "public"; @@ -179,7 +179,7 @@ HI.Name = "foo"; HI.Kind = index::SymbolKind::Variable; HI.Definition = "Foo foo = Foo(5)"; - HI.Type = "Foo"; + HI.Type = {"Foo", llvm::None}; }}, // Implicit template instantiation {R"cpp( @@ -211,12 +211,19 @@ bool Q = false, class... Ts> class Foo {})cpp"; HI.TemplateParameters = { - {std::string("template class"), - std::string("C"), llvm::None}, - {std::string("typename"), llvm::None, std::string("char")}, - {std::string("int"), llvm::None, std::string("0")}, - {std::string("bool"), std::string("Q"), std::string("false")}, - {std::string("class..."), std::string("Ts"), llvm::None}, + {{{std::string("template class"), llvm::None}}, + std::string("C"), + llvm::None}, + {{{std::string("typename"), llvm::None}}, + llvm::None, + std::string("char")}, + {{{std::string("int"), llvm::None}}, llvm::None, std::string("0")}, + {{{std::string("bool"), llvm::None}}, + std::string("Q"), + std::string("false")}, + {{{std::string("class..."), llvm::None}}, + std::string("Ts"), + llvm::None}, }; }}, // Function template @@ -237,8 +244,8 @@ HI.Name = "foo"; HI.Kind = index::SymbolKind::Function; HI.Definition = "template <> void foo>()"; - HI.ReturnType = "void"; - HI.Type = "void ()"; + HI.ReturnType = {"void", llvm::None}; + HI.Type = {"void ()", llvm::None}; HI.Parameters.emplace(); }}, // Function decl @@ -255,11 +262,13 @@ HI.Name = "foo"; HI.Kind = index::SymbolKind::Function; HI.Definition = "Foo foo(int, bool T = false)"; - HI.ReturnType = "Foo"; - HI.Type = "Foo (int, bool)"; + HI.ReturnType = {"Foo", llvm::None}; + HI.Type = {"Foo (int, bool)", llvm::None}; HI.Parameters = { - {std::string("int"), llvm::None, llvm::None}, - {std::string("bool"), std::string("T"), std::string("false")}, + {{{std::string("int"), llvm::None}}, llvm::None, llvm::None}, + {{{std::string("bool"), llvm::None}}, + std::string("T"), + std::string("false")}, }; }}, // Pointers to lambdas @@ -276,11 +285,13 @@ HI.Name = "c"; HI.Kind = index::SymbolKind::Variable; HI.Definition = "auto *c = &b"; - HI.Type = "(lambda) **"; - HI.ReturnType = "bool"; + HI.Type = {"(lambda) **", llvm::None}; + HI.ReturnType = {"bool", llvm::None}; HI.Parameters = { - {std::string("int"), std::string("T"), llvm::None}, - {std::string("bool"), std::string("B"), llvm::None}, + {{{std::string("int"), llvm::None}}, std::string("T"), llvm::None}, + {{{std::string("bool"), llvm::None}}, + std::string("B"), + llvm::None}, }; return HI; }}, @@ -297,11 +308,13 @@ HI.Name = "bar"; HI.Kind = index::SymbolKind::Parameter; HI.Definition = "decltype(lamb) &bar"; - HI.Type = "decltype(lamb) &"; - HI.ReturnType = "bool"; + HI.Type = {"decltype(lamb) &", {"(lambda) &"}}; + HI.ReturnType = {"bool", llvm::None}; HI.Parameters = { - {std::string("int"), std::string("T"), llvm::None}, - {std::string("bool"), std::string("B"), llvm::None}, + {{{std::string("int"), llvm::None}}, std::string("T"), llvm::None}, + {{{std::string("bool"), llvm::None}}, + std::string("B"), + llvm::None}, }; return HI; }}, @@ -318,11 +331,13 @@ HI.Name = "bar"; HI.Kind = index::SymbolKind::Parameter; HI.Definition = "decltype(lamb) bar"; - HI.Type = "class (lambda)"; - HI.ReturnType = "bool"; + HI.Type = {"class (lambda)", llvm::None}; + HI.ReturnType = {"bool", llvm::None}; HI.Parameters = { - {std::string("int"), std::string("T"), llvm::None}, - {std::string("bool"), std::string("B"), llvm::None}, + {{{std::string("int"), llvm::None}}, std::string("T"), llvm::None}, + {{{std::string("bool"), llvm::None}}, + std::string("B"), + llvm::None}, }; HI.Value = "false"; return HI; @@ -341,11 +356,13 @@ HI.Name = "lamb"; HI.Kind = index::SymbolKind::Variable; HI.Definition = "auto lamb = [&bar](int T, bool B) -> bool {}"; - HI.Type = "class (lambda)"; - HI.ReturnType = "bool"; + HI.Type = {"class (lambda)", llvm::None}; + HI.ReturnType = {"bool", llvm::None}; HI.Parameters = { - {std::string("int"), std::string("T"), llvm::None}, - {std::string("bool"), std::string("B"), llvm::None}, + {{{std::string("int"), llvm::None}}, std::string("T"), llvm::None}, + {{{std::string("bool"), llvm::None}}, + std::string("B"), + llvm::None}, }; return HI; }}, @@ -361,7 +378,7 @@ HI.Name = "test"; HI.Kind = index::SymbolKind::Variable; HI.Definition = "int test"; - HI.Type = "int"; + HI.Type = {"int", llvm::None}; }}, // Partially-specialized class template. (formerly type-parameter-0-0) {R"cpp( @@ -497,7 +514,7 @@ HI.Name = "bar"; HI.Definition = "int bar = add(1, 2)"; HI.Kind = index::SymbolKind::Variable; - HI.Type = "int"; + HI.Type = {"int", llvm::None}; HI.NamespaceScope = ""; HI.Value = "3"; }}, @@ -508,7 +525,7 @@ HI.Name = "bar"; HI.Definition = "int bar = sizeof(char)"; HI.Kind = index::SymbolKind::Variable; - HI.Type = "int"; + HI.Type = {"int", llvm::None}; HI.NamespaceScope = ""; HI.Value = "1"; }}, @@ -522,7 +539,7 @@ HI.Name = "bar"; HI.Definition = "int bar = Add<1, 2>::result"; HI.Kind = index::SymbolKind::Variable; - HI.Type = "int"; + HI.Type = {"int", llvm::None}; HI.NamespaceScope = ""; HI.Value = "3"; }}, @@ -536,7 +553,7 @@ HI.LocalScope = "Color::"; HI.Definition = "GREEN = 5"; HI.Kind = index::SymbolKind::EnumConstant; - HI.Type = "enum Color"; + HI.Type = {"enum Color", llvm::None}; HI.Value = "5"; // Numeric on the enumerator name, no hex as small. }}, {R"cpp( @@ -549,7 +566,7 @@ HI.NamespaceScope = ""; HI.Definition = "Color x = RED"; HI.Kind = index::SymbolKind::Variable; - HI.Type = "enum Color"; + HI.Type = {"enum Color", llvm::None}; HI.Value = "RED (0xffffff85)"; // Symbolic on an expression. }}, {R"cpp( @@ -562,22 +579,23 @@ HI.Name = "result"; HI.Definition = "static constexpr int result = a + b"; HI.Kind = index::SymbolKind::StaticProperty; - HI.Type = "const int"; + HI.Type = {"const int", llvm::None}; HI.NamespaceScope = ""; HI.LocalScope = "Add<1, 2>::"; HI.Value = "3"; HI.AccessSpecifier = "public"; }}, {R"cpp( - constexpr int answer() { return 40 + 2; } + using my_int = int; + constexpr my_int answer() { return 40 + 2; } int x = [[ans^wer]](); )cpp", [](HoverInfo &HI) { HI.Name = "answer"; - HI.Definition = "constexpr int answer()"; + HI.Definition = "constexpr my_int answer()"; HI.Kind = index::SymbolKind::Function; - HI.Type = "int ()"; - HI.ReturnType = "int"; + HI.Type = {"my_int ()", {"int ()"}}; + HI.ReturnType = {"my_int", {"int"}}; HI.Parameters.emplace(); HI.NamespaceScope = ""; HI.Value = "42 (0x2a)"; @@ -589,7 +607,7 @@ HI.Name = "bar"; HI.Definition = "const char *bar = \"1234\""; HI.Kind = index::SymbolKind::Variable; - HI.Type = "const char *"; + HI.Type = {"const char *", llvm::None}; HI.NamespaceScope = ""; HI.Value = "&\"1234\"[0]"; }}, @@ -607,7 +625,7 @@ HI.Name = "name"; HI.Definition = "int name"; HI.Kind = index::SymbolKind::Parameter; - HI.Type = "int"; + HI.Type = {"int", llvm::None}; HI.NamespaceScope = ""; HI.LocalScope = "boom::"; }}, @@ -679,7 +697,7 @@ HI.NamespaceScope = ""; HI.Definition = "typename T = int"; HI.LocalScope = "foo::"; - HI.Type = "typename"; + HI.Type = {"typename", llvm::None}; HI.AccessSpecifier = "public"; }}, {// TemplateTemplate Type Parameter @@ -692,7 +710,7 @@ HI.NamespaceScope = ""; HI.Definition = "template class T"; HI.LocalScope = "foo::"; - HI.Type = "template class"; + HI.Type = {"template class", llvm::None}; HI.AccessSpecifier = "public"; }}, {// NonType Template Parameter @@ -705,7 +723,7 @@ HI.NamespaceScope = ""; HI.Definition = "int T = 5"; HI.LocalScope = "foo::"; - HI.Type = "int"; + HI.Type = {"int", llvm::None}; HI.AccessSpecifier = "public"; }}, @@ -720,8 +738,8 @@ HI.Definition = "float y()"; HI.LocalScope = "X::"; HI.Documentation = "Trivial accessor for `Y`."; - HI.Type = "float ()"; - HI.ReturnType = "float"; + HI.Type = {"float ()", llvm::None}; + HI.ReturnType = {"float", llvm::None}; HI.Parameters.emplace(); HI.AccessSpecifier = "public"; }}, @@ -736,11 +754,11 @@ HI.Definition = "void setY(float v)"; HI.LocalScope = "X::"; HI.Documentation = "Trivial setter for `Y`."; - HI.Type = "void (float)"; - HI.ReturnType = "void"; + HI.Type = {"void (float)", llvm::None}; + HI.ReturnType = {"void", llvm::None}; HI.Parameters.emplace(); HI.Parameters->emplace_back(); - HI.Parameters->back().Type = "float"; + HI.Parameters->back().Type = {"float", llvm::None}; HI.Parameters->back().Name = "v"; HI.AccessSpecifier = "public"; }}, @@ -755,11 +773,11 @@ HI.Definition = "X &setY(float v)"; HI.LocalScope = "X::"; HI.Documentation = "Trivial setter for `Y`."; - HI.Type = "X &(float)"; - HI.ReturnType = "X &"; + HI.Type = {"X &(float)", llvm::None}; + HI.ReturnType = {"X &", llvm::None}; HI.Parameters.emplace(); HI.Parameters->emplace_back(); - HI.Parameters->back().Type = "float"; + HI.Parameters->back().Type = {"float", llvm::None}; HI.Parameters->back().Name = "v"; HI.AccessSpecifier = "public"; }}, @@ -775,11 +793,11 @@ HI.Definition = "void setY(float v)"; HI.LocalScope = "X::"; HI.Documentation = "Trivial setter for `Y`."; - HI.Type = "void (float)"; - HI.ReturnType = "void"; + HI.Type = {"void (float)", llvm::None}; + HI.ReturnType = {"void", llvm::None}; HI.Parameters.emplace(); HI.Parameters->emplace_back(); - HI.Parameters->back().Type = "float"; + HI.Parameters->back().Type = {"float", llvm::None}; HI.Parameters->back().Name = "v"; HI.AccessSpecifier = "public"; }}, @@ -793,7 +811,7 @@ HI.Kind = index::SymbolKind::Variable; HI.NamespaceScope = ""; HI.Definition = "X x"; - HI.Type = "struct X"; + HI.Type = {"struct X", llvm::None}; }}, {// Don't crash on null types. R"cpp(auto [^[[x]]] = 1; /*error-ok*/)cpp", @@ -802,7 +820,7 @@ HI.Kind = index::SymbolKind::Variable; HI.NamespaceScope = ""; HI.Definition = ""; - HI.Type = "NULL TYPE"; + HI.Type = {"NULL TYPE", llvm::None}; // Bindings are in theory public members of an anonymous struct. HI.AccessSpecifier = "public"; }}, @@ -821,10 +839,10 @@ HI.Definition = "int b = 2"; HI.LocalScope = "code::"; HI.Value = "2"; - HI.Type = "int"; + HI.Type = {"int", llvm::None}; HI.CalleeArgInfo.emplace(); HI.CalleeArgInfo->Name = "arg_b"; - HI.CalleeArgInfo->Type = "int &"; + HI.CalleeArgInfo->Type = {"int &", llvm::None}; HI.CallPassType.emplace(); HI.CallPassType->PassBy = PassMode::Ref; HI.CallPassType->Converted = false; @@ -848,10 +866,10 @@ HI.Definition = "int a = 1"; HI.LocalScope = "code::"; HI.Value = "1"; - HI.Type = "int"; + HI.Type = {"int", llvm::None}; HI.CalleeArgInfo.emplace(); HI.CalleeArgInfo->Name = "arg_a"; - HI.CalleeArgInfo->Type = "int"; + HI.CalleeArgInfo->Type = {"int", llvm::None}; HI.CalleeArgInfo->Default = "3"; HI.CallPassType.emplace(); HI.CallPassType->PassBy = PassMode::Value; @@ -869,7 +887,7 @@ HI.NamespaceScope = ""; HI.Definition = "int xx"; HI.LocalScope = "Foo::"; - HI.Type = "int"; + HI.Type = {"int", llvm::None}; HI.AccessSpecifier = "public"; }}, {R"cpp( @@ -884,7 +902,7 @@ HI.NamespaceScope = ""; HI.Definition = "int yy"; HI.LocalScope = "Foo::"; - HI.Type = "int"; + HI.Type = {"int", llvm::None}; HI.AccessSpecifier = "public"; }}, {// No crash on InitListExpr. @@ -899,8 +917,79 @@ [](HoverInfo &HI) { HI.Name = "expression"; HI.Kind = index::SymbolKind::Unknown; - HI.Type = "int[10]"; + HI.Type = {"int[10]", llvm::None}; HI.Value = "{1}"; + }}, + {// Canonical type + R"cpp( + template + struct TestHover { + using Type = T; + }; + + void code() { + TestHover::Type ^[[a]]; + } + )cpp", + [](HoverInfo &HI) { + HI.Name = "a"; + HI.NamespaceScope = ""; + HI.LocalScope = "code::"; + HI.Definition = "TestHover::Type a"; + HI.Kind = index::SymbolKind::Variable; + HI.Type = {"TestHover::Type", {"int"}}; + }}, + {// Canonical template type + R"cpp( + template + void ^[[foo]](T arg) {} + )cpp", + [](HoverInfo &HI) { + HI.Name = "foo"; + HI.Kind = index::SymbolKind::Function; + HI.NamespaceScope = ""; + HI.Definition = "template void foo(T arg)"; + HI.Type = {"void (T)", llvm::None}; + HI.ReturnType = {"void", llvm::None}; + HI.Parameters = {{{{std::string("T"), llvm::None}}, + std::string("arg"), + llvm::None}}; + HI.TemplateParameters = {{{{std::string("typename"), llvm::None}}, + std::string("T"), + llvm::None}}; + }}, + {// TypeAlias Template + R"cpp( + template + using ^[[alias]] = T; + )cpp", + [](HoverInfo &HI) { + HI.Name = "alias"; + HI.NamespaceScope = ""; + HI.LocalScope = ""; + HI.Kind = index::SymbolKind::TypeAlias; + HI.Definition = "template using alias = T"; + HI.Type = {"T", llvm::None}; + HI.TemplateParameters = { + {{{"typename", llvm::None}}, std::string("T"), llvm::None}}; + }}, + {// TypeAlias Template + R"cpp( + template + using A = T; + + template + using ^[[AA]] = A; + )cpp", + [](HoverInfo &HI) { + HI.Name = "AA"; + HI.NamespaceScope = ""; + HI.LocalScope = ""; + HI.Kind = index::SymbolKind::TypeAlias; + HI.Definition = "template using AA = A"; + HI.Type = {"A", {"type-parameter-0-0"}}; // FIXME: should be 'T' + HI.TemplateParameters = { + {{{"typename", llvm::None}}, std::string("T"), llvm::None}}; }}}; for (const auto &Case : Cases) { SCOPED_TRACE(Case.Code); @@ -1117,7 +1206,7 @@ HI.Kind = index::SymbolKind::Variable; HI.NamespaceScope = ""; HI.LocalScope = "main::"; - HI.Type = "int"; + HI.Type = {"int", llvm::None}; HI.Definition = "int bonjour"; }}, { @@ -1134,7 +1223,7 @@ HI.Kind = index::SymbolKind::Variable; HI.NamespaceScope = ""; HI.LocalScope = "s::method::"; - HI.Type = "int"; + HI.Type = {"int", llvm::None}; HI.Definition = "int bonjour"; }}, { @@ -1193,12 +1282,12 @@ HI.Name = "foo"; HI.Kind = index::SymbolKind::Function; HI.NamespaceScope = ""; - HI.Type = "void (int)"; + HI.Type = {"void (int)", llvm::None}; HI.Definition = "void foo(int)"; HI.Documentation = "Function definition via pointer"; - HI.ReturnType = "void"; + HI.ReturnType = {"void", llvm::None}; HI.Parameters = { - {std::string("int"), llvm::None, llvm::None}, + {{{std::string("int"), llvm::None}}, llvm::None, llvm::None}, }; }}, { @@ -1212,12 +1301,12 @@ HI.Name = "foo"; HI.Kind = index::SymbolKind::Function; HI.NamespaceScope = ""; - HI.Type = "int (int)"; + HI.Type = {"int (int)", llvm::None}; HI.Definition = "int foo(int)"; HI.Documentation = "Function declaration via call"; - HI.ReturnType = "int"; + HI.ReturnType = {"int", llvm::None}; HI.Parameters = { - {std::string("int"), llvm::None, llvm::None}, + {{{std::string("int"), llvm::None}}, llvm::None, llvm::None}, }; }}, { @@ -1233,7 +1322,7 @@ HI.Kind = index::SymbolKind::Field; HI.NamespaceScope = ""; HI.LocalScope = "Foo::"; - HI.Type = "int"; + HI.Type = {"int", llvm::None}; HI.Definition = "int x"; }}, { @@ -1249,7 +1338,7 @@ HI.Kind = index::SymbolKind::Field; HI.NamespaceScope = ""; HI.LocalScope = "Foo::"; - HI.Type = "int"; + HI.Type = {"int", llvm::None}; HI.Definition = "int x = 5"; }}, { @@ -1264,7 +1353,7 @@ HI.Kind = index::SymbolKind::StaticProperty; HI.NamespaceScope = ""; HI.LocalScope = "Foo::"; - HI.Type = "int"; + HI.Type = {"int", llvm::None}; HI.Definition = "static int x"; }}, { @@ -1279,7 +1368,7 @@ HI.Kind = index::SymbolKind::Field; HI.NamespaceScope = ""; HI.LocalScope = "Foo::"; - HI.Type = "int"; + HI.Type = {"int", llvm::None}; HI.Definition = "int x"; }}, { @@ -1294,7 +1383,7 @@ HI.Kind = index::SymbolKind::Field; HI.NamespaceScope = ""; HI.LocalScope = "Foo::"; - HI.Type = "int"; + HI.Type = {"int", llvm::None}; HI.Definition = "int x"; // FIXME: Initializer for x is a DesignatedInitListExpr, hence it is // of struct type and omitted. @@ -1311,7 +1400,7 @@ HI.Kind = index::SymbolKind::Field; HI.NamespaceScope = ""; HI.LocalScope = "Foo::"; - HI.Type = "int"; + HI.Type = {"int", llvm::None}; HI.Definition = "int x"; }}, { @@ -1327,9 +1416,9 @@ HI.Kind = index::SymbolKind::InstanceMethod; HI.NamespaceScope = ""; HI.LocalScope = "Foo::"; - HI.Type = "int ()"; + HI.Type = {"int ()", llvm::None}; HI.Definition = "int x()"; - HI.ReturnType = "int"; + HI.ReturnType = {"int", llvm::None}; HI.Parameters = std::vector{}; }}, { @@ -1344,9 +1433,9 @@ HI.Kind = index::SymbolKind::StaticMethod; HI.NamespaceScope = ""; HI.LocalScope = "Foo::"; - HI.Type = "int ()"; + HI.Type = {"int ()", llvm::None}; HI.Definition = "static int x()"; - HI.ReturnType = "int"; + HI.ReturnType = {"int", llvm::None}; HI.Parameters = std::vector{}; }}, { @@ -1361,6 +1450,7 @@ HI.Kind = index::SymbolKind::TypeAlias; HI.NamespaceScope = ""; HI.Definition = "typedef int Foo"; + HI.Type = {"int", llvm::None}; HI.Documentation = "Typedef"; // FIXME: Maybe put underlying type into HI.Type for aliases? }}, @@ -1376,6 +1466,7 @@ HI.Kind = index::SymbolKind::TypeAlias; HI.NamespaceScope = ""; HI.Definition = "typedef struct Bar Foo"; + HI.Type = {"struct Bar", llvm::None}; HI.Documentation = "Typedef with embedded definition"; }}, { @@ -1404,7 +1495,7 @@ HI.Name = "foo"; HI.Kind = index::SymbolKind::Variable; HI.NamespaceScope = "ns::"; - HI.Type = "int"; + HI.Type = {"int", llvm::None}; HI.Definition = "int foo"; }}, { @@ -1464,10 +1555,10 @@ HI.Name = "foo"; HI.Kind = index::SymbolKind::Function; HI.NamespaceScope = ""; - HI.Type = "void ()"; + HI.Type = {"void ()", llvm::None}; HI.Definition = "void foo()"; HI.Documentation = "Function declaration"; - HI.ReturnType = "void"; + HI.ReturnType = {"void", llvm::None}; HI.Parameters = std::vector{}; }}, { @@ -1500,7 +1591,7 @@ HI.Kind = index::SymbolKind::EnumConstant; HI.NamespaceScope = ""; HI.LocalScope = "Hello::"; - HI.Type = "enum Hello"; + HI.Type = {"enum Hello", llvm::None}; HI.Definition = "ONE"; HI.Value = "0"; }}, @@ -1519,7 +1610,7 @@ HI.NamespaceScope = ""; // FIXME: This should be `(anon enum)::` HI.LocalScope = ""; - HI.Type = "enum (unnamed)"; + HI.Type = {"enum (unnamed)", llvm::None}; HI.Definition = "ONE"; HI.Value = "0"; }}, @@ -1534,7 +1625,7 @@ HI.Name = "hey"; HI.Kind = index::SymbolKind::Variable; HI.NamespaceScope = ""; - HI.Type = "int"; + HI.Type = {"int", llvm::None}; HI.Definition = "static int hey = 10"; HI.Documentation = "Global variable"; // FIXME: Value shouldn't be set in this case @@ -1553,7 +1644,7 @@ HI.Name = "hey"; HI.Kind = index::SymbolKind::Variable; HI.NamespaceScope = "ns1::"; - HI.Type = "long long"; + HI.Type = {"long long", llvm::None}; HI.Definition = "static long long hey = -36637162602497"; HI.Value = "-36637162602497 (0xffffdeadbeefffff)"; // needs 64 bits }}, @@ -1571,7 +1662,7 @@ HI.Kind = index::SymbolKind::Field; HI.NamespaceScope = ""; HI.LocalScope = "(anonymous struct)::"; - HI.Type = "int"; + HI.Type = {"int", llvm::None}; HI.Definition = "int hello"; }}, { @@ -1586,10 +1677,10 @@ HI.Name = "foo"; HI.Kind = index::SymbolKind::Function; HI.NamespaceScope = ""; - HI.Type = "int ()"; + HI.Type = {"int ()", llvm::None}; HI.Definition = "template <> int foo()"; HI.Documentation = "Templated function"; - HI.ReturnType = "int"; + HI.ReturnType = {"int", llvm::None}; HI.Parameters = std::vector{}; // FIXME: We should populate template parameters with arguments in // case of instantiations. @@ -1608,7 +1699,7 @@ HI.Kind = index::SymbolKind::Field; HI.NamespaceScope = ""; HI.LocalScope = "outer::(anonymous union)::"; - HI.Type = "int"; + HI.Type = {"int", llvm::None}; HI.Definition = "int def"; }}, { @@ -1621,9 +1712,9 @@ HI.Name = "indexSymbol"; HI.Kind = index::SymbolKind::Function; HI.NamespaceScope = ""; - HI.Type = "void ()"; + HI.Type = {"void ()", llvm::None}; HI.Definition = "void indexSymbol()"; - HI.ReturnType = "void"; + HI.ReturnType = {"void", llvm::None}; HI.Parameters = std::vector{}; HI.Documentation = "comment from index"; }}, @@ -2013,7 +2104,7 @@ HI.Kind = index::SymbolKind::Variable; HI.NamespaceScope = ""; HI.LocalScope = "test::"; - HI.Type = "Test &&"; + HI.Type = {"Test &&", llvm::None}; HI.Definition = "Test &&test = {}"; }}, { @@ -2024,7 +2115,7 @@ [](HoverInfo &HI) { HI.Name = "auto"; HI.Kind = index::SymbolKind::TypeAlias; - HI.Definition = "int_type"; + HI.Definition = "int_type // aka: int"; }}, { R"cpp(// auto on alias @@ -2035,7 +2126,7 @@ [](HoverInfo &HI) { HI.Name = "auto"; HI.Kind = index::SymbolKind::TypeAlias; - HI.Definition = "cls_type"; + HI.Definition = "cls_type // aka: cls"; HI.Documentation = "auto on alias"; }}, { @@ -2114,8 +2205,8 @@ HI.LocalScope = "cls::"; HI.Name = "method"; HI.Parameters.emplace(); - HI.ReturnType = "int"; - HI.Type = "int ()"; + HI.ReturnType = {"int", llvm::None}; + HI.Type = {"int ()", llvm::None}; }}, { R"cpp(// type of nested templates. @@ -2127,7 +2218,7 @@ HI.Kind = index::SymbolKind::Variable; HI.NamespaceScope = ""; HI.Name = "foo"; - HI.Type = "cls>>"; + HI.Type = {"cls>>", llvm::None}; }}, { R"cpp(// type of nested templates. @@ -2150,7 +2241,7 @@ HI.Kind = index::SymbolKind::Variable; HI.NamespaceScope = ""; HI.Name = "b"; - HI.Type = "int"; + HI.Type = {"int", llvm::None}; }}, { R"cpp(// type with decltype @@ -2162,7 +2253,7 @@ HI.Kind = index::SymbolKind::Variable; HI.NamespaceScope = ""; HI.Name = "b"; - HI.Type = "int"; + HI.Type = {"int", llvm::None}; }}, { R"cpp(// type with decltype @@ -2173,7 +2264,7 @@ HI.Kind = index::SymbolKind::Variable; HI.NamespaceScope = ""; HI.Name = "b"; - HI.Type = "int"; + HI.Type = {"int", llvm::None}; }}, { R"cpp(// type with decltype @@ -2186,10 +2277,12 @@ HI.Name = "foo"; // FIXME: Handle composite types with decltype with a printing // policy. - HI.Type = "auto (decltype(a)) -> decltype(a)"; - HI.ReturnType = "int"; - HI.Parameters = { - {std::string("int"), std::string("x"), llvm::None}}; + HI.Type = {"auto (decltype(a)) -> decltype(a)", + {"auto (int) -> int"}}; + HI.ReturnType = {"int", llvm::None}; + HI.Parameters = {{{{std::string("int"), llvm::None}}, + std::string("x"), + llvm::None}}; }}, { R"cpp(// sizeof expr @@ -2198,7 +2291,7 @@ })cpp", [](HoverInfo &HI) { HI.Name = "expression"; - HI.Type = "unsigned long"; + HI.Type = {"unsigned long", llvm::None}; HI.Value = "1"; }}, { @@ -2208,7 +2301,7 @@ })cpp", [](HoverInfo &HI) { HI.Name = "expression"; - HI.Type = "unsigned long"; + HI.Type = {"unsigned long", llvm::None}; HI.Value = "1"; }}, { @@ -2220,10 +2313,11 @@ [](HoverInfo &HI) { HI.Name = "foo"; HI.Kind = index::SymbolKind::Function; - HI.Type = "void (const int &)"; - HI.ReturnType = "void"; - HI.Parameters = { - {std::string("const int &"), llvm::None, std::string("T()")}}; + HI.Type = {"void (const int &)", llvm::None}; + HI.ReturnType = {"void", llvm::None}; + HI.Parameters = {{{{std::string("const int &"), llvm::None}}, + llvm::None, + std::string("T()")}}; HI.Definition = "template <> void foo(const int &)"; HI.NamespaceScope = ""; }}, @@ -2235,7 +2329,7 @@ )cpp", [](HoverInfo &HI) { HI.Name = "data"; - HI.Type = "char"; + HI.Type = {"char", llvm::None}; HI.Kind = index::SymbolKind::Field; HI.LocalScope = "ObjC::"; HI.NamespaceScope = ""; @@ -2386,7 +2480,7 @@ HI.Name = "result"; HI.Definition = "int result = 2"; HI.Kind = index::SymbolKind::Variable; - HI.Type = "int"; + HI.Type = {"int", llvm::None}; HI.LocalScope = "+[Foo(Private) somePrivateMethod]::"; HI.NamespaceScope = ""; HI.Value = "2"; @@ -2406,7 +2500,7 @@ HI.Name = "result"; HI.Definition = "int result = 0"; HI.Kind = index::SymbolKind::Variable; - HI.Type = "int"; + HI.Type = {"int", llvm::None}; HI.LocalScope = "-[Foo variadicArgMethod:, ...]::"; HI.NamespaceScope = ""; HI.Value = "0"; @@ -2580,8 +2674,11 @@ HI.Kind = index::SymbolKind::Class; HI.Size = 10; HI.TemplateParameters = { - {std::string("typename"), std::string("T"), llvm::None}, - {std::string("typename"), std::string("C"), + {{{std::string("typename"), llvm::None}}, + std::string("T"), + llvm::None}, + {{{std::string("typename"), llvm::None}}, + std::string("C"), std::string("bool")}, }; HI.Documentation = "documentation"; @@ -2601,12 +2698,12 @@ [](HoverInfo &HI) { HI.Kind = index::SymbolKind::Function; HI.Name = "foo"; - HI.Type = "type"; - HI.ReturnType = "ret_type"; + HI.Type = {"type", {"c_type"}}; + HI.ReturnType = {"ret_type", {"can_ret_type"}}; HI.Parameters.emplace(); HoverInfo::Param P; HI.Parameters->push_back(P); - P.Type = "type"; + P.Type = {"type", {"can_type"}}; HI.Parameters->push_back(P); P.Name = "foo"; HI.Parameters->push_back(P); @@ -2617,12 +2714,12 @@ }, "function foo\n" "\n" - "→ ret_type\n" + "→ ret_type (aka can_ret_type)\n" "Parameters:\n" "- \n" - "- type\n" - "- type foo\n" - "- type foo = default\n" + "- type (aka can_type)\n" + "- type foo (aka can_type)\n" + "- type foo = default (aka can_type)\n" "\n" "// In namespace ns\n" "ret_type foo(params) {}", @@ -2633,7 +2730,7 @@ HI.LocalScope = "test::Bar::"; HI.Value = "value"; HI.Name = "foo"; - HI.Type = "type"; + HI.Type = {"type", {"can_type"}}; HI.Definition = "def"; HI.Size = 4; HI.Offset = 12; @@ -2641,7 +2738,7 @@ }, R"(field foo -Type: type +Type: type (aka can_type) Value = value Offset: 12 bytes Size: 4 bytes (+4 padding) @@ -2664,22 +2761,22 @@ }, { [](HoverInfo &HI) { - HI.Definition = "int method()"; + HI.Definition = "size_t method()"; HI.AccessSpecifier = "protected"; HI.Kind = index::SymbolKind::InstanceMethod; HI.NamespaceScope = ""; HI.LocalScope = "cls::"; HI.Name = "method"; HI.Parameters.emplace(); - HI.ReturnType = "int"; - HI.Type = "int ()"; + HI.ReturnType = {"size_t", {"unsigned long"}}; + HI.Type = {"size_t ()", {"unsigned long ()"}}; }, R"(instance-method method -→ int +→ size_t (aka unsigned long) // In cls -protected: int method())", +protected: size_t method())", }, { [](HoverInfo &HI) { @@ -2701,10 +2798,10 @@ HI.Definition = "int foo = 3"; HI.LocalScope = "test::Bar::"; HI.Value = "3"; - HI.Type = "int"; + HI.Type = {"int", llvm::None}; HI.CalleeArgInfo.emplace(); HI.CalleeArgInfo->Name = "arg_a"; - HI.CalleeArgInfo->Type = "int"; + HI.CalleeArgInfo->Type = {"int", llvm::None}; HI.CalleeArgInfo->Default = "7"; HI.CallPassType.emplace(); HI.CallPassType->PassBy = PassMode::Value; @@ -2726,10 +2823,10 @@ HI.Definition = "int foo = 3"; HI.LocalScope = "test::Bar::"; HI.Value = "3"; - HI.Type = "int"; + HI.Type = {"int", llvm::None}; HI.CalleeArgInfo.emplace(); HI.CalleeArgInfo->Name = "arg_a"; - HI.CalleeArgInfo->Type = "int"; + HI.CalleeArgInfo->Type = {"int", llvm::None}; HI.CalleeArgInfo->Default = "7"; HI.CallPassType.emplace(); HI.CallPassType->PassBy = PassMode::Ref; @@ -2751,10 +2848,10 @@ HI.Definition = "int foo = 3"; HI.LocalScope = "test::Bar::"; HI.Value = "3"; - HI.Type = "int"; + HI.Type = {"int", llvm::None}; HI.CalleeArgInfo.emplace(); HI.CalleeArgInfo->Name = "arg_a"; - HI.CalleeArgInfo->Type = "int"; + HI.CalleeArgInfo->Type = {"alias_int", {"int"}}; HI.CalleeArgInfo->Default = "7"; HI.CallPassType.emplace(); HI.CallPassType->PassBy = PassMode::Value; @@ -2764,7 +2861,7 @@ Type: int Value = 3 -Passed as arg_a (converted to int) +Passed as arg_a (converted to alias_int) // In test::Bar int foo = 3)", @@ -2776,10 +2873,10 @@ HI.Definition = "int foo = 3"; HI.LocalScope = "test::Bar::"; HI.Value = "3"; - HI.Type = "int"; + HI.Type = {"int", llvm::None}; HI.CalleeArgInfo.emplace(); HI.CalleeArgInfo->Name = "arg_a"; - HI.CalleeArgInfo->Type = "int"; + HI.CalleeArgInfo->Type = {"int", llvm::None}; HI.CalleeArgInfo->Default = "7"; HI.CallPassType.emplace(); HI.CallPassType->PassBy = PassMode::ConstRef; diff --git a/clang/include/clang/AST/ASTDiagnostic.h b/clang/include/clang/AST/ASTDiagnostic.h --- a/clang/include/clang/AST/ASTDiagnostic.h +++ b/clang/include/clang/AST/ASTDiagnostic.h @@ -9,6 +9,7 @@ #ifndef LLVM_CLANG_AST_ASTDIAGNOSTIC_H #define LLVM_CLANG_AST_ASTDIAGNOSTIC_H +#include "clang/AST/Type.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/DiagnosticAST.h" @@ -31,6 +32,10 @@ SmallVectorImpl &Output, void *Cookie, ArrayRef QualTypeVals); + + /// Returns a desugared version of the QualType, and marks ShouldAKA as true + /// whenever we remove significant sugar from the type. + QualType Desugar(ASTContext &Context, QualType QT, bool &ShouldAKA); } // end namespace clang #endif diff --git a/clang/lib/AST/ASTDiagnostic.cpp b/clang/lib/AST/ASTDiagnostic.cpp --- a/clang/lib/AST/ASTDiagnostic.cpp +++ b/clang/lib/AST/ASTDiagnostic.cpp @@ -26,7 +26,7 @@ // Returns a desugared version of the QualType, and marks ShouldAKA as true // whenever we remove significant sugar from the type. -static QualType Desugar(ASTContext &Context, QualType QT, bool &ShouldAKA) { +QualType clang::Desugar(ASTContext &Context, QualType QT, bool &ShouldAKA) { QualifierCollector QC; while (true) {