diff --git a/src/cpp.c b/src/cpp.c
index ad60643f4646e719c37cebfda39103fa7a7cf33c..86961ef7b67fd57b6442165c613e390fb80e4d9a 100644
--- a/src/cpp.c
+++ b/src/cpp.c
@@ -1947,6 +1947,21 @@ static void insert_callback_define_no_args(struct cpp *this,
  *! as @expr{#pragma strict_types@} .
  */
 
+/*! @decl constant static_assert
+ *!
+ *!   This define expands to the symbol @[_Static_assert].
+ *!
+ *!   It is the preferred way to perform static
+ *!   (ie compile-time) assertions.
+ *!
+ *! @note
+ *!   The macro can also be used to check for whether static assertions
+ *!   are supported.
+ *!
+ *! @seealso
+ *!   @[_Static_assert()]
+ */
+
 /*! @decl constant __PIKE__
  *!
  *! This define is always true.
@@ -2236,8 +2251,9 @@ void f_cpp(INT32 args)
   do_magic_define(&this,"__DATE__",insert_current_date_as_string);
   do_magic_define(&this,"__TIME__",insert_current_time_as_string);
 
-  /* This is from the 201x C standard. */
+  /* These are from the 201x C standard. */
   do_magic_define(&this,"_Pragma",insert_pragma)->args = 1;
+  simple_add_define(&this, "static_assert", "_Static_assert");
 
   /* These are Pike extensions. */
   do_magic_define(&this,"__DIR__",insert_current_dir_as_string);
diff --git a/src/operators.c b/src/operators.c
index 5b97ca415dc26a7bdd75572190e294ac27112efb..383b4b71030a8a6cacf515e93feac89d27045fd5 100644
--- a/src/operators.c
+++ b/src/operators.c
@@ -5475,6 +5475,54 @@ static int generate_sizeof(node *n)
 
 extern int generate_call_function(node *n);
 
+/*! @decl void _Static_assert(int constant_expression, string constant_message)
+ *!
+ *!   Perform a compile-time assertion check.
+ *!
+ *!   If @[constant_expression] is false, a compiler error message
+ *!   containing @[constant_message] will be generated.
+ *!
+ *! @note
+ *!   Note that the function call compiles to the null statement,
+ *!   and thus does not affect the run-time.
+ *!
+ *! @seealso
+ *!   @[cpp::static_assert]
+ */
+static int generate__Static_assert(node *n)
+{
+  struct compilation *c = THIS_COMPILATION;
+  ptrdiff_t tmp;
+  node **expr = my_get_arg(&_CDR(n), 0);
+  node **msg = my_get_arg(&_CDR(n), 1);
+  if(!expr || !msg || count_args(CDR(n)) != 2) {
+    yyerror("Bad number of arguments to _Static_assert().");
+    return 1;
+  }
+  tmp = eval_low(*msg, 0);
+  if (tmp < 1) {
+    yyerror("Argument 2 to _Static_assert() is not constant.");
+    return 1;
+  }
+  if (tmp > 1) pop_n_elems(tmp-1);
+  if (TYPEOF(Pike_sp[-1]) != T_STRING) {
+    yyerror("Bad argument 2 to _Static_assert(), expected string.");
+    return 1;
+  }
+  tmp = eval_low(*expr, 0);
+  if (tmp < 1) {
+    pop_stack();
+    yyerror("Argument 1 to _Static_assert is not constant.");
+    return 1;
+  }
+  if (tmp > 1) pop_n_elems(tmp-1);
+  if (SAFE_IS_ZERO(Pike_sp-1)) {
+    my_yyerror("Assertion failed: %S", Pike_sp[-2].u.string);
+  }
+  pop_n_elems(2);
+  return 1;
+}
+
 /*! @class string_assignment
  */
 
@@ -5828,6 +5876,10 @@ multiset & mapping -> mapping
   /* function(mixed,mixed ...:mixed) */
   ADD_EFUN2("call_function",f_call_function,tFuncV(tMix,tMix,tMix),OPT_SIDE_EFFECT | OPT_EXTERNAL_DEPEND,0,generate_call_function);
 
+  /* From the 201x C standard */
+  ADD_EFUN2("_Static_assert", NULL,
+	    tFunc(tInt tStr, tVoid), OPT_TRY_OPTIMIZE,
+	    NULL, generate__Static_assert);
 
   start_new_program();
   ADD_STORAGE(struct string_assignment_storage);
diff --git a/src/testsuite.in b/src/testsuite.in
index 581aa931f19ece995045fb2f274caf916143184b..b55158bc52bd5a4ce60fc7ba41a6bfbf0c840c1b 100644
--- a/src/testsuite.in
+++ b/src/testsuite.in
@@ -709,6 +709,9 @@ ignore_warning("Soft cast of scope(0,function(*)) to function is a noop.", [[
   test_eq(typeof([function]`+), typeof(`+))
 ]])
 
+test_compile_error([[ static_assert(0, "Fail."); ]])
+test_any([[ static_assert(1, "Ok."); ]], 0)
+
 test_any([[
   /* Detect bug in modify_shared_string().
    *