tech@mandoc.bsd.lv
 help / color / mirror / Atom feed
* enum type safety
       [not found]     ` <20140817122227.GH21604@danbala.tuwien.ac.at>
@ 2014-08-17 15:57       ` Ingo Schwarze
  0 siblings, 0 replies; only message in thread
From: Ingo Schwarze @ 2014-08-17 15:57 UTC (permalink / raw)
  To: tech; +Cc: Thomas Klausner

Hi,

Thomas Klausner just pointed out that some compilers still worry
that the local variable r might be used uninitialized in term_ascii.c,
function ascii_hspan().

Digging into this, i found that it cannot actually happen:

 1. The function ascii_hspan() is only called through the
    struct termp hspan function pointer.

 2. Such a call happens at exactly one place: term.c, term_hspan().

 3. The function term_hspan() has the following callers:

     - term.c, term_setwidth()
     - man_term.c, a2width()
     - mdoc_term.c, a2width()
     - mdoc_term.c, a2offs()

    All these callers initialize the struct roffsu passed to term_hspan()
    using a2roffsu() and checking the return value or SCALE_HS_INIT().

Now obviously, when compiling the term_ascii.c translation unit,
the compiler cannot know what the calling translation units may
pass into this non-static function.

But what can they?  All the enum roffscale enumeration constants
defined in out.h are handled in ascii_hspan().  Isn't that safe?
What could possibly go wrong?

Digging into this, i learnt something about C i didn't yet know.
Here is what the C standard says (C99 = ISO/IEC 9899:TC3,
C11 = ISO/IEC 9899:201x Comittee Draft):

 * Each enumerated type shall be compatible with a char,
   a signed integer type, or an unsigned integer type.
   The choice of type is implementation-defined, ...
   (C99/C11 6.7.2.2 paragraph 4)

 * Conversion of an operand value to a compatible type
   causes no change to the value or the representation.
   (C99/C11 6.3 paragraph 2)

So the C standard *requires* enum types to *not* be type-safe,
the following would be legal C:

	enum roffscale	 scale;
	char		 c;
	/* ... */
	scale = 42;
	/* ... */
	c = scale;

And now the C standard *requires* that c ends up being 42.

This is amazing.  You use enum for type safety (that's generally
regarded as good practice, isn't it?) and then the very standard
forbids the compiler to actually implement enum in a type-safe way.

So whereever you have an interface with external linkage accepting
an enum value, for defensive programming you have to assume that
*any* value representable in *any* signed or unsigned integer type
can come in, so you basically *always* need a default: clause.

Is this analysis right, or do you consider the patch appended
below as silly?

Yours,
  Ingo


Index: term_ascii.c
===================================================================
RCS file: /usr/vhosts/mdocml.bsd.lv/cvs/mdocml/term_ascii.c,v
retrieving revision 1.31
diff -u -p -r1.31 term_ascii.c
--- term_ascii.c	16 Aug 2014 19:00:01 -0000	1.31
+++ term_ascii.c	17 Aug 2014 15:54:48 -0000
@@ -253,7 +253,7 @@ ascii_hspan(const struct termp *p, const
 	case SCALE_EM:
 		r = su->scale;
 		break;
-	case SCALE_MAX:
+	default:
 		abort();
 		/* NOTREACHED */
 	}
--
 To unsubscribe send an email to tech+unsubscribe@mdocml.bsd.lv

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2014-08-17 15:58 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <20140814214036.GJ29858@iris.usta.de>
     [not found] ` <sfid-H20140816-235801-+037.93-1@spamfilter.osbf.lua>
     [not found]   ` <20140816215701.GE12335@iris.usta.de>
     [not found]     ` <20140817122227.GH21604@danbala.tuwien.ac.at>
2014-08-17 15:57       ` enum type safety Ingo Schwarze

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).