diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/Sema/SemaType.cpp | 42 |
1 files changed, 39 insertions, 3 deletions
diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index d3b773e5350..d950d329b4e 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -2614,6 +2614,8 @@ namespace { SingleLevelPointer, // Multi-level pointer (of any pointer kind). MultiLevelPointer, + // CFFooRef* + MaybePointerToCFRef, // CFErrorRef* CFErrorRefPointer, // NSError** @@ -2754,6 +2756,9 @@ static PointerDeclaratorKind classifyPointerDeclarator(Sema &S, case 1: return PointerDeclaratorKind::SingleLevelPointer; + case 2: + return PointerDeclaratorKind::MaybePointerToCFRef; + default: return PointerDeclaratorKind::MultiLevelPointer; } @@ -2894,6 +2899,8 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, // Determine whether we should infer __nonnull on pointer types. Optional<NullabilityKind> inferNullability; bool inferNullabilityCS = false; + bool inferNullabilityInnerOnly = false; + bool inferNullabilityInnerOnlyComplete = false; // Are we in an assume-nonnull region? bool inAssumeNonNullRegion = false; @@ -3007,6 +3014,31 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, if (isFunctionOrMethod && inAssumeNonNullRegion) inferNullability = NullabilityKind::Nullable; break; + + case PointerDeclaratorKind::MaybePointerToCFRef: + if (isFunctionOrMethod) { + // On pointer-to-pointer parameters marked cf_returns_retained or + // cf_returns_not_retained, if the outer pointer is explicit then + // infer the inner pointer as __nullable. + auto hasCFReturnsAttr = [](const AttributeList *NextAttr) -> bool { + while (NextAttr) { + if (NextAttr->getKind() == AttributeList::AT_CFReturnsRetained || + NextAttr->getKind() == AttributeList::AT_CFReturnsNotRetained) + return true; + NextAttr = NextAttr->getNext(); + } + return false; + }; + if (const auto *InnermostChunk = D.getInnermostNonParenChunk()) { + if (hasCFReturnsAttr(D.getAttributes()) || + hasCFReturnsAttr(InnermostChunk->getAttrs()) || + hasCFReturnsAttr(D.getDeclSpec().getAttributes().getList())) { + inferNullability = NullabilityKind::Nullable; + inferNullabilityInnerOnly = true; + } + } + } + break; } break; @@ -3047,9 +3079,10 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, return nullptr; // If we're supposed to infer nullability, do so now. - if (inferNullability) { - auto syntax = inferNullabilityCS ? AttributeList::AS_ContextSensitiveKeyword - : AttributeList::AS_Keyword; + if (inferNullability && !inferNullabilityInnerOnlyComplete) { + AttributeList::Syntax syntax + = inferNullabilityCS ? AttributeList::AS_ContextSensitiveKeyword + : AttributeList::AS_Keyword; AttributeList *nullabilityAttr = state.getDeclarator().getAttributePool() .create( S.getNullabilityKeyword( @@ -3059,6 +3092,9 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, nullptr, 0, syntax); spliceAttrIntoList(*nullabilityAttr, attrs); + + if (inferNullabilityInnerOnly) + inferNullabilityInnerOnlyComplete = true; return nullabilityAttr; } |