diff --git a/clang/lib/AST/Comment.cpp b/clang/lib/AST/Comment.cpp index e60eed9630c1..292129b9602a 100644 --- a/clang/lib/AST/Comment.cpp +++ b/clang/lib/AST/Comment.cpp @@ -266,6 +266,10 @@ void DeclInfo::fill() { TL = MemberPointerTL.getPointeeLoc().getUnqualifiedLoc(); continue; } + if (ElaboratedTypeLoc ETL = TL.getAs()) { + TL = ETL.getNamedTypeLoc(); + continue; + } // Is this a typedef for a function type? if (FunctionTypeLoc FTL = TL.getAs()) { Kind = FunctionKind; @@ -275,6 +279,28 @@ void DeclInfo::fill() { ResultType = FTL.getResultLoc().getType(); break; } + if (TemplateSpecializationTypeLoc STL = + TL.getAs()) { + // If we have a typedef to a template specialization with exactly one + // template argument of a function type, this looks like std::function, + // boost::function, or other function wrapper. Treat these typedefs as + // functions. + if (STL.getNumArgs() != 1) + break; + TemplateArgumentLoc MaybeFunction = STL.getArgLoc(0); + if (MaybeFunction.getArgument().getKind() != TemplateArgument::Type) + break; + TypeSourceInfo *MaybeFunctionTSI = MaybeFunction.getTypeSourceInfo(); + TypeLoc TL = MaybeFunctionTSI->getTypeLoc().getUnqualifiedLoc(); + if (FunctionTypeLoc FTL = TL.getAs()) { + Kind = FunctionKind; + ArrayRef Params = FTL.getParams(); + ParamVars = ArrayRef(Params.data(), + Params.size()); + ResultType = FTL.getResultLoc().getType(); + } + break; + } break; } break; diff --git a/clang/test/Sema/warn-documentation.cpp b/clang/test/Sema/warn-documentation.cpp index a8b9ea520a6f..00c56015b6ca 100644 --- a/clang/test/Sema/warn-documentation.cpp +++ b/clang/test/Sema/warn-documentation.cpp @@ -275,6 +275,21 @@ int test_param21(int a); /// \param x2 Ccc. int test_param22(int x1, int x2, int x3); +//===--- +// Test that we treat typedefs to some non-function types as functions for the +// purposes of documentation comment parsing. +//===--- + +namespace foo { + inline namespace bar { + template + struct function_wrapper {}; + + template + struct not_a_function_wrapper {}; + } +}; + // expected-warning@+2 {{parameter 'bbb' not found in the function declaration}} expected-note@+2 {{did you mean 'ccc'?}} /// \param aaa Meow. /// \param bbb Bbb. @@ -299,6 +314,19 @@ typedef int (* const test_function_like_typedef3)(int aaa, int ccc); /// \returns aaa. typedef int (C::*test_function_like_typedef4)(int aaa, int ccc); +// expected-warning@+2 {{parameter 'bbb' not found in the function declaration}} expected-note@+2 {{did you mean 'ccc'?}} +/// \param aaa Meow. +/// \param bbb Bbb. +/// \returns aaa. +typedef foo::function_wrapper test_function_like_typedef5; + +// expected-warning@+2 {{parameter 'bbb' not found in the function declaration}} expected-note@+2 {{did you mean 'ccc'?}} +/// \param aaa Meow. +/// \param bbb Bbb. +/// \returns aaa. +typedef foo::function_wrapper *test_function_like_typedef6; + + typedef int (*test_not_function_like_typedef1)(int aaa); // expected-warning@+1 {{'\param' command used in a comment that is not attached to a function declaration}} @@ -311,6 +339,9 @@ typedef test_not_function_like_typedef1 test_not_function_like_typedef2; /// @param aaa Meow. typedef unsigned int test_not_function_like_typedef3; +// expected-warning@+1 {{'\param' command used in a comment that is not attached to a function declaration}} +/// \param aaa Meow. +typedef foo::not_a_function_wrapper<1> test_not_function_like_typedef4; /// \param aaa Aaa /// \param ... Vararg