diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index e98737946b7856ee75a815237940f69e93864aab..2f776f9fa4963fe513654d37e1fec23caa8b5ae4 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -3827,6 +3827,23 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, } } + // Local function that returns true if its argument looks like a va_list. + auto isVaList = [&S](QualType T) -> bool { + auto *typedefTy = T->getAs<TypedefType>(); + if (!typedefTy) + return false; + TypedefDecl *vaListTypedef = S.Context.getBuiltinVaListDecl(); + do { + if (typedefTy->getDecl() == vaListTypedef) + return true; + if (auto *name = typedefTy->getDecl()->getIdentifier()) + if (name->isStr("va_list")) + return true; + typedefTy = typedefTy->desugar()->getAs<TypedefType>(); + } while (typedefTy); + return false; + }; + // Local function that checks the nullability for a given pointer declarator. // Returns true if _Nonnull was inferred. auto inferPointerNullability = [&](SimplePointerKind pointerKind, @@ -3905,37 +3922,27 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, // nullability and perform consistency checking. if (S.ActiveTemplateInstantiations.empty()) { if (T->canHaveNullability() && !T->getNullability(S.Context)) { - SimplePointerKind pointerKind = SimplePointerKind::Pointer; - if (T->isBlockPointerType()) - pointerKind = SimplePointerKind::BlockPointer; - else if (T->isMemberPointerType()) - pointerKind = SimplePointerKind::MemberPointer; - - if (auto *attr = inferPointerNullability( - pointerKind, D.getDeclSpec().getTypeSpecTypeLoc(), - D.getMutableDeclSpec().getAttributes().getListRef())) { - T = Context.getAttributedType( - AttributedType::getNullabilityAttrKind(*inferNullability), T, T); - attr->setUsedAsTypeAttr(); + if (isVaList(T)) { + // Record that we've seen a pointer, but do nothing else. + if (NumPointersRemaining > 0) + --NumPointersRemaining; + } else { + SimplePointerKind pointerKind = SimplePointerKind::Pointer; + if (T->isBlockPointerType()) + pointerKind = SimplePointerKind::BlockPointer; + else if (T->isMemberPointerType()) + pointerKind = SimplePointerKind::MemberPointer; + + if (auto *attr = inferPointerNullability( + pointerKind, D.getDeclSpec().getTypeSpecTypeLoc(), + D.getMutableDeclSpec().getAttributes().getListRef())) { + T = Context.getAttributedType( + AttributedType::getNullabilityAttrKind(*inferNullability),T,T); + attr->setUsedAsTypeAttr(); + } } } - auto isVaList = [&S](QualType T) -> bool { - auto *typedefTy = T->getAs<TypedefType>(); - if (!typedefTy) - return false; - TypedefDecl *vaListTypedef = S.Context.getBuiltinVaListDecl(); - do { - if (typedefTy->getDecl() == vaListTypedef) - return true; - if (auto *name = typedefTy->getDecl()->getIdentifier()) - if (name->isStr("va_list")) - return true; - typedefTy = typedefTy->desugar()->getAs<TypedefType>(); - } while (typedefTy); - return false; - }; - if (complainAboutMissingNullability == CAMN_Yes && T->isArrayType() && !T->getNullability(S.Context) && !isVaList(T) && D.isPrototypeContext() &&