Implement function attribute artificial

Added support in clang for GCC function attribute 'artificial'. This attribute 
is used to control stepping behavior of debugger with respect to inline 
functions.

Patch By: Elizabeth Andrews (eandrews)

Differential Revision: https://reviews.llvm.org/D43259



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@325081 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Erich Keane 2018-02-14 00:14:07 +00:00
parent a701b12944
commit 789b385fd1
6 changed files with 37 additions and 1 deletions

View File

@ -111,6 +111,9 @@ def SharedVar : SubsetSubject<Var,
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 @@ def AlwaysInline : InheritableAttr {
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">];

View File

@ -3273,3 +3273,13 @@ For more information see
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
}];
}

View File

@ -3235,7 +3235,7 @@ void CGDebugInfo::EmitFunctionStart(GlobalDecl GD, SourceLocation Loc,
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();

View File

@ -6057,6 +6057,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
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;

10
test/CodeGen/artificial.c Normal file
View File

@ -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();
}

4
test/Sema/artificial.c Normal file
View File

@ -0,0 +1,4 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s
inline void __attribute__((artificial)) foo() {}
void __attribute__((artificial)) bar() {} // expected-warning {{'artificial' attribute only applies to inline functions}}