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 @@ -1451,6 +1451,16 @@ let Documentation = [Undocumented]; } +def OptimizeSize: InheritableAttr { + // This attribute has no spellings as it is only ever created implicitly. + let Spellings = []; + let Subjects = SubjectList<[Function]>; + let Args = [EnumArgument<"Kind", "Kind", + ["off", "on"], + ["Off", "On"]>]; + let Documentation = [Undocumented]; +} + def FlagEnum : InheritableAttr { let Spellings = [Clang<"flag_enum">]; let Subjects = SubjectList<[Enum]>; 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 @@ -1653,6 +1653,19 @@ if (!GD.getDecl()) return; + bool HasOptnone = GD.getDecl()->hasAttr(); + bool HasOptsizeOn = false; + bool HasOptsizeOff = false; + if (GD.getDecl()->hasAttr()) { + OptimizeSizeAttr *Attr = GD.getDecl()->getAttr(); + HasOptsizeOn = Attr->getKind() == OptimizeSizeAttr::On; + HasOptsizeOff = Attr->getKind() == OptimizeSizeAttr::Off; + } + if (HasOptsizeOn && !HasOptnone) + F->addFnAttr(llvm::Attribute::OptimizeForSize); + if (HasOptsizeOff) + F->removeFnAttr(llvm::Attribute::OptimizeForSize); + if (GD.getDecl()->hasAttr()) { F->removeFnAttr("frame-pointer"); FramePointerAttr *Attr = GD.getDecl()->getAttr(); 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,19 @@ checkSwiftAsyncErrorBlock(S, D, ErrorAttr, AsyncAttr); } +static void handleOptimizeSizeAttr(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; + } + + OptimizeSizeAttr::Kind Kind; + IdentifierInfo *II = AL.getArgAsIdent(0)->Ident; + OptimizeSizeAttr::ConvertStrToKind(II->getName(), Kind); + D->addAttr(::new (S.Context) OptimizeSizeAttr(S.Context, AL, Kind)); +} + static void handleFramePointer(Sema &S, Decl *D, const ParsedAttr &AL) { if (!AL.isArgIdent(0)) { S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type) @@ -8534,6 +8547,9 @@ case ParsedAttr::AT_MinSize: handleMinSizeAttr(S, D, AL); break; + case ParsedAttr::AT_OptimizeSize: + handleOptimizeSizeAttr(S, D, AL); + break; case ParsedAttr::AT_OptimizeNone: handleOptimizeNoneAttr(S, D, AL); break;