diff options
author | Fariborz Jahanian <fjahanian@apple.com> | 2012-10-10 18:34:52 +0000 |
---|---|---|
committer | Fariborz Jahanian <fjahanian@apple.com> | 2012-10-10 18:34:52 +0000 |
commit | bf967be66ea8c51b66c61659c23240f762a56dbe (patch) | |
tree | 41a5fab46daa1e64b94cd5460874794072abd2b8 /lib | |
parent | 4eff6b5d6a5cbb6bd669854a84365aa61d70819e (diff) |
[Doc parsing] This patch searches overridden objc/c++
methods looking for documentation on a particular base
class inherited by any method that overrides the base class.
In case of redeclaration, as when objc method is defined
in the implementation, it also looks up for documentation
in class/class extension being redeclared.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@165643 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/AST/ASTContext.cpp | 60 | ||||
-rw-r--r-- | lib/AST/Comment.cpp | 20 | ||||
-rw-r--r-- | lib/AST/CommentDumper.cpp | 2 | ||||
-rw-r--r-- | lib/AST/CommentSema.cpp | 12 | ||||
-rw-r--r-- | lib/AST/DeclObjC.cpp | 2 |
5 files changed, 75 insertions, 21 deletions
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 874861872a..a58eca6a0a 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -24,6 +24,7 @@ #include "clang/AST/ASTMutationListener.h" #include "clang/AST/RecordLayout.h" #include "clang/AST/Mangle.h" +#include "clang/AST/Comment.h" #include "clang/Basic/Builtins.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/TargetInfo.h" @@ -355,21 +356,72 @@ const RawComment *ASTContext::getRawCommentForAnyRedecl( return RC; } +static void addRedeclaredMethods(const ObjCMethodDecl *ObjCMethod, + SmallVectorImpl<const NamedDecl *> &Redeclared) { + const DeclContext *DC = ObjCMethod->getDeclContext(); + if (const ObjCImplDecl *IMD = dyn_cast<ObjCImplDecl>(DC)) { + const ObjCInterfaceDecl *ID = IMD->getClassInterface(); + if (!ID) + return; + // Add redeclared method here. + for (const ObjCCategoryDecl *ClsExtDecl = ID->getFirstClassExtension(); + ClsExtDecl; ClsExtDecl = ClsExtDecl->getNextClassExtension()) { + if (ObjCMethodDecl *RedeclaredMethod = + ClsExtDecl->getMethod(ObjCMethod->getSelector(), + ObjCMethod->isInstanceMethod())) + Redeclared.push_back(RedeclaredMethod); + } + } +} + comments::FullComment *ASTContext::getCommentForDecl( const Decl *D, const Preprocessor *PP) const { D = adjustDeclToTemplate(D); + const Decl *Canonical = D->getCanonicalDecl(); llvm::DenseMap<const Decl *, comments::FullComment *>::iterator Pos = ParsedComments.find(Canonical); - if (Pos != ParsedComments.end()) + + if (Pos != ParsedComments.end()) { + if (Canonical != D && + (isa<ObjCMethodDecl>(D) || isa<FunctionDecl>(D))) { + // case of method being redeclaration of the canonical, not + // overriding it; i.e. method in implementation, canonical in + // interface. Or, out-of-line cxx-method definition. + comments::FullComment *FC = Pos->second; + comments::FullComment *CFC = + new (*this) comments::FullComment(FC->getBlocks(), + FC->getThisDeclInfo(), + const_cast<Decl *>(D)); + return CFC; + } return Pos->second; - + } + const Decl *OriginalDecl; + const RawComment *RC = getRawCommentForAnyRedecl(D, &OriginalDecl); - if (!RC) + if (!RC) { + if (isa<ObjCMethodDecl>(D) || isa<FunctionDecl>(D)) { + SmallVector<const NamedDecl*, 8> overridden; + if (const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(D)) + addRedeclaredMethods(OMD, overridden); + const_cast<ASTContext *>(this)->getOverriddenMethods(dyn_cast<NamedDecl>(D), + overridden); + for (unsigned i = 0, e = overridden.size(); i < e; i++) { + if (comments::FullComment *FC = getCommentForDecl(overridden[i], PP)) { + comments::FullComment *CFC = + new (*this) comments::FullComment(FC->getBlocks(), + FC->getThisDeclInfo(), + const_cast<Decl *>(D)); + return CFC; + } + } + } return NULL; - + } + // If the RawComment was attached to other redeclaration of this Decl, we // should parse the comment in context of that other Decl. This is important // because comments can contain references to parameter names which can be diff --git a/lib/AST/Comment.cpp b/lib/AST/Comment.cpp index 4336885d39..09f4290f1b 100644 --- a/lib/AST/Comment.cpp +++ b/lib/AST/Comment.cpp @@ -151,13 +151,13 @@ void DeclInfo::fill() { ParamVars = ArrayRef<const ParmVarDecl *>(); TemplateParameters = NULL; - if (!ThisDecl) { + if (!CommentDecl) { // If there is no declaration, the defaults is our only guess. IsFilled = true; return; } - Decl::Kind K = ThisDecl->getKind(); + Decl::Kind K = CommentDecl->getKind(); switch (K) { default: // Defaults are should be good for declarations we don't handle explicitly. @@ -167,7 +167,7 @@ void DeclInfo::fill() { case Decl::CXXConstructor: case Decl::CXXDestructor: case Decl::CXXConversion: { - const FunctionDecl *FD = cast<FunctionDecl>(ThisDecl); + const FunctionDecl *FD = cast<FunctionDecl>(CommentDecl); Kind = FunctionKind; ParamVars = ArrayRef<const ParmVarDecl *>(FD->param_begin(), FD->getNumParams()); @@ -181,14 +181,14 @@ void DeclInfo::fill() { if (K == Decl::CXXMethod || K == Decl::CXXConstructor || K == Decl::CXXDestructor || K == Decl::CXXConversion) { - const CXXMethodDecl *MD = cast<CXXMethodDecl>(ThisDecl); + const CXXMethodDecl *MD = cast<CXXMethodDecl>(CommentDecl); IsInstanceMethod = MD->isInstance(); IsClassMethod = !IsInstanceMethod; } break; } case Decl::ObjCMethod: { - const ObjCMethodDecl *MD = cast<ObjCMethodDecl>(ThisDecl); + const ObjCMethodDecl *MD = cast<ObjCMethodDecl>(CommentDecl); Kind = FunctionKind; ParamVars = ArrayRef<const ParmVarDecl *>(MD->param_begin(), MD->param_size()); @@ -199,7 +199,7 @@ void DeclInfo::fill() { break; } case Decl::FunctionTemplate: { - const FunctionTemplateDecl *FTD = cast<FunctionTemplateDecl>(ThisDecl); + const FunctionTemplateDecl *FTD = cast<FunctionTemplateDecl>(CommentDecl); Kind = FunctionKind; TemplateKind = Template; const FunctionDecl *FD = FTD->getTemplatedDecl(); @@ -210,7 +210,7 @@ void DeclInfo::fill() { break; } case Decl::ClassTemplate: { - const ClassTemplateDecl *CTD = cast<ClassTemplateDecl>(ThisDecl); + const ClassTemplateDecl *CTD = cast<ClassTemplateDecl>(CommentDecl); Kind = ClassKind; TemplateKind = Template; TemplateParameters = CTD->getTemplateParameters(); @@ -218,7 +218,7 @@ void DeclInfo::fill() { } case Decl::ClassTemplatePartialSpecialization: { const ClassTemplatePartialSpecializationDecl *CTPSD = - cast<ClassTemplatePartialSpecializationDecl>(ThisDecl); + cast<ClassTemplatePartialSpecializationDecl>(CommentDecl); Kind = ClassKind; TemplateKind = TemplatePartialSpecialization; TemplateParameters = CTPSD->getTemplateParameters(); @@ -246,7 +246,7 @@ void DeclInfo::fill() { Kind = TypedefKind; // If this is a typedef to something we consider a function, extract // arguments and return type. - const TypedefDecl *TD = cast<TypedefDecl>(ThisDecl); + const TypedefDecl *TD = cast<TypedefDecl>(CommentDecl); const TypeSourceInfo *TSI = TD->getTypeSourceInfo(); if (!TSI) break; @@ -290,7 +290,7 @@ void DeclInfo::fill() { Kind = TypedefKind; break; case Decl::TypeAliasTemplate: { - const TypeAliasTemplateDecl *TAT = cast<TypeAliasTemplateDecl>(ThisDecl); + const TypeAliasTemplateDecl *TAT = cast<TypeAliasTemplateDecl>(CommentDecl); Kind = TypedefKind; TemplateKind = Template; TemplateParameters = TAT->getTemplateParameters(); diff --git a/lib/AST/CommentDumper.cpp b/lib/AST/CommentDumper.cpp index f6fb3b1baa..f9050d5f71 100644 --- a/lib/AST/CommentDumper.cpp +++ b/lib/AST/CommentDumper.cpp @@ -183,7 +183,7 @@ void CommentDumper::visitParamCommandComment(const ParamCommandComment *C) { OS << " implicitly"; if (C->hasParamName()) - OS << " Param=\"" << C->getParamName() << "\""; + OS << " Param=\"" << C->getParamName(0) << "\""; if (C->isParamIndexValid()) OS << " ParamIndex=" << C->getParamIndex(); diff --git a/lib/AST/CommentSema.cpp b/lib/AST/CommentSema.cpp index dd746ad119..59dc6c7295 100644 --- a/lib/AST/CommentSema.cpp +++ b/lib/AST/CommentSema.cpp @@ -36,7 +36,7 @@ void Sema::setDecl(const Decl *D) { return; ThisDeclInfo = new (Allocator) DeclInfo; - ThisDeclInfo->ThisDecl = D; + ThisDeclInfo->CommentDecl = D; ThisDeclInfo->IsFilled = false; } @@ -413,7 +413,7 @@ HTMLEndTagComment *Sema::actOnHTMLEndTag(SourceLocation LocBegin, FullComment *Sema::actOnFullComment( ArrayRef<BlockContentComment *> Blocks) { - FullComment *FC = new (Allocator) FullComment(Blocks, ThisDeclInfo); + FullComment *FC = new (Allocator) FullComment(Blocks, ThisDeclInfo, 0); resolveParamCommandIndexes(FC); return FC; } @@ -441,7 +441,7 @@ void Sema::checkReturnsCommand(const BlockCommandComment *Command) { if (isFunctionDecl()) { if (ThisDeclInfo->ResultType->isVoidType()) { unsigned DiagKind; - switch (ThisDeclInfo->ThisDecl->getKind()) { + switch (ThisDeclInfo->CommentDecl->getKind()) { default: if (ThisDeclInfo->IsObjCMethod) DiagKind = 3; @@ -508,7 +508,7 @@ void Sema::checkDeprecatedCommand(const BlockCommandComment *Command) { if (!Traits.getCommandInfo(Command->getCommandID())->IsDeprecatedCommand) return; - const Decl *D = ThisDeclInfo->ThisDecl; + const Decl *D = ThisDeclInfo->CommentDecl; if (!D) return; @@ -574,7 +574,7 @@ void Sema::resolveParamCommandIndexes(const FullComment *FC) { ParamCommandComment *PCC = dyn_cast<ParamCommandComment>(*I); if (!PCC || !PCC->hasParamName()) continue; - StringRef ParamName = PCC->getParamName(); + StringRef ParamName = PCC->getParamName(0); // Check that referenced parameter name is in the function decl. const unsigned ResolvedParamIndex = resolveParmVarReference(ParamName, @@ -609,7 +609,7 @@ void Sema::resolveParamCommandIndexes(const FullComment *FC) { const ParamCommandComment *PCC = UnresolvedParamCommands[i]; SourceRange ArgRange = PCC->getParamNameRange(); - StringRef ParamName = PCC->getParamName(); + StringRef ParamName = PCC->getParamName(0); Diag(ArgRange.getBegin(), diag::warn_doc_param_not_found) << ParamName << ArgRange; diff --git a/lib/AST/DeclObjC.cpp b/lib/AST/DeclObjC.cpp index 90b8807be9..f4a0bdf38b 100644 --- a/lib/AST/DeclObjC.cpp +++ b/lib/AST/DeclObjC.cpp @@ -859,6 +859,8 @@ static void collectOnCategoriesAfterLocation(SourceLocation Loc, /// overrides lookup that it does for methods, inside implementations, will /// stop at the interface level (if there is a method there) and not look /// further in super classes. +/// Methods in an implementation can overide methods in super class's category +/// but not in current class's category. But, such methods static void collectOverriddenMethodsFast(SourceManager &SM, const ObjCMethodDecl *Method, SmallVectorImpl<const ObjCMethodDecl *> &Methods) { |