diff --git a/clang/include/clang/AST/Comment.h b/clang/include/clang/AST/Comment.h --- a/clang/include/clang/AST/Comment.h +++ b/clang/include/clang/AST/Comment.h @@ -1077,6 +1077,9 @@ /// Can be true only if \c IsFunctionDecl is true. unsigned IsClassMethod : 1; + /// Is \c CommentDecl something we consider a "function" that's variadic. + unsigned IsVariadic : 1; + void fill(); DeclKind getKind() const LLVM_READONLY { diff --git a/clang/lib/AST/Comment.cpp b/clang/lib/AST/Comment.cpp --- a/clang/lib/AST/Comment.cpp +++ b/clang/lib/AST/Comment.cpp @@ -210,6 +210,7 @@ IsObjCMethod = false; IsInstanceMethod = false; IsClassMethod = false; + IsVariadic = false; ParamVars = None; TemplateParameters = nullptr; @@ -248,6 +249,7 @@ IsInstanceMethod = MD->isInstance(); IsClassMethod = !IsInstanceMethod; } + IsVariadic = FD->isVariadic(); break; } case Decl::ObjCMethod: { @@ -258,6 +260,7 @@ IsObjCMethod = true; IsInstanceMethod = MD->isInstanceMethod(); IsClassMethod = !IsInstanceMethod; + IsVariadic = MD->isVariadic(); break; } case Decl::FunctionTemplate: { @@ -268,6 +271,7 @@ ParamVars = FD->parameters(); ReturnType = FD->getReturnType(); TemplateParameters = FTD->getTemplateParameters(); + IsVariadic = FD->isVariadic(); break; } case Decl::ClassTemplate: { @@ -351,6 +355,8 @@ Kind = FunctionKind; ParamVars = FTL.getParams(); ReturnType = FTL.getReturnLoc().getType(); + if (const auto *FPT = FTL.getTypePtr()->getAs()) + IsVariadic = FPT->isVariadic(); } } diff --git a/clang/lib/AST/CommentSema.cpp b/clang/lib/AST/CommentSema.cpp --- a/clang/lib/AST/CommentSema.cpp +++ b/clang/lib/AST/CommentSema.cpp @@ -830,26 +830,11 @@ } bool Sema::isFunctionOrMethodVariadic() { - if (!isFunctionDecl() || !ThisDeclInfo->CurrentDecl) + if (!ThisDeclInfo) return false; - if (const FunctionDecl *FD = - dyn_cast(ThisDeclInfo->CurrentDecl)) - return FD->isVariadic(); - if (const FunctionTemplateDecl *FTD = - dyn_cast(ThisDeclInfo->CurrentDecl)) - return FTD->getTemplatedDecl()->isVariadic(); - if (const ObjCMethodDecl *MD = - dyn_cast(ThisDeclInfo->CurrentDecl)) - return MD->isVariadic(); - if (const TypedefNameDecl *TD = - dyn_cast(ThisDeclInfo->CurrentDecl)) { - QualType Type = TD->getUnderlyingType(); - if (Type->isFunctionPointerType() || Type->isBlockPointerType()) - Type = Type->getPointeeType(); - if (const auto *FT = Type->getAs()) - return FT->isVariadic(); - } - return false; + if (!ThisDeclInfo->IsFilled) + inspectThisDecl(); + return ThisDeclInfo->IsVariadic; } bool Sema::isObjCMethodDecl() { diff --git a/clang/test/Sema/warn-documentation.cpp b/clang/test/Sema/warn-documentation.cpp --- a/clang/test/Sema/warn-documentation.cpp +++ b/clang/test/Sema/warn-documentation.cpp @@ -1448,6 +1448,17 @@ */ using VariadicFnType2 = void (*)(int a, ...); +/*! + * Function pointer type variable. + * + * @param a + * works + * + * @param ... + * now should work too. + */ +void (*variadicFnVar)(int a, ...); + // expected-warning@+2 {{empty paragraph passed to '@note' command}} /** @note