//===------- 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
