//===--- CommentSema.cpp - Doxygen comment semantic analysis --------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "clang/AST/CommentSema.h"
#include "clang/AST/Attr.h"
#include "clang/AST/CommentCommandTraits.h"
#include "clang/AST/CommentDiagnostic.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Lex/Preprocessor.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringSwitch.h"
namespace clang {
namespace comments {
namespace {
#include "clang/AST/CommentHTMLTagsProperties.inc"
} // unnamed 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(NULL), BriefCommand(NULL), ReturnsCommand(NULL),
HeaderfileCommand(NULL) {
}
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);
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 (!isFunctionDecl())
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() ? 1 : 0;
break;
case CommandTraits::KCI_functiongroup:
DiagSelect = !isAnyFunctionDecl() ? 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)
<<