[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') {
|
if (char ed{ToLowerCaseLetter(*at_)}; ed == 'e' || ed == 'd') {
|
||||||
// Do some look-ahead to ensure that this 'e'/'d' is an exponent,
|
// Do some look-ahead to ensure that this 'e'/'d' is an exponent,
|
||||||
// not the start of an identifier that could be a macro.
|
// not the start of an identifier that could be a macro.
|
||||||
const char *p{SkipWhiteSpace(at_ + 1)};
|
const char *startAt{at_};
|
||||||
if (*p == '+' || *p == '-') {
|
int startColumn{column_};
|
||||||
p = SkipWhiteSpace(p + 1);
|
TokenSequence possible;
|
||||||
|
EmitCharAndAdvance(possible, *at_);
|
||||||
|
if (*at_ == '+' || *at_ == '-') {
|
||||||
|
EmitCharAndAdvance(possible, *at_);
|
||||||
}
|
}
|
||||||
if (IsDecimalDigit(*p)) { // it's an exponent
|
if (IsDecimalDigit(*at_)) { // it's an exponent; scan it
|
||||||
EmitCharAndAdvance(tokens, ed);
|
|
||||||
if (*at_ == '+' || *at_ == '-') {
|
|
||||||
EmitCharAndAdvance(tokens, *at_);
|
|
||||||
}
|
|
||||||
while (IsDecimalDigit(*at_)) {
|
while (IsDecimalDigit(*at_)) {
|
||||||
EmitCharAndAdvance(tokens, *at_);
|
EmitCharAndAdvance(possible, *at_);
|
||||||
}
|
}
|
||||||
|
possible.CloseToken();
|
||||||
|
tokens.CloseToken();
|
||||||
|
tokens.Put(possible);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
// Not an exponent; backtrack
|
||||||
|
at_ = startAt;
|
||||||
|
column_ = startColumn;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Prescanner::HandleKindSuffix(TokenSequence &tokens) {
|
bool Prescanner::HandleKindSuffix(TokenSequence &tokens) {
|
||||||
if (*at_ == '_' && IsLegalInIdentifier(at_[1])) {
|
if (*at_ != '_') {
|
||||||
// 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 {
|
|
||||||
return false;
|
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) {
|
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