summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDmitri Gribenko <gribozavr@gmail.com>2012-09-22 21:47:50 +0000
committerDmitri Gribenko <gribozavr@gmail.com>2012-09-22 21:47:50 +0000
commit1da888691587e6dd338b70b97c02a740e29c99dc (patch)
tree739b4ba38689ddb34c3b562b74a1aa911c4af934
parentd0885d2941d437026e60b79425a08cbf44ee069a (diff)
downloadbcm5719-llvm-1da888691587e6dd338b70b97c02a740e29c99dc.tar.gz
bcm5719-llvm-1da888691587e6dd338b70b97c02a740e29c99dc.zip
Comment sema: warn when comment has \deprecated but declaration does not have a
deprecation attribute ('deprecated', 'availability' or 'unavailable'). This warning is under a separate flag, -Wdocumentation-deprecated-sync, so it can be turned off easily while leaving other -Wdocumentation warnings on. llvm-svn: 164467
-rw-r--r--clang/include/clang/AST/CommentCommandTraits.h3
-rw-r--r--clang/include/clang/AST/CommentCommands.td6
-rw-r--r--clang/include/clang/AST/CommentSema.h2
-rw-r--r--clang/include/clang/Basic/DiagnosticCommentKinds.td10
-rw-r--r--clang/include/clang/Basic/DiagnosticGroups.td7
-rw-r--r--clang/lib/AST/CommentSema.cpp34
-rw-r--r--clang/test/Sema/warn-documentation-fixits.cpp37
-rw-r--r--clang/test/Sema/warn-documentation.cpp29
-rw-r--r--clang/utils/TableGen/ClangCommentCommandInfoEmitter.cpp1
9 files changed, 125 insertions, 4 deletions
diff --git a/clang/include/clang/AST/CommentCommandTraits.h b/clang/include/clang/AST/CommentCommandTraits.h
index 73ded54a31b..6d44c706c3d 100644
--- a/clang/include/clang/AST/CommentCommandTraits.h
+++ b/clang/include/clang/AST/CommentCommandTraits.h
@@ -66,6 +66,9 @@ struct CommandInfo {
/// a template parameter (\\tparam or an alias).
unsigned IsTParamCommand : 1;
+ /// True if this command is \\deprecated or an alias.
+ unsigned IsDeprecatedCommand : 1;
+
/// True if we don't want to warn about this command being passed an empty
/// paragraph. Meaningful only for block commands.
unsigned IsEmptyParagraphAllowed : 1;
diff --git a/clang/include/clang/AST/CommentCommands.td b/clang/include/clang/AST/CommentCommands.td
index ced9e9ef7f9..3d8bad89c26 100644
--- a/clang/include/clang/AST/CommentCommands.td
+++ b/clang/include/clang/AST/CommentCommands.td
@@ -11,6 +11,7 @@ class Command<string name> {
bit IsReturnsCommand = 0;
bit IsParamCommand = 0;
bit IsTParamCommand = 0;
+ bit IsDeprecatedCommand = 0;
bit IsEmptyParagraphAllowed = 0;
@@ -75,7 +76,10 @@ def Tparam : BlockCommand<"tparam"> { let IsTParamCommand = 1; }
// HeaderDoc
def Templatefield : BlockCommand<"templatefield"> { let IsTParamCommand = 1; }
-def Deprecated : BlockCommand<"deprecated"> { let IsEmptyParagraphAllowed = 1; }
+def Deprecated : BlockCommand<"deprecated"> {
+ let IsEmptyParagraphAllowed = 1;
+ let IsDeprecatedCommand = 1;
+}
def Author : BlockCommand<"author">;
def Authors : BlockCommand<"authors">;
diff --git a/clang/include/clang/AST/CommentSema.h b/clang/include/clang/AST/CommentSema.h
index c913d28daef..2c4efc307ca 100644
--- a/clang/include/clang/AST/CommentSema.h
+++ b/clang/include/clang/AST/CommentSema.h
@@ -187,6 +187,8 @@ public:
/// used only once per comment, e.g., \\brief and \\returns.
void checkBlockCommandDuplicate(const BlockCommandComment *Command);
+ void checkDeprecatedCommand(const BlockCommandComment *Comment);
+
/// Resolve parameter names to parameter indexes in function declaration.
/// Emit diagnostics about unknown parametrs.
void resolveParamCommandIndexes(const FullComment *FC);
diff --git a/clang/include/clang/Basic/DiagnosticCommentKinds.td b/clang/include/clang/Basic/DiagnosticCommentKinds.td
index 235ca79564d..7203ac75f86 100644
--- a/clang/include/clang/Basic/DiagnosticCommentKinds.td
+++ b/clang/include/clang/Basic/DiagnosticCommentKinds.td
@@ -121,5 +121,15 @@ def warn_doc_returns_attached_to_a_void_function : Warning<
"method returning void}1">,
InGroup<Documentation>, DefaultIgnore;
+// \deprecated command
+
+def warn_doc_deprecated_not_sync : Warning<
+ "declaration is marked with '\\deprecated' command but does not have "
+ "a deprecation attribute">,
+ InGroup<DocumentationDeprecatedSync>, DefaultIgnore;
+
+def note_add_deprecation_attr : Note<
+ "add a deprecation attribute to the declaration to silence this warning">;
+
} // end of documentation issue category
} // end of AST component
diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td
index 223c6c5e29a..a4e9231daa8 100644
--- a/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/clang/include/clang/Basic/DiagnosticGroups.td
@@ -61,9 +61,14 @@ def DeprecatedImplementations :DiagGroup<"deprecated-implementations">;
def : DiagGroup<"disabled-optimization">;
def : DiagGroup<"discard-qual">;
def : DiagGroup<"div-by-zero">;
+
def DocumentationHTML : DiagGroup<"documentation-html">;
def DocumentationPedantic : DiagGroup<"documentation-pedantic">;
-def Documentation : DiagGroup<"documentation", [DocumentationHTML]>;
+def DocumentationDeprecatedSync : DiagGroup<"documentation-deprecated-sync">;
+def Documentation : DiagGroup<"documentation",
+ [DocumentationHTML,
+ DocumentationDeprecatedSync]>;
+
def EmptyBody : DiagGroup<"empty-body">;
def ExtraTokens : DiagGroup<"extra-tokens">;
def CXX11ExtraSemi : DiagGroup<"c++11-extra-semi">;
diff --git a/clang/lib/AST/CommentSema.cpp b/clang/lib/AST/CommentSema.cpp
index 6d84a2a4b91..4f9f1f241c8 100644
--- a/clang/lib/AST/CommentSema.cpp
+++ b/clang/lib/AST/CommentSema.cpp
@@ -59,6 +59,7 @@ void Sema::actOnBlockCommandFinish(BlockCommandComment *Command,
checkBlockCommandEmptyParagraph(Command);
checkBlockCommandDuplicate(Command);
checkReturnsCommand(Command);
+ checkDeprecatedCommand(Command);
}
ParamCommandComment *Sema::actOnParamCommandStart(SourceLocation LocBegin,
@@ -500,6 +501,39 @@ void Sema::checkBlockCommandDuplicate(const BlockCommandComment *Command) {
<< CommandName;
}
+void Sema::checkDeprecatedCommand(const BlockCommandComment *Command) {
+ if (!Traits.getCommandInfo(Command->getCommandID())->IsDeprecatedCommand)
+ return;
+
+ const Decl *D = ThisDeclInfo->ThisDecl;
+ if (!D)
+ return;
+
+ if (D->hasAttr<DeprecatedAttr>() ||
+ D->hasAttr<AvailabilityAttr>() ||
+ D->hasAttr<UnavailableAttr>())
+ return;
+
+ Diag(Command->getLocation(),
+ diag::warn_doc_deprecated_not_sync)
+ << Command->getSourceRange();
+
+ // Try to emit a fixit with a deprecation attribute.
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ // Don't emit a Fix-It for non-member function definitions. GCC does not
+ // accept attributes on them.
+ const DeclContext *Ctx = FD->getDeclContext();
+ if ((!Ctx || !Ctx->isRecord()) &&
+ FD->doesThisDeclarationHaveABody())
+ return;
+
+ Diag(FD->getLocEnd(),
+ diag::note_add_deprecation_attr)
+ << FixItHint::CreateInsertion(FD->getLocEnd().getLocWithOffset(1),
+ " __attribute__((deprecated))");
+ }
+}
+
void Sema::resolveParamCommandIndexes(const FullComment *FC) {
if (!isFunctionDecl()) {
// We already warned that \\param commands are not attached to a function
diff --git a/clang/test/Sema/warn-documentation-fixits.cpp b/clang/test/Sema/warn-documentation-fixits.cpp
index 732b44db027..812d404e68d 100644
--- a/clang/test/Sema/warn-documentation-fixits.cpp
+++ b/clang/test/Sema/warn-documentation-fixits.cpp
@@ -20,8 +20,45 @@ void test3(T aaa);
template<typename SomeTy, typename OtherTy>
void test4(SomeTy aaa, OtherTy bbb);
+// expected-warning@+1 {{declaration is marked with '\deprecated' command but does not have a deprecation attribute}} expected-note@+2 {{add a deprecation attribute to the declaration to silence this warning}}
+/// \deprecated
+void test_deprecated_1();
+
+// expected-warning@+1 {{declaration is marked with '\deprecated' command but does not have a deprecation attribute}} expected-note@+2 {{add a deprecation attribute to the declaration to silence this warning}}
+/// \deprecated
+void test_deprecated_2(int a);
+
+struct test_deprecated_3 {
+ // expected-warning@+1 {{declaration is marked with '\deprecated' command but does not have a deprecation attribute}} expected-note@+2 {{add a deprecation attribute to the declaration to silence this warning}}
+ /// \deprecated
+ void test_deprecated_4();
+
+ // expected-warning@+1 {{declaration is marked with '\deprecated' command but does not have a deprecation attribute}} expected-note@+2 {{add a deprecation attribute to the declaration to silence this warning}}
+ /// \deprecated
+ void test_deprecated_5() {
+ }
+};
+
+template<typename T>
+struct test_deprecated_6 {
+ // expected-warning@+1 {{declaration is marked with '\deprecated' command but does not have a deprecation attribute}} expected-note@+2 {{add a deprecation attribute to the declaration to silence this warning}}
+ /// \deprecated
+ void test_deprecated_7();
+
+ // expected-warning@+1 {{declaration is marked with '\deprecated' command but does not have a deprecation attribute}} expected-note@+2 {{add a deprecation attribute to the declaration to silence this warning}}
+ /// \deprecated
+ void test_deprecated_8() {
+ }
+};
+
// CHECK: fix-it:"{{.*}}":{5:12-5:22}:"a"
// CHECK: fix-it:"{{.*}}":{9:12-9:15}:"aaa"
// CHECK: fix-it:"{{.*}}":{13:13-13:23}:"T"
// CHECK: fix-it:"{{.*}}":{18:13-18:18}:"SomeTy"
+// CHECK: fix-it:"{{.*}}":{25:25-25:25}:" __attribute__((deprecated))"
+// CHECK: fix-it:"{{.*}}":{29:30-29:30}:" __attribute__((deprecated))"
+// CHECK: fix-it:"{{.*}}":{34:27-34:27}:" __attribute__((deprecated))"
+// CHECK: fix-it:"{{.*}}":{38:27-38:27}:" __attribute__((deprecated))"
+// CHECK: fix-it:"{{.*}}":{46:27-46:27}:" __attribute__((deprecated))"
+// CHECK: fix-it:"{{.*}}":{50:27-50:27}:" __attribute__((deprecated))"
diff --git a/clang/test/Sema/warn-documentation.cpp b/clang/test/Sema/warn-documentation.cpp
index 649f072ab97..b5d3300efd0 100644
--- a/clang/test/Sema/warn-documentation.cpp
+++ b/clang/test/Sema/warn-documentation.cpp
@@ -380,14 +380,39 @@ using test_tparam15 = test_tparam13<T, int>;
/// Aaa
/// \deprecated Bbb
-void test_deprecated_1(int a);
+void test_deprecated_1(int a) __attribute__((deprecated));
// We don't want \deprecated to warn about empty paragraph. It is fine to use
// \deprecated by itself without explanations.
/// Aaa
/// \deprecated
-void test_deprecated_2(int a);
+void test_deprecated_2(int a) __attribute__((deprecated));
+
+/// Aaa
+/// \deprecated
+void test_deprecated_3(int a) __attribute__((availability(macosx,introduced=10.4)));
+
+/// Aaa
+/// \deprecated
+void test_deprecated_4(int a) __attribute__((unavailable));
+
+// expected-warning@+2 {{declaration is marked with '\deprecated' command but does not have a deprecation attribute}} expected-note@+3 {{add a deprecation attribute to the declaration to silence this warning}}
+/// Aaa
+/// \deprecated
+void test_deprecated_5(int a);
+
+// expected-warning@+2 {{declaration is marked with '\deprecated' command but does not have a deprecation attribute}} expected-note@+3 {{add a deprecation attribute to the declaration to silence this warning}}
+/// Aaa
+/// \deprecated
+void test_deprecated_6(int a) {
+}
+
+// expected-warning@+2 {{declaration is marked with '\deprecated' command but does not have a deprecation attribute}}
+/// Aaa
+/// \deprecated
+template<typename T>
+void test_deprecated_7(T aaa);
/// \invariant aaa
diff --git a/clang/utils/TableGen/ClangCommentCommandInfoEmitter.cpp b/clang/utils/TableGen/ClangCommentCommandInfoEmitter.cpp
index 599d1385a83..36fbcd40b2f 100644
--- a/clang/utils/TableGen/ClangCommentCommandInfoEmitter.cpp
+++ b/clang/utils/TableGen/ClangCommentCommandInfoEmitter.cpp
@@ -38,6 +38,7 @@ void EmitClangCommentCommandInfo(RecordKeeper &Records, raw_ostream &OS) {
<< Tag.getValueAsBit("IsReturnsCommand") << ", "
<< Tag.getValueAsBit("IsParamCommand") << ", "
<< Tag.getValueAsBit("IsTParamCommand") << ", "
+ << Tag.getValueAsBit("IsDeprecatedCommand") << ", "
<< Tag.getValueAsBit("IsEmptyParagraphAllowed") << ", "
<< Tag.getValueAsBit("IsVerbatimBlockCommand") << ", "
<< Tag.getValueAsBit("IsVerbatimBlockEndCommand") << ", "
OpenPOWER on IntegriCloud