-
Notifications
You must be signed in to change notification settings - Fork 15.2k
[clang] Add support for optional func-name argument in #pragma init_seg #167133
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
base: main
Are you sure you want to change the base?
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 |
|---|---|---|
|
|
@@ -2075,6 +2075,10 @@ class Sema final : public SemaBase { | |
| /// Last section used with #pragma init_seg. | ||
| StringLiteral *CurInitSeg; | ||
| SourceLocation CurInitSegLoc; | ||
| /// Optional function name provided to #pragma init_seg([seg][, func-name]). | ||
| /// When present, stores the IdentifierInfo and its location. | ||
| IdentifierInfo *CurInitSegFn; | ||
| SourceLocation CurInitSegFnLoc; | ||
|
|
||
| /// Sections used with #pragma alloc_text. | ||
| llvm::StringMap<std::tuple<StringRef, SourceLocation>> FunctionToSectionMap; | ||
|
|
@@ -2245,8 +2249,12 @@ class Sema final : public SemaBase { | |
| StringLiteral *SegmentName); | ||
|
|
||
| /// Called on well-formed \#pragma init_seg(). | ||
| /// If a function name is provided (", func-name"), it will be passed | ||
| /// via Func and FuncLoc. | ||
| void ActOnPragmaMSInitSeg(SourceLocation PragmaLocation, | ||
| StringLiteral *SegmentName); | ||
| StringLiteral *SegmentName, | ||
| IdentifierInfo *Func = nullptr, | ||
|
Collaborator
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. Just do an |
||
| SourceLocation FuncLoc = SourceLocation()); | ||
|
|
||
| /// Called on well-formed \#pragma alloc_text(). | ||
| void ActOnPragmaMSAllocText( | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1229,6 +1229,11 @@ bool Parser::HandlePragmaMSInitSeg(StringRef PragmaName, | |
|
|
||
| // Parse either the known section names or the string section name. | ||
| StringLiteral *SegmentName = nullptr; | ||
| // Optional function identifier provided as the second argument to | ||
| // #pragma init_seg([segment][, func-name]). Declared here so it's in scope | ||
| // for the call to ActOnPragmaMSInitSeg below. | ||
| IdentifierInfo *FuncII = nullptr; | ||
| SourceLocation FuncLoc; | ||
| if (Tok.isAnyIdentifier()) { | ||
| auto *II = Tok.getIdentifierInfo(); | ||
| StringRef Section = llvm::StringSwitch<StringRef>(II->getName()) | ||
|
|
@@ -1259,7 +1264,31 @@ bool Parser::HandlePragmaMSInitSeg(StringRef PragmaName, | |
| << PragmaName; | ||
| return false; | ||
| } | ||
| // FIXME: Add support for the '[, func-name]' part of the pragma. | ||
| // Nothing else here; the optional ', func-name' (if present) will be | ||
| // parsed after the segment parsing so it works whether the segment was | ||
| // specified as a known identifier or as a string literal. | ||
| } | ||
|
|
||
| // After parsing the segment name (either via identifier mapping or a | ||
| // string literal), optionally parse a comma and an identifier naming the | ||
| // helper function to be used in place of atexit. | ||
| // Only consume the comma if an identifier follows; otherwise leave it | ||
| // for ExpectAndConsume(tok::r_paren) to report the error naturally (e.g., | ||
| // for malformed pragmas like #pragma init_seg("a", "b")). | ||
| if (Tok.is(tok::comma)) { | ||
| // Save current token state for potential backtrack. | ||
| Token SavedTok = Tok; | ||
| PP.Lex(Tok); // tentatively consume comma | ||
| if (Tok.is(tok::identifier)) { | ||
| // The comma is followed by an identifier; keep both consumed. | ||
| FuncII = Tok.getIdentifierInfo(); | ||
| FuncLoc = Tok.getLocation(); | ||
| PP.Lex(Tok); // consume identifier and move to next token | ||
| } else { | ||
| // Not an identifier after comma; restore and don't consume the comma. | ||
| // The r_paren check below will produce the expected diagnostics. | ||
| Tok = SavedTok; | ||
|
Collaborator
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. I don't think you can do this, this will mess up any of our lexers that do look-ahead/etc. This is not something that is acceptable. Instead, just do a |
||
| } | ||
| } | ||
|
|
||
| if (!SegmentName) { | ||
|
|
@@ -1273,7 +1302,8 @@ bool Parser::HandlePragmaMSInitSeg(StringRef PragmaName, | |
| PragmaName)) | ||
| return false; | ||
|
|
||
| Actions.ActOnPragmaMSInitSeg(PragmaLocation, SegmentName); | ||
| Actions.ActOnPragmaMSInitSeg(PragmaLocation, SegmentName, FuncII, | ||
| FuncLoc); | ||
| return true; | ||
| } | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -888,12 +888,17 @@ void Sema::ActOnPragmaMSSection(SourceLocation PragmaLocation, | |
| } | ||
|
|
||
| void Sema::ActOnPragmaMSInitSeg(SourceLocation PragmaLocation, | ||
| StringLiteral *SegmentName) { | ||
| // There's no stack to maintain, so we just have a current section. When we | ||
| // see the default section, reset our current section back to null so we stop | ||
| // tacking on unnecessary attributes. | ||
| CurInitSeg = SegmentName->getString() == ".CRT$XCU" ? nullptr : SegmentName; | ||
| StringLiteral *SegmentName, | ||
| IdentifierInfo *Func, | ||
| SourceLocation FuncLoc) { | ||
|
|
||
| // When we see the default section, reset back to null. | ||
| CurInitSeg = (SegmentName->getString() == ".CRT$XCU") ? nullptr : SegmentName; | ||
| CurInitSegLoc = PragmaLocation; | ||
|
|
||
| // Store optional function identifier (may be null). | ||
| CurInitSegFn = Func; | ||
|
Collaborator
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. Where are these two used? What do they do? What is the purpose of storing/capturing them? |
||
| CurInitSegFnLoc = Func ? FuncLoc : SourceLocation(); | ||
| } | ||
|
|
||
| void Sema::ActOnPragmaMSAllocText( | ||
|
|
||
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.
Is there a reason that these and the above have to be separate? I would expect us to only be parsing 1x at a time, right? Could we combine all 4 into a single data structure?