| //===--- 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; |
| } else if (const TypeAliasTemplateDecl *TAT = |
| dyn_cast<TypeAliasTemplateDecl>(ThisDecl)) { |
| IsTemplateDecl = true; |
| TemplateParameters = TAT->getTemplateParameters(); |
| } |
| IsFilled = true; |
| } |
| |
| } // end namespace comments |
| } // end namespace clang |