{-# LANGUAGE DeriveDataTypeable, GeneralizedNewtypeDeriving #-} ----------------------------------------------------------------------------- -- | -- Module : Language.C.Analysis.SemError -- Copyright : (c) 2008 Benedikt Huber -- License : BSD-style -- Maintainer : benedikt.huber@gmail.com -- Stability : alpha -- Portability : ghc -- -- Errors in the semantic analysis ----------------------------------------------------------------------------- module Language.C.Analysis.SemError ( InvalidASTError(..), invalidAST, BadSpecifierError(..), badSpecifierError, TypeMismatch(..), typeMismatch, RedefError(..), RedefInfo(..), RedefKind(..), redefinition, ) where import Data.Typeable -- this means we cannot use SemError in SemRep, but use rich types here import Language.C.Analysis.SemRep import Language.C.Data.Error import Language.C.Data.Node -- here are the errors available -- | InvalidASTError is caused by the violation of an invariant in the AST newtype InvalidASTError = InvalidAST ErrorInfo deriving (Typeable) instance Error InvalidASTError where errorInfo (InvalidAST ei) = ei changeErrorLevel (InvalidAST ei) lvl' = InvalidAST (changeErrorLevel ei lvl') -- | BadSpecifierError is caused by an invalid combination of specifiers newtype BadSpecifierError = BadSpecifierError ErrorInfo deriving (Typeable) instance Error BadSpecifierError where errorInfo (BadSpecifierError ei) = ei changeErrorLevel (BadSpecifierError ei) lvl' = BadSpecifierError (changeErrorLevel ei lvl') -- | RedefError is caused by an invalid redefinition of the same identifier or type data RedefError = RedefError ErrorLevel RedefInfo deriving Typeable data RedefInfo = RedefInfo String RedefKind NodeInfo NodeInfo data RedefKind = DuplicateDef | DiffKindRedecl | ShadowedDef | DisagreeLinkage | NoLinkageOld data TypeMismatch = TypeMismatch String (NodeInfo,Type) (NodeInfo,Type) deriving Typeable -- Invalid AST -- ~~~~~~~~~~~ instance Show InvalidASTError where show = showError "AST invariant violated" invalidAST :: NodeInfo -> String -> InvalidASTError invalidAST node_info msg = InvalidAST (mkErrorInfo LevelError msg node_info) -- Bad specifier (e.g. static for a parameter, or extern when there is an initializer) -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ instance Show BadSpecifierError where show = showError "Bad specifier" badSpecifierError :: NodeInfo -> String -> BadSpecifierError badSpecifierError node_info msg = BadSpecifierError (mkErrorInfo LevelError msg node_info) -- Type mismatch -- ~~~~~~~~~~~~~ typeMismatch :: String -> (NodeInfo, Type) -> (NodeInfo,Type) -> TypeMismatch typeMismatch = TypeMismatch instance Show TypeMismatch where show tm = showError "Type mismatch" (typeMismatchInfo tm) instance Error TypeMismatch where errorInfo = typeMismatchInfo typeMismatchInfo :: TypeMismatch -> ErrorInfo typeMismatchInfo (TypeMismatch reason (node1,_ty2) _t2) = ErrorInfo LevelError (posOfNode node1) [reason] -- Redefinitions -- ~~~~~~~~~~~~~ instance Show RedefError where show (RedefError lvl info) = showErrorInfo (redefErrLabel info) (redefErrorInfo lvl info) instance Error RedefError where errorInfo (RedefError lvl info) = redefErrorInfo lvl info changeErrorLevel (RedefError _lvl info) lvl' = RedefError lvl' info redefErrLabel :: RedefInfo -> String redefErrLabel (RedefInfo ident _ _ _) = ident ++ " redefined" redefErrorInfo :: ErrorLevel -> RedefInfo -> ErrorInfo redefErrorInfo lvl info@(RedefInfo _ _ node old_node) = ErrorInfo lvl (posOfNode node) ([redefErrReason info] ++ prevDeclMsg old_node) redefErrReason :: RedefInfo -> String redefErrReason (RedefInfo ident DuplicateDef _ _) = "duplicate definition of " ++ ident redefErrReason (RedefInfo ident ShadowedDef _ _) = "this declaration of " ++ ident ++ " shadows a previous one" redefErrReason (RedefInfo ident DiffKindRedecl _ _) = ident ++ " previously declared as a different kind of symbol" redefErrReason (RedefInfo ident DisagreeLinkage _ _) = ident ++ " previously declared with different linkage" redefErrReason (RedefInfo ident NoLinkageOld _ _) = ident ++ " previously declared without linkage" prevDeclMsg :: NodeInfo -> [String] prevDeclMsg old_node = ["The previous declaration was here: ", show (posOfNode old_node)] redefinition :: ErrorLevel -> String -> RedefKind -> NodeInfo -> NodeInfo -> RedefError redefinition lvl ctx kind new old = RedefError lvl (RedefInfo ctx kind new old)