//===--- ForwardDeclarationNamespaceCheck.cpp - clang-tidy ------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#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
