gfortran.h (gfc_option_t): Remove warn_aliasing,
[gcc.git] / gcc / fortran / intrinsic.c
index 9c69d7dfc9429112bf20a90a97b910ab08f129b1..5dd4092e63a2d22a04ab06d296f4366acc54ff3e 100644 (file)
@@ -1,8 +1,6 @@
 /* Build up a list of intrinsic subroutines and functions for the
    name-resolution stage.
-   Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
-   2009, 2010
-   Free Software Foundation, Inc.
+   Copyright (C) 2000-2014 Free Software Foundation, Inc.
    Contributed by Andy Vaught & Katherine Holcomb
 
 This file is part of GCC.
@@ -23,6 +21,7 @@ along with GCC; see the file COPYING3.  If not see
 
 #include "config.h"
 #include "system.h"
+#include "coretypes.h"
 #include "flags.h"
 #include "gfortran.h"
 #include "intrinsic.h"
@@ -51,7 +50,7 @@ sizing;
 
 enum klass
 { CLASS_IMPURE = 0, CLASS_PURE, CLASS_ELEMENTAL,
-  CLASS_INQUIRY, CLASS_TRANSFORMATIONAL };
+  CLASS_INQUIRY, CLASS_TRANSFORMATIONAL, CLASS_ATOMIC };
 
 #define ACTUAL_NO      0
 #define ACTUAL_YES     1
@@ -175,11 +174,77 @@ find_char_conv (gfc_typespec *from, gfc_typespec *to)
 }
 
 
+/* Check TS29113, C407b for assumed type and C535b for assumed-rank,
+   and a likewise check for NO_ARG_CHECK.  */
+
+static bool
+do_ts29113_check (gfc_intrinsic_sym *specific, gfc_actual_arglist *arg)
+{
+  gfc_actual_arglist *a;
+
+  for (a = arg; a; a = a->next)
+    {
+      if (!a->expr)
+       continue;
+
+      if (a->expr->expr_type == EXPR_VARIABLE
+         && (a->expr->symtree->n.sym->attr.ext_attr
+             & (1 << EXT_ATTR_NO_ARG_CHECK))
+         && specific->id != GFC_ISYM_C_LOC
+         && specific->id != GFC_ISYM_PRESENT)
+       {
+         gfc_error ("Variable with NO_ARG_CHECK attribute at %L is only "
+                    "permitted as argument to the intrinsic functions "
+                    "C_LOC and PRESENT", &a->expr->where);
+         return false;
+       }
+      else if (a->expr->ts.type == BT_ASSUMED
+              && specific->id != GFC_ISYM_LBOUND
+              && specific->id != GFC_ISYM_PRESENT
+              && specific->id != GFC_ISYM_RANK
+              && specific->id != GFC_ISYM_SHAPE
+              && specific->id != GFC_ISYM_SIZE
+              && specific->id != GFC_ISYM_SIZEOF
+              && specific->id != GFC_ISYM_UBOUND
+              && specific->id != GFC_ISYM_C_LOC)
+       {
+         gfc_error ("Assumed-type argument at %L is not permitted as actual"
+                    " argument to the intrinsic %s", &a->expr->where,
+                    gfc_current_intrinsic);
+         return false;
+       }
+      else if (a->expr->ts.type == BT_ASSUMED && a != arg)
+       {
+         gfc_error ("Assumed-type argument at %L is only permitted as "
+                    "first actual argument to the intrinsic %s",
+                    &a->expr->where, gfc_current_intrinsic);
+         return false;
+       }
+      if (a->expr->rank == -1 && !specific->inquiry)
+       {
+         gfc_error ("Assumed-rank argument at %L is only permitted as actual "
+                    "argument to intrinsic inquiry functions",
+                    &a->expr->where);
+         return false;
+       }
+      if (a->expr->rank == -1 && arg != a)
+       {
+         gfc_error ("Assumed-rank argument at %L is only permitted as first "
+                    "actual argument to the intrinsic inquiry function %s",
+                    &a->expr->where, gfc_current_intrinsic);
+         return false;
+       }
+    }
+
+  return true;
+}
+
+
 /* Interface to the check functions.  We break apart an argument list
    and call the proper check function rather than forcing each
    function to manipulate the argument list.  */
 
-static gfc_try
+static bool
 do_check (gfc_intrinsic_sym *specific, gfc_actual_arglist *arg)
 {
   gfc_expr *a1, *a2, *a3, *a4, *a5;
@@ -274,10 +339,7 @@ add_sym (const char *name, gfc_isym_id id, enum klass cl, int actual_ok, bt type
       strcat (buf, name);
       next_sym->lib_name = gfc_get_string (buf);
 
-      /* There are no IMPURE ELEMENTAL intrinsics, thus the ELEMENTAL class
-        also implies PURE.  Additionally, there's the PURE class itself.  */
-      next_sym->pure = (cl == CLASS_ELEMENTAL || cl == CLASS_PURE);
-
+      next_sym->pure = (cl != CLASS_IMPURE);
       next_sym->elemental = (cl == CLASS_ELEMENTAL);
       next_sym->inquiry = (cl == CLASS_INQUIRY);
       next_sym->transformational = (cl == CLASS_TRANSFORMATIONAL);
@@ -347,7 +409,7 @@ add_sym (const char *name, gfc_isym_id id, enum klass cl, int actual_ok, bt type
 static void
 add_sym_0 (const char *name, gfc_isym_id id, enum klass cl, int actual_ok, bt type,
           int kind, int standard,
-          gfc_try (*check) (void),
+          bool (*check) (void),
           gfc_expr *(*simplify) (void),
           void (*resolve) (gfc_expr *))
 {
@@ -390,7 +452,7 @@ add_sym_0s (const char *name, gfc_isym_id id, int standard,
 static void
 add_sym_1 (const char *name, gfc_isym_id id, enum klass cl, int actual_ok, bt type,
           int kind, int standard,
-          gfc_try (*check) (gfc_expr *),
+          bool (*check) (gfc_expr *),
           gfc_expr *(*simplify) (gfc_expr *),
           void (*resolve) (gfc_expr *, gfc_expr *),
           const char *a1, bt type1, int kind1, int optional1)
@@ -415,7 +477,7 @@ add_sym_1 (const char *name, gfc_isym_id id, enum klass cl, int actual_ok, bt ty
 static void
 add_sym_1_intent (const char *name, gfc_isym_id id, enum klass cl,
                  int actual_ok, bt type, int kind, int standard,
-                 gfc_try (*check) (gfc_expr *),
+                 bool (*check) (gfc_expr *),
                  gfc_expr *(*simplify) (gfc_expr *),
                  void (*resolve) (gfc_expr *, gfc_expr *),
                  const char *a1, bt type1, int kind1, int optional1,
@@ -440,7 +502,7 @@ add_sym_1_intent (const char *name, gfc_isym_id id, enum klass cl,
 
 static void
 add_sym_1s (const char *name, gfc_isym_id id, enum klass cl, bt type, int kind,
-           int standard, gfc_try (*check) (gfc_expr *),
+           int standard, bool (*check) (gfc_expr *),
            gfc_expr *(*simplify) (gfc_expr *), void (*resolve) (gfc_code *),
            const char *a1, bt type1, int kind1, int optional1,
            sym_intent intent1)
@@ -465,7 +527,7 @@ add_sym_1s (const char *name, gfc_isym_id id, enum klass cl, bt type, int kind,
 static void
 add_sym_1m (const char *name, gfc_isym_id id, enum klass cl, int actual_ok, bt type,
            int kind, int standard,
-           gfc_try (*check) (gfc_actual_arglist *),
+           bool (*check) (gfc_actual_arglist *),
            gfc_expr *(*simplify) (gfc_expr *),
            void (*resolve) (gfc_expr *, gfc_actual_arglist *),
            const char *a1, bt type1, int kind1, int optional1,
@@ -492,7 +554,7 @@ add_sym_1m (const char *name, gfc_isym_id id, enum klass cl, int actual_ok, bt t
 static void
 add_sym_2 (const char *name, gfc_isym_id id, enum klass cl, int actual_ok, bt type,
           int kind, int standard,
-          gfc_try (*check) (gfc_expr *, gfc_expr *),
+          bool (*check) (gfc_expr *, gfc_expr *),
           gfc_expr *(*simplify) (gfc_expr *, gfc_expr *),
           void (*resolve) (gfc_expr *, gfc_expr *, gfc_expr *),
           const char *a1, bt type1, int kind1, int optional1,
@@ -519,7 +581,7 @@ add_sym_2 (const char *name, gfc_isym_id id, enum klass cl, int actual_ok, bt ty
 static void
 add_sym_2_intent (const char *name, gfc_isym_id id, enum klass cl,
                  int actual_ok, bt type, int kind, int standard,
-                 gfc_try (*check) (gfc_expr *, gfc_expr *),
+                 bool (*check) (gfc_expr *, gfc_expr *),
                  gfc_expr *(*simplify) (gfc_expr *, gfc_expr *),
                  void (*resolve) (gfc_expr *, gfc_expr *, gfc_expr *),
                  const char *a1, bt type1, int kind1, int optional1,
@@ -547,7 +609,7 @@ add_sym_2_intent (const char *name, gfc_isym_id id, enum klass cl,
 static void
 add_sym_2s (const char *name, gfc_isym_id id, enum klass cl, bt type,
            int kind, int standard,
-           gfc_try (*check) (gfc_expr *, gfc_expr *),
+           bool (*check) (gfc_expr *, gfc_expr *),
            gfc_expr *(*simplify) (gfc_expr *, gfc_expr *),
            void (*resolve) (gfc_code *),
            const char *a1, bt type1, int kind1, int optional1,
@@ -575,7 +637,7 @@ add_sym_2s (const char *name, gfc_isym_id id, enum klass cl, bt type,
 static void
 add_sym_3 (const char *name, gfc_isym_id id, enum klass cl, int actual_ok, bt type,
           int kind, int standard,
-          gfc_try (*check) (gfc_expr *, gfc_expr *, gfc_expr *),
+          bool (*check) (gfc_expr *, gfc_expr *, gfc_expr *),
           gfc_expr *(*simplify) (gfc_expr *, gfc_expr *, gfc_expr *),
           void (*resolve) (gfc_expr *, gfc_expr *, gfc_expr *, gfc_expr *),
           const char *a1, bt type1, int kind1, int optional1,
@@ -604,7 +666,7 @@ add_sym_3 (const char *name, gfc_isym_id id, enum klass cl, int actual_ok, bt ty
 static void
 add_sym_3ml (const char *name, gfc_isym_id id, enum klass cl, int actual_ok, bt type,
             int kind, int standard,
-            gfc_try (*check) (gfc_actual_arglist *),
+            bool (*check) (gfc_actual_arglist *),
             gfc_expr *(*simplify) (gfc_expr *, gfc_expr *, gfc_expr *),
             void (*resolve) (gfc_expr *, gfc_expr *, gfc_expr *, gfc_expr *),
             const char *a1, bt type1, int kind1, int optional1,
@@ -633,7 +695,7 @@ add_sym_3ml (const char *name, gfc_isym_id id, enum klass cl, int actual_ok, bt
 static void
 add_sym_3red (const char *name, gfc_isym_id id, enum klass cl, int actual_ok, bt type,
              int kind, int standard,
-             gfc_try (*check) (gfc_actual_arglist *),
+             bool (*check) (gfc_actual_arglist *),
              gfc_expr *(*simplify) (gfc_expr *, gfc_expr *, gfc_expr *),
              void (*resolve) (gfc_expr *, gfc_expr *, gfc_expr *, gfc_expr *),
              const char *a1, bt type1, int kind1, int optional1,
@@ -662,7 +724,7 @@ add_sym_3red (const char *name, gfc_isym_id id, enum klass cl, int actual_ok, bt
 static void
 add_sym_3s (const char *name, gfc_isym_id id, enum klass cl, bt type,
            int kind, int standard,
-           gfc_try (*check) (gfc_expr *, gfc_expr *, gfc_expr *),
+           bool (*check) (gfc_expr *, gfc_expr *, gfc_expr *),
            gfc_expr *(*simplify) (gfc_expr *, gfc_expr *, gfc_expr *),
            void (*resolve) (gfc_code *),
            const char *a1, bt type1, int kind1, int optional1,
@@ -692,7 +754,7 @@ add_sym_3s (const char *name, gfc_isym_id id, enum klass cl, bt type,
 static void
 add_sym_4 (const char *name, gfc_isym_id id, enum klass cl, int actual_ok, bt type,
           int kind, int standard,
-          gfc_try (*check) (gfc_expr *, gfc_expr *, gfc_expr *, gfc_expr *),
+          bool (*check) (gfc_expr *, gfc_expr *, gfc_expr *, gfc_expr *),
           gfc_expr *(*simplify) (gfc_expr *, gfc_expr *, gfc_expr *,
                                  gfc_expr *),
           void (*resolve) (gfc_expr *, gfc_expr *, gfc_expr *, gfc_expr *,
@@ -725,7 +787,7 @@ add_sym_4 (const char *name, gfc_isym_id id, enum klass cl, int actual_ok, bt ty
 static void
 add_sym_4s (const char *name, gfc_isym_id id, enum klass cl, bt type, int kind,
            int standard,
-           gfc_try (*check) (gfc_expr *, gfc_expr *, gfc_expr *, gfc_expr *),
+           bool (*check) (gfc_expr *, gfc_expr *, gfc_expr *, gfc_expr *),
            gfc_expr *(*simplify) (gfc_expr *, gfc_expr *, gfc_expr *,
                                   gfc_expr *),
            void (*resolve) (gfc_code *),
@@ -758,7 +820,7 @@ add_sym_4s (const char *name, gfc_isym_id id, enum klass cl, bt type, int kind,
 static void
 add_sym_5s (const char *name, gfc_isym_id id, enum klass cl, bt type, int kind,
            int standard,
-           gfc_try (*check) (gfc_expr *, gfc_expr *, gfc_expr *, gfc_expr *,
+           bool (*check) (gfc_expr *, gfc_expr *, gfc_expr *, gfc_expr *,
                          gfc_expr *),
            gfc_expr *(*simplify) (gfc_expr *, gfc_expr *, gfc_expr *,
                                   gfc_expr *, gfc_expr *),
@@ -814,6 +876,75 @@ find_sym (gfc_intrinsic_sym *start, int n, const char *name)
 }
 
 
+gfc_isym_id
+gfc_isym_id_by_intmod (intmod_id from_intmod, int intmod_sym_id)
+{
+  if (from_intmod == INTMOD_NONE)
+    return (gfc_isym_id) intmod_sym_id;
+  else if (from_intmod == INTMOD_ISO_C_BINDING)
+    return (gfc_isym_id) c_interop_kinds_table[intmod_sym_id].value;
+  else if (from_intmod == INTMOD_ISO_FORTRAN_ENV)
+    switch (intmod_sym_id)
+      {
+#define NAMED_SUBROUTINE(a,b,c,d) \
+      case a: \
+       return (gfc_isym_id) c;
+#define NAMED_FUNCTION(a,b,c,d) \
+      case a: \
+       return (gfc_isym_id) c;
+#include "iso-fortran-env.def"
+      default:
+       gcc_unreachable ();
+      }
+  else
+    gcc_unreachable ();
+  return (gfc_isym_id) 0;
+}
+
+
+gfc_isym_id
+gfc_isym_id_by_intmod_sym (gfc_symbol *sym)
+{
+  return gfc_isym_id_by_intmod (sym->from_intmod, sym->intmod_sym_id);
+}
+
+
+gfc_intrinsic_sym *
+gfc_intrinsic_subroutine_by_id (gfc_isym_id id)
+{
+  gfc_intrinsic_sym *start = subroutines;
+  int n = nsub;
+
+  while (true)
+    {
+      gcc_assert (n > 0);
+      if (id == start->id)
+       return start;
+
+      start++;
+      n--;
+    }
+}
+
+
+gfc_intrinsic_sym *
+gfc_intrinsic_function_by_id (gfc_isym_id id)
+{
+  gfc_intrinsic_sym *start = functions;
+  int n = nfunc;
+
+  while (true)
+    {
+      gcc_assert (n > 0);
+      if (id == start->id)
+       return start;
+
+      start++;
+      n--;
+    }
+}
+
+
 /* Given a name, find a function in the intrinsic function table.
    Returns NULL if not found.  */
 
@@ -823,10 +954,10 @@ gfc_find_function (const char *name)
   gfc_intrinsic_sym *sym;
 
   sym = find_sym (functions, nfunc, name);
-  if (!sym)
+  if (!sym || sym->from_module)
     sym = find_sym (conversion, nconv, name);
 
-  return sym;
+  return (!sym || sym->from_module) ? NULL : sym;
 }
 
 
@@ -836,7 +967,9 @@ gfc_find_function (const char *name)
 gfc_intrinsic_sym *
 gfc_find_subroutine (const char *name)
 {
-  return find_sym (subroutines, nsub, name);
+  gfc_intrinsic_sym *sym;
+  sym = find_sym (subroutines, nsub, name);
+  return (!sym || sym->from_module) ? NULL : sym;
 }
 
 
@@ -849,7 +982,7 @@ gfc_generic_intrinsic (const char *name)
   gfc_intrinsic_sym *sym;
 
   sym = gfc_find_function (name);
-  return (sym == NULL) ? 0 : sym->generic;
+  return (!sym || sym->from_module) ? 0 : sym->generic;
 }
 
 
@@ -862,7 +995,7 @@ gfc_specific_intrinsic (const char *name)
   gfc_intrinsic_sym *sym;
 
   sym = gfc_find_function (name);
-  return (sym == NULL) ? 0 : sym->specific;
+  return (!sym || sym->from_module) ? 0 : sym->specific;
 }
 
 
@@ -884,9 +1017,9 @@ gfc_intrinsic_actual_ok (const char *name, const bool subroutine_flag)
 }
 
 
-/* Given a symbol, find out if it is (and is to be treated) an intrinsic.  If
-   it's name refers to an intrinsic but this intrinsic is not included in the
-   selected standard, this returns FALSE and sets the symbol's external
+/* Given a symbol, find out if it is (and is to be treated as) an intrinsic.
+   If its name refers to an intrinsic, but this intrinsic is not included in
+   the selected standard, this returns FALSE and sets the symbol's external
    attribute.  */
 
 bool
@@ -895,10 +1028,13 @@ gfc_is_intrinsic (gfc_symbol* sym, int subroutine_flag, locus loc)
   gfc_intrinsic_sym* isym;
   const char* symstd;
 
-  /* If INTRINSIC/EXTERNAL state is already known, return.  */
+  /* If INTRINSIC attribute is already known, return.  */
   if (sym->attr.intrinsic)
     return true;
-  if (sym->attr.external)
+
+  /* Check for attributes which prevent the symbol from being INTRINSIC.  */
+  if (sym->attr.external || sym->attr.contained
+      || sym->attr.if_source == IFSRC_IFBODY)
     return false;
 
   if (subroutine_flag)
@@ -911,13 +1047,13 @@ gfc_is_intrinsic (gfc_symbol* sym, int subroutine_flag, locus loc)
     return false;
 
   /* See if this intrinsic is allowed in the current standard.  */
-  if (gfc_check_intrinsic_standard (isym, &symstd, false, loc) == FAILURE)
+  if (!gfc_check_intrinsic_standard (isym, &symstd, false, loc)
+      && !sym->attr.artificial)
     {
-      if (sym->attr.proc == PROC_UNKNOWN
-         && gfc_option.warn_intrinsics_std)
-       gfc_warning_now ("The intrinsic '%s' at %L is not included in the"
-                        " selected standard but %s and '%s' will be"
-                        " treated as if declared EXTERNAL.  Use an"
+      if (sym->attr.proc == PROC_UNKNOWN && warn_intrinsics_std)
+       gfc_warning_now (OPT_Wintrinsics_std, "The intrinsic %qs at %L is not "
+                        "included in the selected standard but %s and %qs will"
+                        " be treated as if declared EXTERNAL.  Use an"
                         " appropriate -std=* option or define"
                         " -fall-intrinsics to allow this intrinsic.",
                         sym->name, &loc, symstd, sym->name);
@@ -950,7 +1086,7 @@ make_generic (const char *name, gfc_isym_id id, int standard ATTRIBUTE_UNUSED)
 
   g = gfc_find_function (name);
   if (g == NULL)
-    gfc_internal_error ("make_generic(): Can't find generic symbol '%s'",
+    gfc_internal_error ("make_generic(): Can't find generic symbol %qs",
                        name);
 
   gcc_assert (g->id == id);
@@ -1014,6 +1150,15 @@ make_noreturn (void)
     next_sym[-1].noreturn = 1;
 }
 
+
+/* Mark current intrinsic as module intrinsic.  */
+static void
+make_from_module (void)
+{
+  if (sizing == SZ_NOTHING)
+    next_sym[-1].from_module = 1;
+}
+
 /* Set the attr.value of the current procedure.  */
 
 static void
@@ -1060,7 +1205,7 @@ add_functions (void)
     *z = "z", *ln = "len", *ut = "unit", *han = "handler",
     *num = "number", *tm = "time", *nm = "name", *md = "mode",
     *vl = "values", *p1 = "path1", *p2 = "path2", *com = "command",
-    *ca = "coarray", *sub = "sub";
+    *ca = "coarray", *sub = "sub", *dist = "distance", *failed="failed";
 
   int di, dr, dd, dl, dc, dz, ii;
 
@@ -1531,8 +1676,8 @@ add_functions (void)
 
   make_generic ("dprod", GFC_ISYM_DPROD, GFC_STD_F77);
 
-  add_sym_1 ("dreal", GFC_ISYM_REAL, CLASS_ELEMENTAL, ACTUAL_NO, BT_REAL, dd, GFC_STD_GNU,
-            NULL, NULL, NULL,
+  add_sym_1 ("dreal", GFC_ISYM_REAL, CLASS_ELEMENTAL, ACTUAL_NO,
+            BT_REAL, dd, GFC_STD_GNU, NULL, gfc_simplify_dreal, NULL,
             a, BT_COMPLEX, dd, REQUIRED);
 
   make_generic ("dreal", GFC_ISYM_REAL, GFC_STD_GNU);
@@ -1637,7 +1782,8 @@ add_functions (void)
 
   add_sym_2 ("extends_type_of", GFC_ISYM_EXTENDS_TYPE_OF, CLASS_INQUIRY,
             ACTUAL_NO, BT_LOGICAL, dl, GFC_STD_F2003,
-            gfc_check_same_type_as, NULL, gfc_resolve_extends_type_of,
+            gfc_check_same_type_as, gfc_simplify_extends_type_of,
+            gfc_resolve_extends_type_of,
             a, BT_UNKNOWN, 0, REQUIRED,
             mo, BT_UNKNOWN, 0, REQUIRED);
 
@@ -2331,8 +2477,11 @@ add_functions (void)
 
   make_generic ("null", GFC_ISYM_NULL, GFC_STD_F95);
 
-  add_sym_0 ("num_images", GFC_ISYM_NUMIMAGES, CLASS_INQUIRY, ACTUAL_NO, BT_INTEGER, di, GFC_STD_F2008,
-            NULL, gfc_simplify_num_images, NULL);
+  add_sym_2 ("num_images", GFC_ISYM_NUM_IMAGES, CLASS_INQUIRY, ACTUAL_NO,
+            BT_INTEGER, di, GFC_STD_F2008,
+            gfc_check_num_images, gfc_simplify_num_images, NULL,
+            dist, BT_INTEGER, di, OPTIONAL,
+            failed, BT_LOGICAL, dl, OPTIONAL);
 
   add_sym_3 ("pack", GFC_ISYM_PACK, CLASS_TRANSFORMATIONAL, ACTUAL_NO, BT_REAL, dr, GFC_STD_F95,
             gfc_check_pack, gfc_simplify_pack, gfc_resolve_pack,
@@ -2405,6 +2554,11 @@ add_functions (void)
 
   make_generic ("range", GFC_ISYM_RANGE, GFC_STD_F95);
 
+  add_sym_1 ("rank", GFC_ISYM_RANK, CLASS_INQUIRY, ACTUAL_NO, BT_INTEGER, di,
+            GFC_STD_F2008_TS, gfc_check_rank, gfc_simplify_rank, gfc_resolve_rank,
+            a, BT_REAL, dr, REQUIRED);
+  make_generic ("rank", GFC_ISYM_RANK, GFC_STD_F2008_TS);
+
   add_sym_2 ("real", GFC_ISYM_REAL, CLASS_ELEMENTAL, ACTUAL_NO, BT_REAL, dr, GFC_STD_F77,
             gfc_check_real, gfc_simplify_real, gfc_resolve_real,
             a, BT_UNKNOWN, dr, REQUIRED, kind, BT_INTEGER, di, OPTIONAL);
@@ -2455,7 +2609,7 @@ add_functions (void)
 
   add_sym_2 ("same_type_as", GFC_ISYM_SAME_TYPE_AS, CLASS_INQUIRY, ACTUAL_NO,
             BT_LOGICAL, dl, GFC_STD_F2003,
-            gfc_check_same_type_as, NULL, NULL,
+            gfc_check_same_type_as, gfc_simplify_same_type_as, NULL,
             a, BT_UNKNOWN, 0, REQUIRED,
             b, BT_UNKNOWN, 0, REQUIRED);
 
@@ -2514,9 +2668,10 @@ add_functions (void)
 
   make_generic ("set_exponent", GFC_ISYM_SET_EXPONENT, GFC_STD_F95);
 
-  add_sym_1 ("shape", GFC_ISYM_SHAPE, CLASS_INQUIRY, ACTUAL_NO, BT_INTEGER, di, GFC_STD_F95,
+  add_sym_2 ("shape", GFC_ISYM_SHAPE, CLASS_INQUIRY, ACTUAL_NO, BT_INTEGER, di, GFC_STD_F95,
             gfc_check_shape, gfc_simplify_shape, gfc_resolve_shape,
-            src, BT_REAL, dr, REQUIRED);
+            src, BT_REAL, dr, REQUIRED,
+            kind, BT_INTEGER, di, OPTIONAL);
 
   make_generic ("shape", GFC_ISYM_SHAPE, GFC_STD_F95);
 
@@ -2560,7 +2715,7 @@ add_functions (void)
 
   add_sym_2 ("signal", GFC_ISYM_SIGNAL, CLASS_IMPURE, ACTUAL_NO, BT_INTEGER,
             di, GFC_STD_GNU, gfc_check_signal, NULL, gfc_resolve_signal,
-            num, BT_INTEGER, di, REQUIRED, han, BT_UNKNOWN, 0, REQUIRED);
+            num, BT_INTEGER, di, REQUIRED, han, BT_VOID, 0, REQUIRED);
 
   make_generic ("signal", GFC_ISYM_SIGNAL, GFC_STD_GNU);
 
@@ -2602,15 +2757,56 @@ add_functions (void)
 
   make_generic ("size", GFC_ISYM_SIZE, GFC_STD_F95);
 
-  add_sym_1 ("sizeof", GFC_ISYM_SIZEOF, CLASS_IMPURE, ACTUAL_NO, BT_INTEGER, ii,
-            GFC_STD_GNU, gfc_check_sizeof, NULL, NULL,
+  /* Obtain the stride for a given dimensions; to be used only internally.
+     "make_from_module" makes it inaccessible for external users.  */
+  add_sym_2 (GFC_PREFIX ("stride"), GFC_ISYM_STRIDE, CLASS_INQUIRY, ACTUAL_NO,
+            BT_INTEGER, gfc_index_integer_kind, GFC_STD_GNU,
+            NULL, NULL, gfc_resolve_stride,
+            ar, BT_REAL, dr, REQUIRED, dm, BT_INTEGER, ii, OPTIONAL);
+  make_from_module();
+
+  add_sym_1 ("sizeof", GFC_ISYM_SIZEOF, CLASS_INQUIRY, ACTUAL_NO,
+            BT_INTEGER, ii, GFC_STD_GNU,
+            gfc_check_sizeof, gfc_simplify_sizeof, NULL,
             x, BT_UNKNOWN, 0, REQUIRED);
 
   make_generic ("sizeof", GFC_ISYM_SIZEOF, GFC_STD_GNU);
-  
+
+  /* The following functions are part of ISO_C_BINDING.  */
+  add_sym_2 ("c_associated", GFC_ISYM_C_ASSOCIATED, CLASS_INQUIRY, ACTUAL_NO,
+            BT_LOGICAL, dl, GFC_STD_F2003, gfc_check_c_associated, NULL, NULL,
+            "C_PTR_1", BT_VOID, 0, REQUIRED,
+            "C_PTR_2", BT_VOID, 0, OPTIONAL);
+  make_from_module();
+
+  add_sym_1 ("c_loc", GFC_ISYM_C_LOC, CLASS_INQUIRY, ACTUAL_NO,
+            BT_VOID, 0, GFC_STD_F2003,
+            gfc_check_c_loc, NULL, gfc_resolve_c_loc,
+            x, BT_UNKNOWN, 0, REQUIRED);
+  make_from_module();
+
+  add_sym_1 ("c_funloc", GFC_ISYM_C_FUNLOC, CLASS_INQUIRY, ACTUAL_NO,
+            BT_VOID, 0, GFC_STD_F2003,
+            gfc_check_c_funloc, NULL, gfc_resolve_c_funloc,
+            x, BT_UNKNOWN, 0, REQUIRED);
+  make_from_module();
+
   add_sym_1 ("c_sizeof", GFC_ISYM_C_SIZEOF, CLASS_INQUIRY, ACTUAL_NO,
-            BT_INTEGER, ii, GFC_STD_F2008, gfc_check_c_sizeof, NULL, NULL,
+            BT_INTEGER, gfc_index_integer_kind, GFC_STD_F2008,
+            gfc_check_c_sizeof, gfc_simplify_sizeof, NULL,
             x, BT_UNKNOWN, 0, REQUIRED);
+  make_from_module();
+
+  /* COMPILER_OPTIONS and COMPILER_VERSION are part of ISO_FORTRAN_ENV.  */  
+  add_sym_0 ("compiler_options", GFC_ISYM_COMPILER_OPTIONS, CLASS_INQUIRY,
+            ACTUAL_NO, BT_CHARACTER, dc, GFC_STD_F2008,
+            NULL, gfc_simplify_compiler_options, NULL);
+  make_from_module();
+
+  add_sym_0 ("compiler_version", GFC_ISYM_COMPILER_VERSION, CLASS_INQUIRY,
+            ACTUAL_NO, BT_CHARACTER, dc, GFC_STD_F2008,
+            NULL, gfc_simplify_compiler_version, NULL);
+  make_from_module();
 
   add_sym_1 ("spacing", GFC_ISYM_SPACING, CLASS_ELEMENTAL, ACTUAL_NO, BT_REAL, dr, GFC_STD_F95,
             gfc_check_x, gfc_simplify_spacing, gfc_resolve_spacing,
@@ -2655,7 +2851,8 @@ add_functions (void)
 
   add_sym_2 ("storage_size", GFC_ISYM_STORAGE_SIZE, CLASS_INQUIRY, ACTUAL_NO,
             BT_INTEGER, di, GFC_STD_F2008,
-            gfc_check_storage_size, NULL, gfc_resolve_storage_size,
+            gfc_check_storage_size, gfc_simplify_storage_size,
+            gfc_resolve_storage_size,
             a, BT_UNKNOWN, 0, REQUIRED,
             kind, BT_INTEGER, di, OPTIONAL);
   
@@ -2698,9 +2895,10 @@ add_functions (void)
 
   make_generic ("tanh", GFC_ISYM_TANH, GFC_STD_F77);
 
-  add_sym_2 ("this_image", GFC_ISYM_THIS_IMAGE, CLASS_INQUIRY, ACTUAL_NO, BT_INTEGER, di, GFC_STD_F2008,
+  add_sym_3 ("this_image", GFC_ISYM_THIS_IMAGE, CLASS_INQUIRY, ACTUAL_NO, BT_INTEGER, di, GFC_STD_F2008,
             gfc_check_this_image, gfc_simplify_this_image, gfc_resolve_this_image,
-            ca, BT_REAL, dr, OPTIONAL, dm, BT_INTEGER, ii, OPTIONAL);
+            ca, BT_REAL, dr, OPTIONAL, dm, BT_INTEGER, ii, OPTIONAL,
+            dist, BT_INTEGER, di, OPTIONAL);
 
   add_sym_0 ("time", GFC_ISYM_TIME, CLASS_IMPURE, ACTUAL_NO, BT_INTEGER,
             di, GFC_STD_GNU, NULL, NULL, gfc_resolve_time);
@@ -2800,6 +2998,13 @@ add_functions (void)
             x, BT_UNKNOWN, 0, REQUIRED);
                
   make_generic ("loc", GFC_ISYM_LOC, GFC_STD_GNU);
+
+  /* The following function is internally used for coarray libray functions.
+     "make_from_module" makes it inaccessible for external users.  */
+  add_sym_1 (GFC_PREFIX ("caf_get"), GFC_ISYM_CAF_GET, CLASS_IMPURE, ACTUAL_NO,
+            BT_REAL, dr, GFC_STD_GNU, NULL, NULL, NULL,
+            x, BT_REAL, dr, REQUIRED);
+  make_from_module();
 }
 
 
@@ -2810,7 +3015,7 @@ add_subroutines (void)
 {
   /* Argument names as in the standard (to be used as argument keywords).  */
   const char
-    *h = "harvest", *dt = "date", *vl = "values", *pt = "put",
+    *a = "a", *h = "harvest", *dt = "date", *vl = "values", *pt = "put",
     *c = "count", *tm = "time", *tp = "topos", *gt = "get",
     *t = "to", *zn = "zone", *fp = "frompos", *cm = "count_max",
     *f = "from", *sz = "size", *ln = "len", *cr = "count_rate",
@@ -2819,7 +3024,8 @@ add_subroutines (void)
     *trim_name = "trim_name", *ut = "unit", *han = "handler",
     *sec = "seconds", *res = "result", *of = "offset", *md = "mode",
     *whence = "whence", *pos = "pos", *ptr = "ptr", *p1 = "path1",
-    *p2 = "path2", *msk = "mask", *old = "old";
+    *p2 = "path2", *msk = "mask", *old = "old", *result_image = "result_image",
+    *stat = "stat", *errmsg = "errmsg";
 
   int di, dr, dc, dl, ii;
 
@@ -2833,6 +3039,91 @@ add_subroutines (void)
 
   make_noreturn();
 
+  add_sym_3s ("atomic_define", GFC_ISYM_ATOMIC_DEF, CLASS_ATOMIC,
+             BT_UNKNOWN, 0, GFC_STD_F2008,
+             gfc_check_atomic_def, NULL, gfc_resolve_atomic_def,
+             "atom", BT_INTEGER, di, REQUIRED, INTENT_OUT,
+             "value", BT_INTEGER, di, REQUIRED, INTENT_IN,
+             stat, BT_INTEGER, di, OPTIONAL, INTENT_OUT);
+
+  add_sym_3s ("atomic_ref", GFC_ISYM_ATOMIC_REF, CLASS_ATOMIC,
+             BT_UNKNOWN, 0, GFC_STD_F2008,
+             gfc_check_atomic_ref, NULL, gfc_resolve_atomic_ref,
+             "value", BT_INTEGER, di, REQUIRED, INTENT_OUT,
+             "atom", BT_INTEGER, di, REQUIRED, INTENT_IN,
+             stat, BT_INTEGER, di, OPTIONAL, INTENT_OUT);
+
+  add_sym_5s ("atomic_cas", GFC_ISYM_ATOMIC_CAS, CLASS_ATOMIC,
+             BT_UNKNOWN, 0, GFC_STD_F2008_TS,
+             gfc_check_atomic_cas, NULL, NULL,
+             "atom", BT_INTEGER, di, REQUIRED, INTENT_INOUT,
+             "old", BT_INTEGER, di, REQUIRED, INTENT_OUT,
+             "compare", BT_INTEGER, di, REQUIRED, INTENT_IN,
+             "new", BT_INTEGER, di, REQUIRED, INTENT_IN,
+             stat, BT_INTEGER, di, OPTIONAL, INTENT_OUT);
+
+  add_sym_3s ("atomic_add", GFC_ISYM_ATOMIC_ADD, CLASS_ATOMIC,
+             BT_UNKNOWN, 0, GFC_STD_F2008_TS,
+             gfc_check_atomic_op, NULL, NULL,
+             "atom", BT_INTEGER, di, REQUIRED, INTENT_OUT,
+             "value", BT_INTEGER, di, REQUIRED, INTENT_IN,
+             stat, BT_INTEGER, di, OPTIONAL, INTENT_OUT);
+
+  add_sym_3s ("atomic_and", GFC_ISYM_ATOMIC_AND, CLASS_ATOMIC,
+             BT_UNKNOWN, 0, GFC_STD_F2008_TS,
+             gfc_check_atomic_op, NULL, NULL,
+             "atom", BT_INTEGER, di, REQUIRED, INTENT_OUT,
+             "value", BT_INTEGER, di, REQUIRED, INTENT_IN,
+             stat, BT_INTEGER, di, OPTIONAL, INTENT_OUT);
+
+  add_sym_3s ("atomic_or", GFC_ISYM_ATOMIC_OR, CLASS_ATOMIC,
+             BT_UNKNOWN, 0, GFC_STD_F2008_TS,
+             gfc_check_atomic_op, NULL, NULL,
+             "atom", BT_INTEGER, di, REQUIRED, INTENT_OUT,
+             "value", BT_INTEGER, di, REQUIRED, INTENT_IN,
+             stat, BT_INTEGER, di, OPTIONAL, INTENT_OUT);
+
+  add_sym_3s ("atomic_xor", GFC_ISYM_ATOMIC_XOR, CLASS_ATOMIC,
+             BT_UNKNOWN, 0, GFC_STD_F2008_TS,
+             gfc_check_atomic_op, NULL, NULL,
+             "atom", BT_INTEGER, di, REQUIRED, INTENT_OUT,
+             "value", BT_INTEGER, di, REQUIRED, INTENT_IN,
+             stat, BT_INTEGER, di, OPTIONAL, INTENT_OUT);
+
+  add_sym_4s ("atomic_fetch_add", GFC_ISYM_ATOMIC_FETCH_ADD, CLASS_ATOMIC,
+             BT_UNKNOWN, 0, GFC_STD_F2008_TS,
+             gfc_check_atomic_fetch_op, NULL, NULL,
+             "atom", BT_INTEGER, di, REQUIRED, INTENT_OUT,
+             "value", BT_INTEGER, di, REQUIRED, INTENT_IN,
+             "old", BT_INTEGER, di, REQUIRED, INTENT_OUT,
+             stat, BT_INTEGER, di, OPTIONAL, INTENT_OUT);
+
+  add_sym_4s ("atomic_fetch_and", GFC_ISYM_ATOMIC_FETCH_AND, CLASS_ATOMIC,
+             BT_UNKNOWN, 0, GFC_STD_F2008_TS,
+             gfc_check_atomic_fetch_op, NULL, NULL,
+             "atom", BT_INTEGER, di, REQUIRED, INTENT_OUT,
+             "value", BT_INTEGER, di, REQUIRED, INTENT_IN,
+             "old", BT_INTEGER, di, REQUIRED, INTENT_OUT,
+             stat, BT_INTEGER, di, OPTIONAL, INTENT_OUT);
+
+  add_sym_4s ("atomic_fetch_or", GFC_ISYM_ATOMIC_FETCH_OR, CLASS_ATOMIC,
+             BT_UNKNOWN, 0, GFC_STD_F2008_TS,
+             gfc_check_atomic_fetch_op, NULL, NULL,
+             "atom", BT_INTEGER, di, REQUIRED, INTENT_OUT,
+             "value", BT_INTEGER, di, REQUIRED, INTENT_IN,
+             "old", BT_INTEGER, di, REQUIRED, INTENT_OUT,
+             stat, BT_INTEGER, di, OPTIONAL, INTENT_OUT);
+
+  add_sym_4s ("atomic_fetch_xor", GFC_ISYM_ATOMIC_FETCH_XOR, CLASS_ATOMIC,
+             BT_UNKNOWN, 0, GFC_STD_F2008_TS,
+             gfc_check_atomic_fetch_op, NULL, NULL,
+             "atom", BT_INTEGER, di, REQUIRED, INTENT_OUT,
+             "value", BT_INTEGER, di, REQUIRED, INTENT_IN,
+             "old", BT_INTEGER, di, REQUIRED, INTENT_OUT,
+             stat, BT_INTEGER, di, OPTIONAL, INTENT_OUT);
+
+  add_sym_0s ("backtrace", GFC_ISYM_BACKTRACE, GFC_STD_GNU, NULL);
+
   add_sym_1s ("cpu_time", GFC_ISYM_CPU_TIME, CLASS_IMPURE, BT_UNKNOWN, 0,
              GFC_STD_F95, gfc_check_cpu_time, NULL, gfc_resolve_cpu_time,
              tm, BT_REAL, dr, REQUIRED, INTENT_OUT);
@@ -2985,6 +3276,74 @@ add_subroutines (void)
              pt, BT_INTEGER, di, OPTIONAL, INTENT_IN,
              gt, BT_INTEGER, di, OPTIONAL, INTENT_OUT);
 
+  /* The following subroutines are part of ISO_C_BINDING.  */
+
+  add_sym_3s ("c_f_pointer", GFC_ISYM_C_F_POINTER, CLASS_IMPURE, BT_UNKNOWN, 0,
+             GFC_STD_F2003, gfc_check_c_f_pointer, NULL, NULL,
+             "cptr", BT_VOID, 0, REQUIRED, INTENT_IN,
+             "fptr", BT_UNKNOWN, 0, REQUIRED, INTENT_OUT,
+             "shape", BT_INTEGER, di, OPTIONAL, INTENT_IN);
+  make_from_module();
+
+  add_sym_2s ("c_f_procpointer", GFC_ISYM_C_F_PROCPOINTER, CLASS_IMPURE,
+             BT_UNKNOWN, 0, GFC_STD_F2003, gfc_check_c_f_procpointer,
+             NULL, NULL,
+             "cptr", BT_VOID, 0, REQUIRED, INTENT_IN,
+             "fptr", BT_UNKNOWN, 0, REQUIRED, INTENT_OUT);
+  make_from_module();
+
+  /* Coarray collectives.  */
+  add_sym_4s ("co_broadcast", GFC_ISYM_CO_BROADCAST, CLASS_IMPURE,
+             BT_UNKNOWN, 0, GFC_STD_F2008_TS,
+             gfc_check_co_broadcast, NULL, NULL,
+             a, BT_REAL, dr, REQUIRED, INTENT_INOUT,
+             "source_image", BT_INTEGER, di, REQUIRED, INTENT_IN,
+             stat, BT_INTEGER, di, OPTIONAL, INTENT_OUT,
+             errmsg, BT_CHARACTER, dc, OPTIONAL, INTENT_OUT);
+
+  add_sym_4s ("co_max", GFC_ISYM_CO_MAX, CLASS_IMPURE,
+             BT_UNKNOWN, 0, GFC_STD_F2008_TS,
+             gfc_check_co_minmax, NULL, NULL,
+             a, BT_REAL, dr, REQUIRED, INTENT_INOUT,
+             result_image, BT_INTEGER, di, OPTIONAL, INTENT_IN,
+             stat, BT_INTEGER, di, OPTIONAL, INTENT_OUT,
+             errmsg, BT_CHARACTER, dc, OPTIONAL, INTENT_OUT);
+
+  add_sym_4s ("co_min", GFC_ISYM_CO_MIN, CLASS_IMPURE,
+             BT_UNKNOWN, 0, GFC_STD_F2008_TS,
+             gfc_check_co_minmax, NULL, NULL,
+             a, BT_REAL, dr, REQUIRED, INTENT_INOUT,
+             result_image, BT_INTEGER, di, OPTIONAL, INTENT_IN,
+             stat, BT_INTEGER, di, OPTIONAL, INTENT_OUT,
+             errmsg, BT_CHARACTER, dc, OPTIONAL, INTENT_OUT);
+
+  add_sym_4s ("co_sum", GFC_ISYM_CO_SUM, CLASS_IMPURE,
+             BT_UNKNOWN, 0, GFC_STD_F2008_TS,
+             gfc_check_co_sum, NULL, NULL,
+             a, BT_REAL, dr, REQUIRED, INTENT_INOUT,
+             result_image, BT_INTEGER, di, OPTIONAL, INTENT_IN,
+             stat, BT_INTEGER, di, OPTIONAL, INTENT_OUT,
+             errmsg, BT_CHARACTER, dc, OPTIONAL, INTENT_OUT);
+
+  add_sym_5s ("co_reduce", GFC_ISYM_CO_REDUCE, CLASS_IMPURE,
+             BT_UNKNOWN, 0, GFC_STD_F2008_TS,
+             gfc_check_co_reduce, NULL, NULL,
+             a, BT_REAL, dr, REQUIRED, INTENT_INOUT,
+             "operator", BT_INTEGER, di, REQUIRED, INTENT_IN,
+             result_image, BT_INTEGER, di, OPTIONAL, INTENT_IN,
+             stat, BT_INTEGER, di, OPTIONAL, INTENT_OUT,
+             errmsg, BT_CHARACTER, dc, OPTIONAL, INTENT_OUT);
+
+
+  /* The following subroutine is internally used for coarray libray functions.
+     "make_from_module" makes it inaccessible for external users.  */
+  add_sym_2s (GFC_PREFIX ("caf_send"), GFC_ISYM_CAF_SEND, CLASS_IMPURE,
+             BT_UNKNOWN, 0, GFC_STD_GNU, NULL, NULL, NULL,
+             "x", BT_REAL, dr, REQUIRED, INTENT_OUT,
+             "y", BT_REAL, dr, REQUIRED, INTENT_IN);
+  make_from_module();
+
+
   /* More G77 compatibility garbage.  */
   add_sym_3s ("alarm", GFC_ISYM_ALARM, CLASS_IMPURE, BT_UNKNOWN, 0, GFC_STD_GNU,
              gfc_check_alarm_sub, NULL, gfc_resolve_alarm_sub,
@@ -3328,8 +3687,6 @@ add_char_conversions (void)
 void
 gfc_intrinsic_init_1 (void)
 {
-  int i;
-
   nargs = nfunc = nsub = nconv = 0;
 
   /* Create a namespace to hold the resolved intrinsic symbols.  */
@@ -3362,24 +3719,15 @@ gfc_intrinsic_init_1 (void)
 
   /* Character conversion intrinsics need to be treated separately.  */
   add_char_conversions ();
-
-  /* Set the pure flag.  All intrinsic functions are pure, and
-     intrinsic subroutines are pure if they are elemental.  */
-
-  for (i = 0; i < nfunc; i++)
-    functions[i].pure = 1;
-
-  for (i = 0; i < nsub; i++)
-    subroutines[i].pure = subroutines[i].elemental;
 }
 
 
 void
 gfc_intrinsic_done_1 (void)
 {
-  gfc_free (functions);
-  gfc_free (conversion);
-  gfc_free (char_conversions);
+  free (functions);
+  free (conversion);
+  free (char_conversions);
   gfc_free_namespace (gfc_intrinsic_namespace);
 }
 
@@ -3427,9 +3775,9 @@ remove_nullargs (gfc_actual_arglist **ap)
    with the format arglist.  Arguments that are not present are given
    a blank gfc_actual_arglist structure.  If something is obviously
    wrong (say, a missing required argument) we abort sorting and
-   return FAILURE.  */
+   return false.  */
 
-static gfc_try
+static bool
 sort_actual (const char *name, gfc_actual_arglist **ap,
             gfc_intrinsic_arg *formal, locus *where)
 {
@@ -3446,7 +3794,7 @@ sort_actual (const char *name, gfc_actual_arglist **ap,
   a = actual;
 
   if (f == NULL && a == NULL)  /* No arguments */
-    return SUCCESS;
+    return true;
 
   for (;;)
     {          /* Put the nonkeyword arguments in a 1:1 correspondence */
@@ -3468,7 +3816,7 @@ sort_actual (const char *name, gfc_actual_arglist **ap,
     goto do_sort;
 
   gfc_error ("Too many arguments in call to '%s' at %L", name, where);
-  return FAILURE;
+  return false;
 
 keywords:
   /* Associate the remaining actual arguments, all of which have
@@ -3487,14 +3835,14 @@ keywords:
          else
            gfc_error ("Can't find keyword named '%s' in call to '%s' at %L",
                       a->name, name, where);
-         return FAILURE;
+         return false;
        }
 
       if (f->actual != NULL)
        {
          gfc_error ("Argument '%s' appears twice in call to '%s' at %L",
                     f->name, name, where);
-         return FAILURE;
+         return false;
        }
 
       f->actual = a;
@@ -3508,7 +3856,7 @@ optional:
        {
          gfc_error ("Missing actual argument '%s' in call to '%s' at %L",
                     f->name, name, where);
-         return FAILURE;
+         return false;
        }
     }
 
@@ -3522,7 +3870,7 @@ do_sort:
       if (f->actual && f->actual->label != NULL && f->ts.type)
        {
          gfc_error ("ALTERNATE RETURN not permitted at %L", where);
-         return FAILURE;
+         return false;
        }
 
       if (f->actual == NULL)
@@ -3542,7 +3890,7 @@ do_sort:
     }
   actual->next = NULL;         /* End the sorted argument list.  */
 
-  return SUCCESS;
+  return true;
 }
 
 
@@ -3550,7 +3898,7 @@ do_sort:
    list.  The lists are checked for agreement of type.  We don't check
    for arrayness here.  */
 
-static gfc_try
+static bool
 check_arglist (gfc_actual_arglist **ap, gfc_intrinsic_sym *sym,
               int error_flag)
 {
@@ -3583,11 +3931,23 @@ check_arglist (gfc_actual_arglist **ap, gfc_intrinsic_sym *sym,
                       gfc_current_intrinsic, &actual->expr->where,
                       gfc_typename (&formal->ts),
                       gfc_typename (&actual->expr->ts));
-         return FAILURE;
+         return false;
+       }
+
+      /* If the formal argument is INTENT([IN]OUT), check for definability.  */
+      if (formal->intent == INTENT_INOUT || formal->intent == INTENT_OUT)
+       {
+         const char* context = (error_flag
+                                ? _("actual argument to INTENT = OUT/INOUT")
+                                : NULL);
+
+         /* No pointer arguments for intrinsics.  */
+         if (!gfc_check_vardef_context (actual->expr, false, false, false, context))
+           return false;
        }
     }
 
-  return SUCCESS;
+  return true;
 }
 
 
@@ -3678,11 +4038,11 @@ resolve_intrinsic (gfc_intrinsic_sym *specific, gfc_expr *e)
 
 /* Given an intrinsic symbol node and an expression node, call the
    simplification function (if there is one), perhaps replacing the
-   expression with something simpler.  We return FAILURE on an error
-   of the simplification, SUCCESS if the simplification worked, even
+   expression with something simpler.  We return false on an error
+   of the simplification, true if the simplification worked, even
    if nothing has changed in the expression itself.  */
 
-static gfc_try
+static bool
 do_simplify (gfc_intrinsic_sym *specific, gfc_expr *e)
 {
   gfc_expr *result, *a1, *a2, *a3, *a4, *a5;
@@ -3766,7 +4126,7 @@ do_simplify (gfc_intrinsic_sym *specific, gfc_expr *e)
 
 finish:
   if (result == &gfc_bad_expr)
-    return FAILURE;
+    return false;
 
   if (result == NULL)
     resolve_intrinsic (specific, e);   /* Must call at run-time */
@@ -3776,12 +4136,12 @@ finish:
       gfc_replace_expr (e, result);
     }
 
-  return SUCCESS;
+  return true;
 }
 
 
 /* Initialize the gfc_current_intrinsic_arg[] array for the benefit of
-   error messages.  This subroutine returns FAILURE if a subroutine
+   error messages.  This subroutine returns false if a subroutine
    has more than MAX_INTRINSIC_ARGS, in which case the actual argument
    list cannot match any intrinsic.  */
 
@@ -3805,14 +4165,14 @@ init_arglist (gfc_intrinsic_sym *isym)
 
 /* Given a pointer to an intrinsic symbol and an expression consisting
    of a function call, see if the function call is consistent with the
-   intrinsic's formal argument list.  Return SUCCESS if the expression
-   and intrinsic match, FAILURE otherwise.  */
+   intrinsic's formal argument list.  Return true if the expression
+   and intrinsic match, false otherwise.  */
 
-static gfc_try
+static bool
 check_specific (gfc_intrinsic_sym *specific, gfc_expr *expr, int error_flag)
 {
   gfc_actual_arglist *arg, **ap;
-  gfc_try t;
+  bool t;
 
   ap = &expr->value.function.actual;
 
@@ -3823,11 +4183,17 @@ check_specific (gfc_intrinsic_sym *specific, gfc_expr *expr, int error_flag)
       || specific->check.f1m == gfc_check_min_max_integer
       || specific->check.f1m == gfc_check_min_max_real
       || specific->check.f1m == gfc_check_min_max_double)
-    return (*specific->check.f1m) (*ap);
+    {
+      if (!do_ts29113_check (specific, *ap))
+       return false;
+      return (*specific->check.f1m) (*ap);
+    }
 
-  if (sort_actual (specific->name, ap, specific->formal,
-                  &expr->where) == FAILURE)
-    return FAILURE;
+  if (!sort_actual (specific->name, ap, specific->formal, &expr->where))
+    return false;
+
+  if (!do_ts29113_check (specific, *ap))
+    return false;
 
   if (specific->check.f3ml == gfc_check_minloc_maxloc)
     /* This is special because we might have to reorder the argument list.  */
@@ -3848,7 +4214,7 @@ check_specific (gfc_intrinsic_sym *specific, gfc_expr *expr, int error_flag)
        if (specific->check.f1 == NULL)
         {
           t = check_arglist (ap, specific, error_flag);
-          if (t == SUCCESS)
+          if (t)
             expr->ts = specific->ts;
         }
        else
@@ -3856,7 +4222,7 @@ check_specific (gfc_intrinsic_sym *specific, gfc_expr *expr, int error_flag)
      }
 
   /* Check conformance of elemental intrinsics.  */
-  if (t == SUCCESS && specific->elemental)
+  if (t && specific->elemental)
     {
       int n = 0;
       gfc_expr *first_expr;
@@ -3867,16 +4233,16 @@ check_specific (gfc_intrinsic_sym *specific, gfc_expr *expr, int error_flag)
       first_expr = arg->expr;
 
       for ( ; arg && arg->expr; arg = arg->next, n++)
-       if (gfc_check_conformance (first_expr, arg->expr,
-                                  "arguments '%s' and '%s' for "
-                                  "intrinsic '%s'",
-                                  gfc_current_intrinsic_arg[0]->name,
-                                  gfc_current_intrinsic_arg[n]->name,
-                                  gfc_current_intrinsic) == FAILURE)
-         return FAILURE;
+       if (!gfc_check_conformance (first_expr, arg->expr, 
+                                   "arguments '%s' and '%s' for "
+                                   "intrinsic '%s'", 
+                                   gfc_current_intrinsic_arg[0]->name, 
+                                   gfc_current_intrinsic_arg[n]->name, 
+                                   gfc_current_intrinsic))
+         return false;
     }
 
-  if (t == FAILURE)
+  if (!t)
     remove_nullargs (ap);
 
   return t;
@@ -3889,9 +4255,9 @@ check_specific (gfc_intrinsic_sym *specific, gfc_expr *expr, int error_flag)
    textual representation of the symbols standard status (like
    "new in Fortran 2008", "a GNU extension" or "obsolescent in Fortran 95") that
    can be used to construct a detailed warning/error message in case of
-   a FAILURE.  */
+   a false.  */
 
-gfc_try
+bool
 gfc_check_intrinsic_standard (const gfc_intrinsic_sym* isym,
                              const char** symstd, bool silent, locus where)
 {
@@ -3899,7 +4265,7 @@ gfc_check_intrinsic_standard (const gfc_intrinsic_sym* isym,
 
   /* For -fall-intrinsics, just succeed.  */
   if (gfc_option.flag_all_intrinsics)
-    return SUCCESS;
+    return true;
 
   /* Find the symbol's standard message for later usage.  */
   switch (isym->standard)
@@ -3928,6 +4294,10 @@ gfc_check_intrinsic_standard (const gfc_intrinsic_sym* isym,
       symstd_msg = "new in Fortran 2008";
       break;
 
+    case GFC_STD_F2008_TS:
+      symstd_msg = "new in TS 29113/TS 18508";
+      break;
+
     case GFC_STD_GNU:
       symstd_msg = "a GNU Fortran extension";
       break;
@@ -3937,7 +4307,7 @@ gfc_check_intrinsic_standard (const gfc_intrinsic_sym* isym,
       break;
 
     default:
-      gfc_internal_error ("Invalid standard code on intrinsic '%s' (%d)",
+      gfc_internal_error ("Invalid standard code on intrinsic %qs (%d)",
                          isym->name, isym->standard);
     }
 
@@ -3949,17 +4319,17 @@ gfc_check_intrinsic_standard (const gfc_intrinsic_sym* isym,
        gfc_warning ("Intrinsic '%s' (is %s) is used at %L",
                     isym->name, _(symstd_msg), &where);
 
-      return SUCCESS;
+      return true;
     }
 
   /* If allowing the symbol's standard, succeed, too.  */
   if (gfc_option.allow_std & isym->standard)
-    return SUCCESS;
+    return true;
 
   /* Otherwise, fail.  */
   if (symstd)
     *symstd = _(symstd_msg);
-  return FAILURE;
+  return false;
 }
 
 
@@ -3985,7 +4355,7 @@ gfc_intrinsic_func_interface (gfc_expr *expr, int error_flag)
   int flag;
 
   if (expr->value.function.isym != NULL)
-    return (do_simplify (expr->value.function.isym, expr) == FAILURE)
+    return (!do_simplify(expr->value.function.isym, expr))
           ? MATCH_ERROR : MATCH_YES;
 
   if (!error_flag)
@@ -3999,7 +4369,14 @@ gfc_intrinsic_func_interface (gfc_expr *expr, int error_flag)
 
   name = expr->symtree->n.sym->name;
 
-  isym = specific = gfc_find_function (name);
+  if (expr->symtree->n.sym->intmod_sym_id)
+    {
+      gfc_isym_id id = gfc_isym_id_by_intmod_sym (expr->symtree->n.sym);
+      isym = specific = gfc_intrinsic_function_by_id (id);
+    }
+  else
+    isym = specific = gfc_find_function (name);
+
   if (isym == NULL)
     {
       if (!error_flag)
@@ -4010,9 +4387,8 @@ gfc_intrinsic_func_interface (gfc_expr *expr, int error_flag)
   if ((isym->id == GFC_ISYM_REAL || isym->id == GFC_ISYM_DBLE
        || isym->id == GFC_ISYM_CMPLX)
       && gfc_init_expr_flag
-      && gfc_notify_std (GFC_STD_F2003, "Fortran 2003: Function '%s' "
-                        "as initialization expression at %L", name,
-                        &expr->where) == FAILURE)
+      && !gfc_notify_std (GFC_STD_F2003, "Function '%s' as initialization "
+                         "expression at %L", name, &expr->where))
     {
       if (!error_flag)
        gfc_pop_suppress_errors ();
@@ -4021,12 +4397,12 @@ gfc_intrinsic_func_interface (gfc_expr *expr, int error_flag)
 
   gfc_current_intrinsic_where = &expr->where;
 
-  /* Bypass the generic list for min and max.  */
+  /* Bypass the generic list for min, max and ISO_C_Binding's c_loc.  */
   if (isym->check.f1m == gfc_check_min_max)
     {
       init_arglist (isym);
 
-      if (gfc_check_min_max (expr->value.function.actual) == SUCCESS)
+      if (isym->check.f1m(expr->value.function.actual))
        goto got_specific;
 
       if (!error_flag)
@@ -4047,7 +4423,7 @@ gfc_intrinsic_func_interface (gfc_expr *expr, int error_flag)
        {
          if (specific == isym)
            continue;
-         if (check_specific (specific, expr, 0) == SUCCESS)
+         if (check_specific (specific, expr, 0))
            {
              gfc_pop_suppress_errors ();
              goto got_specific;
@@ -4057,7 +4433,7 @@ gfc_intrinsic_func_interface (gfc_expr *expr, int error_flag)
 
   gfc_pop_suppress_errors ();
 
-  if (check_specific (isym, expr, error_flag) == FAILURE)
+  if (!check_specific (isym, expr, error_flag))
     {
       if (!error_flag)
        gfc_pop_suppress_errors ();
@@ -4068,12 +4444,13 @@ gfc_intrinsic_func_interface (gfc_expr *expr, int error_flag)
 
 got_specific:
   expr->value.function.isym = specific;
-  gfc_intrinsic_symbol (expr->symtree->n.sym);
+  if (!expr->symtree->n.sym->module)
+    gfc_intrinsic_symbol (expr->symtree->n.sym);
 
   if (!error_flag)
     gfc_pop_suppress_errors ();
 
-  if (do_simplify (specific, expr) == FAILURE)
+  if (!do_simplify (specific, expr))
     return MATCH_ERROR;
 
   /* F95, 7.1.6.1, Initialization expressions
@@ -4086,9 +4463,9 @@ got_specific:
            where each argument is an initialization expression  */
 
   if (gfc_init_expr_flag && isym->elemental && flag
-      && gfc_notify_std (GFC_STD_F2003, "Fortran 2003: Elemental function "
-                       "as initialization expression with non-integer/non-"
-                       "character arguments at %L", &expr->where) == FAILURE)
+      && !gfc_notify_std (GFC_STD_F2003, "Elemental function as "
+                         "initialization expression with non-integer/non-"
+                         "character arguments at %L", &expr->where))
     return MATCH_ERROR;
 
   return MATCH_YES;
@@ -4108,7 +4485,14 @@ gfc_intrinsic_sub_interface (gfc_code *c, int error_flag)
 
   name = c->symtree->n.sym->name;
 
-  isym = gfc_find_subroutine (name);
+  if (c->symtree->n.sym->intmod_sym_id)
+    {
+      gfc_isym_id id;
+      id = gfc_isym_id_by_intmod_sym (c->symtree->n.sym);
+      isym = gfc_intrinsic_subroutine_by_id (id);
+    }
+  else
+    isym = gfc_find_subroutine (name);
   if (isym == NULL)
     return MATCH_NO;
 
@@ -4117,17 +4501,20 @@ gfc_intrinsic_sub_interface (gfc_code *c, int error_flag)
 
   init_arglist (isym);
 
-  if (sort_actual (name, &c->ext.actual, isym->formal, &c->loc) == FAILURE)
+  if (!sort_actual (name, &c->ext.actual, isym->formal, &c->loc))
+    goto fail;
+
+  if (!do_ts29113_check (isym, c->ext.actual))
     goto fail;
 
   if (isym->check.f1 != NULL)
     {
-      if (do_check (isym, c->ext.actual) == FAILURE)
+      if (!do_check (isym, c->ext.actual))
        goto fail;
     }
   else
     {
-      if (check_arglist (&c->ext.actual, isym, 1) == FAILURE)
+      if (!check_arglist (&c->ext.actual, isym, 1))
        goto fail;
     }
 
@@ -4145,13 +4532,23 @@ gfc_intrinsic_sub_interface (gfc_code *c, int error_flag)
       c->resolved_sym->attr.elemental = isym->elemental;
     }
 
-  if (gfc_pure (NULL) && !isym->elemental)
+  if (gfc_do_concurrent_flag && !isym->pure)
+    {
+      gfc_error ("Subroutine call to intrinsic '%s' in DO CONCURRENT "
+                "block at %L is not PURE", name, &c->loc);
+      return MATCH_ERROR;
+    }
+
+  if (!isym->pure && gfc_pure (NULL))
     {
       gfc_error ("Subroutine call to intrinsic '%s' at %L is not PURE", name,
                 &c->loc);
       return MATCH_ERROR;
     }
 
+  if (!isym->pure)
+    gfc_unset_implicit_pure (NULL);
+
   c->resolved_sym->attr.noreturn = isym->noreturn;
 
   return MATCH_YES;
@@ -4165,7 +4562,7 @@ fail:
 
 /* Call gfc_convert_type() with warning enabled.  */
 
-gfc_try
+bool
 gfc_convert_type (gfc_expr *expr, gfc_typespec *ts, int eflag)
 {
   return gfc_convert_type_warn (expr, ts, eflag, 1);
@@ -4182,7 +4579,7 @@ gfc_convert_type (gfc_expr *expr, gfc_typespec *ts, int eflag)
 
    'wflag' controls the warning related to conversion.  */
 
-gfc_try
+bool
 gfc_convert_type_warn (gfc_expr *expr, gfc_typespec *ts, int eflag, int wflag)
 {
   gfc_intrinsic_sym *sym;
@@ -4203,7 +4600,7 @@ gfc_convert_type_warn (gfc_expr *expr, gfc_typespec *ts, int eflag, int wflag)
     {
       /* Sometimes the RHS acquire the type.  */
       expr->ts = *ts;
-      return SUCCESS;
+      return true;
     }
 
   if (expr->ts.type == BT_UNKNOWN)
@@ -4211,7 +4608,7 @@ gfc_convert_type_warn (gfc_expr *expr, gfc_typespec *ts, int eflag, int wflag)
 
   if (expr->ts.type == BT_DERIVED && ts->type == BT_DERIVED
       && gfc_compare_types (&expr->ts, ts))
-    return SUCCESS;
+    return true;
 
   sym = find_conv (&expr->ts, ts);
   if (sym == NULL)
@@ -4254,14 +4651,14 @@ gfc_convert_type_warn (gfc_expr *expr, gfc_typespec *ts, int eflag, int wflag)
          /* Larger kinds can hold values of smaller kinds without problems.
             Hence, only warn if target kind is smaller than the source
             kind - or if -Wconversion-extra is specified.  */
-         if (gfc_option.warn_conversion_extra)
-           gfc_warning_now ("Conversion from %s to %s at %L",
+         if (warn_conversion && from_ts.kind > ts->kind)
+           gfc_warning_now (OPT_Wconversion, "Possible change of value in "
+                            "conversion from %s to %s at %L",
                             gfc_typename (&from_ts), gfc_typename (ts),
                             &expr->where);
-         else if (gfc_option.warn_conversion
-                  && from_ts.kind > ts->kind)
-           gfc_warning_now ("Possible change of value in conversion "
-                            "from %s to %s at %L", gfc_typename (&from_ts),
+         else if (warn_conversion_extra)
+           gfc_warning_now (OPT_Wconversion_extra, "Conversion from %s to %s "
+                            "at %L", gfc_typename (&from_ts),
                             gfc_typename (ts), &expr->where);
        }
       else if ((from_ts.type == BT_REAL && ts->type == BT_INTEGER)
@@ -4270,18 +4667,17 @@ gfc_convert_type_warn (gfc_expr *expr, gfc_typespec *ts, int eflag, int wflag)
        {
          /* Conversion from REAL/COMPLEX to INTEGER or COMPLEX to REAL
             usually comes with a loss of information, regardless of kinds.  */
-         if (gfc_option.warn_conversion_extra
-             || gfc_option.warn_conversion)
-           gfc_warning_now ("Possible change of value in conversion "
-                            "from %s to %s at %L", gfc_typename (&from_ts),
-                            gfc_typename (ts), &expr->where);
+         if (warn_conversion)
+           gfc_warning_now (OPT_Wconversion, "Possible change of value in "
+                            "conversion from %s to %s at %L",
+                            gfc_typename (&from_ts), gfc_typename (ts),
+                            &expr->where);
        }
       else if (from_ts.type == BT_HOLLERITH || ts->type == BT_HOLLERITH)
        {
          /* If HOLLERITH is involved, all bets are off.  */
-         if (gfc_option.warn_conversion_extra
-             || gfc_option.warn_conversion)
-           gfc_warning_now ("Conversion from %s to %s at %L",
+         if (warn_conversion)
+           gfc_warning_now (OPT_Wconversion, "Conversion from %s to %s at %L",
                             gfc_typename (&from_ts), gfc_typename (ts),
                             &expr->where);
        }
@@ -4317,36 +4713,36 @@ gfc_convert_type_warn (gfc_expr *expr, gfc_typespec *ts, int eflag, int wflag)
 
   *expr = *new_expr;
 
-  gfc_free (new_expr);
+  free (new_expr);
   expr->ts = *ts;
 
   if (gfc_is_constant_expr (expr->value.function.actual->expr)
-      && do_simplify (sym, expr) == FAILURE)
+      && !do_simplify (sym, expr))
     {
 
       if (eflag == 2)
        goto bad;
-      return FAILURE;          /* Error already generated in do_simplify() */
+      return false;            /* Error already generated in do_simplify() */
     }
 
-  return SUCCESS;
+  return true;
 
 bad:
   if (eflag == 1)
     {
       gfc_error ("Can't convert %s to %s at %L",
                 gfc_typename (&from_ts), gfc_typename (ts), &expr->where);
-      return FAILURE;
+      return false;
     }
 
-  gfc_internal_error ("Can't convert %s to %s at %L",
+  gfc_internal_error ("Can't convert %qs to %qs at %L",
                      gfc_typename (&from_ts), gfc_typename (ts),
                      &expr->where);
   /* Not reached */
 }
 
 
-gfc_try
+bool
 gfc_convert_chartype (gfc_expr *expr, gfc_typespec *ts)
 {
   gfc_intrinsic_sym *sym;
@@ -4386,17 +4782,17 @@ gfc_convert_chartype (gfc_expr *expr, gfc_typespec *ts)
 
   *expr = *new_expr;
 
-  gfc_free (new_expr);
+  free (new_expr);
   expr->ts = *ts;
 
   if (gfc_is_constant_expr (expr->value.function.actual->expr)
-      && do_simplify (sym, expr) == FAILURE)
+      && !do_simplify (sym, expr))
     {
       /* Error already generated in do_simplify() */
-      return FAILURE;
+      return false;
     }
 
-  return SUCCESS;
+  return true;
 }
 
 
@@ -4411,7 +4807,7 @@ gfc_warn_intrinsic_shadow (const gfc_symbol* sym, bool in_module, bool func)
   gfc_intrinsic_sym* isym;
 
   /* If the warning is disabled, do nothing at all.  */
-  if (!gfc_option.warn_intrinsic_shadow)
+  if (!warn_intrinsic_shadow)
     return;
 
   /* Try to find an intrinsic of the same name.  */
@@ -4422,12 +4818,12 @@ gfc_warn_intrinsic_shadow (const gfc_symbol* sym, bool in_module, bool func)
 
   /* If no intrinsic was found with this name or it's not included in the
      selected standard, everything's fine.  */
-  if (!isym || gfc_check_intrinsic_standard (isym, NULL, true,
-                                            sym->declared_at) == FAILURE)
+  if (!isym || !gfc_check_intrinsic_standard (isym, NULL, true, 
+                                             sym->declared_at))
     return;
 
   /* Emit the warning.  */
-  if (in_module)
+  if (in_module || sym->ns->proc_name)
     gfc_warning ("'%s' declared at %L may shadow the intrinsic of the same"
                 " name.  In order to call the intrinsic, explicit INTRINSIC"
                 " declarations may be required.",