aboutsummaryrefslogtreecommitdiff
path: root/gcc/fortran
diff options
context:
space:
mode:
authorTobias Burnus <burnus@net-b.de>2013-04-16 22:54:21 +0200
committerTobias Burnus <burnus@gcc.gnu.org>2013-04-16 22:54:21 +0200
commite7ac6a7cebc7af45319ac1b88d3f6071f0fed49e (patch)
treeae48f47ebf76afba5e32eeb6ff8fdc0fcb516a97 /gcc/fortran
parentbafa0782ad3ba8e5c92196b00d76b38d69e3e1e1 (diff)
downloadgcc-e7ac6a7cebc7af45319ac1b88d3f6071f0fed49e.zip
gcc-e7ac6a7cebc7af45319ac1b88d3f6071f0fed49e.tar.gz
gcc-e7ac6a7cebc7af45319ac1b88d3f6071f0fed49e.tar.bz2
re PR fortran/39505 (Consider a 'no arg check' directive)
2013-04-12 Tobias Burnus <burnus@net-b.de> PR fortran/39505 * decl.c (ext_attr_list): Add EXT_ATTR_NO_ARG_CHECK. * gfortran.h (ext_attr_id_t): Ditto. * gfortran.texi (GNU Fortran Compiler Directives): Document it. * interface.c (compare_type_rank): Ignore rank for NO_ARG_CHECK. (compare_parameter): Ditto - and regard as unlimited polymorphic. * resolve.c (resolve_symbol, resolve_variable): Add same * constraint checks as for TYPE(*); turn dummy to TYPE(*),dimension(*). (gfc_explicit_interface_required): Require explicit interface for NO_ARG_CHECK. 2013-04-12 Tobias Burnus <burnus@net-b.de> PR fortran/39505 * gfortran.dg/no_arg_check_1.f90: New. * gfortran.dg/no_arg_check_2.f90: New. * gfortran.dg/no_arg_check_3.f90: New. From-SVN: r198011
Diffstat (limited to 'gcc/fortran')
-rw-r--r--gcc/fortran/ChangeLog14
-rw-r--r--gcc/fortran/decl.c13
-rw-r--r--gcc/fortran/gfortran.h1
-rw-r--r--gcc/fortran/gfortran.texi23
-rw-r--r--gcc/fortran/interface.c9
-rw-r--r--gcc/fortran/resolve.c97
6 files changed, 141 insertions, 16 deletions
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
index ee160b6..2f99025 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -1,3 +1,17 @@
+2013-04-16 Tobias Burnus <burnus@net-b.de>
+
+ PR fortran/39505
+ * decl.c (ext_attr_list): Add EXT_ATTR_NO_ARG_CHECK.
+ * gfortran.h (ext_attr_id_t): Ditto.
+ * gfortran.texi (GNU Fortran Compiler Directives):
+ Document it.
+ * interface.c (compare_type_rank): Ignore rank for NO_ARG_CHECK.
+ (compare_parameter): Ditto - and regard as unlimited polymorphic.
+ * resolve.c (resolve_symbol, resolve_variable): Add same constraint
+ checks as for TYPE(*); turn dummy to TYPE(*),dimension(*).
+ (gfc_explicit_interface_required): Require explicit interface
+ for NO_ARG_CHECK.
+
2013-04-16 Janus Weil <janus@gcc.gnu.org>
PR fortran/56968
diff --git a/gcc/fortran/decl.c b/gcc/fortran/decl.c
index ffaa65d..f9891c9 100644
--- a/gcc/fortran/decl.c
+++ b/gcc/fortran/decl.c
@@ -8572,12 +8572,13 @@ gfc_match_final_decl (void)
const ext_attr_t ext_attr_list[] = {
- { "dllimport", EXT_ATTR_DLLIMPORT, "dllimport" },
- { "dllexport", EXT_ATTR_DLLEXPORT, "dllexport" },
- { "cdecl", EXT_ATTR_CDECL, "cdecl" },
- { "stdcall", EXT_ATTR_STDCALL, "stdcall" },
- { "fastcall", EXT_ATTR_FASTCALL, "fastcall" },
- { NULL, EXT_ATTR_LAST, NULL }
+ { "dllimport", EXT_ATTR_DLLIMPORT, "dllimport" },
+ { "dllexport", EXT_ATTR_DLLEXPORT, "dllexport" },
+ { "cdecl", EXT_ATTR_CDECL, "cdecl" },
+ { "stdcall", EXT_ATTR_STDCALL, "stdcall" },
+ { "fastcall", EXT_ATTR_FASTCALL, "fastcall" },
+ { "no_arg_check", EXT_ATTR_NO_ARG_CHECK, NULL },
+ { NULL, EXT_ATTR_LAST, NULL }
};
/* Match a !GCC$ ATTRIBUTES statement of the form:
diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h
index a69cea2..27662f7 100644
--- a/gcc/fortran/gfortran.h
+++ b/gcc/fortran/gfortran.h
@@ -679,6 +679,7 @@ typedef enum
EXT_ATTR_STDCALL,
EXT_ATTR_CDECL,
EXT_ATTR_FASTCALL,
+ EXT_ATTR_NO_ARG_CHECK,
EXT_ATTR_LAST, EXT_ATTR_NUM = EXT_ATTR_LAST
}
ext_attr_id_t;
diff --git a/gcc/fortran/gfortran.texi b/gcc/fortran/gfortran.texi
index 61cb3bb..f4bcdef 100644
--- a/gcc/fortran/gfortran.texi
+++ b/gcc/fortran/gfortran.texi
@@ -2688,6 +2688,29 @@ are in a shared library. The following attributes are available:
@item @code{DLLIMPORT} -- reference the function or variable using a global pointer
@end itemize
+For dummy arguments, the @code{NO_ARG_CHECK} attribute can be used; in
+other compilers, it is also known as @code{IGNORE_TKR}. For dummy arguments
+with this attribute actual arguments of any type and kind (similar to
+@code{TYPE(*)}), scalars and arrays of any rank (no equivalent
+in Fortran standard) are accepted. As with @code{TYPE(*)}, the argument
+is unlimited polymorphic and no type information is available.
+Additionally, the same restrictions apply, i.e. the argument may only be
+passed to dummy arguments with the @code{NO_ARG_CHECK} attribute and as
+argument to the @code{C_LOC} intrinsic function of the @code{ISO_C_BINDING}
+module.
+
+Variables with @code{NO_ARG_CHECK} attribute shall be of assumed-type
+(@code{TYPE(*)}; recommended) or of an intrinsic numeric type; they
+shall not have the @code{ALLOCATE}, @code{CODIMENSION}, @code{INTENT(OUT)},
+@code{POINTER} or @code{VALUE} attribute; furthermore, they shall be
+either scalar or of assumed-size (@code{dimension(*)}). As @code{TYPE(*)},
+the @code{NO_ARG_CHECK} attribute requires an explicit interface.
+
+@itemize
+@item @code{NO_ARG_CHECK} -- disable the type, kind and rank checking
+@end itemize
+
+
The attributes are specified using the syntax
@code{!GCC$ ATTRIBUTES} @var{attribute-list} @code{::} @var{variable-list}
diff --git a/gcc/fortran/interface.c b/gcc/fortran/interface.c
index 7414164..8f7cad7 100644
--- a/gcc/fortran/interface.c
+++ b/gcc/fortran/interface.c
@@ -518,6 +518,10 @@ compare_type_rank (gfc_symbol *s1, gfc_symbol *s2)
gfc_array_spec *as1, *as2;
int r1, r2;
+ if (s1->attr.ext_attr & (1 << EXT_ATTR_NO_ARG_CHECK)
+ || s2->attr.ext_attr & (1 << EXT_ATTR_NO_ARG_CHECK))
+ return 1;
+
as1 = (s1->ts.type == BT_CLASS) ? CLASS_DATA (s1)->as : s1->as;
as2 = (s2->ts.type == BT_CLASS) ? CLASS_DATA (s2)->as : s2->as;
@@ -1900,6 +1904,7 @@ compare_parameter (gfc_symbol *formal, gfc_expr *actual,
if ((actual->expr_type != EXPR_NULL || actual->ts.type != BT_UNKNOWN)
&& actual->ts.type != BT_HOLLERITH
&& formal->ts.type != BT_ASSUMED
+ && !(formal->attr.ext_attr & (1 << EXT_ATTR_NO_ARG_CHECK))
&& !gfc_compare_types (&formal->ts, &actual->ts)
&& !(formal->ts.type == BT_DERIVED && actual->ts.type == BT_CLASS
&& gfc_compare_derived_types (formal->ts.u.derived,
@@ -2060,6 +2065,10 @@ compare_parameter (gfc_symbol *formal, gfc_expr *actual,
|| formal->as->type == AS_DEFERRED)
&& actual->expr_type != EXPR_NULL;
+ /* Skip rank checks for NO_ARG_CHECK. */
+ if (formal->attr.ext_attr & (1 << EXT_ATTR_NO_ARG_CHECK))
+ return 1;
+
/* Scalar & coindexed, see: F2008, Section 12.5.2.4. */
if (rank_check || ranks_must_agree
|| (formal->attr.pointer && actual->expr_type != EXPR_NULL)
diff --git a/gcc/fortran/resolve.c b/gcc/fortran/resolve.c
index 684d205..90bce53 100644
--- a/gcc/fortran/resolve.c
+++ b/gcc/fortran/resolve.c
@@ -2191,6 +2191,11 @@ gfc_explicit_interface_required (gfc_symbol *sym, char *errmsg, int err_len)
strncpy (errmsg, _("polymorphic argument"), err_len);
return true;
}
+ else if (arg->sym->attr.ext_attr & (1 << EXT_ATTR_NO_ARG_CHECK))
+ {
+ strncpy (errmsg, _("NO_ARG_CHECK attribute"), err_len);
+ return true;
+ }
else if (arg->sym->ts.type == BT_ASSUMED)
{
/* As assumed-type is unlimited polymorphic (cf. above).
@@ -4644,8 +4649,19 @@ resolve_variable (gfc_expr *e)
return false;
sym = e->symtree->n.sym;
+ /* Use same check as for TYPE(*) below; this check has to be before TYPE(*)
+ as ts.type is set to BT_ASSUMED in resolve_symbol. */
+ if (sym->attr.ext_attr & (1 << EXT_ATTR_NO_ARG_CHECK))
+ {
+ if (!actual_arg || inquiry_argument)
+ {
+ gfc_error ("Variable %s at %L with NO_ARG_CHECK attribute may only "
+ "be used as actual argument", sym->name, &e->where);
+ return false;
+ }
+ }
/* TS 29113, 407b. */
- if (e->ts.type == BT_ASSUMED)
+ else if (e->ts.type == BT_ASSUMED)
{
if (!actual_arg)
{
@@ -4665,13 +4681,12 @@ resolve_variable (gfc_expr *e)
return false;
}
}
-
/* TS 29113, C535b. */
- if ((sym->ts.type == BT_CLASS && sym->attr.class_ok
- && CLASS_DATA (sym)->as
- && CLASS_DATA (sym)->as->type == AS_ASSUMED_RANK)
- || (sym->ts.type != BT_CLASS && sym->as
- && sym->as->type == AS_ASSUMED_RANK))
+ else if ((sym->ts.type == BT_CLASS && sym->attr.class_ok
+ && CLASS_DATA (sym)->as
+ && CLASS_DATA (sym)->as->type == AS_ASSUMED_RANK)
+ || (sym->ts.type != BT_CLASS && sym->as
+ && sym->as->type == AS_ASSUMED_RANK))
{
if (!actual_arg)
{
@@ -4692,11 +4707,19 @@ resolve_variable (gfc_expr *e)
}
}
- /* TS 29113, 407b. */
- if (e->ts.type == BT_ASSUMED && e->ref
+ if ((sym->attr.ext_attr & (1 << EXT_ATTR_NO_ARG_CHECK)) && e->ref
&& !(e->ref->type == REF_ARRAY && e->ref->u.ar.type == AR_FULL
&& e->ref->next == NULL))
{
+ gfc_error ("Variable %s at %L with NO_ARG_CHECK attribute shall not have "
+ "a subobject reference", sym->name, &e->ref->u.ar.where);
+ return false;
+ }
+ /* TS 29113, 407b. */
+ else if (e->ts.type == BT_ASSUMED && e->ref
+ && !(e->ref->type == REF_ARRAY && e->ref->u.ar.type == AR_FULL
+ && e->ref->next == NULL))
+ {
gfc_error ("Assumed-type variable %s at %L shall not have a subobject "
"reference", sym->name, &e->ref->u.ar.where);
return false;
@@ -12837,7 +12860,61 @@ resolve_symbol (gfc_symbol *sym)
}
}
- if (sym->ts.type == BT_ASSUMED)
+ /* Use the same constraints as TYPE(*), except for the type check
+ and that only scalars and assumed-size arrays are permitted. */
+ if (sym->attr.ext_attr & (1 << EXT_ATTR_NO_ARG_CHECK))
+ {
+ if (!sym->attr.dummy)
+ {
+ gfc_error ("Variable %s at %L with NO_ARG_CHECK attribute shall be "
+ "a dummy argument", sym->name, &sym->declared_at);
+ return;
+ }
+
+ if (sym->ts.type != BT_ASSUMED && sym->ts.type != BT_INTEGER
+ && sym->ts.type != BT_REAL && sym->ts.type != BT_LOGICAL
+ && sym->ts.type != BT_COMPLEX)
+ {
+ gfc_error ("Variable %s at %L with NO_ARG_CHECK attribute shall be "
+ "of type TYPE(*) or of an numeric intrinsic type",
+ sym->name, &sym->declared_at);
+ return;
+ }
+
+ if (sym->attr.allocatable || sym->attr.codimension
+ || sym->attr.pointer || sym->attr.value)
+ {
+ gfc_error ("Variable %s at %L with NO_ARG_CHECK attribute may not "
+ "have the ALLOCATABLE, CODIMENSION, POINTER or VALUE "
+ "attribute", sym->name, &sym->declared_at);
+ return;
+ }
+
+ if (sym->attr.intent == INTENT_OUT)
+ {
+ gfc_error ("Variable %s at %L with NO_ARG_CHECK attribute may not "
+ "have the INTENT(OUT) attribute",
+ sym->name, &sym->declared_at);
+ return;
+ }
+ if (sym->attr.dimension && sym->as->type != AS_ASSUMED_SIZE)
+ {
+ gfc_error ("Variable %s at %L with NO_ARG_CHECK attribute shall "
+ "either be a scalar or an assumed-size array",
+ sym->name, &sym->declared_at);
+ return;
+ }
+
+ /* Set the type to TYPE(*) and add a dimension(*) to ensure
+ NO_ARG_CHECK is correctly handled in trans*.c, e.g. with
+ packing. */
+ sym->ts.type = BT_ASSUMED;
+ sym->as = gfc_get_array_spec ();
+ sym->as->type = AS_ASSUMED_SIZE;
+ sym->as->rank = 1;
+ sym->as->lower[0] = gfc_get_int_expr (gfc_default_integer_kind, NULL, 1);
+ }
+ else if (sym->ts.type == BT_ASSUMED)
{
/* TS 29113, C407a. */
if (!sym->attr.dummy)