diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -3388,6 +3388,12 @@ return; } Ty = getFunctionOrMethodResultType(D); + // replace instancetype with the class type + if (Ty.getTypePtr() == S.Context.getObjCInstanceTypeDecl()->getTypeForDecl()) + if (auto *OMD = dyn_cast(D)) + if (auto *Interface = OMD->getClassInterface()) + Ty = S.Context.getObjCObjectPointerType( + QualType(Interface->getTypeForDecl(), 0)); if (!isNSStringType(Ty, S.Context, /*AllowNSAttributedString=*/true) && !isCFStringType(Ty, S.Context) && (!Ty->isPointerType() || diff --git a/clang/test/SemaObjC/format-arg-attribute.m b/clang/test/SemaObjC/format-arg-attribute.m --- a/clang/test/SemaObjC/format-arg-attribute.m +++ b/clang/test/SemaObjC/format-arg-attribute.m @@ -1,6 +1,14 @@ // RUN: %clang_cc1 -verify -fsyntax-only %s -@class NSString; +@interface NSString ++(instancetype)stringWithCString:(const char *)cstr __attribute__((format_arg(1))); ++(instancetype)stringWithString:(NSString *)cstr __attribute__((format_arg(1))); +@end + +@protocol MaybeString +-(instancetype)maybeString:(const char *)cstr __attribute__((format_arg(1))); // expected-error {{function does not return string type}} +@end + @class NSAttributedString; extern NSString *fa2 (const NSString *) __attribute__((format_arg(1)));