1*f4a2713aSLionel Sambuc //===--- Comment.cpp - Comment AST node implementation --------------------===// 2*f4a2713aSLionel Sambuc // 3*f4a2713aSLionel Sambuc // The LLVM Compiler Infrastructure 4*f4a2713aSLionel Sambuc // 5*f4a2713aSLionel Sambuc // This file is distributed under the University of Illinois Open Source 6*f4a2713aSLionel Sambuc // License. See LICENSE.TXT for details. 7*f4a2713aSLionel Sambuc // 8*f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===// 9*f4a2713aSLionel Sambuc 10*f4a2713aSLionel Sambuc #include "clang/AST/ASTContext.h" 11*f4a2713aSLionel Sambuc #include "clang/AST/Comment.h" 12*f4a2713aSLionel Sambuc #include "clang/AST/Decl.h" 13*f4a2713aSLionel Sambuc #include "clang/AST/DeclObjC.h" 14*f4a2713aSLionel Sambuc #include "clang/AST/DeclTemplate.h" 15*f4a2713aSLionel Sambuc #include "clang/Basic/CharInfo.h" 16*f4a2713aSLionel Sambuc #include "llvm/Support/ErrorHandling.h" 17*f4a2713aSLionel Sambuc #include "llvm/Support/raw_ostream.h" 18*f4a2713aSLionel Sambuc 19*f4a2713aSLionel Sambuc namespace clang { 20*f4a2713aSLionel Sambuc namespace comments { 21*f4a2713aSLionel Sambuc 22*f4a2713aSLionel Sambuc const char *Comment::getCommentKindName() const { 23*f4a2713aSLionel Sambuc switch (getCommentKind()) { 24*f4a2713aSLionel Sambuc case NoCommentKind: return "NoCommentKind"; 25*f4a2713aSLionel Sambuc #define ABSTRACT_COMMENT(COMMENT) 26*f4a2713aSLionel Sambuc #define COMMENT(CLASS, PARENT) \ 27*f4a2713aSLionel Sambuc case CLASS##Kind: \ 28*f4a2713aSLionel Sambuc return #CLASS; 29*f4a2713aSLionel Sambuc #include "clang/AST/CommentNodes.inc" 30*f4a2713aSLionel Sambuc #undef COMMENT 31*f4a2713aSLionel Sambuc #undef ABSTRACT_COMMENT 32*f4a2713aSLionel Sambuc } 33*f4a2713aSLionel Sambuc llvm_unreachable("Unknown comment kind!"); 34*f4a2713aSLionel Sambuc } 35*f4a2713aSLionel Sambuc 36*f4a2713aSLionel Sambuc namespace { 37*f4a2713aSLionel Sambuc struct good {}; 38*f4a2713aSLionel Sambuc struct bad {}; 39*f4a2713aSLionel Sambuc 40*f4a2713aSLionel Sambuc template <typename T> 41*f4a2713aSLionel Sambuc good implements_child_begin_end(Comment::child_iterator (T::*)() const) { 42*f4a2713aSLionel Sambuc return good(); 43*f4a2713aSLionel Sambuc } 44*f4a2713aSLionel Sambuc 45*f4a2713aSLionel Sambuc LLVM_ATTRIBUTE_UNUSED 46*f4a2713aSLionel Sambuc static inline bad implements_child_begin_end( 47*f4a2713aSLionel Sambuc Comment::child_iterator (Comment::*)() const) { 48*f4a2713aSLionel Sambuc return bad(); 49*f4a2713aSLionel Sambuc } 50*f4a2713aSLionel Sambuc 51*f4a2713aSLionel Sambuc #define ASSERT_IMPLEMENTS_child_begin(function) \ 52*f4a2713aSLionel Sambuc (void) good(implements_child_begin_end(function)) 53*f4a2713aSLionel Sambuc 54*f4a2713aSLionel Sambuc LLVM_ATTRIBUTE_UNUSED 55*f4a2713aSLionel Sambuc static inline void CheckCommentASTNodes() { 56*f4a2713aSLionel Sambuc #define ABSTRACT_COMMENT(COMMENT) 57*f4a2713aSLionel Sambuc #define COMMENT(CLASS, PARENT) \ 58*f4a2713aSLionel Sambuc ASSERT_IMPLEMENTS_child_begin(&CLASS::child_begin); \ 59*f4a2713aSLionel Sambuc ASSERT_IMPLEMENTS_child_begin(&CLASS::child_end); 60*f4a2713aSLionel Sambuc #include "clang/AST/CommentNodes.inc" 61*f4a2713aSLionel Sambuc #undef COMMENT 62*f4a2713aSLionel Sambuc #undef ABSTRACT_COMMENT 63*f4a2713aSLionel Sambuc } 64*f4a2713aSLionel Sambuc 65*f4a2713aSLionel Sambuc #undef ASSERT_IMPLEMENTS_child_begin 66*f4a2713aSLionel Sambuc 67*f4a2713aSLionel Sambuc } // end unnamed namespace 68*f4a2713aSLionel Sambuc 69*f4a2713aSLionel Sambuc Comment::child_iterator Comment::child_begin() const { 70*f4a2713aSLionel Sambuc switch (getCommentKind()) { 71*f4a2713aSLionel Sambuc case NoCommentKind: llvm_unreachable("comment without a kind"); 72*f4a2713aSLionel Sambuc #define ABSTRACT_COMMENT(COMMENT) 73*f4a2713aSLionel Sambuc #define COMMENT(CLASS, PARENT) \ 74*f4a2713aSLionel Sambuc case CLASS##Kind: \ 75*f4a2713aSLionel Sambuc return static_cast<const CLASS *>(this)->child_begin(); 76*f4a2713aSLionel Sambuc #include "clang/AST/CommentNodes.inc" 77*f4a2713aSLionel Sambuc #undef COMMENT 78*f4a2713aSLionel Sambuc #undef ABSTRACT_COMMENT 79*f4a2713aSLionel Sambuc } 80*f4a2713aSLionel Sambuc llvm_unreachable("Unknown comment kind!"); 81*f4a2713aSLionel Sambuc } 82*f4a2713aSLionel Sambuc 83*f4a2713aSLionel Sambuc Comment::child_iterator Comment::child_end() const { 84*f4a2713aSLionel Sambuc switch (getCommentKind()) { 85*f4a2713aSLionel Sambuc case NoCommentKind: llvm_unreachable("comment without a kind"); 86*f4a2713aSLionel Sambuc #define ABSTRACT_COMMENT(COMMENT) 87*f4a2713aSLionel Sambuc #define COMMENT(CLASS, PARENT) \ 88*f4a2713aSLionel Sambuc case CLASS##Kind: \ 89*f4a2713aSLionel Sambuc return static_cast<const CLASS *>(this)->child_end(); 90*f4a2713aSLionel Sambuc #include "clang/AST/CommentNodes.inc" 91*f4a2713aSLionel Sambuc #undef COMMENT 92*f4a2713aSLionel Sambuc #undef ABSTRACT_COMMENT 93*f4a2713aSLionel Sambuc } 94*f4a2713aSLionel Sambuc llvm_unreachable("Unknown comment kind!"); 95*f4a2713aSLionel Sambuc } 96*f4a2713aSLionel Sambuc 97*f4a2713aSLionel Sambuc bool TextComment::isWhitespaceNoCache() const { 98*f4a2713aSLionel Sambuc for (StringRef::const_iterator I = Text.begin(), E = Text.end(); 99*f4a2713aSLionel Sambuc I != E; ++I) { 100*f4a2713aSLionel Sambuc if (!clang::isWhitespace(*I)) 101*f4a2713aSLionel Sambuc return false; 102*f4a2713aSLionel Sambuc } 103*f4a2713aSLionel Sambuc return true; 104*f4a2713aSLionel Sambuc } 105*f4a2713aSLionel Sambuc 106*f4a2713aSLionel Sambuc bool ParagraphComment::isWhitespaceNoCache() const { 107*f4a2713aSLionel Sambuc for (child_iterator I = child_begin(), E = child_end(); I != E; ++I) { 108*f4a2713aSLionel Sambuc if (const TextComment *TC = dyn_cast<TextComment>(*I)) { 109*f4a2713aSLionel Sambuc if (!TC->isWhitespace()) 110*f4a2713aSLionel Sambuc return false; 111*f4a2713aSLionel Sambuc } else 112*f4a2713aSLionel Sambuc return false; 113*f4a2713aSLionel Sambuc } 114*f4a2713aSLionel Sambuc return true; 115*f4a2713aSLionel Sambuc } 116*f4a2713aSLionel Sambuc 117*f4a2713aSLionel Sambuc const char *ParamCommandComment::getDirectionAsString(PassDirection D) { 118*f4a2713aSLionel Sambuc switch (D) { 119*f4a2713aSLionel Sambuc case ParamCommandComment::In: 120*f4a2713aSLionel Sambuc return "[in]"; 121*f4a2713aSLionel Sambuc case ParamCommandComment::Out: 122*f4a2713aSLionel Sambuc return "[out]"; 123*f4a2713aSLionel Sambuc case ParamCommandComment::InOut: 124*f4a2713aSLionel Sambuc return "[in,out]"; 125*f4a2713aSLionel Sambuc } 126*f4a2713aSLionel Sambuc llvm_unreachable("unknown PassDirection"); 127*f4a2713aSLionel Sambuc } 128*f4a2713aSLionel Sambuc 129*f4a2713aSLionel Sambuc void DeclInfo::fill() { 130*f4a2713aSLionel Sambuc assert(!IsFilled); 131*f4a2713aSLionel Sambuc 132*f4a2713aSLionel Sambuc // Set defaults. 133*f4a2713aSLionel Sambuc Kind = OtherKind; 134*f4a2713aSLionel Sambuc TemplateKind = NotTemplate; 135*f4a2713aSLionel Sambuc IsObjCMethod = false; 136*f4a2713aSLionel Sambuc IsInstanceMethod = false; 137*f4a2713aSLionel Sambuc IsClassMethod = false; 138*f4a2713aSLionel Sambuc ParamVars = None; 139*f4a2713aSLionel Sambuc TemplateParameters = NULL; 140*f4a2713aSLionel Sambuc 141*f4a2713aSLionel Sambuc if (!CommentDecl) { 142*f4a2713aSLionel Sambuc // If there is no declaration, the defaults is our only guess. 143*f4a2713aSLionel Sambuc IsFilled = true; 144*f4a2713aSLionel Sambuc return; 145*f4a2713aSLionel Sambuc } 146*f4a2713aSLionel Sambuc CurrentDecl = CommentDecl; 147*f4a2713aSLionel Sambuc 148*f4a2713aSLionel Sambuc Decl::Kind K = CommentDecl->getKind(); 149*f4a2713aSLionel Sambuc switch (K) { 150*f4a2713aSLionel Sambuc default: 151*f4a2713aSLionel Sambuc // Defaults are should be good for declarations we don't handle explicitly. 152*f4a2713aSLionel Sambuc break; 153*f4a2713aSLionel Sambuc case Decl::Function: 154*f4a2713aSLionel Sambuc case Decl::CXXMethod: 155*f4a2713aSLionel Sambuc case Decl::CXXConstructor: 156*f4a2713aSLionel Sambuc case Decl::CXXDestructor: 157*f4a2713aSLionel Sambuc case Decl::CXXConversion: { 158*f4a2713aSLionel Sambuc const FunctionDecl *FD = cast<FunctionDecl>(CommentDecl); 159*f4a2713aSLionel Sambuc Kind = FunctionKind; 160*f4a2713aSLionel Sambuc ParamVars = ArrayRef<const ParmVarDecl *>(FD->param_begin(), 161*f4a2713aSLionel Sambuc FD->getNumParams()); 162*f4a2713aSLionel Sambuc ResultType = FD->getResultType(); 163*f4a2713aSLionel Sambuc unsigned NumLists = FD->getNumTemplateParameterLists(); 164*f4a2713aSLionel Sambuc if (NumLists != 0) { 165*f4a2713aSLionel Sambuc TemplateKind = TemplateSpecialization; 166*f4a2713aSLionel Sambuc TemplateParameters = 167*f4a2713aSLionel Sambuc FD->getTemplateParameterList(NumLists - 1); 168*f4a2713aSLionel Sambuc } 169*f4a2713aSLionel Sambuc 170*f4a2713aSLionel Sambuc if (K == Decl::CXXMethod || K == Decl::CXXConstructor || 171*f4a2713aSLionel Sambuc K == Decl::CXXDestructor || K == Decl::CXXConversion) { 172*f4a2713aSLionel Sambuc const CXXMethodDecl *MD = cast<CXXMethodDecl>(CommentDecl); 173*f4a2713aSLionel Sambuc IsInstanceMethod = MD->isInstance(); 174*f4a2713aSLionel Sambuc IsClassMethod = !IsInstanceMethod; 175*f4a2713aSLionel Sambuc } 176*f4a2713aSLionel Sambuc break; 177*f4a2713aSLionel Sambuc } 178*f4a2713aSLionel Sambuc case Decl::ObjCMethod: { 179*f4a2713aSLionel Sambuc const ObjCMethodDecl *MD = cast<ObjCMethodDecl>(CommentDecl); 180*f4a2713aSLionel Sambuc Kind = FunctionKind; 181*f4a2713aSLionel Sambuc ParamVars = ArrayRef<const ParmVarDecl *>(MD->param_begin(), 182*f4a2713aSLionel Sambuc MD->param_size()); 183*f4a2713aSLionel Sambuc ResultType = MD->getResultType(); 184*f4a2713aSLionel Sambuc IsObjCMethod = true; 185*f4a2713aSLionel Sambuc IsInstanceMethod = MD->isInstanceMethod(); 186*f4a2713aSLionel Sambuc IsClassMethod = !IsInstanceMethod; 187*f4a2713aSLionel Sambuc break; 188*f4a2713aSLionel Sambuc } 189*f4a2713aSLionel Sambuc case Decl::FunctionTemplate: { 190*f4a2713aSLionel Sambuc const FunctionTemplateDecl *FTD = cast<FunctionTemplateDecl>(CommentDecl); 191*f4a2713aSLionel Sambuc Kind = FunctionKind; 192*f4a2713aSLionel Sambuc TemplateKind = Template; 193*f4a2713aSLionel Sambuc const FunctionDecl *FD = FTD->getTemplatedDecl(); 194*f4a2713aSLionel Sambuc ParamVars = ArrayRef<const ParmVarDecl *>(FD->param_begin(), 195*f4a2713aSLionel Sambuc FD->getNumParams()); 196*f4a2713aSLionel Sambuc ResultType = FD->getResultType(); 197*f4a2713aSLionel Sambuc TemplateParameters = FTD->getTemplateParameters(); 198*f4a2713aSLionel Sambuc break; 199*f4a2713aSLionel Sambuc } 200*f4a2713aSLionel Sambuc case Decl::ClassTemplate: { 201*f4a2713aSLionel Sambuc const ClassTemplateDecl *CTD = cast<ClassTemplateDecl>(CommentDecl); 202*f4a2713aSLionel Sambuc Kind = ClassKind; 203*f4a2713aSLionel Sambuc TemplateKind = Template; 204*f4a2713aSLionel Sambuc TemplateParameters = CTD->getTemplateParameters(); 205*f4a2713aSLionel Sambuc break; 206*f4a2713aSLionel Sambuc } 207*f4a2713aSLionel Sambuc case Decl::ClassTemplatePartialSpecialization: { 208*f4a2713aSLionel Sambuc const ClassTemplatePartialSpecializationDecl *CTPSD = 209*f4a2713aSLionel Sambuc cast<ClassTemplatePartialSpecializationDecl>(CommentDecl); 210*f4a2713aSLionel Sambuc Kind = ClassKind; 211*f4a2713aSLionel Sambuc TemplateKind = TemplatePartialSpecialization; 212*f4a2713aSLionel Sambuc TemplateParameters = CTPSD->getTemplateParameters(); 213*f4a2713aSLionel Sambuc break; 214*f4a2713aSLionel Sambuc } 215*f4a2713aSLionel Sambuc case Decl::ClassTemplateSpecialization: 216*f4a2713aSLionel Sambuc Kind = ClassKind; 217*f4a2713aSLionel Sambuc TemplateKind = TemplateSpecialization; 218*f4a2713aSLionel Sambuc break; 219*f4a2713aSLionel Sambuc case Decl::Record: 220*f4a2713aSLionel Sambuc case Decl::CXXRecord: 221*f4a2713aSLionel Sambuc Kind = ClassKind; 222*f4a2713aSLionel Sambuc break; 223*f4a2713aSLionel Sambuc case Decl::Var: 224*f4a2713aSLionel Sambuc case Decl::Field: 225*f4a2713aSLionel Sambuc case Decl::EnumConstant: 226*f4a2713aSLionel Sambuc case Decl::ObjCIvar: 227*f4a2713aSLionel Sambuc case Decl::ObjCAtDefsField: 228*f4a2713aSLionel Sambuc Kind = VariableKind; 229*f4a2713aSLionel Sambuc break; 230*f4a2713aSLionel Sambuc case Decl::Namespace: 231*f4a2713aSLionel Sambuc Kind = NamespaceKind; 232*f4a2713aSLionel Sambuc break; 233*f4a2713aSLionel Sambuc case Decl::Typedef: { 234*f4a2713aSLionel Sambuc Kind = TypedefKind; 235*f4a2713aSLionel Sambuc // If this is a typedef to something we consider a function, extract 236*f4a2713aSLionel Sambuc // arguments and return type. 237*f4a2713aSLionel Sambuc const TypedefDecl *TD = cast<TypedefDecl>(CommentDecl); 238*f4a2713aSLionel Sambuc const TypeSourceInfo *TSI = TD->getTypeSourceInfo(); 239*f4a2713aSLionel Sambuc if (!TSI) 240*f4a2713aSLionel Sambuc break; 241*f4a2713aSLionel Sambuc TypeLoc TL = TSI->getTypeLoc().getUnqualifiedLoc(); 242*f4a2713aSLionel Sambuc while (true) { 243*f4a2713aSLionel Sambuc TL = TL.IgnoreParens(); 244*f4a2713aSLionel Sambuc // Look through qualified types. 245*f4a2713aSLionel Sambuc if (QualifiedTypeLoc QualifiedTL = TL.getAs<QualifiedTypeLoc>()) { 246*f4a2713aSLionel Sambuc TL = QualifiedTL.getUnqualifiedLoc(); 247*f4a2713aSLionel Sambuc continue; 248*f4a2713aSLionel Sambuc } 249*f4a2713aSLionel Sambuc // Look through pointer types. 250*f4a2713aSLionel Sambuc if (PointerTypeLoc PointerTL = TL.getAs<PointerTypeLoc>()) { 251*f4a2713aSLionel Sambuc TL = PointerTL.getPointeeLoc().getUnqualifiedLoc(); 252*f4a2713aSLionel Sambuc continue; 253*f4a2713aSLionel Sambuc } 254*f4a2713aSLionel Sambuc if (BlockPointerTypeLoc BlockPointerTL = 255*f4a2713aSLionel Sambuc TL.getAs<BlockPointerTypeLoc>()) { 256*f4a2713aSLionel Sambuc TL = BlockPointerTL.getPointeeLoc().getUnqualifiedLoc(); 257*f4a2713aSLionel Sambuc continue; 258*f4a2713aSLionel Sambuc } 259*f4a2713aSLionel Sambuc if (MemberPointerTypeLoc MemberPointerTL = 260*f4a2713aSLionel Sambuc TL.getAs<MemberPointerTypeLoc>()) { 261*f4a2713aSLionel Sambuc TL = MemberPointerTL.getPointeeLoc().getUnqualifiedLoc(); 262*f4a2713aSLionel Sambuc continue; 263*f4a2713aSLionel Sambuc } 264*f4a2713aSLionel Sambuc // Is this a typedef for a function type? 265*f4a2713aSLionel Sambuc if (FunctionTypeLoc FTL = TL.getAs<FunctionTypeLoc>()) { 266*f4a2713aSLionel Sambuc Kind = FunctionKind; 267*f4a2713aSLionel Sambuc ArrayRef<ParmVarDecl *> Params = FTL.getParams(); 268*f4a2713aSLionel Sambuc ParamVars = ArrayRef<const ParmVarDecl *>(Params.data(), 269*f4a2713aSLionel Sambuc Params.size()); 270*f4a2713aSLionel Sambuc ResultType = FTL.getResultLoc().getType(); 271*f4a2713aSLionel Sambuc break; 272*f4a2713aSLionel Sambuc } 273*f4a2713aSLionel Sambuc break; 274*f4a2713aSLionel Sambuc } 275*f4a2713aSLionel Sambuc break; 276*f4a2713aSLionel Sambuc } 277*f4a2713aSLionel Sambuc case Decl::TypeAlias: 278*f4a2713aSLionel Sambuc Kind = TypedefKind; 279*f4a2713aSLionel Sambuc break; 280*f4a2713aSLionel Sambuc case Decl::TypeAliasTemplate: { 281*f4a2713aSLionel Sambuc const TypeAliasTemplateDecl *TAT = cast<TypeAliasTemplateDecl>(CommentDecl); 282*f4a2713aSLionel Sambuc Kind = TypedefKind; 283*f4a2713aSLionel Sambuc TemplateKind = Template; 284*f4a2713aSLionel Sambuc TemplateParameters = TAT->getTemplateParameters(); 285*f4a2713aSLionel Sambuc break; 286*f4a2713aSLionel Sambuc } 287*f4a2713aSLionel Sambuc case Decl::Enum: 288*f4a2713aSLionel Sambuc Kind = EnumKind; 289*f4a2713aSLionel Sambuc break; 290*f4a2713aSLionel Sambuc } 291*f4a2713aSLionel Sambuc 292*f4a2713aSLionel Sambuc IsFilled = true; 293*f4a2713aSLionel Sambuc } 294*f4a2713aSLionel Sambuc 295*f4a2713aSLionel Sambuc StringRef ParamCommandComment::getParamName(const FullComment *FC) const { 296*f4a2713aSLionel Sambuc assert(isParamIndexValid()); 297*f4a2713aSLionel Sambuc if (isVarArgParam()) 298*f4a2713aSLionel Sambuc return "..."; 299*f4a2713aSLionel Sambuc return FC->getDeclInfo()->ParamVars[getParamIndex()]->getName(); 300*f4a2713aSLionel Sambuc } 301*f4a2713aSLionel Sambuc 302*f4a2713aSLionel Sambuc StringRef TParamCommandComment::getParamName(const FullComment *FC) const { 303*f4a2713aSLionel Sambuc assert(isPositionValid()); 304*f4a2713aSLionel Sambuc const TemplateParameterList *TPL = FC->getDeclInfo()->TemplateParameters; 305*f4a2713aSLionel Sambuc for (unsigned i = 0, e = getDepth(); i != e; ++i) { 306*f4a2713aSLionel Sambuc if (i == e-1) 307*f4a2713aSLionel Sambuc return TPL->getParam(getIndex(i))->getName(); 308*f4a2713aSLionel Sambuc const NamedDecl *Param = TPL->getParam(getIndex(i)); 309*f4a2713aSLionel Sambuc if (const TemplateTemplateParmDecl *TTP = 310*f4a2713aSLionel Sambuc dyn_cast<TemplateTemplateParmDecl>(Param)) 311*f4a2713aSLionel Sambuc TPL = TTP->getTemplateParameters(); 312*f4a2713aSLionel Sambuc } 313*f4a2713aSLionel Sambuc return ""; 314*f4a2713aSLionel Sambuc } 315*f4a2713aSLionel Sambuc 316*f4a2713aSLionel Sambuc } // end namespace comments 317*f4a2713aSLionel Sambuc } // end namespace clang 318*f4a2713aSLionel Sambuc 319