Re: Forcing compile-time error

Discussion in 'C Programming' started by Stargazer, Jun 11, 2010.

  1. Stargazer

    Stargazer Guest

    On Jun 11, 4:53 pm, Kenneth Brody <> wrote:
    > I know about the #error directive, but it can't be used in this case...
    >
    > I am replacing calls to an outdated system function with a new wrapper
    > function which can be updated as needed.  (ie: if the "new" system function
    > gets obsoleted down the road, it can be replaced in a single location.)  All
    > of the source code is being updated to use the new wrapper function, but I
    > would like to catch any missed calls to the old function, and fail at
    > compile time.
    >
    > For example:
    >
    >      x = OldFunction(foo,bar);
    > is replaced with:
    >      x = NewFunctionWrapper(foo,bar,baz);
    >
    > Suppose there is some line, somewhere in the source, which was missed.  Is
    > it possible to force a compile-time error at that line?
    >
    > I know that the following is invalid, but it's the kind of thing I would
    > want to be able to do:
    >
    >      #define OldFunction(foo,bar) #error OldFunction called __FILE__ __LINE__


    Just #define OldFunction to syntactically erroneous expression, e.g.

    #define OldFunction(foo,bar) (1 = foo, 3 = bar)

    Most compilers are smart enough to diagnose precise line, source file
    and macro name.
    Put the definition in the header that includes function prototype or
    your own headers.

    >
    > I was thinking of something like this, but it just seems... ugly.
    >
    >      #define OldFunction(foo,bar) {***__OldFunction__ called!***;}
    >
    > Another problem with this version is that the macro would have to be in
    > every source file (obviously), but _after_ the "normal" #includes, as
    > OldFunction is prototyped in the (standard other than C) header files which
    > are included.


    Didn't get a reason of this requirement. Anyway, you may limit the
    effect of erroneous definition to your sources only, something like

    #ifdef MY_SOURCE
    #define OldFunction(foo,bar) {***__OldFunction__ called!***;}
    #endif

    in the system header, and put

    #define MY_SOURCE

    at first line of all your sources.

    Daniel
     
    Stargazer, Jun 11, 2010
    #1
    1. Advertising

  2. Stargazer

    Eric Sosman Guest

    On 6/11/2010 5:24 PM, Stargazer wrote:
    > On Jun 11, 4:53 pm, Kenneth Brody<> wrote:
    >> I know about the #error directive, but it can't be used in this case...
    >>
    >> I am replacing calls to an outdated system function with a new wrapper
    >> function which can be updated as needed. (ie: if the "new" system function
    >> gets obsoleted down the road, it can be replaced in a single location.) All
    >> of the source code is being updated to use the new wrapper function, but I
    >> would like to catch any missed calls to the old function, and fail at
    >> compile time.
    >>
    >> For example:
    >>
    >> x = OldFunction(foo,bar);
    >> is replaced with:
    >> x = NewFunctionWrapper(foo,bar,baz);
    >>
    >> Suppose there is some line, somewhere in the source, which was missed. Is
    >> it possible to force a compile-time error at that line?
    >>
    >> I know that the following is invalid, but it's the kind of thing I would
    >> want to be able to do:
    >>
    >> #define OldFunction(foo,bar) #error OldFunction called __FILE__ __LINE__

    >
    > Just #define OldFunction to syntactically erroneous expression, e.g.
    >
    > #define OldFunction(foo,bar) (1 = foo, 3 = bar)
    >
    > Most compilers are smart enough to diagnose precise line, source file
    > and macro name.
    > Put the definition in the header that includes function prototype or
    > your own headers.
    >
    >>
    >> I was thinking of something like this, but it just seems... ugly.
    >>
    >> #define OldFunction(foo,bar) {***__OldFunction__ called!***;}
    >>
    >> Another problem with this version is that the macro would have to be in
    >> every source file (obviously), but _after_ the "normal" #includes, as
    >> OldFunction is prototyped in the (standard other than C) header files which
    >> are included.

    >
    > Didn't get a reason of this requirement.


    Because if the macro is in force when the system header utters
    its prototype

    void OldFunction(int this, double that);

    .... the macro will change it to

    void (1 == int this, 2 = double that);

    .... right at the point of the header's declaration. This causes a
    compile error (as desired), but for every file that includes the
    header, whether it uses OldFunction or not.

    > Anyway, you may limit the
    > effect of erroneous definition to your sources only, something like
    >
    > #ifdef MY_SOURCE
    > #define OldFunction(foo,bar) {***__OldFunction__ called!***;}
    > #endif
    >
    > in the system header, [...]


    Most programming shops take a dim view of hand-editing the
    system-supplied headers. Too much opportunity for mischief (both
    intentional and accidental), and also susceptible to being clobbered
    by the next vendor-supplied patch ...

    It seems to me that the compiler is not the right tool for this
    job. It is tempting to (ab)use the compiler as a software quality
    enforcer; I've yielded to the temptation more than once, but have
    always wound up regretting it. Rather, I'd agree with Keith Thompson
    and others that a grep or equivalent will be more direct and more
    effective. True, it won't catch everything: An OldFunction reference
    built by token-pasting, for example, would elude a simple search. But
    it will catch all but the most contrived cases -- and if repeated as
    part of the standard build and/or check-in procedure, it will catch
    accidental re-introductions in the future, too.

    --
    Eric Sosman
    lid
     
    Eric Sosman, Jun 11, 2010
    #2
    1. Advertising

  3. Stargazer

    Stargazer Guest

    On Jun 12, 1:14 am, Eric Sosman <> wrote:
    > On 6/11/2010 5:24 PM, Stargazer wrote:
    >
    >
    >
    >
    >
    > > On Jun 11, 4:53 pm, Kenneth Brody<>  wrote:
    > >> I know about the #error directive, but it can't be used in this case....

    >
    > >> I am replacing calls to an outdated system function with a new wrapper
    > >> function which can be updated as needed.  (ie: if the "new" system function
    > >> gets obsoleted down the road, it can be replaced in a single location.)  All
    > >> of the source code is being updated to use the new wrapper function, but I
    > >> would like to catch any missed calls to the old function, and fail at
    > >> compile time.

    >
    > >> For example:

    >
    > >>       x = OldFunction(foo,bar);
    > >> is replaced with:
    > >>       x = NewFunctionWrapper(foo,bar,baz);

    >
    > >> Suppose there is some line, somewhere in the source, which was missed.  Is
    > >> it possible to force a compile-time error at that line?

    >
    > >> I know that the following is invalid, but it's the kind of thing I would
    > >> want to be able to do:

    >
    > >>       #define OldFunction(foo,bar) #error OldFunction called __FILE__ __LINE__

    >
    > > Just #define OldFunction to syntactically erroneous expression, e.g.

    >
    > > #define OldFunction(foo,bar) (1 = foo, 3 = bar)

    >
    > > Most compilers are smart enough to diagnose precise line, source file
    > > and macro name.
    > > Put the definition in the header that includes function prototype or
    > > your own headers.

    >
    > >> I was thinking of something like this, but it just seems... ugly.

    >
    > >>       #define OldFunction(foo,bar) {***__OldFunction__ called!***;}

    >
    > >> Another problem with this version is that the macro would have to be in
    > >> every source file (obviously), but _after_ the "normal" #includes, as
    > >> OldFunction is prototyped in the (standard other than C) header files which
    > >> are included.

    >
    > > Didn't get a reason of this requirement.

    >
    >      Because if the macro is in force when the system header utters
    > its prototype
    >
    >         void OldFunction(int this, double that);
    >
    > ... the macro will change it to
    >
    >         void (1 == int this, 2 = double that);
    >
    > ... right at the point of the header's declaration.  This causes a
    > compile error (as desired), but for every file that includes the
    > header, whether it uses OldFunction or not.


    This will happen only if

    #define OldFunction(foo,bar) (1 = foo, 3 = bar)

    occurs before OldFunction()'s declaration in the header; so it should
    appear after #include to that system header or in the header *after*
    the declaration of OldFunction().

    Usually projects have their own "common" headers that all developed
    code include. So such a definition can be put in "project-header.h",
    which will also include the system header in question (let's call it
    "system-header.h").

    E.g.

    ---------- project-header.h -------------
    #include "system-header.h"
    //...
    #define OldFunction(foo,bar) (1 = foo, 3 = bar)
    //...
    -----------------------------------------

    If desired, "project-header.h" can ensure that "system-header.h"
    hasn't been already included, assuming that system header is protected
    agains multiple inclusion, say, with

    #ifndef SYSTEM_HEADER_H
    #define SYSTEM_HEADER_H
    //... Header contents
    #endif

    ---------- project-header.h -------------
    #ifdef SYSTEM_HEADER_H
    #error <<system-header.h>> was already included
    #endif
    #include "system-header.h"
    //...
    #define OldFunction(foo,bar) (1 = foo, 3 = bar)
    //...
    -----------------------------------------

    > > Anyway, you may limit the
    > > effect of erroneous definition to your sources only, something like

    >
    > > #ifdef MY_SOURCE
    > > #define OldFunction(foo,bar) {***__OldFunction__ called!***;}
    > > #endif

    >
    > > in the system header, [...]

    >
    >      Most programming shops take a dim view of hand-editing the
    > system-supplied headers.  Too much opportunity for mischief (both
    > intentional and accidental), and also susceptible to being clobbered
    > by the next vendor-supplied patch ...


    True. But sometimes (much more often than I would actually like it to
    occur) vendors won't supply you anything unless you prove them "beyond
    any doubt" that they have a bug. They wouldn't even acknowledge that
    they have a bug unless you prove it. In such a case a programmer has
    only two options: declare that there's a problem and nothing can be
    done about it, or use any existing instrument to do the diagnosis.

    >      It seems to me that the compiler is not the right tool for this
    > job.  It is tempting to (ab)use the compiler as a software quality
    > enforcer; I've yielded to the temptation more than once, but have
    > always wound up regretting it.  Rather, I'd agree with Keith Thompson
    > and others that a grep or equivalent will be more direct and more
    > effective.  True, it won't catch everything: An OldFunction reference
    > built by token-pasting, for example, would elude a simple search.  But
    > it will catch all but the most contrived cases -- and if repeated as
    > part of the standard build and/or check-in procedure, it will catch
    > accidental re-introductions in the future, too.


    Well, for just the job that OP requested I would first try to use find
    +grep in order to locate all appearances of "OldFunction". The
    utilities are today available on all build systems that I know,
    including Windows. Most compilers today include some option to emit
    proprocessor output, so as part of build grep may be applied to such
    output, catching even references to OldFunction made by replacement of
    "#define mkfuncname (name) Old##name". But... we still don't know
    enought the OP's obstacles and needs, so as they say :):

    "Trust the programmer."
    "Don’t prevent the programmer from doing what needs to be done."

    Daniel
     
    Stargazer, Jun 12, 2010
    #3
  4. Stargazer

    Eric Sosman Guest

    On 6/12/2010 7:54 AM, Stargazer wrote:
    > On Jun 12, 1:14 am, Eric Sosman<> wrote:
    >> On 6/11/2010 5:24 PM, Stargazer wrote:
    >>> On Jun 11, 4:53 pm, Kenneth Brody<> wrote:
    >>>> [...]
    >>>> I was thinking of something like this, but it just seems... ugly.

    >>
    >>>> #define OldFunction(foo,bar) {***__OldFunction__ called!***;}

    >>
    >>>> Another problem with this version is that the macro would have to be in
    >>>> every source file (obviously), but _after_ the "normal" #includes, as
    >>>> OldFunction is prototyped in the (standard other than C) header files which
    >>>> are included.

    >>
    >>> Didn't get a reason of this requirement.

    >>
    >> Because if the macro is in force when the system header utters
    >> its prototype
    >>
    >> void OldFunction(int this, double that);
    >>
    >> ... the macro will change it to
    >>
    >> void (1 == int this, 2 = double that);
    >>
    >> ... right at the point of the header's declaration. This causes a
    >> compile error (as desired), but for every file that includes the
    >> header, whether it uses OldFunction or not.

    >
    > This will happen only if
    >
    > #define OldFunction(foo,bar) (1 = foo, 3 = bar)
    >
    > occurs before OldFunction()'s declaration in the header; so it should
    > appear after #include to that system header or in the header *after*
    > the declaration of OldFunction().


    Right. Isn't that the requirement you "didn't get a reason of?"

    > [...]
    >>> Anyway, you may limit the
    >>> effect of erroneous definition to your sources only, something like

    >>
    >>> #ifdef MY_SOURCE
    >>> #define OldFunction(foo,bar) {***__OldFunction__ called!***;}
    >>> #endif

    >>
    >>> in the system header, [...]

    >>
    >> Most programming shops take a dim view of hand-editing the
    >> system-supplied headers. Too much opportunity for mischief (both
    >> intentional and accidental), and also susceptible to being clobbered
    >> by the next vendor-supplied patch ...

    >
    > True. But sometimes (much more often than I would actually like it to
    > occur) vendors won't supply you anything unless you prove them "beyond
    > any doubt" that they have a bug. They wouldn't even acknowledge that
    > they have a bug unless you prove it. In such a case a programmer has
    > only two options: declare that there's a problem and nothing can be
    > done about it, or use any existing instrument to do the diagnosis.


    The O.P. didn't say anything about OldFunction() being buggy;
    he just called it "outdated." That is, there's nothing "wrong" with
    the system header; it's just that one project has decided to migrate
    to using the newer/better/whiter/brighter interface exclusively, and
    would like to police itself. Also, the O.P. did not imply that this
    migration was to apply to all projects; others may still want and need
    to use the older interface.

    Plus, as I mentioned earlier, the vendor might perfectly well
    issue a new version of the header in a patch, still retaining the old
    interface for backwards compatibility, so any local edits are vulnerable
    to being overwritten.

    To summarize, nothing you've said convinces me that modifying the
    implementation is either wise or effective. YMMV -- but in the end,
    the decision is not up to either of us.

    --
    Eric Sosman
    lid
     
    Eric Sosman, Jun 12, 2010
    #4
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Michael Gaab

    forcing a compile time error

    Michael Gaab, Nov 8, 2003, in forum: C++
    Replies:
    8
    Views:
    583
    NFish
    Nov 9, 2003
  2. Bryan Bullard
    Replies:
    17
    Views:
    582
    Donovan Rebbechi
    Jan 11, 2004
  3. flamesrock
    Replies:
    8
    Views:
    476
    Hendrik van Rooyen
    Nov 24, 2006
  4. Nagaraj
    Replies:
    1
    Views:
    872
    Lionel B
    Mar 1, 2007
  5. Carter
    Replies:
    2
    Views:
    509
    Carter
    Mar 4, 2009
Loading...

Share This Page