aboutsummaryrefslogtreecommitdiff
path: root/gcc/fortran/resolve.c
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@golang.org>2021-09-13 10:37:49 -0700
committerIan Lance Taylor <iant@golang.org>2021-09-13 10:37:49 -0700
commite252b51ccde010cbd2a146485d8045103cd99533 (patch)
treee060f101cdc32bf5e520de8e5275db9d4236b74c /gcc/fortran/resolve.c
parentf10c7c4596dda99d2ee872c995ae4aeda65adbdf (diff)
parent104c05c5284b7822d770ee51a7d91946c7e56d50 (diff)
downloadgcc-e252b51ccde010cbd2a146485d8045103cd99533.zip
gcc-e252b51ccde010cbd2a146485d8045103cd99533.tar.gz
gcc-e252b51ccde010cbd2a146485d8045103cd99533.tar.bz2
Merge from trunk revision 104c05c5284b7822d770ee51a7d91946c7e56d50.
Diffstat (limited to 'gcc/fortran/resolve.c')
-rw-r--r--gcc/fortran/resolve.c220
1 files changed, 155 insertions, 65 deletions
diff --git a/gcc/fortran/resolve.c b/gcc/fortran/resolve.c
index 32015c2..8e5ed1c 100644
--- a/gcc/fortran/resolve.c
+++ b/gcc/fortran/resolve.c
@@ -804,6 +804,15 @@ resolve_entries (gfc_namespace *ns)
the same string length, i.e. both len=*, or both len=4.
Having both len=<variable> is also possible, but difficult to
check at compile time. */
+ else if (ts->type == BT_CHARACTER
+ && (el->sym->result->attr.allocatable
+ != ns->entries->sym->result->attr.allocatable))
+ {
+ gfc_error ("Function %s at %L has entry %s with mismatched "
+ "characteristics", ns->entries->sym->name,
+ &ns->entries->sym->declared_at, el->sym->name);
+ return;
+ }
else if (ts->type == BT_CHARACTER && ts->u.cl && fts->u.cl
&& (((ts->u.cl->length && !fts->u.cl->length)
||(!ts->u.cl->length && fts->u.cl->length))
@@ -970,7 +979,7 @@ resolve_common_vars (gfc_common_head *common_block, bool named_common)
}
if (UNLIMITED_POLY (csym))
- gfc_error_now ("%qs in cannot appear in COMMON at %L "
+ gfc_error_now ("%qs at %L cannot appear in COMMON "
"[F2008:C5100]", csym->name, &csym->declared_at);
if (csym->ts.type != BT_DERIVED)
@@ -3994,7 +4003,8 @@ static bool
resolve_operator (gfc_expr *e)
{
gfc_expr *op1, *op2;
- char msg[200];
+ /* One error uses 3 names; additional space for wording (also via gettext). */
+ char msg[3*GFC_MAX_SYMBOL_LEN + 1 + 50];
bool dual_locus_error;
bool t = true;
@@ -4047,7 +4057,8 @@ resolve_operator (gfc_expr *e)
if ((op1 && op1->expr_type == EXPR_NULL)
|| (op2 && op2->expr_type == EXPR_NULL))
{
- sprintf (msg, _("Invalid context for NULL() pointer at %%L"));
+ snprintf (msg, sizeof (msg),
+ _("Invalid context for NULL() pointer at %%L"));
goto bad_op;
}
@@ -4063,8 +4074,9 @@ resolve_operator (gfc_expr *e)
break;
}
- sprintf (msg, _("Operand of unary numeric operator %%<%s%%> at %%L is %s"),
- gfc_op2string (e->value.op.op), gfc_typename (e));
+ snprintf (msg, sizeof (msg),
+ _("Operand of unary numeric operator %%<%s%%> at %%L is %s"),
+ gfc_op2string (e->value.op.op), gfc_typename (e));
goto bad_op;
case INTRINSIC_PLUS:
@@ -4079,14 +4091,14 @@ resolve_operator (gfc_expr *e)
}
if (op1->ts.type == BT_DERIVED || op2->ts.type == BT_DERIVED)
- sprintf (msg,
- _("Unexpected derived-type entities in binary intrinsic "
- "numeric operator %%<%s%%> at %%L"),
+ snprintf (msg, sizeof (msg),
+ _("Unexpected derived-type entities in binary intrinsic "
+ "numeric operator %%<%s%%> at %%L"),
gfc_op2string (e->value.op.op));
else
- sprintf (msg,
- _("Operands of binary numeric operator %%<%s%%> at %%L are %s/%s"),
- gfc_op2string (e->value.op.op), gfc_typename (op1),
+ snprintf (msg, sizeof(msg),
+ _("Operands of binary numeric operator %%<%s%%> at %%L are %s/%s"),
+ gfc_op2string (e->value.op.op), gfc_typename (op1),
gfc_typename (op2));
goto bad_op;
@@ -4099,9 +4111,9 @@ resolve_operator (gfc_expr *e)
break;
}
- sprintf (msg,
- _("Operands of string concatenation operator at %%L are %s/%s"),
- gfc_typename (op1), gfc_typename (op2));
+ snprintf (msg, sizeof (msg),
+ _("Operands of string concatenation operator at %%L are %s/%s"),
+ gfc_typename (op1), gfc_typename (op2));
goto bad_op;
case INTRINSIC_AND:
@@ -4142,9 +4154,10 @@ resolve_operator (gfc_expr *e)
goto simplify_op;
}
- sprintf (msg, _("Operands of logical operator %%<%s%%> at %%L are %s/%s"),
- gfc_op2string (e->value.op.op), gfc_typename (op1),
- gfc_typename (op2));
+ snprintf (msg, sizeof (msg),
+ _("Operands of logical operator %%<%s%%> at %%L are %s/%s"),
+ gfc_op2string (e->value.op.op), gfc_typename (op1),
+ gfc_typename (op2));
goto bad_op;
@@ -4165,8 +4178,8 @@ resolve_operator (gfc_expr *e)
break;
}
- sprintf (msg, _("Operand of .not. operator at %%L is %s"),
- gfc_typename (op1));
+ snprintf (msg, sizeof (msg), _("Operand of .not. operator at %%L is %s"),
+ gfc_typename (op1));
goto bad_op;
case INTRINSIC_GT:
@@ -4276,16 +4289,16 @@ resolve_operator (gfc_expr *e)
}
if (op1->ts.type == BT_LOGICAL && op2->ts.type == BT_LOGICAL)
- sprintf (msg,
- _("Logicals at %%L must be compared with %s instead of %s"),
- (e->value.op.op == INTRINSIC_EQ
- || e->value.op.op == INTRINSIC_EQ_OS)
- ? ".eqv." : ".neqv.", gfc_op2string (e->value.op.op));
+ snprintf (msg, sizeof (msg),
+ _("Logicals at %%L must be compared with %s instead of %s"),
+ (e->value.op.op == INTRINSIC_EQ
+ || e->value.op.op == INTRINSIC_EQ_OS)
+ ? ".eqv." : ".neqv.", gfc_op2string (e->value.op.op));
else
- sprintf (msg,
- _("Operands of comparison operator %%<%s%%> at %%L are %s/%s"),
- gfc_op2string (e->value.op.op), gfc_typename (op1),
- gfc_typename (op2));
+ snprintf (msg, sizeof (msg),
+ _("Operands of comparison operator %%<%s%%> at %%L are %s/%s"),
+ gfc_op2string (e->value.op.op), gfc_typename (op1),
+ gfc_typename (op2));
goto bad_op;
@@ -4296,19 +4309,23 @@ resolve_operator (gfc_expr *e)
const char *guessed;
guessed = lookup_uop_fuzzy (name, e->value.op.uop->ns->uop_root);
if (guessed)
- sprintf (msg, _("Unknown operator %%<%s%%> at %%L; did you mean '%s'?"),
- name, guessed);
+ snprintf (msg, sizeof (msg),
+ _("Unknown operator %%<%s%%> at %%L; did you mean '%s'?"),
+ name, guessed);
else
- sprintf (msg, _("Unknown operator %%<%s%%> at %%L"), name);
+ snprintf (msg, sizeof (msg), _("Unknown operator %%<%s%%> at %%L"),
+ name);
}
else if (op2 == NULL)
- sprintf (msg, _("Operand of user operator %%<%s%%> at %%L is %s"),
- e->value.op.uop->name, gfc_typename (op1));
+ snprintf (msg, sizeof (msg),
+ _("Operand of user operator %%<%s%%> at %%L is %s"),
+ e->value.op.uop->name, gfc_typename (op1));
else
{
- sprintf (msg, _("Operands of user operator %%<%s%%> at %%L are %s/%s"),
- e->value.op.uop->name, gfc_typename (op1),
- gfc_typename (op2));
+ snprintf (msg, sizeof (msg),
+ _("Operands of user operator %%<%s%%> at %%L are %s/%s"),
+ e->value.op.uop->name, gfc_typename (op1),
+ gfc_typename (op2));
e->value.op.uop->op->sym->attr.referenced = 1;
}
@@ -4391,8 +4408,8 @@ resolve_operator (gfc_expr *e)
/* Try user-defined operators, and otherwise throw an error. */
dual_locus_error = true;
- sprintf (msg,
- _("Inconsistent ranks for operator at %%L and %%L"));
+ snprintf (msg, sizeof (msg),
+ _("Inconsistent ranks for operator at %%L and %%L"));
goto bad_op;
}
}
@@ -5701,7 +5718,6 @@ resolve_variable (gfc_expr *e)
part_ref. */
gfc_ref *ref = gfc_get_ref ();
ref->type = REF_ARRAY;
- ref->u.ar = *gfc_get_array_ref();
ref->u.ar.type = AR_FULL;
if (sym->as)
{
@@ -7813,8 +7829,9 @@ resolve_allocate_expr (gfc_expr *e, gfc_code *code, bool *array_alloc_wo_spec)
}
}
- /* Check for F08:C628. */
- if (allocatable == 0 && pointer == 0 && !unlimited)
+ /* Check for F08:C628 (F2018:C932). Each allocate-object shall be a data
+ pointer or an allocatable variable. */
+ if (allocatable == 0 && pointer == 0)
{
gfc_error ("Allocate-object at %L must be ALLOCATABLE or a POINTER",
&e->where);
@@ -8148,16 +8165,21 @@ resolve_allocate_deallocate (gfc_code *code, const char *fcn)
/* Check the stat variable. */
if (stat)
{
- gfc_check_vardef_context (stat, false, false, false,
- _("STAT variable"));
+ if (!gfc_check_vardef_context (stat, false, false, false,
+ _("STAT variable")))
+ goto done_stat;
- if ((stat->ts.type != BT_INTEGER
- && !(stat->ref && (stat->ref->type == REF_ARRAY
- || stat->ref->type == REF_COMPONENT)))
+ if (stat->ts.type != BT_INTEGER
|| stat->rank > 0)
gfc_error ("Stat-variable at %L must be a scalar INTEGER "
"variable", &stat->where);
+ if (stat->expr_type == EXPR_CONSTANT || stat->symtree == NULL)
+ goto done_stat;
+
+ /* F2018:9.7.4: The stat-variable shall not be allocated or deallocated
+ * within the ALLOCATE or DEALLOCATE statement in which it appears ...
+ */
for (p = code->ext.alloc.list; p; p = p->next)
if (p->expr->symtree->n.sym->name == stat->symtree->n.sym->name)
{
@@ -8185,6 +8207,8 @@ resolve_allocate_deallocate (gfc_code *code, const char *fcn)
}
}
+done_stat:
+
/* Check the errmsg variable. */
if (errmsg)
{
@@ -8192,22 +8216,26 @@ resolve_allocate_deallocate (gfc_code *code, const char *fcn)
gfc_warning (0, "ERRMSG at %L is useless without a STAT tag",
&errmsg->where);
- gfc_check_vardef_context (errmsg, false, false, false,
- _("ERRMSG variable"));
+ if (!gfc_check_vardef_context (errmsg, false, false, false,
+ _("ERRMSG variable")))
+ goto done_errmsg;
/* F18:R928 alloc-opt is ERRMSG = errmsg-variable
F18:R930 errmsg-variable is scalar-default-char-variable
F18:R906 default-char-variable is variable
F18:C906 default-char-variable shall be default character. */
- if ((errmsg->ts.type != BT_CHARACTER
- && !(errmsg->ref
- && (errmsg->ref->type == REF_ARRAY
- || errmsg->ref->type == REF_COMPONENT)))
+ if (errmsg->ts.type != BT_CHARACTER
|| errmsg->rank > 0
|| errmsg->ts.kind != gfc_default_character_kind)
gfc_error ("ERRMSG variable at %L shall be a scalar default CHARACTER "
"variable", &errmsg->where);
+ if (errmsg->expr_type == EXPR_CONSTANT || errmsg->symtree == NULL)
+ goto done_errmsg;
+
+ /* F2018:9.7.5: The errmsg-variable shall not be allocated or deallocated
+ * within the ALLOCATE or DEALLOCATE statement in which it appears ...
+ */
for (p = code->ext.alloc.list; p; p = p->next)
if (p->expr->symtree->n.sym->name == errmsg->symtree->n.sym->name)
{
@@ -8235,6 +8263,8 @@ resolve_allocate_deallocate (gfc_code *code, const char *fcn)
}
}
+done_errmsg:
+
/* Check that an allocate-object appears only once in the statement. */
for (p = code->ext.alloc.list; p; p = p->next)
@@ -9246,7 +9276,7 @@ resolve_select_type (gfc_code *code, gfc_namespace *old_ns)
gfc_code *class_is = NULL, *default_case = NULL;
gfc_case *c;
gfc_symtree *st;
- char name[GFC_MAX_SYMBOL_LEN];
+ char name[GFC_MAX_SYMBOL_LEN + 12 + 1];
gfc_namespace *ns;
int error = 0;
int rank = 0;
@@ -10216,19 +10246,27 @@ resolve_sync (gfc_code *code)
/* Check STAT. */
gfc_resolve_expr (code->expr2);
- if (code->expr2
- && (code->expr2->ts.type != BT_INTEGER || code->expr2->rank != 0
- || code->expr2->expr_type != EXPR_VARIABLE))
- gfc_error ("STAT= argument at %L must be a scalar INTEGER variable",
- &code->expr2->where);
+ if (code->expr2)
+ {
+ if (code->expr2->ts.type != BT_INTEGER || code->expr2->rank != 0)
+ gfc_error ("STAT= argument at %L must be a scalar INTEGER variable",
+ &code->expr2->where);
+ else
+ gfc_check_vardef_context (code->expr2, false, false, false,
+ _("STAT variable"));
+ }
/* Check ERRMSG. */
gfc_resolve_expr (code->expr3);
- if (code->expr3
- && (code->expr3->ts.type != BT_CHARACTER || code->expr3->rank != 0
- || code->expr3->expr_type != EXPR_VARIABLE))
- gfc_error ("ERRMSG= argument at %L must be a scalar CHARACTER variable",
- &code->expr3->where);
+ if (code->expr3)
+ {
+ if (code->expr3->ts.type != BT_CHARACTER || code->expr3->rank != 0)
+ gfc_error ("ERRMSG= argument at %L must be a scalar CHARACTER variable",
+ &code->expr3->where);
+ else
+ gfc_check_vardef_context (code->expr3, false, false, false,
+ _("ERRMSG variable"));
+ }
}
@@ -10789,15 +10827,30 @@ gfc_resolve_blocks (gfc_code *b, gfc_namespace *ns)
case EXEC_OMP_DISTRIBUTE_SIMD:
case EXEC_OMP_DO:
case EXEC_OMP_DO_SIMD:
+ case EXEC_OMP_ERROR:
+ case EXEC_OMP_LOOP:
+ case EXEC_OMP_MASKED:
+ case EXEC_OMP_MASKED_TASKLOOP:
+ case EXEC_OMP_MASKED_TASKLOOP_SIMD:
case EXEC_OMP_MASTER:
+ case EXEC_OMP_MASTER_TASKLOOP:
+ case EXEC_OMP_MASTER_TASKLOOP_SIMD:
case EXEC_OMP_ORDERED:
case EXEC_OMP_PARALLEL:
case EXEC_OMP_PARALLEL_DO:
case EXEC_OMP_PARALLEL_DO_SIMD:
+ case EXEC_OMP_PARALLEL_LOOP:
+ case EXEC_OMP_PARALLEL_MASKED:
+ case EXEC_OMP_PARALLEL_MASKED_TASKLOOP:
+ case EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD:
+ case EXEC_OMP_PARALLEL_MASTER:
+ case EXEC_OMP_PARALLEL_MASTER_TASKLOOP:
+ case EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD:
case EXEC_OMP_PARALLEL_SECTIONS:
case EXEC_OMP_PARALLEL_WORKSHARE:
case EXEC_OMP_SECTIONS:
case EXEC_OMP_SIMD:
+ case EXEC_OMP_SCOPE:
case EXEC_OMP_SINGLE:
case EXEC_OMP_TARGET:
case EXEC_OMP_TARGET_DATA:
@@ -10806,12 +10859,14 @@ gfc_resolve_blocks (gfc_code *b, gfc_namespace *ns)
case EXEC_OMP_TARGET_PARALLEL:
case EXEC_OMP_TARGET_PARALLEL_DO:
case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
+ case EXEC_OMP_TARGET_PARALLEL_LOOP:
case EXEC_OMP_TARGET_SIMD:
case EXEC_OMP_TARGET_TEAMS:
case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
+ case EXEC_OMP_TARGET_TEAMS_LOOP:
case EXEC_OMP_TARGET_UPDATE:
case EXEC_OMP_TASK:
case EXEC_OMP_TASKGROUP:
@@ -10823,6 +10878,7 @@ gfc_resolve_blocks (gfc_code *b, gfc_namespace *ns)
case EXEC_OMP_TEAMS_DISTRIBUTE:
case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
+ case EXEC_OMP_TEAMS_LOOP:
case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD:
case EXEC_OMP_WORKSHARE:
break;
@@ -11755,6 +11811,12 @@ gfc_resolve_code (gfc_code *code, gfc_namespace *ns)
case EXEC_OMP_PARALLEL:
case EXEC_OMP_PARALLEL_DO:
case EXEC_OMP_PARALLEL_DO_SIMD:
+ case EXEC_OMP_PARALLEL_MASKED:
+ case EXEC_OMP_PARALLEL_MASKED_TASKLOOP:
+ case EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD:
+ case EXEC_OMP_PARALLEL_MASTER:
+ case EXEC_OMP_PARALLEL_MASTER_TASKLOOP:
+ case EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD:
case EXEC_OMP_PARALLEL_SECTIONS:
case EXEC_OMP_TARGET_PARALLEL:
case EXEC_OMP_TARGET_PARALLEL_DO:
@@ -11930,6 +11992,12 @@ start:
if (resolve_ordinary_assign (code, ns))
{
+ if (omp_workshare_flag)
+ {
+ gfc_error ("Expected intrinsic assignment in OMP WORKSHARE "
+ "at %L", &code->loc);
+ break;
+ }
if (code->op == EXEC_COMPCALL)
goto compcall;
else
@@ -11991,6 +12059,7 @@ start:
/* Assigning a class object always is a regular assign. */
if (code->expr2->ts.type == BT_CLASS
&& code->expr1->ts.type == BT_CLASS
+ && CLASS_DATA (code->expr2)
&& !CLASS_DATA (code->expr2)->attr.dimension
&& !(gfc_expr_attr (code->expr1).proc_pointer
&& code->expr2->expr_type == EXPR_VARIABLE
@@ -12189,15 +12258,24 @@ start:
case EXEC_OMP_CANCELLATION_POINT:
case EXEC_OMP_CRITICAL:
case EXEC_OMP_FLUSH:
+ case EXEC_OMP_DEPOBJ:
case EXEC_OMP_DISTRIBUTE:
case EXEC_OMP_DISTRIBUTE_PARALLEL_DO:
case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD:
case EXEC_OMP_DISTRIBUTE_SIMD:
case EXEC_OMP_DO:
case EXEC_OMP_DO_SIMD:
+ case EXEC_OMP_ERROR:
+ case EXEC_OMP_LOOP:
case EXEC_OMP_MASTER:
+ case EXEC_OMP_MASTER_TASKLOOP:
+ case EXEC_OMP_MASTER_TASKLOOP_SIMD:
+ case EXEC_OMP_MASKED:
+ case EXEC_OMP_MASKED_TASKLOOP:
+ case EXEC_OMP_MASKED_TASKLOOP_SIMD:
case EXEC_OMP_ORDERED:
case EXEC_OMP_SCAN:
+ case EXEC_OMP_SCOPE:
case EXEC_OMP_SECTIONS:
case EXEC_OMP_SIMD:
case EXEC_OMP_SINGLE:
@@ -12208,12 +12286,14 @@ start:
case EXEC_OMP_TARGET_PARALLEL:
case EXEC_OMP_TARGET_PARALLEL_DO:
case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
+ case EXEC_OMP_TARGET_PARALLEL_LOOP:
case EXEC_OMP_TARGET_SIMD:
case EXEC_OMP_TARGET_TEAMS:
case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
+ case EXEC_OMP_TARGET_TEAMS_LOOP:
case EXEC_OMP_TARGET_UPDATE:
case EXEC_OMP_TASK:
case EXEC_OMP_TASKGROUP:
@@ -12226,6 +12306,7 @@ start:
case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD:
+ case EXEC_OMP_TEAMS_LOOP:
case EXEC_OMP_WORKSHARE:
gfc_resolve_omp_directive (code, ns);
break;
@@ -12233,6 +12314,13 @@ start:
case EXEC_OMP_PARALLEL:
case EXEC_OMP_PARALLEL_DO:
case EXEC_OMP_PARALLEL_DO_SIMD:
+ case EXEC_OMP_PARALLEL_LOOP:
+ case EXEC_OMP_PARALLEL_MASKED:
+ case EXEC_OMP_PARALLEL_MASKED_TASKLOOP:
+ case EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD:
+ case EXEC_OMP_PARALLEL_MASTER:
+ case EXEC_OMP_PARALLEL_MASTER_TASKLOOP:
+ case EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD:
case EXEC_OMP_PARALLEL_SECTIONS:
case EXEC_OMP_PARALLEL_WORKSHARE:
omp_workshare_save = omp_workshare_flag;
@@ -16029,7 +16117,8 @@ resolve_symbol (gfc_symbol *sym)
&& !(sym->ns->save_all && !sym->attr.automatic)
&& sym->module == NULL
&& (sym->ns->proc_name == NULL
- || sym->ns->proc_name->attr.flavor != FL_MODULE))
+ || (sym->ns->proc_name->attr.flavor != FL_MODULE
+ && !sym->ns->proc_name->attr.is_main_program)))
gfc_error ("Threadprivate at %L isn't SAVEd", &sym->declared_at);
/* Check omp declare target restrictions. */
@@ -16040,7 +16129,8 @@ resolve_symbol (gfc_symbol *sym)
&& (!sym->attr.in_common
&& sym->module == NULL
&& (sym->ns->proc_name == NULL
- || sym->ns->proc_name->attr.flavor != FL_MODULE)))
+ || (sym->ns->proc_name->attr.flavor != FL_MODULE
+ && !sym->ns->proc_name->attr.is_main_program))))
gfc_error ("!$OMP DECLARE TARGET variable %qs at %L isn't SAVEd",
sym->name, &sym->declared_at);