Author: Sam McCall Date: 2024-03-15T21:55:37+01:00 New Revision: ca4c4a6758d184f209cb5d88ef42ecc011b11642
URL: https://github.com/llvm/llvm-project/commit/ca4c4a6758d184f209cb5d88ef42ecc011b11642 DIFF: https://github.com/llvm/llvm-project/commit/ca4c4a6758d184f209cb5d88ef42ecc011b11642.diff LOG: Revert "[clang][nullability] allow _Nonnull etc on nullable class types (#82705)" This reverts commit 92a09c0165b87032e1bd05020a78ed845cf35661. 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. Added: Modified: clang/docs/ReleaseNotes.rst clang/include/clang/Basic/Attr.td clang/include/clang/Basic/AttrDocs.td clang/include/clang/Basic/Features.def clang/include/clang/Parse/Parser.h clang/include/clang/Sema/Sema.h clang/lib/AST/Type.cpp clang/lib/CodeGen/CGCall.cpp clang/lib/CodeGen/CodeGenFunction.cpp clang/lib/Parse/ParseDeclCXX.cpp clang/lib/Sema/SemaAttr.cpp clang/lib/Sema/SemaChecking.cpp clang/lib/Sema/SemaDecl.cpp clang/lib/Sema/SemaDeclAttr.cpp clang/lib/Sema/SemaInit.cpp clang/lib/Sema/SemaOverload.cpp clang/lib/Sema/SemaTemplate.cpp clang/lib/Sema/SemaType.cpp clang/test/Sema/nullability.c clang/test/SemaCXX/nullability.cpp Removed: ################################################################################ diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index e1743368b157e0..623a4b3c18bb1a 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -204,21 +204,6 @@ Attribute Changes in Clang and each must be a positive integer when provided. The parameter ``x`` is required, while ``y`` and ``z`` are optional with default value of 1. -- The ``_Nullable`` and ``_Nonnull`` family of type attributes can now apply - to certain C++ class types, such as smart pointers: - ``void useObject(std::unique_ptr<Object> _Nonnull obj);``. - - This works for standard library types including ``unique_ptr``, ``shared_ptr``, - and ``function``. See - `the attribute reference documentation <https://llvm.org/docs/AttributeReference.html#nullability-attributes>`_ - for the full list. - -- The ``_Nullable`` attribute can be applied to C++ class declarations: - ``template <class T> class _Nullable MySmartPointer {};``. - - This allows the ``_Nullable`` and ``_Nonnull`` family of type attributes to - apply to this class. - Improvements to Clang's diagnostics ----------------------------------- - Clang now applies syntax highlighting to the code snippets it diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index 24bc06476b1f9c..67d87eca16ede8 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -2178,10 +2178,9 @@ def TypeNonNull : TypeAttr { let Documentation = [TypeNonNullDocs]; } -def TypeNullable : DeclOrTypeAttr { +def TypeNullable : TypeAttr { let Spellings = [CustomKeyword<"_Nullable">]; let Documentation = [TypeNullableDocs]; -// let Subjects = SubjectList<[CXXRecord], ErrorDiag>; } def TypeNullableResult : TypeAttr { diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index 075324a213ff78..d61f96ade557d5 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -4151,20 +4151,6 @@ non-underscored keywords. For example: @property (assign, nullable) NSView *superview; @property (readonly, nonnull) NSArray *subviews; @end - -As well as built-in pointer types, the nullability attributes can be attached -to C++ classes marked with the ``_Nullable`` attribute. - -The following C++ standard library types are considered nullable: -``unique_ptr``, ``shared_ptr``, ``auto_ptr``, ``exception_ptr``, ``function``, -``move_only_function`` and ``coroutine_handle``. - -Types should be marked nullable only where the type itself leaves nullability -ambiguous. For example, ``std::optional`` is not marked ``_Nullable``, because -``optional<int> _Nullable`` is redundant and ``optional<int> _Nonnull`` is -not a useful type. ``std::weak_ptr`` is not nullable, because its nullability -can change with no visible modification, so static annotation is unlikely to be -unhelpful. }]; } @@ -4199,17 +4185,6 @@ The ``_Nullable`` nullability qualifier indicates that a value of the int fetch_or_zero(int * _Nullable ptr); a caller of ``fetch_or_zero`` can provide null. - -The ``_Nullable`` attribute on classes indicates that the given class can -represent null values, and so the ``_Nullable``, ``_Nonnull`` etc qualifiers -make sense for this type. For example: - - .. code-block:: c - - class _Nullable ArenaPointer { ... }; - - ArenaPointer _Nonnull x = ...; - ArenaPointer _Nullable y = nullptr; }]; } diff --git a/clang/include/clang/Basic/Features.def b/clang/include/clang/Basic/Features.def index 7c0755b7318306..5fad5fc3623cb6 100644 --- a/clang/include/clang/Basic/Features.def +++ b/clang/include/clang/Basic/Features.def @@ -94,7 +94,6 @@ EXTENSION(define_target_os_macros, FEATURE(enumerator_attributes, true) FEATURE(nullability, true) FEATURE(nullability_on_arrays, true) -FEATURE(nullability_on_classes, true) FEATURE(nullability_nullable_result, true) FEATURE(memory_sanitizer, LangOpts.Sanitize.hasOneOf(SanitizerKind::Memory | diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index 14df75180ef321..64e031d5094c74 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -3014,7 +3014,6 @@ class Parser : public CodeCompletionHandler { void DiagnoseAndSkipExtendedMicrosoftTypeAttributes(); SourceLocation SkipExtendedMicrosoftTypeAttributes(); void ParseMicrosoftInheritanceClassAttributes(ParsedAttributes &attrs); - void ParseNullabilityClassAttributes(ParsedAttributes &attrs); void ParseBorlandTypeAttributes(ParsedAttributes &attrs); void ParseOpenCLKernelAttributes(ParsedAttributes &attrs); void ParseOpenCLQualifiers(ParsedAttributes &Attrs); diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 64de39acc72176..69d5709e5e2f06 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -1655,9 +1655,6 @@ class Sema final { /// Add [[gsl::Pointer]] attributes for std:: types. void inferGslPointerAttribute(TypedefNameDecl *TD); - /// Add _Nullable attributes for std:: types. - void inferNullableClassAttribute(CXXRecordDecl *CRD); - enum PragmaOptionsAlignKind { POAK_Native, // #pragma options align=native POAK_Natural, // #pragma options align=natural diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index f7730bc776b373..22666184c56ccf 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -4558,15 +4558,16 @@ bool Type::canHaveNullability(bool ResultIfUnknown) const { case Type::Auto: return ResultIfUnknown; - // Dependent template specializations could instantiate to pointer types. + // Dependent template specializations can instantiate to pointer + // types unless they're known to be specializations of a class + // template. case Type::TemplateSpecialization: - // If it's a known class template, we can already check if it's nullable. - if (TemplateDecl *templateDecl = - cast<TemplateSpecializationType>(type.getTypePtr()) - ->getTemplateName() - .getAsTemplateDecl()) - if (auto *CTD = dyn_cast<ClassTemplateDecl>(templateDecl)) - return CTD->getTemplatedDecl()->hasAttr<TypeNullableAttr>(); + if (TemplateDecl *templateDecl + = cast<TemplateSpecializationType>(type.getTypePtr()) + ->getTemplateName().getAsTemplateDecl()) { + if (isa<ClassTemplateDecl>(templateDecl)) + return false; + } return ResultIfUnknown; case Type::Builtin: @@ -4623,17 +4624,6 @@ bool Type::canHaveNullability(bool ResultIfUnknown) const { } llvm_unreachable("unknown builtin type"); - case Type::Record: { - const RecordDecl *RD = cast<RecordType>(type)->getDecl(); - // For template specializations, look only at primary template attributes. - // This is a consistent regardless of whether the instantiation is known. - if (const auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(RD)) - return CTSD->getSpecializedTemplate() - ->getTemplatedDecl() - ->hasAttr<TypeNullableAttr>(); - return RD->hasAttr<TypeNullableAttr>(); - } - // Non-pointer types. case Type::Complex: case Type::LValueReference: @@ -4651,6 +4641,7 @@ bool Type::canHaveNullability(bool ResultIfUnknown) const { case Type::DependentAddressSpace: case Type::FunctionProto: case Type::FunctionNoProto: + case Type::Record: case Type::DeducedTemplateSpecialization: case Type::Enum: case Type::InjectedClassName: diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index 17607fe500413d..a28d7888715d85 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -4372,8 +4372,7 @@ void CodeGenFunction::EmitNonNullArgCheck(RValue RV, QualType ArgType, NNAttr = getNonNullAttr(AC.getDecl(), PVD, ArgType, ArgNo); bool CanCheckNullability = false; - if (SanOpts.has(SanitizerKind::NullabilityArg) && !NNAttr && PVD && - !PVD->getType()->isRecordType()) { + if (SanOpts.has(SanitizerKind::NullabilityArg) && !NNAttr && PVD) { auto Nullability = PVD->getType()->getNullability(); CanCheckNullability = Nullability && *Nullability == NullabilityKind::NonNull && diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index 8e4dc8915602fa..4a3ff49b0007a3 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -979,8 +979,7 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy, // return value. Initialize the flag to 'true' and refine it in EmitParmDecl. if (SanOpts.has(SanitizerKind::NullabilityReturn)) { auto Nullability = FnRetTy->getNullability(); - if (Nullability && *Nullability == NullabilityKind::NonNull && - !FnRetTy->isRecordType()) { + if (Nullability && *Nullability == NullabilityKind::NonNull) { if (!(SanOpts.has(SanitizerKind::ReturnsNonnullAttribute) && CurCodeDecl && CurCodeDecl->getAttr<ReturnsNonNullAttr>())) RetValNullabilityPrecondition = diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index b23f9ba1bfd460..77d2382ea6d907 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -1494,15 +1494,6 @@ void Parser::ParseMicrosoftInheritanceClassAttributes(ParsedAttributes &attrs) { } } -void Parser::ParseNullabilityClassAttributes(ParsedAttributes &attrs) { - while (Tok.is(tok::kw__Nullable)) { - IdentifierInfo *AttrName = Tok.getIdentifierInfo(); - auto Kind = Tok.getKind(); - SourceLocation AttrNameLoc = ConsumeToken(); - attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0, Kind); - } -} - /// Determine whether the following tokens are valid after a type-specifier /// which could be a standalone declaration. This will conservatively return /// true if there's any doubt, and is appropriate for insert-';' fixits. @@ -1684,21 +1675,15 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, ParsedAttributes attrs(AttrFactory); // If attributes exist after tag, parse them. - for (;;) { - MaybeParseAttributes(PAKM_CXX11 | PAKM_Declspec | PAKM_GNU, attrs); - // Parse inheritance specifiers. - if (Tok.isOneOf(tok::kw___single_inheritance, - tok::kw___multiple_inheritance, - tok::kw___virtual_inheritance)) { - ParseMicrosoftInheritanceClassAttributes(attrs); - continue; - } - if (Tok.is(tok::kw__Nullable)) { - ParseNullabilityClassAttributes(attrs); - continue; - } - break; - } + MaybeParseAttributes(PAKM_CXX11 | PAKM_Declspec | PAKM_GNU, attrs); + + // Parse inheritance specifiers. + if (Tok.isOneOf(tok::kw___single_inheritance, tok::kw___multiple_inheritance, + tok::kw___virtual_inheritance)) + ParseMicrosoftInheritanceClassAttributes(attrs); + + // Allow attributes to precede or succeed the inheritance specifiers. + MaybeParseAttributes(PAKM_CXX11 | PAKM_Declspec | PAKM_GNU, attrs); // Source location used by FIXIT to insert misplaced // C++11 attributes diff --git a/clang/lib/Sema/SemaAttr.cpp b/clang/lib/Sema/SemaAttr.cpp index a5dd158808f26b..0dcf42e4899713 100644 --- a/clang/lib/Sema/SemaAttr.cpp +++ b/clang/lib/Sema/SemaAttr.cpp @@ -215,18 +215,6 @@ void Sema::inferGslOwnerPointerAttribute(CXXRecordDecl *Record) { inferGslPointerAttribute(Record, Record); } -void Sema::inferNullableClassAttribute(CXXRecordDecl *CRD) { - static llvm::StringSet<> Nullable{ - "auto_ptr", "shared_ptr", "unique_ptr", "exception_ptr", - "coroutine_handle", "function", "move_only_function", - }; - - if (CRD->isInStdNamespace() && Nullable.count(CRD->getName()) && - !CRD->hasAttr<TypeNullableAttr>()) - for (Decl *Redecl : CRD->redecls()) - Redecl->addAttr(TypeNullableAttr::CreateImplicit(Context)); -} - void Sema::ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind, SourceLocation PragmaLoc) { PragmaMsStackAction Action = Sema::PSK_Reset; diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index d88a38eb6eb97b..290afd930e796d 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -27,7 +27,6 @@ #include "clang/AST/ExprObjC.h" #include "clang/AST/ExprOpenMP.h" #include "clang/AST/FormatString.h" -#include "clang/AST/IgnoreExpr.h" #include "clang/AST/NSAPI.h" #include "clang/AST/NonTrivialTypeVisitor.h" #include "clang/AST/OperationKinds.h" @@ -7358,14 +7357,6 @@ bool Sema::getFormatStringInfo(const FormatAttr *Format, bool IsCXXMember, /// /// Returns true if the value evaluates to null. static bool CheckNonNullExpr(Sema &S, const Expr *Expr) { - // Treat (smart) pointers constructed from nullptr as null, whether we can - // const-evaluate them or not. - // This must happen first: the smart pointer expr might have _Nonnull type! - if (isa<CXXNullPtrLiteralExpr>( - IgnoreExprNodes(Expr, IgnoreImplicitAsWrittenSingleStep, - IgnoreElidableImplicitConstructorSingleStep))) - return true; - // If the expression has non-null type, it doesn't evaluate to null. if (auto nullability = Expr->IgnoreImplicit()->getType()->getNullability()) { if (*nullability == NullabilityKind::NonNull) diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 7acce77458a372..5850cd0ab6b9aa 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -18254,10 +18254,8 @@ Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc, if (PrevDecl) mergeDeclAttributes(New, PrevDecl); - if (auto *CXXRD = dyn_cast<CXXRecordDecl>(New)) { + if (auto *CXXRD = dyn_cast<CXXRecordDecl>(New)) inferGslOwnerPointerAttribute(CXXRD); - inferNullableClassAttribute(CXXRD); - } // If there's a #pragma GCC visibility in scope, set the visibility of this // record. diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 47e1d9debac3f4..ec00fdf3f88d9e 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -5976,20 +5976,6 @@ static void handleBuiltinAliasAttr(Sema &S, Decl *D, D->addAttr(::new (S.Context) BuiltinAliasAttr(S.Context, AL, Ident)); } -static void handleNullableTypeAttr(Sema &S, Decl *D, const ParsedAttr &AL) { - if (AL.isUsedAsTypeAttr()) - return; - - if (auto *CRD = dyn_cast<CXXRecordDecl>(D); - !CRD || !(CRD->isClass() || CRD->isStruct())) { - S.Diag(AL.getRange().getBegin(), diag::err_attribute_wrong_decl_type_str) - << AL << AL.isRegularKeywordAttribute() << "classes"; - return; - } - - handleSimpleAttribute<TypeNullableAttr>(S, D, AL); -} - static void handlePreferredTypeAttr(Sema &S, Decl *D, const ParsedAttr &AL) { if (!AL.hasParsedType()) { 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, case ParsedAttr::AT_UsingIfExists: handleSimpleAttribute<UsingIfExistsAttr>(S, D, AL); break; - - case ParsedAttr::AT_TypeNullable: - handleNullableTypeAttr(S, D, AL); - break; } } diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index 96029072257d1c..aa470adb30b47f 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -7075,11 +7075,6 @@ PerformConstructorInitialization(Sema &S, hasCopyOrMoveCtorParam(S.Context, getConstructorInfo(Step.Function.FoundDecl)); - // A smart pointer constructed from a nullable pointer is nullable. - if (NumArgs == 1 && !Kind.isExplicitCast()) - S.diagnoseNullableToNonnullConversion( - Entity.getType(), Args.front()->getType(), Kind.getLocation()); - // Determine the arguments required to actually perform the constructor // call. if (S.CompleteConstructorCall(Constructor, Step.Type, Args, Loc, diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 4e03c3124e39ab..f6bd85bdc64692 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -14797,13 +14797,6 @@ ExprResult Sema::CreateOverloadedBinOp(SourceLocation OpLoc, } } - // Check for nonnull = nullable. - // This won't be caught in the arg's initialization: the parameter to - // the assignment operator is not marked nonnull. - if (Op == OO_Equal) - diagnoseNullableToNonnullConversion(Args[0]->getType(), - Args[1]->getType(), OpLoc); - // Convert the arguments. if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FnDecl)) { // Best->Access is only meaningful for class members. diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 8bc7f5f3607338..005529a53270c3 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -2171,7 +2171,6 @@ DeclResult Sema::CheckClassTemplate( AddPushedVisibilityAttribute(NewClass); inferGslOwnerPointerAttribute(NewClass); - inferNullableClassAttribute(NewClass); if (TUK != TUK_Friend) { // Per C++ [basic.scope.temp]p2, skip the template parameter scopes. diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index 81d69fff24f4e7..9aaacaa0771f2f 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -4711,18 +4711,6 @@ static bool DiagnoseMultipleAddrSpaceAttributes(Sema &S, LangAS ASOld, return false; } -// Whether this is a type broadly expected to have nullability attached. -// These types are affected by `#pragma assume_nonnull`, and missing nullability -// will be diagnosed with -Wnullability-completeness. -static bool shouldHaveNullability(QualType T) { - return T->canHaveNullability(/*ResultIfUnknown=*/false) && - // For now, do not infer/require nullability on C++ smart pointers. - // It's unclear whether the pragma's behavior is useful for C++. - // e.g. treating type-aliases and template-type-parameters diff erently - // from types of declarations can be surprising. - !isa<RecordType>(T); -} - static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, QualType declSpecType, TypeSourceInfo *TInfo) { @@ -4841,7 +4829,8 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, // inner pointers. complainAboutMissingNullability = CAMN_InnerPointers; - if (shouldHaveNullability(T) && !T->getNullability()) { + if (T->canHaveNullability(/*ResultIfUnknown*/ false) && + !T->getNullability()) { // Note that we allow but don't require nullability on dependent types. ++NumPointersRemaining; } @@ -5064,7 +5053,8 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, // If the type itself could have nullability but does not, infer pointer // nullability and perform consistency checking. if (S.CodeSynthesisContexts.empty()) { - if (shouldHaveNullability(T) && !T->getNullability()) { + if (T->canHaveNullability(/*ResultIfUnknown*/ false) && + !T->getNullability()) { if (isVaList(T)) { // Record that we've seen a pointer, but do nothing else. if (NumPointersRemaining > 0) diff --git a/clang/test/Sema/nullability.c b/clang/test/Sema/nullability.c index 0401516233b6db..7d193bea46771f 100644 --- a/clang/test/Sema/nullability.c +++ b/clang/test/Sema/nullability.c @@ -248,5 +248,3 @@ void arraysInBlocks(void) { void (^withTypedefBad)(INTS _Nonnull [2]) = // expected-error {{nullability specifier '_Nonnull' cannot be applied to non-pointer type 'INTS' (aka 'int[4]')}} ^(INTS _Nonnull x[2]) {}; // expected-error {{nullability specifier '_Nonnull' cannot be applied to non-pointer type 'INTS' (aka 'int[4]')}} } - -struct _Nullable NotCplusplusClass {}; // expected-error {{'_Nullable' attribute only applies to classes}} diff --git a/clang/test/SemaCXX/nullability.cpp b/clang/test/SemaCXX/nullability.cpp index d52ba4efaccdbd..8d0c4dc195a6bd 100644 --- a/clang/test/SemaCXX/nullability.cpp +++ b/clang/test/SemaCXX/nullability.cpp @@ -4,10 +4,6 @@ #else # error nullability feature should be defined #endif -#if __has_feature(nullability_on_classes) -#else -# error smart-pointer feature should be defined -#endif #include "nullability-completeness.h" @@ -31,7 +27,6 @@ template<typename T> struct AddNonNull { typedef _Nonnull T type; // expected-error{{nullability specifier '_Nonnull' cannot be applied to non-pointer type 'int'}} // expected-error@-1{{nullability specifier '_Nonnull' cannot be applied to non-pointer type 'std::nullptr_t'}} - // expected-error@-2{{nullability specifier '_Nonnull' cannot be applied to non-pointer type 'NotPtr'}} }; typedef AddNonNull<int *>::type nonnull_int_ptr_1; @@ -40,33 +35,6 @@ typedef AddNonNull<nullptr_t>::type nonnull_int_ptr_3; // expected-note{{in inst typedef AddNonNull<int>::type nonnull_non_pointer_1; // expected-note{{in instantiation of template class 'AddNonNull<int>' requested here}} -// Nullability on C++ class types (smart pointers). -struct NotPtr{}; -typedef AddNonNull<NotPtr>::type nonnull_non_pointer_2; // expected-note{{in instantiation}} -struct _Nullable SmartPtr{ - SmartPtr(); - SmartPtr(nullptr_t); - SmartPtr(const SmartPtr&); - SmartPtr(SmartPtr&&); - SmartPtr &operator=(const SmartPtr&); - SmartPtr &operator=(SmartPtr&&); -}; -typedef AddNonNull<SmartPtr>::type nonnull_smart_pointer_1; -template<class> struct _Nullable SmartPtrTemplate{}; -typedef AddNonNull<SmartPtrTemplate<int>>::type nonnull_smart_pointer_2; -namespace std { inline namespace __1 { - template <class> class unique_ptr {}; - template <class> class function; - template <class Ret, class... Args> class function<Ret(Args...)> {}; -} } -typedef AddNonNull<std::unique_ptr<int>>::type nonnull_smart_pointer_3; -typedef AddNonNull<std::function<int()>>::type nonnull_smart_pointer_4; - -class Derived : public SmartPtr {}; -Derived _Nullable x; // expected-error {{'_Nullable' cannot be applied}} -class DerivedPrivate : private SmartPtr {}; -DerivedPrivate _Nullable y; // expected-error {{'_Nullable' cannot be applied}} - // Non-null checking within a template. template<typename T> struct AddNonNull2 { @@ -86,7 +54,6 @@ void (*& accepts_nonnull_2)(_Nonnull int *ptr) = accepts_nonnull_1; void (X::* accepts_nonnull_3)(_Nonnull int *ptr); void accepts_nonnull_4(_Nonnull int *ptr); void (&accepts_nonnull_5)(_Nonnull int *ptr) = accepts_nonnull_4; -void accepts_nonnull_6(SmartPtr _Nonnull); void test_accepts_nonnull_null_pointer_literal(X *x) { accepts_nonnull_1(0); // expected-warning{{null passed to a callee that requires a non-null argument}} @@ -94,8 +61,6 @@ void test_accepts_nonnull_null_pointer_literal(X *x) { (x->*accepts_nonnull_3)(0); // expected-warning{{null passed to a callee that requires a non-null argument}} accepts_nonnull_4(0); // expected-warning{{null passed to a callee that requires a non-null argument}} accepts_nonnull_5(0); // expected-warning{{null passed to a callee that requires a non-null argument}} - - accepts_nonnull_6(nullptr); // expected-warning{{null passed to a callee that requires a non-null argument}} } template<void FP(_Nonnull int*)> @@ -106,7 +71,6 @@ void test_accepts_nonnull_null_pointer_literal_template() { template void test_accepts_nonnull_null_pointer_literal_template<&accepts_nonnull_4>(); // expected-note{{instantiation of function template specialization}} void TakeNonnull(void *_Nonnull); -void TakeSmartNonnull(SmartPtr _Nonnull); // Check diff erent forms of assignment to a nonull type from a nullable one. void AssignAndInitNonNull() { void *_Nullable nullable; @@ -117,26 +81,12 @@ void AssignAndInitNonNull() { void *_Nonnull nonnull; nonnull = nullable; // expected-warning{{implicit conversion from nullable pointer 'void * _Nullable' to non-nullable pointer type 'void * _Nonnull'}} nonnull = {nullable}; // expected-warning{{implicit conversion from nullable pointer 'void * _Nullable' to non-nullable pointer type 'void * _Nonnull'}} + TakeNonnull(nullable); //expected-warning{{implicit conversion from nullable pointer 'void * _Nullable' to non-nullable pointer type 'void * _Nonnull}} TakeNonnull(nonnull); // OK - nonnull = (void *_Nonnull)nullable; // explicit cast OK - - SmartPtr _Nullable s_nullable; - SmartPtr _Nonnull s(s_nullable); // expected-warning{{implicit conversion from nullable pointer 'SmartPtr _Nullable' to non-nullable pointer type 'SmartPtr _Nonnull'}} - SmartPtr _Nonnull s2{s_nullable}; // expected-warning{{implicit conversion from nullable pointer 'SmartPtr _Nullable' to non-nullable pointer type 'SmartPtr _Nonnull'}} - SmartPtr _Nonnull s3 = {s_nullable}; // expected-warning{{implicit conversion from nullable pointer 'SmartPtr _Nullable' to non-nullable pointer type 'SmartPtr _Nonnull'}} - SmartPtr _Nonnull s4 = s_nullable; // expected-warning{{implicit conversion from nullable pointer 'SmartPtr _Nullable' to non-nullable pointer type 'SmartPtr _Nonnull'}} - SmartPtr _Nonnull s_nonnull; - s_nonnull = s_nullable; // expected-warning{{implicit conversion from nullable pointer 'SmartPtr _Nullable' to non-nullable pointer type 'SmartPtr _Nonnull'}} - s_nonnull = {s_nullable}; // no warning here - might be nice? - TakeSmartNonnull(s_nullable); //expected-warning{{implicit conversion from nullable pointer 'SmartPtr _Nullable' to non-nullable pointer type 'SmartPtr _Nonnull}} - TakeSmartNonnull(s_nonnull); // OK - s_nonnull = (SmartPtr _Nonnull)s_nullable; // explicit cast OK - s_nonnull = static_cast<SmartPtr _Nonnull>(s_nullable); // explicit cast OK } void *_Nullable ReturnNullable(); -SmartPtr _Nullable ReturnSmartNullable(); void AssignAndInitNonNullFromFn() { void *_Nonnull p(ReturnNullable()); // expected-warning{{implicit conversion from nullable pointer 'void * _Nullable' to non-nullable pointer type 'void * _Nonnull'}} @@ -146,16 +96,8 @@ void AssignAndInitNonNullFromFn() { void *_Nonnull nonnull; nonnull = ReturnNullable(); // expected-warning{{implicit conversion from nullable pointer 'void * _Nullable' to non-nullable pointer type 'void * _Nonnull'}} nonnull = {ReturnNullable()}; // expected-warning{{implicit conversion from nullable pointer 'void * _Nullable' to non-nullable pointer type 'void * _Nonnull'}} - TakeNonnull(ReturnNullable()); //expected-warning{{implicit conversion from nullable pointer 'void * _Nullable' to non-nullable pointer type 'void * _Nonnull}} - SmartPtr _Nonnull s(ReturnSmartNullable()); // expected-warning{{implicit conversion from nullable pointer 'SmartPtr _Nullable' to non-nullable pointer type 'SmartPtr _Nonnull'}} - SmartPtr _Nonnull s2{ReturnSmartNullable()}; // expected-warning{{implicit conversion from nullable pointer 'SmartPtr _Nullable' to non-nullable pointer type 'SmartPtr _Nonnull'}} - SmartPtr _Nonnull s3 = {ReturnSmartNullable()}; // expected-warning{{implicit conversion from nullable pointer 'SmartPtr _Nullable' to non-nullable pointer type 'SmartPtr _Nonnull'}} - SmartPtr _Nonnull s4 = ReturnSmartNullable(); // expected-warning{{implicit conversion from nullable pointer 'SmartPtr _Nullable' to non-nullable pointer type 'SmartPtr _Nonnull'}} - SmartPtr _Nonnull s_nonnull; - s_nonnull = ReturnSmartNullable(); // expected-warning{{implicit conversion from nullable pointer 'SmartPtr _Nullable' to non-nullable pointer type 'SmartPtr _Nonnull'}} - s_nonnull = {ReturnSmartNullable()}; - TakeSmartNonnull(ReturnSmartNullable()); // expected-warning{{implicit conversion from nullable pointer 'SmartPtr _Nullable' to non-nullable pointer type 'SmartPtr _Nonnull'}} + TakeNonnull(ReturnNullable()); //expected-warning{{implicit conversion from nullable pointer 'void * _Nullable' to non-nullable pointer type 'void * _Nonnull}} } void ConditionalExpr(bool c) { _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits