Enable comment parsing and semantic analysis to emit diagnostics.  A few
diagnostics implemented -- see testcases.

I created a new TableGen file for comment diagnostics,
DiagnosticCommentKinds.td, because comment diagnostics don't logically
fit into AST diagnostics file.  But I don't feel strongly about it.

This also implements support for self-closing HTML tags in comment
lexer and parser (for example, <br />).

In order to issue precise diagnostics CommentSema needs to know the
declaration the comment is attached to.  There is no easy way to find a decl by 
comment, so we match comments and decls in lockstep: after parsing one
declgroup we check if we have any new, not yet attached comments.  If we do --
then we do the usual comment-finding process.

It is interesting that this automatically handles trailing comments.
We pick up not only comments that precede the declaration, but also
comments that *follow* the declaration -- thanks to the lookahead in
the lexer: after parsing the declgroup we've consumed the semicolon
and looked ahead through comments.

Added -Wdocumentation-html flag for semantic HTML errors to allow the user to 
disable only HTML warnings (but not HTML parse errors, which we emit as
warnings in -Wdocumentation).



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@160078 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/unittests/AST/CommentLexer.cpp b/unittests/AST/CommentLexer.cpp
index e1089cc..4718639 100644
--- a/unittests/AST/CommentLexer.cpp
+++ b/unittests/AST/CommentLexer.cpp
@@ -1142,6 +1142,60 @@
 }
 
 TEST_F(CommentLexerTest, HTML15) {
+  const char *Sources[] = {
+    "// <tag/>",
+    "// <tag />"
+  };
+
+  for (size_t i = 0, e = array_lengthof(Sources); i != e; i++) {
+    std::vector<Token> Toks;
+
+    lexString(Sources[i], Toks);
+
+    ASSERT_EQ(4U, Toks.size());
+
+    ASSERT_EQ(tok::text,               Toks[0].getKind());
+    ASSERT_EQ(StringRef(" "),          Toks[0].getText());
+
+    ASSERT_EQ(tok::html_tag_open,      Toks[1].getKind());
+    ASSERT_EQ(StringRef("tag"),        Toks[1].getHTMLTagOpenName());
+
+    ASSERT_EQ(tok::html_slash_greater, Toks[2].getKind());
+
+    ASSERT_EQ(tok::newline,            Toks[3].getKind());
+  }
+}
+
+TEST_F(CommentLexerTest, HTML16) {
+  const char *Sources[] = {
+    "// <tag/ Aaa",
+    "// <tag / Aaa"
+  };
+
+  for (size_t i = 0, e = array_lengthof(Sources); i != e; i++) {
+    std::vector<Token> Toks;
+
+    lexString(Sources[i], Toks);
+
+    ASSERT_EQ(5U, Toks.size());
+
+    ASSERT_EQ(tok::text,               Toks[0].getKind());
+    ASSERT_EQ(StringRef(" "),          Toks[0].getText());
+
+    ASSERT_EQ(tok::html_tag_open,      Toks[1].getKind());
+    ASSERT_EQ(StringRef("tag"),        Toks[1].getHTMLTagOpenName());
+
+    ASSERT_EQ(tok::text,               Toks[2].getKind());
+    ASSERT_EQ(StringRef("/"),          Toks[2].getText());
+
+    ASSERT_EQ(tok::text,               Toks[3].getKind());
+    ASSERT_EQ(StringRef(" Aaa"),       Toks[3].getText());
+
+    ASSERT_EQ(tok::newline,            Toks[4].getKind());
+  }
+}
+
+TEST_F(CommentLexerTest, HTML17) {
   const char *Source = "// </";
 
   std::vector<Token> Toks;
@@ -1159,8 +1213,7 @@
   ASSERT_EQ(tok::newline,        Toks[2].getKind());
 }
 
-
-TEST_F(CommentLexerTest, HTML16) {
+TEST_F(CommentLexerTest, HTML18) {
   const char *Source = "// </@";
 
   std::vector<Token> Toks;
@@ -1181,7 +1234,7 @@
   ASSERT_EQ(tok::newline,        Toks[3].getKind());
 }
 
-TEST_F(CommentLexerTest, HTML17) {
+TEST_F(CommentLexerTest, HTML19) {
   const char *Source = "// </tag";
 
   std::vector<Token> Toks;
@@ -1199,7 +1252,7 @@
   ASSERT_EQ(tok::newline,        Toks[2].getKind());
 }
 
-TEST_F(CommentLexerTest, HTML18) {
+TEST_F(CommentLexerTest, HTML20) {
   const char *Sources[] = {
     "// </tag>",
     "// </ tag>",