Skip to content

Commit bf1b6fb

Browse files
Shriiraz KukatlaShriiraz Kukatla
authored andcommitted
[clang] Add support for optional func-name argument in #pragma init_seg
This patch implements parsing of the optional [, func-name] argument of MSVC's #pragma init_seg directive. The function identifier is now parsed and stored in Sema, matching MSVC's accepted syntax. No behavior changes to code generation yet. Fixes the FIXME comment in ParsePragma.cpp. Signed-off-by: Shriiraz Kukatla <[email protected]>
1 parent 3226a5f commit bf1b6fb

File tree

5 files changed

+55
-9
lines changed

5 files changed

+55
-9
lines changed

clang/include/clang/Sema/Sema.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2075,6 +2075,10 @@ class Sema final : public SemaBase {
20752075
/// Last section used with #pragma init_seg.
20762076
StringLiteral *CurInitSeg;
20772077
SourceLocation CurInitSegLoc;
2078+
/// Optional function name provided to #pragma init_seg([seg][, func-name]).
2079+
/// When present, stores the IdentifierInfo and its location.
2080+
IdentifierInfo *CurInitSegFn;
2081+
SourceLocation CurInitSegFnLoc;
20782082

20792083
/// Sections used with #pragma alloc_text.
20802084
llvm::StringMap<std::tuple<StringRef, SourceLocation>> FunctionToSectionMap;
@@ -2245,8 +2249,12 @@ class Sema final : public SemaBase {
22452249
StringLiteral *SegmentName);
22462250

22472251
/// Called on well-formed \#pragma init_seg().
2252+
/// If a function name is provided (", func-name"), it will be passed
2253+
/// via Func and FuncLoc.
22482254
void ActOnPragmaMSInitSeg(SourceLocation PragmaLocation,
2249-
StringLiteral *SegmentName);
2255+
StringLiteral *SegmentName,
2256+
IdentifierInfo *Func = nullptr,
2257+
SourceLocation FuncLoc = SourceLocation());
22502258

22512259
/// Called on well-formed \#pragma alloc_text().
22522260
void ActOnPragmaMSAllocText(

clang/lib/Parse/ParsePragma.cpp

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1229,6 +1229,11 @@ bool Parser::HandlePragmaMSInitSeg(StringRef PragmaName,
12291229

12301230
// Parse either the known section names or the string section name.
12311231
StringLiteral *SegmentName = nullptr;
1232+
// Optional function identifier provided as the second argument to
1233+
// #pragma init_seg([segment][, func-name]). Declared here so it's in scope
1234+
// for the call to ActOnPragmaMSInitSeg below.
1235+
IdentifierInfo *FuncII = nullptr;
1236+
SourceLocation FuncLoc;
12321237
if (Tok.isAnyIdentifier()) {
12331238
auto *II = Tok.getIdentifierInfo();
12341239
StringRef Section = llvm::StringSwitch<StringRef>(II->getName())
@@ -1259,7 +1264,31 @@ bool Parser::HandlePragmaMSInitSeg(StringRef PragmaName,
12591264
<< PragmaName;
12601265
return false;
12611266
}
1262-
// FIXME: Add support for the '[, func-name]' part of the pragma.
1267+
// Nothing else here; the optional ', func-name' (if present) will be
1268+
// parsed after the segment parsing so it works whether the segment was
1269+
// specified as a known identifier or as a string literal.
1270+
}
1271+
1272+
// After parsing the segment name (either via identifier mapping or a
1273+
// string literal), optionally parse a comma and an identifier naming the
1274+
// helper function to be used in place of atexit.
1275+
// Only consume the comma if an identifier follows; otherwise leave it
1276+
// for ExpectAndConsume(tok::r_paren) to report the error naturally (e.g.,
1277+
// for malformed pragmas like #pragma init_seg("a", "b")).
1278+
if (Tok.is(tok::comma)) {
1279+
// Save current token state for potential backtrack.
1280+
Token SavedTok = Tok;
1281+
PP.Lex(Tok); // tentatively consume comma
1282+
if (Tok.is(tok::identifier)) {
1283+
// The comma is followed by an identifier; keep both consumed.
1284+
FuncII = Tok.getIdentifierInfo();
1285+
FuncLoc = Tok.getLocation();
1286+
PP.Lex(Tok); // consume identifier and move to next token
1287+
} else {
1288+
// Not an identifier after comma; restore and don't consume the comma.
1289+
// The r_paren check below will produce the expected diagnostics.
1290+
Tok = SavedTok;
1291+
}
12631292
}
12641293

12651294
if (!SegmentName) {
@@ -1273,7 +1302,8 @@ bool Parser::HandlePragmaMSInitSeg(StringRef PragmaName,
12731302
PragmaName))
12741303
return false;
12751304

1276-
Actions.ActOnPragmaMSInitSeg(PragmaLocation, SegmentName);
1305+
Actions.ActOnPragmaMSInitSeg(PragmaLocation, SegmentName, FuncII,
1306+
FuncLoc);
12771307
return true;
12781308
}
12791309

clang/lib/Sema/Sema.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -313,7 +313,7 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
313313
DataSegStack(nullptr), BSSSegStack(nullptr), ConstSegStack(nullptr),
314314
CodeSegStack(nullptr), StrictGuardStackCheckStack(false),
315315
FpPragmaStack(FPOptionsOverride()), CurInitSeg(nullptr),
316-
VisContext(nullptr), PragmaAttributeCurrentTargetDecl(nullptr),
316+
CurInitSegFn(nullptr), CurInitSegFnLoc(), VisContext(nullptr), PragmaAttributeCurrentTargetDecl(nullptr),
317317
StdCoroutineTraitsCache(nullptr), IdResolver(pp),
318318
OriginalLexicalContext(nullptr), StdInitializerList(nullptr),
319319
StdTypeIdentity(nullptr),

clang/lib/Sema/SemaAttr.cpp

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -888,12 +888,17 @@ void Sema::ActOnPragmaMSSection(SourceLocation PragmaLocation,
888888
}
889889

890890
void Sema::ActOnPragmaMSInitSeg(SourceLocation PragmaLocation,
891-
StringLiteral *SegmentName) {
892-
// There's no stack to maintain, so we just have a current section. When we
893-
// see the default section, reset our current section back to null so we stop
894-
// tacking on unnecessary attributes.
895-
CurInitSeg = SegmentName->getString() == ".CRT$XCU" ? nullptr : SegmentName;
891+
StringLiteral *SegmentName,
892+
IdentifierInfo *Func,
893+
SourceLocation FuncLoc) {
894+
895+
// When we see the default section, reset back to null.
896+
CurInitSeg = (SegmentName->getString() == ".CRT$XCU") ? nullptr : SegmentName;
896897
CurInitSegLoc = PragmaLocation;
898+
899+
// Store optional function identifier (may be null).
900+
CurInitSegFn = Func;
901+
CurInitSegFnLoc = Func ? FuncLoc : SourceLocation();
897902
}
898903

899904
void Sema::ActOnPragmaMSAllocText(

clang/test/SemaCXX/pragma-init_seg.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@
1717
#pragma init_seg("a" L"b") // expected-warning {{expected non-wide string literal in '#pragma init_seg'}}
1818

1919
#pragma init_seg(compiler)
20+
// Test optional func-name parsing: declare an identifier and use it.
21+
int myexit();
22+
#pragma init_seg(compiler, myexit)
2023
#else
2124
#pragma init_seg(compiler) // expected-warning {{'#pragma init_seg' is only supported when targeting a Microsoft environment}}
2225
#endif

0 commit comments

Comments
 (0)