Comment.cpp revision 1ca7ecc8854ffea215c033a0d8482551bf1b73f0
1//===--- Comment.cpp - Comment AST node implementation --------------------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9 10#include "clang/AST/Comment.h" 11#include "clang/AST/Decl.h" 12#include "clang/AST/DeclObjC.h" 13#include "clang/AST/DeclTemplate.h" 14#include "llvm/Support/ErrorHandling.h" 15#include "llvm/Support/raw_ostream.h" 16 17namespace clang { 18namespace comments { 19 20const char *Comment::getCommentKindName() const { 21 switch (getCommentKind()) { 22 case NoCommentKind: return "NoCommentKind"; 23#define ABSTRACT_COMMENT(COMMENT) 24#define COMMENT(CLASS, PARENT) \ 25 case CLASS##Kind: \ 26 return #CLASS; 27#include "clang/AST/CommentNodes.inc" 28#undef COMMENT 29#undef ABSTRACT_COMMENT 30 } 31 llvm_unreachable("Unknown comment kind!"); 32} 33 34void Comment::dump() const { 35 // It is important that Comment::dump() is defined in a different TU than 36 // Comment::dump(raw_ostream, SourceManager). If both functions were defined 37 // in CommentDumper.cpp, that object file would be removed by linker because 38 // none of its functions are referenced by other object files, despite the 39 // LLVM_ATTRIBUTE_USED. 40 dump(llvm::errs(), NULL); 41} 42 43void Comment::dump(SourceManager &SM) const { 44 dump(llvm::errs(), &SM); 45} 46 47namespace { 48struct good {}; 49struct bad {}; 50 51template <typename T> 52good implements_child_begin_end(Comment::child_iterator (T::*)() const) { 53 return good(); 54} 55 56static inline bad implements_child_begin_end( 57 Comment::child_iterator (Comment::*)() const) { 58 return bad(); 59} 60 61#define ASSERT_IMPLEMENTS_child_begin(function) \ 62 (void) sizeof(good(implements_child_begin_end(function))) 63 64static inline void CheckCommentASTNodes() { 65#define ABSTRACT_COMMENT(COMMENT) 66#define COMMENT(CLASS, PARENT) \ 67 ASSERT_IMPLEMENTS_child_begin(&CLASS::child_begin); \ 68 ASSERT_IMPLEMENTS_child_begin(&CLASS::child_end); 69#include "clang/AST/CommentNodes.inc" 70#undef COMMENT 71#undef ABSTRACT_COMMENT 72} 73 74#undef ASSERT_IMPLEMENTS_child_begin 75 76} // end unnamed namespace 77 78Comment::child_iterator Comment::child_begin() const { 79 switch (getCommentKind()) { 80 case NoCommentKind: llvm_unreachable("comment without a kind"); 81#define ABSTRACT_COMMENT(COMMENT) 82#define COMMENT(CLASS, PARENT) \ 83 case CLASS##Kind: \ 84 return static_cast<const CLASS *>(this)->child_begin(); 85#include "clang/AST/CommentNodes.inc" 86#undef COMMENT 87#undef ABSTRACT_COMMENT 88 } 89 llvm_unreachable("Unknown comment kind!"); 90} 91 92Comment::child_iterator Comment::child_end() const { 93 switch (getCommentKind()) { 94 case NoCommentKind: llvm_unreachable("comment without a kind"); 95#define ABSTRACT_COMMENT(COMMENT) 96#define COMMENT(CLASS, PARENT) \ 97 case CLASS##Kind: \ 98 return static_cast<const CLASS *>(this)->child_end(); 99#include "clang/AST/CommentNodes.inc" 100#undef COMMENT 101#undef ABSTRACT_COMMENT 102 } 103 llvm_unreachable("Unknown comment kind!"); 104} 105 106bool TextComment::isWhitespaceNoCache() const { 107 for (StringRef::const_iterator I = Text.begin(), E = Text.end(); 108 I != E; ++I) { 109 const char C = *I; 110 if (C != ' ' && C != '\n' && C != '\r' && 111 C != '\t' && C != '\f' && C != '\v') 112 return false; 113 } 114 return true; 115} 116 117bool ParagraphComment::isWhitespaceNoCache() const { 118 for (child_iterator I = child_begin(), E = child_end(); I != E; ++I) { 119 if (const TextComment *TC = dyn_cast<TextComment>(*I)) { 120 if (!TC->isWhitespace()) 121 return false; 122 } else 123 return false; 124 } 125 return true; 126} 127 128const char *ParamCommandComment::getDirectionAsString(PassDirection D) { 129 switch (D) { 130 case ParamCommandComment::In: 131 return "[in]"; 132 case ParamCommandComment::Out: 133 return "[out]"; 134 case ParamCommandComment::InOut: 135 return "[in,out]"; 136 } 137 llvm_unreachable("unknown PassDirection"); 138} 139 140void DeclInfo::fill() { 141 assert(!IsFilled); 142 143 // Set defaults. 144 IsFunctionDecl = false; 145 IsTemplateDecl = false; 146 IsTemplateSpecialization = false; 147 IsTemplatePartialSpecialization = false; 148 IsInstanceMethod = false; 149 IsClassMethod = false; 150 ParamVars = ArrayRef<const ParmVarDecl *>(); 151 TemplateParameters = NULL; 152 153 if (!ThisDecl) { 154 // Defaults are OK. 155 } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ThisDecl)) { 156 IsFunctionDecl = true; 157 ParamVars = ArrayRef<const ParmVarDecl *>(FD->param_begin(), 158 FD->getNumParams()); 159 unsigned NumLists = FD->getNumTemplateParameterLists(); 160 if (NumLists != 0) { 161 IsTemplateDecl = true; 162 IsTemplateSpecialization = true; 163 TemplateParameters = 164 FD->getTemplateParameterList(NumLists - 1); 165 } 166 167 if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) { 168 IsInstanceMethod = MD->isInstance(); 169 IsClassMethod = !IsInstanceMethod; 170 } 171 } else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(ThisDecl)) { 172 IsFunctionDecl = true; 173 ParamVars = ArrayRef<const ParmVarDecl *>(MD->param_begin(), 174 MD->param_size()); 175 IsInstanceMethod = MD->isInstanceMethod(); 176 IsClassMethod = !IsInstanceMethod; 177 } else if (const FunctionTemplateDecl *FTD = 178 dyn_cast<FunctionTemplateDecl>(ThisDecl)) { 179 IsFunctionDecl = true; 180 IsTemplateDecl = true; 181 const FunctionDecl *FD = FTD->getTemplatedDecl(); 182 ParamVars = ArrayRef<const ParmVarDecl *>(FD->param_begin(), 183 FD->getNumParams()); 184 TemplateParameters = FTD->getTemplateParameters(); 185 } else if (const ClassTemplateDecl *CTD = 186 dyn_cast<ClassTemplateDecl>(ThisDecl)) { 187 IsTemplateDecl = true; 188 TemplateParameters = CTD->getTemplateParameters(); 189 } else if (const ClassTemplatePartialSpecializationDecl *CTPSD = 190 dyn_cast<ClassTemplatePartialSpecializationDecl>(ThisDecl)) { 191 IsTemplateDecl = true; 192 IsTemplatePartialSpecialization = true; 193 TemplateParameters = CTPSD->getTemplateParameters(); 194 } else if (isa<ClassTemplateSpecializationDecl>(ThisDecl)) { 195 IsTemplateDecl = true; 196 IsTemplateSpecialization = true; 197 } 198 IsFilled = true; 199} 200 201} // end namespace comments 202} // end namespace clang 203