-
Notifications
You must be signed in to change notification settings - Fork 14.4k
[Attributes] Support Attributes being declared as supporting an experimental late parsing mode "extension" #88596
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -592,6 +592,49 @@ class AttrSubjectMatcherAggregateRule<AttrSubject subject> { | |
|
||
def SubjectMatcherForNamed : AttrSubjectMatcherAggregateRule<Named>; | ||
|
||
// Enumeration specifying what kind of behavior should be used for late | ||
// parsing of attributes. | ||
class LateAttrParseKind <int val> { | ||
int Kind = val; | ||
} | ||
delcypher marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
// Never late parsed | ||
def LateAttrParseNever : LateAttrParseKind<0>; | ||
|
||
// Standard late attribute parsing | ||
// | ||
// This is language dependent. For example: | ||
// | ||
// * For C++ enables late parsing of a declaration attributes | ||
// * For C does not enable late parsing of attributes | ||
// | ||
def LateAttrParseStandard : LateAttrParseKind<1>; | ||
|
||
// Experimental extension to standard late attribute parsing | ||
// | ||
// This extension behaves like `LateAttrParseStandard` but allows | ||
// late parsing attributes in more contexts. | ||
// | ||
// In contexts where `LateAttrParseStandard` attributes are late | ||
// parsed, `LateAttrParseExperimentalExt` attributes will also | ||
// be late parsed. | ||
// | ||
// In contexts that only late parse `LateAttrParseExperimentalExt` attributes | ||
// (see `LateParsedAttrList::lateAttrParseExperimentalExtOnly()`) | ||
// | ||
// * If `-fexperimental-late-parse-attributes` | ||
// (`LangOpts.ExperimentalLateParseAttributes`) is enabled the attribute | ||
// will be late parsed. | ||
// * If `-fexperimental-late-parse-attributes` | ||
// (`LangOpts.ExperimentalLateParseAttributes`) is disabled the attribute | ||
// will **not** be late parsed (i.e parsed immediately). | ||
// | ||
// The following contexts are supported: | ||
// | ||
// * TODO: Add contexts here when they are implemented. | ||
// | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It would be helpful to clarify whether this applies in all language modes or not given that There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @AaronBallman Or did you have something else in mind? |
||
def LateAttrParseExperimentalExt : LateAttrParseKind<2>; | ||
|
||
class Attr { | ||
// The various ways in which an attribute can be spelled in source | ||
list<Spelling> Spellings; | ||
|
@@ -603,8 +646,8 @@ class Attr { | |
list<Accessor> Accessors = []; | ||
// Specify targets for spellings. | ||
list<TargetSpecificSpelling> TargetSpecificSpellings = []; | ||
// Set to true for attributes with arguments which require delayed parsing. | ||
bit LateParsed = 0; | ||
// Specifies the late parsing kind. | ||
LateAttrParseKind LateParsed = LateAttrParseNever; | ||
// Set to false to prevent an attribute from being propagated from a template | ||
// to the instantiation. | ||
bit Clone = 1; | ||
|
@@ -3173,7 +3216,7 @@ def DiagnoseIf : InheritableAttr { | |
BoolArgument<"ArgDependent", 0, /*fake*/ 1>, | ||
DeclArgument<Named, "Parent", 0, /*fake*/ 1>]; | ||
let InheritEvenIfAlreadyPresent = 1; | ||
let LateParsed = 1; | ||
let LateParsed = LateAttrParseStandard; | ||
let AdditionalMembers = [{ | ||
bool isError() const { return diagnosticType == DT_Error; } | ||
bool isWarning() const { return diagnosticType == DT_Warning; } | ||
|
@@ -3472,7 +3515,7 @@ def AssertCapability : InheritableAttr { | |
let Spellings = [Clang<"assert_capability", 0>, | ||
Clang<"assert_shared_capability", 0>]; | ||
let Subjects = SubjectList<[Function]>; | ||
let LateParsed = 1; | ||
let LateParsed = LateAttrParseStandard; | ||
let TemplateDependent = 1; | ||
let ParseArgumentsAsUnevaluated = 1; | ||
let InheritEvenIfAlreadyPresent = 1; | ||
|
@@ -3488,7 +3531,7 @@ def AcquireCapability : InheritableAttr { | |
GNU<"exclusive_lock_function">, | ||
GNU<"shared_lock_function">]; | ||
let Subjects = SubjectList<[Function]>; | ||
let LateParsed = 1; | ||
let LateParsed = LateAttrParseStandard; | ||
let TemplateDependent = 1; | ||
let ParseArgumentsAsUnevaluated = 1; | ||
let InheritEvenIfAlreadyPresent = 1; | ||
|
@@ -3504,7 +3547,7 @@ def TryAcquireCapability : InheritableAttr { | |
Clang<"try_acquire_shared_capability", 0>]; | ||
let Subjects = SubjectList<[Function], | ||
ErrorDiag>; | ||
let LateParsed = 1; | ||
let LateParsed = LateAttrParseStandard; | ||
let TemplateDependent = 1; | ||
let ParseArgumentsAsUnevaluated = 1; | ||
let InheritEvenIfAlreadyPresent = 1; | ||
|
@@ -3520,7 +3563,7 @@ def ReleaseCapability : InheritableAttr { | |
Clang<"release_generic_capability", 0>, | ||
Clang<"unlock_function", 0>]; | ||
let Subjects = SubjectList<[Function]>; | ||
let LateParsed = 1; | ||
let LateParsed = LateAttrParseStandard; | ||
let TemplateDependent = 1; | ||
let ParseArgumentsAsUnevaluated = 1; | ||
let InheritEvenIfAlreadyPresent = 1; | ||
|
@@ -3539,7 +3582,7 @@ def RequiresCapability : InheritableAttr { | |
Clang<"requires_shared_capability", 0>, | ||
Clang<"shared_locks_required", 0>]; | ||
let Args = [VariadicExprArgument<"Args">]; | ||
let LateParsed = 1; | ||
let LateParsed = LateAttrParseStandard; | ||
let TemplateDependent = 1; | ||
let ParseArgumentsAsUnevaluated = 1; | ||
let InheritEvenIfAlreadyPresent = 1; | ||
|
@@ -3559,7 +3602,7 @@ def NoThreadSafetyAnalysis : InheritableAttr { | |
def GuardedBy : InheritableAttr { | ||
let Spellings = [GNU<"guarded_by">]; | ||
let Args = [ExprArgument<"Arg">]; | ||
let LateParsed = 1; | ||
let LateParsed = LateAttrParseStandard; | ||
let TemplateDependent = 1; | ||
let ParseArgumentsAsUnevaluated = 1; | ||
let InheritEvenIfAlreadyPresent = 1; | ||
|
@@ -3570,7 +3613,7 @@ def GuardedBy : InheritableAttr { | |
def PtGuardedBy : InheritableAttr { | ||
let Spellings = [GNU<"pt_guarded_by">]; | ||
let Args = [ExprArgument<"Arg">]; | ||
let LateParsed = 1; | ||
let LateParsed = LateAttrParseStandard; | ||
let TemplateDependent = 1; | ||
let ParseArgumentsAsUnevaluated = 1; | ||
let InheritEvenIfAlreadyPresent = 1; | ||
|
@@ -3581,7 +3624,7 @@ def PtGuardedBy : InheritableAttr { | |
def AcquiredAfter : InheritableAttr { | ||
let Spellings = [GNU<"acquired_after">]; | ||
let Args = [VariadicExprArgument<"Args">]; | ||
let LateParsed = 1; | ||
let LateParsed = LateAttrParseStandard; | ||
let TemplateDependent = 1; | ||
let ParseArgumentsAsUnevaluated = 1; | ||
let InheritEvenIfAlreadyPresent = 1; | ||
|
@@ -3592,7 +3635,7 @@ def AcquiredAfter : InheritableAttr { | |
def AcquiredBefore : InheritableAttr { | ||
let Spellings = [GNU<"acquired_before">]; | ||
let Args = [VariadicExprArgument<"Args">]; | ||
let LateParsed = 1; | ||
let LateParsed = LateAttrParseStandard; | ||
let TemplateDependent = 1; | ||
let ParseArgumentsAsUnevaluated = 1; | ||
let InheritEvenIfAlreadyPresent = 1; | ||
|
@@ -3603,7 +3646,7 @@ def AcquiredBefore : InheritableAttr { | |
def AssertExclusiveLock : InheritableAttr { | ||
let Spellings = [GNU<"assert_exclusive_lock">]; | ||
let Args = [VariadicExprArgument<"Args">]; | ||
let LateParsed = 1; | ||
let LateParsed = LateAttrParseStandard; | ||
let TemplateDependent = 1; | ||
let ParseArgumentsAsUnevaluated = 1; | ||
let InheritEvenIfAlreadyPresent = 1; | ||
|
@@ -3614,7 +3657,7 @@ def AssertExclusiveLock : InheritableAttr { | |
def AssertSharedLock : InheritableAttr { | ||
let Spellings = [GNU<"assert_shared_lock">]; | ||
let Args = [VariadicExprArgument<"Args">]; | ||
let LateParsed = 1; | ||
let LateParsed = LateAttrParseStandard; | ||
let TemplateDependent = 1; | ||
let ParseArgumentsAsUnevaluated = 1; | ||
let InheritEvenIfAlreadyPresent = 1; | ||
|
@@ -3627,7 +3670,7 @@ def AssertSharedLock : InheritableAttr { | |
def ExclusiveTrylockFunction : InheritableAttr { | ||
let Spellings = [GNU<"exclusive_trylock_function">]; | ||
let Args = [ExprArgument<"SuccessValue">, VariadicExprArgument<"Args">]; | ||
let LateParsed = 1; | ||
let LateParsed = LateAttrParseStandard; | ||
let TemplateDependent = 1; | ||
let ParseArgumentsAsUnevaluated = 1; | ||
let InheritEvenIfAlreadyPresent = 1; | ||
|
@@ -3640,7 +3683,7 @@ def ExclusiveTrylockFunction : InheritableAttr { | |
def SharedTrylockFunction : InheritableAttr { | ||
let Spellings = [GNU<"shared_trylock_function">]; | ||
let Args = [ExprArgument<"SuccessValue">, VariadicExprArgument<"Args">]; | ||
let LateParsed = 1; | ||
let LateParsed = LateAttrParseStandard; | ||
let TemplateDependent = 1; | ||
let ParseArgumentsAsUnevaluated = 1; | ||
let InheritEvenIfAlreadyPresent = 1; | ||
|
@@ -3651,7 +3694,7 @@ def SharedTrylockFunction : InheritableAttr { | |
def LockReturned : InheritableAttr { | ||
let Spellings = [GNU<"lock_returned">]; | ||
let Args = [ExprArgument<"Arg">]; | ||
let LateParsed = 1; | ||
let LateParsed = LateAttrParseStandard; | ||
let TemplateDependent = 1; | ||
let ParseArgumentsAsUnevaluated = 1; | ||
let Subjects = SubjectList<[Function]>; | ||
|
@@ -3661,7 +3704,7 @@ def LockReturned : InheritableAttr { | |
def LocksExcluded : InheritableAttr { | ||
let Spellings = [GNU<"locks_excluded">]; | ||
let Args = [VariadicExprArgument<"Args">]; | ||
let LateParsed = 1; | ||
let LateParsed = LateAttrParseStandard; | ||
let TemplateDependent = 1; | ||
let ParseArgumentsAsUnevaluated = 1; | ||
let InheritEvenIfAlreadyPresent = 1; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
// RUN: %clang %s -c -fexperimental-late-parse-attributes 2>&1 -### | FileCheck %s -check-prefix=CHECK-ON | ||
// RUN: %clang %s -c -fno-experimental-late-parse-attributes -fexperimental-late-parse-attributes 2>&1 -### | FileCheck %s -check-prefix=CHECK-ON | ||
|
||
// CHECK-ON: -cc1 | ||
// CHECK-ON: -fexperimental-late-parse-attributes | ||
|
||
// RUN: %clang %s -c 2>&1 -### | FileCheck %s -check-prefix=CHECK-OFF | ||
// RUN: %clang %s -c -fno-experimental-late-parse-attributes 2>&1 -### | FileCheck %s -check-prefix=CHECK-OFF | ||
// RUN: %clang %s -c -fexperimental-late-parse-attributes -fno-experimental-late-parse-attributes 2>&1 -### | FileCheck %s -check-prefix=CHECK-OFF | ||
|
||
// CHECK-OFF: -cc1 | ||
// CHECK-OFF-NOT: -fexperimental-late-parse-attributes |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@AaronBallman I added some documentation on the new flag. It's a bit vague right now but I'll make it more specific when the first use of
LateAttrParseExperimentalExt
is added.