Comment.cpp revision dd7b803e6ce5b8e61cf3b14af2c57199e5e991d9
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 Kind = OtherKind; 145 TemplateKind = NotTemplate; 146 IsObjCMethod = false; 147 IsInstanceMethod = false; 148 IsClassMethod = false; 149 ParamVars = ArrayRef<const ParmVarDecl *>(); 150 TemplateParameters = NULL; 151 152 if (!ThisDecl) { 153 // If there is no declaration, the defaults is our only guess. 154 IsFilled = true; 155 return; 156 } 157 158 Decl::Kind K = ThisDecl->getKind(); 159 switch (K) { 160 default: 161 // Defaults are should be good for declarations we don't handle explicitly. 162 break; 163 case Decl::Function: 164 case Decl::CXXMethod: 165 case Decl::CXXConstructor: 166 case Decl::CXXDestructor: 167 case Decl::CXXConversion: { 168 const FunctionDecl *FD = cast<FunctionDecl>(ThisDecl); 169 Kind = FunctionKind; 170 ParamVars = ArrayRef<const ParmVarDecl *>(FD->param_begin(), 171 FD->getNumParams()); 172 ResultType = FD->getResultType(); 173 unsigned NumLists = FD->getNumTemplateParameterLists(); 174 if (NumLists != 0) { 175 TemplateKind = TemplateSpecialization; 176 TemplateParameters = 177 FD->getTemplateParameterList(NumLists - 1); 178 } 179 180 if (K == Decl::CXXMethod || K == Decl::CXXConstructor || 181 K == Decl::CXXDestructor || K == Decl::CXXConversion) { 182 const CXXMethodDecl *MD = cast<CXXMethodDecl>(ThisDecl); 183 IsInstanceMethod = MD->isInstance(); 184 IsClassMethod = !IsInstanceMethod; 185 } 186 break; 187 } 188 case Decl::ObjCMethod: { 189 const ObjCMethodDecl *MD = cast<ObjCMethodDecl>(ThisDecl); 190 Kind = FunctionKind; 191 ParamVars = ArrayRef<const ParmVarDecl *>(MD->param_begin(), 192 MD->param_size()); 193 ResultType = MD->getResultType(); 194 IsObjCMethod = true; 195 IsInstanceMethod = MD->isInstanceMethod(); 196 IsClassMethod = !IsInstanceMethod; 197 break; 198 } 199 case Decl::FunctionTemplate: { 200 const FunctionTemplateDecl *FTD = cast<FunctionTemplateDecl>(ThisDecl); 201 Kind = FunctionKind; 202 TemplateKind = Template; 203 const FunctionDecl *FD = FTD->getTemplatedDecl(); 204 ParamVars = ArrayRef<const ParmVarDecl *>(FD->param_begin(), 205 FD->getNumParams()); 206 ResultType = FD->getResultType(); 207 TemplateParameters = FTD->getTemplateParameters(); 208 break; 209 } 210 case Decl::ClassTemplate: { 211 const ClassTemplateDecl *CTD = cast<ClassTemplateDecl>(ThisDecl); 212 Kind = ClassKind; 213 TemplateKind = Template; 214 TemplateParameters = CTD->getTemplateParameters(); 215 break; 216 } 217 case Decl::ClassTemplatePartialSpecialization: { 218 const ClassTemplatePartialSpecializationDecl *CTPSD = 219 cast<ClassTemplatePartialSpecializationDecl>(ThisDecl); 220 Kind = ClassKind; 221 TemplateKind = TemplatePartialSpecialization; 222 TemplateParameters = CTPSD->getTemplateParameters(); 223 break; 224 } 225 case Decl::ClassTemplateSpecialization: 226 Kind = ClassKind; 227 TemplateKind = TemplateSpecialization; 228 break; 229 case Decl::Record: 230 case Decl::CXXRecord: 231 Kind = ClassKind; 232 break; 233 case Decl::Var: 234 case Decl::Field: 235 case Decl::EnumConstant: 236 case Decl::ObjCIvar: 237 case Decl::ObjCAtDefsField: 238 Kind = VariableKind; 239 break; 240 case Decl::Namespace: 241 Kind = NamespaceKind; 242 break; 243 case Decl::Typedef: 244 case Decl::TypeAlias: 245 Kind = TypedefKind; 246 break; 247 case Decl::TypeAliasTemplate: { 248 const TypeAliasTemplateDecl *TAT = cast<TypeAliasTemplateDecl>(ThisDecl); 249 Kind = TypedefKind; 250 TemplateKind = Template; 251 TemplateParameters = TAT->getTemplateParameters(); 252 break; 253 } 254 } 255 256 IsFilled = true; 257} 258 259} // end namespace comments 260} // end namespace clang 261 262