From: Dmitri Gribenko Date: Mon, 24 Jun 2013 04:41:32 +0000 (+0000) Subject: Comment parsing: allow "\param ..." to describe variadic arguments X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=c5b0054693b3b3cafe6a13549358c22e07fcd4ff;p=clang Comment parsing: allow "\param ..." to describe variadic arguments Original patch by Fariborz Jahanian; extended by me. Fixes rdar://14124644 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@184688 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/bindings/xml/comment-xml-schema.rng b/bindings/xml/comment-xml-schema.rng index 22371dfed1..13cf7addec 100644 --- a/bindings/xml/comment-xml-schema.rng +++ b/bindings/xml/comment-xml-schema.rng @@ -410,9 +410,14 @@ - - - + + + + + + + + diff --git a/include/clang/AST/Comment.h b/include/clang/AST/Comment.h index c02a82f0fa..613ad5308f 100644 --- a/include/clang/AST/Comment.h +++ b/include/clang/AST/Comment.h @@ -699,7 +699,10 @@ private: unsigned ParamIndex; public: - enum { InvalidParamIndex = ~0U }; + enum { + InvalidParamIndex = ~0U, + VarArgParamIndex = InvalidParamIndex - 1U + }; ParamCommandComment(SourceLocation LocBegin, SourceLocation LocEnd, @@ -755,14 +758,25 @@ public: return ParamIndex != InvalidParamIndex; } + bool isVarArgParam() const LLVM_READONLY { + return ParamIndex == VarArgParamIndex; + } + + void setIsVarArgParam() { + ParamIndex = VarArgParamIndex; + assert(isParamIndexValid()); + } + unsigned getParamIndex() const LLVM_READONLY { assert(isParamIndexValid()); + assert(!isVarArgParam()); return ParamIndex; } void setParamIndex(unsigned Index) { ParamIndex = Index; assert(isParamIndexValid()); + assert(!isVarArgParam()); } }; diff --git a/include/clang/AST/CommentSema.h b/include/clang/AST/CommentSema.h index c6b59bb11b..39109602b1 100644 --- a/include/clang/AST/CommentSema.h +++ b/include/clang/AST/CommentSema.h @@ -212,6 +212,7 @@ public: /// \returns \c true if declaration that this comment is attached to declares /// a function pointer. bool isFunctionPointerVarDecl(); + bool isFunctionOrMethodVariadic(); bool isObjCMethodDecl(); bool isObjCPropertyDecl(); bool isTemplateOrSpecialization(); diff --git a/lib/AST/Comment.cpp b/lib/AST/Comment.cpp index 68c73fd48e..058485e3fd 100644 --- a/lib/AST/Comment.cpp +++ b/lib/AST/Comment.cpp @@ -293,6 +293,8 @@ void DeclInfo::fill() { StringRef ParamCommandComment::getParamName(const FullComment *FC) const { assert(isParamIndexValid()); + if (isVarArgParam()) + return "..."; return FC->getThisDeclInfo()->ParamVars[getParamIndex()]->getName(); } diff --git a/lib/AST/CommentSema.cpp b/lib/AST/CommentSema.cpp index 55ccfb339d..c0dc647ca4 100644 --- a/lib/AST/CommentSema.cpp +++ b/lib/AST/CommentSema.cpp @@ -726,6 +726,10 @@ void Sema::resolveParamCommandIndexes(const FullComment *FC) { // Check that referenced parameter name is in the function decl. const unsigned ResolvedParamIndex = resolveParmVarReference(ParamName, ParamVars); + if (ResolvedParamIndex == ParamCommandComment::VarArgParamIndex) { + PCC->setIsVarArgParam(); + continue; + } if (ResolvedParamIndex == ParamCommandComment::InvalidParamIndex) { UnresolvedParamCommands.push_back(PCC); continue; @@ -796,7 +800,19 @@ bool Sema::isAnyFunctionDecl() { return isFunctionDecl() && ThisDeclInfo->CurrentDecl && isa(ThisDeclInfo->CurrentDecl); } - + +bool Sema::isFunctionOrMethodVariadic() { + if (!isAnyFunctionDecl() && !isObjCMethodDecl()) + return false; + if (const FunctionDecl *FD = + dyn_cast(ThisDeclInfo->CurrentDecl)) + return FD->isVariadic(); + if (const ObjCMethodDecl *MD = + dyn_cast(ThisDeclInfo->CurrentDecl)) + return MD->isVariadic(); + return false; +} + bool Sema::isObjCMethodDecl() { return isFunctionDecl() && ThisDeclInfo->CurrentDecl && isa(ThisDeclInfo->CurrentDecl); @@ -915,6 +931,8 @@ unsigned Sema::resolveParmVarReference(StringRef Name, if (II && II->getName() == Name) return i; } + if (Name == "..." && isFunctionOrMethodVariadic()) + return ParamCommandComment::VarArgParamIndex; return ParamCommandComment::InvalidParamIndex; } diff --git a/test/Index/Inputs/CommentXML/invalid-function-13.xml b/test/Index/Inputs/CommentXML/invalid-function-13.xml new file mode 100644 index 0000000000..14cd31bfa4 --- /dev/null +++ b/test/Index/Inputs/CommentXML/invalid-function-13.xml @@ -0,0 +1,13 @@ + + +aaa +Aaa. + + + x1 + + Bbb + + + + diff --git a/test/Index/Inputs/CommentXML/valid-function-07.xml b/test/Index/Inputs/CommentXML/valid-function-07.xml index 9ff2f63d85..e9f5911537 100644 --- a/test/Index/Inputs/CommentXML/valid-function-07.xml +++ b/test/Index/Inputs/CommentXML/valid-function-07.xml @@ -20,14 +20,20 @@ in,out Ddd + + x4 + + in + Eee + - Eee. - Fff + Fff. + Ggg - Ggg - Hhh + Hhh + Iii diff --git a/test/Index/comment-to-html-xml-conversion.cpp b/test/Index/comment-to-html-xml-conversion.cpp index 78fd793deb..b70259ad12 100644 --- a/test/Index/comment-to-html-xml-conversion.cpp +++ b/test/Index/comment-to-html-xml-conversion.cpp @@ -271,12 +271,29 @@ void comment_to_html_conversion_16(int x1, int x2); // CHECK-NEXT: (CXComment_Paragraph // CHECK-NEXT: (CXComment_Text Text=[ Aaa.]))))] +/// \param x1 Aaa. +/// \param ... Bbb. +void comment_to_html_conversion_17(int x1, ...); + +// CHECK: comment-to-html-xml-conversion.cpp:[[@LINE-2]]:6: FunctionDecl=comment_to_html_conversion_17:{{.*}} FullCommentAsHTML=[
x1
Aaa.
...
Bbb.
] FullCommentAsXML=[comment_to_html_conversion_17c:@F@comment_to_html_conversion_17#I.#void comment_to_html_conversion_17(int x1, ...)x10in Aaa. ...in Bbb.] +// CHECK-NEXT: CommentAST=[ +// CHECK-NEXT: (CXComment_FullComment +// CHECK-NEXT: (CXComment_Paragraph IsWhitespace +// CHECK-NEXT: (CXComment_Text Text=[ ] IsWhitespace)) +// CHECK-NEXT: (CXComment_ParamCommand in implicitly ParamName=[x1] ParamIndex=0 +// CHECK-NEXT: (CXComment_Paragraph +// CHECK-NEXT: (CXComment_Text Text=[ Aaa.] HasTrailingNewline) +// CHECK-NEXT: (CXComment_Text Text=[ ] IsWhitespace))) +// CHECK-NEXT: (CXComment_ParamCommand in implicitly ParamName=[...] ParamIndex=4294967295 +// CHECK-NEXT: (CXComment_Paragraph +// CHECK-NEXT: (CXComment_Text Text=[ Bbb.]))))] Extent=[276:1 - 276:48] + /// \tparam /// \param aaa Blah blah template -void comment_to_html_conversion_17(T aaa); +void comment_to_html_conversion_18(T aaa); -// CHECK: comment-to-html-xml-conversion.cpp:[[@LINE-2]]:6: FunctionTemplate=comment_to_html_conversion_17:{{.*}} FullCommentAsHTML=[
aaa
Blah blah
] FullCommentAsXML=[comment_to_html_conversion_17c:@FT@>1#Tcomment_to_html_conversion_17#t0.0#template <typename T> void comment_to_html_conversion_17(T aaa)aaa0in Blah blah] +// CHECK: comment-to-html-xml-conversion.cpp:[[@LINE-2]]:6: FunctionTemplate=comment_to_html_conversion_18:{{.*}} FullCommentAsHTML=[
aaa
Blah blah
] FullCommentAsXML=[comment_to_html_conversion_18c:@FT@>1#Tcomment_to_html_conversion_18#t0.0#template <typename T> void comment_to_html_conversion_18(T aaa)aaa0in Blah blah] // CHECK-NEXT: CommentAST=[ // CHECK-NEXT: (CXComment_FullComment // CHECK-NEXT: (CXComment_Paragraph IsWhitespace @@ -291,9 +308,9 @@ void comment_to_html_conversion_17(T aaa); /// \tparam T /// \param aaa Blah blah template -void comment_to_html_conversion_18(T aaa); +void comment_to_html_conversion_19(T aaa); -// CHECK: comment-to-html-xml-conversion.cpp:[[@LINE-2]]:6: FunctionTemplate=comment_to_html_conversion_18:{{.*}} FullCommentAsHTML=[
aaa
Blah blah
] FullCommentAsXML=[comment_to_html_conversion_18c:@FT@>1#Tcomment_to_html_conversion_18#t0.0#template <typename T> void comment_to_html_conversion_18(T aaa)aaa0in Blah blah] +// CHECK: comment-to-html-xml-conversion.cpp:[[@LINE-2]]:6: FunctionTemplate=comment_to_html_conversion_19:{{.*}} FullCommentAsHTML=[
aaa
Blah blah
] FullCommentAsXML=[comment_to_html_conversion_19c:@FT@>1#Tcomment_to_html_conversion_19#t0.0#template <typename T> void comment_to_html_conversion_19(T aaa)aaa0in Blah blah] // CHECK-NEXT: CommentAST=[ // CHECK-NEXT: (CXComment_FullComment // CHECK-NEXT: (CXComment_Paragraph IsWhitespace @@ -308,9 +325,9 @@ void comment_to_html_conversion_18(T aaa); /// \tparam T2 Bbb /// \tparam T1 Aaa template -void comment_to_html_conversion_19(T1 aaa, T2 bbb); +void comment_to_html_conversion_20(T1 aaa, T2 bbb); -// CHECK: comment-to-html-xml-conversion.cpp:[[@LINE-2]]:6: FunctionTemplate=comment_to_html_conversion_19:{{.*}} FullCommentAsHTML=[
T1
Aaa
T2
Bbb
] FullCommentAsXML=[comment_to_html_conversion_19c:@FT@>2#T#Tcomment_to_html_conversion_19#t0.0#t0.1#template <typename T1, typename T2>\nvoid comment_to_html_conversion_19(T1 aaa, T2 bbb)T10 AaaT21 Bbb ] +// CHECK: comment-to-html-xml-conversion.cpp:[[@LINE-2]]:6: FunctionTemplate=comment_to_html_conversion_20:{{.*}} FullCommentAsHTML=[
T1
Aaa
T2
Bbb
] FullCommentAsXML=[comment_to_html_conversion_20c:@FT@>2#T#Tcomment_to_html_conversion_20#t0.0#t0.1#template <typename T1, typename T2>\nvoid comment_to_html_conversion_20(T1 aaa, T2 bbb)T10 AaaT21 Bbb ] // CHECK-NEXT: CommentAST=[ // CHECK-NEXT: (CXComment_FullComment // CHECK-NEXT: (CXComment_Paragraph IsWhitespace @@ -328,9 +345,9 @@ void comment_to_html_conversion_19(T1 aaa, T2 bbb); /// \tparam V Ccc /// \tparam T1 Aaa template -void comment_to_html_conversion_20(T1 aaa, T2 bbb); +void comment_to_html_conversion_21(T1 aaa, T2 bbb); -// CHECK: comment-to-html-xml-conversion.cpp:[[@LINE-2]]:6: FunctionTemplate=comment_to_html_conversion_20:{{.*}} FullCommentAsHTML=[
T1
Aaa
T2
Bbb
V
Ccc
U
Zzz
] FullCommentAsXML=[comment_to_html_conversion_20c:@FT@>3#T#T#NIcomment_to_html_conversion_20#t0.0#t0.1#template <typename T1, typename T2, int V>\nvoid comment_to_html_conversion_20(T1 aaa, T2 bbb)T10 AaaT21 Bbb V2 Ccc U Zzz ] +// CHECK: comment-to-html-xml-conversion.cpp:[[@LINE-2]]:6: FunctionTemplate=comment_to_html_conversion_21:{{.*}} FullCommentAsHTML=[
T1
Aaa
T2
Bbb
V
Ccc
U
Zzz
] FullCommentAsXML=[comment_to_html_conversion_21c:@FT@>3#T#T#NIcomment_to_html_conversion_21#t0.0#t0.1#template <typename T1, typename T2, int V>\nvoid comment_to_html_conversion_21(T1 aaa, T2 bbb)T10 AaaT21 Bbb V2 Ccc U Zzz ] // CHECK-NEXT: CommentAST=[ // CHECK-NEXT: (CXComment_FullComment // CHECK-NEXT: (CXComment_Paragraph IsWhitespace @@ -356,9 +373,9 @@ void comment_to_html_conversion_20(T1 aaa, T2 bbb); /// \tparam T Aaa /// \tparam TT Bbb template class TT, class C> class TTT> -void comment_to_html_conversion_21(); +void comment_to_html_conversion_22(); -// CHECK: comment-to-html-xml-conversion.cpp:[[@LINE-2]]:6: FunctionTemplate=comment_to_html_conversion_21:{{.*}} FullCommentAsHTML=[
TTT
Ddd
C
Ccc
T
Aaa
TT
Bbb
] FullCommentAsXML=[comment_to_html_conversion_21c:@FT@>1#t>2#t>1#T#Tcomment_to_html_conversion_21#template <template <template <typename T> class TT, class C> class TTT>\nvoid comment_to_html_conversion_21()TTT0 Ddd C Ccc T Aaa TT Bbb] +// CHECK: comment-to-html-xml-conversion.cpp:[[@LINE-2]]:6: FunctionTemplate=comment_to_html_conversion_22:{{.*}} FullCommentAsHTML=[
TTT
Ddd
C
Ccc
T
Aaa
TT
Bbb
] FullCommentAsXML=[comment_to_html_conversion_22c:@FT@>1#t>2#t>1#T#Tcomment_to_html_conversion_22#template <template <template <typename T> class TT, class C> class TTT>\nvoid comment_to_html_conversion_22()TTT0 Ddd C Ccc T Aaa TT Bbb] // CHECK-NEXT: CommentAST=[ // CHECK-NEXT: (CXComment_FullComment // CHECK-NEXT: (CXComment_Paragraph IsWhitespace @@ -386,9 +403,9 @@ void comment_to_html_conversion_21(); /// \param x2 Ddd. /// \param x1 Ccc. /// \returns Eee. -void comment_to_html_conversion_22(int x1, int x2); +void comment_to_html_conversion_23(int x1, int x2); -// CHECK: comment-to-html-xml-conversion.cpp:[[@LINE-2]]:6: FunctionDecl=comment_to_html_conversion_22:{{.*}} FullCommentAsHTML=[

Aaa.

Bbb.

x1
Ccc.
x2
Ddd.

Returns Eee.

] FullCommentAsXML=[comment_to_html_conversion_22c:@F@comment_to_html_conversion_22#I#I#void comment_to_html_conversion_22(int x1, int x2) Aaa.x10in Ccc. x21in Ddd. Eee. Bbb.] +// CHECK: comment-to-html-xml-conversion.cpp:[[@LINE-2]]:6: FunctionDecl=comment_to_html_conversion_23:{{.*}} FullCommentAsHTML=[

Aaa.

Bbb.

x1
Ccc.
x2
Ddd.

Returns Eee.

] FullCommentAsXML=[comment_to_html_conversion_23c:@F@comment_to_html_conversion_23#I#I#void comment_to_html_conversion_23(int x1, int x2) Aaa.x10in Ccc. x21in Ddd. Eee. Bbb.] // CHECK-NEXT: CommentAST=[ // CHECK-NEXT: (CXComment_FullComment // CHECK-NEXT: (CXComment_Paragraph IsWhitespace @@ -413,9 +430,9 @@ void comment_to_html_conversion_22(int x1, int x2); // CHECK-NEXT: (CXComment_Text Text=[ Eee.]))))] ///
Aaa -void comment_to_html_conversion_23(); +void comment_to_html_conversion_24(); -// CHECK: comment-to-html-xml-conversion.cpp:[[@LINE-2]]:6: FunctionDecl=comment_to_html_conversion_23:{{.*}} FullCommentAsHTML=[


Aaa

] FullCommentAsXML=[comment_to_html_conversion_23c:@F@comment_to_html_conversion_23#void comment_to_html_conversion_23() ]]>]]>Aaa</a>] +// CHECK: comment-to-html-xml-conversion.cpp:[[@LINE-2]]:6: FunctionDecl=comment_to_html_conversion_24:{{.*}} FullCommentAsHTML=[


Aaa

] FullCommentAsXML=[comment_to_html_conversion_24c:@F@comment_to_html_conversion_24#void comment_to_html_conversion_24() ]]>]]>Aaa</a>] // CHECK-NEXT: CommentAST=[ // CHECK-NEXT: (CXComment_FullComment // CHECK-NEXT: (CXComment_Paragraph @@ -429,9 +446,9 @@ void comment_to_html_conversion_23(); /// Aaa /// Aaa /// \endverbatim -void comment_to_html_conversion_24(); +void comment_to_html_conversion_25(); -// CHECK: comment-to-html-xml-conversion.cpp:[[@LINE-2]]:6: FunctionDecl=comment_to_html_conversion_24:{{.*}} FullCommentAsHTML=[
 <a href="http://example.com/">Aaa</a>\n <a href='http://example.com/'>Aaa</a>
] FullCommentAsXML=[comment_to_html_conversion_24c:@F@comment_to_html_conversion_24#void comment_to_html_conversion_24() <a href="http://example.com/">Aaa</a>\n <a href='http://example.com/'>Aaa</a>] +// CHECK: comment-to-html-xml-conversion.cpp:[[@LINE-2]]:6: FunctionDecl=comment_to_html_conversion_25:{{.*}} FullCommentAsHTML=[
 <a href="http://example.com/">Aaa</a>\n <a href='http://example.com/'>Aaa</a>
] FullCommentAsXML=[comment_to_html_conversion_25c:@F@comment_to_html_conversion_25#void comment_to_html_conversion_25() <a href="http://example.com/">Aaa</a>\n <a href='http://example.com/'>Aaa</a>] // CHECK-NEXT: CommentAST=[ // CHECK-NEXT: (CXComment_FullComment // CHECK-NEXT: (CXComment_Paragraph IsWhitespace @@ -445,9 +462,9 @@ void comment_to_html_conversion_24(); /// \method foo /// \interface foo /// Blah blah. -void comment_to_html_conversion_25(); +void comment_to_html_conversion_26(); -// CHECK: comment-to-html-xml-conversion.cpp:[[@LINE-2]]:6: FunctionDecl=comment_to_html_conversion_25:{{.*}} FullCommentAsHTML=[

Blah blah.

] FullCommentAsXML=[comment_to_html_conversion_25c:@F@comment_to_html_conversion_25#void comment_to_html_conversion_25() Blah blah.] +// CHECK: comment-to-html-xml-conversion.cpp:[[@LINE-2]]:6: FunctionDecl=comment_to_html_conversion_26:{{.*}} FullCommentAsHTML=[

Blah blah.

] FullCommentAsXML=[comment_to_html_conversion_26c:@F@comment_to_html_conversion_26#void comment_to_html_conversion_26() Blah blah.] // CHECK-NEXT: CommentAST=[ // CHECK-NEXT: (CXComment_FullComment // CHECK-NEXT: (CXComment_Paragraph IsWhitespace @@ -466,9 +483,9 @@ void comment_to_html_conversion_25(); // CHECK-NEXT: (CXComment_Text Text=[ Blah blah.])))] /// \unknown -void comment_to_html_conversion_26(); +void comment_to_html_conversion_27(); -// CHECK: comment-to-html-xml-conversion.cpp:[[@LINE-2]]:6: FunctionDecl=comment_to_html_conversion_26:{{.*}} FullCommentAsHTML=[

] FullCommentAsXML=[comment_to_html_conversion_26c:@F@comment_to_html_conversion_26#void comment_to_html_conversion_26() ] +// CHECK: comment-to-html-xml-conversion.cpp:[[@LINE-2]]:6: FunctionDecl=comment_to_html_conversion_27:{{.*}} FullCommentAsHTML=[

] FullCommentAsXML=[comment_to_html_conversion_27c:@F@comment_to_html_conversion_27#void comment_to_html_conversion_27() ] // CHECK-NEXT: CommentAST=[ // CHECK-NEXT: (CXComment_FullComment // CHECK-NEXT: (CXComment_Paragraph @@ -476,9 +493,9 @@ void comment_to_html_conversion_26(); // CHECK-NEXT: (CXComment_InlineCommand CommandName=[unknown] RenderNormal)))] /// \b Aaa -void comment_to_html_conversion_27(); +void comment_to_html_conversion_28(); -// CHECK: comment-to-html-xml-conversion.cpp:[[@LINE-2]]:6: FunctionDecl=comment_to_html_conversion_27:{{.*}} FullCommentAsHTML=[

Aaa

] FullCommentAsXML=[comment_to_html_conversion_27c:@F@comment_to_html_conversion_27#void comment_to_html_conversion_27() Aaa] +// CHECK: comment-to-html-xml-conversion.cpp:[[@LINE-2]]:6: FunctionDecl=comment_to_html_conversion_28:{{.*}} FullCommentAsHTML=[

Aaa

] FullCommentAsXML=[comment_to_html_conversion_28c:@F@comment_to_html_conversion_28#void comment_to_html_conversion_28() Aaa] // CHECK-NEXT: CommentAST=[ // CHECK-NEXT: (CXComment_FullComment // CHECK-NEXT: (CXComment_Paragraph @@ -486,9 +503,9 @@ void comment_to_html_conversion_27(); // CHECK-NEXT: (CXComment_InlineCommand CommandName=[b] RenderBold Arg[0]=Aaa)))] /// \c Aaa \p Bbb -void comment_to_html_conversion_28(); +void comment_to_html_conversion_29(); -// CHECK: comment-to-html-xml-conversion.cpp:[[@LINE-2]]:6: FunctionDecl=comment_to_html_conversion_28:{{.*}} FullCommentAsHTML=[

Aaa Bbb

] FullCommentAsXML=[comment_to_html_conversion_28c:@F@comment_to_html_conversion_28#void comment_to_html_conversion_28() Aaa Bbb] +// CHECK: comment-to-html-xml-conversion.cpp:[[@LINE-2]]:6: FunctionDecl=comment_to_html_conversion_29:{{.*}} FullCommentAsHTML=[

Aaa Bbb

] FullCommentAsXML=[comment_to_html_conversion_29c:@F@comment_to_html_conversion_29#void comment_to_html_conversion_29() Aaa Bbb] // CHECK-NEXT: CommentAST=[ // CHECK-NEXT: (CXComment_FullComment // CHECK-NEXT: (CXComment_Paragraph @@ -498,9 +515,9 @@ void comment_to_html_conversion_28(); // CHECK-NEXT: (CXComment_InlineCommand CommandName=[p] RenderMonospaced Arg[0]=Bbb)))] /// \a Aaa \e Bbb \em Ccc -void comment_to_html_conversion_29(); +void comment_to_html_conversion_30(); -// CHECK: comment-to-html-xml-conversion.cpp:[[@LINE-2]]:6: FunctionDecl=comment_to_html_conversion_29:{{.*}} FullCommentAsHTML=[

Aaa Bbb Ccc

] FullCommentAsXML=[comment_to_html_conversion_29c:@F@comment_to_html_conversion_29#void comment_to_html_conversion_29() Aaa Bbb Ccc] +// CHECK: comment-to-html-xml-conversion.cpp:[[@LINE-2]]:6: FunctionDecl=comment_to_html_conversion_30:{{.*}} FullCommentAsHTML=[

Aaa Bbb Ccc

] FullCommentAsXML=[comment_to_html_conversion_30c:@F@comment_to_html_conversion_30#void comment_to_html_conversion_30() Aaa Bbb Ccc] // CHECK-NEXT: CommentAST=[ // CHECK-NEXT: (CXComment_FullComment // CHECK-NEXT: (CXComment_Paragraph @@ -512,9 +529,9 @@ void comment_to_html_conversion_29(); // CHECK-NEXT: (CXComment_InlineCommand CommandName=[em] RenderEmphasized Arg[0]=Ccc)))] /// \a 1<2 \e 3<4 \em 5<6 \param 7<8 aaa \tparam 9<10 bbb -void comment_to_html_conversion_30(); +void comment_to_html_conversion_31(); -// CHECK: comment-to-html-xml-conversion.cpp:[[@LINE-2]]:6: FunctionDecl=comment_to_html_conversion_30:{{.*}} FullCommentAsHTML=[

1<2 3<4 5<6

9<10
bbb
7<8
aaa
] FullCommentAsXML=[comment_to_html_conversion_30c:@F@comment_to_html_conversion_30#void comment_to_html_conversion_30() 1<2 3<4 5<6 9<10 bbb7<8in aaa ] +// CHECK: comment-to-html-xml-conversion.cpp:[[@LINE-2]]:6: FunctionDecl=comment_to_html_conversion_31:{{.*}} FullCommentAsHTML=[

1<2 3<4 5<6

9<10
bbb
7<8
aaa
] FullCommentAsXML=[comment_to_html_conversion_31c:@F@comment_to_html_conversion_31#void comment_to_html_conversion_31() 1<2 3<4 5<6 9<10 bbb7<8in aaa ] // CHECK-NEXT: CommentAST=[ // CHECK-NEXT: (CXComment_FullComment // CHECK-NEXT: (CXComment_Paragraph @@ -533,9 +550,9 @@ void comment_to_html_conversion_30(); // CHECK-NEXT: (CXComment_Text Text=[ bbb]))))] /// \\ \@ \& \$ \# \< \> \% \" \. \:: -void comment_to_html_conversion_31(); +void comment_to_html_conversion_32(); -// CHECK: comment-to-html-xml-conversion.cpp:[[@LINE-2]]:6: FunctionDecl=comment_to_html_conversion_31:{{.*}} FullCommentAsHTML=[

\ @ & $ # < > % " . ::

] FullCommentAsXML=[comment_to_html_conversion_31c:@F@comment_to_html_conversion_31#void comment_to_html_conversion_31() \ @ & $ # < > % " . ::] +// CHECK: comment-to-html-xml-conversion.cpp:[[@LINE-2]]:6: FunctionDecl=comment_to_html_conversion_32:{{.*}} FullCommentAsHTML=[

\ @ & $ # < > % " . ::

] FullCommentAsXML=[comment_to_html_conversion_32c:@F@comment_to_html_conversion_32#void comment_to_html_conversion_32() \ @ & $ # < > % " . ::] // CHECK-NEXT: CommentAST=[ // CHECK-NEXT: (CXComment_FullComment // CHECK-NEXT: (CXComment_Paragraph @@ -563,9 +580,9 @@ void comment_to_html_conversion_31(); // CHECK-NEXT: (CXComment_Text Text=[::])))] /// & < > " ' meow meow -void comment_to_html_conversion_32(); +void comment_to_html_conversion_33(); -// CHECK: comment-to-html-xml-conversion.cpp:[[@LINE-2]]:6: FunctionDecl=comment_to_html_conversion_32:{{.*}} FullCommentAsHTML=[

& < > " ' meow meow

] FullCommentAsXML=[comment_to_html_conversion_32c:@F@comment_to_html_conversion_32#void comment_to_html_conversion_32() & < > " ' meow meow] +// CHECK: comment-to-html-xml-conversion.cpp:[[@LINE-2]]:6: FunctionDecl=comment_to_html_conversion_33:{{.*}} FullCommentAsHTML=[

& < > " ' meow meow

] FullCommentAsXML=[comment_to_html_conversion_33c:@F@comment_to_html_conversion_33#void comment_to_html_conversion_33() & < > " ' meow meow] // CHECK-NEXT: CommentAST=[ // CHECK-NEXT: (CXComment_FullComment // CHECK-NEXT: (CXComment_Paragraph @@ -591,9 +608,9 @@ void comment_to_html_conversion_32(); // CHECK-NEXT: (CXComment_Text Text=[w])))] /// 0<i -void comment_to_html_conversion_33(); +void comment_to_html_conversion_34(); -// CHECK: comment-to-html-xml-conversion.cpp:[[@LINE-2]]:6: FunctionDecl=comment_to_html_conversion_33:{{.*}} FullCommentAsHTML=[

0<i

] FullCommentAsXML=[comment_to_html_conversion_33c:@F@comment_to_html_conversion_33#void comment_to_html_conversion_33() ]]>0<i</em>] +// CHECK: comment-to-html-xml-conversion.cpp:[[@LINE-2]]:6: FunctionDecl=comment_to_html_conversion_34:{{.*}} FullCommentAsHTML=[

0<i

] FullCommentAsXML=[comment_to_html_conversion_34c:@F@comment_to_html_conversion_34#void comment_to_html_conversion_34() ]]>0<i</em>] // CHECK-NEXT: CommentAST=[ // CHECK-NEXT: (CXComment_FullComment // CHECK-NEXT: (CXComment_Paragraph @@ -611,9 +628,9 @@ void comment_to_html_conversion_33(); ///   a non breakable space. /// Δ Greek letter Delta Δ. /// Γ Greek letter Gamma Γ. -void comment_to_html_conversion_34(); +void comment_to_html_conversion_35(); -// CHECK: comment-to-html-xml-conversion.cpp:[[@LINE-2]]:6: FunctionDecl=comment_to_html_conversion_34:{{.*}} FullCommentAsHTML=[

© the copyright symbol ™ the trade mark symbol ® the registered trade mark symbol   a non breakable space. Δ Greek letter Delta Δ. Γ Greek letter Gamma Γ.

] FullCommentAsXML=[comment_to_html_conversion_34c:@F@comment_to_html_conversion_34#void comment_to_html_conversion_34() © the copyright symbol ™ the trade mark symbol ® the registered trade mark symbol   a non breakable space. Δ Greek letter Delta Δ. Γ Greek letter Gamma Γ.] +// CHECK: comment-to-html-xml-conversion.cpp:[[@LINE-2]]:6: FunctionDecl=comment_to_html_conversion_35:{{.*}} FullCommentAsHTML=[

© the copyright symbol ™ the trade mark symbol ® the registered trade mark symbol   a non breakable space. Δ Greek letter Delta Δ. Γ Greek letter Gamma Γ.

] FullCommentAsXML=[comment_to_html_conversion_35c:@F@comment_to_html_conversion_35#void comment_to_html_conversion_35() © the copyright symbol ™ the trade mark symbol ® the registered trade mark symbol   a non breakable space. Δ Greek letter Delta Δ. Γ Greek letter Gamma Γ.] // CHECK-NEXT: CommentAST=[ // CHECK-NEXT: (CXComment_FullComment // CHECK-NEXT: (CXComment_Paragraph diff --git a/test/Index/comment-xml-schema.c b/test/Index/comment-xml-schema.c index b8560f7e27..0c0929f15d 100644 --- a/test/Index/comment-xml-schema.c +++ b/test/Index/comment-xml-schema.c @@ -45,6 +45,7 @@ // RUN: xmllint --noout --relaxng %S/../../bindings/xml/comment-xml-schema.rng %S/Inputs/CommentXML/invalid-function-10.xml 2>&1 | FileCheck %s -check-prefix=INVALID // RUN: xmllint --noout --relaxng %S/../../bindings/xml/comment-xml-schema.rng %S/Inputs/CommentXML/invalid-function-11.xml 2>&1 | FileCheck %s -check-prefix=INVALID // RUN: xmllint --noout --relaxng %S/../../bindings/xml/comment-xml-schema.rng %S/Inputs/CommentXML/invalid-function-12.xml 2>&1 | FileCheck %s -check-prefix=INVALID +// RUN: xmllint --noout --relaxng %S/../../bindings/xml/comment-xml-schema.rng %S/Inputs/CommentXML/invalid-function-13.xml 2>&1 | FileCheck %s -check-prefix=INVALID // // RUN: xmllint --noout --relaxng %S/../../bindings/xml/comment-xml-schema.rng %S/Inputs/CommentXML/invalid-para-kind-01.xml 2>&1 | FileCheck %s -check-prefix=INVALID // RUN: xmllint --noout --relaxng %S/../../bindings/xml/comment-xml-schema.rng %S/Inputs/CommentXML/invalid-para-kind-02.xml 2>&1 | FileCheck %s -check-prefix=INVALID diff --git a/test/Sema/warn-documentation.cpp b/test/Sema/warn-documentation.cpp index 21b8dcb0d2..7166a49909 100644 --- a/test/Sema/warn-documentation.cpp +++ b/test/Sema/warn-documentation.cpp @@ -305,6 +305,22 @@ typedef test_param27 test_param28; typedef unsigned int test_param29; +/// \param aaa Aaa +/// \param ... Vararg +int test_vararg_param1(int aaa, ...); + +/// \param ... Vararg +int test_vararg_param2(...); + +// expected-warning@+1 {{parameter '...' not found in the function declaration}} expected-note@+1 {{did you mean 'aaa'?}} +/// \param ... Vararg +int test_vararg_param3(int aaa); + +// expected-warning@+1 {{parameter '...' not found in the function declaration}} +/// \param ... Vararg +int test_vararg_param4(); + + // expected-warning@+1 {{'\tparam' command used in a comment that is not attached to a template declaration}} /// \tparam T Aaa int test_tparam1; diff --git a/test/Sema/warn-documentation.m b/test/Sema/warn-documentation.m index 17dd92e6eb..5e95e2a1e8 100644 --- a/test/Sema/warn-documentation.m +++ b/test/Sema/warn-documentation.m @@ -215,3 +215,17 @@ int FooBar(); /// \brief comment -(void)meth {} @end + +// rdar://14124644 +@interface test_vararg1 +/// @param[in] arg somthing +/// @param[in] ... This is vararg +- (void) VarArgMeth : (id)arg, ...; +@end + +@implementation test_vararg1 +/// @param[in] arg somthing +/// @param[in] ... This is vararg +- (void) VarArgMeth : (id)arg, ... {} +@end + diff --git a/tools/libclang/CXComment.cpp b/tools/libclang/CXComment.cpp index 583b850a44..ad131a5221 100644 --- a/tools/libclang/CXComment.cpp +++ b/tools/libclang/CXComment.cpp @@ -268,7 +268,7 @@ unsigned clang_ParamCommandComment_isParamIndexValid(CXComment CXC) { unsigned clang_ParamCommandComment_getParamIndex(CXComment CXC) { const ParamCommandComment *PCC = getASTNodeAs(CXC); - if (!PCC || !PCC->isParamIndexValid()) + if (!PCC || !PCC->isParamIndexValid() || PCC->isVarArgParam()) return ParamCommandComment::InvalidParamIndex; return PCC->getParamIndex(); @@ -358,19 +358,27 @@ CXString clang_VerbatimLineComment_getText(CXComment CXC) { namespace { -/// This comparison will sort parameters with valid index by index and -/// invalid (unresolved) parameters last. +/// This comparison will sort parameters with valid index by index, then vararg +/// parameters, and invalid (unresolved) parameters last. class ParamCommandCommentCompareIndex { public: bool operator()(const ParamCommandComment *LHS, const ParamCommandComment *RHS) const { unsigned LHSIndex = UINT_MAX; unsigned RHSIndex = UINT_MAX; - if (LHS->isParamIndexValid()) - LHSIndex = LHS->getParamIndex(); - if (RHS->isParamIndexValid()) - RHSIndex = RHS->getParamIndex(); + if (LHS->isParamIndexValid()) { + if (LHS->isVarArgParam()) + LHSIndex = UINT_MAX - 1; + else + LHSIndex = LHS->getParamIndex(); + } + if (RHS->isParamIndexValid()) { + if (RHS->isVarArgParam()) + RHSIndex = UINT_MAX - 1; + else + RHSIndex = RHS->getParamIndex(); + } return LHSIndex < RHSIndex; } }; @@ -671,10 +679,15 @@ void CommentASTToHTMLConverter::visitBlockCommandComment( void CommentASTToHTMLConverter::visitParamCommandComment( const ParamCommandComment *C) { if (C->isParamIndexValid()) { - Result << "
getParamIndex() - << "\">"; - appendToResultWithHTMLEscaping(C->getParamName(FC)); + if (C->isVarArgParam()) { + Result << "
"; + appendToResultWithHTMLEscaping(C->getParamNameAsWritten()); + } else { + Result << "
getParamIndex() + << "\">"; + appendToResultWithHTMLEscaping(C->getParamName(FC)); + } } else { Result << "
"; appendToResultWithHTMLEscaping(C->getParamNameAsWritten()); @@ -682,9 +695,12 @@ void CommentASTToHTMLConverter::visitParamCommandComment( Result << "
"; if (C->isParamIndexValid()) { - Result << "
getParamIndex() - << "\">"; + if (C->isVarArgParam()) + Result << "
"; + else + Result << "
getParamIndex() + << "\">"; } else Result << "
"; @@ -1070,8 +1086,12 @@ void CommentASTToXMLConverter::visitParamCommandComment(const ParamCommandCommen : C->getParamNameAsWritten()); Result << ""; - if (C->isParamIndexValid()) - Result << "" << C->getParamIndex() << ""; + if (C->isParamIndexValid()) { + if (C->isVarArgParam()) + Result << ""; + else + Result << "" << C->getParamIndex() << ""; + } Result << "isDirectionExplicit() << "\">"; switch (C->getDirection()) {