[Git][ghc/ghc][master] Parser: be more careful when lexing extended literals (#25258)

Marge Bot (@marge-bot) gitlab at gitlab.haskell.org
Sat Sep 21 21:53:53 UTC 2024



Marge Bot pushed to branch master at Glasgow Haskell Compiler / GHC


Commits:
d7016e0d by Sylvain Henry at 2024-09-21T17:52:24-04:00
Parser: be more careful when lexing extended literals (#25258)

Previously we would lex invalid prefixes like "8#Int3" as [8#Int, 3].

A side-effect of this patch is that we now allow negative unsigned
extended literals. They trigger an overflow warning later anyway.

- - - - -


13 changed files:

- compiler/GHC/Data/StringBuffer.hs
- compiler/GHC/Parser/Lexer.x
- docs/users_guide/exts/extended_literals.rst
- + testsuite/tests/parser/should_compile/T25258.hs
- + testsuite/tests/parser/should_compile/T25258.stderr
- testsuite/tests/parser/should_compile/all.T
- + testsuite/tests/parser/should_fail/T25258a.hs
- + testsuite/tests/parser/should_fail/T25258a.stderr
- + testsuite/tests/parser/should_fail/T25258b.hs
- + testsuite/tests/parser/should_fail/T25258b.stderr
- + testsuite/tests/parser/should_fail/T25258c.hs
- + testsuite/tests/parser/should_fail/T25258c.stderr
- testsuite/tests/parser/should_fail/all.T


Changes:

=====================================
compiler/GHC/Data/StringBuffer.hs
=====================================
@@ -9,6 +9,7 @@ Buffers for scanning string input stored in external arrays.
 {-# LANGUAGE CPP #-}
 {-# LANGUAGE MagicHash #-}
 {-# LANGUAGE UnboxedTuples #-}
+{-# LANGUAGE LambdaCase #-}
 
 {-# OPTIONS_GHC -O2 #-}
 -- We always optimise this, otherwise performance of a non-optimised
@@ -47,6 +48,7 @@ module GHC.Data.StringBuffer
 
          -- * Parsing integers
         parseUnsignedInteger,
+        findHashOffset,
 
         -- * Checking for bi-directional format characters
         containsBidirectionalFormatChar,
@@ -417,3 +419,15 @@ parseUnsignedInteger (StringBuffer buf _ cur) len radix char_to_int
                '_'  -> go (i + 1) x    -- skip "_" (#14473)
                char -> go (i + 1) (x * radix + toInteger (char_to_int char))
   in go 0 0
+
+-- | Find the offset of the '#' character in the StringBuffer.
+--
+-- Make sure that it contains one before calling this function!
+findHashOffset :: StringBuffer -> Int
+findHashOffset (StringBuffer buf _ cur)
+  = inlinePerformIO $ withForeignPtr buf $ \ptr -> do
+      let
+        go p = peek p >>= \case
+          (0x23 :: Word8) -> pure $! ((p `minusPtr` ptr) - cur)
+          _               -> go (p `plusPtr` 1)
+      go (ptr `plusPtr` cur)


=====================================
compiler/GHC/Parser/Lexer.x
=====================================
@@ -562,6 +562,18 @@ $unigraphic / { isSmartQuote } { smart_quote_error }
   @octallit                 \# \# / { ifExtension MagicHashBit }        { tok_primword 2 4 octal }
   @hexadecimallit           \# \# / { ifExtension MagicHashBit }        { tok_primword 2 4 hexadecimal }
 
+  @decimal                  \# $idchar+  / { ifExtension ExtendedLiteralsBit } { tok_prim_num_ext positive 0 decimal }
+  @binarylit                \# $idchar+  / { ifExtension ExtendedLiteralsBit `alexAndPred`
+                                             ifExtension BinaryLiteralsBit }   { tok_prim_num_ext positive 2 binary }
+  @octallit                 \# $idchar+  / { ifExtension ExtendedLiteralsBit } { tok_prim_num_ext positive 2 octal }
+  @hexadecimallit           \# $idchar+  / { ifExtension ExtendedLiteralsBit } { tok_prim_num_ext positive 2 hexadecimal }
+  @negative @decimal        \# $idchar+  / { negHashLitPred ExtendedLiteralsBit } { tok_prim_num_ext negative 1 decimal }
+  @negative @binarylit      \# $idchar+  / { negHashLitPred ExtendedLiteralsBit `alexAndPred`
+                                             ifExtension BinaryLiteralsBit }   { tok_prim_num_ext negative 3 binary }
+  @negative @octallit       \# $idchar+  / { negHashLitPred ExtendedLiteralsBit } { tok_prim_num_ext negative 3 octal }
+  @negative @hexadecimallit \# $idchar+  / { negHashLitPred ExtendedLiteralsBit } { tok_prim_num_ext negative 3 hexadecimal }
+
+
   -- Unboxed floats and doubles (:: Float#, :: Double#)
   -- prim_{float,double} work with signed literals
   @floating_point                  \# / { ifExtension MagicHashBit }        { tok_frac 1 tok_primfloat }
@@ -573,91 +585,6 @@ $unigraphic / { isSmartQuote } { smart_quote_error }
   @negative 0[xX] @numspc @hex_floating_point \# / { ifExtension HexFloatLiteralsBit `alexAndPred` negHashLitPred MagicHashBit } { tok_frac 1 tok_prim_hex_float }
   @negative 0[xX] @numspc @hex_floating_point \# \# / { ifExtension HexFloatLiteralsBit `alexAndPred` negHashLitPred MagicHashBit } { tok_frac 2 tok_prim_hex_double }
 
-  @decimal                  \#"Int8"   / { ifExtension ExtendedLiteralsBit } { tok_primint8 positive 0 decimal }
-  @binarylit                \#"Int8"   / { ifExtension ExtendedLiteralsBit `alexAndPred`
-                                           ifExtension BinaryLiteralsBit }   { tok_primint8 positive 2 binary }
-  @octallit                 \#"Int8"   / { ifExtension ExtendedLiteralsBit } { tok_primint8 positive 2 octal }
-  @hexadecimallit           \#"Int8"   / { ifExtension ExtendedLiteralsBit } { tok_primint8 positive 2 hexadecimal }
-  @negative @decimal        \#"Int8"   / { negHashLitPred ExtendedLiteralsBit } { tok_primint8 negative 1 decimal }
-  @negative @binarylit      \#"Int8"   / { negHashLitPred ExtendedLiteralsBit `alexAndPred`
-                                           ifExtension BinaryLiteralsBit }   { tok_primint8 negative 3 binary }
-  @negative @octallit       \#"Int8"   / { negHashLitPred ExtendedLiteralsBit } { tok_primint8 negative 3 octal }
-  @negative @hexadecimallit \#"Int8"   / { negHashLitPred ExtendedLiteralsBit } { tok_primint8 negative 3 hexadecimal }
-
-  @decimal                  \#"Int16"  / { ifExtension ExtendedLiteralsBit } { tok_primint16 positive 0 decimal }
-  @binarylit                \#"Int16"  / { ifExtension ExtendedLiteralsBit `alexAndPred`
-                                           ifExtension BinaryLiteralsBit }   { tok_primint16 positive 2 binary }
-  @octallit                 \#"Int16"  / { ifExtension ExtendedLiteralsBit } { tok_primint16 positive 2 octal }
-  @hexadecimallit           \#"Int16"  / { ifExtension ExtendedLiteralsBit } { tok_primint16 positive 2 hexadecimal }
-  @negative @decimal        \#"Int16"  / { negHashLitPred ExtendedLiteralsBit} { tok_primint16 negative 1 decimal }
-  @negative @binarylit      \#"Int16"  / { negHashLitPred ExtendedLiteralsBit `alexAndPred`
-                                           ifExtension BinaryLiteralsBit }   { tok_primint16 negative 3 binary }
-  @negative @octallit       \#"Int16"  / { negHashLitPred ExtendedLiteralsBit} { tok_primint16 negative 3 octal }
-  @negative @hexadecimallit \#"Int16"  / { negHashLitPred ExtendedLiteralsBit} { tok_primint16 negative 3 hexadecimal }
-
-  @decimal                  \#"Int32"  / { ifExtension ExtendedLiteralsBit } { tok_primint32 positive 0 decimal }
-  @binarylit                \#"Int32"  / { ifExtension ExtendedLiteralsBit `alexAndPred`
-                                           ifExtension BinaryLiteralsBit }   { tok_primint32 positive 2 binary }
-  @octallit                 \#"Int32"  / { ifExtension ExtendedLiteralsBit } { tok_primint32 positive 2 octal }
-  @hexadecimallit           \#"Int32"  / { ifExtension ExtendedLiteralsBit } { tok_primint32 positive 2 hexadecimal }
-  @negative @decimal        \#"Int32"  / { negHashLitPred ExtendedLiteralsBit } { tok_primint32 negative 1 decimal }
-  @negative @binarylit      \#"Int32"  / { negHashLitPred ExtendedLiteralsBit `alexAndPred`
-                                           ifExtension BinaryLiteralsBit }   { tok_primint32 negative 3 binary }
-  @negative @octallit       \#"Int32"  / { negHashLitPred ExtendedLiteralsBit} { tok_primint32 negative 3 octal }
-  @negative @hexadecimallit \#"Int32"  / { negHashLitPred ExtendedLiteralsBit} { tok_primint32 negative 3 hexadecimal }
-
-  @decimal                  \#"Int64"  / { ifExtension ExtendedLiteralsBit } { tok_primint64 positive 0 decimal }
-  @binarylit                \#"Int64"  / { ifExtension ExtendedLiteralsBit `alexAndPred`
-                                           ifExtension BinaryLiteralsBit }   { tok_primint64 positive 2 binary }
-  @octallit                 \#"Int64"  / { ifExtension ExtendedLiteralsBit } { tok_primint64 positive 2 octal }
-  @hexadecimallit           \#"Int64"  / { ifExtension ExtendedLiteralsBit } { tok_primint64 positive 2 hexadecimal }
-  @negative @decimal        \#"Int64"  / { negHashLitPred ExtendedLiteralsBit } { tok_primint64 negative 1 decimal }
-  @negative @binarylit      \#"Int64"  / { negHashLitPred ExtendedLiteralsBit `alexAndPred`
-                                           ifExtension BinaryLiteralsBit }   { tok_primint64 negative 3 binary }
-  @negative @octallit       \#"Int64"  / { negHashLitPred ExtendedLiteralsBit } { tok_primint64 negative 3 octal }
-  @negative @hexadecimallit \#"Int64"  / { negHashLitPred ExtendedLiteralsBit } { tok_primint64 negative 3 hexadecimal }
-
-  @decimal                  \#"Int"    / { ifExtension ExtendedLiteralsBit } { tok_primint positive 0 4 decimal }
-  @binarylit                \#"Int"    / { ifExtension ExtendedLiteralsBit `alexAndPred`
-                                           ifExtension BinaryLiteralsBit }   { tok_primint positive 2 6 binary }
-  @octallit                 \#"Int"    / { ifExtension ExtendedLiteralsBit } { tok_primint positive 2 6 octal }
-  @hexadecimallit           \#"Int"    / { ifExtension ExtendedLiteralsBit } { tok_primint positive 2 6 hexadecimal }
-  @negative @decimal        \#"Int"    / { negHashLitPred ExtendedLiteralsBit } { tok_primint negative 1 5 decimal }
-  @negative @binarylit      \#"Int"    / { negHashLitPred ExtendedLiteralsBit `alexAndPred`
-                                           ifExtension BinaryLiteralsBit }   { tok_primint negative 3 7 binary }
-  @negative @octallit       \#"Int"    / { negHashLitPred ExtendedLiteralsBit } { tok_primint negative 3 7 octal }
-  @negative @hexadecimallit \#"Int"    / { negHashLitPred ExtendedLiteralsBit } { tok_primint negative 3 7 hexadecimal }
-
-  @decimal                  \#"Word8"  / { ifExtension ExtendedLiteralsBit } { tok_primword8 0 decimal }
-  @binarylit                \#"Word8"  / { ifExtension ExtendedLiteralsBit `alexAndPred`
-                                           ifExtension BinaryLiteralsBit }   { tok_primword8 2 binary }
-  @octallit                 \#"Word8"  / { ifExtension ExtendedLiteralsBit } { tok_primword8 2 octal }
-  @hexadecimallit           \#"Word8"  / { ifExtension ExtendedLiteralsBit } { tok_primword8 2 hexadecimal }
-
-  @decimal                  \#"Word16" / { ifExtension ExtendedLiteralsBit } { tok_primword16 0 decimal }
-  @binarylit                \#"Word16" / { ifExtension ExtendedLiteralsBit `alexAndPred`
-                                           ifExtension BinaryLiteralsBit }   { tok_primword16 2 binary }
-  @octallit                 \#"Word16" / { ifExtension ExtendedLiteralsBit } { tok_primword16 2 octal }
-  @hexadecimallit           \#"Word16" / { ifExtension ExtendedLiteralsBit } { tok_primword16 2 hexadecimal }
-
-  @decimal                  \#"Word32" / { ifExtension ExtendedLiteralsBit } { tok_primword32 0 decimal }
-  @binarylit                \#"Word32" / { ifExtension ExtendedLiteralsBit `alexAndPred`
-                                           ifExtension BinaryLiteralsBit }   { tok_primword32 2 binary }
-  @octallit                 \#"Word32" / { ifExtension ExtendedLiteralsBit } { tok_primword32 2 octal }
-  @hexadecimallit           \#"Word32" / { ifExtension ExtendedLiteralsBit } { tok_primword32 2 hexadecimal }
-
-  @decimal                  \#"Word64" / { ifExtension ExtendedLiteralsBit } { tok_primword64 0 decimal }
-  @binarylit                \#"Word64" / { ifExtension ExtendedLiteralsBit `alexAndPred`
-                                           ifExtension BinaryLiteralsBit }   { tok_primword64 2 binary }
-  @octallit                 \#"Word64" / { ifExtension ExtendedLiteralsBit } { tok_primword64 2 octal }
-  @hexadecimallit           \#"Word64" / { ifExtension ExtendedLiteralsBit } { tok_primword64 2 hexadecimal }
-
-  @decimal                  \#"Word"   / { ifExtension ExtendedLiteralsBit } { tok_primword 0 5 decimal }
-  @binarylit                \#"Word"   / { ifExtension ExtendedLiteralsBit `alexAndPred`
-                                           ifExtension BinaryLiteralsBit }   { tok_primword 2 7 binary }
-  @octallit                 \#"Word"   / { ifExtension ExtendedLiteralsBit } { tok_primword 2 7 octal }
-  @hexadecimallit           \#"Word"   / { ifExtension ExtendedLiteralsBit } { tok_primword 2 7 hexadecimal }
-
 }
 
 -- Strings and chars are lexed by hand-written code.  The reason is
@@ -1905,21 +1832,56 @@ sym con span buf len _buf2 =
     !fs = lexemeToFastString buf len
 
 -- Variations on the integral numeric literal.
-tok_integral :: (SourceText -> Integer -> Token)
-             -> (Integer -> Integer)
-             -> Int -> Int
-             -> (Integer, (Char -> Int))
-             -> Action
-tok_integral itint transint transbuf translen (radix,char_to_int) span buf len _buf2 = do
+tok_integral
+  :: (SourceText -> Integer -> Token) -- ^ token constructor
+  -> (Integer -> Integer)             -- ^ value transformation (e.g. negate)
+  -> Int                              -- ^ Offset of the unsigned value (e.g. 1 when we parsed "-", 2 for "0x", etc.)
+  -> Int                              -- ^ Number of non-numeric characters parsed (e.g. 6 in "-12#Int8")
+  -> (Integer, (Char -> Int))         -- ^ (radix, char_to_int parsing function)
+  -> Action
+tok_integral mk_token transval offset translen (radix,char_to_int) span buf len _buf2 = do
   numericUnderscores <- getBit NumericUnderscoresBit  -- #14473
   let src = lexemeToFastString buf len
   when ((not numericUnderscores) && ('_' `elem` unpackFS src)) $ do
     pState <- getPState
     let msg = PsErrNumUnderscores NumUnderscore_Integral
     addError $ mkPlainErrorMsgEnvelope (mkSrcSpanPs (last_loc pState)) msg
-  return $ L span $ itint (SourceText src)
-       $! transint $ parseUnsignedInteger
-       (offsetBytes transbuf buf) (subtract translen len) radix char_to_int
+  return $ L span $ mk_token (SourceText src)
+       $! transval $ parseUnsignedInteger
+       (offsetBytes offset buf) (subtract translen len) radix char_to_int
+
+-- | Helper to parse ExtendedLiterals (e.g. -0x10#Word32)
+--
+-- This function finds the offset of the "#" character and checks that the
+-- suffix is valid. Then it calls tok_integral with the appropriate suffix
+-- length taken into account.
+tok_prim_num_ext
+  :: (Integer -> Integer)             -- ^ value transformation (e.g. negate)
+  -> Int                              -- ^ Offset of the unsigned value (e.g. 1 when we parsed "-", 2 for "0x", etc.)
+  -> (Integer, (Char -> Int))         -- ^ (radix, char_to_int parsing function)
+  -> Action
+tok_prim_num_ext transval offset (radix,char_to_int) span buf len buf2 = do
+  let !suffix_offset = findHashOffset buf + 1
+  let !suffix_len    = len - suffix_offset
+  let !suffix        = lexemeToFastString (offsetBytes suffix_offset buf) suffix_len
+
+  mk_token <- if
+    | suffix == fsLit "Word"   -> pure ITprimword
+    | suffix == fsLit "Word8"  -> pure ITprimword8
+    | suffix == fsLit "Word16" -> pure ITprimword16
+    | suffix == fsLit "Word32" -> pure ITprimword32
+    | suffix == fsLit "Word64" -> pure ITprimword64
+    | suffix == fsLit "Int"    -> pure ITprimint
+    | suffix == fsLit "Int8"   -> pure ITprimint8
+    | suffix == fsLit "Int16"  -> pure ITprimint16
+    | suffix == fsLit "Int32"  -> pure ITprimint32
+    | suffix == fsLit "Int64"  -> pure ITprimint64
+    | otherwise                -> srcParseFail
+
+  let !translen      = suffix_len+offset+1
+  tok_integral mk_token transval offset translen (radix,char_to_int) span buf len buf2
+
+
 
 tok_num :: (Integer -> Integer)
         -> Int -> Int
@@ -1941,48 +1903,16 @@ tok_primint = tok_integral ITprimint
 tok_primword :: Int -> Int
              -> (Integer, (Char->Int)) -> Action
 tok_primword = tok_integral ITprimword positive
+
 positive, negative :: (Integer -> Integer)
 positive = id
 negative = negate
-decimal, octal, hexadecimal :: (Integer, Char -> Int)
-decimal = (10,octDecDigit)
-binary = (2,octDecDigit)
-octal = (8,octDecDigit)
-hexadecimal = (16,hexDigit)
 
--- | Helper for defining @IntX@ primitive literal parsers (specifically for
---   the ExtendedLiterals extension, such as @123#Int8@).
-tok_primintX :: (SourceText -> Integer -> Token)
-             -> Int
-             -> (Integer -> Integer)
-             -> Int
-             -> (Integer, (Char->Int)) -> Action
-tok_primintX itint addlen transint transbuf =
-    tok_integral itint transint transbuf (transbuf+addlen)
-
-tok_primint8,     tok_primint16,  tok_primint32,  tok_primint64
-    :: (Integer -> Integer)
-    -> Int -> (Integer, (Char->Int)) -> Action
-tok_primint8  = tok_primintX ITprimint8   5
-tok_primint16 = tok_primintX ITprimint16  6
-tok_primint32 = tok_primintX ITprimint32  6
-tok_primint64 = tok_primintX ITprimint64  6
-
--- | Helper for defining @WordX@ primitive literal parsers (specifically for
---   the ExtendedLiterals extension, such as @234#Word8@).
-tok_primwordX :: (SourceText -> Integer -> Token)
-              -> Int
-              -> Int
-              -> (Integer, (Char->Int)) -> Action
-tok_primwordX itint addlen transbuf =
-    tok_integral itint positive transbuf (transbuf+addlen)
-
-tok_primword8, tok_primword16, tok_primword32, tok_primword64
-    :: Int -> (Integer, (Char->Int)) -> Action
-tok_primword8  = tok_primwordX ITprimword8  6
-tok_primword16 = tok_primwordX ITprimword16 7
-tok_primword32 = tok_primwordX ITprimword32 7
-tok_primword64 = tok_primwordX ITprimword64 7
+binary, octal, decimal, hexadecimal :: (Integer, Char -> Int)
+binary      = (2,octDecDigit)
+octal       = (8,octDecDigit)
+decimal     = (10,octDecDigit)
+hexadecimal = (16,hexDigit)
 
 -- readSignificandExponentPair can understand negative rationals, exponents, everything.
 tok_frac :: Int -> (String -> Token) -> Action


=====================================
docs/users_guide/exts/extended_literals.rst
=====================================
@@ -35,11 +35,10 @@ The primitive numeric types allowed are:
 - ``Word64#``
 - ``Word#``
 
-All types permit any nonnegative Haskell integer lexeme, e.g. ``70``, ``0x2A``,
-``0o1276``, ``0b1010`` (with :extension:`BinaryLiterals`). The signed ``Int``
-types also permit negative integer lexemes. Defining a literal with a value that
-can't fit in its requested type will emit an overflow warning by default, the
-same as boxed numeric literals.
+All types permit any positive and negative Haskell integer lexeme. Defining a
+literal with a value that can't fit in its requested type will emit an overflow
+warning by default, the same as boxed numeric literals (see
+:ghc-flag:`-Woverflowed-literals`).
 
 As with :extension:`MagicHash`, this extension does not bring anything into
 scope, nor change any semantics. The syntax only applies to numeric literals.


=====================================
testsuite/tests/parser/should_compile/T25258.hs
=====================================
@@ -0,0 +1,18 @@
+{-# LANGUAGE MagicHash, ExtendedLiterals, RequiredTypeArguments #-}
+
+module T25258 where
+
+import GHC.Exts
+import GHC.Word
+
+f :: Int# -> forall t -> ()
+f _ _ = ()
+
+x4 :: forall t -> ()
+x4 = f 0x08#Int
+
+x5 :: ()
+x5 = f 0x08# Int
+
+x6 :: Word8
+x6 = W8# (-10#Word8) -- we now allow negative unsigned extended literals (with a warning)


=====================================
testsuite/tests/parser/should_compile/T25258.stderr
=====================================
@@ -0,0 +1,3 @@
+T25258.hs:18:11: warning: [GHC-97441] [-Woverflowed-literals (in -Wdefault)]
+    Literal -10 is out of the Word8# range 0..255
+


=====================================
testsuite/tests/parser/should_compile/all.T
=====================================
@@ -204,3 +204,4 @@ test('ListTuplePunsFamilies', [expect_broken(23135), extra_files(['ListTuplePuns
 test('T22155', normal, compile, ['-dsuppress-uniques -ddump-simpl -dsuppress-all -dno-typeable-binds'])
 
 test('T25132', normal, compile, [''])
+test('T25258', normal, compile, [''])


=====================================
testsuite/tests/parser/should_fail/T25258a.hs
=====================================
@@ -0,0 +1,7 @@
+{-# LANGUAGE MagicHash, ExtendedLiterals #-}
+
+module T25258a where
+
+import GHC.Exts
+
+x1 = 0x08#Misc  -- invalid uppercase identifier


=====================================
testsuite/tests/parser/should_fail/T25258a.stderr
=====================================
@@ -0,0 +1,2 @@
+T25258a.hs:7:6: error: [GHC-58481] parse error on input ‘0x08#Misc’
+


=====================================
testsuite/tests/parser/should_fail/T25258b.hs
=====================================
@@ -0,0 +1,7 @@
+{-# LANGUAGE MagicHash, ExtendedLiterals #-}
+
+module T25258b where
+
+import GHC.Exts
+
+x2 = 0x80#Int3


=====================================
testsuite/tests/parser/should_fail/T25258b.stderr
=====================================
@@ -0,0 +1,2 @@
+T25258b.hs:7:6: error: [GHC-58481] parse error on input ‘0x80#Int3’
+


=====================================
testsuite/tests/parser/should_fail/T25258c.hs
=====================================
@@ -0,0 +1,7 @@
+{-# LANGUAGE MagicHash, ExtendedLiterals #-}
+
+module T25258c where
+
+import GHC.Exts
+
+x0 = 0x08#misc  -- invalid lowercase identifier


=====================================
testsuite/tests/parser/should_fail/T25258c.stderr
=====================================
@@ -0,0 +1,2 @@
+T25258c.hs:7:6: error: [GHC-58481] parse error on input ‘0x08#misc’
+


=====================================
testsuite/tests/parser/should_fail/all.T
=====================================
@@ -234,3 +234,6 @@ test('OrPatInExprErr', normal, compile_fail, [''])
 test('MultilineStringsError', [normalise_whitespace_fun(lambda s: s)], compile_fail, [''])
 test('MultilineStringsSmartQuotes', normal, compile_fail, [''])
 test('MultilineStringsInnerTab', normal, compile_fail, [''])
+test('T25258a', normal, compile_fail, [''])
+test('T25258b', normal, compile_fail, [''])
+test('T25258c', normal, compile_fail, [''])



View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/d7016e0d41769f777c713158817bc0c43fb2a33f

-- 
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/d7016e0d41769f777c713158817bc0c43fb2a33f
You're receiving this email because of your account on gitlab.haskell.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/ghc-commits/attachments/20240921/353d03e8/attachment-0001.html>


More information about the ghc-commits mailing list