identifier scope in old-style declarations

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Thomas Pornin

    #1

    identifier scope in old-style declarations

    Hello,

    with gcc-4.2.3, this does not compile:

    typedef int foo;
    int f(foo)
    int foo;
    {
    return foo;
    }

    The error message is rather explicit ("old-style parameter declarations
    in prototyped function definition"), which means that the compiler, when
    encountering the "foo" on the second line, considered it to be a type
    name, and not an argument name which would override the global type
    definition within the function scope.

    I understand, from a practical point of view, that doing otherwise would
    mess the compiler (it would contradict the almost-LALR(1) property of
    the C grammer). However, I cannot find in the C standard where such an
    override is forbidden. Right now, it seems to me that the construction
    is ambiguous.

    Could someone shed some light on this ?


    --Thomas Pornin
  • santosh

    #2
    Re: identifier scope in old-style declarations

    Thomas Pornin wrote:
    Hello,
    >
    with gcc-4.2.3, this does not compile:
    >
    typedef int foo;
    int f(foo)
    int foo;
    {
    return foo;
    }
    >
    The error message is rather explicit ("old-style parameter
    declarations in prototyped function definition"), which means that the
    compiler, when encountering the "foo" on the second line, considered
    it to be a type name, and not an argument name which would override
    the global type definition within the function scope.
    Hmm, I don't know all the details of pre-ANSI C, but I fail to see how
    you can use a type alias in place of an lvalue. Foo is an alias for
    int, a type. You need an object or expression of foo within the
    parameter list to f() and in the subsequent type declaration and in the
    return statement.

    <snip>

    typedef int foo;
    foo fx(f)
    foo f;
    {
    return f;
    }

    main() { fx(); return 0; }

    Comment

    • Eric Sosman

      #3
      Re: identifier scope in old-style declarations

      Thomas Pornin wrote:
      Hello,
      >
      with gcc-4.2.3, this does not compile:
      >
      typedef int foo;
      int f(foo)
      int foo;
      {
      return foo;
      }
      >
      The error message is rather explicit ("old-style parameter declarations
      in prototyped function definition"), which means that the compiler, when
      encountering the "foo" on the second line, considered it to be a type
      name, and not an argument name which would override the global type
      definition within the function scope.
      >
      I understand, from a practical point of view, that doing otherwise would
      mess the compiler (it would contradict the almost-LALR(1) property of
      the C grammer). However, I cannot find in the C standard where such an
      override is forbidden. Right now, it seems to me that the construction
      is ambiguous.
      >
      Could someone shed some light on this ?
      Had to hunt for it a little, but I found it. 6.9.1p6: "[...] An
      identifier declared as a typedef name shall not be redeclared as a
      parameter. [...]"

      --
      Eric.Sosman@sun .com

      Comment

      • Thomas Pornin

        #4
        Re: identifier scope in old-style declarations

        According to Eric Sosman <Eric.Sosman@su n.com>:
        Had to hunt for it a little, but I found it. 6.9.1p6: "[...] An
        identifier declared as a typedef name shall not be redeclared as a
        parameter. [...]"
        Well spotted ! Thanks.


        --Thomas Pornin

        Comment

        • Huibert Bol

          #5
          Re: identifier scope in old-style declarations

          Eric Sosman wrote:
          Thomas Pornin wrote:
          >Hello,
          >>
          >with gcc-4.2.3, this does not compile:
          >>
          > typedef int foo;
          > int f(foo)
          > int foo;
          > {
          > return foo;
          > }
          >>
          >The error message is rather explicit ("old-style parameter declarations
          >in prototyped function definition"), which means that the compiler, when
          >encountering the "foo" on the second line, considered it to be a type
          >name, and not an argument name which would override the global type
          >definition within the function scope.
          >>
          >I understand, from a practical point of view, that doing otherwise would
          >mess the compiler (it would contradict the almost-LALR(1) property of
          >the C grammer). However, I cannot find in the C standard where such an
          >override is forbidden. Right now, it seems to me that the construction
          >is ambiguous.
          >>
          >Could someone shed some light on this ?
          >
          Had to hunt for it a little, but I found it. 6.9.1p6: "[...] An
          identifier declared as a typedef name shall not be redeclared as a
          parameter. [...]"
          But that's only the case if the declarator includes an _identifier list_, but
          in the example above contains a _parameter type list_; so 6.9.1p5 applies:
          "[...] No declaration list shall follow." which matches the error message
          above.

          - Huibert.

          Comment

          • Thomas Pornin

            #6
            Re: identifier scope in old-style declarations

            According to santosh <santosh.k83@gm ail.com>:
            Hmm, I don't know all the details of pre-ANSI C, but I fail to see how
            you can use a type alias in place of an lvalue.
            You can override names in inner scopes. This works for variables,
            but also for type names. For instance, this compiles and works:

            typedef int foo;
            int f(int foo)
            {
            return foo;
            }

            Here, the identifier "foo" is redefined in an inner scope (the
            function); within the function, when "foo" is encountered, it designates
            the function argument. Outside of the function, the global typedef
            prevails.

            My question was: if it works with a new-style function definition (with
            a prototype, as shown above), why does it not work with an old-style
            function definition (with a list of variable names, and extra
            declarations, as shown in my previous post) ? Eric Sosman found the
            paragraph I had missed in the C standard, i.e. 6.9.1/6, which
            explicitely rules out the override of a typedefed name with an old-style
            parameter.


            --Thomas Pornin

            Comment

            • Thomas Pornin

              #7
              Re: identifier scope in old-style declarations

              According to Huibert Bol <huibert.bol@qu icknet.nl>:
              But that's only the case if the declarator includes an _identifier
              list_, but in the example above contains a _parameter type list_
              Ah, that's the whole point. If the list is parsed as a parameter type
              list, then the presence of the declarations is a violation, and so is
              the lack of parameter name (unnamed parameters are allowed only in
              prototypes without a function definition). The question was: what
              prevents the compiler from parsing the list as an identifier list ? And
              the answer is: this would imply that an identifier in this list
              overrides a typedefed name at file scope, an occurrence which 6.9.1/6
              specifically forbids (overrides of typedefed names with argument names
              is allowed only with a new-style prototype, not with an old-style
              identifier list).


              --Thomas Pornin

              Comment

              • Eric Sosman

                #8
                Re: identifier scope in old-style declarations

                Huibert Bol wrote:
                Eric Sosman wrote:
                >
                >Thomas Pornin wrote:
                >>Hello,
                >>>
                >>with gcc-4.2.3, this does not compile:
                >>>
                >> typedef int foo;
                >> int f(foo)
                >> int foo;
                >> {
                >> return foo;
                >> }
                >>>
                >>The error message is rather explicit ("old-style parameter declarations
                >>in prototyped function definition"), [...]
                >>>
                > Had to hunt for it a little, but I found it. 6.9.1p6: "[...] An
                >identifier declared as a typedef name shall not be redeclared as a
                >parameter. [...]"
                >
                But that's only the case if the declarator includes an _identifier list_, but
                in the example above contains a _parameter type list_; so 6.9.1p5 applies:
                "[...] No declaration list shall follow." which matches the error message
                above.
                If the `(foo)' in the O.P.'s first line is taken as a parameter
                list, it violates 6.9.1p5. If it is taken as an identifier list,
                it violates 6.9.1p6. It is invalid either way, and diagnosing one
                violation is as good as diagnosing the other.

                There's often some ambiguity in pinpointing "the" error in an
                erroneous source. Fundamentally, all that's really known is that
                the source is incorrect; diagnosing the nature of its incorrectness
                involves imagining a plausible correct source and describing the
                "edit distance" between them. Since there are many, many possible
                correct sources, there are many possible diagnoses.

                For example, how would you describe the error in

                #include <stdio.h>
                int man(void) {
                return puts ("Hello, world!\n") == EOF;
                }

                ? (Yes, this is a trick question.)

                --
                Eric.Sosman@sun .com

                Comment

                • Huibert Bol

                  #9
                  Re: identifier scope in old-style declarations

                  Eric Sosman wrote:
                  For example, how would you describe the error in
                  >
                  #include <stdio.h>
                  int man(void) {
                  return puts ("Hello, world!\n") == EOF;
                  }
                  >
                  ? (Yes, this is a trick question.)
                  It prints an additional newline ;-)

                  - Huibert.

                  Comment

                  • Mark B [Diputsur]

                    #10
                    Re: identifier scope in old-style declarations


                    "Huibert Bol" <huibert.bol@qu icknet.nlwrote in message
                    news:g7cqut$9qc $1@registered.m otzarella.org.. .
                    Eric Sosman wrote:
                    >
                    > For example, how would you describe the error in
                    >>
                    >#include <stdio.h>
                    >int man(void) {
                    > return puts ("Hello, world!\n") == EOF;
                    >}
                    >>
                    >? (Yes, this is a trick question.)
                    >
                    It prints an additional newline ;-)
                    Doubtful it will print anything...
                    it's missing the function called at program startup.


                    Comment

                    • Huibert Bol

                      #11
                      Re: identifier scope in old-style declarations

                      Mark B. wrote:
                      "Huibert Bol" <huibert.bol@qu icknet.nlwrote in message
                      news:g7cqut$9qc $1@registered.m otzarella.org.. .
                      >Eric Sosman wrote:
                      >>
                      >> For example, how would you describe the error in
                      >>>
                      >>#include <stdio.h>
                      >>int man(void) {
                      >> return puts ("Hello, world!\n") == EOF;
                      >>}
                      >>>
                      >>? (Yes, this is a trick question.)
                      >>
                      >It prints an additional newline ;-)
                      >
                      Doubtful it will print anything...
                      it's missing the function called at program startup.
                      Dûh, Eric never said it was a complete program!

                      - Huibert.

                      Comment

                      • santosh

                        #12
                        Re: identifier scope in old-style declarations

                        Eric Sosman wrote:

                        <snip>
                        There's often some ambiguity in pinpointing "the" error in an
                        erroneous source. Fundamentally, all that's really known is that
                        the source is incorrect; diagnosing the nature of its incorrectness
                        involves imagining a plausible correct source and describing the
                        "edit distance" between them. Since there are many, many possible
                        correct sources, there are many possible diagnoses.
                        >
                        For example, how would you describe the error in
                        >
                        #include <stdio.h>
                        int man(void) {
                        return puts ("Hello, world!\n") == EOF;
                        }
                        >
                        ? (Yes, this is a trick question.)
                        Well I suppose there would be no error until the last phase of
                        translation, which will fail because main is not defined, (and you have
                        not told us if the program is freestanding, in which case it would be
                        correct, provided the contents of stdio.h and the definition for puts
                        are supplied by the user.)

                        Comment

                        • Mark B [Diputsur]

                          #13
                          Re: identifier scope in old-style declarations


                          "Huibert Bol" <huibert.bol@qu icknet.nlwrote in message
                          news:g7crj1$9qc $2@registered.m otzarella.org.. .
                          Mark B. wrote:
                          >
                          >"Huibert Bol" <huibert.bol@qu icknet.nlwrote in message
                          >news:g7cqut$9q c$1@registered. motzarella.org. ..
                          >>Eric Sosman wrote:
                          >>>
                          >>> For example, how would you describe the error in
                          >>>>
                          >>>#include <stdio.h>
                          >>>int man(void) {
                          >>> return puts ("Hello, world!\n") == EOF;
                          >>>}
                          >>>>
                          >>>? (Yes, this is a trick question.)
                          >>>
                          >>It prints an additional newline ;-)
                          >>
                          >Doubtful it will print anything...
                          >it's missing the function called at program startup.
                          >
                          Dûh, Eric never said it was a complete program!
                          Yet his claim that there is an error in the code suggests
                          that it should be... unless we have requirements on return
                          values from functions named 'man();' that I don't know
                          about...



                          Comment

                          • santosh

                            #14
                            Re: identifier scope in old-style declarations

                            santosh wrote:
                            Eric Sosman wrote:
                            >
                            <snip>
                            >
                            > There's often some ambiguity in pinpointing "the" error in an
                            >erroneous source. Fundamentally, all that's really known is that
                            >the source is incorrect; diagnosing the nature of its incorrectness
                            >involves imagining a plausible correct source and describing the
                            >"edit distance" between them. Since there are many, many possible
                            >correct sources, there are many possible diagnoses.
                            >>
                            > For example, how would you describe the error in
                            >>
                            >#include <stdio.h>
                            >int man(void) {
                            >return puts ("Hello, world!\n") == EOF;
                            >}
                            >>
                            >? (Yes, this is a trick question.)
                            >
                            Well I suppose there would be no error until the last phase of
                            translation, which will fail because main is not defined, (and you
                            have not told us if the program is freestanding, in which case it
                            would be correct, provided the contents of stdio.h and the definition
                            for puts are supplied by the user.)
                            Just to followup, many knowledgeable members of this group have
                            previously said that an implementation is not required to reject the
                            translation of any program that does not contain a selected #error
                            directive. In light of that I would amend my answer above and say that
                            no error need be emitted by a compiler for the translation unit given
                            above by Eric. A conforming implementation could insert it's own main
                            and invoke man from it.

                            Comment

                            • Eric Sosman

                              #15
                              Re: identifier scope in old-style declarations

                              Eric Sosman wrote:
                              [...]
                              There's often some ambiguity in pinpointing "the" error in an
                              erroneous source. Fundamentally, all that's really known is that
                              the source is incorrect; diagnosing the nature of its incorrectness
                              involves imagining a plausible correct source and describing the
                              "edit distance" between them. Since there are many, many possible
                              correct sources, there are many possible diagnoses.
                              >
                              For example, how would you describe the error in
                              >
                              #include <stdio.h>
                              int man(void) {
                              return puts ("Hello, world!\n") == EOF;
                              }
                              >
                              ? (Yes, this is a trick question.)
                              Huibert Bol, Mark B [Diputsur], and santosh have between them
                              described two errors in this code. To their credit, they did not
                              get sidetracked by the blatant red herring, either! But they all
                              overlooked the *real* error, which is that the code prints "Hello,
                              world!\n\n" instead of "Hello, world!\a\n" ;-)

                              Anyway, that's my illustration of the ambiguity of diagnostics.
                              One of the first lessons programmers learn is that error messages,
                              no matter how detailed and specific, may mean only "Something is
                              wrong somewhere." This is a consequence of the fact that the mapping
                              from incorrect sources to correct sources is many-to-many.

                              --
                              Eric.Sosman@sun .com

                              Comment

                              Working...