From: Fariborz Jahanian Date: Fri, 26 Apr 2013 20:55:38 +0000 (+0000) Subject: document parsing. When a sub-class (c++ Objective-C) missing X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=622bb4acc00fd63bac545ca23f7c42fd909dc0e7;p=clang document parsing. When a sub-class (c++ Objective-C) missing a comment, grab the first comment found in its class heirarchy. Also, when a category is mossing a comment, grab comment of its primary class. // rdar://13647476 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@180629 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 22ee0cfcb6..29f1d7bd1a 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -451,6 +451,51 @@ comments::FullComment *ASTContext::getCommentForDecl( if (comments::FullComment *FC = getCommentForDecl(TD, PP)) return cloneFullComment(FC, D); } + else if (const ObjCInterfaceDecl *IC = dyn_cast(D)) { + while (IC->getSuperClass()) { + IC = IC->getSuperClass(); + if (comments::FullComment *FC = getCommentForDecl(IC, PP)) + return cloneFullComment(FC, D); + } + } + else if (const ObjCCategoryDecl *CD = dyn_cast(D)) { + if (const ObjCInterfaceDecl *IC = CD->getClassInterface()) + if (comments::FullComment *FC = getCommentForDecl(IC, PP)) + return cloneFullComment(FC, D); + } + else if (const CXXRecordDecl *RD = dyn_cast(D)) { + if (!(RD = RD->getDefinition())) + return NULL; + // Check non-virtual bases. + for (CXXRecordDecl::base_class_const_iterator I = + RD->bases_begin(), E = RD->bases_end(); I != E; ++I) { + if (I->isVirtual()) + continue; + QualType Ty = I->getType(); + if (Ty.isNull()) + continue; + if (const CXXRecordDecl *NonVirtualBase = Ty->getAsCXXRecordDecl()) { + if (!(NonVirtualBase= NonVirtualBase->getDefinition())) + continue; + + if (comments::FullComment *FC = getCommentForDecl((NonVirtualBase), PP)) + return cloneFullComment(FC, D); + } + } + // Check virtual bases. + for (CXXRecordDecl::base_class_const_iterator I = + RD->vbases_begin(), E = RD->vbases_end(); I != E; ++I) { + QualType Ty = I->getType(); + if (Ty.isNull()) + continue; + if (const CXXRecordDecl *VirtualBase = Ty->getAsCXXRecordDecl()) { + if (!(VirtualBase= VirtualBase->getDefinition())) + continue; + if (comments::FullComment *FC = getCommentForDecl((VirtualBase), PP)) + return cloneFullComment(FC, D); + } + } + } return NULL; } diff --git a/test/Misc/ast-dump-subclass-comment.mm b/test/Misc/ast-dump-subclass-comment.mm new file mode 100644 index 0000000000..4e05a2a612 --- /dev/null +++ b/test/Misc/ast-dump-subclass-comment.mm @@ -0,0 +1,101 @@ +// RUN: %clang_cc1 -x objective-c++ -Wdocumentation -ast-dump %s | FileCheck %s +// rdar://13647476 + +//! NSObject is root of all. +@interface NSObject +@end +// CHECK: ObjCInterfaceDecl{{.*}}NSObject +// CHECK-NEXT: FullComment 0x{{[^ ]*}} +// CHECK-NEXT: ParagraphComment{{.*}} +// CHECK-NEXT: TextComment{{.*}} Text=" NSObject is root of all." + +//! An umbrella class for super classes. +@interface SuperClass +@end +// CHECK: ObjCInterfaceDecl{{.*}}SuperClass +// CHECK-NEXT: FullComment 0x{{[^ ]*}} +// CHECK-NEXT: ParagraphComment{{.*}} +// CHECK-NEXT: TextComment{{.*}} Text=" An umbrella class for super classes." + +@interface SubClass : SuperClass +@end +// CHECK: ObjCInterfaceDecl 0x{{[^ ]*}} SubClass +// CHECK-NEXT: ObjCInterface 0x{{[^ ]*}} 'SuperClass' +// CHECK-NEXT: FullComment +// CHECK-NEXT: ParagraphComment{{.*}} +// CHECK-NEXT: TextComment{{.*}} Text=" An umbrella class for super classes." + +@interface SubSubClass : SubClass +@end +// CHECK: ObjCInterfaceDecl 0x{{[^ ]*}} SubSubClass +// CHECK-NEXT: ObjCInterface{{.*}} 'SubClass' +// CHECK-NEXT: FullComment +// CHECK-NEXT: ParagraphComment{{.*}} +// CHECK-NEXT: TextComment{{.*}} Text=" An umbrella class for super classes." + +@interface SubSubClass (Private) +@end +// CHECK: ObjCCategoryDecl 0x{{[^ ]*}} Private +// CHECK-NEXT: ObjCInterface{{.*}} 'SubSubClass' +// CHECK-NEXT: FullComment +// CHECK-NEXT: ParagraphComment{{.*}} +// CHECK-TEXT: TextComment{{.*}} Text=" An umbrella class for super classes." + +//! Something valuable to the organization. +class Asset { + +}; +// CHECK: CXXRecordDecl 0x{{[^ ]*}} class Asset +// CHECK-NEXT: FullComment +// CHECK-NEXT: ParagraphComment{{.*}} +// CHECK-NEXT: TextComment{{.*}} Text=" Something valuable to the organization." + +//! An individual human or human individual. +class Person : public Asset { +}; +// CHECK: CXXRecordDecl 0x{{[^ ]*}} class Person +// CHECK-NEXT: public 'class Asset' +// CHECK-NEXT: FullComment +// CHECK-NEXT: ParagraphComment{{.*}} +// CHECK-NEXT: TextComment{{.*}} Text=" An individual human or human individual." + +class Student : public Person { +}; +// CHECK: CXXRecordDecl 0x{{[^ ]*}} class Student +// CHECK-NEXT: public 'class Person' +// CHECK-NEXT: FullComment +// CHECK-NEXT: ParagraphComment{{.*}} +// CHECK-NEXT: TextComment{{.*}} Text=" An individual human or human individual." + +//! Every thing is a part +class Parts { +}; +// CHECK: CXXRecordDecl 0x{{[^ ]*}} class Parts +// CHECK-NEXT: FullComment +// CHECK-NEXT: ParagraphComment{{.*}} +// CHECK-NEXT: TextComment{{.*}} Text=" Every thing is a part" + +class Window : virtual Parts { +}; +// CHECK: CXXRecordDecl 0x{{[^ ]*}} class Window +// CHECK-NEXT: virtual private 'class Parts' +// CHECK-NEXT: FullComment +// CHECK-NEXT: ParagraphComment{{.*}} +// CHECK-NEXT: TextComment{{.*}} Text=" Every thing is a part" + +class Door : virtual Parts { +}; +// CHECK: CXXRecordDecl 0x{{[^ ]*}} class Door +// CHECK-NEXT: virtual private 'class Parts' +// CHECK-NEXT: FullComment +// CHECK-NEXT: ParagraphComment{{.*}} +// CHECK-NEXT: TextComment{{.*}} Text=" Every thing is a part" + +class House : Window, Door { +}; +// CHECK: CXXRecordDecl 0x{{[^ ]*}} class House +// CHECK-NEXT: private 'class Window' +// CHECK-NEXT: private 'class Door' +// CHECK-NEXT: FullComment +// CHECK-NEXT: ParagraphComment{{.*}} +// CHECK-NEXT: TextComment{{.*}} Text=" Every thing is a part"