Comment.cpp revision 341825
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 10314564Sdim#include "clang/AST/Comment.h" 11243830Sdim#include "clang/AST/ASTContext.h" 12239313Sdim#include "clang/AST/Decl.h" 13239313Sdim#include "clang/AST/DeclObjC.h" 14239313Sdim#include "clang/AST/DeclTemplate.h" 15261991Sdim#include "clang/Basic/CharInfo.h" 16239313Sdim#include "llvm/Support/ErrorHandling.h" 17239313Sdim 18239313Sdimnamespace clang { 19239313Sdimnamespace comments { 20239313Sdim 21239313Sdimconst char *Comment::getCommentKindName() const { 22239313Sdim switch (getCommentKind()) { 23239313Sdim case NoCommentKind: return "NoCommentKind"; 24239313Sdim#define ABSTRACT_COMMENT(COMMENT) 25239313Sdim#define COMMENT(CLASS, PARENT) \ 26239313Sdim case CLASS##Kind: \ 27239313Sdim return #CLASS; 28239313Sdim#include "clang/AST/CommentNodes.inc" 29239313Sdim#undef COMMENT 30239313Sdim#undef ABSTRACT_COMMENT 31239313Sdim } 32239313Sdim llvm_unreachable("Unknown comment kind!"); 33239313Sdim} 34239313Sdim 35239313Sdimnamespace { 36239313Sdimstruct good {}; 37239313Sdimstruct bad {}; 38239313Sdim 39239313Sdimtemplate <typename T> 40239313Sdimgood implements_child_begin_end(Comment::child_iterator (T::*)() const) { 41239313Sdim return good(); 42239313Sdim} 43239313Sdim 44261991SdimLLVM_ATTRIBUTE_UNUSED 45239313Sdimstatic inline bad implements_child_begin_end( 46239313Sdim Comment::child_iterator (Comment::*)() const) { 47239313Sdim return bad(); 48239313Sdim} 49239313Sdim 50239313Sdim#define ASSERT_IMPLEMENTS_child_begin(function) \ 51261991Sdim (void) good(implements_child_begin_end(function)) 52239313Sdim 53261991SdimLLVM_ATTRIBUTE_UNUSED 54239313Sdimstatic inline void CheckCommentASTNodes() { 55239313Sdim#define ABSTRACT_COMMENT(COMMENT) 56239313Sdim#define COMMENT(CLASS, PARENT) \ 57239313Sdim ASSERT_IMPLEMENTS_child_begin(&CLASS::child_begin); \ 58239313Sdim ASSERT_IMPLEMENTS_child_begin(&CLASS::child_end); 59239313Sdim#include "clang/AST/CommentNodes.inc" 60239313Sdim#undef COMMENT 61239313Sdim#undef ABSTRACT_COMMENT 62239313Sdim} 63239313Sdim 64239313Sdim#undef ASSERT_IMPLEMENTS_child_begin 65239313Sdim 66239313Sdim} // end unnamed namespace 67239313Sdim 68239313SdimComment::child_iterator Comment::child_begin() const { 69239313Sdim switch (getCommentKind()) { 70239313Sdim case NoCommentKind: llvm_unreachable("comment without a kind"); 71239313Sdim#define ABSTRACT_COMMENT(COMMENT) 72239313Sdim#define COMMENT(CLASS, PARENT) \ 73239313Sdim case CLASS##Kind: \ 74239313Sdim return static_cast<const CLASS *>(this)->child_begin(); 75239313Sdim#include "clang/AST/CommentNodes.inc" 76239313Sdim#undef COMMENT 77239313Sdim#undef ABSTRACT_COMMENT 78239313Sdim } 79239313Sdim llvm_unreachable("Unknown comment kind!"); 80239313Sdim} 81239313Sdim 82239313SdimComment::child_iterator Comment::child_end() const { 83239313Sdim switch (getCommentKind()) { 84239313Sdim case NoCommentKind: llvm_unreachable("comment without a kind"); 85239313Sdim#define ABSTRACT_COMMENT(COMMENT) 86239313Sdim#define COMMENT(CLASS, PARENT) \ 87239313Sdim case CLASS##Kind: \ 88239313Sdim return static_cast<const CLASS *>(this)->child_end(); 89239313Sdim#include "clang/AST/CommentNodes.inc" 90239313Sdim#undef COMMENT 91239313Sdim#undef ABSTRACT_COMMENT 92239313Sdim } 93239313Sdim llvm_unreachable("Unknown comment kind!"); 94239313Sdim} 95239313Sdim 96239313Sdimbool TextComment::isWhitespaceNoCache() const { 97239313Sdim for (StringRef::const_iterator I = Text.begin(), E = Text.end(); 98239313Sdim I != E; ++I) { 99261991Sdim if (!clang::isWhitespace(*I)) 100239313Sdim return false; 101239313Sdim } 102239313Sdim return true; 103239313Sdim} 104239313Sdim 105239313Sdimbool ParagraphComment::isWhitespaceNoCache() const { 106239313Sdim for (child_iterator I = child_begin(), E = child_end(); I != E; ++I) { 107239313Sdim if (const TextComment *TC = dyn_cast<TextComment>(*I)) { 108239313Sdim if (!TC->isWhitespace()) 109239313Sdim return false; 110239313Sdim } else 111239313Sdim return false; 112239313Sdim } 113239313Sdim return true; 114239313Sdim} 115239313Sdim 116314564Sdimstatic TypeLoc lookThroughTypedefOrTypeAliasLocs(TypeLoc &SrcTL) { 117314564Sdim TypeLoc TL = SrcTL.IgnoreParens(); 118314564Sdim 119321369Sdim // Look through attribute types. 120321369Sdim if (AttributedTypeLoc AttributeTL = TL.getAs<AttributedTypeLoc>()) 121321369Sdim return AttributeTL.getModifiedLoc(); 122314564Sdim // Look through qualified types. 123314564Sdim if (QualifiedTypeLoc QualifiedTL = TL.getAs<QualifiedTypeLoc>()) 124314564Sdim return QualifiedTL.getUnqualifiedLoc(); 125314564Sdim // Look through pointer types. 126314564Sdim if (PointerTypeLoc PointerTL = TL.getAs<PointerTypeLoc>()) 127314564Sdim return PointerTL.getPointeeLoc().getUnqualifiedLoc(); 128314564Sdim // Look through reference types. 129314564Sdim if (ReferenceTypeLoc ReferenceTL = TL.getAs<ReferenceTypeLoc>()) 130314564Sdim return ReferenceTL.getPointeeLoc().getUnqualifiedLoc(); 131314564Sdim // Look through adjusted types. 132314564Sdim if (AdjustedTypeLoc ATL = TL.getAs<AdjustedTypeLoc>()) 133314564Sdim return ATL.getOriginalLoc(); 134314564Sdim if (BlockPointerTypeLoc BlockPointerTL = TL.getAs<BlockPointerTypeLoc>()) 135314564Sdim return BlockPointerTL.getPointeeLoc().getUnqualifiedLoc(); 136314564Sdim if (MemberPointerTypeLoc MemberPointerTL = TL.getAs<MemberPointerTypeLoc>()) 137314564Sdim return MemberPointerTL.getPointeeLoc().getUnqualifiedLoc(); 138314564Sdim if (ElaboratedTypeLoc ETL = TL.getAs<ElaboratedTypeLoc>()) 139314564Sdim return ETL.getNamedTypeLoc(); 140314564Sdim 141314564Sdim return TL; 142314564Sdim} 143314564Sdim 144314564Sdimstatic bool getFunctionTypeLoc(TypeLoc TL, FunctionTypeLoc &ResFTL) { 145314564Sdim TypeLoc PrevTL; 146314564Sdim while (PrevTL != TL) { 147314564Sdim PrevTL = TL; 148314564Sdim TL = lookThroughTypedefOrTypeAliasLocs(TL); 149314564Sdim } 150314564Sdim 151314564Sdim if (FunctionTypeLoc FTL = TL.getAs<FunctionTypeLoc>()) { 152314564Sdim ResFTL = FTL; 153314564Sdim return true; 154314564Sdim } 155314564Sdim 156314564Sdim if (TemplateSpecializationTypeLoc STL = 157314564Sdim TL.getAs<TemplateSpecializationTypeLoc>()) { 158314564Sdim // If we have a typedef to a template specialization with exactly one 159314564Sdim // template argument of a function type, this looks like std::function, 160314564Sdim // boost::function, or other function wrapper. Treat these typedefs as 161314564Sdim // functions. 162314564Sdim if (STL.getNumArgs() != 1) 163314564Sdim return false; 164314564Sdim TemplateArgumentLoc MaybeFunction = STL.getArgLoc(0); 165314564Sdim if (MaybeFunction.getArgument().getKind() != TemplateArgument::Type) 166314564Sdim return false; 167314564Sdim TypeSourceInfo *MaybeFunctionTSI = MaybeFunction.getTypeSourceInfo(); 168314564Sdim TypeLoc TL = MaybeFunctionTSI->getTypeLoc().getUnqualifiedLoc(); 169314564Sdim if (FunctionTypeLoc FTL = TL.getAs<FunctionTypeLoc>()) { 170314564Sdim ResFTL = FTL; 171314564Sdim return true; 172314564Sdim } 173314564Sdim } 174314564Sdim 175314564Sdim return false; 176314564Sdim} 177314564Sdim 178239313Sdimconst char *ParamCommandComment::getDirectionAsString(PassDirection D) { 179239313Sdim switch (D) { 180239313Sdim case ParamCommandComment::In: 181239313Sdim return "[in]"; 182239313Sdim case ParamCommandComment::Out: 183239313Sdim return "[out]"; 184239313Sdim case ParamCommandComment::InOut: 185239313Sdim return "[in,out]"; 186239313Sdim } 187239313Sdim llvm_unreachable("unknown PassDirection"); 188239313Sdim} 189239313Sdim 190239313Sdimvoid DeclInfo::fill() { 191239313Sdim assert(!IsFilled); 192239313Sdim 193239313Sdim // Set defaults. 194239313Sdim Kind = OtherKind; 195239313Sdim TemplateKind = NotTemplate; 196239313Sdim IsObjCMethod = false; 197239313Sdim IsInstanceMethod = false; 198239313Sdim IsClassMethod = false; 199251662Sdim ParamVars = None; 200276479Sdim TemplateParameters = nullptr; 201239313Sdim 202243830Sdim if (!CommentDecl) { 203239313Sdim // If there is no declaration, the defaults is our only guess. 204239313Sdim IsFilled = true; 205239313Sdim return; 206239313Sdim } 207243830Sdim CurrentDecl = CommentDecl; 208341825Sdim 209243830Sdim Decl::Kind K = CommentDecl->getKind(); 210239313Sdim switch (K) { 211239313Sdim default: 212239313Sdim // Defaults are should be good for declarations we don't handle explicitly. 213239313Sdim break; 214239313Sdim case Decl::Function: 215239313Sdim case Decl::CXXMethod: 216239313Sdim case Decl::CXXConstructor: 217239313Sdim case Decl::CXXDestructor: 218239313Sdim case Decl::CXXConversion: { 219243830Sdim const FunctionDecl *FD = cast<FunctionDecl>(CommentDecl); 220239313Sdim Kind = FunctionKind; 221309124Sdim ParamVars = FD->parameters(); 222276479Sdim ReturnType = FD->getReturnType(); 223239313Sdim unsigned NumLists = FD->getNumTemplateParameterLists(); 224239313Sdim if (NumLists != 0) { 225239313Sdim TemplateKind = TemplateSpecialization; 226239313Sdim TemplateParameters = 227239313Sdim FD->getTemplateParameterList(NumLists - 1); 228239313Sdim } 229239313Sdim 230239313Sdim if (K == Decl::CXXMethod || K == Decl::CXXConstructor || 231239313Sdim K == Decl::CXXDestructor || K == Decl::CXXConversion) { 232243830Sdim const CXXMethodDecl *MD = cast<CXXMethodDecl>(CommentDecl); 233239313Sdim IsInstanceMethod = MD->isInstance(); 234239313Sdim IsClassMethod = !IsInstanceMethod; 235239313Sdim } 236239313Sdim break; 237239313Sdim } 238239313Sdim case Decl::ObjCMethod: { 239243830Sdim const ObjCMethodDecl *MD = cast<ObjCMethodDecl>(CommentDecl); 240239313Sdim Kind = FunctionKind; 241309124Sdim ParamVars = MD->parameters(); 242276479Sdim ReturnType = MD->getReturnType(); 243239313Sdim IsObjCMethod = true; 244239313Sdim IsInstanceMethod = MD->isInstanceMethod(); 245239313Sdim IsClassMethod = !IsInstanceMethod; 246239313Sdim break; 247239313Sdim } 248239313Sdim case Decl::FunctionTemplate: { 249243830Sdim const FunctionTemplateDecl *FTD = cast<FunctionTemplateDecl>(CommentDecl); 250239313Sdim Kind = FunctionKind; 251239313Sdim TemplateKind = Template; 252239313Sdim const FunctionDecl *FD = FTD->getTemplatedDecl(); 253309124Sdim ParamVars = FD->parameters(); 254276479Sdim ReturnType = FD->getReturnType(); 255239313Sdim TemplateParameters = FTD->getTemplateParameters(); 256239313Sdim break; 257239313Sdim } 258239313Sdim case Decl::ClassTemplate: { 259243830Sdim const ClassTemplateDecl *CTD = cast<ClassTemplateDecl>(CommentDecl); 260239313Sdim Kind = ClassKind; 261239313Sdim TemplateKind = Template; 262239313Sdim TemplateParameters = CTD->getTemplateParameters(); 263239313Sdim break; 264239313Sdim } 265239313Sdim case Decl::ClassTemplatePartialSpecialization: { 266239313Sdim const ClassTemplatePartialSpecializationDecl *CTPSD = 267243830Sdim cast<ClassTemplatePartialSpecializationDecl>(CommentDecl); 268239313Sdim Kind = ClassKind; 269239313Sdim TemplateKind = TemplatePartialSpecialization; 270239313Sdim TemplateParameters = CTPSD->getTemplateParameters(); 271239313Sdim break; 272239313Sdim } 273239313Sdim case Decl::ClassTemplateSpecialization: 274239313Sdim Kind = ClassKind; 275239313Sdim TemplateKind = TemplateSpecialization; 276239313Sdim break; 277239313Sdim case Decl::Record: 278239313Sdim case Decl::CXXRecord: 279239313Sdim Kind = ClassKind; 280239313Sdim break; 281239313Sdim case Decl::Var: 282239313Sdim case Decl::Field: 283239313Sdim case Decl::EnumConstant: 284239313Sdim case Decl::ObjCIvar: 285239313Sdim case Decl::ObjCAtDefsField: 286321369Sdim case Decl::ObjCProperty: { 287321369Sdim const TypeSourceInfo *TSI; 288321369Sdim if (const auto *VD = dyn_cast<DeclaratorDecl>(CommentDecl)) 289321369Sdim TSI = VD->getTypeSourceInfo(); 290321369Sdim else if (const auto *PD = dyn_cast<ObjCPropertyDecl>(CommentDecl)) 291321369Sdim TSI = PD->getTypeSourceInfo(); 292321369Sdim else 293321369Sdim TSI = nullptr; 294321369Sdim if (TSI) { 295321369Sdim TypeLoc TL = TSI->getTypeLoc().getUnqualifiedLoc(); 296321369Sdim FunctionTypeLoc FTL; 297321369Sdim if (getFunctionTypeLoc(TL, FTL)) { 298321369Sdim ParamVars = FTL.getParams(); 299321369Sdim ReturnType = FTL.getReturnLoc().getType(); 300321369Sdim } 301321369Sdim } 302239313Sdim Kind = VariableKind; 303239313Sdim break; 304321369Sdim } 305239313Sdim case Decl::Namespace: 306239313Sdim Kind = NamespaceKind; 307239313Sdim break; 308314564Sdim case Decl::TypeAlias: 309243830Sdim case Decl::Typedef: { 310243830Sdim Kind = TypedefKind; 311314564Sdim // If this is a typedef / using to something we consider a function, extract 312243830Sdim // arguments and return type. 313314564Sdim const TypeSourceInfo *TSI = 314314564Sdim K == Decl::Typedef 315314564Sdim ? cast<TypedefDecl>(CommentDecl)->getTypeSourceInfo() 316314564Sdim : cast<TypeAliasDecl>(CommentDecl)->getTypeSourceInfo(); 317243830Sdim if (!TSI) 318243830Sdim break; 319243830Sdim TypeLoc TL = TSI->getTypeLoc().getUnqualifiedLoc(); 320314564Sdim FunctionTypeLoc FTL; 321314564Sdim if (getFunctionTypeLoc(TL, FTL)) { 322314564Sdim Kind = FunctionKind; 323314564Sdim ParamVars = FTL.getParams(); 324314564Sdim ReturnType = FTL.getReturnLoc().getType(); 325243830Sdim } 326243830Sdim break; 327243830Sdim } 328239313Sdim case Decl::TypeAliasTemplate: { 329243830Sdim const TypeAliasTemplateDecl *TAT = cast<TypeAliasTemplateDecl>(CommentDecl); 330239313Sdim Kind = TypedefKind; 331239313Sdim TemplateKind = Template; 332239313Sdim TemplateParameters = TAT->getTemplateParameters(); 333314564Sdim TypeAliasDecl *TAD = TAT->getTemplatedDecl(); 334314564Sdim if (!TAD) 335314564Sdim break; 336314564Sdim 337314564Sdim const TypeSourceInfo *TSI = TAD->getTypeSourceInfo(); 338314564Sdim if (!TSI) 339314564Sdim break; 340314564Sdim TypeLoc TL = TSI->getTypeLoc().getUnqualifiedLoc(); 341314564Sdim FunctionTypeLoc FTL; 342314564Sdim if (getFunctionTypeLoc(TL, FTL)) { 343314564Sdim Kind = FunctionKind; 344314564Sdim ParamVars = FTL.getParams(); 345314564Sdim ReturnType = FTL.getReturnLoc().getType(); 346314564Sdim } 347239313Sdim break; 348239313Sdim } 349239313Sdim case Decl::Enum: 350239313Sdim Kind = EnumKind; 351239313Sdim break; 352239313Sdim } 353239313Sdim 354239313Sdim IsFilled = true; 355239313Sdim} 356239313Sdim 357243830SdimStringRef ParamCommandComment::getParamName(const FullComment *FC) const { 358243830Sdim assert(isParamIndexValid()); 359261991Sdim if (isVarArgParam()) 360261991Sdim return "..."; 361261991Sdim return FC->getDeclInfo()->ParamVars[getParamIndex()]->getName(); 362243830Sdim} 363243830Sdim 364243830SdimStringRef TParamCommandComment::getParamName(const FullComment *FC) const { 365243830Sdim assert(isPositionValid()); 366261991Sdim const TemplateParameterList *TPL = FC->getDeclInfo()->TemplateParameters; 367243830Sdim for (unsigned i = 0, e = getDepth(); i != e; ++i) { 368243830Sdim if (i == e-1) 369243830Sdim return TPL->getParam(getIndex(i))->getName(); 370243830Sdim const NamedDecl *Param = TPL->getParam(getIndex(i)); 371243830Sdim if (const TemplateTemplateParmDecl *TTP = 372243830Sdim dyn_cast<TemplateTemplateParmDecl>(Param)) 373243830Sdim TPL = TTP->getTemplateParameters(); 374243830Sdim } 375243830Sdim return ""; 376243830Sdim} 377243830Sdim 378239313Sdim} // end namespace comments 379239313Sdim} // end namespace clang 380239313Sdim 381