diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index b78aec68bec6..f64a7da2a528 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -7021,6 +7021,7 @@ static void CheckMissingFormatAttributes(Sema *S, FormatStringType FormatType, NamedDecl *Caller = S->getCurFunctionOrMethodDecl(); if (!Caller) return; + Caller = dyn_cast(Caller->getCanonicalDecl()); unsigned NumCallerParams = getFunctionOrMethodNumParams(Caller); @@ -7069,24 +7070,39 @@ static void CheckMissingFormatAttributes(Sema *S, FormatStringType FormatType, } // Emit the diagnostic and fixit. - unsigned FormatStringIndex = CallerParamIdx + CallerArgumentIndexOffset; - StringRef AttrPrefix, AttrSuffix; - if (S->getLangOpts().C23 || S->getLangOpts().CPlusPlus11) { - AttrPrefix = "[[gnu::"; - AttrSuffix = "]] "; - } else { - AttrPrefix = "__attribute__(("; - AttrSuffix = ")) "; - } - StringRef FormatTypeName = S->GetFormatStringTypeName(FormatType); - std::string Attr = - ("format(" + FormatTypeName + ", " + llvm::Twine(FormatStringIndex) + - ", " + llvm::Twine(FirstArgumentIndex) + ")") - .str(); - S->Diag(Loc, diag::warn_missing_format_attribute) - << Attr << Caller - << FixItHint::CreateInsertion(Caller->getBeginLoc(), - (AttrPrefix + Attr + AttrSuffix).str()); + do { + unsigned FormatStringIndex = CallerParamIdx + CallerArgumentIndexOffset; + StringRef FormatTypeName = S->GetFormatStringTypeName(FormatType); + std::string Attr, Fixit; + llvm::raw_string_ostream(Attr) + << "format(" << FormatTypeName << ", " << FormatStringIndex << ", " + << FirstArgumentIndex << ")"; + auto DB = S->Diag(Loc, diag::warn_missing_format_attribute) + << Attr << Caller; + const LangOptions &LO = S->getLangOpts(); + SourceLocation SL; + llvm::raw_string_ostream IS(Fixit); + // The attribute goes at the start of the declaration in C/C++ functions + // and methods, but after the declaration for Objective-C methods. + if (isa(Caller)) { + IS << ' '; + SL = Caller->getEndLoc(); + } + + if (LO.C23 || LO.CPlusPlus11) + IS << "[[gnu::" << Attr << "]]"; + else if (LO.ObjC || LO.GNUMode) + IS << "__attribute__((" << Attr << "))"; + else + break; + + if (!isa(Caller)) { + IS << ' '; + SL = Caller->getBeginLoc(); + } + IS.flush(); + DB << FixItHint::CreateInsertion(SL, Fixit); + } while (false); S->Diag(Caller->getLocation(), diag::note_entity_declared_at) << Caller; }