Index: include/clang/Basic/Attr.td =================================================================== --- include/clang/Basic/Attr.td +++ include/clang/Basic/Attr.td @@ -111,6 +111,9 @@ def GlobalVar : SubsetSubjecthasGlobalStorage()}], "global variables">; +def InlineFunction : SubsetSubjectisInlineSpecified()}], "inline functions">; + // FIXME: this hack is needed because DeclNodes.td defines the base Decl node // type to be a class, not a definition. This makes it impossible to create an // attribute subject which accepts a Decl. Normally, this is not a problem, @@ -588,6 +591,12 @@ let Documentation = [Undocumented]; } +def Artificial : InheritableAttr { + let Spellings = [GCC<"artificial">]; + let Subjects = SubjectList<[InlineFunction], WarnDiag>; + let Documentation = [ArtificialDocs]; +} + def XRayInstrument : InheritableAttr { let Spellings = [Clang<"xray_always_instrument">, Clang<"xray_never_instrument">]; Index: include/clang/Basic/AttrDocs.td =================================================================== --- include/clang/Basic/AttrDocs.td +++ include/clang/Basic/AttrDocs.td @@ -3273,3 +3273,13 @@ or `msvc documentation `_. }]; } + +def ArtificialDocs : Documentation { + let Category = DocCatFunction; + let Content = [{ +The ``artificial`` attribute is used with inline functions to treat the inline +function as a unit while debugging. For more information see GCC_ documentation. + +.. _GCC: https://gcc.gnu.org/onlinedocs/gcc-4.6.4/gcc/Function-Attributes.html + }]; +} Index: lib/CodeGen/CGDebugInfo.cpp =================================================================== --- lib/CodeGen/CGDebugInfo.cpp +++ lib/CodeGen/CGDebugInfo.cpp @@ -3229,7 +3229,7 @@ if (Name.startswith("\01")) Name = Name.substr(1); - if (!HasDecl || D->isImplicit()) { + if (!HasDecl || D->isImplicit() || D->hasAttr()) { Flags |= llvm::DINode::FlagArtificial; // Artificial functions should not silently reuse CurLoc. CurLoc = SourceLocation(); Index: lib/Sema/SemaDeclAttr.cpp =================================================================== --- lib/Sema/SemaDeclAttr.cpp +++ lib/Sema/SemaDeclAttr.cpp @@ -6057,6 +6057,9 @@ case AttributeList::AT_AlwaysInline: handleAlwaysInlineAttr(S, D, Attr); break; + case AttributeList::AT_Artificial: + handleSimpleAttribute(S, D, Attr); + break; case AttributeList::AT_AnalyzerNoReturn: handleAnalyzerNoReturnAttr(S, D, Attr); break; Index: test/CodeGen/artificial.c =================================================================== --- /dev/null +++ test/CodeGen/artificial.c @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -triple=x86_64-unknown-linux-gnu -emit-llvm -debug-info-kind=limited %s -o - | FileCheck %s + +extern void foo(); +// CHECK: !DISubprogram(name: "foo" +// CHECK-SAME: flags: DIFlagArtificial +inline void __attribute__((artificial)) foo() {} + +void baz() { + foo(); +} Index: test/Sema/artificial.c =================================================================== --- /dev/null +++ test/Sema/artificial.c @@ -0,0 +1,3 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +void __attribute__((artificial)) bar() {} // expected-warning {{'artificial' attribute only applies to inline functions}}