diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -1441,6 +1441,16 @@ let Documentation = [Undocumented]; } +def FramePointer : InheritableAttr { + // This attribute has no spellings as it is only ever created implicitly. + let Spellings = []; + let Subjects = SubjectList<[Function]>; + let Args = [EnumArgument<"Kind", "Kind", + ["none", "non_leaf", "all"], + ["None", "NonLeaf", "All"]>]; + let Documentation = [Undocumented]; +} + def FlagEnum : InheritableAttr { let Spellings = [Clang<"flag_enum">]; let Subjects = SubjectList<[Enum]>; diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -11633,4 +11633,8 @@ "a randomized struct can only be initialized with a designated initializer">; def err_cast_from_randomized_struct : Error< "casting from randomized structure pointer type %0 to %1">; + +def warn_frame_pointer_type_not_supported : Warning< + "%0 frame_pointer argument not supported: %1">, + InGroup; } // end of sema component. diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -1650,6 +1650,24 @@ /*AttrOnCallSite=*/false, IsThunk); F->setAttributes(PAL); F->setCallingConv(static_cast(CallingConv)); + if (!GD.getDecl()) + return; + + if (GD.getDecl()->hasAttr()) { + F->removeFnAttr("frame-pointer"); + FramePointerAttr *Attr = GD.getDecl()->getAttr(); + switch (Attr->getKind()) { + case FramePointerAttr::None: + F->addFnAttr("frame-pointer", "none"); + break; + case FramePointerAttr::NonLeaf: + F->addFnAttr("frame-pointer", "non-leaf"); + break; + case FramePointerAttr::All: + F->addFnAttr("frame-pointer", "all"); + break; + } + } } static void removeImageAccessQualifier(std::string& TyName) { 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 @@ -6763,6 +6763,24 @@ checkSwiftAsyncErrorBlock(S, D, ErrorAttr, AsyncAttr); } +static void handleFramePointer(Sema &S, Decl *D, const ParsedAttr &AL) { + if (!AL.isArgIdent(0)) { + S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type) + << AL << 1 << AANT_ArgumentIdentifier; + return; + } + + FramePointerAttr::Kind Kind; + IdentifierInfo *II = AL.getArgAsIdent(0)->Ident; + if (!FramePointerAttr::ConvertStrToKind(II->getName(), Kind)) { + S.Diag(AL.getLoc(), diag::warn_frame_pointer_type_not_supported) << AL + << II; + return; + } + + D->addAttr(::new (S.Context) FramePointerAttr(S.Context, AL, Kind)); +} + //===----------------------------------------------------------------------===// // Microsoft specific attribute handlers. //===----------------------------------------------------------------------===// @@ -9031,6 +9049,10 @@ case ParsedAttr::AT_UsingIfExists: handleSimpleAttribute(S, D, AL); break; + + case ParsedAttr::AT_FramePointer: + handleFramePointer(S, D, AL); + break; } }