<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang xml:lang>
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="mpark/wg21" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <meta name="dcterms.date" content="2024-09-17" />
  <title>A Safety Profile Verifying Class Initialization</title>
  <style>
code{white-space: pre-wrap;}
span.smallcaps{font-variant: small-caps;}
span.underline{text-decoration: underline;}
div.column{display: inline-block; vertical-align: top; width: 50%;}
div.csl-block{margin-left: 1.5em;}
ul.task-list{list-style: none;}
pre > code.sourceCode { white-space: pre; position: relative; }
pre > code.sourceCode > span { line-height: 1.25; }
pre > code.sourceCode > span:empty { height: 1.2em; }
.sourceCode { overflow: visible; }
code.sourceCode > span { color: inherit; text-decoration: inherit; }
div.sourceCode { margin: 1em 0; }
pre.sourceCode { margin: 0; }
@media screen {
div.sourceCode { overflow: auto; }
}
@media print {
pre > code.sourceCode { white-space: pre-wrap; }
pre > code.sourceCode > span { display: inline-block; text-indent: -5em; padding-left: 5em; }
}
pre.numberSource code
{ counter-reset: source-line 0; }
pre.numberSource code > span
{ position: relative; left: -4em; counter-increment: source-line; }
pre.numberSource code > span > a:first-child::before
{ content: counter(source-line);
position: relative; left: -1em; text-align: right; vertical-align: baseline;
border: none; display: inline-block;
-webkit-touch-callout: none; -webkit-user-select: none;
-khtml-user-select: none; -moz-user-select: none;
-ms-user-select: none; user-select: none;
padding: 0 4px; width: 4em;
color: #aaaaaa;
}
pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa; padding-left: 4px; }
div.sourceCode
{ background-color: #f6f8fa; }
@media screen {
pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
}
code span { } 
code span.al { color: #ff0000; } 
code span.an { } 
code span.at { } 
code span.bn { color: #9f6807; } 
code span.bu { color: #9f6807; } 
code span.cf { color: #00607c; } 
code span.ch { color: #9f6807; } 
code span.cn { } 
code span.co { color: #008000; font-style: italic; } 
code span.cv { color: #008000; font-style: italic; } 
code span.do { color: #008000; } 
code span.dt { color: #00607c; } 
code span.dv { color: #9f6807; } 
code span.er { color: #ff0000; font-weight: bold; } 
code span.ex { } 
code span.fl { color: #9f6807; } 
code span.fu { } 
code span.im { } 
code span.in { color: #008000; } 
code span.kw { color: #00607c; } 
code span.op { color: #af1915; } 
code span.ot { } 
code span.pp { color: #6f4e37; } 
code span.re { } 
code span.sc { color: #9f6807; } 
code span.ss { color: #9f6807; } 
code span.st { color: #9f6807; } 
code span.va { } 
code span.vs { color: #9f6807; } 
code span.wa { color: #008000; font-weight: bold; } 
code.diff {color: #898887}
code.diff span.va {color: #006e28}
code.diff span.st {color: #bf0303}
</style>
  <style type="text/css">
body {
margin: 5em;
font-family: serif;

hyphens: auto;
line-height: 1.35;
text-align: justify;
}
@media screen and (max-width: 30em) {
body {
margin: 1.5em;
}
}
div.wrapper {
max-width: 60em;
margin: auto;
}
ul {
list-style-type: none;
padding-left: 2em;
margin-top: -0.2em;
margin-bottom: -0.2em;
}
a {
text-decoration: none;
color: #4183C4;
}
a.hidden_link {
text-decoration: none;
color: inherit;
}
li {
margin-top: 0.6em;
margin-bottom: 0.6em;
}
h1, h2, h3, h4 {
position: relative;
line-height: 1;
}
a.self-link {
position: absolute;
top: 0;
left: calc(-1 * (3.5rem - 26px));
width: calc(3.5rem - 26px);
height: 2em;
text-align: center;
border: none;
transition: opacity .2s;
opacity: .5;
font-family: sans-serif;
font-weight: normal;
font-size: 83%;
}
a.self-link:hover { opacity: 1; }
a.self-link::before { content: "§"; }
ul > li:before {
content: "\2014";
position: absolute;
margin-left: -1.5em;
}
:target { background-color: #C9FBC9; }
:target .codeblock { background-color: #C9FBC9; }
:target ul { background-color: #C9FBC9; }
.abbr_ref { float: right; }
.folded_abbr_ref { float: right; }
:target .folded_abbr_ref { display: none; }
:target .unfolded_abbr_ref { float: right; display: inherit; }
.unfolded_abbr_ref { display: none; }
.secnum { display: inline-block; min-width: 35pt; }
.header-section-number { display: inline-block; min-width: 35pt; }
.annexnum { display: block; }
div.sourceLinkParent {
float: right;
}
a.sourceLink {
position: absolute;
opacity: 0;
margin-left: 10pt;
}
a.sourceLink:hover {
opacity: 1;
}
a.itemDeclLink {
position: absolute;
font-size: 75%;
text-align: right;
width: 5em;
opacity: 0;
}
a.itemDeclLink:hover { opacity: 1; }
span.marginalizedparent {
position: relative;
left: -5em;
}
li span.marginalizedparent { left: -7em; }
li ul > li span.marginalizedparent { left: -9em; }
li ul > li ul > li span.marginalizedparent { left: -11em; }
li ul > li ul > li ul > li span.marginalizedparent { left: -13em; }
div.footnoteNumberParent {
position: relative;
left: -4.7em;
}
a.marginalized {
position: absolute;
font-size: 75%;
text-align: right;
width: 5em;
}
a.enumerated_item_num {
position: relative;
left: -3.5em;
display: inline-block;
margin-right: -3em;
text-align: right;
width: 3em;
}
div.para { margin-bottom: 0.6em; margin-top: 0.6em; text-align: justify; }
div.section { text-align: justify; }
div.sentence { display: inline; }
span.indexparent {
display: inline;
position: relative;
float: right;
right: -1em;
}
a.index {
position: absolute;
display: none;
}
a.index:before { content: "⟵"; }

a.index:target {
display: inline;
}
.indexitems {
margin-left: 2em;
text-indent: -2em;
}
div.itemdescr {
margin-left: 3em;
}
.bnf {
font-family: serif;
margin-left: 40pt;
margin-top: 0.5em;
margin-bottom: 0.5em;
}
.ncbnf {
font-family: serif;
margin-top: 0.5em;
margin-bottom: 0.5em;
margin-left: 40pt;
}
.ncsimplebnf {
font-family: serif;
font-style: italic;
margin-top: 0.5em;
margin-bottom: 0.5em;
margin-left: 40pt;
background: inherit; 
}
span.textnormal {
font-style: normal;
font-family: serif;
white-space: normal;
display: inline-block;
}
span.rlap {
display: inline-block;
width: 0px;
}
span.descr { font-style: normal; font-family: serif; }
span.grammarterm { font-style: italic; }
span.term { font-style: italic; }
span.terminal { font-family: monospace; font-style: normal; }
span.nonterminal { font-style: italic; }
span.tcode { font-family: monospace; font-style: normal; }
span.textbf { font-weight: bold; }
span.textsc { font-variant: small-caps; }
a.nontermdef { font-style: italic; font-family: serif; }
span.emph { font-style: italic; }
span.techterm { font-style: italic; }
span.mathit { font-style: italic; }
span.mathsf { font-family: sans-serif; }
span.mathrm { font-family: serif; font-style: normal; }
span.textrm { font-family: serif; }
span.textsl { font-style: italic; }
span.mathtt { font-family: monospace; font-style: normal; }
span.mbox { font-family: serif; font-style: normal; }
span.ungap { display: inline-block; width: 2pt; }
span.textit { font-style: italic; }
span.texttt { font-family: monospace; }
span.tcode_in_codeblock { font-family: monospace; font-style: normal; }
span.phantom { color: white; }

span.math { font-style: normal; }
span.mathblock {
display: block;
margin-left: auto;
margin-right: auto;
margin-top: 1.2em;
margin-bottom: 1.2em;
text-align: center;
}
span.mathalpha {
font-style: italic;
}
span.synopsis {
font-weight: bold;
margin-top: 0.5em;
display: block;
}
span.definition {
font-weight: bold;
display: block;
}
.codeblock {
margin-left: 1.2em;
line-height: 127%;
}
.outputblock {
margin-left: 1.2em;
line-height: 127%;
}
div.itemdecl {
margin-top: 2ex;
}
code.itemdeclcode {
white-space: pre;
display: block;
}
span.textsuperscript {
vertical-align: super;
font-size: smaller;
line-height: 0;
}
.footnotenum { vertical-align: super; font-size: smaller; line-height: 0; }
.footnote {
font-size: small;
margin-left: 2em;
margin-right: 2em;
margin-top: 0.6em;
margin-bottom: 0.6em;
}
div.minipage {
display: inline-block;
margin-right: 3em;
}
div.numberedTable {
text-align: center;
margin: 2em;
}
div.figure {
text-align: center;
margin: 2em;
}
table {
border: 1px solid black;
border-collapse: collapse;
margin-left: auto;
margin-right: auto;
margin-top: 0.8em;
text-align: left;
hyphens: none; 
}
td, th {
padding-left: 1em;
padding-right: 1em;
vertical-align: top;
}
td.empty {
padding: 0px;
padding-left: 1px;
}
td.left {
text-align: left;
}
td.right {
text-align: right;
}
td.center {
text-align: center;
}
td.justify {
text-align: justify;
}
td.border {
border-left: 1px solid black;
}
tr.rowsep, td.cline {
border-top: 1px solid black;
}
tr.even, tr.odd {
border-bottom: 1px solid black;
}
tr.capsep {
border-top: 3px solid black;
border-top-style: double;
}
tr.header {
border-bottom: 3px solid black;
border-bottom-style: double;
}
th {
border-bottom: 1px solid black;
}
span.centry {
font-weight: bold;
}
div.table {
display: block;
margin-left: auto;
margin-right: auto;
text-align: center;
width: 90%;
}
span.indented {
display: block;
margin-left: 2em;
margin-bottom: 1em;
margin-top: 1em;
}
ol.enumeratea { list-style-type: none; background: inherit; }
ol.enumerate { list-style-type: none; background: inherit; }

code.sourceCode > span { display: inline; }
</style>
  <link href="data:image/vnd.microsoft.icon;base64,AAABAAIAEBAAAAEAIABoBAAAJgAAACAgAAABACAAqBAAAI4EAAAoAAAAEAAAACAAAAABACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////AIJEAACCRAAAgkQAAIJEAACCRAAAgkQAVoJEAN6CRADegkQAWIJEAACCRAAAgkQAAIJEAACCRAAA////AP///wCCRAAAgkQAAIJEAACCRAAsgkQAvoJEAP+CRAD/gkQA/4JEAP+CRADAgkQALoJEAACCRAAAgkQAAP///wD///8AgkQAAIJEABSCRACSgkQA/IJEAP99PQD/dzMA/3czAP99PQD/gkQA/4JEAPyCRACUgkQAFIJEAAD///8A////AHw+AFiBQwDqgkQA/4BBAP9/PxP/uZd6/9rJtf/bybX/upd7/39AFP+AQQD/gkQA/4FDAOqAQgBc////AP///wDKklv4jlEa/3o7AP+PWC//8+3o///////////////////////z7un/kFox/35AAP+GRwD/mVYA+v///wD///8A0Zpk+NmibP+0d0T/8evj///////+/fv/1sKz/9bCs//9/fr//////+/m2/+NRwL/nloA/5xYAPj///8A////ANKaZPjRmGH/5cKh////////////k149/3UwAP91MQD/lmQ//86rhv+USg3/m1YA/5hSAP+bVgD4////AP///wDSmmT4zpJY/+/bx///////8+TV/8mLT/+TVx//gkIA/5lVAP+VTAD/x6B//7aEVv/JpH7/s39J+P///wD///8A0ppk+M6SWP/u2sf///////Pj1f/Nj1T/2KFs/8mOUv+eWhD/lEsA/8aee/+0glT/x6F7/7J8Rvj///8A////ANKaZPjRmGH/48Cf///////+/v7/2qt//82PVP/OkFX/37KJ/86siv+USg7/mVQA/5hRAP+bVgD4////AP///wDSmmT40ppk/9CVXP/69O////////7+/v/x4M//8d/P//7+/f//////9u7n/6tnJf+XUgD/nFgA+P///wD///8A0ppk+NKaZP/RmWL/1qNy//r07///////////////////////+vXw/9akdP/Wnmn/y5FY/6JfFvj///8A////ANKaZFTSmmTo0ppk/9GYYv/Ql1//5cWm//Hg0P/x4ND/5cWm/9GXYP/RmGH/0ppk/9KaZOjVnmpY////AP///wDSmmQA0ppkEtKaZI7SmmT60ppk/9CWX//OkVb/zpFW/9CWX//SmmT/0ppk/NKaZJDSmmQS0ppkAP///wD///8A0ppkANKaZADSmmQA0ppkKtKaZLrSmmT/0ppk/9KaZP/SmmT/0ppkvNKaZCrSmmQA0ppkANKaZAD///8A////ANKaZADSmmQA0ppkANKaZADSmmQA0ppkUtKaZNzSmmTc0ppkVNKaZADSmmQA0ppkANKaZADSmmQA////AP5/AAD4HwAA4AcAAMADAACAAQAAgAEAAIABAACAAQAAgAEAAIABAACAAQAAgAEAAMADAADgBwAA+B8AAP5/AAAoAAAAIAAAAEAAAAABACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////AP///wCCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAAyCRACMgkQA6oJEAOqCRACQgkQAEIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAA////AP///wD///8A////AIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRABigkQA5oJEAP+CRAD/gkQA/4JEAP+CRADqgkQAZoJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAAD///8A////AP///wD///8AgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAA4gkQAwoJEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQAxIJEADyCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAP///wD///8A////AP///wCCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAWgkQAmIJEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAJyCRAAYgkQAAIJEAACCRAAAgkQAAIJEAACCRAAA////AP///wD///8A////AIJEAACCRAAAgkQAAIJEAACCRAAAgkQAdIJEAPCCRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAPSCRAB4gkQAAIJEAACCRAAAgkQAAIJEAAD///8A////AP///wD///8AgkQAAIJEAACCRAAAgkQASoJEANKCRAD/gkQA/4JEAP+CRAD/g0YA/39AAP9zLgD/bSQA/2shAP9rIQD/bSQA/3MuAP9/PwD/g0YA/4JEAP+CRAD/gkQA/4JEAP+CRADUgkQAToJEAACCRAAAgkQAAP///wD///8A////AP///wB+PwAAgkUAIoJEAKiCRAD/gkQA/4JEAP+CRAD/hEcA/4BBAP9sIwD/dTAA/5RfKv+viF7/vp56/76ee/+wiF7/lWAr/3YxAP9sIwD/f0AA/4RHAP+CRAD/gkQA/4JEAP+CRAD/gkQArIJEACaBQwAA////AP///wD///8A////AIBCAEBzNAD6f0EA/4NFAP+CRAD/gkQA/4VIAP92MwD/bSUA/6N1Tv/ezsL/////////////////////////////////38/D/6V3Uv9uJgD/dTEA/4VJAP+CRAD/gkQA/4JEAP+BQwD/fUAA/4FDAEj///8A////AP///wD///8AzJRd5qBlKf91NgD/dDUA/4JEAP+FSQD/cy4A/3YyAP/PuKP//////////////////////////////////////////////////////9K7qP94NQD/ciwA/4VJAP+CRAD/fkEA/35BAP+LSwD/mlYA6v///wD///8A////AP///wDdpnL/4qx3/8KJUv+PUhf/cTMA/3AsAP90LgD/4dK+/////////////////////////////////////////////////////////////////+TYxf91MAD/dTIA/31CAP+GRwD/llQA/6FcAP+gWwD8////AP///wD///8A////ANGZY/LSm2X/4ap3/92mcP+wdT3/byQA/8mwj////////////////////////////////////////////////////////////////////////////+LYxv9zLgP/jUoA/59bAP+hXAD/nFgA/5xYAPL///8A////AP///wD///8A0ppk8tKaZP/RmWL/1p9q/9ubXv/XqXj////////////////////////////7+fD/vZyG/6BxS/+gcUr/vJuE//r37f//////////////////////3MOr/5dQBf+dVQD/nVkA/5xYAP+cWAD/nFgA8v///wD///8A////AP///wDSmmTy0ppk/9KaZP/SmWP/yohJ//jo2P//////////////////////4NTG/4JDFf9lGAD/bSQA/20kAP9kGAD/fz8S/+Xb0f//////5NG9/6txN/+LOgD/m1QA/51aAP+cWAD/m1cA/5xYAP+cWADy////AP///wD///8A////ANKaZPLSmmT/0ppk/8+TWf/Unmv//v37//////////////////////+TWRr/VwsA/35AAP+ERgD/g0UA/4JGAP9lHgD/kFga/8KXX/+TRwD/jT4A/49CAP+VTQD/n10A/5xYAP+OQQD/lk4A/55cAPL///8A////AP///wD///8A0ppk8tKaZP/SmmT/y4tO/92yiP//////////////////////8NnE/8eCQP+rcTT/ez0A/3IyAP98PgD/gEMA/5FSAP+USwD/jj8A/5lUAP+JNwD/yqV2/694Mf+HNQD/jkAA/82rf/+laBj/jT4A8v///wD///8A////AP///wDSmmTy0ppk/9KaZP/LiUr/4byY///////////////////////gupX/0I5P/+Wuev/Lklz/l1sj/308AP+QSwD/ol0A/59aAP+aVQD/k0oA/8yoh///////+fXv/6pwO//Lp3v///////Pr4f+oay7y////AP///wD///8A////ANKaZPLSmmT/0ppk/8uJSv/hvJj//////////////////////+G7l//Jhkb/0ppk/96nc//fqXX/x4xO/6dkFP+QSQD/llEA/5xXAP+USgD/yaOA///////38uv/qG05/8ijdv//////8efb/6ZpLPL///8A////AP///wD///8A0ppk8tKaZP/SmmT/zIxO/9yxh///////////////////////7dbA/8iEQf/Sm2X/0Zlj/9ScZv/eqHf/2KJv/7yAQf+XTgD/iToA/5lSAP+JNgD/yKFv/611LP+HNQD/jT8A/8qmeP+kZRT/jT4A8v///wD///8A////AP///wDSmmTy0ppk/9KaZP/Pk1n/1J5q//78+//////////////////+/fv/1aFv/8iEQv/Tm2b/0ppl/9GZY//Wn2z/1pZc/9eldf/Bl2b/kUcA/4w9AP+OQAD/lUwA/59eAP+cWQD/jT8A/5ZOAP+eXADy////AP///wD///8A////ANKaZPLSmmT/0ppk/9KZY//KiEn/8d/P///////////////////////47+f/05tm/8iCP//KiEj/yohJ/8eCP//RmGH//vfy///////n1sP/rXQ7/4k4AP+TTAD/nVoA/5xYAP+cVwD/nFgA/5xYAPL///8A////AP///wD///8A0ppk8tKaZP/SmmT/0ptl/8uLTf/aq37////////////////////////////+/fz/6c2y/961jv/etY7/6Myx//78+v//////////////////////3MWv/5xXD/+ORAD/mFQA/51ZAP+cWAD/nFgA8v///wD///8A////AP///wDSmmTy0ppk/9KaZP/SmmT/0ppk/8mFRP/s1b//////////////////////////////////////////////////////////////////////////////+PD/0JFU/7NzMv+WUQD/kUsA/5tXAP+dWQDy////AP///wD///8A////ANKaZP/SmmT/0ppk/9KaZP/Sm2X/z5NZ/8yMT//z5NX/////////////////////////////////////////////////////////////////9Ofa/8yNUP/UmGH/36p5/8yTWv+qaSD/kksA/5ROAPz///8A////AP///wD///8A0ppk5NKaZP/SmmT/0ppk/9KaZP/TnGf/zY9T/82OUv/t1sD//////////////////////////////////////////////////////+7Yw//OkFX/zI5R/9OcZ//SmmP/26V0/9ymdf/BhUf/ol8R6P///wD///8A////AP///wDSmmQ80ppk9tKaZP/SmmT/0ppk/9KaZP/TnGj/zpFW/8qJSv/dson/8uHS//////////////////////////////////Lj0//etIv/y4lL/86QVf/TnGj/0ppk/9KaZP/RmWP/05xn/9ymdfjUnWdC////AP///wD///8A////ANKaZADSmmQc0ppkotKaZP/SmmT/0ppk/9KaZP/Tm2b/0Zli/8qJSf/NjlH/16Z3/+G8mP/myKr/5siq/+G8mP/Xp3f/zY5S/8qISf/RmGH/05tm/9KaZP/SmmT/0ppk/9KaZP/SmmSm0pljINWdaQD///8A////AP///wD///8A0ppkANKaZADSmmQA0ppkQtKaZMrSmmT/0ppk/9KaZP/SmmT/0ptl/9GYYf/Nj1P/y4lL/8qISP/KiEj/y4lK/82PU//RmGH/0ptl/9KaZP/SmmT/0ppk/9KaZP/SmmTO0ppkRtKaZADSmmQA0ppkAP///wD///8A////AP///wDSmmQA0ppkANKaZADSmmQA0ppkANKaZGzSmmTu0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmTw0ppkcNKaZADSmmQA0ppkANKaZADSmmQA////AP///wD///8A////ANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZBLSmmSQ0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppklNKaZBTSmmQA0ppkANKaZADSmmQA0ppkANKaZAD///8A////AP///wD///8A0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQy0ppkutKaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppkvtKaZDbSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkAP///wD///8A////AP///wDSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkXNKaZODSmmT/0ppk/9KaZP/SmmT/0ppk5NKaZGDSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA////AP///wD///8A////ANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkBtKaZIbSmmTo0ppk6tKaZIrSmmQK0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZAD///8A////AP/8P///+B///+AH//+AAf//AAD//AAAP/AAAA/gAAAHwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA+AAAAfwAAAP/AAAP/8AAP//gAH//+AH///4H////D//" rel="icon" />
  
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<div class="wrapper">
<header id="title-block-header">
<h1 class="title" style="text-align:center">A Safety Profile Verifying
Class Initialization</h1>
<table style="border:none;float:right">
  <tr>
    <td>Document #:</td>
    <td>P3402R0</td>
  </tr>
  <tr>
    <td>Date:</td>
    <td>2024-09-17</td>
  </tr>
  <tr>
    <td style="vertical-align:top">Project:</td>
    <td>Programming Language C++</td>
  </tr>
  <tr>
    <td style="vertical-align:top">Audience:</td>
    <td>
      SG23<br>
    </td>
  </tr>
  <tr>
    <td style="vertical-align:top">Reply-to:</td>
    <td>
      Marc-André Laverdière, Black Duck Software<br>&lt;<a href="mailto:marc-andre.laverdiere@blackduck.com" class="email">marc-andre.laverdiere@blackduck.com</a>&gt;<br>
      Christopher Lapkowski, Black Duck Software<br>&lt;<a href="mailto:redacted@blackduck.com" class="email">redacted@blackduck.com</a>&gt;<br>
      Charles-Henri Gros, Black Duck Software<br>&lt;<a href="mailto:redacted@blackduck.com" class="email">redacted@blackduck.com</a>&gt;<br>
    </td>
  </tr>
</table>
</header>
<div style="clear:both">
<div id="TOC" role="doc-toc">
<h1 id="toctitle">Contents</h1>
<ul>
<li><a href="#abstract" id="toc-abstract"><span class="toc-section-number">1</span> Abstract</a></li>
<li><a href="#introduction" id="toc-introduction"><span class="toc-section-number">2</span> Introduction</a></li>
<li><a href="#definitions" id="toc-definitions"><span class="toc-section-number">3</span> Definitions</a></li>
<li><a href="#location-of-the-profile-annotation" id="toc-location-of-the-profile-annotation"><span class="toc-section-number">4</span> Location of the Profile
Annotation</a></li>
<li><a href="#exemptions" id="toc-exemptions"><span class="toc-section-number">5</span> Exemptions</a>
<ul>
<li><a href="#constantly-initialized-static-data-members" id="toc-constantly-initialized-static-data-members"><span class="toc-section-number">5.1</span> Constantly-Initialized Static Data
Members</a></li>
<li><a href="#explicit-exemptions" id="toc-explicit-exemptions"><span class="toc-section-number">5.2</span> Explicit Exemptions</a>
<ul>
<li><a href="#exemption-by-annotation" id="toc-exemption-by-annotation"><span class="toc-section-number">5.2.1</span> Exemption by Annotation</a></li>
<li><a href="#exemption-by-type" id="toc-exemption-by-type"><span class="toc-section-number">5.2.2</span> Exemption by Type</a></li>
</ul></li>
</ul></li>
<li><a href="#verification-of-constructors" id="toc-verification-of-constructors"><span class="toc-section-number">6</span> Verification of
Constructors</a></li>
<li><a href="#templates" id="toc-templates"><span class="toc-section-number">7</span> Templates</a></li>
<li><a href="#idioms-to-consider" id="toc-idioms-to-consider"><span class="toc-section-number">8</span> Idioms to Consider</a>
<ul>
<li><a href="#non-constructor-delegating" id="toc-non-constructor-delegating"><span class="toc-section-number">8.1</span> Non-Constructor
Delegating</a></li>
</ul></li>
<li><a href="#future-work" id="toc-future-work"><span class="toc-section-number">9</span> Future Work</a></li>
<li><a href="#conclusion" id="toc-conclusion"><span class="toc-section-number">10</span> Conclusion</a></li>
<li><a href="#bibliography" id="toc-bibliography"><span class="toc-section-number">11</span> References</a></li>
</ul>
</div>
<h1 data-number="1" id="abstract"><span class="header-section-number">1</span> Abstract<a href="#abstract" class="self-link"></a></h1>
<p>We propose an attribute that specifies that every data member that
belongs to a verified class has all its data members initialized to
determinate values, assuming that the data used for construction is
itself initialized properly. Thus, when the assumptions are validated,
none of its data members can cause undefined or erroneous behavior.</p>
<p>This safety profile restricts what kind of code a constructor can
have. Existing code bases are likely to violate these constraints, and
thus this feature is an opt-in.</p>
<h1 data-number="2" id="introduction"><span class="header-section-number">2</span> Introduction<a href="#introduction" class="self-link"></a></h1>
<p>There is a growing push towards memory-safe languages. While C++ is
not memory-safe, it is desirable to specify and opt-in mechanism
allowing a subset of C++ features that would result in memory
safe-languages. This has been termed ‘profiles’(<span class="citation" data-cites="P3274R0">[<a href="https://wg21.link/p3274r0" role="doc-biblioref">P3274R0</a>]</span>), and would be specified at the
TU level using an attribute. In this paper, we propose <code class="sourceCode cpp"><span class="op">[[</span><span class="at">Profiles</span><span class="op">::</span><span class="at">enable</span><span class="op">(</span><span class="at">initialization</span><span class="op">)]]</span></code>.</p>
<p>All classes under the purview of the profile attribute will have the
guarantee that all its data members are properly initialized once the
object is constructed, assuming that the data used for construction is
itself initialized properly. In the case of a class that inherits from
one or more classes, all its base classes must be compliant with this
profile.</p>
<p>Example:</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> <span class="op">[[</span><span class="at">Profiles</span><span class="op">::</span><span class="at">enable</span><span class="op">(</span><span class="at">initialization</span><span class="op">)]]</span> parent1 <span class="op">{</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>  <span class="dt">int</span> i;</span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>  parent1<span class="op">()</span> <span class="op">=</span> <span class="cf">default</span>; <span class="co">//non-compliant, i is default initialized</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> <span class="op">[[</span><span class="at">Profiles</span><span class="op">::</span><span class="at">enable</span><span class="op">(</span><span class="at">initialization</span><span class="op">)]]</span> child1 <span class="op">:</span> <span class="kw">public</span> parent <span class="op">{</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>  <span class="dt">int</span> j;</span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a>  child1<span class="op">()</span> <span class="op">:</span> parent1<span class="op">()</span>, j<span class="op">(</span><span class="dv">42</span><span class="op">)</span> <span class="op">{}</span> <span class="co">//child is compliant, but parent isn&#39;t</span></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a><span class="co">//Not a verified class, but would be compliant if it were</span></span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> parent2 <span class="op">{</span></span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a>  <span class="dt">int</span> i <span class="op">=</span> <span class="dv">0</span>;</span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a>  parent2<span class="op">()</span> <span class="op">=</span> <span class="cf">default</span>;</span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> <span class="op">[[</span><span class="at">Profiles</span><span class="op">::</span><span class="at">enable</span><span class="op">(</span><span class="at">initialization</span><span class="op">)]]</span> child2 <span class="op">:</span> <span class="kw">public</span> parent2 <span class="op">{</span></span>
<span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a>  <span class="dt">int</span> j;</span>
<span id="cb1-17"><a href="#cb1-17" aria-hidden="true" tabindex="-1"></a>  child<span class="op">()</span> <span class="op">:</span> parent2<span class="op">()</span>, j<span class="op">(</span><span class="dv">42</span><span class="op">)</span> <span class="op">{}</span> <span class="co">//child is not compliant, because parent2 is not a verified class</span></span>
<span id="cb1-18"><a href="#cb1-18" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h1 data-number="3" id="definitions"><span class="header-section-number">3</span> Definitions<a href="#definitions" class="self-link"></a></h1>
<p>A <em>verified class</em> is a class that is affected by the profile
annotation, or a scalar type.</p>
<p>An <em>object parameter</em> is either
<code class="sourceCode cpp"><span class="kw">this</span></code> or an
explicit object parameter.</p>
<p>A <em>verified data member</em> is a data member that is not exempted
from verification.</p>
<h1 data-number="4" id="location-of-the-profile-annotation"><span class="header-section-number">4</span> Location of the Profile
Annotation<a href="#location-of-the-profile-annotation" class="self-link"></a></h1>
<p>In this paper, we give examples with the profile annotation attached
to specific classes. This deviates from <span class="citation" data-cites="P3274R0">[<a href="https://wg21.link/p3274r0" role="doc-biblioref">P3274R0</a>]</span>, which suggested annotations at
the translation unit level. We do so to make it clear which classes are
verified classes and which ones aren’t, since some examples have a mix
of them. Our proposal is orthogonal to the location of the
annotation.</p>
<h1 data-number="5" id="exemptions"><span class="header-section-number">5</span> Exemptions<a href="#exemptions" class="self-link"></a></h1>
<p>Some data members are exempt from verification, either due to
intrinsic properties, or due to explicit opt-out from the developer.</p>
<h2 data-number="5.1" id="constantly-initialized-static-data-members"><span class="header-section-number">5.1</span> Constantly-Initialized Static
Data Members<a href="#constantly-initialized-static-data-members" class="self-link"></a></h2>
<p>The presence of static data members ([class.static.data]) in a class
are allowed in this profile, but the profile offers minimal
guarantees.</p>
<p>Static data members have either static storage duration
([basic.stc.static]) or thread storage duration ([basic.stc.thread]).
They are guaranteed to be initialized with constant initialization
([basic.start.static]). However, they can be reassigned during dynamic
initialization ([basic.start.dynamic]).</p>
<p>Dynamic initialization can lead to subtle bugs, such as:</p>
<ul>
<li>Circular dependencies</li>
<li>Use of statically-initialized values before they are
dynamically-initialized.</li>
<li>Initialization order issues when dealing with symbols variables
defined in other translation units.</li>
<li>Assignment of uninitialized values</li>
</ul>
<p>All static data members belonging to verified classes that are
initialized solely using constant initialization are exempted from
verification. All other static data members are non-compliant with this
profile.</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> randomInt<span class="op">()</span> <span class="op">{</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> therandomint;</span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> therandomint;</span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> <span class="op">[[</span><span class="at">Profiles</span><span class="op">::</span><span class="at">enable</span><span class="op">(</span><span class="at">initialization</span><span class="op">)]]</span> WithStaticUninit1 <span class="op">{</span></span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a>    WithStaticUninit1<span class="op">()</span> <span class="op">=</span> <span class="cf">default</span>; <span class="co">//Not a POD</span></span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a>    <span class="kw">static</span> <span class="dt">int</span> thestatic;</span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> WithStaticUninit1<span class="op">::</span>thestatic <span class="op">=</span> randomInt<span class="op">()</span>; <span class="co">//non-compliant</span></span>
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-11"><a href="#cb2-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-12"><a href="#cb2-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-13"><a href="#cb2-13" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> <span class="op">[[</span><span class="at">Profiles</span><span class="op">::</span><span class="at">enable</span><span class="op">(</span><span class="at">initialization</span><span class="op">)]]</span> GetsCorrupted <span class="op">{</span></span>
<span id="cb2-14"><a href="#cb2-14" aria-hidden="true" tabindex="-1"></a>    GetsCorrupted<span class="op">()</span> <span class="op">:</span> thefield<span class="op">(</span><span class="dv">0</span><span class="op">)</span> <span class="op">{}</span> <span class="co">//compliant</span></span>
<span id="cb2-15"><a href="#cb2-15" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> thefield; </span>
<span id="cb2-16"><a href="#cb2-16" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb2-17"><a href="#cb2-17" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-18"><a href="#cb2-18" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> <span class="op">[[</span><span class="at">Profiles</span><span class="op">::</span><span class="at">enable</span><span class="op">(</span><span class="at">initialization</span><span class="op">)]]</span> Wrapper <span class="op">{</span></span>
<span id="cb2-19"><a href="#cb2-19" aria-hidden="true" tabindex="-1"></a>    Wrapper<span class="op">()</span> <span class="op">=</span> <span class="cf">default</span>; <span class="co">//Not a POD</span></span>
<span id="cb2-20"><a href="#cb2-20" aria-hidden="true" tabindex="-1"></a>    <span class="kw">static</span> GetsCorrupted wrapped;</span>
<span id="cb2-21"><a href="#cb2-21" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb2-22"><a href="#cb2-22" aria-hidden="true" tabindex="-1"></a>GetsCorrupted corruptingFactory<span class="op">()</span> <span class="op">{</span></span>
<span id="cb2-23"><a href="#cb2-23" aria-hidden="true" tabindex="-1"></a>    GetsCorrupted ret<span class="op">{}</span>;  <span class="co">//All initialized, good</span></span>
<span id="cb2-24"><a href="#cb2-24" aria-hidden="true" tabindex="-1"></a>    ret<span class="op">.</span>thefield <span class="op">=</span> randomInt<span class="op">()</span>; <span class="co">//Now, some uninitialized memory snuck in</span></span>
<span id="cb2-25"><a href="#cb2-25" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> ret;</span>
<span id="cb2-26"><a href="#cb2-26" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb2-27"><a href="#cb2-27" aria-hidden="true" tabindex="-1"></a>GetsCorrupted Wrapper<span class="op">::</span>wrapped <span class="op">=</span> corruptingFactory<span class="op">()</span>; <span class="co">//Non-compliant</span></span></code></pre></div>
<h2 data-number="5.2" id="explicit-exemptions"><span class="header-section-number">5.2</span> Explicit Exemptions<a href="#explicit-exemptions" class="self-link"></a></h2>
<p><span class="citation" data-cites="P3274R0">[<a href="https://wg21.link/p3274r0" role="doc-biblioref">P3274R0</a>]</span> mentions that performance
critical applications won’t initialize output buffers at first and
mentions a few possibilities: “suppression, an uninitialized annotation,
and/or by specific uninitialized types.”</p>
<p>This profile allows a pointer to be initialized to any value, whether
that’s a
<code class="sourceCode cpp"><span class="kw">nullptr</span></code>, the
return value of a
<code class="sourceCode cpp"><span class="kw">new</span></code>, or even
an hardcoded address. It does not require that the memory space pointed
to by the pointer is set to any value. This is an allowance for systems
programming, which sometimes have buffers pointing to hardcoded
addresses, which are used for interacting with devices. We leave the
question of pointer safety to <code class="sourceCode cpp"><span class="op">[[</span><span class="at">Profiles</span><span class="op">::</span><span class="at">enable</span><span class="op">(</span><span class="at">Pointers</span><span class="op">)]]</span></code>.</p>
<h3 data-number="5.2.1" id="exemption-by-annotation"><span class="header-section-number">5.2.1</span> Exemption by Annotation<a href="#exemption-by-annotation" class="self-link"></a></h3>
<p>Developers who require to exempt specific data members from
verification may use the <code class="sourceCode cpp"><span class="op">[[</span><span class="at">indeterminate</span><span class="op">]]</span></code>
annotation from <span class="citation" data-cites="P2795R5">[<a href="https://wg21.link/p2795r5" role="doc-biblioref">P2795R5</a>]</span>.</p>
<h3 data-number="5.2.2" id="exemption-by-type"><span class="header-section-number">5.2.2</span> Exemption by Type<a href="#exemption-by-type" class="self-link"></a></h3>
<p>A better solution is to use a specialized type offers restricted
access to memory regions. We envision a class named <code class="sourceCode cpp">std<span class="op">::</span>RawBuffer<span class="op">&lt;</span>T<span class="op">&gt;</span></code>,
which would record which regions of the buffer have been written
previously, and prohibit reads outside of that region. This class would
have use beyond this profile, making it a more generic solution.</p>
<h1 data-number="6" id="verification-of-constructors"><span class="header-section-number">6</span> Verification of Constructors<a href="#verification-of-constructors" class="self-link"></a></h1>
<p>All constructors of a verified class must satisfy the following
properties:</p>
<ul>
<li>All base classes must be verified classes.</li>
<li>All base classes must be initialized before any of their non-static
data members are read.</li>
<li>All verified data members must be initialized before being
read.</li>
<li>All verified data members must be initialized on all paths.</li>
<li>No data member that is explicitly exempted, or any of its data
members, can be read.</li>
<li>Any use of an object parameter is restricted until all non-static
data members are initialized. When restricted, the object parameter can
only be used for accessing non-static data members.</li>
<li>The constructor may only call constructors of verified classes until
all non-static data members are initialized. Calls to other functions
are prohibited until then.</li>
<li>The return value of function calls may never be assigned to an data
member, either directly or indirectly.</li>
<li>Default initialization is not considered as initializing anything
for the sake of these criteria.</li>
</ul>
<p>A non-static data member is considered read whenever it is present in
the function, except when:</p>
<ul>
<li>It is an unevaluated operand [expr.context]</li>
<li>It is part of a discarded statement [stmt.if]</li>
<li>It is the left operand of an assignment [expr.ass]</li>
<li>It is the receiver object of a constructor invocation</li>
</ul>
<p>This definition implies the following:</p>
<ul>
<li>Obtaining the address of a data members violates this profile.</li>
<li>A verified class’ non-static data members are either verified
classes or PODs. Note that PODs don’t have constructors to call, even
though the syntax used may give that impression.</li>
<li>A nonconforming constructor would bring the rejection of its class
only, and not of its subclasses. This decision is intended to reduce the
noisiness that would come from a faulty constructor at the top of a very
large class hierarchy.</li>
<li>An initialized pointer can point to an uninitialized memory region
(e.g. <code class="sourceCode cpp">buf<span class="op">(</span><span class="kw">new</span> <span class="dt">char</span><span class="op">[</span>BUF_SIZE<span class="op">]))</span></code>)
and be compliant. We discuss this <a href="#explicit-exemptions">above</a>.</li>
<li>The constructor may execute nearly arbritary code after its
non-static data members are intitialized.</li>
</ul>
<p>We restrict function calls after initialization because we want to
keep the analysis intraprocedural. Initialization that occurs in a
member function, or occurs from a function’s return value, would require
either interprocedural analysis. Keeping the analysis intraprocedural
would faciliate adoption.</p>
<p>Examples:</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> <span class="op">[[</span><span class="at">Profiles</span><span class="op">::</span><span class="at">enable</span><span class="op">(</span><span class="at">initialization</span><span class="op">)]]</span> clazz1 <span class="op">{</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>  <span class="dt">int</span> i;</span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a>  <span class="dt">int</span> j;</span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a>  <span class="dt">int</span> z <span class="op">=</span> <span class="dv">0</span>;</span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a>  clazz1<span class="op">()</span> <span class="op">{</span></span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a>      i <span class="op">=</span> <span class="dv">123</span>;</span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a>      <span class="cf">if</span> <span class="op">(</span>nondet<span class="op">)</span> <span class="op">{</span></span>
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true" tabindex="-1"></a>        j <span class="op">=</span> <span class="dv">456</span>;</span>
<span id="cb3-9"><a href="#cb3-9" aria-hidden="true" tabindex="-1"></a>      <span class="op">}</span></span>
<span id="cb3-10"><a href="#cb3-10" aria-hidden="true" tabindex="-1"></a>      <span class="co">//non-compliant: j is not defined on all paths</span></span>
<span id="cb3-11"><a href="#cb3-11" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb3-12"><a href="#cb3-12" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<div class="sourceCode" id="cb4"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> <span class="op">[[</span><span class="at">Profiles</span><span class="op">::</span><span class="at">enable</span><span class="op">(</span><span class="at">initialization</span><span class="op">)]]</span> clazz2 <span class="op">{</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>  <span class="dt">int</span> i;</span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a>  <span class="dt">int</span> j;</span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a>  clazz2<span class="op">()</span> <span class="op">:</span> i<span class="op">(</span>j<span class="op">)</span>, j<span class="op">(</span><span class="dv">42</span><span class="op">)</span> <span class="op">{}</span> <span class="co">//non-compliant: j is read before it is initialized</span></span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<div class="sourceCode" id="cb5"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> <span class="op">[[</span><span class="at">Profiles</span><span class="op">::</span><span class="at">enable</span><span class="op">(</span><span class="at">initialization</span><span class="op">)]]</span> clazz3 <span class="op">{</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>  <span class="dt">int</span> i;</span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a>  <span class="dt">int</span> j;</span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a>  clazz3<span class="op">()</span> <span class="op">{</span> <span class="co">//compliant, but bad form</span></span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a>    <span class="kw">this</span><span class="op">-&gt;</span>i <span class="op">=</span> <span class="dv">0</span>;</span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">this</span><span class="op">-&gt;</span>j <span class="op">=</span> <span class="dv">42</span>;</span>
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb5-8"><a href="#cb5-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<div class="sourceCode" id="cb6"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> pod <span class="op">{</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a>  <span class="dt">int</span> i;</span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a>  <span class="dt">int</span> j;</span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> <span class="op">[[</span><span class="at">Profiles</span><span class="op">::</span><span class="at">enable</span><span class="op">(</span><span class="at">initialization</span><span class="op">)]]</span> clazz4 <span class="op">{</span></span>
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true" tabindex="-1"></a>  pod p;</span>
<span id="cb6-7"><a href="#cb6-7" aria-hidden="true" tabindex="-1"></a>  clazz4<span class="op">()</span> <span class="op">=</span> <span class="cf">default</span>; <span class="co">//non-compliant, p is default initialized</span></span>
<span id="cb6-8"><a href="#cb6-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb6-9"><a href="#cb6-9" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> <span class="op">[[</span><span class="at">Profiles</span><span class="op">::</span><span class="at">enable</span><span class="op">(</span><span class="at">initialization</span><span class="op">)]]</span> clazz5 <span class="op">{</span></span>
<span id="cb6-10"><a href="#cb6-10" aria-hidden="true" tabindex="-1"></a>  pod p<span class="op">{}</span>;</span>
<span id="cb6-11"><a href="#cb6-11" aria-hidden="true" tabindex="-1"></a>  clazz5<span class="op">()</span> <span class="op">=</span> <span class="cf">default</span>; <span class="co">//compliant, p is value-initialized</span></span>
<span id="cb6-12"><a href="#cb6-12" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb6-13"><a href="#cb6-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-14"><a href="#cb6-14" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> <span class="op">[[</span><span class="at">Profiles</span><span class="op">::</span><span class="at">enable</span><span class="op">(</span><span class="at">initialization</span><span class="op">)]]</span> clazz6 <span class="op">{</span></span>
<span id="cb6-15"><a href="#cb6-15" aria-hidden="true" tabindex="-1"></a>  pod podFactory<span class="op">()</span> <span class="op">{</span></span>
<span id="cb6-16"><a href="#cb6-16" aria-hidden="true" tabindex="-1"></a>    pod p;    <span class="co">//p is default-initialized</span></span>
<span id="cb6-17"><a href="#cb6-17" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> p;</span>
<span id="cb6-18"><a href="#cb6-18" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb6-19"><a href="#cb6-19" aria-hidden="true" tabindex="-1"></a>  clazz6<span class="op">()</span> <span class="op">:</span> p<span class="op">(</span>podFactory<span class="op">())</span> <span class="op">{}</span> ; <span class="co">//non-compliant, p initialized from a function&#39;s return value</span></span>
<span id="cb6-20"><a href="#cb6-20" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb7"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> <span class="op">[[</span><span class="at">Profiles</span><span class="op">::</span><span class="at">enable</span><span class="op">(</span><span class="at">initialization</span><span class="op">)]]</span> clazz7 <span class="op">{</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a>  <span class="dt">int</span> i;</span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a>  <span class="dt">int</span> j;</span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a>  clazz7<span class="op">(</span><span class="dt">int</span> i<span class="op">)</span> <span class="op">:</span> i<span class="op">(</span>i<span class="op">)</span>, j<span class="op">()</span> <span class="op">{}</span>; <span class="co">//compliant, j is value-initialized</span></span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<h1 data-number="7" id="templates"><span class="header-section-number">7</span> Templates<a href="#templates" class="self-link"></a></h1>
<p>In the case of templated classes, the property is verified during
template instantiation.</p>
<div class="sourceCode" id="cb8"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> NotAnnotated<span class="op">{</span><span class="co">/**/</span><span class="op">}</span>;</span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> <span class="op">[[</span><span class="at">Profiles</span><span class="op">::</span><span class="at">enable</span><span class="op">(</span><span class="at">initialization</span><span class="op">)]]</span> Annotated <span class="op">{</span><span class="co">/**/</span><span class="op">}</span>;</span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span></span>
<span id="cb8-5"><a href="#cb8-5" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> <span class="op">[[</span><span class="at">Profiles</span><span class="op">::</span><span class="at">enable</span><span class="op">(</span><span class="at">initialization</span><span class="op">)]]</span> AnnotatedTemplate <span class="op">{</span></span>
<span id="cb8-6"><a href="#cb8-6" aria-hidden="true" tabindex="-1"></a>  T field <span class="op">=</span> T<span class="op">()</span>;</span>
<span id="cb8-7"><a href="#cb8-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb8-8"><a href="#cb8-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-9"><a href="#cb8-9" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> foo<span class="op">()</span> <span class="op">{</span></span>
<span id="cb8-10"><a href="#cb8-10" aria-hidden="true" tabindex="-1"></a>  AnnotatedTemplate<span class="op">&lt;</span>NotAnnotated<span class="op">&gt;</span> nat <span class="op">{}</span>; <span class="co">//non-compliant, calling the constructor to a non-verified class</span></span>
<span id="cb8-11"><a href="#cb8-11" aria-hidden="true" tabindex="-1"></a>  AnnotatedTemplate<span class="op">&lt;</span>Annotated<span class="op">&gt;</span>     at <span class="op">{}</span>; <span class="co">//compliant</span></span>
<span id="cb8-12"><a href="#cb8-12" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h1 data-number="8" id="idioms-to-consider"><span class="header-section-number">8</span> Idioms to Consider<a href="#idioms-to-consider" class="self-link"></a></h1>
<h2 data-number="8.1" id="non-constructor-delegating"><span class="header-section-number">8.1</span> Non-Constructor Delegating<a href="#non-constructor-delegating" class="self-link"></a></h2>
<p>A recent SG23 ML discussion highlighted that it is idiomatic in C++
to delegate initialization to a non-constructor method. Supporting this
idiom would make this profile more useful.</p>
<p>The bit of code that triggered the discussion is the following:</p>
<div class="sourceCode" id="cb9"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a>basic_string<span class="op">(</span><span class="kw">const</span> _CharT<span class="op">*</span> __s, <span class="kw">const</span> _Alloc<span class="op">&amp;</span> __a <span class="op">=</span> _Alloc<span class="op">())</span></span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a><span class="op">:</span> _M_dataplus<span class="op">(</span>_M_local_data<span class="op">()</span>, __a<span class="op">)</span></span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a>  <span class="co">//...</span></span>
<span id="cb9-5"><a href="#cb9-5" aria-hidden="true" tabindex="-1"></a>  _M_construct<span class="op">(</span>__s, __end, forward_iterator_tag<span class="op">())</span>;</span>
<span id="cb9-6"><a href="#cb9-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>In this case, <code class="sourceCode cpp">_M_local_data<span class="op">()</span></code>
returns a const pointer to a data member
(<code class="sourceCode cpp">_M_local_buf</code>) and passes it to the
<code class="sourceCode cpp">_M_dataplus</code> data member. The
initialization then is done by
<code class="sourceCode cpp">_M_construct</code>. This code would be
reported as violating the safety profile as we specify it in this draft,
since the constructor does not initialize
<code class="sourceCode cpp">_M_dataplus</code> directly.</p>
<p>There are a few solutions to this problem:</p>
<ol type="1">
<li>Force developers to rewrite their code to use delegating
constructors.</li>
<li>Use an on-demand interprocedural analysis that ensures that
initialization happens on all paths in the callee.</li>
<li>A suggestion was to annotate arguments that must be initialized with
<code class="sourceCode cpp"><span class="op">[[</span><span class="at">must_init</span><span class="op">]]</span></code>.
This option is less intrusive than option 1, but adding another
annotation is undesirable. It nonetheless would be simpler to verify
than option 2, simply because the scope of the analysis becomes
well-bounded. As such, it is worth considering.</li>
</ol>
<p>It would be a good idea to have a straw poll about which of these
options the community considers best suited.</p>
<h1 data-number="9" id="future-work"><span class="header-section-number">9</span> Future Work<a href="#future-work" class="self-link"></a></h1>
<p>The proposed attribute could be misunderstood to mean that all
variables in all the code in the scope of the annotation are properly
initialized. This may be addressed in a future version of this profile,
or in another profile.</p>
<p>We also observe that profiles imply a constraint on what types can be
used in a template. This hints at a new concept. A future revision of
this paper would explore this further.</p>
<h1 data-number="10" id="conclusion"><span class="header-section-number">10</span> Conclusion<a href="#conclusion" class="self-link"></a></h1>
<p>In this paper, we propose a safety profile that guarantees that any
class affected by the profile annotation will have all its data members
initialized, assuming that the data used for construction is itself
initialized properly. The profile does not depend on the presence of
specific modern C++ features and can thus be applied to legacy code
bases.</p>
<h1 data-number="11" id="bibliography"><span class="header-section-number">11</span> References<a href="#bibliography" class="self-link"></a></h1>
<div id="refs" class="references csl-bib-body hanging-indent" data-entry-spacing="1" role="list">
<div id="ref-P2795R5" class="csl-entry" role="listitem">
[P2795R5] Thomas Köppe. 2024-03-22. Erroneous behaviour for
uninitialized reads. <a href="https://wg21.link/p2795r5"><div class="csl-block">https://wg21.link/p2795r5</div></a>
</div>
<div id="ref-P3274R0" class="csl-entry" role="listitem">
[P3274R0] Bjarne Stroustrup. 2024-05-10. A framework for Profiles
development. <a href="https://wg21.link/p3274r0"><div class="csl-block">https://wg21.link/p3274r0</div></a>
</div>
</div>
</div>
</div>
</body>
</html>
