Skip to content

Commit ca4c4a6

Browse files
committed
Revert "[clang][nullability] allow _Nonnull etc on nullable class types (#82705)"
This reverts commit 92a09c0. This is triggering a bunch of new -Wnullability-completeness warnings in code with existing raw pointer nullability annotations. The intent was the new nullability locations wouldn't affect those warnings, so this is a bug at least for now.
1 parent a4610c7 commit ca4c4a6

20 files changed

+29
-225
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -204,21 +204,6 @@ Attribute Changes in Clang
204204
and each must be a positive integer when provided. The parameter ``x`` is required, while ``y`` and
205205
``z`` are optional with default value of 1.
206206

207-
- The ``_Nullable`` and ``_Nonnull`` family of type attributes can now apply
208-
to certain C++ class types, such as smart pointers:
209-
``void useObject(std::unique_ptr<Object> _Nonnull obj);``.
210-
211-
This works for standard library types including ``unique_ptr``, ``shared_ptr``,
212-
and ``function``. See
213-
`the attribute reference documentation <https://llvm.org/docs/AttributeReference.html#nullability-attributes>`_
214-
for the full list.
215-
216-
- The ``_Nullable`` attribute can be applied to C++ class declarations:
217-
``template <class T> class _Nullable MySmartPointer {};``.
218-
219-
This allows the ``_Nullable`` and ``_Nonnull`` family of type attributes to
220-
apply to this class.
221-
222207
Improvements to Clang's diagnostics
223208
-----------------------------------
224209
- Clang now applies syntax highlighting to the code snippets it

clang/include/clang/Basic/Attr.td

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2178,10 +2178,9 @@ def TypeNonNull : TypeAttr {
21782178
let Documentation = [TypeNonNullDocs];
21792179
}
21802180

2181-
def TypeNullable : DeclOrTypeAttr {
2181+
def TypeNullable : TypeAttr {
21822182
let Spellings = [CustomKeyword<"_Nullable">];
21832183
let Documentation = [TypeNullableDocs];
2184-
// let Subjects = SubjectList<[CXXRecord], ErrorDiag>;
21852184
}
21862185

21872186
def TypeNullableResult : TypeAttr {

clang/include/clang/Basic/AttrDocs.td

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -4151,20 +4151,6 @@ non-underscored keywords. For example:
41514151
@property (assign, nullable) NSView *superview;
41524152
@property (readonly, nonnull) NSArray *subviews;
41534153
@end
4154-
4155-
As well as built-in pointer types, the nullability attributes can be attached
4156-
to C++ classes marked with the ``_Nullable`` attribute.
4157-
4158-
The following C++ standard library types are considered nullable:
4159-
``unique_ptr``, ``shared_ptr``, ``auto_ptr``, ``exception_ptr``, ``function``,
4160-
``move_only_function`` and ``coroutine_handle``.
4161-
4162-
Types should be marked nullable only where the type itself leaves nullability
4163-
ambiguous. For example, ``std::optional`` is not marked ``_Nullable``, because
4164-
``optional<int> _Nullable`` is redundant and ``optional<int> _Nonnull`` is
4165-
not a useful type. ``std::weak_ptr`` is not nullable, because its nullability
4166-
can change with no visible modification, so static annotation is unlikely to be
4167-
unhelpful.
41684154
}];
41694155
}
41704156

@@ -4199,17 +4185,6 @@ The ``_Nullable`` nullability qualifier indicates that a value of the
41994185
int fetch_or_zero(int * _Nullable ptr);
42004186

42014187
a caller of ``fetch_or_zero`` can provide null.
4202-
4203-
The ``_Nullable`` attribute on classes indicates that the given class can
4204-
represent null values, and so the ``_Nullable``, ``_Nonnull`` etc qualifiers
4205-
make sense for this type. For example:
4206-
4207-
.. code-block:: c
4208-
4209-
class _Nullable ArenaPointer { ... };
4210-
4211-
ArenaPointer _Nonnull x = ...;
4212-
ArenaPointer _Nullable y = nullptr;
42134188
}];
42144189
}
42154190

clang/include/clang/Basic/Features.def

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,6 @@ EXTENSION(define_target_os_macros,
9494
FEATURE(enumerator_attributes, true)
9595
FEATURE(nullability, true)
9696
FEATURE(nullability_on_arrays, true)
97-
FEATURE(nullability_on_classes, true)
9897
FEATURE(nullability_nullable_result, true)
9998
FEATURE(memory_sanitizer,
10099
LangOpts.Sanitize.hasOneOf(SanitizerKind::Memory |

clang/include/clang/Parse/Parser.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3014,7 +3014,6 @@ class Parser : public CodeCompletionHandler {
30143014
void DiagnoseAndSkipExtendedMicrosoftTypeAttributes();
30153015
SourceLocation SkipExtendedMicrosoftTypeAttributes();
30163016
void ParseMicrosoftInheritanceClassAttributes(ParsedAttributes &attrs);
3017-
void ParseNullabilityClassAttributes(ParsedAttributes &attrs);
30183017
void ParseBorlandTypeAttributes(ParsedAttributes &attrs);
30193018
void ParseOpenCLKernelAttributes(ParsedAttributes &attrs);
30203019
void ParseOpenCLQualifiers(ParsedAttributes &Attrs);

clang/include/clang/Sema/Sema.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1655,9 +1655,6 @@ class Sema final {
16551655
/// Add [[gsl::Pointer]] attributes for std:: types.
16561656
void inferGslPointerAttribute(TypedefNameDecl *TD);
16571657

1658-
/// Add _Nullable attributes for std:: types.
1659-
void inferNullableClassAttribute(CXXRecordDecl *CRD);
1660-
16611658
enum PragmaOptionsAlignKind {
16621659
POAK_Native, // #pragma options align=native
16631660
POAK_Natural, // #pragma options align=natural

clang/lib/AST/Type.cpp

Lines changed: 10 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4558,15 +4558,16 @@ bool Type::canHaveNullability(bool ResultIfUnknown) const {
45584558
case Type::Auto:
45594559
return ResultIfUnknown;
45604560

4561-
// Dependent template specializations could instantiate to pointer types.
4561+
// Dependent template specializations can instantiate to pointer
4562+
// types unless they're known to be specializations of a class
4563+
// template.
45624564
case Type::TemplateSpecialization:
4563-
// If it's a known class template, we can already check if it's nullable.
4564-
if (TemplateDecl *templateDecl =
4565-
cast<TemplateSpecializationType>(type.getTypePtr())
4566-
->getTemplateName()
4567-
.getAsTemplateDecl())
4568-
if (auto *CTD = dyn_cast<ClassTemplateDecl>(templateDecl))
4569-
return CTD->getTemplatedDecl()->hasAttr<TypeNullableAttr>();
4565+
if (TemplateDecl *templateDecl
4566+
= cast<TemplateSpecializationType>(type.getTypePtr())
4567+
->getTemplateName().getAsTemplateDecl()) {
4568+
if (isa<ClassTemplateDecl>(templateDecl))
4569+
return false;
4570+
}
45704571
return ResultIfUnknown;
45714572

45724573
case Type::Builtin:
@@ -4623,17 +4624,6 @@ bool Type::canHaveNullability(bool ResultIfUnknown) const {
46234624
}
46244625
llvm_unreachable("unknown builtin type");
46254626

4626-
case Type::Record: {
4627-
const RecordDecl *RD = cast<RecordType>(type)->getDecl();
4628-
// For template specializations, look only at primary template attributes.
4629-
// This is a consistent regardless of whether the instantiation is known.
4630-
if (const auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(RD))
4631-
return CTSD->getSpecializedTemplate()
4632-
->getTemplatedDecl()
4633-
->hasAttr<TypeNullableAttr>();
4634-
return RD->hasAttr<TypeNullableAttr>();
4635-
}
4636-
46374627
// Non-pointer types.
46384628
case Type::Complex:
46394629
case Type::LValueReference:
@@ -4651,6 +4641,7 @@ bool Type::canHaveNullability(bool ResultIfUnknown) const {
46514641
case Type::DependentAddressSpace:
46524642
case Type::FunctionProto:
46534643
case Type::FunctionNoProto:
4644+
case Type::Record:
46544645
case Type::DeducedTemplateSpecialization:
46554646
case Type::Enum:
46564647
case Type::InjectedClassName:

clang/lib/CodeGen/CGCall.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4372,8 +4372,7 @@ void CodeGenFunction::EmitNonNullArgCheck(RValue RV, QualType ArgType,
43724372
NNAttr = getNonNullAttr(AC.getDecl(), PVD, ArgType, ArgNo);
43734373

43744374
bool CanCheckNullability = false;
4375-
if (SanOpts.has(SanitizerKind::NullabilityArg) && !NNAttr && PVD &&
4376-
!PVD->getType()->isRecordType()) {
4375+
if (SanOpts.has(SanitizerKind::NullabilityArg) && !NNAttr && PVD) {
43774376
auto Nullability = PVD->getType()->getNullability();
43784377
CanCheckNullability = Nullability &&
43794378
*Nullability == NullabilityKind::NonNull &&

clang/lib/CodeGen/CodeGenFunction.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -979,8 +979,7 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy,
979979
// return value. Initialize the flag to 'true' and refine it in EmitParmDecl.
980980
if (SanOpts.has(SanitizerKind::NullabilityReturn)) {
981981
auto Nullability = FnRetTy->getNullability();
982-
if (Nullability && *Nullability == NullabilityKind::NonNull &&
983-
!FnRetTy->isRecordType()) {
982+
if (Nullability && *Nullability == NullabilityKind::NonNull) {
984983
if (!(SanOpts.has(SanitizerKind::ReturnsNonnullAttribute) &&
985984
CurCodeDecl && CurCodeDecl->getAttr<ReturnsNonNullAttr>()))
986985
RetValNullabilityPrecondition =

clang/lib/Parse/ParseDeclCXX.cpp

Lines changed: 9 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1494,15 +1494,6 @@ void Parser::ParseMicrosoftInheritanceClassAttributes(ParsedAttributes &attrs) {
14941494
}
14951495
}
14961496

1497-
void Parser::ParseNullabilityClassAttributes(ParsedAttributes &attrs) {
1498-
while (Tok.is(tok::kw__Nullable)) {
1499-
IdentifierInfo *AttrName = Tok.getIdentifierInfo();
1500-
auto Kind = Tok.getKind();
1501-
SourceLocation AttrNameLoc = ConsumeToken();
1502-
attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0, Kind);
1503-
}
1504-
}
1505-
15061497
/// Determine whether the following tokens are valid after a type-specifier
15071498
/// which could be a standalone declaration. This will conservatively return
15081499
/// true if there's any doubt, and is appropriate for insert-';' fixits.
@@ -1684,21 +1675,15 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
16841675

16851676
ParsedAttributes attrs(AttrFactory);
16861677
// If attributes exist after tag, parse them.
1687-
for (;;) {
1688-
MaybeParseAttributes(PAKM_CXX11 | PAKM_Declspec | PAKM_GNU, attrs);
1689-
// Parse inheritance specifiers.
1690-
if (Tok.isOneOf(tok::kw___single_inheritance,
1691-
tok::kw___multiple_inheritance,
1692-
tok::kw___virtual_inheritance)) {
1693-
ParseMicrosoftInheritanceClassAttributes(attrs);
1694-
continue;
1695-
}
1696-
if (Tok.is(tok::kw__Nullable)) {
1697-
ParseNullabilityClassAttributes(attrs);
1698-
continue;
1699-
}
1700-
break;
1701-
}
1678+
MaybeParseAttributes(PAKM_CXX11 | PAKM_Declspec | PAKM_GNU, attrs);
1679+
1680+
// Parse inheritance specifiers.
1681+
if (Tok.isOneOf(tok::kw___single_inheritance, tok::kw___multiple_inheritance,
1682+
tok::kw___virtual_inheritance))
1683+
ParseMicrosoftInheritanceClassAttributes(attrs);
1684+
1685+
// Allow attributes to precede or succeed the inheritance specifiers.
1686+
MaybeParseAttributes(PAKM_CXX11 | PAKM_Declspec | PAKM_GNU, attrs);
17021687

17031688
// Source location used by FIXIT to insert misplaced
17041689
// C++11 attributes

clang/lib/Sema/SemaAttr.cpp

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -215,18 +215,6 @@ void Sema::inferGslOwnerPointerAttribute(CXXRecordDecl *Record) {
215215
inferGslPointerAttribute(Record, Record);
216216
}
217217

218-
void Sema::inferNullableClassAttribute(CXXRecordDecl *CRD) {
219-
static llvm::StringSet<> Nullable{
220-
"auto_ptr", "shared_ptr", "unique_ptr", "exception_ptr",
221-
"coroutine_handle", "function", "move_only_function",
222-
};
223-
224-
if (CRD->isInStdNamespace() && Nullable.count(CRD->getName()) &&
225-
!CRD->hasAttr<TypeNullableAttr>())
226-
for (Decl *Redecl : CRD->redecls())
227-
Redecl->addAttr(TypeNullableAttr::CreateImplicit(Context));
228-
}
229-
230218
void Sema::ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind,
231219
SourceLocation PragmaLoc) {
232220
PragmaMsStackAction Action = Sema::PSK_Reset;

clang/lib/Sema/SemaChecking.cpp

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727
#include "clang/AST/ExprObjC.h"
2828
#include "clang/AST/ExprOpenMP.h"
2929
#include "clang/AST/FormatString.h"
30-
#include "clang/AST/IgnoreExpr.h"
3130
#include "clang/AST/NSAPI.h"
3231
#include "clang/AST/NonTrivialTypeVisitor.h"
3332
#include "clang/AST/OperationKinds.h"
@@ -7358,14 +7357,6 @@ bool Sema::getFormatStringInfo(const FormatAttr *Format, bool IsCXXMember,
73587357
///
73597358
/// Returns true if the value evaluates to null.
73607359
static bool CheckNonNullExpr(Sema &S, const Expr *Expr) {
7361-
// Treat (smart) pointers constructed from nullptr as null, whether we can
7362-
// const-evaluate them or not.
7363-
// This must happen first: the smart pointer expr might have _Nonnull type!
7364-
if (isa<CXXNullPtrLiteralExpr>(
7365-
IgnoreExprNodes(Expr, IgnoreImplicitAsWrittenSingleStep,
7366-
IgnoreElidableImplicitConstructorSingleStep)))
7367-
return true;
7368-
73697360
// If the expression has non-null type, it doesn't evaluate to null.
73707361
if (auto nullability = Expr->IgnoreImplicit()->getType()->getNullability()) {
73717362
if (*nullability == NullabilityKind::NonNull)

clang/lib/Sema/SemaDecl.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18254,10 +18254,8 @@ Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc,
1825418254
if (PrevDecl)
1825518255
mergeDeclAttributes(New, PrevDecl);
1825618256

18257-
if (auto *CXXRD = dyn_cast<CXXRecordDecl>(New)) {
18257+
if (auto *CXXRD = dyn_cast<CXXRecordDecl>(New))
1825818258
inferGslOwnerPointerAttribute(CXXRD);
18259-
inferNullableClassAttribute(CXXRD);
18260-
}
1826118259

1826218260
// If there's a #pragma GCC visibility in scope, set the visibility of this
1826318261
// record.

clang/lib/Sema/SemaDeclAttr.cpp

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5976,20 +5976,6 @@ static void handleBuiltinAliasAttr(Sema &S, Decl *D,
59765976
D->addAttr(::new (S.Context) BuiltinAliasAttr(S.Context, AL, Ident));
59775977
}
59785978

5979-
static void handleNullableTypeAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
5980-
if (AL.isUsedAsTypeAttr())
5981-
return;
5982-
5983-
if (auto *CRD = dyn_cast<CXXRecordDecl>(D);
5984-
!CRD || !(CRD->isClass() || CRD->isStruct())) {
5985-
S.Diag(AL.getRange().getBegin(), diag::err_attribute_wrong_decl_type_str)
5986-
<< AL << AL.isRegularKeywordAttribute() << "classes";
5987-
return;
5988-
}
5989-
5990-
handleSimpleAttribute<TypeNullableAttr>(S, D, AL);
5991-
}
5992-
59935979
static void handlePreferredTypeAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
59945980
if (!AL.hasParsedType()) {
59955981
S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1;
@@ -9959,10 +9945,6 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL,
99599945
case ParsedAttr::AT_UsingIfExists:
99609946
handleSimpleAttribute<UsingIfExistsAttr>(S, D, AL);
99619947
break;
9962-
9963-
case ParsedAttr::AT_TypeNullable:
9964-
handleNullableTypeAttr(S, D, AL);
9965-
break;
99669948
}
99679949
}
99689950

clang/lib/Sema/SemaInit.cpp

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7075,11 +7075,6 @@ PerformConstructorInitialization(Sema &S,
70757075
hasCopyOrMoveCtorParam(S.Context,
70767076
getConstructorInfo(Step.Function.FoundDecl));
70777077

7078-
// A smart pointer constructed from a nullable pointer is nullable.
7079-
if (NumArgs == 1 && !Kind.isExplicitCast())
7080-
S.diagnoseNullableToNonnullConversion(
7081-
Entity.getType(), Args.front()->getType(), Kind.getLocation());
7082-
70837078
// Determine the arguments required to actually perform the constructor
70847079
// call.
70857080
if (S.CompleteConstructorCall(Constructor, Step.Type, Args, Loc,

clang/lib/Sema/SemaOverload.cpp

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14797,13 +14797,6 @@ ExprResult Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
1479714797
}
1479814798
}
1479914799

14800-
// Check for nonnull = nullable.
14801-
// This won't be caught in the arg's initialization: the parameter to
14802-
// the assignment operator is not marked nonnull.
14803-
if (Op == OO_Equal)
14804-
diagnoseNullableToNonnullConversion(Args[0]->getType(),
14805-
Args[1]->getType(), OpLoc);
14806-
1480714800
// Convert the arguments.
1480814801
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FnDecl)) {
1480914802
// Best->Access is only meaningful for class members.

clang/lib/Sema/SemaTemplate.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2171,7 +2171,6 @@ DeclResult Sema::CheckClassTemplate(
21712171

21722172
AddPushedVisibilityAttribute(NewClass);
21732173
inferGslOwnerPointerAttribute(NewClass);
2174-
inferNullableClassAttribute(NewClass);
21752174

21762175
if (TUK != TUK_Friend) {
21772176
// Per C++ [basic.scope.temp]p2, skip the template parameter scopes.

clang/lib/Sema/SemaType.cpp

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4711,18 +4711,6 @@ static bool DiagnoseMultipleAddrSpaceAttributes(Sema &S, LangAS ASOld,
47114711
return false;
47124712
}
47134713

4714-
// Whether this is a type broadly expected to have nullability attached.
4715-
// These types are affected by `#pragma assume_nonnull`, and missing nullability
4716-
// will be diagnosed with -Wnullability-completeness.
4717-
static bool shouldHaveNullability(QualType T) {
4718-
return T->canHaveNullability(/*ResultIfUnknown=*/false) &&
4719-
// For now, do not infer/require nullability on C++ smart pointers.
4720-
// It's unclear whether the pragma's behavior is useful for C++.
4721-
// e.g. treating type-aliases and template-type-parameters differently
4722-
// from types of declarations can be surprising.
4723-
!isa<RecordType>(T);
4724-
}
4725-
47264714
static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
47274715
QualType declSpecType,
47284716
TypeSourceInfo *TInfo) {
@@ -4841,7 +4829,8 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
48414829
// inner pointers.
48424830
complainAboutMissingNullability = CAMN_InnerPointers;
48434831

4844-
if (shouldHaveNullability(T) && !T->getNullability()) {
4832+
if (T->canHaveNullability(/*ResultIfUnknown*/ false) &&
4833+
!T->getNullability()) {
48454834
// Note that we allow but don't require nullability on dependent types.
48464835
++NumPointersRemaining;
48474836
}
@@ -5064,7 +5053,8 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
50645053
// If the type itself could have nullability but does not, infer pointer
50655054
// nullability and perform consistency checking.
50665055
if (S.CodeSynthesisContexts.empty()) {
5067-
if (shouldHaveNullability(T) && !T->getNullability()) {
5056+
if (T->canHaveNullability(/*ResultIfUnknown*/ false) &&
5057+
!T->getNullability()) {
50685058
if (isVaList(T)) {
50695059
// Record that we've seen a pointer, but do nothing else.
50705060
if (NumPointersRemaining > 0)

clang/test/Sema/nullability.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -248,5 +248,3 @@ void arraysInBlocks(void) {
248248
void (^withTypedefBad)(INTS _Nonnull [2]) = // expected-error {{nullability specifier '_Nonnull' cannot be applied to non-pointer type 'INTS' (aka 'int[4]')}}
249249
^(INTS _Nonnull x[2]) {}; // expected-error {{nullability specifier '_Nonnull' cannot be applied to non-pointer type 'INTS' (aka 'int[4]')}}
250250
}
251-
252-
struct _Nullable NotCplusplusClass {}; // expected-error {{'_Nullable' attribute only applies to classes}}

0 commit comments

Comments
 (0)