Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit f1f10a1

Browse files
committed
Add declaration-level assertions for compile-time checks
Those new assertions can be used at file scope, outside of any function for compilation checks. This commit provides implementations for C and C++, and fallback implementations. Author: Peter Smith Reviewed-by: Andres Freund, Kyotaro Horiguchi, Dagfinn Ilmari Mannsåker, Michael Paquier Discussion: https://postgr.es/m/201DD0641B056142AC8C6645EC1B5F62014B8E8030@SYD1217
1 parent 6148e2b commit f1f10a1

File tree

7 files changed

+76
-12
lines changed

7 files changed

+76
-12
lines changed

src/backend/storage/page/bufpage.c

+1-8
Original file line numberDiff line numberDiff line change
@@ -119,14 +119,7 @@ PageIsVerified(Page page, BlockNumber blkno)
119119
return true;
120120
}
121121

122-
/*
123-
* Check all-zeroes case. Luckily BLCKSZ is guaranteed to always be a
124-
* multiple of size_t - and it's much faster to compare memory using the
125-
* native word size.
126-
*/
127-
StaticAssertStmt(BLCKSZ == (BLCKSZ / sizeof(size_t)) * sizeof(size_t),
128-
"BLCKSZ has to be a multiple of sizeof(size_t)");
129-
122+
/* Check all-zeroes case */
130123
all_zeroes = true;
131124
pagebytes = (size_t *) page;
132125
for (i = 0; i < (BLCKSZ / sizeof(size_t)); i++)

src/backend/utils/adt/lockfuncs.c

+6
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,19 @@ const char *const LockTagTypeNames[] = {
3636
"advisory"
3737
};
3838

39+
StaticAssertDecl(lengthof(LockTagTypeNames) == (LOCKTAG_ADVISORY + 1),
40+
"array length mismatch");
41+
3942
/* This must match enum PredicateLockTargetType (predicate_internals.h) */
4043
static const char *const PredicateLockTagTypeNames[] = {
4144
"relation",
4245
"page",
4346
"tuple"
4447
};
4548

49+
StaticAssertDecl(lengthof(PredicateLockTagTypeNames) == (PREDLOCKTAG_TUPLE + 1),
50+
"array length mismatch");
51+
4652
/* Working status for pg_lock_status */
4753
typedef struct
4854
{

src/backend/utils/misc/guc.c

+39
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,9 @@ static const struct config_enum_entry bytea_output_options[] = {
241241
{NULL, 0, false}
242242
};
243243

244+
StaticAssertDecl(lengthof(bytea_output_options) == (BYTEA_OUTPUT_HEX + 2),
245+
"array length mismatch");
246+
244247
/*
245248
* We have different sets for client and server message level options because
246249
* they sort slightly different (see "log" level), and because "fatal"/"panic"
@@ -286,13 +289,19 @@ static const struct config_enum_entry intervalstyle_options[] = {
286289
{NULL, 0, false}
287290
};
288291

292+
StaticAssertDecl(lengthof(intervalstyle_options) == (INTSTYLE_ISO_8601 + 2),
293+
"array length mismatch");
294+
289295
static const struct config_enum_entry log_error_verbosity_options[] = {
290296
{"terse", PGERROR_TERSE, false},
291297
{"default", PGERROR_DEFAULT, false},
292298
{"verbose", PGERROR_VERBOSE, false},
293299
{NULL, 0, false}
294300
};
295301

302+
StaticAssertDecl(lengthof(log_error_verbosity_options) == (PGERROR_VERBOSE + 2),
303+
"array length mismatch");
304+
296305
static const struct config_enum_entry log_statement_options[] = {
297306
{"none", LOGSTMT_NONE, false},
298307
{"ddl", LOGSTMT_DDL, false},
@@ -301,6 +310,9 @@ static const struct config_enum_entry log_statement_options[] = {
301310
{NULL, 0, false}
302311
};
303312

313+
StaticAssertDecl(lengthof(log_statement_options) == (LOGSTMT_ALL + 2),
314+
"array length mismatch");
315+
304316
static const struct config_enum_entry isolation_level_options[] = {
305317
{"serializable", XACT_SERIALIZABLE, false},
306318
{"repeatable read", XACT_REPEATABLE_READ, false},
@@ -316,6 +328,9 @@ static const struct config_enum_entry session_replication_role_options[] = {
316328
{NULL, 0, false}
317329
};
318330

331+
StaticAssertDecl(lengthof(session_replication_role_options) == (SESSION_REPLICATION_ROLE_LOCAL + 2),
332+
"array length mismatch");
333+
319334
static const struct config_enum_entry syslog_facility_options[] = {
320335
#ifdef HAVE_SYSLOG
321336
{"local0", LOG_LOCAL0, false},
@@ -339,18 +354,27 @@ static const struct config_enum_entry track_function_options[] = {
339354
{NULL, 0, false}
340355
};
341356

357+
StaticAssertDecl(lengthof(track_function_options) == (TRACK_FUNC_ALL + 2),
358+
"array length mismatch");
359+
342360
static const struct config_enum_entry xmlbinary_options[] = {
343361
{"base64", XMLBINARY_BASE64, false},
344362
{"hex", XMLBINARY_HEX, false},
345363
{NULL, 0, false}
346364
};
347365

366+
StaticAssertDecl(lengthof(xmlbinary_options) == (XMLBINARY_HEX + 2),
367+
"array length mismatch");
368+
348369
static const struct config_enum_entry xmloption_options[] = {
349370
{"content", XMLOPTION_CONTENT, false},
350371
{"document", XMLOPTION_DOCUMENT, false},
351372
{NULL, 0, false}
352373
};
353374

375+
StaticAssertDecl(lengthof(xmloption_options) == (XMLOPTION_CONTENT + 2),
376+
"array length mismatch");
377+
354378
/*
355379
* Although only "on", "off", and "safe_encoding" are documented, we
356380
* accept all the likely variants of "on" and "off".
@@ -465,6 +489,9 @@ const struct config_enum_entry ssl_protocol_versions_info[] = {
465489
{NULL, 0, false}
466490
};
467491

492+
StaticAssertDecl(lengthof(ssl_protocol_versions_info) == (PG_TLS1_3_VERSION + 2),
493+
"array length mismatch");
494+
468495
static struct config_enum_entry shared_memory_options[] = {
469496
#ifndef WIN32
470497
{"sysv", SHMEM_TYPE_SYSV, false},
@@ -615,6 +642,9 @@ const char *const GucContext_Names[] =
615642
/* PGC_USERSET */ "user"
616643
};
617644

645+
StaticAssertDecl(lengthof(GucContext_Names) == (PGC_USERSET + 1),
646+
"array length mismatch");
647+
618648
/*
619649
* Displayable names for source types (enum GucSource)
620650
*
@@ -638,6 +668,9 @@ const char *const GucSource_Names[] =
638668
/* PGC_S_SESSION */ "session"
639669
};
640670

671+
StaticAssertDecl(lengthof(GucSource_Names) == (PGC_S_SESSION + 1),
672+
"array length mismatch");
673+
641674
/*
642675
* Displayable names for the groupings defined in enum config_group
643676
*/
@@ -749,6 +782,9 @@ const char *const config_group_names[] =
749782
NULL
750783
};
751784

785+
StaticAssertDecl(lengthof(config_group_names) == (DEVELOPER_OPTIONS + 2),
786+
"array length mismatch");
787+
752788
/*
753789
* Displayable names for GUC variable types (enum config_type)
754790
*
@@ -763,6 +799,9 @@ const char *const config_type_names[] =
763799
/* PGC_ENUM */ "enum"
764800
};
765801

802+
StaticAssertDecl(lengthof(config_type_names) == (PGC_ENUM + 1),
803+
"array length mismatch");
804+
766805
/*
767806
* Unit conversion tables.
768807
*

src/bin/pg_dump/pg_dump_sort.c

+3
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,9 @@ static const int dbObjectTypePriority[] =
8080
38 /* DO_SUBSCRIPTION */
8181
};
8282

83+
StaticAssertDecl(lengthof(dbObjectTypePriority) == (DO_SUBSCRIPTION + 1),
84+
"array length mismatch");
85+
8386
static DumpId preDataBoundId;
8487
static DumpId postDataBoundId;
8588

src/common/relpath.c

+3
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ const char *const forkNames[] = {
3737
"init" /* INIT_FORKNUM */
3838
};
3939

40+
StaticAssertDecl(lengthof(forkNames) == (MAX_FORKNUM + 1),
41+
"array length mismatch");
42+
4043
/*
4144
* forkname_to_number - look up fork number by name
4245
*

src/include/c.h

+14-4
Original file line numberDiff line numberDiff line change
@@ -832,8 +832,10 @@ extern void ExceptionalCondition(const char *conditionName,
832832
* throw a compile error using the "errmessage" (a string literal).
833833
*
834834
* gcc 4.6 and up supports _Static_assert(), but there are bizarre syntactic
835-
* placement restrictions. These macros make it safe to use as a statement
836-
* or in an expression, respectively.
835+
* placement restrictions. Macros StaticAssertStmt() and StaticAssertExpr()
836+
* make it safe to use as a statement or in an expression, respectively.
837+
* The macro StaticAssertDecl() is suitable for use at file scope (outside of
838+
* any function).
837839
*
838840
* Otherwise we fall back on a kluge that assumes the compiler will complain
839841
* about a negative width for a struct bit-field. This will not include a
@@ -845,24 +847,32 @@ extern void ExceptionalCondition(const char *conditionName,
845847
do { _Static_assert(condition, errmessage); } while(0)
846848
#define StaticAssertExpr(condition, errmessage) \
847849
((void) ({ StaticAssertStmt(condition, errmessage); true; }))
850+
#define StaticAssertDecl(condition, errmessage) \
851+
_Static_assert(condition, errmessage)
848852
#else /* !HAVE__STATIC_ASSERT */
849853
#define StaticAssertStmt(condition, errmessage) \
850854
((void) sizeof(struct { int static_assert_failure : (condition) ? 1 : -1; }))
851855
#define StaticAssertExpr(condition, errmessage) \
852856
StaticAssertStmt(condition, errmessage)
857+
#define StaticAssertDecl(condition, errmessage) \
858+
extern void static_assert_func(int static_assert_failure[(condition) ? 1 : -1])
853859
#endif /* HAVE__STATIC_ASSERT */
854860
#else /* C++ */
855861
#if defined(__cpp_static_assert) && __cpp_static_assert >= 200410
856862
#define StaticAssertStmt(condition, errmessage) \
857863
static_assert(condition, errmessage)
858864
#define StaticAssertExpr(condition, errmessage) \
859865
({ static_assert(condition, errmessage); })
860-
#else
866+
#define StaticAssertDecl(condition, errmessage) \
867+
static_assert(condition, errmessage)
868+
#else /* !__cpp_static_assert */
861869
#define StaticAssertStmt(condition, errmessage) \
862870
do { struct static_assert_struct { int static_assert_failure : (condition) ? 1 : -1; }; } while(0)
863871
#define StaticAssertExpr(condition, errmessage) \
864872
((void) ({ StaticAssertStmt(condition, errmessage); }))
865-
#endif
873+
#define StaticAssertDecl(condition, errmessage) \
874+
extern void static_assert_func(int static_assert_failure[(condition) ? 1 : -1])
875+
#endif /* __cpp_static_assert */
866876
#endif /* C++ */
867877

868878

src/include/storage/bufpage.h

+10
Original file line numberDiff line numberDiff line change
@@ -418,6 +418,16 @@ do { \
418418
((overwrite) ? PAI_OVERWRITE : 0) | \
419419
((is_heap) ? PAI_IS_HEAP : 0))
420420

421+
/*
422+
* Check that BLCKSZ is a multiple of sizeof(size_t). In PageIsVerified(),
423+
* it is much faster to check if a page is full of zeroes using the native
424+
* word size. Note that this assertion is kept within a header to make
425+
* sure that StaticAssertDecl() works across various combinations of
426+
* platforms and compilers.
427+
*/
428+
StaticAssertDecl(BLCKSZ == ((BLCKSZ / sizeof(size_t)) * sizeof(size_t)),
429+
"BLCKSZ has to be a multiple of sizeof(size_t)");
430+
421431
extern void PageInit(Page page, Size pageSize, Size specialSize);
422432
extern bool PageIsVerified(Page page, BlockNumber blkno);
423433
extern OffsetNumber PageAddItemExtended(Page page, Item item, Size size,

0 commit comments

Comments
 (0)