Comment parsing: refactor handling of command markers in AST

* Use the term 'command marker', because the semantics of 'backslash' and 'at'
  commands are the same.  (Talking about 'at commands' makes them look like a
  special entity.)

* Sink the flag down into bitfields, reducing the size of AST nodes.

* Change the flag into an enum for clarity.  Boolean function parameters are
  not very clear.

* Add unittests for new tok::at_command tokens.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@176461 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/unittests/AST/CommentLexer.cpp b/unittests/AST/CommentLexer.cpp
index 46de945..507daf8 100644
--- a/unittests/AST/CommentLexer.cpp
+++ b/unittests/AST/CommentLexer.cpp
@@ -301,8 +301,10 @@
 
 // Doxygen escape sequences.
 TEST_F(CommentLexerTest, DoxygenCommand4) {
-  const char *Source =
-    "/// \\\\ \\@ \\& \\$ \\# \\< \\> \\% \\\" \\. \\::";
+  const char *Sources[] = {
+    "/// \\\\ \\@ \\& \\$ \\# \\< \\> \\% \\\" \\. \\::",
+    "/// @\\ @@ @& @$ @# @< @> @% @\" @. @::"
+  };
   const char *Text[] = {
     " ",
     "\\", " ", "@", " ", "&", " ", "$",  " ", "#", " ",
@@ -310,16 +312,18 @@
     "::", ""
   };
 
-  std::vector<Token> Toks;
+  for (size_t i = 0, e = array_lengthof(Sources); i != e; i++) {
+    std::vector<Token> Toks;
 
-  lexString(Source, Toks);
+    lexString(Sources[i], Toks);
 
-  ASSERT_EQ(array_lengthof(Text), Toks.size());
+    ASSERT_EQ(array_lengthof(Text), Toks.size());
 
-  for (size_t i = 0, e = Toks.size(); i != e; i++) {
-    if(Toks[i].is(tok::text))
-      ASSERT_EQ(StringRef(Text[i]), Toks[i].getText())
-        << "index " << i;
+    for (size_t j = 0, e = Toks.size(); j != e; j++) {
+      if(Toks[j].is(tok::text))
+        ASSERT_EQ(StringRef(Text[j]), Toks[j].getText())
+          << "index " << i;
+    }
   }
 }
 
@@ -404,6 +408,38 @@
 }
 
 TEST_F(CommentLexerTest, DoxygenCommand8) {
+  const char *Source = "/// @em@em @em\t@em\n";
+  std::vector<Token> Toks;
+
+  lexString(Source, Toks);
+
+  ASSERT_EQ(8U, Toks.size());
+
+  ASSERT_EQ(tok::text,       Toks[0].getKind());
+  ASSERT_EQ(StringRef(" "),  Toks[0].getText());
+
+  ASSERT_EQ(tok::at_command, Toks[1].getKind());
+  ASSERT_EQ(StringRef("em"), getCommandName(Toks[1]));
+
+  ASSERT_EQ(tok::at_command, Toks[2].getKind());
+  ASSERT_EQ(StringRef("em"), getCommandName(Toks[2]));
+
+  ASSERT_EQ(tok::text,       Toks[3].getKind());
+  ASSERT_EQ(StringRef(" "),  Toks[3].getText());
+
+  ASSERT_EQ(tok::at_command, Toks[4].getKind());
+  ASSERT_EQ(StringRef("em"), getCommandName(Toks[4]));
+
+  ASSERT_EQ(tok::text,       Toks[5].getKind());
+  ASSERT_EQ(StringRef("\t"), Toks[5].getText());
+
+  ASSERT_EQ(tok::at_command, Toks[6].getKind());
+  ASSERT_EQ(StringRef("em"), getCommandName(Toks[6]));
+
+  ASSERT_EQ(tok::newline,    Toks[7].getKind());
+}
+
+TEST_F(CommentLexerTest, DoxygenCommand9) {
   const char *Source = "/// \\aaa\\bbb \\ccc\t\\ddd\n";
   std::vector<Token> Toks;
 
@@ -435,7 +471,7 @@
   ASSERT_EQ(tok::newline,     Toks[7].getKind());
 }
 
-TEST_F(CommentLexerTest, DoxygenCommand9) {
+TEST_F(CommentLexerTest, DoxygenCommand10) {
   const char *Source = "// \\c\n";
   std::vector<Token> Toks;
 
@@ -453,7 +489,9 @@
 }
 
 TEST_F(CommentLexerTest, RegisterCustomBlockCommand) {
-  const char *Source = "/// \\NewBlockCommand Aaa.\n";
+  const char *Source =
+    "/// \\NewBlockCommand Aaa.\n"
+    "/// @NewBlockCommand Aaa.\n";
 
   Traits.registerBlockCommand(StringRef("NewBlockCommand"));
 
@@ -461,10 +499,10 @@
 
   lexString(Source, Toks);
 
-  ASSERT_EQ(4U, Toks.size());
+  ASSERT_EQ(8U, Toks.size());
 
-  ASSERT_EQ(tok::text,      Toks[0].getKind());
-  ASSERT_EQ(StringRef(" "), Toks[0].getText());
+  ASSERT_EQ(tok::text,          Toks[0].getKind());
+  ASSERT_EQ(StringRef(" "),     Toks[0].getText());
 
   ASSERT_EQ(tok::backslash_command, Toks[1].getKind());
   ASSERT_EQ(StringRef("NewBlockCommand"), getCommandName(Toks[1]));
@@ -472,7 +510,18 @@
   ASSERT_EQ(tok::text,          Toks[2].getKind());
   ASSERT_EQ(StringRef(" Aaa."), Toks[2].getText());
 
-  ASSERT_EQ(tok::newline,        Toks[3].getKind());
+  ASSERT_EQ(tok::newline,       Toks[3].getKind());
+
+  ASSERT_EQ(tok::text,          Toks[4].getKind());
+  ASSERT_EQ(StringRef(" "),     Toks[4].getText());
+
+  ASSERT_EQ(tok::at_command,    Toks[5].getKind());
+  ASSERT_EQ(StringRef("NewBlockCommand"), getCommandName(Toks[5]));
+
+  ASSERT_EQ(tok::text,          Toks[6].getKind());
+  ASSERT_EQ(StringRef(" Aaa."), Toks[6].getText());
+
+  ASSERT_EQ(tok::newline,       Toks[7].getKind());
 }
 
 TEST_F(CommentLexerTest, RegisterMultipleBlockCommands) {