Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[flang] Allow macro replacement in numeric kind suffix #132120

Merged
merged 1 commit into from
Mar 26, 2025

Conversation

klausler
Copy link
Contributor

When a numeric value has a kind suffix containing an identifier, allow macro replacement for that identifier by treating it as its own token.

Fixes #131548.

@llvmbot llvmbot added flang Flang issues not falling into any other category flang:parser labels Mar 19, 2025
@llvmbot
Copy link
Member

llvmbot commented Mar 19, 2025

@llvm/pr-subscribers-flang-parser

Author: Peter Klausler (klausler)

Changes

When a numeric value has a kind suffix containing an identifier, allow macro replacement for that identifier by treating it as its own token.

Fixes #131548.


Full diff: https://github.com/llvm/llvm-project/pull/132120.diff

3 Files Affected:

  • (modified) flang/lib/Parser/prescan.cpp (+39-27)
  • (modified) flang/lib/Parser/prescan.h (+3-1)
  • (added) flang/test/Preprocessing/kind-suffix.F90 (+6)
diff --git a/flang/lib/Parser/prescan.cpp b/flang/lib/Parser/prescan.cpp
index b4ac82839b73f..c91a6b7c9742c 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,33 +839,36 @@ 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_);
-    }
-    while (IsDecimalDigit(*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();
     }
-    if (*at_ == '_') {
-      while (IsLegalInIdentifier(EmitCharAndAdvance(tokens, *at_))) {
-      }
+    while (IsLegalInIdentifier(EmitCharAndAdvance(tokens, *at_))) {
     }
     return true;
   } else {
@@ -873,6 +876,15 @@ bool Prescanner::ExponentAndKind(TokenSequence &tokens) {
   }
 }
 
+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

When a numeric value has a kind suffix containing an identifier,
allow macro replacement for that identifier by treating it as its
own token.

Fixes llvm#131548.
@klausler klausler merged commit f3991e1 into llvm:main Mar 26, 2025
11 checks passed
@klausler klausler deleted the bug131548 branch March 26, 2025 19:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
flang:parser flang Flang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Flang] Preprocessor does not work correctly in int-literal-constant
3 participants