Make concepts of optional and forbidden end tags separate. Thanks Jordan for pointing this!
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@160149 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/AST/CommentSema.h b/include/clang/AST/CommentSema.h
index 7b45320..aae8e5c 100644
--- a/include/clang/AST/CommentSema.h
+++ b/include/clang/AST/CommentSema.h
@@ -156,7 +156,9 @@
unsigned getBlockCommandNumArgs(StringRef Name);
bool isInlineCommand(StringRef Name);
- bool HTMLOpenTagNeedsClosing(StringRef Name);
+
+ bool isHTMLCloseTagOptional(StringRef Name);
+ bool isHTMLCloseTagForbidden(StringRef Name);
};
} // end namespace comments
diff --git a/include/clang/Basic/DiagnosticCommentKinds.td b/include/clang/Basic/DiagnosticCommentKinds.td
index 7500d40..a4b974a 100644
--- a/include/clang/Basic/DiagnosticCommentKinds.td
+++ b/include/clang/Basic/DiagnosticCommentKinds.td
@@ -26,6 +26,10 @@
// HTML semantic errors
+def warn_doc_html_close_forbidden : Warning<
+ "HTML closing tag '%0' is forbidden">,
+ InGroup<DocumentationHTML>, DefaultIgnore;
+
def warn_doc_html_close_unbalanced : Warning<
"HTML closing tag does not match any opening tag">,
InGroup<DocumentationHTML>, DefaultIgnore;
diff --git a/lib/AST/CommentSema.cpp b/lib/AST/CommentSema.cpp
index ae13fa2..69cc016 100644
--- a/lib/AST/CommentSema.cpp
+++ b/lib/AST/CommentSema.cpp
@@ -289,7 +289,7 @@
Tag->setGreaterLoc(GreaterLoc);
if (IsSelfClosing)
Tag->setSelfClosing();
- else
+ else if (!isHTMLCloseTagForbidden(Tag->getTagName()))
HTMLOpenTags.push_back(Tag);
return Tag;
}
@@ -299,6 +299,12 @@
StringRef TagName) {
HTMLCloseTagComment *HCT =
new (Allocator) HTMLCloseTagComment(LocBegin, LocEnd, TagName);
+ if (isHTMLCloseTagForbidden(TagName)) {
+ Diag(HCT->getLocation(), diag::warn_doc_html_close_forbidden)
+ << TagName << HCT->getSourceRange();
+ return HCT;
+ }
+
bool FoundOpen = false;
for (SmallVectorImpl<HTMLOpenTagComment *>::const_reverse_iterator
I = HTMLOpenTags.rbegin(), E = HTMLOpenTags.rend();
@@ -321,7 +327,7 @@
if (LastNotClosedTagName == TagName)
break;
- if (!HTMLOpenTagNeedsClosing(LastNotClosedTagName))
+ if (isHTMLCloseTagOptional(LastNotClosedTagName))
continue;
bool OpenLineInvalid;
@@ -448,12 +454,29 @@
.Default(false);
}
-bool Sema::HTMLOpenTagNeedsClosing(StringRef Name) {
+bool Sema::isHTMLCloseTagOptional(StringRef Name) {
return llvm::StringSwitch<bool>(Name)
- .Case("br", false)
- .Case("hr", false)
- .Case("li", false)
- .Default(true);
+ .Case("p", true)
+ .Case("li", true)
+ .Case("dt", true)
+ .Case("dd", true)
+ .Case("tr", true)
+ .Case("th", true)
+ .Case("td", true)
+ .Case("thead", true)
+ .Case("tfoot", true)
+ .Case("tbody", true)
+ .Case("colgroup", true)
+ .Default(false);
+}
+
+bool Sema::isHTMLCloseTagForbidden(StringRef Name) {
+ return llvm::StringSwitch<bool>(Name)
+ .Case("br", true)
+ .Case("hr", true)
+ .Case("img", true)
+ .Case("col", true)
+ .Default(false);
}
} // end namespace comments
diff --git a/test/Sema/warn-documentation.cpp b/test/Sema/warn-documentation.cpp
index 3949b2e..b1c871a 100644
--- a/test/Sema/warn-documentation.cpp
+++ b/test/Sema/warn-documentation.cpp
@@ -45,6 +45,9 @@
*/
int test_html10(int);
+// expected-warning@+1 {{HTML closing tag 'br' is forbidden}}
+/// <br></br>
+int test_html11(int);
/// <blockquote>Meow</blockquote>
int test_html_nesting1(int);