Author: Aaron Ballman Date: 2020-09-23T15:26:50-04:00 New Revision: af1d3e655991e5f0c86df372b8583a60d20268e0
URL: https://github.com/llvm/llvm-project/commit/af1d3e655991e5f0c86df372b8583a60d20268e0 DIFF: https://github.com/llvm/llvm-project/commit/af1d3e655991e5f0c86df372b8583a60d20268e0.diff LOG: 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. Added: Modified: clang/include/clang/Basic/Attr.td clang/include/clang/Basic/AttrDocs.td clang/lib/Sema/SemaDeclAttr.cpp clang/test/SemaCXX/init-priority-attr.cpp Removed: ################################################################################ diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index e8ac819c8b556..7222f396089e0 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -2196,7 +2196,7 @@ def InitPriority : InheritableAttr { let Spellings = [GCC<"init_priority", /*AllowInC*/0>]; let Args = [UnsignedArgument<"Priority">]; let Subjects = SubjectList<[Var], ErrorDiag>; - let Documentation = [Undocumented]; + let Documentation = [InitPriorityDocs]; } def Section : InheritableAttr { diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index 9c119218656d8..3e27924589e4a 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -57,6 +57,32 @@ global variable or function should be in after translation. let Heading = "section, __declspec(allocate)"; } +def InitPriorityDocs : Documentation { + let Category = DocCatVariable; + let Content = [{ +In C++, the order in which global variables are initialized across translation +units is unspecified, unlike the ordering within a single translation unit. The +``init_priority`` attribute allows you to specify a relative ordering for the +initialization of objects declared at namespace scope in C++. The priority is +given as an integer constant expression between 101 and 65535 (inclusive). +Priorities outside of that range are reserved for use by the implementation. A +lower value indicates a higher priority of initialization. Note that only the +relative ordering of values is important. For example: + +.. code-block:: c++ + + struct SomeType { SomeType(); }; + __attribute__((init_priority(200))) SomeType Obj1; + __attribute__((init_priority(101))) SomeType Obj2; + +``Obj1`` will be initialized *before* ``Obj2`` despite the usual order of +initialization being the opposite. + +This attribute is only supported for C++ and Objective-C++ and is ignored in +other language modes. + }]; +} + def InitSegDocs : Documentation { let Category = DocCatVariable; let Content = [{ diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 6edeb79396296..3babbe05ca8f9 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -3313,7 +3313,11 @@ static void handleInitPriorityAttr(Sema &S, Decl *D, const ParsedAttr &AL) { return; } - if (prioritynum < 101 || prioritynum > 65535) { + // Only perform the priority check if the attribute is outside of a system + // header. Values <= 100 are reserved for the implementation, and libc++ + // benefits from being able to specify values in that range. + if ((prioritynum < 101 || prioritynum > 65535) && + !S.getSourceManager().isInSystemHeader(AL.getLoc())) { S.Diag(AL.getLoc(), diag::err_attribute_argument_out_of_range) << E->getSourceRange() << AL << 101 << 65535; AL.setInvalid(); diff --git a/clang/test/SemaCXX/init-priority-attr.cpp b/clang/test/SemaCXX/init-priority-attr.cpp index 8f31e2fd62d00..5b5e3b9eb940e 100644 --- a/clang/test/SemaCXX/init-priority-attr.cpp +++ b/clang/test/SemaCXX/init-priority-attr.cpp @@ -1,4 +1,9 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -fsyntax-only -DSYSTEM -verify %s + +#if defined(SYSTEM) +#5 "init-priority-attr.cpp" 3 // system header +#endif class Two { private: @@ -21,7 +26,15 @@ Two foo __attribute__((init_priority(101))) ( 5, 6 ); Two goo __attribute__((init_priority(2,3))) ( 5, 6 ); // expected-error {{'init_priority' attribute takes one argument}} -Two coo[2] __attribute__((init_priority(3))); // expected-error {{'init_priority' attribute requires integer constant between 101 and 65535 inclusive}} +Two coo[2] __attribute__((init_priority(100))); +#if !defined(SYSTEM) +// expected-error@-2 {{'init_priority' attribute requires integer constant between 101 and 65535 inclusive}} +#endif + +Two boo[2] __attribute__((init_priority(65536))); +#if !defined(SYSTEM) +// expected-error@-2 {{'init_priority' attribute requires integer constant between 101 and 65535 inclusive}} +#endif Two koo[4] __attribute__((init_priority(1.13))); // expected-error {{'init_priority' attribute requires an integer constant}} @@ -30,6 +43,5 @@ Two func() __attribute__((init_priority(1001))); // expected-error {{'init_prio int i __attribute__((init_priority(1001))); // expected-error {{can only use 'init_priority' attribute on file-scope definitions of objects of class type}} int main() { - Two foo __attribute__((init_priority(1001))); // expected-error {{can only use 'init_priority' attribute on file-scope definitions of objects of class type}} + Two foo __attribute__((init_priority(1001))); // expected-error {{can only use 'init_priority' attribute on file-scope definitions of objects of class type}} } - _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits