From: Dmitri Gribenko Date: Wed, 1 Aug 2012 23:08:09 +0000 (+0000) Subject: Comment AST: add DeclInfo to store information about the declaration. Sema was X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=1ca7ecc8854ffea215c033a0d8482551bf1b73f0;p=clang Comment AST: add DeclInfo to store information about the declaration. Sema was already extracting most of this, but discarding at the end of semantic analysis. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@161140 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/Comment.h b/include/clang/AST/Comment.h index 089e7cd8e3..32c96a59ec 100644 --- a/include/clang/AST/Comment.h +++ b/include/clang/AST/Comment.h @@ -19,6 +19,10 @@ #include "llvm/ADT/StringRef.h" namespace clang { +class Decl; +class ParmVarDecl; +class TemplateParameterList; + namespace comments { /// Any part of the comment. @@ -906,14 +910,61 @@ public: } }; +/// Information about the declaration, useful to clients of FullComment. +struct DeclInfo { + /// Declaration the comment is attached to. Should not be NULL. + const Decl *ThisDecl; + + /// Parameters that can be referenced by \\param if \c ThisDecl is something + /// that we consider a "function". + ArrayRef ParamVars; + + /// Template parameters that can be referenced by \\tparam if \c ThisDecl is + /// a template. + const TemplateParameterList *TemplateParameters; + + /// If false, only \c ThisDecl is valid. + unsigned IsFilled : 1; + + /// Is \c ThisDecl something that we consider a "function". + unsigned IsFunctionDecl : 1; + + /// Is \c ThisDecl something that we consider a "class". + unsigned IsClassDecl : 1; + + /// Is \c ThisDecl a template declaration. + unsigned IsTemplateDecl : 1; + + /// Is \c ThisDecl a template specialization. + unsigned IsTemplateSpecialization : 1; + + /// Is \c ThisDecl a template partial specialization. + /// Never true if \c IsFunctionDecl is true. + unsigned IsTemplatePartialSpecialization : 1; + + /// Is \c ThisDecl a non-static member function of C++ class or + /// instance method of ObjC class. + /// Can be true only if \c IsFunctionDecl is true. + unsigned IsInstanceMethod : 1; + + /// Is \c ThisDecl a static member function of C++ class or + /// class method of ObjC class. + /// Can be true only if \c IsFunctionDecl is true. + unsigned IsClassMethod : 1; + + void fill(); +}; + /// A full comment attached to a declaration, contains block content. class FullComment : public Comment { llvm::ArrayRef Blocks; + DeclInfo *ThisDeclInfo; + public: - FullComment(llvm::ArrayRef Blocks) : + FullComment(llvm::ArrayRef Blocks, DeclInfo *D) : Comment(FullCommentKind, SourceLocation(), SourceLocation()), - Blocks(Blocks) { + Blocks(Blocks), ThisDeclInfo(D) { if (Blocks.empty()) return; @@ -935,6 +986,16 @@ public: child_iterator child_end() const { return reinterpret_cast(Blocks.end()); } + + const Decl *getDecl() const LLVM_READONLY { + return ThisDeclInfo->ThisDecl; + } + + const DeclInfo *getDeclInfo() const LLVM_READONLY { + if (!ThisDeclInfo->IsFilled) + ThisDeclInfo->fill(); + return ThisDeclInfo; + } }; } // end namespace comments diff --git a/include/clang/AST/CommentSema.h b/include/clang/AST/CommentSema.h index c51439b96f..77fa85aa91 100644 --- a/include/clang/AST/CommentSema.h +++ b/include/clang/AST/CommentSema.h @@ -24,9 +24,6 @@ namespace clang { class Decl; -class FunctionDecl; -class ParmVarDecl; -class TemplateParameterList; class SourceMgr; namespace comments { @@ -43,45 +40,22 @@ class Sema { DiagnosticsEngine &Diags; - /// Declaration this comment is attached to. - const Decl *ThisDecl; - - /// Parameters that can be referenced by \\param if \c ThisDecl is something - /// that we consider a "function". - /// Contains a valid value if \c IsThisDeclInspected is true. - ArrayRef ParamVars; + /// Information about the declaration this comment is attached to. + DeclInfo *ThisDeclInfo; /// Comment AST nodes that correspond to \c ParamVars for which we have /// found a \\param command or NULL if no documentation was found so far. /// - /// Has correct size and contains valid values if \c IsThisDeclInspected is + /// Has correct size and contains valid values if \c DeclInfo->IsFilled is /// true. llvm::SmallVector ParamVarDocs; - /// Template parameters that can be referenced by \\tparam if \c ThisDecl is - /// a template. - /// - /// Contains a valid value if \c IsThisDeclInspected is true. - const TemplateParameterList *TemplateParameters; - /// Comment AST nodes that correspond to parameter names in /// \c TemplateParameters. /// - /// Contains a valid value if \c IsThisDeclInspected is true. + /// Contains a valid value if \c DeclInfo->IsFilled is true. llvm::StringMap TemplateParameterDocs; - /// True if we extracted all important information from \c ThisDecl into - /// \c Sema members. - unsigned IsThisDeclInspected : 1; - - /// Is \c ThisDecl something that we consider a "function". - /// Contains a valid value if \c IsThisDeclInspected is true. - unsigned IsFunctionDecl : 1; - - /// Is \c ThisDecl a template declaration. - /// Contains a valid value if \c IsThisDeclInspected is true. - unsigned IsTemplateDecl : 1; - DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID) { return Diags.Report(Loc, DiagID); } @@ -212,8 +186,8 @@ public: ArrayRef getParamVars(); - /// Extract all important semantic information from \c ThisDecl into - /// \c Sema members. + /// Extract all important semantic information from + /// \c ThisDeclInfo->ThisDecl into \c ThisDeclInfo members. void inspectThisDecl(); /// Returns index of a function parameter with a given name. diff --git a/lib/AST/Comment.cpp b/lib/AST/Comment.cpp index 82dbed47f8..15b80c6455 100644 --- a/lib/AST/Comment.cpp +++ b/lib/AST/Comment.cpp @@ -8,6 +8,9 @@ //===----------------------------------------------------------------------===// #include "clang/AST/Comment.h" +#include "clang/AST/Decl.h" +#include "clang/AST/DeclObjC.h" +#include "clang/AST/DeclTemplate.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" @@ -134,5 +137,66 @@ const char *ParamCommandComment::getDirectionAsString(PassDirection D) { llvm_unreachable("unknown PassDirection"); } +void DeclInfo::fill() { + assert(!IsFilled); + + // Set defaults. + IsFunctionDecl = false; + IsTemplateDecl = false; + IsTemplateSpecialization = false; + IsTemplatePartialSpecialization = false; + IsInstanceMethod = false; + IsClassMethod = false; + ParamVars = ArrayRef(); + TemplateParameters = NULL; + + if (!ThisDecl) { + // Defaults are OK. + } else if (const FunctionDecl *FD = dyn_cast(ThisDecl)) { + IsFunctionDecl = true; + ParamVars = ArrayRef(FD->param_begin(), + FD->getNumParams()); + unsigned NumLists = FD->getNumTemplateParameterLists(); + if (NumLists != 0) { + IsTemplateDecl = true; + IsTemplateSpecialization = true; + TemplateParameters = + FD->getTemplateParameterList(NumLists - 1); + } + + if (const CXXMethodDecl *MD = dyn_cast(FD)) { + IsInstanceMethod = MD->isInstance(); + IsClassMethod = !IsInstanceMethod; + } + } else if (const ObjCMethodDecl *MD = dyn_cast(ThisDecl)) { + IsFunctionDecl = true; + ParamVars = ArrayRef(MD->param_begin(), + MD->param_size()); + IsInstanceMethod = MD->isInstanceMethod(); + IsClassMethod = !IsInstanceMethod; + } else if (const FunctionTemplateDecl *FTD = + dyn_cast(ThisDecl)) { + IsFunctionDecl = true; + IsTemplateDecl = true; + const FunctionDecl *FD = FTD->getTemplatedDecl(); + ParamVars = ArrayRef(FD->param_begin(), + FD->getNumParams()); + TemplateParameters = FTD->getTemplateParameters(); + } else if (const ClassTemplateDecl *CTD = + dyn_cast(ThisDecl)) { + IsTemplateDecl = true; + TemplateParameters = CTD->getTemplateParameters(); + } else if (const ClassTemplatePartialSpecializationDecl *CTPSD = + dyn_cast(ThisDecl)) { + IsTemplateDecl = true; + IsTemplatePartialSpecialization = true; + TemplateParameters = CTPSD->getTemplateParameters(); + } else if (isa(ThisDecl)) { + IsTemplateDecl = true; + IsTemplateSpecialization = true; + } + IsFilled = true; +} + } // end namespace comments } // end namespace clang diff --git a/lib/AST/CommentSema.cpp b/lib/AST/CommentSema.cpp index 7b42c861d3..3566091655 100644 --- a/lib/AST/CommentSema.cpp +++ b/lib/AST/CommentSema.cpp @@ -10,7 +10,6 @@ #include "clang/AST/CommentSema.h" #include "clang/AST/CommentDiagnostic.h" #include "clang/AST/Decl.h" -#include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" #include "clang/Basic/SourceManager.h" #include "llvm/ADT/StringSwitch.h" @@ -20,12 +19,16 @@ namespace comments { Sema::Sema(llvm::BumpPtrAllocator &Allocator, const SourceManager &SourceMgr, DiagnosticsEngine &Diags) : - Allocator(Allocator), SourceMgr(SourceMgr), Diags(Diags), ThisDecl(NULL), - IsThisDeclInspected(false) { + Allocator(Allocator), SourceMgr(SourceMgr), Diags(Diags), + ThisDeclInfo(NULL) { } void Sema::setDecl(const Decl *D) { - ThisDecl = D; + if (!D) + return; + + ThisDeclInfo = new (Allocator) DeclInfo; + ThisDeclInfo->ThisDecl = D; } ParagraphComment *Sema::actOnParagraphComment( @@ -234,6 +237,8 @@ TParamCommandComment *Sema::actOnTParamCommandParamNameArg( return Command; } + const TemplateParameterList *TemplateParameters = + ThisDeclInfo->TemplateParameters; SmallVector Position; if (resolveTParamReference(Arg, TemplateParameters, &Position)) { Command->setPosition(copyArray(llvm::makeArrayRef(Position))); @@ -449,7 +454,7 @@ HTMLEndTagComment *Sema::actOnHTMLEndTag(SourceLocation LocBegin, FullComment *Sema::actOnFullComment( ArrayRef Blocks) { - return new (Allocator) FullComment(Blocks); + return new (Allocator) FullComment(Blocks, ThisDeclInfo); } void Sema::checkBlockCommandEmptyParagraph(BlockCommandComment *Command) { @@ -467,80 +472,30 @@ void Sema::checkBlockCommandEmptyParagraph(BlockCommandComment *Command) { } bool Sema::isFunctionDecl() { - if (!IsThisDeclInspected) + if (!ThisDeclInfo) + return false; + if (!ThisDeclInfo->IsFilled) inspectThisDecl(); - return IsFunctionDecl; + return ThisDeclInfo->IsFunctionDecl; } bool Sema::isTemplateDecl() { - if (!IsThisDeclInspected) + if (!ThisDeclInfo) + return false; + if (!ThisDeclInfo->IsFilled) inspectThisDecl(); - return IsTemplateDecl; + return ThisDeclInfo->IsTemplateDecl; } ArrayRef Sema::getParamVars() { - if (!IsThisDeclInspected) + if (!ThisDeclInfo->IsFilled) inspectThisDecl(); - return ParamVars; + return ThisDeclInfo->ParamVars; } void Sema::inspectThisDecl() { - assert(!IsThisDeclInspected); - if (!ThisDecl) { - IsFunctionDecl = false; - IsTemplateDecl = false; - ParamVars = ArrayRef(); - TemplateParameters = NULL; - } else if (const FunctionDecl *FD = dyn_cast(ThisDecl)) { - IsFunctionDecl = true; - IsTemplateDecl = false; - ParamVars = ArrayRef(FD->param_begin(), - FD->getNumParams()); - TemplateParameters = NULL; - unsigned NumLists = FD->getNumTemplateParameterLists(); - if (NumLists != 0) { - IsTemplateDecl = true; - TemplateParameters = FD->getTemplateParameterList(NumLists - 1); - } - } else if (const ObjCMethodDecl *MD = dyn_cast(ThisDecl)) { - IsFunctionDecl = true; - IsTemplateDecl = false; - ParamVars = ArrayRef(MD->param_begin(), - MD->param_size()); - TemplateParameters = NULL; - } else if (const FunctionTemplateDecl *FTD = - dyn_cast(ThisDecl)) { - IsFunctionDecl = true; - IsTemplateDecl = true; - const FunctionDecl *FD = FTD->getTemplatedDecl(); - ParamVars = ArrayRef(FD->param_begin(), - FD->getNumParams()); - TemplateParameters = FTD->getTemplateParameters(); - } else if (const ClassTemplateDecl *CTD = - dyn_cast(ThisDecl)) { - IsFunctionDecl = false; - IsTemplateDecl = true; - ParamVars = ArrayRef(); - TemplateParameters = CTD->getTemplateParameters(); - } else if (const ClassTemplatePartialSpecializationDecl *CTPSD = - dyn_cast(ThisDecl)) { - IsFunctionDecl = false; - IsTemplateDecl = true; - ParamVars = ArrayRef(); - TemplateParameters = CTPSD->getTemplateParameters(); - } else if (isa(ThisDecl)) { - IsFunctionDecl = false; - IsTemplateDecl = true; - ParamVars = ArrayRef(); - TemplateParameters = NULL; - } else { - IsFunctionDecl = false; - IsTemplateDecl = false; - ParamVars = ArrayRef(); - TemplateParameters = NULL; - } - ParamVarDocs.resize(ParamVars.size(), NULL); - IsThisDeclInspected = true; + ThisDeclInfo->fill(); + ParamVarDocs.resize(ThisDeclInfo->ParamVars.size(), NULL); } unsigned Sema::resolveParmVarReference(StringRef Name,