diff mbox

[Fortran] Fix PR 60526, variable name has already been declared as a type

Message ID 56B65596.3080800@netcologne.de
State New
Headers show

Commit Message

Thomas Koenig Feb. 6, 2016, 8:20 p.m. UTC
Hi Andre,

> In preventing memory clutter I like to advise the use of:
>
> char u_name[GFC_MAX_SYMBOL_LEN + 1];
>
> and safe us all the dynamic memory allocation/free.

We're really talking micro-optimizations here, but well ... ;-)

In the attached patch, I have replaced this with alloca.  I was going
to  use a VLA originally, but apparently C++ doesn't like that, at least
not in the version that we use within C++.

I think this is the right idiom for a throw-away variable like this.
I also found 15 instances of alloca in fortran, so it is OK to use.

> Furthermore, how
> about switching:
>
>    strncpy (u_name, name, nlen+ 1);
>    u_name[0] = TOUPPER(u_name[0]);
>
> that way strncpy() can use its full power and copy aligned data using
> longs,

I don't think this would have mattered for an array of char
(these are usually not aligned).  However, a pointer using alloca
should be aligned, so this could be used.

So, here's the new version.

OK for all trunk and 5?



>> 2016-02-03  Thomas Koenig  <tkoenig@gcc.gnu.org>
>>
>>           PR fortran/60526
>>           * decl.c (build_sym):  If the name has already been defined as a
>>           type, issue error and return false.
>>
>> 2016-02-03  Thomas Koenig  <tkoenig@gcc.gnu.org>
>>
>>           PR fortran/60526
>>           * gfortran.dg/type_decl_4.f90:  New test.
>
>

Comments

Janne Blomqvist Feb. 11, 2016, 6:55 p.m. UTC | #1
On Sat, Feb 6, 2016 at 10:20 PM, Thomas Koenig <tkoenig@netcologne.de> wrote:
> Hi Andre,
>
>> In preventing memory clutter I like to advise the use of:
>>
>> char u_name[GFC_MAX_SYMBOL_LEN + 1];
>>
>> and safe us all the dynamic memory allocation/free.
>
>
> We're really talking micro-optimizations here, but well ... ;-)

/me joins the micro-optimization bikeshed!

> In the attached patch, I have replaced this with alloca.  I was going
> to  use a VLA originally, but apparently C++ doesn't like that, at least
> not in the version that we use within C++.

IIRC VLA's were proposed for C++14, but were ultimately rejected.

The usual arguments against VLA's (and alloca, which is just another
way to spell the same thing, really) are that

- It reserves an extra register for the frame pointer.

- Functions using VLA's aren't inlined by GCC

- From a correctness perspective, unless you check the size somehow
beforehand, you can easily get a stack overflow crash.

So one solution to these correctness and performance issues is to have
a reasonably small statically sized buffer on the stack, and if the
size is bigger than that, fall back to heap allocation. E.g. something
like

void foo(..., size_t n) {
  char tmp[BUFSIZE];
  char *buf;
  if (n <= BUFSIZE)
    buf = tmp;
  else
    buf = xmalloc(n);
  // Use buf
 if (n > BUFSIZE)
    free(buf);
}

This is roughly what std::string does with the new C++11 compatible
libstdc++ ABI. As we're supposed to be C++ nowadays, why aren't we
using that?
Thomas Koenig Feb. 12, 2016, 8:02 a.m. UTC | #2
Hi Janne,

[std::string]

> As we're supposed to be C++ nowadays, why aren't we
> using that?

My reason is simple: I know C and Fortran. I hardly know C++,
and I don't want to learn it for the sake of some largely
irrelevant micro-optimizations.

We should restrict C++ usage to those cases where there is
a clear and large benefit.

Regards

	Thomas
Andre Vehreschild Feb. 12, 2016, 10:16 a.m. UTC | #3
Hi all,

it wasn't my intention to start such a big discussion for such a small
thing. Please stop this academic battle and get back to the issue at
hand:

Thomas is examining a symbol, that

- has come through the scanner, i.e., it adheres to the rules of
  gfortran, especially it is known to be smaller than GFC_MAX_SYMBOL_LEN

- is still a valid symbol. When gfortran's internal
  composition/modification of symbols breaks this rule, we are done
  earlier already. 

- its length is not changed in his routine.

I was only trying to prevent an alloc/free for this small use case,
which should fit on the stack quite easily. The proposed alloca() call
has according to the documentation of libc some availability issues on
certain platforms, too. Therefore why not going with the fixed size
stack array and adding a check for possible overflow to it and be done?

Regards,
	Andre

On Fri, 12 Feb 2016 09:02:27 +0100
Thomas Koenig <tkoenig@netcologne.de> wrote:

> Hi Janne,
> 
> [std::string]
> 
> > As we're supposed to be C++ nowadays, why aren't we
> > using that?  
> 
> My reason is simple: I know C and Fortran. I hardly know C++,
> and I don't want to learn it for the sake of some largely
> irrelevant micro-optimizations.
> 
> We should restrict C++ usage to those cases where there is
> a clear and large benefit.
> 
> Regards
> 
> 	Thomas
Janne Blomqvist Feb. 12, 2016, 10:42 a.m. UTC | #4
On Fri, Feb 12, 2016 at 12:16 PM, Andre Vehreschild <vehre@gmx.de> wrote:
> Hi all,
>
> it wasn't my intention to start such a big discussion for such a small
> thing. Please stop this academic battle and get back to the issue at
> hand:
>
> Thomas is examining a symbol, that
>
> - has come through the scanner, i.e., it adheres to the rules of
>   gfortran, especially it is known to be smaller than GFC_MAX_SYMBOL_LEN
>
> - is still a valid symbol. When gfortran's internal
>   composition/modification of symbols breaks this rule, we are done
>   earlier already.
>
> - its length is not changed in his routine.
>
> I was only trying to prevent an alloc/free for this small use case,
> which should fit on the stack quite easily. The proposed alloca() call
> has according to the documentation of libc some availability issues on
> certain platforms, too. Therefore why not going with the fixed size
> stack array and adding a check for possible overflow to it and be done?

Yes, I agree. That sounds like the best approach in this case.
diff mbox

Patch

Index: decl.c
===================================================================
--- decl.c	(Revision 232864)
+++ decl.c	(Arbeitskopie)
@@ -1215,10 +1215,30 @@  build_sym (const char *name, gfc_charlen *cl, bool
 {
   symbol_attribute attr;
   gfc_symbol *sym;
+  int nlen;
+  char *u_name;
+  gfc_symtree *st;
 
   if (gfc_get_symbol (name, NULL, &sym))
     return false;
 
+  /* Check if the name has already been defined as a type.  The
+     first letter of the symtree will be in upper case then.  */
+
+  nlen = strlen(name);
+  u_name = (char *) alloca (nlen + 1);
+  strncpy (u_name, name, nlen + 1);
+  u_name[0] = TOUPPER(u_name[0]);
+
+  st = gfc_find_symtree (gfc_current_ns->sym_root, u_name);
+
+  if (st != 0)
+    {
+      gfc_error ("Symbol %qs at %C also declared as a type at %L", name,
+		 &st->n.sym->declared_at);
+      return false;
+    }
+
   /* Start updating the symbol table.  Add basic type attribute if present.  */
   if (current_ts.type != BT_UNKNOWN
       && (sym->attr.implicit_type == 0