[cfe-commits] [PATCH] Introduce diagnostics into comment parsing and semantic analysis

Dmitri Gribenko gribozavr at gmail.com
Wed Jul 11 14:40:18 PDT 2012


On Tue, Jul 10, 2012 at 1:43 PM, Douglas Gregor <dgregor at apple.com> wrote:
> Index: include/clang/Basic/DiagnosticGroups.td
> ===================================================================
> --- include/clang/Basic/DiagnosticGroups.td     (revision 159963)
> +++ include/clang/Basic/DiagnosticGroups.td     (working copy)
> @@ -58,6 +58,7 @@
>  def : DiagGroup<"discard-qual">;
>  def : DiagGroup<"div-by-zero">;
>  def Doxygen : DiagGroup<"doxygen">;
> +def DoxygenPedantic : DiagGroup<"doxygen-pedantic">;
>  def EmptyBody : DiagGroup<"empty-body">;
>  def ExtraTokens : DiagGroup<"extra-tokens">;
>
> Should "doxygen" and "doxygen-pedantic" be "documentation" and "documentation-pedantic"? Some of these warnings (e.g., parameter not found) apply equally to non-Doxygen documentation systems.

Done.

> @@ -558,6 +581,14 @@
>
>    static bool classof(const ParamCommandComment *) { return true; }
>
> +  enum PassDirection {
> +    In,
> +    Out,
> +    InOut
> +  };
> +
> +  static const char *directionToString(PassDirection D);
> +
>
> getDirectionAsString(), perhaps? Function names should generally start with verbs.

Done.

> +  const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(ThisDecl);
> +  // We already warned that this \\param is not attached to a function decl.
> +  if (!FD)
> +    return Command;
>
> Can we make this work for ObjCMethodDecls, too? This can go into a follow-up patch.

Done.

> As a stretch goal, one could imagine that \param might make sense for typedefs of function types, function pointer types, or block pointer types (although that's not nearly as important as ObjCMethodDecls).

I agree it will make sense.

> +    if (OpenLineInvalid || CloseLineInvalid || OpenLine == CloseLine)
> +      Diag(HOT->getLocation(), diag::warn_doc_html_open_close_mismatch)
> +        << HOT->getTagName() << HCT->getTagName()
> +        << HOT->getSourceRange() << HCT->getSourceRange();
> +    else {
> +      Diag(HOT->getLocation(), diag::warn_doc_html_open_close_mismatch)
> +        << HOT->getTagName() << HCT->getTagName()
> +        << HOT->getSourceRange();
> +      Diag(HCT->getLocation(), diag::note_doc_html_closing_tag)
> +        << HCT->getSourceRange();
> +    }
>
> And here I thought we weren't parsing HTML ;)  (I do agree that it makes sense to diagnose these, since we're here anyway. The client can handle recovery and rendering).

We're not really parsing, just checking.  Per Jordan's comment I moved
this warning under a separate flag -Wdocumentation-html which is part
of -Wdocumentation, so that the user can disable this warning
selectively if they want.

> +  // Don't parse the comment if Doxygen diagnostics are ignored.
> +  if (NumDecls != 0 && Group[0] &&
> +      Diags.getDiagnosticLevel(diag::warn_doc_param_not_found,
> +                               Group[0]->getLocation())
> +        != DiagnosticsEngine::Ignored) {
> +    // See if there are any new comments that are not attached to a decl.
> +    ArrayRef<RawComment *> Comments = Context.getRawCommentList().getComments();
> +    if (!Comments.empty() &&
> +        !Comments.back()->isAttached()) {
> +      // There is at least one comment that not attached to a decl.
> +      // Maybe it should be attached to one of these decls?
> +      //
> +      // Note that this way we pick up not only comments that precede the
> +      // declaration, but also comments that *follow* the declaration -- thanks to
> +      // the lookahead in the lexer: we've consumed the semicolon and looked
> +      // ahead through comments.
> +      for (unsigned i = 0; i != NumDecls; ++i)
> +        Context.getCommentForDecl(Group[i]);
> +    }
> +  }
> +
>
> Very nice!

Per our discussion, I added some special-casing for typedefs.  I don't
know if any other special cases are required.  Also I found that we
need to handle TagDecls, namespaces and ObjC @interfaces separately --
because these are not part of any decl group.  Please look at ObjC
tests in test/Sema/warn-documentation.m -- anything worth adding to
it?

> As a performance optimization, should we keep track of the last attached comment, so that we can limit the search that getCommentForDecl does to the range [last attached + 1, end()]? It seems unfortunate that the lower_bound in getRawCommentForDeclNoCache() always starts at the beginning of the list of raw comments, when we could easily tell it to search a restricted range.

Per our discussion, this is broken by:

/// Aaa
typedef struct S { /** Bbb */ int a; } S;

... but we can still check if the last not attached comment is the one
that would be found by lower_bound.  If not -- call lower_bound.  Will
try doing that as followup.

> Aside: should getCommentForDecl() learn that the documentation for ParmVarDecls is actually attached to the part FunctionDecl (or ObjCMethodDecl), and get the documentation from there?

For generality of getCommentForDecl(), I think it should do that.  But
I think that most clients will want to poke the FullComment
themselves.  Should I implement this?

Committed r160078.

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