diff options
author | Jan Korous <jkorous@apple.com> | 2020-02-17 14:55:49 -0800 |
---|---|---|
committer | Jan Korous <jkorous@apple.com> | 2020-02-20 11:32:30 -0800 |
commit | 2f56789c8fe8edb57bc7a193592ecd35a393fe4a (patch) | |
tree | 58f31a93b3172031fc4e5a099dd89ec3b2ef5c99 /clang/lib/AST/CommentSema.cpp | |
parent | 967eeb109bedc4ae606fdf6ad6eca58ffbac6739 (diff) | |
download | llvm-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.cpp | 48 |
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() { |