//===--- CommentSema.cpp - Doxygen comment semantic analysis --------------===//
//
// 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 "clang/AST/CommentSema.h"
#include "clang/AST/Attr.h"
#include "clang/AST/CommentCommandTraits.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/Basic/DiagnosticComment.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/SimpleTypoCorrection.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Lex/Preprocessor.h"
#include "llvm/ADT/StringSwitch.h"

namespace clang {
namespace comments {

namespace {
#include "clang/AST/CommentHTMLTagsProperties.inc"
} // end anonymous namespace

Sema::Sema(llvm::BumpPtrAllocator &Allocator, const SourceManager &SourceMgr,
           DiagnosticsEngine &Diags, CommandTraits &Traits,
           const Preprocessor *PP) :
    Allocator(Allocator), SourceMgr(SourceMgr), Diags(Diags), Traits(Traits),
    PP(PP), ThisDeclInfo(nullptr), BriefCommand(nullptr),
    HeaderfileCommand(nullptr) {
}

void Sema::setDecl(const Decl *D) {
  if (!D)
    return;

  ThisDeclInfo = new (Allocator) DeclInfo;
  ThisDeclInfo->CommentDecl = D;
  ThisDeclInfo->IsFilled = false;
}

ParagraphComment *Sema::actOnParagraphComment(
                              ArrayRef<InlineContentComment *> Content) {
  return new (Allocator) ParagraphComment(Content);
}

BlockCommandComment *Sema::actOnBlockCommandStart(
                                      SourceLocation LocBegin,
                                      SourceLocation LocEnd,
                                      unsigned CommandID,
                                      CommandMarkerKind CommandMarker) {
  BlockCommandComment *BC = new (Allocator) BlockCommandComment(LocBegin, LocEnd,
                                                                CommandID,
                                                                CommandMarker);
  checkContainerDecl(BC);
  return BC;
}

void Sema::actOnBlockCommandArgs(BlockCommandComment *Command,
                                 ArrayRef<BlockCommandComment::Argument> Args) {
  Command->setArgs(Args);
}

void Sema::actOnBlockCommandFinish(BlockCommandComment *Command,
                                   ParagraphComment *Paragraph) {
  Command->setParagraph(Paragraph);
  checkBlockCommandEmptyParagraph(Command);
  checkBlockCommandDuplicate(Command);
  if (ThisDeclInfo) {
    // These checks only make sense if the comment is attached to a
    // declaration.
    checkReturnsCommand(Command);
    checkDeprecatedCommand(Command);
  }
}

ParamCommandComment *Sema::actOnParamCommandStart(
                                      SourceLocation LocBegin,
                                      SourceLocation LocEnd,
                                      unsigned CommandID,
                                      CommandMarkerKind CommandMarker) {
  ParamCommandComment *Command =
      new (Allocator) ParamCommandComment(LocBegin, LocEnd, CommandID,
                                          CommandMarker);

  if (!involvesFunctionType())
    Diag(Command->getLocation(),
         diag::warn_doc_param_not_attached_to_a_function_decl)
      << CommandMarker
      << Command->getCommandNameRange(Traits);

  return Command;
}

void Sema::checkFunctionDeclVerbatimLine(const BlockCommandComment *Comment) {
  const CommandInfo *Info = Traits.getCommandInfo(Comment->getCommandID());
  if (!Info->IsFunctionDeclarationCommand)
    return;

  unsigned DiagSelect;
  switch (Comment->getCommandID()) {
    case CommandTraits::KCI_function:
      DiagSelect = (!isAnyFunctionDecl() && !isFunctionTemplateDecl())? 1 : 0;
      break;
    case CommandTraits::KCI_functiongroup:
      DiagSelect = (!isAnyFunctionDecl() && !isFunctionTemplateDecl())? 2 : 0;
      break;
    case CommandTraits::KCI_method:
      DiagSelect = !isObjCMethodDecl() ? 3 : 0;
      break;
    case CommandTraits::KCI_methodgroup:
      DiagSelect = !isObjCMethodDecl() ? 4 : 0;
      break;
    case CommandTraits::KCI_callback:
      DiagSelect = !isFunctionPointerVarDecl() ? 5 : 0;
      break;
    default:
      DiagSelect = 0;
      break;
  }
  if (DiagSelect)
    Diag(Comment->getLocation(), diag::warn_doc_function_method_decl_mismatch)
    << Comment->getCommandMarker()
    << (DiagSelect-1) << (DiagSelect-1)
    << Comment->getSourceRange();
}

void Sema::checkContainerDeclVerbatimLine(const BlockCommandComment *Comment) {
  const CommandInfo *Info = Traits.getCommandInfo(Comment->getCommandID());
  if (!Info->IsRecordLikeDeclarationCommand)
    return;
  unsigned DiagSelect;
  switch (Comment->getCommandID()) {
    case CommandTraits::KCI_class:
      DiagSelect =
          (!isClassOrStructOrTagTypedefDecl() && !isClassTemplateDecl()) ? 1
                                                                         : 0;
      // Allow @class command on @interface declarations.
      // FIXME. Currently, \class and @class are indistinguishable. So,
      // \class is also allowed on an @interface declaration
      if (DiagSelect && Comment->getCommandMarker() && isObjCInterfaceDecl())
        DiagSelect = 0;
      break;
    case CommandTraits::KCI_interface:
      DiagSelect = !isObjCInterfaceDecl() ? 2 : 0;
      break;
    case CommandTraits::KCI_protocol:
      DiagSelect = !isObjCProtocolDecl() ? 3 : 0;
      break;
    case CommandTraits::KCI_struct:
      DiagSelect = !isClassOrStructOrTagTypedefDecl() ? 4 : 0;
      break;
    case CommandTraits::KCI_union:
      DiagSelect = !isUnionDecl() ? 5 : 0;
      break;
    default:
      DiagSelect = 0;
      break;
  }
  if (DiagSelect)
    Diag(Comment->getLocation(), diag::warn_doc_api_container_decl_mismatch)
    << Comment->getCommandMarker()
    << (DiagSelect-1) << (DiagSelect-1)
    << Comment->getSourceRange();
}

void Sema::checkContainerDecl(const BlockCommandComment *Comment) {
  const CommandInfo *Info = Traits.getCommandInfo(Comment->getCommandID());
  if (!Info->IsRecordLikeDetailCommand || isRecordLikeDecl())
    return;
  unsigned DiagSelect;
  switch (Comment->getCommandID()) {
    case CommandTraits::KCI_classdesign:
      DiagSelect = 1;
      break;
    case CommandTraits::KCI_coclass:
      DiagSelect = 2;
      break;
    case CommandTraits::KCI_dependency:
      DiagSelect = 3;
      break;
    case CommandTraits::KCI_helper:
      DiagSelect = 4;
      break;
    case CommandTraits::KCI_helperclass:
      DiagSelect = 5;
      break;
    case CommandTraits::KCI_helps:
      DiagSelect = 6;
      break;
    case CommandTraits::KCI_instancesize:
      DiagSelect = 7;
      break;
    case CommandTraits::KCI_ownership:
      DiagSelect = 8;
      break;
    case CommandTraits::KCI_performance:
      DiagSelect = 9;
      break;
    case CommandTraits::KCI_security:
      DiagSelect = 10;
      break;
    case CommandTraits::KCI_superclass:
      DiagSelect = 11;
      break;
    default:
      DiagSelect = 0;
      break;
  }
  if (DiagSelect)
    Diag(Comment->getLocation(), diag::warn_doc_container_decl_mismatch)
    << Comment->getCommandMarker()
    << (DiagSelect-1)
    << Comment->getSourceRange();
}

/// Turn a string into the corresponding PassDirection or -1 if it's not
/// valid.
static ParamCommandPassDirection getParamPassDirection(StringRef Arg) {
  return llvm::StringSwitch<ParamCommandPassDirection>(Arg)
      .Case("[in]", ParamCommandPassDirection::In)
      .Case("[out]", ParamCommandPassDirection::Out)
      .Cases("[in,out]", "[out,in]", ParamCommandPassDirection::InOut)
      .Default(static_cast<ParamCommandPassDirection>(-1));
}

void Sema::actOnParamCommandDirectionArg(ParamCommandComment *Command,
                                         SourceLocation ArgLocBegin,
                                         SourceLocation ArgLocEnd,
                                         StringRef Arg) {
  std::string ArgLower = Arg.lower();
  ParamCommandPassDirection Direction = getParamPassDirection(ArgLower);

  if (Direction == static_cast<ParamCommandPassDirection>(-1)) {
    // Try again with whitespace removed.
    llvm::erase_if(ArgLower, clang::isWhitespace);
    Direction = getParamPassDirection(ArgLower);

    SourceRange ArgRange(ArgLocBegin, ArgLocEnd);
    if (Direction != static_cast<ParamCommandPassDirection>(-1)) {
      const char *FixedName =
          ParamCommandComment::getDirectionAsString(Direction);
      Diag(ArgLocBegin, diag::warn_doc_param_spaces_in_direction)
          << ArgRange << FixItHint::CreateReplacement(ArgRange, FixedName);
    } else {
      Diag(ArgLocBegin, diag::warn_doc_param_invalid_direction) << ArgRange;
      Direction = ParamCommandPassDirection::In; // Sane fall back.
    }
  }
  Command->setDirection(Direction,
                        /*Explicit=*/true);
}

void Sema::actOnParamCommandParamNameArg(ParamCommandComment *Command,
                                         SourceLocation ArgLocBegin,
                                         SourceLocation ArgLocEnd,
                                         StringRef Arg) {
  // Parser will not feed us more arguments than needed.
  assert(Command->getNumArgs() == 0);

  if (!Command->isDirectionExplicit()) {
    // User didn't provide a direction argument.
    Command->setDirection(ParamCommandPassDirection::In,
                          /* Explicit = */ false);
  }
  auto *A = new (Allocator)
      Comment::Argument{SourceRange(ArgLocBegin, ArgLocEnd), Arg};
  Command->setArgs(llvm::ArrayRef(A, 1));
}

void Sema::actOnParamCommandFinish(ParamCommandComment *Command,
                                   ParagraphComment *Paragraph) {
  Command->setParagraph(Paragraph);
  checkBlockCommandEmptyParagraph(Command);
}

TParamCommandComment *Sema::actOnTParamCommandStart(
                                      SourceLocation LocBegin,
                                      SourceLocation LocEnd,
                                      unsigned CommandID,
                                      CommandMarkerKind CommandMarker) {
  TParamCommandComment *Command =
      new (Allocator) TParamCommandComment(LocBegin, LocEnd, CommandID,
                                           CommandMarker);

  if (!isTemplateOrSpecialization())
    Diag(Command->getLocation(),
         diag::warn_doc_tparam_not_attached_to_a_template_decl)
      << CommandMarker
      << Command->getCommandNameRange(Traits);

  return Command;
}

void Sema::actOnTParamCommandParamNameArg(TParamCommandComment *Command,
                                          SourceLocation ArgLocBegin,
                                          SourceLocation ArgLocEnd,
                                          StringRef Arg) {
  // Parser will not feed us more arguments than needed.
  assert(Command->getNumArgs() == 0);

  auto *A = new (Allocator)
      Comment::Argument{SourceRange(ArgLocBegin, ArgLocEnd), Arg};
  Command->setArgs(llvm::ArrayRef(A, 1));

  if (!isTemplateOrSpecialization()) {
    // We already warned that this \\tparam is not attached to a template decl.
    return;
  }

  const TemplateParameterList *TemplateParameters =
      ThisDeclInfo->TemplateParameters;
  SmallVector<unsigned, 2> Position;
  if (resolveTParamReference(Arg, TemplateParameters, &Position)) {
    Command->setPosition(copyArray(llvm::ArrayRef(Position)));
    TParamCommandComment *&PrevCommand = TemplateParameterDocs[Arg];
    if (PrevCommand) {
      SourceRange ArgRange(ArgLocBegin, ArgLocEnd);
      Diag(ArgLocBegin, diag::warn_doc_tparam_duplicate)
        << Arg << ArgRange;
      Diag(PrevCommand->getLocation(), diag::note_doc_tparam_previous)
        << PrevCommand->getParamNameRange();
    }
    PrevCommand = Command;
    return;
  }

  SourceRange ArgRange(ArgLocBegin, ArgLocEnd);
  Diag(ArgLocBegin, diag::warn_doc_tparam_not_found)
    << Arg << ArgRange;

  if (!TemplateParameters || TemplateParameters->size() == 0)
    return;

  StringRef CorrectedName;
  if (TemplateParameters->size() == 1) {
    const NamedDecl *Param = TemplateParameters->getParam(0);
    const IdentifierInfo *II = Param->getIdentifier();
    if (II)
      CorrectedName = II->getName();
  } else {
    CorrectedName = correctTypoInTParamReference(Arg, TemplateParameters);
  }

  if (!CorrectedName.empty()) {
    Diag(ArgLocBegin, diag::note_doc_tparam_name_suggestion)
      << CorrectedName
      << FixItHint::CreateReplacement(ArgRange, CorrectedName);
  }
}

void Sema::actOnTParamCommandFinish(TParamCommandComment *Command,
                                    ParagraphComment *Paragraph) {
  Command->setParagraph(Paragraph);
  checkBlockCommandEmptyParagraph(Command);
}

InlineCommandComment *
Sema::actOnInlineCommand(SourceLocation CommandLocBegin,
                         SourceLocation CommandLocEnd, unsigned CommandID,
                         ArrayRef<Comment::Argument> Args) {
  StringRef CommandName = Traits.getCommandInfo(CommandID)->Name;

  return new (Allocator)
      InlineCommandComment(CommandLocBegin, CommandLocEnd, CommandID,
                           getInlineCommandRenderKind(CommandName), Args);
}

InlineContentComment *Sema::actOnUnknownCommand(SourceLocation LocBegin,
                                                SourceLocation LocEnd,
                                                StringRef CommandName) {
  unsigned CommandID = Traits.registerUnknownCommand(CommandName)->getID();
  return actOnUnknownCommand(LocBegin, LocEnd, CommandID);
}

InlineContentComment *Sema::actOnUnknownCommand(SourceLocation LocBegin,
                                                SourceLocation LocEnd,
                                                unsigned CommandID) {
  ArrayRef<InlineCommandComment::Argument> Args;
  return new (Allocator) InlineCommandComment(
      LocBegin, LocEnd, CommandID, InlineCommandRenderKind::Normal, Args);
}

TextComment *Sema::actOnText(SourceLocation LocBegin,
                             SourceLocation LocEnd,
                             StringRef Text) {
  return new (Allocator) TextComment(LocBegin, LocEnd, Text);
}

VerbatimBlockComment *Sema::actOnVerbatimBlockStart(SourceLocation Loc,
                                                    unsigned CommandID) {
  StringRef CommandName = Traits.getCommandInfo(CommandID)->Name;
  return new (Allocator) VerbatimBlockComment(
                                  Loc,
                                  Loc.getLocWithOffset(1 + CommandName.size()),
                                  CommandID);
}

VerbatimBlockLineComment *Sema::actOnVerbatimBlockLine(SourceLocation Loc,
                                                       StringRef Text) {
  return new (Allocator) VerbatimBlockLineComment(Loc, Text);
}

void Sema::actOnVerbatimBlockFinish(
                            VerbatimBlockComment *Block,
                            SourceLocation CloseNameLocBegin,
                            StringRef CloseName,
                            ArrayRef<VerbatimBlockLineComment *> Lines) {
  Block->setCloseName(CloseName, CloseNameLocBegin);
  Block->setLines(Lines);
}

VerbatimLineComment *Sema::actOnVerbatimLine(SourceLocation LocBegin,
                                             unsigned CommandID,
                                             SourceLocation TextBegin,
                                             StringRef Text) {
  VerbatimLineComment *VL = new (Allocator) VerbatimLineComment(
                              LocBegin,
                              TextBegin.getLocWithOffset(Text.size()),
                              CommandID,
                              TextBegin,
                              Text);
  checkFunctionDeclVerbatimLine(VL);
  checkContainerDeclVerbatimLine(VL);
  return VL;
}

HTMLStartTagComment *Sema::actOnHTMLStartTagStart(SourceLocation LocBegin,
                                                  StringRef TagName) {
  return new (Allocator) HTMLStartTagComment(LocBegin, TagName);
}

void Sema::actOnHTMLStartTagFinish(
                              HTMLStartTagComment *Tag,
                              ArrayRef<HTMLStartTagComment::Attribute> Attrs,
                              SourceLocation GreaterLoc,
                              bool IsSelfClosing) {
  Tag->setAttrs(Attrs);
  Tag->setGreaterLoc(GreaterLoc);
  if (IsSelfClosing)
    Tag->setSelfClosing();
  else if (!isHTMLEndTagForbidden(Tag->getTagName()))
    HTMLOpenTags.push_back(Tag);
}

HTMLEndTagComment *Sema::actOnHTMLEndTag(SourceLocation LocBegin,
                                         SourceLocation LocEnd,
                                         StringRef TagName) {
  HTMLEndTagComment *HET =
      new (Allocator) HTMLEndTagComment(LocBegin, LocEnd, TagName);
  if (isHTMLEndTagForbidden(TagName)) {
    Diag(HET->getLocation(), diag::warn_doc_html_end_forbidden)
      << TagName << HET->getSourceRange();
    HET->setIsMalformed();
    return HET;
  }

  bool FoundOpen = false;
  for (SmallVectorImpl<HTMLStartTagComment *>::const_reverse_iterator
       I = HTMLOpenTags.rbegin(), E = HTMLOpenTags.rend();
       I != E; ++I) {
    if ((*I)->getTagName() == TagName) {
      FoundOpen = true;
      break;
    }
  }
  if (!FoundOpen) {
    Diag(HET->getLocation(), diag::warn_doc_html_end_unbalanced)
      << HET->getSourceRange();
    HET->setIsMalformed();
    return HET;
  }

  while (!HTMLOpenTags.empty()) {
    HTMLStartTagComment *HST = HTMLOpenTags.pop_back_val();
    StringRef LastNotClosedTagName = HST->getTagName();
    if (LastNotClosedTagName == TagName) {
      // If the start tag is malformed, end tag is malformed as well.
      if (HST->isMalformed())
        HET->setIsMalformed();
      break;
    }

    if (isHTMLEndTagOptional(LastNotClosedTagName))
      continue;

    bool OpenLineInvalid;
    const unsigned OpenLine = SourceMgr.getPresumedLineNumber(
                                                HST->getLocation(),
                                                &OpenLineInvalid);
    bool CloseLineInvalid;
    const unsigned CloseLine = SourceMgr.getPresumedLineNumber(
                                                HET->getLocation(),
                                                &CloseLineInvalid);

    if (OpenLineInvalid || CloseLineInvalid || OpenLine == CloseLine) {
      Diag(HST->getLocation(), diag::warn_doc_html_start_end_mismatch)
        << HST->getTagName() << HET->getTagName()
        << HST->getSourceRange() << HET->getSourceRange();
      HST->setIsMalformed();
    } else {
      Diag(HST->getLocation(), diag::warn_doc_html_start_end_mismatch)
        << HST->getTagName() << HET->getTagName()
        << HST->getSourceRange();
      Diag(HET->getLocation(), diag::note_doc_html_end_tag)
        << HET->getSourceRange();
      HST->setIsMalformed();
    }
  }

  return HET;
}

FullComment *Sema::actOnFullComment(
                              ArrayRef<BlockContentComment *> Blocks) {
  FullComment *FC = new (Allocator) FullComment(Blocks, ThisDeclInfo);
  resolveParamCommandIndexes(FC);

  // Complain about HTML tags that are not closed.
  while (!HTMLOpenTags.empty()) {
    HTMLStartTagComment *HST = HTMLOpenTags.pop_back_val();
    if (isHTMLEndTagOptional(HST->getTagName()))
      continue;

    Diag(HST->getLocation(), diag::warn_doc_html_missing_end_tag)
      << HST->getTagName() << HST->getSourceRange();
    HST->setIsMalformed();
  }

  return FC;
}

void Sema::checkBlockCommandEmptyParagraph(BlockCommandComment *Command) {
  if (Traits.getCommandInfo(Command->getCommandID())->IsEmptyParagraphAllowed)
    return;

  ParagraphComment *Paragraph = Command->getParagraph();
  if (Paragraph->isWhitespace()) {
    SourceLocation DiagLoc;
    if (Command->getNumArgs() > 0)
      DiagLoc = Command->getArgRange(Command->getNumArgs() - 1).getEnd();
    if (!DiagLoc.isValid())
      DiagLoc = Command->getCommandNameRange(Traits).getEnd();
    Diag(DiagLoc, diag::warn_doc_block_command_empty_paragraph)
      << Command->getCommandMarker()
      << Command->getCommandName(Traits)
      << Command->getSourceRange();
  }
}

void Sema::checkReturnsCommand(const BlockCommandComment *Command) {
  if (!Traits.getCommandInfo(Command->getCommandID())->IsReturnsCommand)
    return;

  assert(ThisDeclInfo && "should not call this check on a bare comment");

  // We allow the return command for all @properties because it can be used
  // to document the value that the property getter returns.
  if (isObjCPropertyDecl())
    return;
  if (involvesFunctionType()) {
    assert(!ThisDeclInfo->ReturnType.isNull() &&
           "should have a valid return type");
    if (ThisDeclInfo->ReturnType->isVoidType()) {
      unsigned DiagKind;
      switch (ThisDeclInfo->CommentDecl->getKind()) {
      default:
        if (ThisDeclInfo->IsObjCMethod)
          DiagKind = 3;
        else
          DiagKind = 0;
        break;
      case Decl::CXXConstructor:
        DiagKind = 1;
        break;
      case Decl::CXXDestructor:
        DiagKind = 2;
        break;
      }
      Diag(Command->getLocation(),
           diag::warn_doc_returns_attached_to_a_void_function)
        << Command->getCommandMarker()
        << Command->getCommandName(Traits)
        << DiagKind
        << Command->getSourceRange();
    }
    return;
  }

  Diag(Command->getLocation(),
       diag::warn_doc_returns_not_attached_to_a_function_decl)
    << Command->getCommandMarker()
    << Command->getCommandName(Traits)
    << Command->getSourceRange();
}

void Sema::checkBlockCommandDuplicate(const BlockCommandComment *Command) {
  const CommandInfo *Info = Traits.getCommandInfo(Command->getCommandID());
  const BlockCommandComment *PrevCommand = nullptr;
  if (Info->IsBriefCommand) {
    if (!BriefCommand) {
      BriefCommand = Command;
      return;
    }
    PrevCommand = BriefCommand;
  } else if (Info->IsHeaderfileCommand) {
    if (!HeaderfileCommand) {
      HeaderfileCommand = Command;
      return;
    }
    PrevCommand = HeaderfileCommand;
  } else {
    // We don't want to check this command for duplicates.
    return;
  }
  StringRef CommandName = Command->getCommandName(Traits);
  StringRef PrevCommandName = PrevCommand->getCommandName(Traits);
  Diag(Command->getLocation(), diag::warn_doc_block_command_duplicate)
      << Command->getCommandMarker()
      << CommandName
      << Command->getSourceRange();
  if (CommandName == PrevCommandName)
    Diag(PrevCommand->getLocation(), diag::note_doc_block_command_previous)
        << PrevCommand->getCommandMarker()
        << PrevCommandName
        << PrevCommand->getSourceRange();
  else
    Diag(PrevCommand->getLocation(),
         diag::note_doc_block_command_previous_alias)
        << PrevCommand->getCommandMarker()
        << PrevCommandName
        << CommandName;
}

void Sema::checkDeprecatedCommand(const BlockCommandComment *Command) {
  if (!Traits.getCommandInfo(Command->getCommandID())->IsDeprecatedCommand)
    return;

  assert(ThisDeclInfo && "should not call this check on a bare comment");

  const Decl *D = ThisDeclInfo->CommentDecl;
  if (!D)
    return;

  if (D->hasAttr<DeprecatedAttr>() ||
      D->hasAttr<AvailabilityAttr>() ||
      D->hasAttr<UnavailableAttr>())
    return;

  Diag(Command->getLocation(), diag::warn_doc_deprecated_not_sync)
      << Command->getSourceRange() << Command->getCommandMarker();

  // Try to emit a fixit with a deprecation attribute.
  if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
    // Don't emit a Fix-It for non-member function definitions.  GCC does not
    // accept attributes on them.
    const DeclContext *Ctx = FD->getDeclContext();
    if ((!Ctx || !Ctx->isRecord()) &&
        FD->doesThisDeclarationHaveABody())
      return;

    const LangOptions &LO = FD->getLangOpts();
    const bool DoubleSquareBracket = LO.CPlusPlus14 || LO.C23;
    StringRef AttributeSpelling =
        DoubleSquareBracket ? "[[deprecated]]" : "__attribute__((deprecated))";
    if (PP) {
      // Try to find a replacement macro:
      // - In C23/C++14 we prefer [[deprecated]].
      // - If not found or an older C/C++ look for __attribute__((deprecated)).
      StringRef MacroName;
      if (DoubleSquareBracket) {
        TokenValue Tokens[] = {tok::l_square, tok::l_square,
                               PP->getIdentifierInfo("deprecated"),
                               tok::r_square, tok::r_square};
        MacroName = PP->getLastMacroWithSpelling(FD->getLocation(), Tokens);
        if (!MacroName.empty())
          AttributeSpelling = MacroName;
      }

      if (MacroName.empty()) {
        TokenValue Tokens[] = {
            tok::kw___attribute, tok::l_paren,
            tok::l_paren,        PP->getIdentifierInfo("deprecated"),
            tok::r_paren,        tok::r_paren};
        StringRef MacroName =
            PP->getLastMacroWithSpelling(FD->getLocation(), Tokens);
        if (!MacroName.empty())
          AttributeSpelling = MacroName;
      }
    }

    SmallString<64> TextToInsert = AttributeSpelling;
    TextToInsert += " ";
    SourceLocation Loc = FD->getSourceRange().getBegin();
    Diag(Loc, diag::note_add_deprecation_attr)
        << FixItHint::CreateInsertion(Loc, TextToInsert);
  }
}

void Sema::resolveParamCommandIndexes(const FullComment *FC) {
  if (!involvesFunctionType()) {
    // We already warned that \\param commands are not attached to a function
    // decl.
    return;
  }

  SmallVector<ParamCommandComment *, 8> UnresolvedParamCommands;

  // Comment AST nodes that correspond to \c ParamVars for which we have
  // found a \\param command or NULL if no documentation was found so far.
  SmallVector<ParamCommandComment *, 8> ParamVarDocs;

  ArrayRef<const ParmVarDecl *> ParamVars = getParamVars();
  ParamVarDocs.resize(ParamVars.size(), nullptr);

  // First pass over all \\param commands: resolve all parameter names.
  for (Comment::child_iterator I = FC->child_begin(), E = FC->child_end();
       I != E; ++I) {
    ParamCommandComment *PCC = dyn_cast<ParamCommandComment>(*I);
    if (!PCC || !PCC->hasParamName())
      continue;
    StringRef ParamName = PCC->getParamNameAsWritten();

    // Check that referenced parameter name is in the function decl.
    const unsigned ResolvedParamIndex = resolveParmVarReference(ParamName,
                                                                ParamVars);
    if (ResolvedParamIndex == ParamCommandComment::VarArgParamIndex) {
      PCC->setIsVarArgParam();
      continue;
    }
    if (ResolvedParamIndex == ParamCommandComment::InvalidParamIndex) {
      UnresolvedParamCommands.push_back(PCC);
      continue;
    }
    PCC->setParamIndex(ResolvedParamIndex);
    if (ParamVarDocs[ResolvedParamIndex]) {
      SourceRange ArgRange = PCC->getParamNameRange();
      Diag(ArgRange.getBegin(), diag::warn_doc_param_duplicate)
        << ParamName << ArgRange;
      ParamCommandComment *PrevCommand = ParamVarDocs[ResolvedParamIndex];
      Diag(PrevCommand->getLocation(), diag::note_doc_param_previous)
        << PrevCommand->getParamNameRange();
    }
    ParamVarDocs[ResolvedParamIndex] = PCC;
  }

  // Find parameter declarations that have no corresponding \\param.
  SmallVector<const ParmVarDecl *, 8> OrphanedParamDecls;
  for (unsigned i = 0, e = ParamVarDocs.size(); i != e; ++i) {
    if (!ParamVarDocs[i])
      OrphanedParamDecls.push_back(ParamVars[i]);
  }

  // Second pass over unresolved \\param commands: do typo correction.
  // Suggest corrections from a set of parameter declarations that have no
  // corresponding \\param.
  for (unsigned i = 0, e = UnresolvedParamCommands.size(); i != e; ++i) {
    const ParamCommandComment *PCC = UnresolvedParamCommands[i];

    SourceRange ArgRange = PCC->getParamNameRange();
    StringRef ParamName = PCC->getParamNameAsWritten();
    Diag(ArgRange.getBegin(), diag::warn_doc_param_not_found)
      << ParamName << ArgRange;

    // All parameters documented -- can't suggest a correction.
    if (OrphanedParamDecls.size() == 0)
      continue;

    unsigned CorrectedParamIndex = ParamCommandComment::InvalidParamIndex;
    if (OrphanedParamDecls.size() == 1) {
      // If one parameter is not documented then that parameter is the only
      // possible suggestion.
      CorrectedParamIndex = 0;
    } else {
      // Do typo correction.
      CorrectedParamIndex = correctTypoInParmVarReference(ParamName,
                                                          OrphanedParamDecls);
    }
    if (CorrectedParamIndex != ParamCommandComment::InvalidParamIndex) {
      const ParmVarDecl *CorrectedPVD = OrphanedParamDecls[CorrectedParamIndex];
      if (const IdentifierInfo *CorrectedII = CorrectedPVD->getIdentifier())
        Diag(ArgRange.getBegin(), diag::note_doc_param_name_suggestion)
          << CorrectedII->getName()
          << FixItHint::CreateReplacement(ArgRange, CorrectedII->getName());
    }
  }
}

bool Sema::involvesFunctionType() {
  if (!ThisDeclInfo)
    return false;
  if (!ThisDeclInfo->IsFilled)
    inspectThisDecl();
  return ThisDeclInfo->involvesFunctionType();
}

bool Sema::isFunctionDecl() {
  if (!ThisDeclInfo)
    return false;
  if (!ThisDeclInfo->IsFilled)
    inspectThisDecl();
  return ThisDeclInfo->getKind() == DeclInfo::FunctionKind;
}

bool Sema::isAnyFunctionDecl() {
  return isFunctionDecl() && ThisDeclInfo->CurrentDecl &&
         isa<FunctionDecl>(ThisDeclInfo->CurrentDecl);
}

bool Sema::isFunctionOrMethodVariadic() {
  if (!ThisDeclInfo)
    return false;
  if (!ThisDeclInfo->IsFilled)
    inspectThisDecl();
  return ThisDeclInfo->IsVariadic;
}

bool Sema::isObjCMethodDecl() {
  return isFunctionDecl() && ThisDeclInfo->CurrentDecl &&
         isa<ObjCMethodDecl>(ThisDeclInfo->CurrentDecl);
}

bool Sema::isFunctionPointerVarDecl() {
  if (!ThisDeclInfo)
    return false;
  if (!ThisDeclInfo->IsFilled)
    inspectThisDecl();
  if (ThisDeclInfo->getKind() == DeclInfo::VariableKind) {
    if (const VarDecl *VD = dyn_cast_or_null<VarDecl>(ThisDeclInfo->CurrentDecl)) {
      QualType QT = VD->getType();
      return QT->isFunctionPointerType();
    }
  }
  return false;
}

bool Sema::isObjCPropertyDecl() {
  if (!ThisDeclInfo)
    return false;
  if (!ThisDeclInfo->IsFilled)
    inspectThisDecl();
  return ThisDeclInfo->CurrentDecl->getKind() == Decl::ObjCProperty;
}

bool Sema::isTemplateOrSpecialization() {
  if (!ThisDeclInfo)
    return false;
  if (!ThisDeclInfo->IsFilled)
    inspectThisDecl();
  return ThisDeclInfo->getTemplateKind() != DeclInfo::NotTemplate;
}

bool Sema::isRecordLikeDecl() {
  if (!ThisDeclInfo)
    return false;
  if (!ThisDeclInfo->IsFilled)
    inspectThisDecl();
  return isUnionDecl() || isClassOrStructDecl() || isObjCInterfaceDecl() ||
         isObjCProtocolDecl();
}

bool Sema::isUnionDecl() {
  if (!ThisDeclInfo)
    return false;
  if (!ThisDeclInfo->IsFilled)
    inspectThisDecl();
  if (const RecordDecl *RD =
        dyn_cast_or_null<RecordDecl>(ThisDeclInfo->CurrentDecl))
    return RD->isUnion();
  return false;
}
static bool isClassOrStructDeclImpl(const Decl *D) {
  if (auto *record = dyn_cast_or_null<RecordDecl>(D))
    return !record->isUnion();

  return false;
}

bool Sema::isClassOrStructDecl() {
  if (!ThisDeclInfo)
    return false;
  if (!ThisDeclInfo->IsFilled)
    inspectThisDecl();

  if (!ThisDeclInfo->CurrentDecl)
    return false;

  return isClassOrStructDeclImpl(ThisDeclInfo->CurrentDecl);
}

bool Sema::isClassOrStructOrTagTypedefDecl() {
  if (!ThisDeclInfo)
    return false;
  if (!ThisDeclInfo->IsFilled)
    inspectThisDecl();

  if (!ThisDeclInfo->CurrentDecl)
    return false;

  if (isClassOrStructDeclImpl(ThisDeclInfo->CurrentDecl))
    return true;

  if (auto *ThisTypedefDecl = dyn_cast<TypedefDecl>(ThisDeclInfo->CurrentDecl)) {
    auto UnderlyingType = ThisTypedefDecl->getUnderlyingType();
    if (auto ThisElaboratedType = dyn_cast<ElaboratedType>(UnderlyingType)) {
      auto DesugaredType = ThisElaboratedType->desugar();
      if (auto *DesugaredTypePtr = DesugaredType.getTypePtrOrNull()) {
        if (auto *ThisRecordType = dyn_cast<RecordType>(DesugaredTypePtr)) {
          return isClassOrStructDeclImpl(ThisRecordType->getAsRecordDecl());
        }
      }
    }
  }

  return false;
}

bool Sema::isClassTemplateDecl() {
  if (!ThisDeclInfo)
    return false;
  if (!ThisDeclInfo->IsFilled)
    inspectThisDecl();
  return ThisDeclInfo->CurrentDecl &&
          (isa<ClassTemplateDecl>(ThisDeclInfo->CurrentDecl));
}

bool Sema::isFunctionTemplateDecl() {
  if (!ThisDeclInfo)
    return false;
  if (!ThisDeclInfo->IsFilled)
    inspectThisDecl();
  return ThisDeclInfo->CurrentDecl &&
         (isa<FunctionTemplateDecl>(ThisDeclInfo->CurrentDecl));
}

bool Sema::isObjCInterfaceDecl() {
  if (!ThisDeclInfo)
    return false;
  if (!ThisDeclInfo->IsFilled)
    inspectThisDecl();
  return ThisDeclInfo->CurrentDecl &&
         isa<ObjCInterfaceDecl>(ThisDeclInfo->CurrentDecl);
}

bool Sema::isObjCProtocolDecl() {
  if (!ThisDeclInfo)
    return false;
  if (!ThisDeclInfo->IsFilled)
    inspectThisDecl();
  return ThisDeclInfo->CurrentDecl &&
         isa<ObjCProtocolDecl>(ThisDeclInfo->CurrentDecl);
}

ArrayRef<const ParmVarDecl *> Sema::getParamVars() {
  if (!ThisDeclInfo->IsFilled)
    inspectThisDecl();
  return ThisDeclInfo->ParamVars;
}

void Sema::inspectThisDecl() {
  ThisDeclInfo->fill();
}

unsigned Sema::resolveParmVarReference(StringRef Name,
                                       ArrayRef<const ParmVarDecl *> ParamVars) {
  for (unsigned i = 0, e = ParamVars.size(); i != e; ++i) {
    const IdentifierInfo *II = ParamVars[i]->getIdentifier();
    if (II && II->getName() == Name)
      return i;
  }
  if (Name == "..." && isFunctionOrMethodVariadic())
    return ParamCommandComment::VarArgParamIndex;
  return ParamCommandComment::InvalidParamIndex;
}

unsigned
Sema::correctTypoInParmVarReference(StringRef Typo,
                                    ArrayRef<const ParmVarDecl *> ParamVars) {
  SimpleTypoCorrection STC(Typo);
  for (unsigned i = 0, e = ParamVars.size(); i != e; ++i) {
    const ParmVarDecl *Param = ParamVars[i];
    if (!Param)
      continue;

    STC.add(Param->getIdentifier());
  }

  if (STC.hasCorrection())
    return STC.getCorrectionIndex();

  return ParamCommandComment::InvalidParamIndex;
}

namespace {
bool ResolveTParamReferenceHelper(
                            StringRef Name,
                            const TemplateParameterList *TemplateParameters,
                            SmallVectorImpl<unsigned> *Position) {
  for (unsigned i = 0, e = TemplateParameters->size(); i != e; ++i) {
    const NamedDecl *Param = TemplateParameters->getParam(i);
    const IdentifierInfo *II = Param->getIdentifier();
    if (II && II->getName() == Name) {
      Position->push_back(i);
      return true;
    }

    if (const TemplateTemplateParmDecl *TTP =
            dyn_cast<TemplateTemplateParmDecl>(Param)) {
      Position->push_back(i);
      if (ResolveTParamReferenceHelper(Name, TTP->getTemplateParameters(),
                                       Position))
        return true;
      Position->pop_back();
    }
  }
  return false;
}
} // end anonymous namespace

bool Sema::resolveTParamReference(
                            StringRef Name,
                            const TemplateParameterList *TemplateParameters,
                            SmallVectorImpl<unsigned> *Position) {
  Position->clear();
  if (!TemplateParameters)
    return false;

  return ResolveTParamReferenceHelper(Name, TemplateParameters, Position);
}

namespace {
void CorrectTypoInTParamReferenceHelper(
    const TemplateParameterList *TemplateParameters,
    SimpleTypoCorrection &STC) {
  for (unsigned i = 0, e = TemplateParameters->size(); i != e; ++i) {
    const NamedDecl *Param = TemplateParameters->getParam(i);
    if (!Param)
      continue;

    STC.add(Param->getIdentifier());

    if (const TemplateTemplateParmDecl *TTP =
            dyn_cast<TemplateTemplateParmDecl>(Param))
      CorrectTypoInTParamReferenceHelper(TTP->getTemplateParameters(), STC);
  }
}
} // end anonymous namespace

StringRef Sema::correctTypoInTParamReference(
                            StringRef Typo,
                            const TemplateParameterList *TemplateParameters) {
  SimpleTypoCorrection STC(Typo);
  CorrectTypoInTParamReferenceHelper(TemplateParameters, STC);

  if (auto CorrectedTParamReference = STC.getCorrection())
    return *CorrectedTParamReference;

  return StringRef();
}

InlineCommandRenderKind Sema::getInlineCommandRenderKind(StringRef Name) const {
  assert(Traits.getCommandInfo(Name)->IsInlineCommand);

  return llvm::StringSwitch<InlineCommandRenderKind>(Name)
      .Case("b", InlineCommandRenderKind::Bold)
      .Cases("c", "p", InlineCommandRenderKind::Monospaced)
      .Cases("a", "e", "em", InlineCommandRenderKind::Emphasized)
      .Case("anchor", InlineCommandRenderKind::Anchor)
      .Default(InlineCommandRenderKind::Normal);
}

} // end namespace comments
} // end namespace clang
