<commit_before>diff --git a/src/Language/C/Analysis/ConstEval.hs b/src/Language/C/Analysis/ConstEval.hs
index 9af4aac..5d28c86 100644
--- a/src/Language/C/Analysis/ConstEval.hs
+++ b/src/Language/C/Analysis/ConstEval.hs
@@ -42,7 +42,7 @@ sizeofType md _ (DirectType TyVoid _ _) = return $ voidSize md
 sizeofType md _ (DirectType (TyIntegral it) _ _) = return $ iSize md it
 sizeofType md _ (DirectType (TyFloating ft) _ _) = return $ fSize md ft
 sizeofType md _ (DirectType (TyComplex ft) _ _) = return $ 2 * fSize md ft
-sizeofType md _ (DirectType (TyComp ctr) _ _) = compSize md ctr
+sizeofType md _ (DirectType (TyComp ctr) _ _) = fst <$> compSizeAndAlign md ctr
 sizeofType md _ (DirectType (TyEnum _) _ _) = return $ iSize md TyInt
 sizeofType md _ (DirectType (TyBuiltin b) _ _) = return $ builtinSize md b
 sizeofType md _ (PtrType _ _ _)  = return $ ptrSize md
@@ -66,6 +66,7 @@ alignofType md _ (DirectType TyVoid _ _) = return $ voidAlign md
 alignofType md _ (DirectType (TyIntegral it) _ _) = return $ iAlign md it
 alignofType md _ (DirectType (TyFloating ft) _ _) = return $ fAlign md ft
 alignofType md _ (DirectType (TyComplex ft) _ _) = return $ fAlign md ft
+alignofType md _ (DirectType (TyComp ctr) _ _) = snd <$> compSizeAndAlign md ctr
 alignofType md _ (DirectType (TyEnum _) _ _) = return $ iAlign md TyInt
 alignofType md _ (DirectType (TyBuiltin b) _ _) = return $ builtinAlign md b
 alignofType md _ (PtrType _ _ _)  = return $ ptrAlign md
@@ -75,8 +76,13 @@ alignofType md n (TypeDefType (TypeDefRef _ t _) _ _) = alignofType md n t
 alignofType _ n t = astError (nodeInfo n) $
                  "can't find alignment of type: " ++ (render . pretty) t
 
-compSize :: MonadTrav m => MachineDesc -> CompTypeRef -> m Integer
-compSize md ctr =
+compSizeAndAlign
+  :: MonadTrav m =>
+     MachineDesc ->
+     CompTypeRef ->
+     m (Integer, Integer)
+     -- ^ (size, alignment)
+compSizeAndAlign md ctr =
   do dt <- getDefTable
      case lookupTag (sueRef ctr) dt of
        Just (Left _)   -> astError (nodeInfo ctr)
@@ -84,13 +90,33 @@ compSize md ctr =
        Just (Right (CompDef (CompType _ tag ms _ ni))) ->
          do let ts = map declType ms
             sizes <- mapM (sizeofType md ni) ts
-            -- XXX: handle padding
-            case tag of
-              StructTag -> return $ sum sizes
-              UnionTag  -> return $ maximum sizes
-       Just (Right (EnumDef _)) -> return $ iSize md TyInt
+            aligns <- mapM (alignofType md ni) ts
+            let alignment = maximum (1 : aligns)
+                size = case tag of
+                  UnionTag -> roundToAlignment alignment (maximum (0 : sizes))
+                  StructTag ->
+                    let sizeAndNextAlignment =
+                          zip sizes (tail aligns ++ [alignment])
+                        offsets = scanl
+                          (\offset (memberSize, nextAlign)
+                           -> roundToAlignment nextAlign (offset + memberSize))
+                          0
+                          sizeAndNextAlignment
+                    in last offsets
+            return (size, alignment)
+       Just (Right (EnumDef _)) -> return $ (iSize md TyInt, iAlign md TyInt)
        Nothing         -> astError (nodeInfo ctr) "unknown composite"
 
+-- | Find the next multiple of an alignment
+roundToAlignment
+  :: Integer
+  -- ^ The alignment
+  -> Integer
+  -- ^ The value to align
+  -> Integer
+  -- ^ The next multiple of alignment
+roundToAlignment alignment value =
+  alignment * ((value + (alignment - 1)) `quot` alignment)
 
 {- Expression evaluation -}
 <commit_msg>Tweak language-c patch<commit_after>diff --git a/src/Language/C/Analysis/ConstEval.hs b/src/Language/C/Analysis/ConstEval.hs
index 9af4aac..bbe64fb 100644
--- a/src/Language/C/Analysis/ConstEval.hs
+++ b/src/Language/C/Analysis/ConstEval.hs
@@ -3,6 +3,7 @@ module Language.C.Analysis.ConstEval where
 
 import Control.Monad
 import Data.Bits
+import Data.List (foldl')
 import Data.Maybe
 import qualified Data.Map as Map
 import Language.C.Syntax.AST
@@ -42,7 +43,7 @@ sizeofType md _ (DirectType TyVoid _ _) = return $ voidSize md
 sizeofType md _ (DirectType (TyIntegral it) _ _) = return $ iSize md it
 sizeofType md _ (DirectType (TyFloating ft) _ _) = return $ fSize md ft
 sizeofType md _ (DirectType (TyComplex ft) _ _) = return $ 2 * fSize md ft
-sizeofType md _ (DirectType (TyComp ctr) _ _) = compSize md ctr
+sizeofType md _ (DirectType (TyComp ctr) _ _) = fst <$> compSizeAndAlign md ctr
 sizeofType md _ (DirectType (TyEnum _) _ _) = return $ iSize md TyInt
 sizeofType md _ (DirectType (TyBuiltin b) _ _) = return $ builtinSize md b
 sizeofType md _ (PtrType _ _ _)  = return $ ptrSize md
@@ -66,6 +67,7 @@ alignofType md _ (DirectType TyVoid _ _) = return $ voidAlign md
 alignofType md _ (DirectType (TyIntegral it) _ _) = return $ iAlign md it
 alignofType md _ (DirectType (TyFloating ft) _ _) = return $ fAlign md ft
 alignofType md _ (DirectType (TyComplex ft) _ _) = return $ fAlign md ft
+alignofType md _ (DirectType (TyComp ctr) _ _) = snd <$> compSizeAndAlign md ctr
 alignofType md _ (DirectType (TyEnum _) _ _) = return $ iAlign md TyInt
 alignofType md _ (DirectType (TyBuiltin b) _ _) = return $ builtinAlign md b
 alignofType md _ (PtrType _ _ _)  = return $ ptrAlign md
@@ -75,8 +77,13 @@ alignofType md n (TypeDefType (TypeDefRef _ t _) _ _) = alignofType md n t
 alignofType _ n t = astError (nodeInfo n) $
                  "can't find alignment of type: " ++ (render . pretty) t
 
-compSize :: MonadTrav m => MachineDesc -> CompTypeRef -> m Integer
-compSize md ctr =
+compSizeAndAlign
+  :: MonadTrav m =>
+     MachineDesc ->
+     CompTypeRef ->
+     m (Integer, Integer)
+     -- ^ (size, alignment)
+compSizeAndAlign md ctr =
   do dt <- getDefTable
      case lookupTag (sueRef ctr) dt of
        Just (Left _)   -> astError (nodeInfo ctr)
@@ -84,13 +91,33 @@ compSize md ctr =
        Just (Right (CompDef (CompType _ tag ms _ ni))) ->
          do let ts = map declType ms
             sizes <- mapM (sizeofType md ni) ts
-            -- XXX: handle padding
-            case tag of
-              StructTag -> return $ sum sizes
-              UnionTag  -> return $ maximum sizes
-       Just (Right (EnumDef _)) -> return $ iSize md TyInt
+            aligns <- mapM (alignofType md ni) ts
+            let alignment = maximum (1 : aligns)
+                size = case tag of
+                  UnionTag -> roundToAlignment alignment (maximum (0 : sizes))
+                  StructTag ->
+                    let sizeAndNextAlignment =
+                          zip sizes (tail aligns ++ [alignment])
+                        offsets = foldl'
+                          (\offset (memberSize, nextAlign)
+                           -> roundToAlignment nextAlign (offset + memberSize))
+                          0
+                          sizeAndNextAlignment
+                    in offsets
+            return (size, alignment)
+       Just (Right (EnumDef _)) -> return $ (iSize md TyInt, iAlign md TyInt)
        Nothing         -> astError (nodeInfo ctr) "unknown composite"
 
+-- | Find the next multiple of an alignment
+roundToAlignment
+  :: Integer
+  -- ^ The alignment
+  -> Integer
+  -- ^ The value to align
+  -> Integer
+  -- ^ The next multiple of alignment
+roundToAlignment alignment value =
+  alignment * ((value + (alignment - 1)) `quot` alignment)
 
 {- Expression evaluation -}
 
{'fraction_non_alphanumeric': 0.10590277777777778, 'fraction_numerical': 0.012152777777777778, 'mean_word_length': 2.332888295505118, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 43, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2262603', 'n_tokens_mistral': 2388, 'n_tokens_neox': 2295, 'n_words': 736}