Skip to content

Commit cddbcd1

Browse files
authored
[flang][preprocessor] Expand some keyword macros in quoted character … (#96987)
…literals To help port codes from compilers using pre-ANSI C preprocessors, which didn't care much about context when replacing macros, support the replacement of keyword macros in quoted character literals when (and only when) the name of the keyword macro constitutes the entire significant portion of a free form continuation line. See the new test case for a motivating example. Fixes #96781.
1 parent a4c1813 commit cddbcd1

File tree

2 files changed

+49
-0
lines changed

2 files changed

+49
-0
lines changed

flang/lib/Parser/prescan.cpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -820,6 +820,41 @@ void Prescanner::QuotedCharacterLiteral(
820820
}
821821
break;
822822
}
823+
// Here's a weird edge case. When there's a two or more following
824+
// continuation lines at this point, and the entire significant part of
825+
// the next continuation line is the name of a keyword macro, replace
826+
// it in the character literal with its definition. Example:
827+
// #define FOO foo
828+
// subroutine subr() bind(c, name="my_&
829+
// &FOO&
830+
// &_bar") ...
831+
// produces a binding name of "my_foo_bar".
832+
while (at_[1] == '&' && nextLine_ < limit_ && !InFixedFormSource()) {
833+
const char *idStart{nextLine_};
834+
if (const char *amper{SkipWhiteSpace(nextLine_)}; *amper == '&') {
835+
idStart = amper + 1;
836+
}
837+
if (IsLegalIdentifierStart(*idStart)) {
838+
std::size_t idLen{1};
839+
for (; IsLegalInIdentifier(idStart[idLen]); ++idLen) {
840+
}
841+
if (idStart[idLen] == '&') {
842+
CharBlock id{idStart, idLen};
843+
if (preprocessor_.IsNameDefined(id)) {
844+
TokenSequence ppTokens;
845+
ppTokens.Put(id, GetProvenance(idStart));
846+
if (auto replaced{
847+
preprocessor_.MacroReplacement(ppTokens, *this)}) {
848+
tokens.Put(*replaced);
849+
at_ = &idStart[idLen - 1];
850+
NextLine();
851+
continue; // try again on the next line
852+
}
853+
}
854+
}
855+
}
856+
break;
857+
}
823858
end = at_ + 1;
824859
NextChar();
825860
if (*at_ == quote && !isEscaped) {
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
! RUN: %flang -E %s 2>&1 | FileCheck %s
2+
! CHECK: subroutine test_b_wrapper_c() bind(C, name="test_b_c_f")
3+
#define TEMP_LETTER b
4+
#define VAL c
5+
subroutine test_&
6+
TEMP_LETTER&
7+
_wrapper_&
8+
VAL&
9+
() bind(C, name="test_&
10+
&TEMP_LETTER&
11+
&_&
12+
&VAL&
13+
&_f")
14+
end

0 commit comments

Comments
 (0)