From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-wr1-x431.google.com (mail-wr1-x431.google.com [IPv6:2a00:1450:4864:20::431]) by sourceware.org (Postfix) with ESMTPS id AF54B385840D for ; Wed, 1 Dec 2021 22:24:36 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org AF54B385840D Received: by mail-wr1-x431.google.com with SMTP id d9so34649066wrw.4 for ; Wed, 01 Dec 2021 14:24:36 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:sender:message-id:date:mime-version:user-agent :subject:content-language:to:cc:references:from:in-reply-to :content-transfer-encoding; bh=aP8ufJ9CQFxEJmfdZpZovLBu3Z20FHV8/JMHTViJ4Qg=; b=pr49Pwcxkw5H6j1vJBaMc1ugNEn7DhUNxh8lUMomrn9yEovBMEgPbBWhyNcQYVIzbu kf1pVOWFU6rGnQNEu9f7Q9ZBSIRkq5GJYijMNZ/hXSZJYBWIqgw4pa8+3Kir+XVxxPvg B6mqh3RDoHd6YLSrq9ssQhS/Dz2qfQhBHFYo2XKtBolmJC+OFVLLhiUi1P3drr/1RcGc kLD0qD/MkwH0fLq2N2E/3thyPgiybj+o87FqhmsZ0qR7oRTNcyTCz8DwHNIUwjbwYbUX VFF9/V2/hVkR8MfFprk2JYor/BsfVhVtcBQb3X8Qe3G837H7ZZ+392AsfxBj88B4tLeC 9Lng== X-Gm-Message-State: AOAM53381mQ0rMu/sUTcJqJifRL/dOYLxjGG/SojzhHkewktlYO2caTO IVDVPjwucmC5rols/qcSQUs= X-Google-Smtp-Source: ABdhPJyrelwHCe6ym3KrOAcnjcDshdZ6Eb14ZbyJKwMwukhjr4GIhi8V5XcZUyOZeyTrNgTtoTC/NA== X-Received: by 2002:adf:dd46:: with SMTP id u6mr10408843wrm.280.1638397475547; Wed, 01 Dec 2021 14:24:35 -0800 (PST) Received: from [192.168.0.160] ([170.253.36.171]) by smtp.gmail.com with ESMTPSA id u13sm541416wmq.14.2021.12.01.14.24.34 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Wed, 01 Dec 2021 14:24:35 -0800 (PST) Sender: Alejandro Colomar Message-ID: Date: Wed, 1 Dec 2021 23:24:33 +0100 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Thunderbird/91.3.0 Subject: Re: [cfe-dev] ISO C3X proposal: nonnull qualifier Content-Language: en-US To: Dmitri Gribenko Cc: Joseph Myers , gcc@gcc.gnu.org, cfe-dev References: <56a1a945-608e-0e5e-7610-c35481abb980@gmail.com> <4883fa8c-2d99-2611-a8e2-6c7612283da4@gmail.com> <93576cba-19f8-8cf6-6597-7377bda9647f@gmail.com> From: "Alejandro Colomar (man-pages)" In-Reply-To: Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 7bit X-Spam-Status: No, score=-6.7 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, NICE_REPLY_A, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: gcc@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 01 Dec 2021 22:24:39 -0000 Hi Dmitry, On 11/23/21 13:45, Dmitri Gribenko wrote: >> >> Let's imagine a scenario where C3X specifies that non-qualified pointers >> are nonnull. And there's only a qualifier, _Nullable, to allow NULL. >> Asigning _Nullable to nonnull would issue a diagnostic. > > I think C3X specifying that non-qualified pointers are nonnnull would > be a showstopper, I don't think it is likely to happen given how the > users and the committee value backward compatibility that C has > offered throughout the decades. Agreed. I even found some cases where it would cause previously-correct code to misbehave, so changing normal pointers to mean nonnull pointers is not possible at this point. Compilers may allow that with pragmas anyway. > > If I were to speculate what would happen if C3X did flip the default, > I think it would be treated by the community as a language fork. Yes > Pre-C3X headers won't work correctly when included in C3X programs, > making incremental adoption of C3X syntax, as it was intended to be > used, impossible. Projects would likely invent a NULLABLE macro, which > would expand to _Nullable in C3X and nothing in earlier versions, to > enable an incremental transition. > > That's why Clang introduced the pragma, enabling new rules to be > adopted incrementally. Let's avoid forking C :) > >> Also, do you have any experience in avoiding to diagnose a _Nullable to >> nonnull assignment _after_ explicitly comparing to NULL? I.e., allow >> the following: >> >> int *_Nullable p; >> int *q; >> >> if (!p) >> q = p; > > Internally at Google we have a checker based on the dataflow analysis > framework (https://lists.llvm.org/pipermail/cfe-dev/2021-October/069098.html) > that diagnoses usages of std::optional::value() not guarded by > has_value(). We are planning to upstream it after we finish > upstreaming the dataflow framework itself. Ensuring guarded usage of > std::optional::value() is very similar to diagnosing dereferences > of nullable pointers. I think a lot of the experience is transferable. > However, we haven't attempted to implement a pointer nullability check > yet, so I don't yet understand all corner cases that arise in real > world software. > > However, fundamentally, there are a few questions that you need to answer: > > - does _Nullable create a distinct type or not? It is extremely > important when you consider C++. Let's talk about _Nonnull, which is more likely to be added. I would say no. Neither const or restrict create a new type, but a qualified version of a type. _Nonnull has a behavior somewhat in between restrict and const. > > - do you want nullability-related diagnostics to be mandatory, or > optional? For example, a compiler is not required to issue a > diagnostic about a program that violates the constraints of > `restrict`. I think this should be similar to const, so a mandatory warning would be better. But still I have doubts, because this is much more complex to diagnose than const violations (there should be no diagnostic after an explicit NULL check). > > If _Nullable does not create a distinct type, and `T*` is the same > type as `T* _Nullable`, then we can't rely on the regular type system > mechanisms to issue diagnostics. > > If _Nullable creates a distinct type, then according to regular C type > checking rules, you would get a warning on the `q = p` assignment > regardless of the `if (!p)` check. That's how the C type system works, > it is not flow-sensitive. > > If we want the diagnostics to be fllow-sensitive like in your example > (I think it would be the best choice), then we need to add a new > flow-sensitive component to the C type system. I don't think there is > a precedent for this in C right now. I'm not sure how the committee or > implementors would react to such a proposal. Yes, it's complex. It should be flow-sensitive. Right now there's a precedent, I think: 'restrict'. But there are no mandatory warnings AFAIK. This would go one step further, and would probably be the most complex addition to the language ever. A minimal complying compiler would need to be much more complex than ever, which is a bad thing. Right now I have two voices in my head saying opposite things: on one hand this would add a lot of complexity to the C language, and I don't like that; on the other hand, this would make standard C much more safe than it is regarding pointers, and for the plain user, it would reduce the cognitive complexity of making sure null pointers are not passed where they shouldn't. GCC adding _Nonnull before the standard would be a good first step. Cheers, Alex