Skip to content

Commit 0874e7e

Browse files
AaronBallmantstellar
authored andcommitted
Allow init_priority values <= 100 and > 65535 within system headers.
This also adds some bare-bones documentation for the attribute rather than leaving it undocumented. (cherry picked from commit af1d3e6)
1 parent 02004c9 commit 0874e7e

File tree

4 files changed

+47
-5
lines changed

4 files changed

+47
-5
lines changed

clang/include/clang/Basic/Attr.td

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2115,7 +2115,7 @@ def InitPriority : InheritableAttr {
21152115
let Spellings = [GCC<"init_priority", /*AllowInC*/0>];
21162116
let Args = [UnsignedArgument<"Priority">];
21172117
let Subjects = SubjectList<[Var], ErrorDiag>;
2118-
let Documentation = [Undocumented];
2118+
let Documentation = [InitPriorityDocs];
21192119
}
21202120

21212121
def Section : InheritableAttr {

clang/include/clang/Basic/AttrDocs.td

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,32 @@ global variable or function should be in after translation.
5757
let Heading = "section, __declspec(allocate)";
5858
}
5959

60+
def InitPriorityDocs : Documentation {
61+
let Category = DocCatVariable;
62+
let Content = [{
63+
In C++, the order in which global variables are initialized across translation
64+
units is unspecified, unlike the ordering within a single translation unit. The
65+
``init_priority`` attribute allows you to specify a relative ordering for the
66+
initialization of objects declared at namespace scope in C++. The priority is
67+
given as an integer constant expression between 101 and 65535 (inclusive).
68+
Priorities outside of that range are reserved for use by the implementation. A
69+
lower value indicates a higher priority of initialization. Note that only the
70+
relative ordering of values is important. For example:
71+
72+
.. code-block:: c++
73+
74+
struct SomeType { SomeType(); };
75+
__attribute__((init_priority(200))) SomeType Obj1;
76+
__attribute__((init_priority(101))) SomeType Obj2;
77+
78+
``Obj1`` will be initialized *before* ``Obj2`` despite the usual order of
79+
initialization being the opposite.
80+
81+
This attribute is only supported for C++ and Objective-C++ and is ignored in
82+
other language modes.
83+
}];
84+
}
85+
6086
def InitSegDocs : Documentation {
6187
let Category = DocCatVariable;
6288
let Content = [{

clang/lib/Sema/SemaDeclAttr.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3301,7 +3301,11 @@ static void handleInitPriorityAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
33013301
return;
33023302
}
33033303

3304-
if (prioritynum < 101 || prioritynum > 65535) {
3304+
// Only perform the priority check if the attribute is outside of a system
3305+
// header. Values <= 100 are reserved for the implementation, and libc++
3306+
// benefits from being able to specify values in that range.
3307+
if ((prioritynum < 101 || prioritynum > 65535) &&
3308+
!S.getSourceManager().isInSystemHeader(AL.getLoc())) {
33053309
S.Diag(AL.getLoc(), diag::err_attribute_argument_out_of_range)
33063310
<< E->getSourceRange() << AL << 101 << 65535;
33073311
AL.setInvalid();

clang/test/SemaCXX/init-priority-attr.cpp

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
11
// RUN: %clang_cc1 -fsyntax-only -verify %s
2+
// RUN: %clang_cc1 -fsyntax-only -DSYSTEM -verify %s
3+
4+
#if defined(SYSTEM)
5+
#5 "init-priority-attr.cpp" 3 // system header
6+
#endif
27

38
class Two {
49
private:
@@ -21,7 +26,15 @@ Two foo __attribute__((init_priority(101))) ( 5, 6 );
2126

2227
Two goo __attribute__((init_priority(2,3))) ( 5, 6 ); // expected-error {{'init_priority' attribute takes one argument}}
2328

24-
Two coo[2] __attribute__((init_priority(3))); // expected-error {{'init_priority' attribute requires integer constant between 101 and 65535 inclusive}}
29+
Two coo[2] __attribute__((init_priority(100)));
30+
#if !defined(SYSTEM)
31+
// expected-error@-2 {{'init_priority' attribute requires integer constant between 101 and 65535 inclusive}}
32+
#endif
33+
34+
Two boo[2] __attribute__((init_priority(65536)));
35+
#if !defined(SYSTEM)
36+
// expected-error@-2 {{'init_priority' attribute requires integer constant between 101 and 65535 inclusive}}
37+
#endif
2538

2639
Two koo[4] __attribute__((init_priority(1.13))); // expected-error {{'init_priority' attribute requires an integer constant}}
2740

@@ -30,6 +43,5 @@ Two func() __attribute__((init_priority(1001))); // expected-error {{'init_prio
3043
int i __attribute__((init_priority(1001))); // expected-error {{can only use 'init_priority' attribute on file-scope definitions of objects of class type}}
3144

3245
int main() {
33-
Two foo __attribute__((init_priority(1001))); // expected-error {{can only use 'init_priority' attribute on file-scope definitions of objects of class type}}
46+
Two foo __attribute__((init_priority(1001))); // expected-error {{can only use 'init_priority' attribute on file-scope definitions of objects of class type}}
3447
}
35-

0 commit comments

Comments
 (0)