Index: clang-tools-extra/clangd/FindTarget.cpp =================================================================== --- clang-tools-extra/clangd/FindTarget.cpp +++ clang-tools-extra/clangd/FindTarget.cpp @@ -181,6 +181,9 @@ for (const UsingShadowDecl *S : UD->shadows()) add(S->getUnderlyingDecl(), Flags); Flags |= Rel::Alias; // continue with the alias. + } else if (const UsingEnumDecl *UED = dyn_cast(D)) { + add(UED->getEnumDecl(), Flags); + Flags |= Rel::Alias; // continue with the alias. } else if (const auto *NAD = dyn_cast(D)) { add(NAD->getUnderlyingDecl(), Flags | Rel::Underlying); Flags |= Rel::Alias; // continue with the alias Index: clang/include/clang/AST/ASTContext.h =================================================================== --- clang/include/clang/AST/ASTContext.h +++ clang/include/clang/AST/ASTContext.h @@ -517,6 +517,12 @@ /// B to the UnresolvedUsingDecl in B. llvm::DenseMap InstantiatedFromUsingDecl; + /// Like InstantiatedFromUsingDecl, but for using-enum declarations. Maps + /// from the instantiated using-enum to the templated decl from whence it + /// came. + llvm::DenseMap InstantiatedFromUsingEnumDecl; + + /// Simlarly maps instantiated UsingShadowDecls to their origin. llvm::DenseMap InstantiatedFromUsingShadowDecl; @@ -885,15 +891,15 @@ MemberSpecializationInfo *getInstantiatedFromStaticDataMember( const VarDecl *Var); - TemplateOrSpecializationInfo - getTemplateOrSpecializationInfo(const VarDecl *Var); - /// Note that the static data member \p Inst is an instantiation of /// the static data member template \p Tmpl of a class template. void setInstantiatedFromStaticDataMember(VarDecl *Inst, VarDecl *Tmpl, TemplateSpecializationKind TSK, SourceLocation PointOfInstantiation = SourceLocation()); + TemplateOrSpecializationInfo + getTemplateOrSpecializationInfo(const VarDecl *Var); + void setTemplateOrSpecializationInfo(VarDecl *Inst, TemplateOrSpecializationInfo TSI); @@ -906,9 +912,18 @@ /// of the using decl \p Pattern of a class template. void setInstantiatedFromUsingDecl(NamedDecl *Inst, NamedDecl *Pattern); + /// If the given using-enum decl \p Inst is an instantiation of a + /// (possibly unresolved) using decl from a template instantiation, + /// return it. + NamedDecl *getInstantiatedFromUsingEnumDecl(NamedDecl *Inst); + + /// Remember that the using enum decl \p Inst is an instantiation + /// of the using enum decl \p Pattern of a class template. + void setInstantiatedFromUsingEnumDecl(NamedDecl *Inst, NamedDecl *Pattern); + + UsingShadowDecl *getInstantiatedFromUsingShadowDecl(UsingShadowDecl *Inst); void setInstantiatedFromUsingShadowDecl(UsingShadowDecl *Inst, UsingShadowDecl *Pattern); - UsingShadowDecl *getInstantiatedFromUsingShadowDecl(UsingShadowDecl *Inst); FieldDecl *getInstantiatedFromUnnamedFieldDecl(FieldDecl *Field); Index: clang/include/clang/AST/DeclCXX.h =================================================================== --- clang/include/clang/AST/DeclCXX.h +++ clang/include/clang/AST/DeclCXX.h @@ -3356,7 +3356,7 @@ void removeShadowDecl(UsingShadowDecl *S); static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classofKind(Kind K) { return K == Using; } + static bool classofKind(Kind K) { return K == Using || K == UsingEnum; } }; /// Represents a shadow constructor declaration introduced into a @@ -3552,6 +3552,65 @@ static bool classofKind(Kind K) { return K == Using; } }; +/// Represents a C++ using-enum-declaration. +/// +/// For example: +/// \code +/// using enum SomeEnumTag ; +/// \endcode + +class UsingEnumDecl : public BaseUsingDecl, public Mergeable { + /// The source location of the 'using' keyword itself. + SourceLocation UsingLocation; + + /// Location of the 'enum' keyword. + SourceLocation EnumLocation; + + /// The enum + EnumDecl *Enum; + + UsingEnumDecl(DeclContext *DC, SourceLocation UL, SourceLocation EL, + SourceLocation NL, EnumDecl *ED) + : BaseUsingDecl(UsingEnum, DC, NL, ED->getDeclName()), UsingLocation(UL), + EnumLocation(EL), Enum(ED) {} + + void anchor() override; + +public: + friend class ASTDeclReader; + friend class ASTDeclWriter; + + /// The source location of the 'using' keyword. + SourceLocation getUsingLoc() const { return UsingLocation; } + void setUsingLoc(SourceLocation L) { UsingLocation = L; } + + /// The source location of the 'enum' keyword. + SourceLocation getEnumLoc() const { return EnumLocation; } + void setEnumLoc(SourceLocation L) { EnumLocation = L; } + +public: + EnumDecl *getEnumDecl() const { return Enum; } + + static UsingEnumDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation UsingL, SourceLocation EnumL, + SourceLocation NameL, EnumDecl *ED); + + static UsingEnumDecl *CreateDeserialized(ASTContext &C, unsigned ID); + + SourceRange getSourceRange() const override LLVM_READONLY; + + /// Retrieves the canonical declaration of this declaration. + UsingEnumDecl *getCanonicalDecl() override { + return cast(getFirstDecl()); + } + const UsingEnumDecl *getCanonicalDecl() const { + return cast(getFirstDecl()); + } + + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classofKind(Kind K) { return K == UsingEnum; } +}; + /// Represents a pack of using declarations that a single /// using-declarator pack-expanded into. /// Index: clang/include/clang/AST/JSONNodeDumper.h =================================================================== --- clang/include/clang/AST/JSONNodeDumper.h +++ clang/include/clang/AST/JSONNodeDumper.h @@ -234,6 +234,7 @@ void VisitUsingDirectiveDecl(const UsingDirectiveDecl *UDD); void VisitNamespaceAliasDecl(const NamespaceAliasDecl *NAD); void VisitUsingDecl(const UsingDecl *UD); + void VisitUsingEnumDecl(const UsingEnumDecl *UED); void VisitUsingShadowDecl(const UsingShadowDecl *USD); void VisitVarDecl(const VarDecl *VD); void VisitFieldDecl(const FieldDecl *FD); Index: clang/include/clang/AST/RecursiveASTVisitor.h =================================================================== --- clang/include/clang/AST/RecursiveASTVisitor.h +++ clang/include/clang/AST/RecursiveASTVisitor.h @@ -1593,6 +1593,8 @@ TRY_TO(TraverseDeclarationNameInfo(D->getNameInfo())); }) +DEF_TRAVERSE_DECL(UsingEnumDecl, {}) + DEF_TRAVERSE_DECL(UsingPackDecl, {}) DEF_TRAVERSE_DECL(UsingDirectiveDecl, { Index: clang/include/clang/AST/TextNodeDumper.h =================================================================== --- clang/include/clang/AST/TextNodeDumper.h +++ clang/include/clang/AST/TextNodeDumper.h @@ -350,6 +350,7 @@ void VisitUsingDecl(const UsingDecl *D); void VisitUnresolvedUsingTypenameDecl(const UnresolvedUsingTypenameDecl *D); void VisitUnresolvedUsingValueDecl(const UnresolvedUsingValueDecl *D); + void VisitUsingEnumDecl(const UsingEnumDecl *D); void VisitUsingShadowDecl(const UsingShadowDecl *D); void VisitConstructorUsingShadowDecl(const ConstructorUsingShadowDecl *D); void VisitLinkageSpecDecl(const LinkageSpecDecl *D); Index: clang/include/clang/Basic/DeclNodes.td =================================================================== --- clang/include/clang/Basic/DeclNodes.td +++ clang/include/clang/Basic/DeclNodes.td @@ -73,6 +73,7 @@ def Concept : DeclNode