Index: include/clang/Driver/CC1Options.td =================================================================== --- include/clang/Driver/CC1Options.td +++ include/clang/Driver/CC1Options.td @@ -223,6 +223,8 @@ HelpText<"Do not put zero initialized data in the BSS">; def backend_option : Separate<["-"], "backend-option">, HelpText<"Additional arguments to forward to LLVM backend (during code gen)">; +def function_attribute : Separate<["-"], "function-attribute">, + HelpText<"Function attributes to attach to functions (during code gen)">; def mregparm : Separate<["-"], "mregparm">, HelpText<"Limit the number of registers available for integer arguments">; def mrelocation_model : Separate<["-"], "mrelocation-model">, Index: include/clang/Frontend/CodeGenOptions.h =================================================================== --- include/clang/Frontend/CodeGenOptions.h +++ include/clang/Frontend/CodeGenOptions.h @@ -151,6 +151,10 @@ /// A list of command-line options to forward to the LLVM backend. std::vector BackendOptions; + /// A list of function attributes in the form of key-value pairs to save to + /// the IR. + std::vector> FunctionAttributes; + /// A list of dependent libraries. std::vector DependentLibraries; Index: lib/CodeGen/BackendUtil.cpp =================================================================== --- lib/CodeGen/BackendUtil.cpp +++ lib/CodeGen/BackendUtil.cpp @@ -536,7 +536,6 @@ Options.NoZerosInBSS = CodeGenOpts.NoZeroInitializedInBSS; Options.UnsafeFPMath = CodeGenOpts.UnsafeFPMath; Options.StackAlignmentOverride = CodeGenOpts.StackAlignment; - Options.TrapFuncName = CodeGenOpts.TrapFuncName; Options.PositionIndependentExecutable = LangOpts.PIELevel != 0; Options.FunctionSections = CodeGenOpts.FunctionSections; Options.DataSections = CodeGenOpts.DataSections; Index: lib/CodeGen/CGCall.cpp =================================================================== --- lib/CodeGen/CGCall.cpp +++ lib/CodeGen/CGCall.cpp @@ -1455,6 +1455,9 @@ FuncAttrs.addAttribute(llvm::Attribute::NoBuiltin); } else { // Attributes that should go on the function, but not the call site. + for (auto &KV : CodeGenOpts.FunctionAttributes) + FuncAttrs.addAttribute(KV.first, KV.second); + if (!CodeGenOpts.DisableFPElim) { FuncAttrs.addAttribute("no-frame-pointer-elim", "false"); } else if (CodeGenOpts.OmitLeafFramePointer) { Index: lib/Driver/Tools.cpp =================================================================== --- lib/Driver/Tools.cpp +++ lib/Driver/Tools.cpp @@ -3938,7 +3938,11 @@ CmdArgs.push_back(A->getValue()); } - Args.AddLastArg(CmdArgs, options::OPT_ftrap_function_EQ); + if (Arg *A = Args.getLastArg(options::OPT_ftrap_function_EQ)) { + CmdArgs.push_back("-function-attribute"); + auto AttrStr = Twine("trap-func-name=") + A->getValue(); + CmdArgs.push_back(Args.MakeArgString(AttrStr)); + } // -fno-strict-overflow implies -fwrapv if it isn't disabled, but // -fstrict-overflow won't turn off an explicitly enabled -fwrapv. Index: lib/Frontend/CompilerInvocation.cpp =================================================================== --- lib/Frontend/CompilerInvocation.cpp +++ lib/Frontend/CompilerInvocation.cpp @@ -356,6 +356,14 @@ } } +static void getFunctionAttributes(CodeGenOptions &Opts, + const std::vector &FnAttrStrs) { + for (const auto &S : FnAttrStrs) { + std::pair KV = StringRef(S).split('='); + Opts.FunctionAttributes.push_back(std::make_pair(KV.first, KV.second)); + } +} + static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, DiagnosticsEngine &Diags, const TargetOptions &TargetOpts) { @@ -496,7 +504,6 @@ Diags.Report(diag::err_drv_invalid_value) << Args.getLastArg(OPT_mthread_model)->getAsString(Args) << Opts.ThreadModel; - Opts.TrapFuncName = Args.getLastArgValue(OPT_ftrap_function_EQ); Opts.UseInitArray = Args.hasArg(OPT_fuse_init_array); Opts.FunctionSections = Args.hasFlag(OPT_ffunction_sections, @@ -668,6 +675,7 @@ Args.getAllArgValues(OPT_fsanitize_trap_EQ), Diags, Opts.SanitizeTrap); + getFunctionAttributes(Opts, Args.getAllArgValues(OPT_function_attribute)); Opts.CudaGpuBinaryFileNames = Args.getAllArgValues(OPT_fcuda_include_gpubinary); Index: test/CodeGen/fn-attr.c =================================================================== --- /dev/null +++ test/CodeGen/fn-attr.c @@ -0,0 +1,5 @@ +// RUN: %clang_cc1 -triple thumbv7-apple-ios5 -function-attribute trap-func-name=trapfuncname1 -emit-llvm -o - %s | FileCheck %s + +// CHECK: attributes #0 = { {{.*}} "trap-func-name"="trapfuncname1" + +int foo1(int a) { return a; }