clang API Documentation
00001 //===--- Comment.cpp - Comment AST node implementation --------------------===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 00010 #include "clang/AST/ASTContext.h" 00011 #include "clang/AST/Comment.h" 00012 #include "clang/AST/Decl.h" 00013 #include "clang/AST/DeclObjC.h" 00014 #include "clang/AST/DeclTemplate.h" 00015 #include "clang/Basic/CharInfo.h" 00016 #include "llvm/Support/ErrorHandling.h" 00017 #include "llvm/Support/raw_ostream.h" 00018 00019 namespace clang { 00020 namespace comments { 00021 00022 const char *Comment::getCommentKindName() const { 00023 switch (getCommentKind()) { 00024 case NoCommentKind: return "NoCommentKind"; 00025 #define ABSTRACT_COMMENT(COMMENT) 00026 #define COMMENT(CLASS, PARENT) \ 00027 case CLASS##Kind: \ 00028 return #CLASS; 00029 #include "clang/AST/CommentNodes.inc" 00030 #undef COMMENT 00031 #undef ABSTRACT_COMMENT 00032 } 00033 llvm_unreachable("Unknown comment kind!"); 00034 } 00035 00036 namespace { 00037 struct good {}; 00038 struct bad {}; 00039 00040 template <typename T> 00041 good implements_child_begin_end(Comment::child_iterator (T::*)() const) { 00042 return good(); 00043 } 00044 00045 LLVM_ATTRIBUTE_UNUSED 00046 static inline bad implements_child_begin_end( 00047 Comment::child_iterator (Comment::*)() const) { 00048 return bad(); 00049 } 00050 00051 #define ASSERT_IMPLEMENTS_child_begin(function) \ 00052 (void) good(implements_child_begin_end(function)) 00053 00054 LLVM_ATTRIBUTE_UNUSED 00055 static inline void CheckCommentASTNodes() { 00056 #define ABSTRACT_COMMENT(COMMENT) 00057 #define COMMENT(CLASS, PARENT) \ 00058 ASSERT_IMPLEMENTS_child_begin(&CLASS::child_begin); \ 00059 ASSERT_IMPLEMENTS_child_begin(&CLASS::child_end); 00060 #include "clang/AST/CommentNodes.inc" 00061 #undef COMMENT 00062 #undef ABSTRACT_COMMENT 00063 } 00064 00065 #undef ASSERT_IMPLEMENTS_child_begin 00066 00067 } // end unnamed namespace 00068 00069 Comment::child_iterator Comment::child_begin() const { 00070 switch (getCommentKind()) { 00071 case NoCommentKind: llvm_unreachable("comment without a kind"); 00072 #define ABSTRACT_COMMENT(COMMENT) 00073 #define COMMENT(CLASS, PARENT) \ 00074 case CLASS##Kind: \ 00075 return static_cast<const CLASS *>(this)->child_begin(); 00076 #include "clang/AST/CommentNodes.inc" 00077 #undef COMMENT 00078 #undef ABSTRACT_COMMENT 00079 } 00080 llvm_unreachable("Unknown comment kind!"); 00081 } 00082 00083 Comment::child_iterator Comment::child_end() const { 00084 switch (getCommentKind()) { 00085 case NoCommentKind: llvm_unreachable("comment without a kind"); 00086 #define ABSTRACT_COMMENT(COMMENT) 00087 #define COMMENT(CLASS, PARENT) \ 00088 case CLASS##Kind: \ 00089 return static_cast<const CLASS *>(this)->child_end(); 00090 #include "clang/AST/CommentNodes.inc" 00091 #undef COMMENT 00092 #undef ABSTRACT_COMMENT 00093 } 00094 llvm_unreachable("Unknown comment kind!"); 00095 } 00096 00097 bool TextComment::isWhitespaceNoCache() const { 00098 for (StringRef::const_iterator I = Text.begin(), E = Text.end(); 00099 I != E; ++I) { 00100 if (!clang::isWhitespace(*I)) 00101 return false; 00102 } 00103 return true; 00104 } 00105 00106 bool ParagraphComment::isWhitespaceNoCache() const { 00107 for (child_iterator I = child_begin(), E = child_end(); I != E; ++I) { 00108 if (const TextComment *TC = dyn_cast<TextComment>(*I)) { 00109 if (!TC->isWhitespace()) 00110 return false; 00111 } else 00112 return false; 00113 } 00114 return true; 00115 } 00116 00117 const char *ParamCommandComment::getDirectionAsString(PassDirection D) { 00118 switch (D) { 00119 case ParamCommandComment::In: 00120 return "[in]"; 00121 case ParamCommandComment::Out: 00122 return "[out]"; 00123 case ParamCommandComment::InOut: 00124 return "[in,out]"; 00125 } 00126 llvm_unreachable("unknown PassDirection"); 00127 } 00128 00129 void DeclInfo::fill() { 00130 assert(!IsFilled); 00131 00132 // Set defaults. 00133 Kind = OtherKind; 00134 TemplateKind = NotTemplate; 00135 IsObjCMethod = false; 00136 IsInstanceMethod = false; 00137 IsClassMethod = false; 00138 ParamVars = None; 00139 TemplateParameters = nullptr; 00140 00141 if (!CommentDecl) { 00142 // If there is no declaration, the defaults is our only guess. 00143 IsFilled = true; 00144 return; 00145 } 00146 CurrentDecl = CommentDecl; 00147 00148 Decl::Kind K = CommentDecl->getKind(); 00149 switch (K) { 00150 default: 00151 // Defaults are should be good for declarations we don't handle explicitly. 00152 break; 00153 case Decl::Function: 00154 case Decl::CXXMethod: 00155 case Decl::CXXConstructor: 00156 case Decl::CXXDestructor: 00157 case Decl::CXXConversion: { 00158 const FunctionDecl *FD = cast<FunctionDecl>(CommentDecl); 00159 Kind = FunctionKind; 00160 ParamVars = llvm::makeArrayRef(FD->param_begin(), FD->getNumParams()); 00161 ReturnType = FD->getReturnType(); 00162 unsigned NumLists = FD->getNumTemplateParameterLists(); 00163 if (NumLists != 0) { 00164 TemplateKind = TemplateSpecialization; 00165 TemplateParameters = 00166 FD->getTemplateParameterList(NumLists - 1); 00167 } 00168 00169 if (K == Decl::CXXMethod || K == Decl::CXXConstructor || 00170 K == Decl::CXXDestructor || K == Decl::CXXConversion) { 00171 const CXXMethodDecl *MD = cast<CXXMethodDecl>(CommentDecl); 00172 IsInstanceMethod = MD->isInstance(); 00173 IsClassMethod = !IsInstanceMethod; 00174 } 00175 break; 00176 } 00177 case Decl::ObjCMethod: { 00178 const ObjCMethodDecl *MD = cast<ObjCMethodDecl>(CommentDecl); 00179 Kind = FunctionKind; 00180 ParamVars = llvm::makeArrayRef(MD->param_begin(), MD->param_size()); 00181 ReturnType = MD->getReturnType(); 00182 IsObjCMethod = true; 00183 IsInstanceMethod = MD->isInstanceMethod(); 00184 IsClassMethod = !IsInstanceMethod; 00185 break; 00186 } 00187 case Decl::FunctionTemplate: { 00188 const FunctionTemplateDecl *FTD = cast<FunctionTemplateDecl>(CommentDecl); 00189 Kind = FunctionKind; 00190 TemplateKind = Template; 00191 const FunctionDecl *FD = FTD->getTemplatedDecl(); 00192 ParamVars = llvm::makeArrayRef(FD->param_begin(), FD->getNumParams()); 00193 ReturnType = FD->getReturnType(); 00194 TemplateParameters = FTD->getTemplateParameters(); 00195 break; 00196 } 00197 case Decl::ClassTemplate: { 00198 const ClassTemplateDecl *CTD = cast<ClassTemplateDecl>(CommentDecl); 00199 Kind = ClassKind; 00200 TemplateKind = Template; 00201 TemplateParameters = CTD->getTemplateParameters(); 00202 break; 00203 } 00204 case Decl::ClassTemplatePartialSpecialization: { 00205 const ClassTemplatePartialSpecializationDecl *CTPSD = 00206 cast<ClassTemplatePartialSpecializationDecl>(CommentDecl); 00207 Kind = ClassKind; 00208 TemplateKind = TemplatePartialSpecialization; 00209 TemplateParameters = CTPSD->getTemplateParameters(); 00210 break; 00211 } 00212 case Decl::ClassTemplateSpecialization: 00213 Kind = ClassKind; 00214 TemplateKind = TemplateSpecialization; 00215 break; 00216 case Decl::Record: 00217 case Decl::CXXRecord: 00218 Kind = ClassKind; 00219 break; 00220 case Decl::Var: 00221 case Decl::Field: 00222 case Decl::EnumConstant: 00223 case Decl::ObjCIvar: 00224 case Decl::ObjCAtDefsField: 00225 Kind = VariableKind; 00226 break; 00227 case Decl::Namespace: 00228 Kind = NamespaceKind; 00229 break; 00230 case Decl::Typedef: { 00231 Kind = TypedefKind; 00232 // If this is a typedef to something we consider a function, extract 00233 // arguments and return type. 00234 const TypedefDecl *TD = cast<TypedefDecl>(CommentDecl); 00235 const TypeSourceInfo *TSI = TD->getTypeSourceInfo(); 00236 if (!TSI) 00237 break; 00238 TypeLoc TL = TSI->getTypeLoc().getUnqualifiedLoc(); 00239 while (true) { 00240 TL = TL.IgnoreParens(); 00241 // Look through qualified types. 00242 if (QualifiedTypeLoc QualifiedTL = TL.getAs<QualifiedTypeLoc>()) { 00243 TL = QualifiedTL.getUnqualifiedLoc(); 00244 continue; 00245 } 00246 // Look through pointer types. 00247 if (PointerTypeLoc PointerTL = TL.getAs<PointerTypeLoc>()) { 00248 TL = PointerTL.getPointeeLoc().getUnqualifiedLoc(); 00249 continue; 00250 } 00251 // Look through reference types. 00252 if (ReferenceTypeLoc ReferenceTL = TL.getAs<ReferenceTypeLoc>()) { 00253 TL = ReferenceTL.getPointeeLoc().getUnqualifiedLoc(); 00254 continue; 00255 } 00256 // Look through adjusted types. 00257 if (AdjustedTypeLoc ATL = TL.getAs<AdjustedTypeLoc>()) { 00258 TL = ATL.getOriginalLoc(); 00259 continue; 00260 } 00261 if (BlockPointerTypeLoc BlockPointerTL = 00262 TL.getAs<BlockPointerTypeLoc>()) { 00263 TL = BlockPointerTL.getPointeeLoc().getUnqualifiedLoc(); 00264 continue; 00265 } 00266 if (MemberPointerTypeLoc MemberPointerTL = 00267 TL.getAs<MemberPointerTypeLoc>()) { 00268 TL = MemberPointerTL.getPointeeLoc().getUnqualifiedLoc(); 00269 continue; 00270 } 00271 if (ElaboratedTypeLoc ETL = TL.getAs<ElaboratedTypeLoc>()) { 00272 TL = ETL.getNamedTypeLoc(); 00273 continue; 00274 } 00275 // Is this a typedef for a function type? 00276 if (FunctionTypeLoc FTL = TL.getAs<FunctionTypeLoc>()) { 00277 Kind = FunctionKind; 00278 ParamVars = FTL.getParams(); 00279 ReturnType = FTL.getReturnLoc().getType(); 00280 break; 00281 } 00282 if (TemplateSpecializationTypeLoc STL = 00283 TL.getAs<TemplateSpecializationTypeLoc>()) { 00284 // If we have a typedef to a template specialization with exactly one 00285 // template argument of a function type, this looks like std::function, 00286 // boost::function, or other function wrapper. Treat these typedefs as 00287 // functions. 00288 if (STL.getNumArgs() != 1) 00289 break; 00290 TemplateArgumentLoc MaybeFunction = STL.getArgLoc(0); 00291 if (MaybeFunction.getArgument().getKind() != TemplateArgument::Type) 00292 break; 00293 TypeSourceInfo *MaybeFunctionTSI = MaybeFunction.getTypeSourceInfo(); 00294 TypeLoc TL = MaybeFunctionTSI->getTypeLoc().getUnqualifiedLoc(); 00295 if (FunctionTypeLoc FTL = TL.getAs<FunctionTypeLoc>()) { 00296 Kind = FunctionKind; 00297 ParamVars = FTL.getParams(); 00298 ReturnType = FTL.getReturnLoc().getType(); 00299 } 00300 break; 00301 } 00302 break; 00303 } 00304 break; 00305 } 00306 case Decl::TypeAlias: 00307 Kind = TypedefKind; 00308 break; 00309 case Decl::TypeAliasTemplate: { 00310 const TypeAliasTemplateDecl *TAT = cast<TypeAliasTemplateDecl>(CommentDecl); 00311 Kind = TypedefKind; 00312 TemplateKind = Template; 00313 TemplateParameters = TAT->getTemplateParameters(); 00314 break; 00315 } 00316 case Decl::Enum: 00317 Kind = EnumKind; 00318 break; 00319 } 00320 00321 IsFilled = true; 00322 } 00323 00324 StringRef ParamCommandComment::getParamName(const FullComment *FC) const { 00325 assert(isParamIndexValid()); 00326 if (isVarArgParam()) 00327 return "..."; 00328 return FC->getDeclInfo()->ParamVars[getParamIndex()]->getName(); 00329 } 00330 00331 StringRef TParamCommandComment::getParamName(const FullComment *FC) const { 00332 assert(isPositionValid()); 00333 const TemplateParameterList *TPL = FC->getDeclInfo()->TemplateParameters; 00334 for (unsigned i = 0, e = getDepth(); i != e; ++i) { 00335 if (i == e-1) 00336 return TPL->getParam(getIndex(i))->getName(); 00337 const NamedDecl *Param = TPL->getParam(getIndex(i)); 00338 if (const TemplateTemplateParmDecl *TTP = 00339 dyn_cast<TemplateTemplateParmDecl>(Param)) 00340 TPL = TTP->getTemplateParameters(); 00341 } 00342 return ""; 00343 } 00344 00345 } // end namespace comments 00346 } // end namespace clang 00347