Index: include/clang/Basic/Attr.td =================================================================== --- include/clang/Basic/Attr.td +++ include/clang/Basic/Attr.td @@ -668,6 +668,12 @@ let Documentation = [Undocumented]; } +def Flatten : InheritableAttr { + let Spellings = [GNU<"flatten">]; + let Subjects = SubjectList<[Function]>; + let Documentation = [Undocumented]; +} + def Format : InheritableAttr { let Spellings = [GCC<"format">]; let Args = [IdentifierArgument<"Type">, IntArgument<"FormatIdx">, Index: lib/CodeGen/CGCall.cpp =================================================================== --- lib/CodeGen/CGCall.cpp +++ lib/CodeGen/CGCall.cpp @@ -1063,6 +1063,7 @@ } void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI, + const Decl *CallerDecl, const Decl *TargetDecl, AttributeListType &PAL, unsigned &CallingConv, @@ -1075,6 +1076,11 @@ if (FI.isNoReturn()) FuncAttrs.addAttribute(llvm::Attribute::NoReturn); + if (CallerDecl) { + if (CallerDecl->hasAttr()) + FuncAttrs.addAttribute(llvm::Attribute::AlwaysInline); + } + // FIXME: handle sseregparm someday... if (TargetDecl) { if (TargetDecl->hasAttr()) @@ -2913,7 +2919,7 @@ unsigned CallingConv; CodeGen::AttributeListType AttributeList; - CGM.ConstructAttributeList(CallInfo, TargetDecl, AttributeList, + CGM.ConstructAttributeList(CallInfo, CurCodeDecl, TargetDecl, AttributeList, CallingConv, true); llvm::AttributeSet Attrs = llvm::AttributeSet::get(getLLVMContext(), AttributeList); Index: lib/CodeGen/CodeGenModule.h =================================================================== --- lib/CodeGen/CodeGenModule.h +++ lib/CodeGen/CodeGenModule.h @@ -906,12 +906,14 @@ /// function type. /// /// \param Info - The function type information. + /// \param CallerDecl - The decl of the caller, if available /// \param TargetDecl - The decl these attributes are being constructed /// for. If supplied the attributes applied to this decl may contribute to the /// function attributes and calling convention. /// \param PAL [out] - On return, the attribute list to use. /// \param CallingConv [out] - On return, the LLVM calling convention to use. void ConstructAttributeList(const CGFunctionInfo &Info, + const Decl *CallerDecl, const Decl *TargetDecl, AttributeListType &PAL, unsigned &CallingConv, Index: lib/CodeGen/CodeGenModule.cpp =================================================================== --- lib/CodeGen/CodeGenModule.cpp +++ lib/CodeGen/CodeGenModule.cpp @@ -576,7 +576,7 @@ llvm::Function *F) { unsigned CallingConv; AttributeListType AttributeList; - ConstructAttributeList(Info, D, AttributeList, CallingConv, false); + ConstructAttributeList(Info, 0, D, AttributeList, CallingConv, false); F->setAttributes(llvm::AttributeSet::get(getLLVMContext(), AttributeList)); F->setCallingConv(static_cast(CallingConv)); } Index: lib/CodeGen/MicrosoftCXXABI.cpp =================================================================== --- lib/CodeGen/MicrosoftCXXABI.cpp +++ lib/CodeGen/MicrosoftCXXABI.cpp @@ -1113,7 +1113,7 @@ unsigned CallingConv; CodeGen::AttributeListType AttributeList; - CGM.ConstructAttributeList(FnInfo, MD, AttributeList, CallingConv, true); + CGM.ConstructAttributeList(FnInfo, 0, MD, AttributeList, CallingConv, true); llvm::AttributeSet Attrs = llvm::AttributeSet::get(CGF.getLLVMContext(), AttributeList); Index: lib/Sema/SemaDeclAttr.cpp =================================================================== --- lib/Sema/SemaDeclAttr.cpp +++ lib/Sema/SemaDeclAttr.cpp @@ -4140,6 +4140,9 @@ case AttributeList::AT_OptimizeNone: handleOptimizeNoneAttr(S, D, Attr); break; + case AttributeList::AT_Flatten: + handleSimpleAttribute(S, D, Attr); + break; case AttributeList::AT_Format: handleFormatAttr(S, D, Attr); break; Index: test/CodeGen/flatten.c =================================================================== --- /dev/null +++ test/CodeGen/flatten.c @@ -0,0 +1,10 @@ +// RUN: %clang -target x86_64-linux-gnu -S %s -emit-llvm -o - | FileCheck %s + +void f(void) {} + +__attribute__((flatten)) +// CHECK: define void @g() +void g(void) { + // CHECK-NOT: call {{.*}} @f + f(); +}