Attaching comments to declarations during parsing: handle more Objective-C declarations.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@160156 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 2a1521e..a9681d8 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -78,9 +78,21 @@
   if (RawComments.empty())
     return NULL;
 
+  // Find declaration location.
+  // For Objective-C declarations we generally don't expect to have multiple
+  // declarators, thus use declaration starting location as the "declaration
+  // location".
+  // For all other declarations multiple declarators are used quite frequently,
+  // so we use the location of the identifier as the "declaration location".
+  SourceLocation DeclLoc;
+  if (isa<ObjCMethodDecl>(D) || isa<ObjCContainerDecl>(D) ||
+      isa<ObjCPropertyDecl>(D))
+    DeclLoc = D->getLocStart();
+  else
+    DeclLoc = D->getLocation();
+
   // If the declaration doesn't map directly to a location in a file, we
   // can't find the comment.
-  SourceLocation DeclLoc = D->getLocation();
   if (DeclLoc.isInvalid() || !DeclLoc.isFileID())
     return NULL;
 
@@ -144,7 +156,7 @@
 
   // There should be no other declarations or preprocessor directives between
   // comment and declaration.
-  if (Text.find_first_of(",;{}#") != StringRef::npos)
+  if (Text.find_first_of(",;{}#@") != StringRef::npos)
     return NULL;
 
   return *Comment;
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 4745376..f00ed82 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -8932,7 +8932,6 @@
   assert(getContainingDC(OCD) == CurContext &&
       "The next DeclContext should be lexically contained in the current one.");
   CurContext = OCD;
-  ActOnDocumentableDecl(IDecl);
   return IDecl;
 }
 
diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp
index 8d46946..17c34a2 100644
--- a/lib/Sema/SemaDeclObjC.cpp
+++ b/lib/Sema/SemaDeclObjC.cpp
@@ -2429,6 +2429,7 @@
     Consumer.HandleTopLevelDeclInObjCContainer(DG);
   }
 
+  ActOnDocumentableDecl(ClassDecl);
   return ClassDecl;
 }
 
diff --git a/lib/Sema/SemaObjCProperty.cpp b/lib/Sema/SemaObjCProperty.cpp
index 34dd068..335dad1 100644
--- a/lib/Sema/SemaObjCProperty.cpp
+++ b/lib/Sema/SemaObjCProperty.cpp
@@ -149,6 +149,7 @@
         if (getLangOpts().ObjCAutoRefCount)
           checkARCPropertyDecl(*this, cast<ObjCPropertyDecl>(Res));
       }
+      ActOnDocumentableDecl(Res);
       return Res;
     }
   
@@ -169,6 +170,7 @@
   if (getLangOpts().ObjCAutoRefCount)
     checkARCPropertyDecl(*this, Res);
 
+  ActOnDocumentableDecl(Res);
   return Res;
 }
 
diff --git a/test/Sema/warn-documentation.m b/test/Sema/warn-documentation.m
index 0a02f7b..3a661c5 100644
--- a/test/Sema/warn-documentation.m
+++ b/test/Sema/warn-documentation.m
@@ -2,11 +2,9 @@
 
 @class NSString;
 
-// expected-warning@+2 {{empty paragraph passed to '\brief' command}}
-/**
- * \brief\brief Aaa
- */
-@interface A
+// expected-warning@+1 {{empty paragraph passed to '\brief' command}}
+/// \brief\brief Aaa
+@interface Test1
 // expected-warning@+2 {{empty paragraph passed to '\brief' command}}
 /**
  * \brief\brief Aaa
@@ -20,5 +18,67 @@
  * \param aab Aaa
  */
 + (NSString *)test2:(NSString *)aaa;
+
+// expected-warning@+1 {{empty paragraph passed to '\brief' command}}
+/// \brief\brief Aaa
+@property int test3; // a property: ObjCPropertyDecl
+
+// expected-warning@+1 {{empty paragraph passed to '\brief' command}}
+/// \brief\brief Aaa
+@property int test4; // a property: ObjCPropertyDecl
 @end
 
+// expected-warning@+1 {{empty paragraph passed to '\brief' command}}
+/// \brief\brief Aaa
+@interface Test1()
+@end
+
+// expected-warning@+1 {{empty paragraph passed to '\brief' command}}
+/// \brief\brief Aaa
+@implementation Test1 // a class implementation : ObjCImplementationDecl
++ (NSString *)test1:(NSString *)aaa suffix:(NSString *)bbb {
+  return 0;
+}
+
++ (NSString *)test2:(NSString *)aaa {
+  return 0;
+}
+
+@synthesize test3; // a property implementation: ObjCPropertyImplDecl
+@dynamic test4; // a property implementation: ObjCPropertyImplDecl
+
+// expected-warning@+1 {{empty paragraph passed to '\brief' command}}
+/// \brief\brief Aaa
+NSString *_test5;
+@end
+
+// expected-warning@+1 {{empty paragraph passed to '\brief' command}}
+/// \brief\brief Aaa
+@interface Test1(Test1Category) // a category: ObjCCategoryDecl
+// expected-warning@+1 {{empty paragraph passed to '\brief' command}}
+/// \brief\brief Aaa
++ (NSString *)test3:(NSString *)aaa;
+@end
+
+// expected-warning@+1 {{empty paragraph passed to '\brief' command}}
+/// \brief\brief Aaa
+@implementation Test1(Test1Category) // a category implementation: ObjCCategoryImplDecl
++ (NSString *)test3:(NSString *)aaa {
+  return 0;
+}
+@end
+
+// expected-warning@+1 {{empty paragraph passed to '\brief' command}}
+/// \brief\brief Aaa
+@protocol TestProto1 // a protocol: ObjCProtocolDecl
+@end
+
+int a;
+
+// expected-warning@+1 {{empty paragraph passed to '\brief' command}}
+/// \brief\brief Aaa
+@interface Test4
+@end
+
+int b;
+