Index: clang/lib/AST/Comment.cpp =================================================================== --- clang/lib/AST/Comment.cpp +++ clang/lib/AST/Comment.cpp @@ -112,7 +112,8 @@ return true; } -static TypeLoc lookThroughTypedefOrTypeAliasLocs(TypeLoc &SrcTL) { +static TypeLoc lookThroughTypedefOrTypeAliasLocs(TypeLoc &SrcTL, + bool testTypedefTypeLoc) { TypeLoc TL = SrcTL.IgnoreParens(); // Look through attribute types. @@ -136,15 +137,22 @@ return MemberPointerTL.getPointeeLoc().getUnqualifiedLoc(); if (ElaboratedTypeLoc ETL = TL.getAs()) return ETL.getNamedTypeLoc(); + if (testTypedefTypeLoc) + if (TypedefTypeLoc TTL = TL.getAs()) { + TypedefNameDecl *TND = TTL.getTypedefNameDecl(); + if (const TypeSourceInfo *TSI = TND->getTypeSourceInfo()) + return TSI->getTypeLoc().getUnqualifiedLoc(); + } return TL; } -static bool getFunctionTypeLoc(TypeLoc TL, FunctionTypeLoc &ResFTL) { +static bool getFunctionTypeLoc(TypeLoc TL, FunctionTypeLoc &ResFTL, + bool testTypedefTypeLoc = false) { TypeLoc PrevTL; while (PrevTL != TL) { PrevTL = TL; - TL = lookThroughTypedefOrTypeAliasLocs(TL); + TL = lookThroughTypedefOrTypeAliasLocs(TL, testTypedefTypeLoc); } if (FunctionTypeLoc FTL = TL.getAs()) { @@ -293,7 +301,10 @@ if (TSI) { TypeLoc TL = TSI->getTypeLoc().getUnqualifiedLoc(); FunctionTypeLoc FTL; - if (getFunctionTypeLoc(TL, FTL)) { + // Need to look through the typedef when + // Sema::isFunctionOrBlockPointerVarLikeDecl found a FunctionPointerType + // or a BlockPointerType else the ReturnType will not be set. + if (getFunctionTypeLoc(TL, FTL, true)) { ParamVars = FTL.getParams(); ReturnType = FTL.getReturnLoc().getType(); } Index: clang/lib/AST/CommentSema.cpp =================================================================== --- clang/lib/AST/CommentSema.cpp +++ clang/lib/AST/CommentSema.cpp @@ -588,6 +588,8 @@ if (isObjCPropertyDecl()) return; if (isFunctionDecl() || isFunctionOrBlockPointerVarLikeDecl()) { + assert(!ThisDeclInfo->ReturnType.isNull() && + "should have a valid return type"); if (ThisDeclInfo->ReturnType->isVoidType()) { unsigned DiagKind; switch (ThisDeclInfo->CommentDecl->getKind()) { Index: clang/test/Sema/warn-documentation.cpp =================================================================== --- clang/test/Sema/warn-documentation.cpp +++ clang/test/Sema/warn-documentation.cpp @@ -1362,3 +1362,30 @@ */ class EmptyNoteNoCrash { }; + +namespace PR42844 { // Assertion failures when using typedefed function pointers +typedef void (*AA)(); +typedef AA A(); +A *a1; ///< \return none +A a2; ///< \return none + +typedef int B(); +B *b; ///< \return none + +typedef void C(); +C *c; ///< \return none +// expected-warning@-1 {{'\return' command used in a comment that is attached to a function returning void}} + +using DD = void(*)(); +using D = DD(); +D *d1; ///< \return none +D d2; ///< \return none + +using E = int(); +E *e; ///< \return none + +using F = void(); +F *f; ///< \return none +// expected-warning@-1 {{'\return' command used in a comment that is attached to a function returning void}} + +} // namespace PR42844 Index: clang/test/Sema/warn-documentation.m =================================================================== --- clang/test/Sema/warn-documentation.m +++ clang/test/Sema/warn-documentation.m @@ -310,3 +310,10 @@ * now should work too. */ typedef void (^VariadicBlockType)(int a, ...); + +// PR42844 - Assertion failures when using typedefed block pointers +typedef void(^VoidBlockType)(); +typedef VoidBlockType VoidBlockTypeCall(); +VoidBlockTypeCall *d; ///< \return none +VoidBlockTypeCall ^e; ///< \return none +VoidBlockTypeCall f; ///< \return none