Hi Fariborz, On Fri, Mar 8, 2013 at 1:33 AM, Fariborz Jahanian <[email protected]> wrote: > Author: fjahanian > Date: Thu Mar 7 17:33:11 2013 > New Revision: 176667 > > URL: http://llvm.org/viewvc/llvm-project?rev=176667&view=rev > Log: > HeaderDoc: Support more of HeaderDoc documentation > commands; top level tags such as @interface and > their 2nd level tags such as @coclass, etc. > // rdar://12379114 > > Modified: > cfe/trunk/include/clang/AST/CommentCommandTraits.h > cfe/trunk/include/clang/AST/CommentCommands.td > cfe/trunk/include/clang/AST/CommentSema.h > cfe/trunk/include/clang/Basic/DiagnosticCommentKinds.td > cfe/trunk/lib/AST/CommentSema.cpp > cfe/trunk/test/Sema/warn-documentation.cpp > cfe/trunk/test/Sema/warn-documentation.m > cfe/trunk/utils/TableGen/ClangCommentCommandInfoEmitter.cpp > > Modified: cfe/trunk/include/clang/AST/CommentCommandTraits.h > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/CommentCommandTraits.h?rev=176667&r1=176666&r2=176667&view=diff > ============================================================================== > --- cfe/trunk/include/clang/AST/CommentCommandTraits.h (original) > +++ cfe/trunk/include/clang/AST/CommentCommandTraits.h Thu Mar 7 17:33:11 > 2013 > @@ -101,8 +101,15 @@ struct CommandInfo { > /// \endcode > unsigned IsDeclarationCommand : 1; > > - /// \brief True if verbatim-like line command is a function declaraton. > + /// \brief True if verbatim-like line command is a function declaration. > unsigned IsFunctionDeclarationCommand : 1; > + > + /// \brief True if block command is further describing a container API; > such > + /// as @coclass, @classdesign, etc. > + unsigned IsContainerDetailCommand : 1; > + > + /// \brief True if block command is a container API; such as @interface. > + unsigned IsContainerDeclarationCommand : 1;
Is the 'container' the best term for this? I don't know ObjC, but a container is something like std::vector for me. > > /// \brief True if this command is unknown. This \c CommandInfo object was > /// created during parsing. > > Modified: cfe/trunk/include/clang/AST/CommentCommands.td > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/CommentCommands.td?rev=176667&r1=176666&r2=176667&view=diff > ============================================================================== > --- cfe/trunk/include/clang/AST/CommentCommands.td (original) > +++ cfe/trunk/include/clang/AST/CommentCommands.td Thu Mar 7 17:33:11 2013 > @@ -25,6 +25,8 @@ class Command<string name> { > bit IsVerbatimLineCommand = 0; > bit IsDeclarationCommand = 0; > bit IsFunctionDeclarationCommand = 0; > + bit IsContainerDetailCommand = 0; > + bit IsContainerDeclarationCommand = 0; > } > > class InlineCommand<string name> : Command<name> { > @@ -66,6 +68,12 @@ class FunctionDeclarationVerbatimLineCom > let IsFunctionDeclarationCommand = 1; > } > > +class ContainerDeclarationVerbatimLineCommand<string name> : > + VerbatimLineCommand<name> { > + let IsDeclarationCommand = 1; > + let IsContainerDeclarationCommand = 1; > +} > + > > //===----------------------------------------------------------------------===// > // InlineCommand > > //===----------------------------------------------------------------------===// > @@ -181,9 +189,11 @@ def Typedef : DeclarationVerbatimLineC > def Var : DeclarationVerbatimLineCommand<"var">; > > // HeaderDoc commands. > -def Class : DeclarationVerbatimLineCommand<"class">; > -def Interface : DeclarationVerbatimLineCommand<"interface">; > -def Protocol : DeclarationVerbatimLineCommand<"protocol">; > +def Class : ContainerDeclarationVerbatimLineCommand<"class">; > +def Interface : ContainerDeclarationVerbatimLineCommand<"interface">; > +def Protocol : ContainerDeclarationVerbatimLineCommand<"protocol">; > +def Struct : ContainerDeclarationVerbatimLineCommand<"struct">; > +def Union : ContainerDeclarationVerbatimLineCommand<"union">; > def Category : DeclarationVerbatimLineCommand<"category">; > def Template : DeclarationVerbatimLineCommand<"template">; > def Function : FunctionDeclarationVerbatimLineCommand<"function">; > @@ -191,7 +201,38 @@ def Method : FunctionDeclarationVerba > def Callback : FunctionDeclarationVerbatimLineCommand<"callback">; > def Const : DeclarationVerbatimLineCommand<"const">; > def Constant : DeclarationVerbatimLineCommand<"constant">; > -def Struct : DeclarationVerbatimLineCommand<"struct">; > -def Union : DeclarationVerbatimLineCommand<"union">; > def Enum : DeclarationVerbatimLineCommand<"enum">; > > +def ClassDesign : BlockCommand<"classdesign"> { > + let IsContainerDetailCommand = 1; > +} > +def CoClass : BlockCommand<"coclass"> { > + let IsContainerDetailCommand = 1; > +} > +def Dependency : BlockCommand<"dependency"> { > + let IsContainerDetailCommand = 1; > +} > +def Helper : BlockCommand<"helper"> { > + let IsContainerDetailCommand = 1; > +} > +def HelperClass : BlockCommand<"helperclass"> { > + let IsContainerDetailCommand = 1; > +} > +def Helps : BlockCommand<"helps"> { > + let IsContainerDetailCommand = 1; > +} > +def InstanceSize : BlockCommand<"instancesize"> { > + let IsContainerDetailCommand = 1; > +} > +def Ownership : BlockCommand<"ownership"> { > + let IsContainerDetailCommand = 1; > +} > +def Performance : BlockCommand<"performance"> { > + let IsContainerDetailCommand = 1; > +} > +def Security : BlockCommand<"security"> { > + let IsContainerDetailCommand = 1; > +} > +def SuperClass : BlockCommand<"superclass"> { > + let IsContainerDetailCommand = 1; > +} Please clean this up by defining a class in .td that is derived from BlockCommand. > > Modified: cfe/trunk/include/clang/AST/CommentSema.h > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/CommentSema.h?rev=176667&r1=176666&r2=176667&view=diff > ============================================================================== > --- cfe/trunk/include/clang/AST/CommentSema.h (original) > +++ cfe/trunk/include/clang/AST/CommentSema.h Thu Mar 7 17:33:11 2013 > @@ -200,6 +200,10 @@ public: > void checkDeprecatedCommand(const BlockCommandComment *Comment); > > void checkFunctionDeclVerbatimLine(const BlockCommandComment *Comment); > + > + void checkContainerDeclVerbatimLine(const BlockCommandComment *Comment); > + > + void checkContainerDecl(const BlockCommandComment *Comment); > > /// Resolve parameter names to parameter indexes in function declaration. > /// Emit diagnostics about unknown parametrs. > @@ -211,6 +215,11 @@ public: > bool isObjCMethodDecl(); > bool isObjCPropertyDecl(); > bool isTemplateOrSpecialization(); > + bool isContainerDecl(); > + bool isClassStructDecl(); > + bool isUnionDecl(); > + bool isObjCInterfaceDecl(); > + bool isObjCProtocolDecl(); > > ArrayRef<const ParmVarDecl *> getParamVars(); > > > Modified: cfe/trunk/include/clang/Basic/DiagnosticCommentKinds.td > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticCommentKinds.td?rev=176667&r1=176666&r2=176667&view=diff > ============================================================================== > --- cfe/trunk/include/clang/Basic/DiagnosticCommentKinds.td (original) > +++ cfe/trunk/include/clang/Basic/DiagnosticCommentKinds.td Thu Mar 7 > 17:33:11 2013 > @@ -79,6 +79,18 @@ def warn_doc_function_method_decl_mismat > "%select{a function|an Objective-C method|a pointer to function}2 > declaration">, > InGroup<Documentation>, DefaultIgnore; > > +def warn_doc_api_container_decl_mismatch : Warning< > + "'%select{\\|@}0%select{class|interface|protocol|struct|union}1' " > + "command should not be used in a comment attached to a " > + "non-%select{class|interface|protocol|struct|union}2 declaration">, > + InGroup<Documentation>, DefaultIgnore; > + > +def warn_doc_container_decl_mismatch : Warning< > + "'%select{\\|@}0%select{classdesign|coclass|dependency|helper" > + > "|helperclass|helps|instancesize|ownership|performance|security|superclass}1' > " > + "command should not be used in a comment attached to a non-container > declaration">, > + InGroup<Documentation>, DefaultIgnore; > + > def warn_doc_param_duplicate : Warning< > "parameter '%0' is already documented">, > InGroup<Documentation>, DefaultIgnore; > > Modified: cfe/trunk/lib/AST/CommentSema.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/CommentSema.cpp?rev=176667&r1=176666&r2=176667&view=diff > ============================================================================== > --- cfe/trunk/lib/AST/CommentSema.cpp (original) > +++ cfe/trunk/lib/AST/CommentSema.cpp Thu Mar 7 17:33:11 2013 > @@ -52,8 +52,11 @@ BlockCommandComment *Sema::actOnBlockCom > SourceLocation LocEnd, > unsigned CommandID, > CommandMarkerKind CommandMarker) { > - return new (Allocator) BlockCommandComment(LocBegin, LocEnd, CommandID, > - CommandMarker); > + BlockCommandComment *BC = new (Allocator) BlockCommandComment(LocBegin, > LocEnd, > + CommandID, > + > CommandMarker); > + checkContainerDecl(BC); > + return BC; > } > > void Sema::actOnBlockCommandArgs(BlockCommandComment *Command, > @@ -105,6 +108,52 @@ void Sema::checkFunctionDeclVerbatimLine > << (DiagSelect-1) << (DiagSelect-1) > << Comment->getSourceRange(); > } > + > +void Sema::checkContainerDeclVerbatimLine(const BlockCommandComment > *Comment) { > + const CommandInfo *Info = Traits.getCommandInfo(Comment->getCommandID()); > + if (!Info->IsContainerDeclarationCommand) > + return; > + StringRef Name = Info->Name; > + unsigned DiagSelect = llvm::StringSwitch<unsigned>(Name) > + .Case("class", !isClassStructDecl() ? 1 : 0) > + .Case("interface", !isObjCInterfaceDecl() ? 2 : 0) > + .Case("protocol", !isObjCProtocolDecl() ? 3 : 0) > + .Case("struct", !isClassStructDecl() ? 4 : 0) > + .Case("union", !isUnionDecl() ? 5 : 0) > + .Default(0); Please don't StringSwitch on the command name. Statically known commands have IDs. See CommentASTToXMLConverter::visitBlockCommandComment for an example of how to use these. > + > + if (DiagSelect) > + Diag(Comment->getLocation(), diag::warn_doc_api_container_decl_mismatch) > + << Comment->getCommandMarker() > + << (DiagSelect-1) << (DiagSelect-1) > + << Comment->getSourceRange(); > +} > + > +void Sema::checkContainerDecl(const BlockCommandComment *Comment) { > + const CommandInfo *Info = Traits.getCommandInfo(Comment->getCommandID()); > + if (!Info->IsContainerDetailCommand || isContainerDecl()) > + return; > + StringRef Name = Info->Name; > + unsigned DiagSelect = llvm::StringSwitch<unsigned>(Name) > + .Case("classdesign", 1) > + .Case("coclass", 2) > + .Case("dependency", 3) > + .Case("helper", 4) > + .Case("helperclass", 5) > + .Case("helps", 6) > + .Case("instancesize", 7) > + .Case("ownership", 8) > + .Case("performance", 9) > + .Case("security", 10) > + .Case("superclass", 11) > + .Default(0); Same here. > + > + if (DiagSelect) > + Diag(Comment->getLocation(), diag::warn_doc_container_decl_mismatch) > + << Comment->getCommandMarker() > + << (DiagSelect-1) > + << Comment->getSourceRange(); > +} > > void Sema::actOnParamCommandDirectionArg(ParamCommandComment *Command, > SourceLocation ArgLocBegin, > @@ -362,6 +411,7 @@ VerbatimLineComment *Sema::actOnVerbatim > TextBegin, > Text); > checkFunctionDeclVerbatimLine(VL); > + checkContainerDeclVerbatimLine(VL); > return VL; > } > > @@ -735,6 +785,54 @@ bool Sema::isTemplateOrSpecialization() > return ThisDeclInfo->getTemplateKind() != DeclInfo::NotTemplate; > } > > +bool Sema::isContainerDecl() { > + if (!ThisDeclInfo) > + return false; > + if (!ThisDeclInfo->IsFilled) > + inspectThisDecl(); > + return isUnionDecl() || isClassStructDecl() > + || isObjCInterfaceDecl() || isObjCProtocolDecl(); > +} > + > +bool Sema::isUnionDecl() { > + if (!ThisDeclInfo) > + return false; > + if (!ThisDeclInfo->IsFilled) > + inspectThisDecl(); > + if (const RecordDecl *RD = > + dyn_cast_or_null<RecordDecl>(ThisDeclInfo->CurrentDecl)) > + return RD->isUnion(); > + return false; > +} > + > +bool Sema::isClassStructDecl() { isClassOrStructDecl() would be a better name. > + if (!ThisDeclInfo) > + return false; > + if (!ThisDeclInfo->IsFilled) > + inspectThisDecl(); > + return ThisDeclInfo->CurrentDecl && > + isa<RecordDecl>(ThisDeclInfo->CurrentDecl) && > + !isUnionDecl(); > +} > + > +bool Sema::isObjCInterfaceDecl() { > + if (!ThisDeclInfo) > + return false; > + if (!ThisDeclInfo->IsFilled) > + inspectThisDecl(); > + return ThisDeclInfo->CurrentDecl && > + isa<ObjCInterfaceDecl>(ThisDeclInfo->CurrentDecl); > +} > + > +bool Sema::isObjCProtocolDecl() { > + if (!ThisDeclInfo) > + return false; > + if (!ThisDeclInfo->IsFilled) > + inspectThisDecl(); > + return ThisDeclInfo->CurrentDecl && > + isa<ObjCProtocolDecl>(ThisDeclInfo->CurrentDecl); > +} > + > ArrayRef<const ParmVarDecl *> Sema::getParamVars() { > if (!ThisDeclInfo->IsFilled) > inspectThisDecl(); > > Modified: cfe/trunk/test/Sema/warn-documentation.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/warn-documentation.cpp?rev=176667&r1=176666&r2=176667&view=diff > ============================================================================== > --- cfe/trunk/test/Sema/warn-documentation.cpp (original) > +++ cfe/trunk/test/Sema/warn-documentation.cpp Thu Mar 7 17:33:11 2013 > @@ -922,3 +922,31 @@ int test_nocrash12(); > // expected-warning@+1 {{empty paragraph passed to '@param' command}} > ///@param x@param y > int test_nocrash13(int x, int y); > + > +// rdar://12379114 > +// expected-warning@+2 {{'@union' command should not be used in a comment > attached to a non-union declaration}} > +/*! > + @union U This is new > +*/ > +struct U { int iS; }; > + > +/*! > + @union U1 > +*/ > +union U1 {int i; }; > + > +// expected-warning@+2 {{'@struct' command should not be used in a comment > attached to a non-struct declaration}} > +/*! > + @struct S2 > +*/ > +union S2 {}; > + > +/*! > + @class C1 > +*/ > +class C1; > + > +/*! > + @struct S3; > +*/ > +class S3; > > Modified: cfe/trunk/test/Sema/warn-documentation.m > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/warn-documentation.m?rev=176667&r1=176666&r2=176667&view=diff > ============================================================================== > --- cfe/trunk/test/Sema/warn-documentation.m (original) > +++ cfe/trunk/test/Sema/warn-documentation.m Thu Mar 7 17:33:11 2013 > @@ -105,3 +105,55 @@ typedef int (^test_param1)(int aaa, int > typedef id ID; > - (unsigned) Base64EncodeEx : (ID)Arg; > @end > + > +// rdar://12379114 > +// expected-warning@+5 {{'@interface' command should not be used in a > comment attached to a non-interface declaration}} > +// expected-warning@+5 {{'@classdesign' command should not be used in a > comment attached to a non-container declaration}} > +// expected-warning@+5 {{'@coclass' command should not be used in a comment > attached to a non-container declaration}} > +@interface NSObject @end > +/*! > +@interface IOCommandGate > +@classdesign Multiple paragraphs go here. > +@coclass myCoClass > +*/ > + > +typedef id OBJ; > +@interface IOCommandGate : NSObject { > + OBJ iv; > +} > +@end > + > +// expected-warning@+2 {{'@protocol' command should not be used in a comment > attached to a non-protocol declaration}} > +/*! > +@protocol PROTO > +*/ > +struct S; > + > +/*! > + @interface NSArray This is an array > +*/ > +@class NSArray; > +@interface NSArray @end > + > +/*! > +@interface NSMutableArray > +@super NSArray > +*/ > +@interface NSMutableArray : NSArray @end > + > +/*! > + @protocol MyProto > +*/ > +@protocol MyProto @end > + > +// expected-warning@+2 {{'@protocol' command should not be used in a comment > attached to a non-protocol declaration}} > +/*! > + @protocol MyProto > +*/ > +@interface INTF <MyProto> @end > + > +// expected-warning@+2 {{'@struct' command should not be used in a comment > attached to a non-struct declaration}} > +/*! > + @struct S1 THIS IS IT > +*/ > +@interface S1 @end > > Modified: cfe/trunk/utils/TableGen/ClangCommentCommandInfoEmitter.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/utils/TableGen/ClangCommentCommandInfoEmitter.cpp?rev=176667&r1=176666&r2=176667&view=diff > ============================================================================== > --- cfe/trunk/utils/TableGen/ClangCommentCommandInfoEmitter.cpp (original) > +++ cfe/trunk/utils/TableGen/ClangCommentCommandInfoEmitter.cpp Thu Mar 7 > 17:33:11 2013 > @@ -48,6 +48,8 @@ void EmitClangCommentCommandInfo(RecordK > << Tag.getValueAsBit("IsVerbatimLineCommand") << ", " > << Tag.getValueAsBit("IsDeclarationCommand") << ", " > << Tag.getValueAsBit("IsFunctionDeclarationCommand") << ", " > + << Tag.getValueAsBit("IsContainerDetailCommand") << ", " > + << Tag.getValueAsBit("IsContainerDeclarationCommand") << ", " > << /* IsUnknownCommand = */ "0" > << " }"; > if (i + 1 != e) Dmitri -- main(i,j){for(i=2;;i++){for(j=2;j<i;j++){if(!(i%j)){j=0;break;}}if (j){printf("%d\n",i);}}} /*Dmitri Gribenko <[email protected]>*/ _______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
