diff --git a/flang/lib/Parser/prescan.cpp b/flang/lib/Parser/prescan.cpp index b4ac82839b73f..0df1e3e291923 100644 --- a/flang/lib/Parser/prescan.cpp +++ b/flang/lib/Parser/prescan.cpp @@ -720,8 +720,8 @@ bool Prescanner::NextToken(TokenSequence &tokens) { } else if (*at_ == '.') { while (IsDecimalDigit(EmitCharAndAdvance(tokens, *at_))) { } - ExponentAndKind(tokens); - } else if (ExponentAndKind(tokens)) { + HandleExponentAndOrKindSuffix(tokens); + } else if (HandleExponentAndOrKindSuffix(tokens)) { } else if (digits == 1 && n == 0 && (*at_ == 'x' || *at_ == 'X') && inPreprocessorDirective_) { do { @@ -743,7 +743,7 @@ bool Prescanner::NextToken(TokenSequence &tokens) { if (!inPreprocessorDirective_ && IsDecimalDigit(nch)) { while (IsDecimalDigit(EmitCharAndAdvance(tokens, *at_))) { } - ExponentAndKind(tokens); + HandleExponentAndOrKindSuffix(tokens); } else if (nch == '.' && EmitCharAndAdvance(tokens, '.') == '.') { EmitCharAndAdvance(tokens, '.'); // variadic macro definition ellipsis } @@ -839,40 +839,53 @@ bool Prescanner::NextToken(TokenSequence &tokens) { return true; } -bool Prescanner::ExponentAndKind(TokenSequence &tokens) { - char ed{ToLowerCaseLetter(*at_)}; - if (ed != 'e' && ed != 'd') { - return false; - } - // 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{at_}; - if (int n{IsSpace(++p)}) { - p += n; - } - if (*p == '+' || *p == '-') { - if (int n{IsSpace(++p)}) { - p += n; +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); + } + if (IsDecimalDigit(*p)) { // it's an exponent + EmitCharAndAdvance(tokens, ed); + if (*at_ == '+' || *at_ == '-') { + EmitCharAndAdvance(tokens, *at_); + } + while (IsDecimalDigit(*at_)) { + EmitCharAndAdvance(tokens, *at_); + } + return true; } } - if (IsDecimalDigit(*p)) { // it's an exponent - EmitCharAndAdvance(tokens, ed); - if (*at_ == '+' || *at_ == '-') { - EmitCharAndAdvance(tokens, *at_); + return false; +} + +bool Prescanner::HandleKindSuffix(TokenSequence &tokens) { + if (*at_ == '_' && IsLegalInIdentifier(*SkipWhiteSpace(at_ + 1))) { + EmitCharAndAdvance(tokens, *at_); + if (IsLegalIdentifierStart(*at_)) { + // The kind specifier might be a macro, so put it into its own token. + tokens.CloseToken(); } - while (IsDecimalDigit(*at_)) { + while (IsLegalInIdentifier(*at_)) { EmitCharAndAdvance(tokens, *at_); } - if (*at_ == '_') { - while (IsLegalInIdentifier(EmitCharAndAdvance(tokens, *at_))) { - } - } return true; } else { return false; } } +bool Prescanner::HandleExponentAndOrKindSuffix(TokenSequence &tokens) { + bool hadExponent{HandleExponent(tokens)}; + if (HandleKindSuffix(tokens)) { + return true; + } else { + return hadExponent; + } +} + void Prescanner::QuotedCharacterLiteral( TokenSequence &tokens, const char *start) { char quote{*at_}; diff --git a/flang/lib/Parser/prescan.h b/flang/lib/Parser/prescan.h index 9cf1b389f5b19..53361ba14f378 100644 --- a/flang/lib/Parser/prescan.h +++ b/flang/lib/Parser/prescan.h @@ -186,7 +186,9 @@ class Prescanner { const char *SkipWhiteSpaceAndCComments(const char *) const; const char *SkipCComment(const char *) const; bool NextToken(TokenSequence &); - bool ExponentAndKind(TokenSequence &); + bool HandleExponent(TokenSequence &); + bool HandleKindSuffix(TokenSequence &); + bool HandleExponentAndOrKindSuffix(TokenSequence &); void QuotedCharacterLiteral(TokenSequence &, const char *start); void Hollerith(TokenSequence &, int count, const char *start); bool PadOutCharacterLiteral(TokenSequence &); diff --git a/flang/test/Preprocessing/kind-suffix.F90 b/flang/test/Preprocessing/kind-suffix.F90 new file mode 100644 index 0000000000000..36aa323630c6c --- /dev/null +++ b/flang/test/Preprocessing/kind-suffix.F90 @@ -0,0 +1,6 @@ +! RUN: %flang -E %s 2>&1 | FileCheck %s +#define n k +parameter(n=4) +!CHECK: print *,1_k +print *,1_n +end