Skip to content

Commit 50ce2d7

Browse files
committed
Add flatten_deep attribute to clang
1 parent 862d346 commit 50ce2d7

File tree

5 files changed

+66
-0
lines changed

5 files changed

+66
-0
lines changed

clang/include/clang/Basic/Attr.td

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1976,6 +1976,13 @@ def Flatten : InheritableAttr {
19761976
let SimpleHandler = 1;
19771977
}
19781978

1979+
def FlattenDeep : InheritableAttr {
1980+
let Spellings = [Clang<"flatten_deep">];
1981+
let Subjects = SubjectList<[Function], ErrorDiag>;
1982+
let Args = [UnsignedArgument<"MaxDepth">];
1983+
let Documentation = [FlattenDeepDocs];
1984+
}
1985+
19791986
def Format : InheritableAttr {
19801987
let Spellings = [GCC<"format">];
19811988
let Args = [IdentifierArgument<"Type">, IntArgument<"FormatIdx">,

clang/include/clang/Basic/AttrDocs.td

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4032,6 +4032,29 @@ callee is unavailable or if the callee has the ``noinline`` attribute.
40324032
}];
40334033
}
40344034

4035+
def FlattenDeepDocs : Documentation {
4036+
let Category = DocCatFunction;
4037+
let Content = [{
4038+
The ``flatten_deep`` attribute causes calls within the attributed function and
4039+
their transitive callees to be inlined up to a specified depth, unless it is
4040+
impossible to do so (for example if the body of the callee is unavailable or if
4041+
the callee has the ``noinline`` attribute).
4042+
4043+
This attribute takes a single unsigned integer argument representing the maximum
4044+
depth of the call tree to inline. For example, ``__attribute__((flatten_deep(3)))``
4045+
will inline all calls within the function, then inline all calls within those
4046+
inlined functions (depth 2), and then inline all calls within those functions
4047+
(depth 3).
4048+
4049+
.. code-block:: c++
4050+
4051+
__attribute__((flatten_deep(3)))
4052+
void process_data() {
4053+
// All calls up to 3 levels deep in the call tree will be inlined
4054+
}
4055+
}];
4056+
}
4057+
40354058
def FormatDocs : Documentation {
40364059
let Category = DocCatFunction;
40374060
let Content = [{

clang/lib/Sema/SemaDeclAttr.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3695,6 +3695,24 @@ static void handleInitPriorityAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
36953695
D->addAttr(::new (S.Context) InitPriorityAttr(S.Context, AL, prioritynum));
36963696
}
36973697

3698+
static void handleFlattenDeepAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
3699+
Expr *E = AL.getArgAsExpr(0);
3700+
uint32_t maxDepth;
3701+
if (!S.checkUInt32Argument(AL, E, maxDepth)) {
3702+
AL.setInvalid();
3703+
return;
3704+
}
3705+
3706+
if (maxDepth == 0) {
3707+
S.Diag(AL.getLoc(), diag::err_attribute_argument_is_zero)
3708+
<< AL << E->getSourceRange();
3709+
AL.setInvalid();
3710+
return;
3711+
}
3712+
3713+
D->addAttr(::new (S.Context) FlattenDeepAttr(S.Context, AL, maxDepth));
3714+
}
3715+
36983716
ErrorAttr *Sema::mergeErrorAttr(Decl *D, const AttributeCommonInfo &CI,
36993717
StringRef NewUserDiagnostic) {
37003718
if (const auto *EA = D->getAttr<ErrorAttr>()) {
@@ -7236,6 +7254,9 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL,
72367254
case ParsedAttr::AT_Format:
72377255
handleFormatAttr(S, D, AL);
72387256
break;
7257+
case ParsedAttr::AT_FlattenDeep:
7258+
handleFlattenDeepAttr(S, D, AL);
7259+
break;
72397260
case ParsedAttr::AT_FormatMatches:
72407261
handleFormatMatchesAttr(S, D, AL);
72417262
break;

clang/test/Misc/pragma-attribute-supported-attributes-list.test

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@
8686
// CHECK-NEXT: ExternalSourceSymbol ((SubjectMatchRule_record, SubjectMatchRule_enum, SubjectMatchRule_enum_constant, SubjectMatchRule_field, SubjectMatchRule_function, SubjectMatchRule_namespace, SubjectMatchRule_objc_category, SubjectMatchRule_objc_implementation, SubjectMatchRule_objc_interface, SubjectMatchRule_objc_method, SubjectMatchRule_objc_property, SubjectMatchRule_objc_protocol, SubjectMatchRule_record, SubjectMatchRule_type_alias, SubjectMatchRule_variable))
8787
// CHECK-NEXT: FlagEnum (SubjectMatchRule_enum)
8888
// CHECK-NEXT: Flatten (SubjectMatchRule_function)
89+
// CHECK-NEXT: FlattenDeep (SubjectMatchRule_function)
8990
// CHECK-NEXT: FunctionReturnThunks (SubjectMatchRule_function)
9091
// CHECK-NEXT: GNUInline (SubjectMatchRule_function)
9192
// CHECK-NEXT: HIPManaged (SubjectMatchRule_variable)
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// RUN: %clang_cc1 -fsyntax-only -verify %s
2+
3+
// Test basic usage - valid
4+
__attribute__((flatten_deep(3)))
5+
void test_valid() {
6+
}
7+
8+
// Test attribute on non-function - should error
9+
__attribute__((flatten_deep(3))) int x; // expected-error {{'flatten_deep' attribute only applies to functions}}
10+
11+
// Test depth = 0 - should error (depth must be >= 1)
12+
__attribute__((flatten_deep(0))) // expected-error {{'flatten_deep' attribute must be greater than 0}}
13+
void test_depth_zero() {
14+
}

0 commit comments

Comments
 (0)