Author: ibiryukov Date: Wed Nov 8 02:39:03 2017 New Revision: 317676 URL: http://llvm.org/viewvc/llvm-project?rev=317676&view=rev Log: Moved QualTypeNames.h from Tooling to AST.
Summary: For code reuse in SemaCodeComplete. Note that the tests for QualTypeNames are still in Tooling as they use Tooling's common testing code. Reviewers: rsmith, saugustine, rnk, klimek, bkramer Reviewed By: rnk Subscribers: cfe-commits, mgorny Differential Revision: https://reviews.llvm.org/D39224 Added: cfe/trunk/include/clang/AST/QualTypeNames.h - copied, changed from r317672, cfe/trunk/include/clang/Tooling/Core/QualTypeNames.h cfe/trunk/lib/AST/QualTypeNames.cpp - copied, changed from r317672, cfe/trunk/lib/Tooling/Core/QualTypeNames.cpp Removed: cfe/trunk/include/clang/Tooling/Core/QualTypeNames.h cfe/trunk/lib/Tooling/Core/QualTypeNames.cpp Modified: cfe/trunk/lib/AST/CMakeLists.txt cfe/trunk/lib/Tooling/Core/CMakeLists.txt cfe/trunk/unittests/Tooling/QualTypeNamesTest.cpp Copied: cfe/trunk/include/clang/AST/QualTypeNames.h (from r317672, cfe/trunk/include/clang/Tooling/Core/QualTypeNames.h) URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/QualTypeNames.h?p2=cfe/trunk/include/clang/AST/QualTypeNames.h&p1=cfe/trunk/include/clang/Tooling/Core/QualTypeNames.h&r1=317672&r2=317676&rev=317676&view=diff ============================================================================== --- cfe/trunk/include/clang/Tooling/Core/QualTypeNames.h (original) +++ cfe/trunk/include/clang/AST/QualTypeNames.h Wed Nov 8 02:39:03 2017 @@ -56,8 +56,8 @@ // // ===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_TOOLING_CORE_QUALTYPENAMES_H -#define LLVM_CLANG_TOOLING_CORE_QUALTYPENAMES_H +#ifndef LLVM_CLANG_AST_QUALTYPENAMES_H +#define LLVM_CLANG_AST_QUALTYPENAMES_H #include "clang/AST/ASTContext.h" @@ -71,9 +71,20 @@ namespace TypeName { /// \param[in] Ctx - the ASTContext to be used. /// \param[in] WithGlobalNsPrefix - If true, then the global namespace /// specifier "::" will be prepended to the fully qualified name. -std::string getFullyQualifiedName(QualType QT, - const ASTContext &Ctx, +std::string getFullyQualifiedName(QualType QT, const ASTContext &Ctx, bool WithGlobalNsPrefix = false); -} // end namespace TypeName -} // end namespace clang -#endif // LLVM_CLANG_TOOLING_CORE_QUALTYPENAMES_H + +/// \brief Generates a QualType that can be used to name the same type +/// if used at the end of the current translation unit. This ignores +/// issues such as type shadowing. +/// +/// \param[in] QT - the type for which the fully qualified type will be +/// returned. +/// \param[in] Ctx - the ASTContext to be used. +/// \param[in] WithGlobalNsPrefix - Indicate whether the global namespace +/// specifier "::" should be prepended or not. +QualType getFullyQualifiedType(QualType QT, const ASTContext &Ctx, + bool WithGlobalNsPrefix = false); +} // end namespace TypeName +} // end namespace clang +#endif // LLVM_CLANG_TOOLING_CORE_QUALTYPENAMES_H Removed: cfe/trunk/include/clang/Tooling/Core/QualTypeNames.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Tooling/Core/QualTypeNames.h?rev=317675&view=auto ============================================================================== --- cfe/trunk/include/clang/Tooling/Core/QualTypeNames.h (original) +++ cfe/trunk/include/clang/Tooling/Core/QualTypeNames.h (removed) @@ -1,79 +0,0 @@ -//===--- QualTypeNames.h - Generate Complete QualType Names ----*- C++ -*-===// -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -// ===----------------------------------------------------------------------===// -// -// \file -// Functionality to generate the fully-qualified names of QualTypes, -// including recursively expanding any subtypes and template -// parameters. -// -// More precisely: Generates a name that can be used to name the same -// type if used at the end of the current translation unit--with -// certain limitations. See below. -// -// This code desugars names only very minimally, so in this code: -// -// namespace A { -// struct X {}; -// } -// using A::X; -// namespace B { -// using std::tuple; -// typedef tuple<X> TX; -// TX t; -// } -// -// B::t's type is reported as "B::TX", rather than std::tuple<A::X>. -// -// Also, this code replaces types found via using declarations with -// their more qualified name, so for the code: -// -// using std::tuple; -// tuple<int> TInt; -// -// TInt's type will be named, "std::tuple<int>". -// -// Limitations: -// -// Some types have ambiguous names at the end of a translation unit, -// are not namable at all there, or are special cases in other ways. -// -// 1) Types with only local scope will have their local names: -// -// void foo() { -// struct LocalType {} LocalVar; -// } -// -// LocalVar's type will be named, "struct LocalType", without any -// qualification. -// -// 2) Types that have been shadowed are reported normally, but a -// client using that name at the end of the translation unit will be -// referring to a different type. -// -// ===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_TOOLING_CORE_QUALTYPENAMES_H -#define LLVM_CLANG_TOOLING_CORE_QUALTYPENAMES_H - -#include "clang/AST/ASTContext.h" - -namespace clang { -namespace TypeName { -/// \brief Get the fully qualified name for a type. This includes full -/// qualification of all template parameters etc. -/// -/// \param[in] QT - the type for which the fully qualified name will be -/// returned. -/// \param[in] Ctx - the ASTContext to be used. -/// \param[in] WithGlobalNsPrefix - If true, then the global namespace -/// specifier "::" will be prepended to the fully qualified name. -std::string getFullyQualifiedName(QualType QT, - const ASTContext &Ctx, - bool WithGlobalNsPrefix = false); -} // end namespace TypeName -} // end namespace clang -#endif // LLVM_CLANG_TOOLING_CORE_QUALTYPENAMES_H Modified: cfe/trunk/lib/AST/CMakeLists.txt URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/CMakeLists.txt?rev=317676&r1=317675&r2=317676&view=diff ============================================================================== --- cfe/trunk/lib/AST/CMakeLists.txt (original) +++ cfe/trunk/lib/AST/CMakeLists.txt Wed Nov 8 02:39:03 2017 @@ -49,6 +49,7 @@ add_clang_library(clangAST ODRHash.cpp OpenMPClause.cpp ParentMap.cpp + QualTypeNames.cpp RawCommentList.cpp RecordLayout.cpp RecordLayoutBuilder.cpp Copied: cfe/trunk/lib/AST/QualTypeNames.cpp (from r317672, cfe/trunk/lib/Tooling/Core/QualTypeNames.cpp) URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/QualTypeNames.cpp?p2=cfe/trunk/lib/AST/QualTypeNames.cpp&p1=cfe/trunk/lib/Tooling/Core/QualTypeNames.cpp&r1=317672&r2=317676&rev=317676&view=diff ============================================================================== --- cfe/trunk/lib/Tooling/Core/QualTypeNames.cpp (original) +++ cfe/trunk/lib/AST/QualTypeNames.cpp Wed Nov 8 02:39:03 2017 @@ -9,11 +9,11 @@ // //===----------------------------------------------------------------------===// -#include "clang/Tooling/Core/QualTypeNames.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/DeclarationName.h" #include "clang/AST/GlobalDecl.h" #include "clang/AST/Mangle.h" +#include "clang/AST/QualTypeNames.h" #include <stdio.h> #include <memory> @@ -21,17 +21,6 @@ namespace clang { namespace TypeName { -/// \brief Generates a QualType that can be used to name the same type -/// if used at the end of the current translation unit. This ignores -/// issues such as type shadowing. -/// -/// \param[in] QT - the type for which the fully qualified type will be -/// returned. -/// \param[in] Ctx - the ASTContext to be used. -/// \param[in] WithGlobalNsPrefix - Indicate whether the global namespace -/// specifier "::" should be prepended or not. -static QualType getFullyQualifiedType(QualType QT, const ASTContext &Ctx, - bool WithGlobalNsPrefix); /// \brief Create a NestedNameSpecifier for Namesp and its enclosing /// scopes. Modified: cfe/trunk/lib/Tooling/Core/CMakeLists.txt URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Tooling/Core/CMakeLists.txt?rev=317676&r1=317675&r2=317676&view=diff ============================================================================== --- cfe/trunk/lib/Tooling/Core/CMakeLists.txt (original) +++ cfe/trunk/lib/Tooling/Core/CMakeLists.txt Wed Nov 8 02:39:03 2017 @@ -3,7 +3,6 @@ set(LLVM_LINK_COMPONENTS support) add_clang_library(clangToolingCore Lookup.cpp Replacement.cpp - QualTypeNames.cpp Diagnostic.cpp LINK_LIBS Removed: cfe/trunk/lib/Tooling/Core/QualTypeNames.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Tooling/Core/QualTypeNames.cpp?rev=317675&view=auto ============================================================================== --- cfe/trunk/lib/Tooling/Core/QualTypeNames.cpp (original) +++ cfe/trunk/lib/Tooling/Core/QualTypeNames.cpp (removed) @@ -1,477 +0,0 @@ -//===------- QualTypeNames.cpp - Generate Complete QualType Names ---------===// -// -// The LLVM Compiler Infrastructure -// -//===----------------------------------------------------------------------===// -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "clang/Tooling/Core/QualTypeNames.h" -#include "clang/AST/DeclTemplate.h" -#include "clang/AST/DeclarationName.h" -#include "clang/AST/GlobalDecl.h" -#include "clang/AST/Mangle.h" - -#include <stdio.h> -#include <memory> - -namespace clang { - -namespace TypeName { -/// \brief Generates a QualType that can be used to name the same type -/// if used at the end of the current translation unit. This ignores -/// issues such as type shadowing. -/// -/// \param[in] QT - the type for which the fully qualified type will be -/// returned. -/// \param[in] Ctx - the ASTContext to be used. -/// \param[in] WithGlobalNsPrefix - Indicate whether the global namespace -/// specifier "::" should be prepended or not. -static QualType getFullyQualifiedType(QualType QT, const ASTContext &Ctx, - bool WithGlobalNsPrefix); - -/// \brief Create a NestedNameSpecifier for Namesp and its enclosing -/// scopes. -/// -/// \param[in] Ctx - the AST Context to be used. -/// \param[in] Namesp - the NamespaceDecl for which a NestedNameSpecifier -/// is requested. -/// \param[in] WithGlobalNsPrefix - Indicate whether the global namespace -/// specifier "::" should be prepended or not. -static NestedNameSpecifier *createNestedNameSpecifier( - const ASTContext &Ctx, - const NamespaceDecl *Namesp, - bool WithGlobalNsPrefix); - -/// \brief Create a NestedNameSpecifier for TagDecl and its enclosing -/// scopes. -/// -/// \param[in] Ctx - the AST Context to be used. -/// \param[in] TD - the TagDecl for which a NestedNameSpecifier is -/// requested. -/// \param[in] FullyQualify - Convert all template arguments into fully -/// qualified names. -/// \param[in] WithGlobalNsPrefix - Indicate whether the global namespace -/// specifier "::" should be prepended or not. -static NestedNameSpecifier *createNestedNameSpecifier( - const ASTContext &Ctx, const TypeDecl *TD, - bool FullyQualify, bool WithGlobalNsPrefix); - -static NestedNameSpecifier *createNestedNameSpecifierForScopeOf( - const ASTContext &Ctx, const Decl *decl, - bool FullyQualified, bool WithGlobalNsPrefix); - -static NestedNameSpecifier *getFullyQualifiedNestedNameSpecifier( - const ASTContext &Ctx, NestedNameSpecifier *scope, bool WithGlobalNsPrefix); - -static bool getFullyQualifiedTemplateName(const ASTContext &Ctx, - TemplateName &TName, - bool WithGlobalNsPrefix) { - bool Changed = false; - NestedNameSpecifier *NNS = nullptr; - - TemplateDecl *ArgTDecl = TName.getAsTemplateDecl(); - // ArgTDecl won't be NULL because we asserted that this isn't a - // dependent context very early in the call chain. - assert(ArgTDecl != nullptr); - QualifiedTemplateName *QTName = TName.getAsQualifiedTemplateName(); - - if (QTName && !QTName->hasTemplateKeyword()) { - NNS = QTName->getQualifier(); - NestedNameSpecifier *QNNS = getFullyQualifiedNestedNameSpecifier( - Ctx, NNS, WithGlobalNsPrefix); - if (QNNS != NNS) { - Changed = true; - NNS = QNNS; - } else { - NNS = nullptr; - } - } else { - NNS = createNestedNameSpecifierForScopeOf( - Ctx, ArgTDecl, true, WithGlobalNsPrefix); - } - if (NNS) { - TName = Ctx.getQualifiedTemplateName(NNS, - /*TemplateKeyword=*/false, ArgTDecl); - Changed = true; - } - return Changed; -} - -static bool getFullyQualifiedTemplateArgument(const ASTContext &Ctx, - TemplateArgument &Arg, - bool WithGlobalNsPrefix) { - bool Changed = false; - - // Note: we do not handle TemplateArgument::Expression, to replace it - // we need the information for the template instance decl. - - if (Arg.getKind() == TemplateArgument::Template) { - TemplateName TName = Arg.getAsTemplate(); - Changed = getFullyQualifiedTemplateName(Ctx, TName, WithGlobalNsPrefix); - if (Changed) { - Arg = TemplateArgument(TName); - } - } else if (Arg.getKind() == TemplateArgument::Type) { - QualType SubTy = Arg.getAsType(); - // Check if the type needs more desugaring and recurse. - QualType QTFQ = getFullyQualifiedType(SubTy, Ctx, WithGlobalNsPrefix); - if (QTFQ != SubTy) { - Arg = TemplateArgument(QTFQ); - Changed = true; - } - } - return Changed; -} - -static const Type *getFullyQualifiedTemplateType(const ASTContext &Ctx, - const Type *TypePtr, - bool WithGlobalNsPrefix) { - // DependentTemplateTypes exist within template declarations and - // definitions. Therefore we shouldn't encounter them at the end of - // a translation unit. If we do, the caller has made an error. - assert(!isa<DependentTemplateSpecializationType>(TypePtr)); - // In case of template specializations, iterate over the arguments - // and fully qualify them as well. - if (const auto *TST = dyn_cast<const TemplateSpecializationType>(TypePtr)) { - bool MightHaveChanged = false; - SmallVector<TemplateArgument, 4> FQArgs; - for (TemplateSpecializationType::iterator I = TST->begin(), E = TST->end(); - I != E; ++I) { - // Cheap to copy and potentially modified by - // getFullyQualifedTemplateArgument. - TemplateArgument Arg(*I); - MightHaveChanged |= getFullyQualifiedTemplateArgument( - Ctx, Arg, WithGlobalNsPrefix); - FQArgs.push_back(Arg); - } - - // If a fully qualified arg is different from the unqualified arg, - // allocate new type in the AST. - if (MightHaveChanged) { - QualType QT = Ctx.getTemplateSpecializationType( - TST->getTemplateName(), FQArgs, - TST->getCanonicalTypeInternal()); - // getTemplateSpecializationType returns a fully qualified - // version of the specialization itself, so no need to qualify - // it. - return QT.getTypePtr(); - } - } else if (const auto *TSTRecord = dyn_cast<const RecordType>(TypePtr)) { - // We are asked to fully qualify and we have a Record Type, - // which can point to a template instantiation with no sugar in any of - // its template argument, however we still need to fully qualify them. - - if (const auto *TSTDecl = - dyn_cast<ClassTemplateSpecializationDecl>(TSTRecord->getDecl())) { - const TemplateArgumentList &TemplateArgs = TSTDecl->getTemplateArgs(); - - bool MightHaveChanged = false; - SmallVector<TemplateArgument, 4> FQArgs; - for (unsigned int I = 0, E = TemplateArgs.size(); I != E; ++I) { - // cheap to copy and potentially modified by - // getFullyQualifedTemplateArgument - TemplateArgument Arg(TemplateArgs[I]); - MightHaveChanged |= getFullyQualifiedTemplateArgument( - Ctx, Arg, WithGlobalNsPrefix); - FQArgs.push_back(Arg); - } - - // If a fully qualified arg is different from the unqualified arg, - // allocate new type in the AST. - if (MightHaveChanged) { - TemplateName TN(TSTDecl->getSpecializedTemplate()); - QualType QT = Ctx.getTemplateSpecializationType( - TN, FQArgs, - TSTRecord->getCanonicalTypeInternal()); - // getTemplateSpecializationType returns a fully qualified - // version of the specialization itself, so no need to qualify - // it. - return QT.getTypePtr(); - } - } - } - return TypePtr; -} - -static NestedNameSpecifier *createOuterNNS(const ASTContext &Ctx, const Decl *D, - bool FullyQualify, - bool WithGlobalNsPrefix) { - const DeclContext *DC = D->getDeclContext(); - if (const auto *NS = dyn_cast<NamespaceDecl>(DC)) { - while (NS && NS->isInline()) { - // Ignore inline namespace; - NS = dyn_cast<NamespaceDecl>(NS->getDeclContext()); - } - if (NS->getDeclName()) { - return createNestedNameSpecifier(Ctx, NS, WithGlobalNsPrefix); - } - return nullptr; // no starting '::', no anonymous - } else if (const auto *TD = dyn_cast<TagDecl>(DC)) { - return createNestedNameSpecifier(Ctx, TD, FullyQualify, WithGlobalNsPrefix); - } else if (const auto *TDD = dyn_cast<TypedefNameDecl>(DC)) { - return createNestedNameSpecifier( - Ctx, TDD, FullyQualify, WithGlobalNsPrefix); - } else if (WithGlobalNsPrefix && DC->isTranslationUnit()) { - return NestedNameSpecifier::GlobalSpecifier(Ctx); - } - return nullptr; // no starting '::' if |WithGlobalNsPrefix| is false -} - -/// \brief Return a fully qualified version of this name specifier. -static NestedNameSpecifier *getFullyQualifiedNestedNameSpecifier( - const ASTContext &Ctx, NestedNameSpecifier *Scope, - bool WithGlobalNsPrefix) { - switch (Scope->getKind()) { - case NestedNameSpecifier::Global: - // Already fully qualified - return Scope; - case NestedNameSpecifier::Namespace: - return TypeName::createNestedNameSpecifier( - Ctx, Scope->getAsNamespace(), WithGlobalNsPrefix); - case NestedNameSpecifier::NamespaceAlias: - // Namespace aliases are only valid for the duration of the - // scope where they were introduced, and therefore are often - // invalid at the end of the TU. So use the namespace name more - // likely to be valid at the end of the TU. - return TypeName::createNestedNameSpecifier( - Ctx, - Scope->getAsNamespaceAlias()->getNamespace()->getCanonicalDecl(), - WithGlobalNsPrefix); - case NestedNameSpecifier::Identifier: - // A function or some other construct that makes it un-namable - // at the end of the TU. Skip the current component of the name, - // but use the name of it's prefix. - return getFullyQualifiedNestedNameSpecifier( - Ctx, Scope->getPrefix(), WithGlobalNsPrefix); - case NestedNameSpecifier::Super: - case NestedNameSpecifier::TypeSpec: - case NestedNameSpecifier::TypeSpecWithTemplate: { - const Type *Type = Scope->getAsType(); - // Find decl context. - const TagDecl *TD = nullptr; - if (const TagType *TagDeclType = Type->getAs<TagType>()) { - TD = TagDeclType->getDecl(); - } else { - TD = Type->getAsCXXRecordDecl(); - } - if (TD) { - return TypeName::createNestedNameSpecifier(Ctx, TD, - true /*FullyQualified*/, - WithGlobalNsPrefix); - } else if (const auto *TDD = dyn_cast<TypedefType>(Type)) { - return TypeName::createNestedNameSpecifier(Ctx, TDD->getDecl(), - true /*FullyQualified*/, - WithGlobalNsPrefix); - } - return Scope; - } - } - llvm_unreachable("bad NNS kind"); -} - -/// \brief Create a nested name specifier for the declaring context of -/// the type. -static NestedNameSpecifier *createNestedNameSpecifierForScopeOf( - const ASTContext &Ctx, const Decl *Decl, - bool FullyQualified, bool WithGlobalNsPrefix) { - assert(Decl); - - const DeclContext *DC = Decl->getDeclContext()->getRedeclContext(); - const auto *Outer = dyn_cast_or_null<NamedDecl>(DC); - const auto *OuterNS = dyn_cast_or_null<NamespaceDecl>(DC); - if (Outer && !(OuterNS && OuterNS->isAnonymousNamespace())) { - if (const auto *CxxDecl = dyn_cast<CXXRecordDecl>(DC)) { - if (ClassTemplateDecl *ClassTempl = - CxxDecl->getDescribedClassTemplate()) { - // We are in the case of a type(def) that was declared in a - // class template but is *not* type dependent. In clang, it - // gets attached to the class template declaration rather than - // any specific class template instantiation. This result in - // 'odd' fully qualified typename: - // - // vector<_Tp,_Alloc>::size_type - // - // Make the situation is 'useable' but looking a bit odd by - // picking a random instance as the declaring context. - if (ClassTempl->spec_begin() != ClassTempl->spec_end()) { - Decl = *(ClassTempl->spec_begin()); - Outer = dyn_cast<NamedDecl>(Decl); - OuterNS = dyn_cast<NamespaceDecl>(Decl); - } - } - } - - if (OuterNS) { - return createNestedNameSpecifier(Ctx, OuterNS, WithGlobalNsPrefix); - } else if (const auto *TD = dyn_cast<TagDecl>(Outer)) { - return createNestedNameSpecifier( - Ctx, TD, FullyQualified, WithGlobalNsPrefix); - } else if (dyn_cast<TranslationUnitDecl>(Outer)) { - // Context is the TU. Nothing needs to be done. - return nullptr; - } else { - // Decl's context was neither the TU, a namespace, nor a - // TagDecl, which means it is a type local to a scope, and not - // accessible at the end of the TU. - return nullptr; - } - } else if (WithGlobalNsPrefix && DC->isTranslationUnit()) { - return NestedNameSpecifier::GlobalSpecifier(Ctx); - } - return nullptr; -} - -/// \brief Create a nested name specifier for the declaring context of -/// the type. -static NestedNameSpecifier *createNestedNameSpecifierForScopeOf( - const ASTContext &Ctx, const Type *TypePtr, - bool FullyQualified, bool WithGlobalNsPrefix) { - if (!TypePtr) return nullptr; - - Decl *Decl = nullptr; - // There are probably other cases ... - if (const auto *TDT = dyn_cast<TypedefType>(TypePtr)) { - Decl = TDT->getDecl(); - } else if (const auto *TagDeclType = dyn_cast<TagType>(TypePtr)) { - Decl = TagDeclType->getDecl(); - } else if (const auto *TST = dyn_cast<TemplateSpecializationType>(TypePtr)) { - Decl = TST->getTemplateName().getAsTemplateDecl(); - } else { - Decl = TypePtr->getAsCXXRecordDecl(); - } - - if (!Decl) return nullptr; - - return createNestedNameSpecifierForScopeOf( - Ctx, Decl, FullyQualified, WithGlobalNsPrefix); -} - -NestedNameSpecifier *createNestedNameSpecifier(const ASTContext &Ctx, - const NamespaceDecl *Namespace, - bool WithGlobalNsPrefix) { - while (Namespace && Namespace->isInline()) { - // Ignore inline namespace; - Namespace = dyn_cast<NamespaceDecl>(Namespace->getDeclContext()); - } - if (!Namespace) return nullptr; - - bool FullyQualified = true; // doesn't matter, DeclContexts are namespaces - return NestedNameSpecifier::Create( - Ctx, - createOuterNNS(Ctx, Namespace, FullyQualified, WithGlobalNsPrefix), - Namespace); -} - -NestedNameSpecifier *createNestedNameSpecifier(const ASTContext &Ctx, - const TypeDecl *TD, - bool FullyQualify, - bool WithGlobalNsPrefix) { - return NestedNameSpecifier::Create( - Ctx, - createOuterNNS(Ctx, TD, FullyQualify, WithGlobalNsPrefix), - false /*No TemplateKeyword*/, - TD->getTypeForDecl()); -} - -/// \brief Return the fully qualified type, including fully-qualified -/// versions of any template parameters. -QualType getFullyQualifiedType(QualType QT, const ASTContext &Ctx, - bool WithGlobalNsPrefix) { - // In case of myType* we need to strip the pointer first, fully - // qualify and attach the pointer once again. - if (isa<PointerType>(QT.getTypePtr())) { - // Get the qualifiers. - Qualifiers Quals = QT.getQualifiers(); - QT = getFullyQualifiedType(QT->getPointeeType(), Ctx, WithGlobalNsPrefix); - QT = Ctx.getPointerType(QT); - // Add back the qualifiers. - QT = Ctx.getQualifiedType(QT, Quals); - return QT; - } - - // In case of myType& we need to strip the reference first, fully - // qualify and attach the reference once again. - if (isa<ReferenceType>(QT.getTypePtr())) { - // Get the qualifiers. - bool IsLValueRefTy = isa<LValueReferenceType>(QT.getTypePtr()); - Qualifiers Quals = QT.getQualifiers(); - QT = getFullyQualifiedType(QT->getPointeeType(), Ctx, WithGlobalNsPrefix); - // Add the r- or l-value reference type back to the fully - // qualified one. - if (IsLValueRefTy) - QT = Ctx.getLValueReferenceType(QT); - else - QT = Ctx.getRValueReferenceType(QT); - // Add back the qualifiers. - QT = Ctx.getQualifiedType(QT, Quals); - return QT; - } - - // Remove the part of the type related to the type being a template - // parameter (we won't report it as part of the 'type name' and it - // is actually make the code below to be more complex (to handle - // those) - while (isa<SubstTemplateTypeParmType>(QT.getTypePtr())) { - // Get the qualifiers. - Qualifiers Quals = QT.getQualifiers(); - - QT = dyn_cast<SubstTemplateTypeParmType>(QT.getTypePtr())->desugar(); - - // Add back the qualifiers. - QT = Ctx.getQualifiedType(QT, Quals); - } - - NestedNameSpecifier *Prefix = nullptr; - // Local qualifiers are attached to the QualType outside of the - // elaborated type. Retrieve them before descending into the - // elaborated type. - Qualifiers PrefixQualifiers = QT.getLocalQualifiers(); - QT = QualType(QT.getTypePtr(), 0); - ElaboratedTypeKeyword Keyword = ETK_None; - if (const auto *ETypeInput = dyn_cast<ElaboratedType>(QT.getTypePtr())) { - QT = ETypeInput->getNamedType(); - assert(!QT.hasLocalQualifiers()); - Keyword = ETypeInput->getKeyword(); - } - // Create a nested name specifier if needed. - Prefix = createNestedNameSpecifierForScopeOf(Ctx, QT.getTypePtr(), - true /*FullyQualified*/, - WithGlobalNsPrefix); - - // In case of template specializations iterate over the arguments and - // fully qualify them as well. - if (isa<const TemplateSpecializationType>(QT.getTypePtr()) || - isa<const RecordType>(QT.getTypePtr())) { - // We are asked to fully qualify and we have a Record Type (which - // may point to a template specialization) or Template - // Specialization Type. We need to fully qualify their arguments. - - const Type *TypePtr = getFullyQualifiedTemplateType( - Ctx, QT.getTypePtr(), WithGlobalNsPrefix); - QT = QualType(TypePtr, 0); - } - if (Prefix || Keyword != ETK_None) { - QT = Ctx.getElaboratedType(Keyword, Prefix, QT); - } - QT = Ctx.getQualifiedType(QT, PrefixQualifiers); - return QT; -} - -std::string getFullyQualifiedName(QualType QT, - const ASTContext &Ctx, - bool WithGlobalNsPrefix) { - PrintingPolicy Policy(Ctx.getPrintingPolicy()); - Policy.SuppressScope = false; - Policy.AnonymousTagLocations = false; - Policy.PolishForDeclaration = true; - Policy.SuppressUnwrittenScope = true; - QualType FQQT = getFullyQualifiedType(QT, Ctx, WithGlobalNsPrefix); - return FQQT.getAsString(Policy); -} - -} // end namespace TypeName -} // end namespace clang Modified: cfe/trunk/unittests/Tooling/QualTypeNamesTest.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Tooling/QualTypeNamesTest.cpp?rev=317676&r1=317675&r2=317676&view=diff ============================================================================== --- cfe/trunk/unittests/Tooling/QualTypeNamesTest.cpp (original) +++ cfe/trunk/unittests/Tooling/QualTypeNamesTest.cpp Wed Nov 8 02:39:03 2017 @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// -#include "clang/Tooling/Core/QualTypeNames.h" +#include "clang/AST/QualTypeNames.h" #include "TestVisitor.h" using namespace clang; _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits