about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMarijn Haverbeke <marijnh@gmail.com>2011-12-07 21:53:05 +0100
committerMarijn Haverbeke <marijnh@gmail.com>2011-12-07 21:53:05 +0100
commit3d0610b072537f43946cf685bc9888ec7df44f08 (patch)
treeb30dc88e7f30a1d53d68eef2ff30b1981de0a2d9
parente3eca9174b9dc186de4ad44f80f7537f2e9e4c60 (diff)
Check for literals that are out of range for their type
-rw-r--r--src/comp/middle/check_const.rs19
-rw-r--r--src/comp/syntax/ast_util.rs18
-rw-r--r--src/libstd/u32.rs2
-rw-r--r--src/test/compile-fail/oversized-literal.rs3
4 files changed, 40 insertions, 2 deletions
diff --git a/src/comp/middle/check_const.rs b/src/comp/middle/check_const.rs
index 44f3891c13c..81d41b06e49 100644
--- a/src/comp/middle/check_const.rs
+++ b/src/comp/middle/check_const.rs
@@ -1,5 +1,5 @@
 import syntax::ast::*;
-import syntax::visit;
+import syntax::{visit, ast_util};
 import driver::session::session;
 
 fn check_crate(sess: session, crate: @crate) {
@@ -56,6 +56,23 @@ fn check_expr(sess: session, e: @expr, &&is_const: bool, v: visit::vt<bool>) {
           }
         }
     }
+    alt e.node {
+      expr_lit(@{node: lit_int(v, t), _}) {
+        if t != ty_char {
+            if (v as u64) > ast_util::int_ty_max(
+                t == ty_i ? sess.get_targ_cfg().int_type : t) {
+                sess.span_err(e.span, "literal out of range for its type");
+            }
+        }
+      }
+      expr_lit(@{node: lit_uint(v, t), _}) {
+        if v > ast_util::uint_ty_max(
+            t == ty_u ? sess.get_targ_cfg().uint_type : t) {
+            sess.span_err(e.span, "literal out of range for its type");
+        }
+      }
+      _ {}
+    }
     visit::visit_expr(e, is_const, v);
 }
 
diff --git a/src/comp/syntax/ast_util.rs b/src/comp/syntax/ast_util.rs
index f6d019c2a85..dc1d0e0bbbb 100644
--- a/src/comp/syntax/ast_util.rs
+++ b/src/comp/syntax/ast_util.rs
@@ -132,6 +132,15 @@ fn int_ty_to_str(t: int_ty) -> str {
     }
 }
 
+fn int_ty_max(t: int_ty) -> u64 {
+    alt t {
+      ty_i8. { 0x80u64 }
+      ty_i16. { 0x800u64 }
+      ty_char. | ty_i32. { 0x80000000u64 }
+      ty_i64. { 0x8000000000000000u64 }
+    }
+}
+
 fn uint_ty_to_str(t: uint_ty) -> str {
     alt t {
       ty_u. { "" } ty_u8. { "u8" } ty_u16. { "u16" }
@@ -139,6 +148,15 @@ fn uint_ty_to_str(t: uint_ty) -> str {
     }
 }
 
+fn uint_ty_max(t: uint_ty) -> u64 {
+    alt t {
+      ty_u8. { 0xffu64 }
+      ty_u16. { 0xffffu64 }
+      ty_u32. { 0xffffffffu64 }
+      ty_u64. { 0xffffffffffffffffu64 }
+    }
+}
+
 fn float_ty_to_str(t: float_ty) -> str {
     alt t { ty_f. { "" } ty_f32. { "f32" } ty_f64. { "f64" } }
 }
diff --git a/src/libstd/u32.rs b/src/libstd/u32.rs
index be6f649a979..f33b8414a4d 100644
--- a/src/libstd/u32.rs
+++ b/src/libstd/u32.rs
@@ -14,7 +14,7 @@ Const: max_value
 
 Return the maximal value for a u32
 */
-const max_value: u32 = 4294967296u32;
+const max_value: u32 = 0xffff_ffffu32;
 
 //
 // Local Variables:
diff --git a/src/test/compile-fail/oversized-literal.rs b/src/test/compile-fail/oversized-literal.rs
new file mode 100644
index 00000000000..30b61811b04
--- /dev/null
+++ b/src/test/compile-fail/oversized-literal.rs
@@ -0,0 +1,3 @@
+// error-pattern:literal out of range
+
+fn main() { log 300u8; }