eandrews created this revision. eandrews added reviewers: erichkeane, aaron.ballman.
Added support in clang for GCC function attribute 'artificial'. This attribute is used to control stepping behavior of debugger with respect to inline functions. https://reviews.llvm.org/D43259 Files: include/clang/Basic/Attr.td include/clang/Basic/AttrDocs.td lib/CodeGen/CGDebugInfo.cpp lib/Sema/SemaDeclAttr.cpp test/CodeGen/artificial.c test/Sema/artificial.c 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}} 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: 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<ArtificialAttr>(S, D, Attr); + break; case AttributeList::AT_AnalyzerNoReturn: handleAnalyzerNoReturnAttr(S, D, Attr); break; 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<ArtificialAttr>()) { Flags |= llvm::DINode::FlagArtificial; // Artificial functions should not silently reuse CurLoc. CurLoc = SourceLocation(); Index: include/clang/Basic/AttrDocs.td =================================================================== --- include/clang/Basic/AttrDocs.td +++ include/clang/Basic/AttrDocs.td @@ -3273,3 +3273,13 @@ or `msvc documentation <https://docs.microsoft.com/pl-pl/cpp/cpp/selectany>`_. }]; } + +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: include/clang/Basic/Attr.td =================================================================== --- include/clang/Basic/Attr.td +++ include/clang/Basic/Attr.td @@ -111,6 +111,9 @@ def GlobalVar : SubsetSubject<Var, [{S->hasGlobalStorage()}], "global variables">; +def InlineFunction : SubsetSubject<Function, + [{S->isInlineSpecified()}], "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: 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}} 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: 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<ArtificialAttr>(S, D, Attr); + break; case AttributeList::AT_AnalyzerNoReturn: handleAnalyzerNoReturnAttr(S, D, Attr); break; 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<ArtificialAttr>()) { Flags |= llvm::DINode::FlagArtificial; // Artificial functions should not silently reuse CurLoc. CurLoc = SourceLocation(); Index: include/clang/Basic/AttrDocs.td =================================================================== --- include/clang/Basic/AttrDocs.td +++ include/clang/Basic/AttrDocs.td @@ -3273,3 +3273,13 @@ or `msvc documentation <https://docs.microsoft.com/pl-pl/cpp/cpp/selectany>`_. }]; } + +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: include/clang/Basic/Attr.td =================================================================== --- include/clang/Basic/Attr.td +++ include/clang/Basic/Attr.td @@ -111,6 +111,9 @@ def GlobalVar : SubsetSubject<Var, [{S->hasGlobalStorage()}], "global variables">; +def InlineFunction : SubsetSubject<Function, + [{S->isInlineSpecified()}], "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">];
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits