From 70ff1091315c60fed68d7197c637ec8c588e67a1 Mon Sep 17 00:00:00 2001 From: Dmitri Gribenko Date: Fri, 24 Aug 2012 00:05:30 +0000 Subject: [PATCH] Comment semantic analysis: treat function typedefs as functions so that one can 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 | 4 ++- lib/AST/Comment.cpp | 53 +++++++++++++++++++++++++++++++- test/Sema/warn-documentation.cpp | 23 ++++++++++++++ test/Sema/warn-documentation.m | 8 ++++- 4 files changed, 85 insertions(+), 3 deletions(-) diff --git a/include/clang/AST/Comment.h b/include/clang/AST/Comment.h index 01aaac3f77..09d0a26731 100644 --- a/include/clang/AST/Comment.h +++ b/include/clang/AST/Comment.h @@ -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": diff --git a/lib/AST/Comment.cpp b/lib/AST/Comment.cpp index 8a711f0c1f..2af3896156 100644 --- a/lib/AST/Comment.cpp +++ b/lib/AST/Comment.cpp @@ -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(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(&TL)) { + TSI = TypedefTL->getTypedefNameDecl()->getTypeSourceInfo(); + if (TSI) + break; + TL = TSI->getTypeLoc().getUnqualifiedLoc(); + continue; + } + // Look through qualified types. + if (QualifiedTypeLoc *QualifiedTL = dyn_cast(&TL)) { + TL = QualifiedTL->getUnqualifiedLoc(); + continue; + } + // Look through pointer types. + if (PointerTypeLoc *PointerTL = dyn_cast(&TL)) { + TL = PointerTL->getPointeeLoc().getUnqualifiedLoc(); + continue; + } + if (BlockPointerTypeLoc *BlockPointerTL = + dyn_cast(&TL)) { + TL = BlockPointerTL->getPointeeLoc().getUnqualifiedLoc(); + continue; + } + if (MemberPointerTypeLoc *MemberPointerTL = + dyn_cast(&TL)) { + TL = MemberPointerTL->getPointeeLoc().getUnqualifiedLoc(); + continue; + } + // Is this a typedef for a function type? + if (FunctionTypeLoc *FTL = dyn_cast(&TL)) { + Kind = FunctionKind; + ArrayRef Params = FTL->getParams(); + ParamVars = ArrayRef(Params.data(), + Params.size()); + ResultType = FTL->getResultLoc().getType(); + break; + } + break; + } + break; + } case Decl::TypeAlias: Kind = TypedefKind; break; diff --git a/test/Sema/warn-documentation.cpp b/test/Sema/warn-documentation.cpp index 1cd1358521..43143ff83d 100644 --- a/test/Sema/warn-documentation.cpp +++ b/test/Sema/warn-documentation.cpp @@ -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 diff --git a/test/Sema/warn-documentation.m b/test/Sema/warn-documentation.m index d6af6edcc8..04ae4ab648 100644 --- a/test/Sema/warn-documentation.m +++ b/test/Sema/warn-documentation.m @@ -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); + -- 2.40.0