aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/AST/CommentSema.cpp
diff options
context:
space:
mode:
authorJan Korous <jkorous@apple.com>2020-02-17 14:55:49 -0800
committerJan Korous <jkorous@apple.com>2020-02-20 11:32:30 -0800
commit2f56789c8fe8edb57bc7a193592ecd35a393fe4a (patch)
tree58f31a93b3172031fc4e5a099dd89ec3b2ef5c99 /clang/lib/AST/CommentSema.cpp
parent967eeb109bedc4ae606fdf6ad6eca58ffbac6739 (diff)
downloadllvm-2f56789c8fe8edb57bc7a193592ecd35a393fe4a.zip
llvm-2f56789c8fe8edb57bc7a193592ecd35a393fe4a.tar.gz
llvm-2f56789c8fe8edb57bc7a193592ecd35a393fe4a.tar.bz2
[clang][doxygen] Fix false -Wdocumentation warning for tag typedefs
For tag typedefs like this one: /*! @class Foo */ typedef class { } Foo; clang -Wdocumentation gives: warning: '@class' command should not be used in a comment attached to a non-struct declaration [-Wdocumentation] ... while doxygen seems fine with it. Differential Revision: https://reviews.llvm.org/D74746
Diffstat (limited to 'clang/lib/AST/CommentSema.cpp')
-rw-r--r--clang/lib/AST/CommentSema.cpp48
1 files changed, 43 insertions, 5 deletions
diff --git a/clang/lib/AST/CommentSema.cpp b/clang/lib/AST/CommentSema.cpp
index 53c1832..8102f01 100644
--- a/clang/lib/AST/CommentSema.cpp
+++ b/clang/lib/AST/CommentSema.cpp
@@ -12,6 +12,7 @@
#include "clang/AST/CommentDiagnostic.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclTemplate.h"
+#include "clang/Basic/LLVM.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Lex/Preprocessor.h"
#include "llvm/ADT/SmallString.h"
@@ -134,7 +135,9 @@ void Sema::checkContainerDeclVerbatimLine(const BlockCommandComment *Comment) {
unsigned DiagSelect;
switch (Comment->getCommandID()) {
case CommandTraits::KCI_class:
- DiagSelect = (!isClassOrStructDecl() && !isClassTemplateDecl()) ? 1 : 0;
+ DiagSelect =
+ (!isClassOrStructOrTagTypedefDecl() && !isClassTemplateDecl()) ? 1
+ : 0;
// Allow @class command on @interface declarations.
// FIXME. Currently, \class and @class are indistinguishable. So,
// \class is also allowed on an @interface declaration
@@ -148,7 +151,7 @@ void Sema::checkContainerDeclVerbatimLine(const BlockCommandComment *Comment) {
DiagSelect = !isObjCProtocolDecl() ? 3 : 0;
break;
case CommandTraits::KCI_struct:
- DiagSelect = !isClassOrStructDecl() ? 4 : 0;
+ DiagSelect = !isClassOrStructOrTagTypedefDecl() ? 4 : 0;
break;
case CommandTraits::KCI_union:
DiagSelect = !isUnionDecl() ? 5 : 0;
@@ -935,15 +938,50 @@ bool Sema::isUnionDecl() {
return RD->isUnion();
return false;
}
+static bool isClassOrStructDeclImpl(const Decl *D) {
+ if (auto *record = dyn_cast_or_null<RecordDecl>(D))
+ return !record->isUnion();
+
+ return false;
+}
bool Sema::isClassOrStructDecl() {
if (!ThisDeclInfo)
return false;
if (!ThisDeclInfo->IsFilled)
inspectThisDecl();
- return ThisDeclInfo->CurrentDecl &&
- isa<RecordDecl>(ThisDeclInfo->CurrentDecl) &&
- !isUnionDecl();
+
+ if (!ThisDeclInfo->CurrentDecl)
+ return false;
+
+ return isClassOrStructDeclImpl(ThisDeclInfo->CurrentDecl);
+}
+
+bool Sema::isClassOrStructOrTagTypedefDecl() {
+ if (!ThisDeclInfo)
+ return false;
+ if (!ThisDeclInfo->IsFilled)
+ inspectThisDecl();
+
+ if (!ThisDeclInfo->CurrentDecl)
+ return false;
+
+ if (isClassOrStructDeclImpl(ThisDeclInfo->CurrentDecl))
+ return true;
+
+ if (auto *ThisTypedefDecl = dyn_cast<TypedefDecl>(ThisDeclInfo->CurrentDecl)) {
+ auto UnderlyingType = ThisTypedefDecl->getUnderlyingType();
+ if (auto ThisElaboratedType = dyn_cast<ElaboratedType>(UnderlyingType)) {
+ auto DesugaredType = ThisElaboratedType->desugar();
+ if (auto *DesugaredTypePtr = DesugaredType.getTypePtrOrNull()) {
+ if (auto *ThisRecordType = dyn_cast<RecordType>(DesugaredTypePtr)) {
+ return isClassOrStructDeclImpl(ThisRecordType->getAsRecordDecl());
+ }
+ }
+ }
+ }
+
+ return false;
}
bool Sema::isClassTemplateDecl() {