}
encode_path(ecx, ebml_w, path, ast_map::path_name(nitem.ident));
}
- foreign_item_const(*) => {
+ foreign_item_static(_, mutbl) => {
encode_def_id(ebml_w, local_def(nitem.id));
- encode_family(ebml_w, 'c');
+ if mutbl {
+ encode_family(ebml_w, 'b');
+ } else {
+ encode_family(ebml_w, 'c');
+ }
encode_type(ecx, ebml_w, node_id_to_type(ecx.tcx, nitem.id));
encode_symbol(ecx, ebml_w, nitem.id);
encode_path(ecx, ebml_w, path, ast_map::path_name(nitem.ident));
}
fn check_item_ctypes(cx: &Context, it: @ast::item) {
+ fn check_ty(cx: &Context, ty: @ast::Ty) {
+ match ty.node {
+ ast::ty_path(_, _, id) => {
+ match cx.tcx.def_map.get_copy(&id) {
+ ast::def_prim_ty(ast::ty_int(ast::ty_i)) => {
+ cx.span_lint(ctypes, ty.span,
+ "found rust type `int` in foreign module, while \
+ libc::c_int or libc::c_long should be used");
+ }
+ ast::def_prim_ty(ast::ty_uint(ast::ty_u)) => {
+ cx.span_lint(ctypes, ty.span,
+ "found rust type `uint` in foreign module, while \
+ libc::c_uint or libc::c_ulong should be used");
+ }
+ _ => ()
+ }
+ }
+ _ => ()
+ }
+ }
fn check_foreign_fn(cx: &Context, decl: &ast::fn_decl) {
let tys = vec::map(decl.inputs, |a| a.ty );
for vec::each(vec::append_one(tys, decl.output)) |ty| {
- match ty.node {
- ast::ty_path(_, _, id) => {
- match cx.tcx.def_map.get_copy(&id) {
- ast::def_prim_ty(ast::ty_int(ast::ty_i)) => {
- cx.span_lint(ctypes, ty.span,
- "found rust type `int` in foreign module, while \
- libc::c_int or libc::c_long should be used");
- }
- ast::def_prim_ty(ast::ty_uint(ast::ty_u)) => {
- cx.span_lint(ctypes, ty.span,
- "found rust type `uint` in foreign module, while \
- libc::c_uint or libc::c_ulong should be used");
- }
- _ => ()
- }
- }
- _ => ()
- }
+ check_ty(cx, *ty);
}
}
ast::item_foreign_mod(ref nmod) if !nmod.abis.is_intrinsic() => {
for nmod.items.iter().advance |ni| {
match ni.node {
- ast::foreign_item_fn(ref decl, _, _) => {
- check_foreign_fn(cx, decl);
- }
- // FIXME #4622: Not implemented.
- ast::foreign_item_const(*) => {}
+ ast::foreign_item_fn(ref decl, _, _) => {
+ check_foreign_fn(cx, decl);
+ }
+ ast::foreign_item_static(t, _) => { check_ty(cx, t); }
}
}
}
visit_foreign_item(foreign_item, (new_parent, visitor));
}
}
- foreign_item_const(*) => {
- let def = def_static(local_def(foreign_item.id), false);
+ foreign_item_static(_, m) => {
+ let def = def_static(local_def(foreign_item.id), m);
name_bindings.define_value(Public, def, foreign_item.span);
visit_foreign_item(foreign_item, (new_parent, visitor));
|| visit_foreign_item(*foreign_item,
((), visitor)));
}
- foreign_item_const(_) => {
+ foreign_item_static(*) => {
visit_foreign_item(*foreign_item,
((), visitor));
}
ni.id,
ni.attrs)
}
- ast::foreign_item_const(*) => {
+ ast::foreign_item_static(*) => {
let typ = ty::node_id_to_type(ccx.tcx, ni.id);
let ident = token::ident_to_str(&ni.ident);
let g = do str::as_c_str(ident) |buf| {
}
}
}
- ast::foreign_item_const(*) => {
+ ast::foreign_item_static(*) => {
let ident = token::ident_to_str(&foreign_item.ident);
ccx.item_symbols.insert(foreign_item.id, /* bad */ident.to_owned());
}
generics,
abis)
}
- ast::foreign_item_const(t) => {
+ ast::foreign_item_static(t, _) => {
ty::ty_param_bounds_and_ty {
generics: ty::Generics {
type_param_defs: @~[],
ast::foreign_item_fn(*) => {
fns.push(fndoc_from_fn(ItemDoc));
}
- ast::foreign_item_const(*) => {} // XXX: Not implemented.
+ ast::foreign_item_static(*) => {} // XXX: Not implemented.
}
}
doc::NmodDoc {
#[deriving(Eq, Encodable, Decodable)]
pub enum foreign_item_ {
foreign_item_fn(fn_decl, purity, Generics),
- foreign_item_const(@Ty)
+ foreign_item_static(@Ty, /* is_mutbl */ bool),
}
// The data we save and restore about an inlined item or method. This is not
purity,
fold_generics(generics, fld))
}
- foreign_item_const(t) => {
- foreign_item_const(fld.fold_ty(t))
+ foreign_item_static(t, m) => {
+ foreign_item_static(fld.fold_ty(t), m)
}
},
id: fld.new_id(ni.id),
use ast::{expr_vstore_slice, expr_vstore_box};
use ast::{expr_vstore_mut_slice, expr_while, extern_fn, field, fn_decl};
use ast::{expr_vstore_uniq, Onceness, Once, Many};
-use ast::{foreign_item, foreign_item_const, foreign_item_fn, foreign_mod};
+use ast::{foreign_item, foreign_item_static, foreign_item_fn, foreign_mod};
use ast::{ident, impure_fn, inherited, item, item_, item_static};
use ast::{item_enum, item_fn, item_foreign_mod, item_impl};
use ast::{item_mac, item_mod, item_struct, item_trait, item_ty, lit, lit_};
} else {
self.expect_keyword(keywords::Static);
}
+ let mutbl = self.eat_keyword(keywords::Mut);
let ident = self.parse_ident();
self.expect(&token::COLON);
self.expect(&token::SEMI);
@ast::foreign_item { ident: ident,
attrs: attrs,
- node: foreign_item_const(ty),
+ node: foreign_item_static(ty, mutbl),
id: self.get_id(),
span: mk_sp(lo, hi),
vis: vis }
word(s.s, ";");
end(s); // end the outer fn box
}
- ast::foreign_item_const(t) => {
+ ast::foreign_item_static(t, m) => {
head(s, "static");
+ if m {
+ word_space(s, "mut");
+ }
print_ident(s, item.ident);
word_space(s, ":");
print_type(s, t);
visit_fn_decl(fd, (copy e, v));
(v.visit_generics)(generics, (e, v));
}
- foreign_item_const(t) => {
+ foreign_item_static(t, _) => {
(v.visit_ty)(t, (e, v));
}
}
return ff;
}
+extern "C" int
+debug_static_mut;
+
+int debug_static_mut = 3;
+
+extern "C" void
+debug_static_mut_check_four() {
+ assert(debug_static_mut == 4);
+}
+
/* Debug builtins for std::dbg. */
static void
debug_get_stk_seg
debug_abi_1
debug_abi_2
+debug_static_mut
+debug_static_mut_check_four
get_task_id
get_time
rust_tzset
rust_take_env_lock
rust_drop_env_lock
rust_update_log_settings
-rust_running_on_valgrind
\ No newline at end of file
+rust_running_on_valgrind
--- /dev/null
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::libc;
+
+extern {
+ static mut a: libc::c_int;
+}
+
+fn main() {
+ a += 3; //~ ERROR: requires unsafe
+ a = 4; //~ ERROR: requires unsafe
+ let _b = a; //~ ERROR: requires unsafe
+}
--- /dev/null
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Constants (static variables) can be used to match in patterns, but mutable
+// statics cannot. This ensures that there's some form of error if this is
+// attempted.
+
+use std::libc;
+
+#[nolink]
+extern {
+ static mut debug_static_mut: libc::c_int;
+ pub fn debug_static_mut_check_four();
+}
+
+unsafe fn static_bound(_: &'static libc::c_int) {}
+
+fn static_bound_set(a: &'static mut libc::c_int) {
+ *a = 3;
+}
+
+unsafe fn run() {
+ assert!(debug_static_mut == 3);
+ debug_static_mut = 4;
+ assert!(debug_static_mut == 4);
+ debug_static_mut_check_four();
+ debug_static_mut += 1;
+ assert!(debug_static_mut == 5);
+ debug_static_mut *= 3;
+ assert!(debug_static_mut == 15);
+ debug_static_mut = -3;
+ assert!(debug_static_mut == -3);
+ static_bound(&debug_static_mut);
+ static_bound_set(&mut debug_static_mut);
+}
+
+fn main() {
+ unsafe { run() }
+}