diff options
-rw-r--r-- | bindings/xml/comment-xml-schema.rng | 29 | ||||
-rw-r--r-- | include/clang/AST/CommentCommandTraits.h | 3 | ||||
-rw-r--r-- | include/clang/AST/CommentCommands.td | 3 | ||||
-rw-r--r-- | include/clang/AST/CommentSema.h | 3 | ||||
-rw-r--r-- | lib/AST/CommentSema.cpp | 9 | ||||
-rw-r--r-- | test/Index/headerfile-comment-to-html.m | 111 | ||||
-rw-r--r-- | test/Sema/warn-documentation.cpp | 8 | ||||
-rw-r--r-- | tools/libclang/CXComment.cpp | 17 | ||||
-rw-r--r-- | utils/TableGen/ClangCommentCommandInfoEmitter.cpp | 1 |
9 files changed, 180 insertions, 4 deletions
diff --git a/bindings/xml/comment-xml-schema.rng b/bindings/xml/comment-xml-schema.rng index d98f405cf9..ed221c60f8 100644 --- a/bindings/xml/comment-xml-schema.rng +++ b/bindings/xml/comment-xml-schema.rng @@ -25,6 +25,9 @@ <ref name="USR" /> </optional> <optional> + <ref name="Headerfile" /> + </optional> + <optional> <ref name="Declaration" /> </optional> <optional> @@ -74,6 +77,9 @@ </optional> <!-- TODO: Add exception specification. --> <optional> + <ref name="Headerfile" /> + </optional> + <optional> <ref name="Declaration" /> </optional> <optional> @@ -121,6 +127,9 @@ <ref name="USR" /> </optional> <optional> + <ref name="Headerfile" /> + </optional> + <optional> <ref name="Declaration" /> </optional> <optional> @@ -153,6 +162,9 @@ <ref name="USR" /> </optional> <optional> + <ref name="Headerfile" /> + </optional> + <optional> <ref name="Declaration" /> </optional> <optional> @@ -186,6 +198,9 @@ <ref name="USR" /> </optional> <optional> + <ref name="Headerfile" /> + </optional> + <optional> <ref name="Declaration" /> </optional> <optional> @@ -219,6 +234,9 @@ <ref name="USR" /> </optional> <optional> + <ref name="Headerfile" /> + </optional> + <optional> <ref name="Declaration" /> </optional> <optional> @@ -252,6 +270,9 @@ <ref name="USR" /> </optional> <optional> + <ref name="Headerfile" /> + </optional> + <optional> <ref name="Declaration" /> </optional> <optional> @@ -329,6 +350,14 @@ </element> </define> + <define name="Headerfile"> + <element name="Headerfile"> + <oneOrMore> + <ref name="TextBlockContent" /> + </oneOrMore> + </element> + </define> + <define name="Discussion"> <element name="Discussion"> <zeroOrMore> diff --git a/include/clang/AST/CommentCommandTraits.h b/include/clang/AST/CommentCommandTraits.h index 3e04726b43..44876a534d 100644 --- a/include/clang/AST/CommentCommandTraits.h +++ b/include/clang/AST/CommentCommandTraits.h @@ -68,6 +68,9 @@ struct CommandInfo { /// True if this command is \\deprecated or an alias. unsigned IsDeprecatedCommand : 1; + + /// \brief True if this is a \headerfile-like documentation + unsigned IsHeaderfileCommand : 1; /// True if we don't want to warn about this command being passed an empty /// paragraph. Meaningful only for block commands. diff --git a/include/clang/AST/CommentCommands.td b/include/clang/AST/CommentCommands.td index 3d8bad89c2..ce051a069d 100644 --- a/include/clang/AST/CommentCommands.td +++ b/include/clang/AST/CommentCommands.td @@ -12,6 +12,7 @@ class Command<string name> { bit IsParamCommand = 0; bit IsTParamCommand = 0; bit IsDeprecatedCommand = 0; + bit IsHeaderfileCommand = 0; bit IsEmptyParagraphAllowed = 0; @@ -80,7 +81,7 @@ def Deprecated : BlockCommand<"deprecated"> { let IsEmptyParagraphAllowed = 1; let IsDeprecatedCommand = 1; } - +def Headerfile : BlockCommand<"headerfile"> { let IsHeaderfileCommand = 1; } def Author : BlockCommand<"author">; def Authors : BlockCommand<"authors">; def Bug : BlockCommand<"bug">; diff --git a/include/clang/AST/CommentSema.h b/include/clang/AST/CommentSema.h index 58cb5d7cfb..97099bfe63 100644 --- a/include/clang/AST/CommentSema.h +++ b/include/clang/AST/CommentSema.h @@ -60,6 +60,9 @@ class Sema { /// AST node for the \\returns command and its aliases. const BlockCommandComment *ReturnsCommand; + + /// AST node for the \\headerfile command. + const BlockCommandComment *HeaderfileCommand; DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID) { return Diags.Report(Loc, DiagID); diff --git a/lib/AST/CommentSema.cpp b/lib/AST/CommentSema.cpp index 590429809b..fd2b5b1810 100644 --- a/lib/AST/CommentSema.cpp +++ b/lib/AST/CommentSema.cpp @@ -29,7 +29,8 @@ Sema::Sema(llvm::BumpPtrAllocator &Allocator, const SourceManager &SourceMgr, DiagnosticsEngine &Diags, CommandTraits &Traits, const Preprocessor *PP) : Allocator(Allocator), SourceMgr(SourceMgr), Diags(Diags), Traits(Traits), - PP(PP), ThisDeclInfo(NULL), BriefCommand(NULL), ReturnsCommand(NULL) { + PP(PP), ThisDeclInfo(NULL), BriefCommand(NULL), ReturnsCommand(NULL), + HeaderfileCommand(NULL) { } void Sema::setDecl(const Decl *D) { @@ -485,6 +486,12 @@ void Sema::checkBlockCommandDuplicate(const BlockCommandComment *Command) { return; } PrevCommand = ReturnsCommand; + } else if (Info->IsHeaderfileCommand) { + if (!HeaderfileCommand) { + HeaderfileCommand = Command; + return; + } + PrevCommand = HeaderfileCommand; } else { // We don't want to check this command for duplicates. return; diff --git a/test/Index/headerfile-comment-to-html.m b/test/Index/headerfile-comment-to-html.m new file mode 100644 index 0000000000..f2e55f07f8 --- /dev/null +++ b/test/Index/headerfile-comment-to-html.m @@ -0,0 +1,111 @@ +// RUN: rm -rf %t +// RUN: mkdir %t +// RUN: c-index-test -test-load-source all -comments-xml-schema=%S/../../bindings/xml/comment-xml-schema.rng %s > %t/out +// RUN: FileCheck %s < %t/out +// rdar://13067629 + +// Ensure that XML we generate is not invalid. +// RUN: FileCheck %s -check-prefix=WRONG < %t/out +// WRONG-NOT: CommentXMLInvalid + +// rdar://12397511 + +/*! + \headerfile Device.h <Foundation/Device.h> + + A Device represents a remote or local computer or device with which the Developer Tools can interact. Each Device supports blah blah blah from doing blah blah blah. +*/ +@interface Device +@end +// CHECK: headerfile-comment-to-html.m:[[@LINE-2]]:12: ObjCInterfaceDecl=Device:{{.*}} FullCommentAsXML=[<Other file="{{[^"]+}}headerfile-comment-to-html.m" line="[[@LINE-2]]" column="12"><Name>Device</Name><USR>c:objc(cs)Device</USR><Headerfile><Para> Device.h <Foundation/Device.h></Para></Headerfile><Declaration>@interface Device\n@end</Declaration><Abstract><Para> A Device represents a remote or local computer or device with which the Developer Tools can interact. Each Device supports blah blah blah from doing blah blah blah.</Para></Abstract></Other>] CommentXMLValid +// CHECK-NEXT: CommentAST=[ +// CHECK-NEXT: (CXComment_FullComment +// CHECK-NEXT: (CXComment_Paragraph IsWhitespace +// CHECK-NEXT: (CXComment_Text Text=[ ] IsWhitespace)) +// CHECK-NEXT: (CXComment_BlockCommand CommandName=[headerfile] +// CHECK-NEXT: (CXComment_Paragraph +// CHECK-NEXT: (CXComment_Text Text=[ Device.h ]) +// CHECK-NEXT: (CXComment_Text Text=[<Foundation]) +// CHECK-NEXT: (CXComment_Text Text=[/Device.h>]))) +// CHECK-NEXT: (CXComment_Paragraph +// CHECK-NEXT: (CXComment_Text Text=[ A Device represents a remote or local computer or device with which the Developer Tools can interact. Each Device supports blah blah blah from doing blah blah blah.])))] + +/*! + \headerfile Sensor.h "Sensor.h" + + \brief This is Sensor on the Device. + Its purpose is not to Sense Device's heat. +*/ + +@interface Sensor +@end +// CHECK: headerfile-comment-to-html.m:[[@LINE-2]]:12: ObjCInterfaceDecl=Sensor:{{.*}} FullCommentAsXML=[<Other file="{{[^"]+}}headerfile-comment-to-html.m" line="[[@LINE-2]]" column="12"><Name>Sensor</Name><USR>c:objc(cs)Sensor</USR><Headerfile><Para> Sensor.h "Sensor.h"</Para></Headerfile><Declaration>@interface Sensor\n@end</Declaration><Abstract><Para> This is Sensor on the Device. Its purpose is not to Sense Device's heat.</Para></Abstract></Other>] CommentXMLValid +// CHECK-NEXT: CommentAST=[ +// CHECK-NEXT: (CXComment_FullComment +// CHECK-NEXT: (CXComment_Paragraph IsWhitespace +// CHECK-NEXT: (CXComment_Text Text=[ ] IsWhitespace)) +// CHECK-NEXT: (CXComment_BlockCommand CommandName=[headerfile] +// CHECK-NEXT: (CXComment_Paragraph +// CHECK-NEXT: (CXComment_Text Text=[ Sensor.h "Sensor.h"]))) +// CHECK-NEXT: (CXComment_Paragraph IsWhitespace +// CHECK-NEXT: (CXComment_Text Text=[ ] IsWhitespace)) +// CHECK-NEXT: (CXComment_BlockCommand CommandName=[brief] +// CHECK-NEXT: (CXComment_Paragraph +// CHECK-NEXT: (CXComment_Text Text=[ This is Sensor on the Device.] HasTrailingNewline) +// CHECK-NEXT: (CXComment_Text Text=[ Its purpose is not to Sense Device's heat.]))))] + +/*! + \brief Test that headerfile can come after brief. + \headerfile VTDevice.h <VTFoundation/VTDevice.h> + + More property decription goes here. +*/ +@interface VTDevice : Device +@end +// CHECK: headerfile-comment-to-html.m:[[@LINE-2]]:12: ObjCInterfaceDecl=VTDevice:{{.*}} FullCommentAsXML=[<Other file="{{[^"]+}}headerfile-comment-to-html.m" line="[[@LINE-2]]" column="12"><Name>VTDevice</Name><USR>c:objc(cs)VTDevice</USR><Headerfile><Para> VTDevice.h <VTFoundation/VTDevice.h></Para></Headerfile><Declaration>@interface VTDevice : Device\n@end</Declaration><Abstract><Para> Test that headerfile can come after brief. </Para></Abstract><Discussion><Para> More property decription goes here.</Para></Discussion></Other>] CommentXMLValid +// CHECK-NEXT: CommentAST=[ +// CHECK-NEXT: (CXComment_FullComment +// CHECK-NEXT: (CXComment_Paragraph IsWhitespace +// CHECK-NEXT: (CXComment_Text Text=[ ] IsWhitespace)) +// CHECK-NEXT: (CXComment_BlockCommand CommandName=[brief] +// CHECK-NEXT: (CXComment_Paragraph +// CHECK-NEXT: (CXComment_Text Text=[ Test that headerfile can come after brief.] HasTrailingNewline) +// CHECK-NEXT: (CXComment_Text Text=[ ] IsWhitespace))) +// CHECK-NEXT: (CXComment_BlockCommand CommandName=[headerfile] +// CHECK-NEXT: (CXComment_Paragraph +// CHECK-NEXT: (CXComment_Text Text=[ VTDevice.h ]) +// CHECK-NEXT: (CXComment_Text Text=[<VTFoundation]) +// CHECK-NEXT: (CXComment_Text Text=[/VTDevice.h>]))) +// CHECK-NEXT: (CXComment_Paragraph +// CHECK-NEXT: (CXComment_Text Text=[ More property decription goes here.])))] + +/*! + \headerfile <stdio.h> +*/ +extern void uses_stdio_h(); +// CHECK: headerfile-comment-to-html.m:[[@LINE-1]]:13: FunctionDecl=uses_stdio_h:{{.*}} FullCommentAsXML=[<Function file="{{[^"]+}}headerfile-comment-to-html.m" line="[[@LINE-1]]" column="13"><Name>uses_stdio_h</Name><USR>c:@F@uses_stdio_h</USR><Headerfile><Para> <stdio.h></Para></Headerfile><Declaration>extern void uses_stdio_h()</Declaration></Function>] CommentXMLValid +// CHECK-NEXT: CommentAST=[ +// CHECK-NEXT: (CXComment_FullComment +// CHECK-NEXT: (CXComment_Paragraph IsWhitespace +// CHECK-NEXT: (CXComment_Text Text=[ ] IsWhitespace)) +// CHECK-NEXT: (CXComment_BlockCommand CommandName=[headerfile] +// CHECK-NEXT: (CXComment_Paragraph +// CHECK-NEXT: (CXComment_Text Text=[ ] IsWhitespace) +// CHECK-NEXT: (CXComment_Text Text=[<stdio]) +// CHECK-NEXT: (CXComment_Text Text=[.h>]))))] + + +/*! + \headerfile <algorithm> +*/ +extern void uses_argorithm(); +// CHECK: headerfile-comment-to-html.m:[[@LINE-1]]:13: FunctionDecl=uses_argorithm:{{.*}} FullCommentAsXML=[<Function file="{{[^"]+}}headerfile-comment-to-html.m" line="[[@LINE-1]]" column="13"><Name>uses_argorithm</Name><USR>c:@F@uses_argorithm</USR><Headerfile><Para> <algorithm></Para></Headerfile><Declaration>extern void uses_argorithm()</Declaration></Function>] CommentXMLValid +// CHECK-NEXT: CommentAST=[ +// CHECK-NEXT: (CXComment_FullComment +// CHECK-NEXT: (CXComment_Paragraph IsWhitespace +// CHECK-NEXT: (CXComment_Text Text=[ ] IsWhitespace)) +// CHECK-NEXT: (CXComment_BlockCommand CommandName=[headerfile] +// CHECK-NEXT: (CXComment_Paragraph +// CHECK-NEXT: (CXComment_Text Text=[ ] IsWhitespace) +// CHECK-NEXT: (CXComment_Text Text=[<algorithm]) +// CHECK-NEXT: (CXComment_Text Text=[>]))))] diff --git a/test/Sema/warn-documentation.cpp b/test/Sema/warn-documentation.cpp index 9845f58780..e2e49e59bf 100644 --- a/test/Sema/warn-documentation.cpp +++ b/test/Sema/warn-documentation.cpp @@ -887,3 +887,11 @@ int test_nocrash12(); ///@param x@param y int test_nocrash13(int x, int y); +// rdar://12397511 + +// expected-note@+2 {{previous command '\headerfile' here}} +// expected-warning@+2 {{duplicated command '\headerfile'}} +/// \headerfile "" +/// \headerfile foo.h +int test_duplicate_headerfile1(int); + diff --git a/tools/libclang/CXComment.cpp b/tools/libclang/CXComment.cpp index 0fcd7c2166..57bab18546 100644 --- a/tools/libclang/CXComment.cpp +++ b/tools/libclang/CXComment.cpp @@ -411,6 +411,7 @@ struct FullCommentParts { const CommandTraits &Traits); const BlockContentComment *Brief; + const BlockContentComment *Headerfile; const ParagraphComment *FirstParagraph; const BlockCommandComment *Returns; SmallVector<const ParamCommandComment *, 8> Params; @@ -420,7 +421,7 @@ struct FullCommentParts { FullCommentParts::FullCommentParts(const FullComment *C, const CommandTraits &Traits) : - Brief(NULL), FirstParagraph(NULL), Returns(NULL) { + Brief(NULL), Headerfile(NULL), FirstParagraph(NULL), Returns(NULL) { for (Comment::child_iterator I = C->child_begin(), E = C->child_end(); I != E; ++I) { const Comment *Child = *I; @@ -448,6 +449,10 @@ FullCommentParts::FullCommentParts(const FullComment *C, Brief = BCC; break; } + if (!Headerfile && Info->IsHeaderfileCommand) { + Headerfile = BCC; + break; + } if (!Returns && Info->IsReturnsCommand) { Returns = BCC; break; @@ -750,6 +755,8 @@ void CommentASTToHTMLConverter::visitFullComment(const FullComment *C) { FullCommentParts Parts(C, Traits); bool FirstParagraphIsBrief = false; + if (Parts.Headerfile) + visit(Parts.Headerfile); if (Parts.Brief) visit(Parts.Brief); else if (Parts.FirstParagraph) { @@ -1202,6 +1209,12 @@ void CommentASTToXMLConverter::visitFullComment(const FullComment *C) { RootEndTag = "</Other>"; Result << "<Other><Name>unknown</Name>"; } + + if (Parts.Headerfile) { + Result << "<Headerfile>"; + visit(Parts.Headerfile); + Result << "</Headerfile>"; + } { // Pretty-print the declaration. @@ -1225,7 +1238,7 @@ void CommentASTToXMLConverter::visitFullComment(const FullComment *C) { Result << "</Abstract>"; FirstParagraphIsBrief = true; } - + if (Parts.TParams.size() != 0) { Result << "<TemplateParameters>"; for (unsigned i = 0, e = Parts.TParams.size(); i != e; ++i) diff --git a/utils/TableGen/ClangCommentCommandInfoEmitter.cpp b/utils/TableGen/ClangCommentCommandInfoEmitter.cpp index 70821ff322..e6253942e0 100644 --- a/utils/TableGen/ClangCommentCommandInfoEmitter.cpp +++ b/utils/TableGen/ClangCommentCommandInfoEmitter.cpp @@ -41,6 +41,7 @@ void EmitClangCommentCommandInfo(RecordKeeper &Records, raw_ostream &OS) { << Tag.getValueAsBit("IsParamCommand") << ", " << Tag.getValueAsBit("IsTParamCommand") << ", " << Tag.getValueAsBit("IsDeprecatedCommand") << ", " + << Tag.getValueAsBit("IsHeaderfileCommand") << ", " << Tag.getValueAsBit("IsEmptyParagraphAllowed") << ", " << Tag.getValueAsBit("IsVerbatimBlockCommand") << ", " << Tag.getValueAsBit("IsVerbatimBlockEndCommand") << ", " |