//===--- ForwardDeclarationNamespaceCheck.cpp - clang-tidy ------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "ForwardDeclarationNamespaceCheck.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/ASTMatchers/ASTMatchers.h"
#include <stack>
#include <string>

using namespace clang::ast_matchers;

namespace clang {
namespace tidy {
namespace bugprone {

void ForwardDeclarationNamespaceCheck::registerMatchers(MatchFinder *Finder) {
  // Match all class declarations/definitions *EXCEPT*
  // 1. implicit classes, e.g. `class A {};` has implicit `class A` inside `A`.
  // 2. nested classes declared/defined inside another class.
  // 3. template class declaration, template instantiation or
  //    specialization (NOTE: extern specialization is filtered out by
  //    `unless(hasAncestor(cxxRecordDecl()))`).
  auto IsInSpecialization = hasAncestor(
      decl(anyOf(cxxRecordDecl(isExplicitTemplateSpecialization()),
                 functionDecl(isExplicitTemplateSpecialization()))));
  Finder->addMatcher(
      cxxRecordDecl(
          hasParent(decl(anyOf(namespaceDecl(), translationUnitDecl()))),
          unless(isImplicit()), unless(hasAncestor(cxxRecordDecl())),
          unless(isInstantiated()), unless(IsInSpecialization),
          unless(classTemplateSpecializationDecl()))
          .bind("record_decl"),
      this);

  // Match all friend declarations. Classes used in friend declarations are not
  // marked as referenced in AST. We need to record all record classes used in
  // friend declarations.
  Finder->addMatcher(friendDecl().bind("friend_decl"), this);
}

void ForwardDeclarationNamespaceCheck::check(
    const MatchFinder::MatchResult &Result) {
  if (const auto *RecordDecl =
          Result.Nodes.getNodeAs<CXXRecordDecl>("record_decl")) {
    StringRef DeclName = RecordDecl->getName();
    if (RecordDecl->isThisDeclarationADefinition()) {
      DeclNameToDefinitions[DeclName].push_back(RecordDecl);
    } else {
      // If a declaration has no definition, the definition could be in another
      // namespace (a wrong namespace).
      // NOTE: even a declaration does have definition, we still need it to
      // compare with other declarations.
      DeclNameToDeclarations[DeclName].push_back(RecordDecl);
    }
  } else {
    const auto *Decl = Result.Nodes.getNodeAs<FriendDecl>("friend_decl");
    assert(Decl && "Decl is neither record_decl nor friend decl!");

    // Classes used in friend delarations are not marked referenced in AST,
    // so we need to check classes used in friend declarations manually to
    // reduce the rate of false positive.
    // For example, in
    //    \code
    //      struct A;
    //      struct B { friend A; };
    //    \endcode
    // `A` will not be marked as "referenced" in the AST.
    if (const TypeSourceInfo *Tsi = Decl->getFriendType()) {
      QualType Desugared = Tsi->getType().getDesugaredType(*Result.Context);
      FriendTypes.insert(Desugared.getTypePtr());
    }
  }
}

static bool haveSameNamespaceOrTranslationUnit(const CXXRecordDecl *Decl1,
                                               const CXXRecordDecl *Decl2) {
  const DeclContext *ParentDecl1 = Decl1->getLexicalParent();
  const DeclContext *ParentDecl2 = Decl2->getLexicalParent();

  // Since we only matched declarations whose parent is Namespace or
  // TranslationUnit declaration, the parent should be either a translation unit
  // or namespace.
  if (ParentDecl1->getDeclKind() == Decl::TranslationUnit ||
      ParentDecl2->getDeclKind() == Decl::TranslationUnit) {
    return ParentDecl1 == ParentDecl2;
  }
  assert(ParentDecl1->getDeclKind() == Decl::Namespace &&
         "ParentDecl1 declaration must be a namespace");
  assert(ParentDecl2->getDeclKind() == Decl::Namespace &&
         "ParentDecl2 declaration must be a namespace");
  auto *Ns1 = NamespaceDecl::castFromDeclContext(ParentDecl1);
  auto *Ns2 = NamespaceDecl::castFromDeclContext(ParentDecl2);
  return Ns1->getOriginalNamespace() == Ns2->getOriginalNamespace();
}

static std::string getNameOfNamespace(const CXXRecordDecl *Decl) {
  const auto *ParentDecl = Decl->getLexicalParent();
  if (ParentDecl->getDeclKind() == Decl::TranslationUnit) {
    return "(global)";
  }
  const auto *NsDecl = cast<NamespaceDecl>(ParentDecl);
  std::string Ns;
  llvm::raw_string_ostream OStream(Ns);
  NsDecl->printQualifiedName(OStream);
  OStream.flush();
  return Ns.empty() ? "(global)" : Ns;
}

void ForwardDeclarationNamespaceCheck::onEndOfTranslationUnit() {
  // Iterate each group of declarations by name.
  for (const auto &KeyValuePair : DeclNameToDeclarations) {
    const auto &Declarations = KeyValuePair.second;
    // If more than 1 declaration exists, we check if all are in the same
    // namespace.
    for (const auto *CurDecl : Declarations) {
      if (CurDecl->hasDefinition() || CurDecl->isReferenced()) {
        continue; // Skip forward declarations that are used/referenced.
      }
      if (FriendTypes.count(CurDecl->getTypeForDecl()) != 0) {
        continue; // Skip forward declarations referenced as friend.
      }
      if (CurDecl->getLocation().isMacroID() ||
          CurDecl->getLocation().isInvalid()) {
        continue;
      }
      // Compare with all other declarations with the same name.
      for (const auto *Decl : Declarations) {
        if (Decl == CurDecl) {
          continue; // Don't compare with self.
        }
        if (!CurDecl->hasDefinition() &&
            !haveSameNamespaceOrTranslationUnit(CurDecl, Decl)) {
          diag(CurDecl->getLocation(),
               "declaration %0 is never referenced, but a declaration with "
               "the same name found in another namespace '%1'")
              << CurDecl << getNameOfNamespace(Decl);
          diag(Decl->getLocation(), "a declaration of %0 is found here",
               DiagnosticIDs::Note)
              << Decl;
          break; // FIXME: We only generate one warning for each declaration.
        }
      }
      // Check if a definition in another namespace exists.
      const auto DeclName = CurDecl->getName();
      if (DeclNameToDefinitions.find(DeclName) == DeclNameToDefinitions.end()) {
        continue; // No definition in this translation unit, we can skip it.
      }
      // Make a warning for each definition with the same name (in other
      // namespaces).
      const auto &Definitions = DeclNameToDefinitions[DeclName];
      for (const auto *Def : Definitions) {
        diag(CurDecl->getLocation(),
             "no definition found for %0, but a definition with "
             "the same name %1 found in another namespace '%2'")
            << CurDecl << Def << getNameOfNamespace(Def);
        diag(Def->getLocation(), "a definition of %0 is found here",
             DiagnosticIDs::Note)
            << Def;
      }
    }
  }
}

} // namespace bugprone
} // namespace tidy
} // namespace clang
