1239313Sdim//===--- Comment.cpp - Comment AST node implementation --------------------===// 2239313Sdim// 3239313Sdim// The LLVM Compiler Infrastructure 4239313Sdim// 5239313Sdim// This file is distributed under the University of Illinois Open Source 6239313Sdim// License. See LICENSE.TXT for details. 7239313Sdim// 8239313Sdim//===----------------------------------------------------------------------===// 9239313Sdim 10243830Sdim#include "clang/AST/ASTContext.h" 11239313Sdim#include "clang/AST/Comment.h" 12239313Sdim#include "clang/AST/Decl.h" 13239313Sdim#include "clang/AST/DeclObjC.h" 14239313Sdim#include "clang/AST/DeclTemplate.h" 15263508Sdim#include "clang/Basic/CharInfo.h" 16239313Sdim#include "llvm/Support/ErrorHandling.h" 17239313Sdim#include "llvm/Support/raw_ostream.h" 18239313Sdim 19239313Sdimnamespace clang { 20239313Sdimnamespace comments { 21239313Sdim 22239313Sdimconst char *Comment::getCommentKindName() const { 23239313Sdim switch (getCommentKind()) { 24239313Sdim case NoCommentKind: return "NoCommentKind"; 25239313Sdim#define ABSTRACT_COMMENT(COMMENT) 26239313Sdim#define COMMENT(CLASS, PARENT) \ 27239313Sdim case CLASS##Kind: \ 28239313Sdim return #CLASS; 29239313Sdim#include "clang/AST/CommentNodes.inc" 30239313Sdim#undef COMMENT 31239313Sdim#undef ABSTRACT_COMMENT 32239313Sdim } 33239313Sdim llvm_unreachable("Unknown comment kind!"); 34239313Sdim} 35239313Sdim 36239313Sdimnamespace { 37239313Sdimstruct good {}; 38239313Sdimstruct bad {}; 39239313Sdim 40239313Sdimtemplate <typename T> 41239313Sdimgood implements_child_begin_end(Comment::child_iterator (T::*)() const) { 42239313Sdim return good(); 43239313Sdim} 44239313Sdim 45263508SdimLLVM_ATTRIBUTE_UNUSED 46239313Sdimstatic inline bad implements_child_begin_end( 47239313Sdim Comment::child_iterator (Comment::*)() const) { 48239313Sdim return bad(); 49239313Sdim} 50239313Sdim 51239313Sdim#define ASSERT_IMPLEMENTS_child_begin(function) \ 52263508Sdim (void) good(implements_child_begin_end(function)) 53239313Sdim 54263508SdimLLVM_ATTRIBUTE_UNUSED 55239313Sdimstatic inline void CheckCommentASTNodes() { 56239313Sdim#define ABSTRACT_COMMENT(COMMENT) 57239313Sdim#define COMMENT(CLASS, PARENT) \ 58239313Sdim ASSERT_IMPLEMENTS_child_begin(&CLASS::child_begin); \ 59239313Sdim ASSERT_IMPLEMENTS_child_begin(&CLASS::child_end); 60239313Sdim#include "clang/AST/CommentNodes.inc" 61239313Sdim#undef COMMENT 62239313Sdim#undef ABSTRACT_COMMENT 63239313Sdim} 64239313Sdim 65239313Sdim#undef ASSERT_IMPLEMENTS_child_begin 66239313Sdim 67239313Sdim} // end unnamed namespace 68239313Sdim 69239313SdimComment::child_iterator Comment::child_begin() const { 70239313Sdim switch (getCommentKind()) { 71239313Sdim case NoCommentKind: llvm_unreachable("comment without a kind"); 72239313Sdim#define ABSTRACT_COMMENT(COMMENT) 73239313Sdim#define COMMENT(CLASS, PARENT) \ 74239313Sdim case CLASS##Kind: \ 75239313Sdim return static_cast<const CLASS *>(this)->child_begin(); 76239313Sdim#include "clang/AST/CommentNodes.inc" 77239313Sdim#undef COMMENT 78239313Sdim#undef ABSTRACT_COMMENT 79239313Sdim } 80239313Sdim llvm_unreachable("Unknown comment kind!"); 81239313Sdim} 82239313Sdim 83239313SdimComment::child_iterator Comment::child_end() const { 84239313Sdim switch (getCommentKind()) { 85239313Sdim case NoCommentKind: llvm_unreachable("comment without a kind"); 86239313Sdim#define ABSTRACT_COMMENT(COMMENT) 87239313Sdim#define COMMENT(CLASS, PARENT) \ 88239313Sdim case CLASS##Kind: \ 89239313Sdim return static_cast<const CLASS *>(this)->child_end(); 90239313Sdim#include "clang/AST/CommentNodes.inc" 91239313Sdim#undef COMMENT 92239313Sdim#undef ABSTRACT_COMMENT 93239313Sdim } 94239313Sdim llvm_unreachable("Unknown comment kind!"); 95239313Sdim} 96239313Sdim 97239313Sdimbool TextComment::isWhitespaceNoCache() const { 98239313Sdim for (StringRef::const_iterator I = Text.begin(), E = Text.end(); 99239313Sdim I != E; ++I) { 100263508Sdim if (!clang::isWhitespace(*I)) 101239313Sdim return false; 102239313Sdim } 103239313Sdim return true; 104239313Sdim} 105239313Sdim 106239313Sdimbool ParagraphComment::isWhitespaceNoCache() const { 107239313Sdim for (child_iterator I = child_begin(), E = child_end(); I != E; ++I) { 108239313Sdim if (const TextComment *TC = dyn_cast<TextComment>(*I)) { 109239313Sdim if (!TC->isWhitespace()) 110239313Sdim return false; 111239313Sdim } else 112239313Sdim return false; 113239313Sdim } 114239313Sdim return true; 115239313Sdim} 116239313Sdim 117239313Sdimconst char *ParamCommandComment::getDirectionAsString(PassDirection D) { 118239313Sdim switch (D) { 119239313Sdim case ParamCommandComment::In: 120239313Sdim return "[in]"; 121239313Sdim case ParamCommandComment::Out: 122239313Sdim return "[out]"; 123239313Sdim case ParamCommandComment::InOut: 124239313Sdim return "[in,out]"; 125239313Sdim } 126239313Sdim llvm_unreachable("unknown PassDirection"); 127239313Sdim} 128239313Sdim 129239313Sdimvoid DeclInfo::fill() { 130239313Sdim assert(!IsFilled); 131239313Sdim 132239313Sdim // Set defaults. 133239313Sdim Kind = OtherKind; 134239313Sdim TemplateKind = NotTemplate; 135239313Sdim IsObjCMethod = false; 136239313Sdim IsInstanceMethod = false; 137239313Sdim IsClassMethod = false; 138251662Sdim ParamVars = None; 139239313Sdim TemplateParameters = NULL; 140239313Sdim 141243830Sdim if (!CommentDecl) { 142239313Sdim // If there is no declaration, the defaults is our only guess. 143239313Sdim IsFilled = true; 144239313Sdim return; 145239313Sdim } 146243830Sdim CurrentDecl = CommentDecl; 147243830Sdim 148243830Sdim Decl::Kind K = CommentDecl->getKind(); 149239313Sdim switch (K) { 150239313Sdim default: 151239313Sdim // Defaults are should be good for declarations we don't handle explicitly. 152239313Sdim break; 153239313Sdim case Decl::Function: 154239313Sdim case Decl::CXXMethod: 155239313Sdim case Decl::CXXConstructor: 156239313Sdim case Decl::CXXDestructor: 157239313Sdim case Decl::CXXConversion: { 158243830Sdim const FunctionDecl *FD = cast<FunctionDecl>(CommentDecl); 159239313Sdim Kind = FunctionKind; 160239313Sdim ParamVars = ArrayRef<const ParmVarDecl *>(FD->param_begin(), 161239313Sdim FD->getNumParams()); 162239313Sdim ResultType = FD->getResultType(); 163239313Sdim unsigned NumLists = FD->getNumTemplateParameterLists(); 164239313Sdim if (NumLists != 0) { 165239313Sdim TemplateKind = TemplateSpecialization; 166239313Sdim TemplateParameters = 167239313Sdim FD->getTemplateParameterList(NumLists - 1); 168239313Sdim } 169239313Sdim 170239313Sdim if (K == Decl::CXXMethod || K == Decl::CXXConstructor || 171239313Sdim K == Decl::CXXDestructor || K == Decl::CXXConversion) { 172243830Sdim const CXXMethodDecl *MD = cast<CXXMethodDecl>(CommentDecl); 173239313Sdim IsInstanceMethod = MD->isInstance(); 174239313Sdim IsClassMethod = !IsInstanceMethod; 175239313Sdim } 176239313Sdim break; 177239313Sdim } 178239313Sdim case Decl::ObjCMethod: { 179243830Sdim const ObjCMethodDecl *MD = cast<ObjCMethodDecl>(CommentDecl); 180239313Sdim Kind = FunctionKind; 181239313Sdim ParamVars = ArrayRef<const ParmVarDecl *>(MD->param_begin(), 182239313Sdim MD->param_size()); 183239313Sdim ResultType = MD->getResultType(); 184239313Sdim IsObjCMethod = true; 185239313Sdim IsInstanceMethod = MD->isInstanceMethod(); 186239313Sdim IsClassMethod = !IsInstanceMethod; 187239313Sdim break; 188239313Sdim } 189239313Sdim case Decl::FunctionTemplate: { 190243830Sdim const FunctionTemplateDecl *FTD = cast<FunctionTemplateDecl>(CommentDecl); 191239313Sdim Kind = FunctionKind; 192239313Sdim TemplateKind = Template; 193239313Sdim const FunctionDecl *FD = FTD->getTemplatedDecl(); 194239313Sdim ParamVars = ArrayRef<const ParmVarDecl *>(FD->param_begin(), 195239313Sdim FD->getNumParams()); 196239313Sdim ResultType = FD->getResultType(); 197239313Sdim TemplateParameters = FTD->getTemplateParameters(); 198239313Sdim break; 199239313Sdim } 200239313Sdim case Decl::ClassTemplate: { 201243830Sdim const ClassTemplateDecl *CTD = cast<ClassTemplateDecl>(CommentDecl); 202239313Sdim Kind = ClassKind; 203239313Sdim TemplateKind = Template; 204239313Sdim TemplateParameters = CTD->getTemplateParameters(); 205239313Sdim break; 206239313Sdim } 207239313Sdim case Decl::ClassTemplatePartialSpecialization: { 208239313Sdim const ClassTemplatePartialSpecializationDecl *CTPSD = 209243830Sdim cast<ClassTemplatePartialSpecializationDecl>(CommentDecl); 210239313Sdim Kind = ClassKind; 211239313Sdim TemplateKind = TemplatePartialSpecialization; 212239313Sdim TemplateParameters = CTPSD->getTemplateParameters(); 213239313Sdim break; 214239313Sdim } 215239313Sdim case Decl::ClassTemplateSpecialization: 216239313Sdim Kind = ClassKind; 217239313Sdim TemplateKind = TemplateSpecialization; 218239313Sdim break; 219239313Sdim case Decl::Record: 220239313Sdim case Decl::CXXRecord: 221239313Sdim Kind = ClassKind; 222239313Sdim break; 223239313Sdim case Decl::Var: 224239313Sdim case Decl::Field: 225239313Sdim case Decl::EnumConstant: 226239313Sdim case Decl::ObjCIvar: 227239313Sdim case Decl::ObjCAtDefsField: 228239313Sdim Kind = VariableKind; 229239313Sdim break; 230239313Sdim case Decl::Namespace: 231239313Sdim Kind = NamespaceKind; 232239313Sdim break; 233243830Sdim case Decl::Typedef: { 234243830Sdim Kind = TypedefKind; 235243830Sdim // If this is a typedef to something we consider a function, extract 236243830Sdim // arguments and return type. 237243830Sdim const TypedefDecl *TD = cast<TypedefDecl>(CommentDecl); 238243830Sdim const TypeSourceInfo *TSI = TD->getTypeSourceInfo(); 239243830Sdim if (!TSI) 240243830Sdim break; 241243830Sdim TypeLoc TL = TSI->getTypeLoc().getUnqualifiedLoc(); 242243830Sdim while (true) { 243243830Sdim TL = TL.IgnoreParens(); 244243830Sdim // Look through qualified types. 245249423Sdim if (QualifiedTypeLoc QualifiedTL = TL.getAs<QualifiedTypeLoc>()) { 246249423Sdim TL = QualifiedTL.getUnqualifiedLoc(); 247243830Sdim continue; 248243830Sdim } 249243830Sdim // Look through pointer types. 250249423Sdim if (PointerTypeLoc PointerTL = TL.getAs<PointerTypeLoc>()) { 251249423Sdim TL = PointerTL.getPointeeLoc().getUnqualifiedLoc(); 252243830Sdim continue; 253243830Sdim } 254249423Sdim if (BlockPointerTypeLoc BlockPointerTL = 255249423Sdim TL.getAs<BlockPointerTypeLoc>()) { 256249423Sdim TL = BlockPointerTL.getPointeeLoc().getUnqualifiedLoc(); 257243830Sdim continue; 258243830Sdim } 259249423Sdim if (MemberPointerTypeLoc MemberPointerTL = 260249423Sdim TL.getAs<MemberPointerTypeLoc>()) { 261249423Sdim TL = MemberPointerTL.getPointeeLoc().getUnqualifiedLoc(); 262243830Sdim continue; 263243830Sdim } 264243830Sdim // Is this a typedef for a function type? 265249423Sdim if (FunctionTypeLoc FTL = TL.getAs<FunctionTypeLoc>()) { 266243830Sdim Kind = FunctionKind; 267249423Sdim ArrayRef<ParmVarDecl *> Params = FTL.getParams(); 268243830Sdim ParamVars = ArrayRef<const ParmVarDecl *>(Params.data(), 269243830Sdim Params.size()); 270249423Sdim ResultType = FTL.getResultLoc().getType(); 271243830Sdim break; 272243830Sdim } 273243830Sdim break; 274243830Sdim } 275243830Sdim break; 276243830Sdim } 277239313Sdim case Decl::TypeAlias: 278239313Sdim Kind = TypedefKind; 279239313Sdim break; 280239313Sdim case Decl::TypeAliasTemplate: { 281243830Sdim const TypeAliasTemplateDecl *TAT = cast<TypeAliasTemplateDecl>(CommentDecl); 282239313Sdim Kind = TypedefKind; 283239313Sdim TemplateKind = Template; 284239313Sdim TemplateParameters = TAT->getTemplateParameters(); 285239313Sdim break; 286239313Sdim } 287239313Sdim case Decl::Enum: 288239313Sdim Kind = EnumKind; 289239313Sdim break; 290239313Sdim } 291239313Sdim 292239313Sdim IsFilled = true; 293239313Sdim} 294239313Sdim 295243830SdimStringRef ParamCommandComment::getParamName(const FullComment *FC) const { 296243830Sdim assert(isParamIndexValid()); 297263508Sdim if (isVarArgParam()) 298263508Sdim return "..."; 299263508Sdim return FC->getDeclInfo()->ParamVars[getParamIndex()]->getName(); 300243830Sdim} 301243830Sdim 302243830SdimStringRef TParamCommandComment::getParamName(const FullComment *FC) const { 303243830Sdim assert(isPositionValid()); 304263508Sdim const TemplateParameterList *TPL = FC->getDeclInfo()->TemplateParameters; 305243830Sdim for (unsigned i = 0, e = getDepth(); i != e; ++i) { 306243830Sdim if (i == e-1) 307243830Sdim return TPL->getParam(getIndex(i))->getName(); 308243830Sdim const NamedDecl *Param = TPL->getParam(getIndex(i)); 309243830Sdim if (const TemplateTemplateParmDecl *TTP = 310243830Sdim dyn_cast<TemplateTemplateParmDecl>(Param)) 311243830Sdim TPL = TTP->getTemplateParameters(); 312243830Sdim } 313243830Sdim return ""; 314243830Sdim} 315243830Sdim 316239313Sdim} // end namespace comments 317239313Sdim} // end namespace clang 318239313Sdim 319