forked from OSchip/llvm-project
203 lines
6.2 KiB
C++
203 lines
6.2 KiB
C++
//===--- Comment.cpp - Comment AST node implementation --------------------===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "clang/AST/Comment.h"
|
|
#include "clang/AST/Decl.h"
|
|
#include "clang/AST/DeclObjC.h"
|
|
#include "clang/AST/DeclTemplate.h"
|
|
#include "llvm/Support/ErrorHandling.h"
|
|
#include "llvm/Support/raw_ostream.h"
|
|
|
|
namespace clang {
|
|
namespace comments {
|
|
|
|
const char *Comment::getCommentKindName() const {
|
|
switch (getCommentKind()) {
|
|
case NoCommentKind: return "NoCommentKind";
|
|
#define ABSTRACT_COMMENT(COMMENT)
|
|
#define COMMENT(CLASS, PARENT) \
|
|
case CLASS##Kind: \
|
|
return #CLASS;
|
|
#include "clang/AST/CommentNodes.inc"
|
|
#undef COMMENT
|
|
#undef ABSTRACT_COMMENT
|
|
}
|
|
llvm_unreachable("Unknown comment kind!");
|
|
}
|
|
|
|
void Comment::dump() const {
|
|
// It is important that Comment::dump() is defined in a different TU than
|
|
// Comment::dump(raw_ostream, SourceManager). If both functions were defined
|
|
// in CommentDumper.cpp, that object file would be removed by linker because
|
|
// none of its functions are referenced by other object files, despite the
|
|
// LLVM_ATTRIBUTE_USED.
|
|
dump(llvm::errs(), NULL);
|
|
}
|
|
|
|
void Comment::dump(SourceManager &SM) const {
|
|
dump(llvm::errs(), &SM);
|
|
}
|
|
|
|
namespace {
|
|
struct good {};
|
|
struct bad {};
|
|
|
|
template <typename T>
|
|
good implements_child_begin_end(Comment::child_iterator (T::*)() const) {
|
|
return good();
|
|
}
|
|
|
|
static inline bad implements_child_begin_end(
|
|
Comment::child_iterator (Comment::*)() const) {
|
|
return bad();
|
|
}
|
|
|
|
#define ASSERT_IMPLEMENTS_child_begin(function) \
|
|
(void) sizeof(good(implements_child_begin_end(function)))
|
|
|
|
static inline void CheckCommentASTNodes() {
|
|
#define ABSTRACT_COMMENT(COMMENT)
|
|
#define COMMENT(CLASS, PARENT) \
|
|
ASSERT_IMPLEMENTS_child_begin(&CLASS::child_begin); \
|
|
ASSERT_IMPLEMENTS_child_begin(&CLASS::child_end);
|
|
#include "clang/AST/CommentNodes.inc"
|
|
#undef COMMENT
|
|
#undef ABSTRACT_COMMENT
|
|
}
|
|
|
|
#undef ASSERT_IMPLEMENTS_child_begin
|
|
|
|
} // end unnamed namespace
|
|
|
|
Comment::child_iterator Comment::child_begin() const {
|
|
switch (getCommentKind()) {
|
|
case NoCommentKind: llvm_unreachable("comment without a kind");
|
|
#define ABSTRACT_COMMENT(COMMENT)
|
|
#define COMMENT(CLASS, PARENT) \
|
|
case CLASS##Kind: \
|
|
return static_cast<const CLASS *>(this)->child_begin();
|
|
#include "clang/AST/CommentNodes.inc"
|
|
#undef COMMENT
|
|
#undef ABSTRACT_COMMENT
|
|
}
|
|
llvm_unreachable("Unknown comment kind!");
|
|
}
|
|
|
|
Comment::child_iterator Comment::child_end() const {
|
|
switch (getCommentKind()) {
|
|
case NoCommentKind: llvm_unreachable("comment without a kind");
|
|
#define ABSTRACT_COMMENT(COMMENT)
|
|
#define COMMENT(CLASS, PARENT) \
|
|
case CLASS##Kind: \
|
|
return static_cast<const CLASS *>(this)->child_end();
|
|
#include "clang/AST/CommentNodes.inc"
|
|
#undef COMMENT
|
|
#undef ABSTRACT_COMMENT
|
|
}
|
|
llvm_unreachable("Unknown comment kind!");
|
|
}
|
|
|
|
bool TextComment::isWhitespaceNoCache() const {
|
|
for (StringRef::const_iterator I = Text.begin(), E = Text.end();
|
|
I != E; ++I) {
|
|
const char C = *I;
|
|
if (C != ' ' && C != '\n' && C != '\r' &&
|
|
C != '\t' && C != '\f' && C != '\v')
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool ParagraphComment::isWhitespaceNoCache() const {
|
|
for (child_iterator I = child_begin(), E = child_end(); I != E; ++I) {
|
|
if (const TextComment *TC = dyn_cast<TextComment>(*I)) {
|
|
if (!TC->isWhitespace())
|
|
return false;
|
|
} else
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
const char *ParamCommandComment::getDirectionAsString(PassDirection D) {
|
|
switch (D) {
|
|
case ParamCommandComment::In:
|
|
return "[in]";
|
|
case ParamCommandComment::Out:
|
|
return "[out]";
|
|
case ParamCommandComment::InOut:
|
|
return "[in,out]";
|
|
}
|
|
llvm_unreachable("unknown PassDirection");
|
|
}
|
|
|
|
void DeclInfo::fill() {
|
|
assert(!IsFilled);
|
|
|
|
// Set defaults.
|
|
IsFunctionDecl = false;
|
|
IsTemplateDecl = false;
|
|
IsTemplateSpecialization = false;
|
|
IsTemplatePartialSpecialization = false;
|
|
IsInstanceMethod = false;
|
|
IsClassMethod = false;
|
|
ParamVars = ArrayRef<const ParmVarDecl *>();
|
|
TemplateParameters = NULL;
|
|
|
|
if (!ThisDecl) {
|
|
// Defaults are OK.
|
|
} else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ThisDecl)) {
|
|
IsFunctionDecl = true;
|
|
ParamVars = ArrayRef<const ParmVarDecl *>(FD->param_begin(),
|
|
FD->getNumParams());
|
|
unsigned NumLists = FD->getNumTemplateParameterLists();
|
|
if (NumLists != 0) {
|
|
IsTemplateDecl = true;
|
|
IsTemplateSpecialization = true;
|
|
TemplateParameters =
|
|
FD->getTemplateParameterList(NumLists - 1);
|
|
}
|
|
|
|
if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) {
|
|
IsInstanceMethod = MD->isInstance();
|
|
IsClassMethod = !IsInstanceMethod;
|
|
}
|
|
} else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(ThisDecl)) {
|
|
IsFunctionDecl = true;
|
|
ParamVars = ArrayRef<const ParmVarDecl *>(MD->param_begin(),
|
|
MD->param_size());
|
|
IsInstanceMethod = MD->isInstanceMethod();
|
|
IsClassMethod = !IsInstanceMethod;
|
|
} else if (const FunctionTemplateDecl *FTD =
|
|
dyn_cast<FunctionTemplateDecl>(ThisDecl)) {
|
|
IsFunctionDecl = true;
|
|
IsTemplateDecl = true;
|
|
const FunctionDecl *FD = FTD->getTemplatedDecl();
|
|
ParamVars = ArrayRef<const ParmVarDecl *>(FD->param_begin(),
|
|
FD->getNumParams());
|
|
TemplateParameters = FTD->getTemplateParameters();
|
|
} else if (const ClassTemplateDecl *CTD =
|
|
dyn_cast<ClassTemplateDecl>(ThisDecl)) {
|
|
IsTemplateDecl = true;
|
|
TemplateParameters = CTD->getTemplateParameters();
|
|
} else if (const ClassTemplatePartialSpecializationDecl *CTPSD =
|
|
dyn_cast<ClassTemplatePartialSpecializationDecl>(ThisDecl)) {
|
|
IsTemplateDecl = true;
|
|
IsTemplatePartialSpecialization = true;
|
|
TemplateParameters = CTPSD->getTemplateParameters();
|
|
} else if (isa<ClassTemplateSpecializationDecl>(ThisDecl)) {
|
|
IsTemplateDecl = true;
|
|
IsTemplateSpecialization = true;
|
|
}
|
|
IsFilled = true;
|
|
}
|
|
|
|
} // end namespace comments
|
|
} // end namespace clang
|