]> granicus.if.org Git - clang/commitdiff
Comment semantic analysis: treat function typedefs as functions so that one can
authorDmitri Gribenko <gribozavr@gmail.com>
Fri, 24 Aug 2012 00:05:30 +0000 (00:05 +0000)
committerDmitri Gribenko <gribozavr@gmail.com>
Fri, 24 Aug 2012 00:05:30 +0000 (00:05 +0000)
use \param and \returns in documentation.

Fixes PR13533.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@162507 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/Comment.h
lib/AST/Comment.cpp
test/Sema/warn-documentation.cpp
test/Sema/warn-documentation.m

index 01aaac3f77adbb1b814d2c43b0213f9926f17dd5..09d0a26731d820bbd985265fcdfb205685d3db0d 100644 (file)
@@ -942,7 +942,9 @@ struct DeclInfo {
     /// \li member function,
     /// \li member function template,
     /// \li member function template specialization,
-    /// \li ObjC method.
+    /// \li ObjC method,
+    /// \li a typedef for a function pointer, member function pointer,
+    ///     ObjC block.
     FunctionKind,
 
     /// Something that we consider a "class":
index 8a711f0c1f80c261d4983351a344b48d2abfcc46..2af38961563e6bbc82137cfec66656092684dec6 100644 (file)
@@ -240,7 +240,58 @@ void DeclInfo::fill() {
   case Decl::Namespace:
     Kind = NamespaceKind;
     break;
-  case Decl::Typedef:
+  case Decl::Typedef: {
+    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 TypeSourceInfo *TSI = TD->getTypeSourceInfo();
+    if (!TSI)
+      break;
+    TypeLoc TL = TSI->getTypeLoc().getUnqualifiedLoc();
+    while (true) {
+      TL = TL.IgnoreParens();
+      // Look through typedefs.
+      if (TypedefTypeLoc *TypedefTL = dyn_cast<TypedefTypeLoc>(&TL)) {
+        TSI = TypedefTL->getTypedefNameDecl()->getTypeSourceInfo();
+        if (TSI)
+          break;
+        TL = TSI->getTypeLoc().getUnqualifiedLoc();
+        continue;
+      }
+      // Look through qualified types.
+      if (QualifiedTypeLoc *QualifiedTL = dyn_cast<QualifiedTypeLoc>(&TL)) {
+        TL = QualifiedTL->getUnqualifiedLoc();
+        continue;
+      }
+      // Look through pointer types.
+      if (PointerTypeLoc *PointerTL = dyn_cast<PointerTypeLoc>(&TL)) {
+        TL = PointerTL->getPointeeLoc().getUnqualifiedLoc();
+        continue;
+      }
+      if (BlockPointerTypeLoc *BlockPointerTL =
+              dyn_cast<BlockPointerTypeLoc>(&TL)) {
+        TL = BlockPointerTL->getPointeeLoc().getUnqualifiedLoc();
+        continue;
+      }
+      if (MemberPointerTypeLoc *MemberPointerTL =
+              dyn_cast<MemberPointerTypeLoc>(&TL)) {
+        TL = MemberPointerTL->getPointeeLoc().getUnqualifiedLoc();
+        continue;
+      }
+      // Is this a typedef for a function type?
+      if (FunctionTypeLoc *FTL = dyn_cast<FunctionTypeLoc>(&TL)) {
+        Kind = FunctionKind;
+        ArrayRef<ParmVarDecl *> Params = FTL->getParams();
+        ParamVars = ArrayRef<const ParmVarDecl *>(Params.data(),
+                                                  Params.size());
+        ResultType = FTL->getResultLoc().getType();
+        break;
+      }
+      break;
+    }
+    break;
+  }
   case Decl::TypeAlias:
     Kind = TypedefKind;
     break;
index 1cd13585212efff25fd4e4f8f1f0e2f728b7426b..43143ff83d0217b9e22e62b59846869af9c78fad 100644 (file)
@@ -250,6 +250,29 @@ int test_param17(int a);
 /// \param x2 Ccc.
 int test_param18(int x1, int x2, int x3);
 
+// expected-warning@+2 {{parameter 'bbb' not found in the function declaration}} expected-note@+2 {{did you mean 'aaa'?}}
+/// \param aaa Meow.
+/// \param bbb Bbb.
+/// \returns aaa.
+typedef int test_param19(int aaa);
+
+// expected-warning@+2 {{parameter 'bbb' not found in the function declaration}} expected-note@+2 {{did you mean 'aaa'?}}
+/// \param aaa Meow.
+/// \param bbb Bbb.
+/// \returns aaa.
+typedef int (*test_param20)(int aaa);
+
+// expected-warning@+2 {{parameter 'bbb' not found in the function declaration}} expected-note@+2 {{did you mean 'aaa'?}}
+/// \param aaa Meow.
+/// \param bbb Bbb.
+/// \returns aaa.
+typedef int (* const test_param21)(int aaa);
+
+// expected-warning@+2 {{parameter 'bbb' not found in the function declaration}} expected-note@+2 {{did you mean 'aaa'?}}
+/// \param aaa Meow.
+/// \param bbb Bbb.
+/// \returns aaa.
+typedef int (C::*test_param22)(int aaa);
 
 // expected-warning@+1 {{'\tparam' command used in a comment that is not attached to a template declaration}}
 /// \tparam T Aaa
index d6af6edcc85d9c068e5324f58266f391cba44e22..04ae4ab64849c5efd1cca181c449823c9e5ef630 100644 (file)
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -Wno-objc-root-class -Wdocumentation -Wdocumentation-pedantic -verify %s
+// RUN: %clang_cc1 -fsyntax-only -fblocks -Wno-objc-root-class -Wdocumentation -Wdocumentation-pedantic -verify %s
 
 @class NSString;
 
@@ -91,3 +91,9 @@ int b;
 - (void)test2:(NSString *)aaa;
 @end
 
+// expected-warning@+2 {{parameter 'bbb' not found in the function declaration}} expected-note@+2 {{did you mean 'aaa'?}}
+/// \param aaa Meow.
+/// \param bbb Bbb.
+/// \returns aaa.
+typedef int (^test_param1)(int aaa);
+