[flang] Rework preprocessor fix for replacement in kind suffixes (#135406)
Recent work to better handle macro replacement in literal constant kind suffixes isn't handling fixed form well, leading to a crash in Fujitsu test 0113/0113_0073.F. The look-ahead needs to be done with the higher-level prescanner functions that skip over fixed form comment fields after column 72. Rework.
This commit is contained in:
parent
da6f493d4a
commit
dba757a33c
@ -891,51 +891,57 @@ bool Prescanner::HandleExponent(TokenSequence &tokens) {
|
||||
if (char ed{ToLowerCaseLetter(*at_)}; ed == 'e' || ed == 'd') {
|
||||
// Do some look-ahead to ensure that this 'e'/'d' is an exponent,
|
||||
// not the start of an identifier that could be a macro.
|
||||
const char *p{SkipWhiteSpace(at_ + 1)};
|
||||
if (*p == '+' || *p == '-') {
|
||||
p = SkipWhiteSpace(p + 1);
|
||||
const char *startAt{at_};
|
||||
int startColumn{column_};
|
||||
TokenSequence possible;
|
||||
EmitCharAndAdvance(possible, *at_);
|
||||
if (*at_ == '+' || *at_ == '-') {
|
||||
EmitCharAndAdvance(possible, *at_);
|
||||
}
|
||||
if (IsDecimalDigit(*p)) { // it's an exponent
|
||||
EmitCharAndAdvance(tokens, ed);
|
||||
if (*at_ == '+' || *at_ == '-') {
|
||||
EmitCharAndAdvance(tokens, *at_);
|
||||
}
|
||||
if (IsDecimalDigit(*at_)) { // it's an exponent; scan it
|
||||
while (IsDecimalDigit(*at_)) {
|
||||
EmitCharAndAdvance(tokens, *at_);
|
||||
EmitCharAndAdvance(possible, *at_);
|
||||
}
|
||||
possible.CloseToken();
|
||||
tokens.CloseToken();
|
||||
tokens.Put(possible);
|
||||
return true;
|
||||
}
|
||||
// Not an exponent; backtrack
|
||||
at_ = startAt;
|
||||
column_ = startColumn;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Prescanner::HandleKindSuffix(TokenSequence &tokens) {
|
||||
if (*at_ == '_' && IsLegalInIdentifier(at_[1])) {
|
||||
// The kind specifier might be a macro (with or without its leading
|
||||
// underscore); put it into its own token if it has been defined.
|
||||
const char *p{at_ + 1};
|
||||
while (IsLegalInIdentifier(*++p)) {
|
||||
}
|
||||
if (CharBlock id{at_, static_cast<std::size_t>(p - at_)};
|
||||
preprocessor_.IsNameDefined(id)) {
|
||||
// In 1.0e0_foo, "_foo" is a defined name; retain the
|
||||
// underscore
|
||||
tokens.CloseToken();
|
||||
} else {
|
||||
EmitCharAndAdvance(tokens, '_');
|
||||
if (CharBlock id{at_, static_cast<std::size_t>(p - at_)};
|
||||
preprocessor_.IsNameDefined(id)) {
|
||||
// In 1.0e0_foo, "foo" is a defined name
|
||||
tokens.CloseToken();
|
||||
}
|
||||
}
|
||||
while (IsLegalInIdentifier(*at_)) {
|
||||
EmitCharAndAdvance(tokens, *at_);
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
if (*at_ != '_') {
|
||||
return false;
|
||||
}
|
||||
TokenSequence withUnderscore, separate;
|
||||
EmitChar(withUnderscore, '_');
|
||||
EmitCharAndAdvance(separate, '_');
|
||||
if (IsLegalInIdentifier(*at_)) {
|
||||
separate.CloseToken();
|
||||
EmitChar(withUnderscore, *at_);
|
||||
EmitCharAndAdvance(separate, *at_);
|
||||
while (IsLegalInIdentifier(*at_)) {
|
||||
EmitChar(withUnderscore, *at_);
|
||||
EmitCharAndAdvance(separate, *at_);
|
||||
}
|
||||
}
|
||||
withUnderscore.CloseToken();
|
||||
separate.CloseToken();
|
||||
tokens.CloseToken();
|
||||
if (separate.SizeInTokens() == 2 &&
|
||||
preprocessor_.IsNameDefined(separate.TokenAt(1)) &&
|
||||
!preprocessor_.IsNameDefined(withUnderscore.ToCharBlock())) {
|
||||
// "_foo" is not defined, but "foo" is
|
||||
tokens.Put(separate); // '_' "foo"
|
||||
} else {
|
||||
tokens.Put(withUnderscore); // "_foo"
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Prescanner::HandleExponentAndOrKindSuffix(TokenSequence &tokens) {
|
||||
|
5
flang/test/Preprocessing/bug518.F
Normal file
5
flang/test/Preprocessing/bug518.F
Normal file
@ -0,0 +1,5 @@
|
||||
! RUN: %flang -fc1 -fdebug-unparse %s 2>&1 | FileCheck %s
|
||||
! CHECK: k=1_4
|
||||
k= 1_99999999
|
||||
&4
|
||||
end
|
Loading…
x
Reference in New Issue
Block a user