diff options
author | Dan Liew <delcypher@gmail.com> | 2024-04-29 18:37:47 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-04-29 18:37:47 -0700 |
commit | b1867e18c346e9621e14270bea2d1acb7d2a9ce0 (patch) | |
tree | 8cd8ccb6ecd6bc41012388d2ed1c5d16cc4051e3 /clang/lib/Parse/ParseDecl.cpp | |
parent | 65ee8f10b2017349b7742843fbe4accb172736e9 (diff) | |
download | llvm-b1867e18c346e9621e14270bea2d1acb7d2a9ce0.zip llvm-b1867e18c346e9621e14270bea2d1acb7d2a9ce0.tar.gz llvm-b1867e18c346e9621e14270bea2d1acb7d2a9ce0.tar.bz2 |
[Attributes] Support Attributes being declared as supporting an experimental late parsing mode "extension" (#88596)
This patch changes the `LateParsed` field of `Attr` in `Attr.td` to be
an instantiation of the new `LateAttrParseKind` class. The instation can be one of the following:
* `LateAttrParsingNever` - Corresponds with the false value of `LateParsed` prior to this patch (the default for an attribute).
* `LateAttrParseStandard` - Corresponds with the true value of `LateParsed` prior to this patch.
* `LateAttrParseExperimentalExt` - A new mode described below.
`LateAttrParseExperimentalExt` is an experimental extension to
`LateAttrParseStandard`. Essentially this allows
`Parser::ParseGNUAttributes(...)` to distinguish between these cases:
1. Only `LateAttrParseExperimentalExt` attributes should be late parsed.
2. Both `LateAttrParseExperimentalExt` and `LateAttrParseStandard`
attributes should be late parsed.
Callers (and indirect callers) of `Parser::ParseGNUAttributes(...)`
indicate the desired behavior by setting a flag in the
`LateParsedAttrList` object that is passed to the function.
In addition to the above, a new driver and frontend flag
(`-fexperimental-late-parse-attributes`) with a corresponding LangOpt
(`ExperimentalLateParseAttributes`) is added that changes how
`LateAttrParseExperimentalExt` attributes are parsed.
* When the flag is disabled (default), in cases where only
`LateAttrParsingExperimentalOnly` late parsing is requested, the
attribute will be parsed immediately (i.e. **NOT** late parsed). This
allows the attribute to act just like a `LateAttrParseStandard`
attribute when the flag is disabled.
* When the flag is enabled, in cases where only
`LateAttrParsingExperimentalOnly` late parsing is requested, the
attribute will be late parsed.
The motivation behind this change is to allow the new `counted_by`
attribute (part of `-fbounds-safety`) to support late parsing but
**only** when `-fexperimental-late-parse-attributes` is enabled. This
attribute needs to support late parsing to allow it to refer to fields
later in a struct definition (or function parameters declared later).
However, there isn't a precedent for supporting late attribute parsing
in C so this flag allows the new behavior to exist in Clang but not be
on by default. This behavior was requested as part of the
`-fbounds-safety` RFC process
(https://discourse.llvm.org/t/rfc-enforcing-bounds-safety-in-c-fbounds-safety/70854/68).
This patch doesn't introduce any uses of `LateAttrParseExperimentalExt`.
This will be added for the `counted_by` attribute in a future patch
(https://github.com/llvm/llvm-project/pull/87596). A consequence is the
new behavior added in this patch is not yet testable. Hence, the lack of
tests covering the new behavior.
rdar://125400257
Diffstat (limited to 'clang/lib/Parse/ParseDecl.cpp')
-rw-r--r-- | clang/lib/Parse/ParseDecl.cpp | 40 |
1 files changed, 34 insertions, 6 deletions
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index a7846e1..7431c25 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -91,13 +91,23 @@ static StringRef normalizeAttrName(StringRef Name) { return Name; } -/// isAttributeLateParsed - Return true if the attribute has arguments that -/// require late parsing. -static bool isAttributeLateParsed(const IdentifierInfo &II) { +/// returns true iff attribute is annotated with `LateAttrParseExperimentalExt` +/// in `Attr.td`. +static bool IsAttributeLateParsedExperimentalExt(const IdentifierInfo &II) { +#define CLANG_ATTR_LATE_PARSED_EXPERIMENTAL_EXT_LIST + return llvm::StringSwitch<bool>(normalizeAttrName(II.getName())) +#include "clang/Parse/AttrParserStringSwitches.inc" + .Default(false); +#undef CLANG_ATTR_LATE_PARSED_EXPERIMENTAL_EXT_LIST +} + +/// returns true iff attribute is annotated with `LateAttrParseStandard` in +/// `Attr.td`. +static bool IsAttributeLateParsedStandard(const IdentifierInfo &II) { #define CLANG_ATTR_LATE_PARSED_LIST - return llvm::StringSwitch<bool>(normalizeAttrName(II.getName())) + return llvm::StringSwitch<bool>(normalizeAttrName(II.getName())) #include "clang/Parse/AttrParserStringSwitches.inc" - .Default(false); + .Default(false); #undef CLANG_ATTR_LATE_PARSED_LIST } @@ -222,8 +232,26 @@ void Parser::ParseGNUAttributes(ParsedAttributes &Attrs, continue; } + bool LateParse = false; + if (!LateAttrs) + LateParse = false; + else if (LateAttrs->lateAttrParseExperimentalExtOnly()) { + // The caller requested that this attribute **only** be late + // parsed for `LateAttrParseExperimentalExt` attributes. This will + // only be late parsed if the experimental language option is enabled. + LateParse = getLangOpts().ExperimentalLateParseAttributes && + IsAttributeLateParsedExperimentalExt(*AttrName); + } else { + // The caller did not restrict late parsing to only + // `LateAttrParseExperimentalExt` attributes so late parse + // both `LateAttrParseStandard` and `LateAttrParseExperimentalExt` + // attributes. + LateParse = IsAttributeLateParsedExperimentalExt(*AttrName) || + IsAttributeLateParsedStandard(*AttrName); + } + // Handle "parameterized" attributes - if (!LateAttrs || !isAttributeLateParsed(*AttrName)) { + if (!LateParse) { ParseGNUAttributeArgs(AttrName, AttrNameLoc, Attrs, &EndLoc, nullptr, SourceLocation(), ParsedAttr::Form::GNU(), D); continue; |