This revision was automatically updated to reflect the committed changes.
Closed by commit rL317676: Moved QualTypeNames.h from Tooling to AST. (authored 
by ibiryukov).

Changed prior to commit:
  https://reviews.llvm.org/D39224?vs=120014&id=122044#toc

Repository:
  rL LLVM

https://reviews.llvm.org/D39224

Files:
  cfe/trunk/include/clang/AST/QualTypeNames.h
  cfe/trunk/include/clang/Tooling/Core/QualTypeNames.h
  cfe/trunk/lib/AST/CMakeLists.txt
  cfe/trunk/lib/AST/QualTypeNames.cpp
  cfe/trunk/lib/Tooling/Core/CMakeLists.txt
  cfe/trunk/lib/Tooling/Core/QualTypeNames.cpp
  cfe/trunk/unittests/Tooling/QualTypeNamesTest.cpp

Index: cfe/trunk/lib/Tooling/Core/CMakeLists.txt
===================================================================
--- cfe/trunk/lib/Tooling/Core/CMakeLists.txt
+++ cfe/trunk/lib/Tooling/Core/CMakeLists.txt
@@ -3,7 +3,6 @@
 add_clang_library(clangToolingCore
   Lookup.cpp
   Replacement.cpp
-  QualTypeNames.cpp
   Diagnostic.cpp
 
   LINK_LIBS
Index: cfe/trunk/lib/AST/CMakeLists.txt
===================================================================
--- cfe/trunk/lib/AST/CMakeLists.txt
+++ cfe/trunk/lib/AST/CMakeLists.txt
@@ -49,6 +49,7 @@
   ODRHash.cpp
   OpenMPClause.cpp
   ParentMap.cpp
+  QualTypeNames.cpp
   RawCommentList.cpp
   RecordLayout.cpp
   RecordLayoutBuilder.cpp
Index: cfe/trunk/lib/AST/QualTypeNames.cpp
===================================================================
--- cfe/trunk/lib/AST/QualTypeNames.cpp
+++ cfe/trunk/lib/AST/QualTypeNames.cpp
@@ -0,0 +1,466 @@
+//===------- 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/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>
+
+namespace clang {
+
+namespace TypeName {
+
+/// \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
Index: cfe/trunk/unittests/Tooling/QualTypeNamesTest.cpp
===================================================================
--- cfe/trunk/unittests/Tooling/QualTypeNamesTest.cpp
+++ cfe/trunk/unittests/Tooling/QualTypeNamesTest.cpp
@@ -7,7 +7,7 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "clang/Tooling/Core/QualTypeNames.h"
+#include "clang/AST/QualTypeNames.h"
 #include "TestVisitor.h"
 using namespace clang;
 
Index: cfe/trunk/include/clang/AST/QualTypeNames.h
===================================================================
--- cfe/trunk/include/clang/AST/QualTypeNames.h
+++ cfe/trunk/include/clang/AST/QualTypeNames.h
@@ -0,0 +1,90 @@
+//===--- 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_AST_QUALTYPENAMES_H
+#define LLVM_CLANG_AST_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);
+
+/// \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
Index: cfe/trunk/lib/Tooling/Core/QualTypeNames.cpp
===================================================================
--- cfe/trunk/lib/Tooling/Core/QualTypeNames.cpp
+++ cfe/trunk/lib/Tooling/Core/QualTypeNames.cpp
@@ -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
Index: cfe/trunk/include/clang/Tooling/Core/QualTypeNames.h
===================================================================
--- cfe/trunk/include/clang/Tooling/Core/QualTypeNames.h
+++ cfe/trunk/include/clang/Tooling/Core/QualTypeNames.h
@@ -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
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to