r176667 - HeaderDoc: Support more of HeaderDoc documentation

jahanian fjahanian at apple.com
Fri Mar 8 16:01:56 PST 2013


In r176739. Thanks for the review.

- Fariborz

On Mar 7, 2013, at 3:51 PM, Dmitri Gribenko <gribozavr at gmail.com> wrote:

> Hi Fariborz,
> 
> On Fri, Mar 8, 2013 at 1:33 AM, Fariborz Jahanian <fjahanian at apple.com> 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 at +1 {{empty paragraph passed to '@param' command}}
>> ///@param x at param y
>> int test_nocrash13(int x, int y);
>> +
>> +// rdar://12379114
>> +// expected-warning at +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 at +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 at +5 {{'@interface' command should not be used in a comment attached to a non-interface declaration}}
>> +// expected-warning at +5 {{'@classdesign' command should not be used in a comment attached to a non-container declaration}}
>> +// expected-warning at +5 {{'@coclass' command should not be used in a comment attached to a non-container declaration}}
>> + at interface NSObject @end
>> +/*!
>> + at interface IOCommandGate
>> + at classdesign Multiple paragraphs go here.
>> + at coclass myCoClass
>> +*/
>> +
>> +typedef id OBJ;
>> + at interface IOCommandGate : NSObject {
>> +  OBJ iv;
>> +}
>> + at end
>> +
>> +// expected-warning at +2 {{'@protocol' command should not be used in a comment attached to a non-protocol declaration}}
>> +/*!
>> + at protocol PROTO
>> +*/
>> +struct S;
>> +
>> +/*!
>> +  @interface NSArray This is an array
>> +*/
>> + at class NSArray;
>> + at interface NSArray @end
>> +
>> +/*!
>> + at interface NSMutableArray
>> + at super NSArray
>> +*/
>> + at interface NSMutableArray : NSArray @end
>> +
>> +/*!
>> +  @protocol MyProto
>> +*/
>> + at protocol MyProto @end
>> +
>> +// expected-warning at +2 {{'@protocol' command should not be used in a comment attached to a non-protocol declaration}}
>> +/*!
>> + @protocol MyProto
>> +*/
>> + at interface INTF <MyProto> @end
>> +
>> +// expected-warning at +2 {{'@struct' command should not be used in a comment attached to a non-struct declaration}}
>> +/*!
>> +  @struct S1 THIS IS IT
>> +*/
>> + at 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 <gribozavr at gmail.com>*/




More information about the cfe-commits mailing list