aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/AST/ASTContext.cpp60
-rw-r--r--lib/AST/Comment.cpp20
-rw-r--r--lib/AST/CommentDumper.cpp2
-rw-r--r--lib/AST/CommentSema.cpp12
-rw-r--r--lib/AST/DeclObjC.cpp2
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) {