Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit f1f10a1

Browse filesBrowse 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
Copy full SHA for f1f10a1

File tree

Expand file treeCollapse file tree

7 files changed

+76
-12
lines changed
Filter options
Expand file treeCollapse file tree

7 files changed

+76
-12
lines changed

‎src/backend/storage/page/bufpage.c

Copy file name to clipboardExpand all lines: src/backend/storage/page/bufpage.c
+1-8Lines changed: 1 addition & 8 deletions
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

Copy file name to clipboardExpand all lines: src/backend/utils/adt/lockfuncs.c
+6Lines changed: 6 additions & 0 deletions
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

Copy file name to clipboardExpand all lines: src/backend/utils/misc/guc.c
+39Lines changed: 39 additions & 0 deletions
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

Copy file name to clipboardExpand all lines: src/bin/pg_dump/pg_dump_sort.c
+3Lines changed: 3 additions & 0 deletions
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

Copy file name to clipboardExpand all lines: src/common/relpath.c
+3Lines changed: 3 additions & 0 deletions
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

Copy file name to clipboardExpand all lines: src/include/c.h
+14-4Lines changed: 14 additions & 4 deletions
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

Copy file name to clipboardExpand all lines: src/include/storage/bufpage.h
+10Lines changed: 10 additions & 0 deletions
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 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.