aboutsummaryrefslogtreecommitdiff
path: root/clang/lib
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/APINotes/APINotesYAMLCompiler.cpp1
-rw-r--r--clang/lib/AST/Type.cpp3
-rw-r--r--clang/lib/AST/TypePrinter.cpp3
-rw-r--r--clang/lib/Basic/Diagnostic.cpp6
-rw-r--r--clang/lib/Basic/IdentifierTable.cpp5
-rw-r--r--clang/lib/Parse/ParseDecl.cpp5
-rw-r--r--clang/lib/Parse/ParseTentative.cpp4
-rw-r--r--clang/lib/Sema/Sema.cpp3
-rw-r--r--clang/lib/Sema/SemaCodeComplete.cpp4
-rw-r--r--clang/lib/Sema/SemaExpr.cpp6
-rw-r--r--clang/lib/Sema/SemaExprObjC.cpp12
-rw-r--r--clang/lib/Sema/SemaType.cpp13
12 files changed, 60 insertions, 5 deletions
diff --git a/clang/lib/APINotes/APINotesYAMLCompiler.cpp b/clang/lib/APINotes/APINotesYAMLCompiler.cpp
index 997929a..a412012 100644
--- a/clang/lib/APINotes/APINotesYAMLCompiler.cpp
+++ b/clang/lib/APINotes/APINotesYAMLCompiler.cpp
@@ -89,6 +89,7 @@ template <> struct ScalarEnumerationTraits<NullabilityKind> {
IO.enumCase(NK, "Nonnull", NullabilityKind::NonNull);
IO.enumCase(NK, "Optional", NullabilityKind::Nullable);
IO.enumCase(NK, "Unspecified", NullabilityKind::Unspecified);
+ IO.enumCase(NK, "NullableResult", NullabilityKind::NullableResult);
// TODO: Mapping this to it's own value would allow for better cross
// checking. Also the default should be Unknown.
IO.enumCase(NK, "Scalar", NullabilityKind::Unspecified);
diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp
index 1c29d3a..c07cab9 100644
--- a/clang/lib/AST/Type.cpp
+++ b/clang/lib/AST/Type.cpp
@@ -3512,6 +3512,7 @@ bool AttributedType::isQualifier() const {
case attr::ObjCInertUnsafeUnretained:
case attr::TypeNonNull:
case attr::TypeNullable:
+ case attr::TypeNullableResult:
case attr::TypeNullUnspecified:
case attr::LifetimeBound:
case attr::AddressSpace:
@@ -4159,6 +4160,8 @@ AttributedType::getImmediateNullability() const {
return NullabilityKind::Nullable;
if (getAttrKind() == attr::TypeNullUnspecified)
return NullabilityKind::Unspecified;
+ if (getAttrKind() == attr::TypeNullableResult)
+ return NullabilityKind::NullableResult;
return None;
}
diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp
index b42ffde..54c4512 100644
--- a/clang/lib/AST/TypePrinter.cpp
+++ b/clang/lib/AST/TypePrinter.cpp
@@ -1579,6 +1579,8 @@ void TypePrinter::printAttributedBefore(const AttributedType *T,
OS << " _Nullable";
else if (T->getAttrKind() == attr::TypeNullUnspecified)
OS << " _Null_unspecified";
+ else if (T->getAttrKind() == attr::TypeNullableResult)
+ OS << " _Nullable_result";
else
llvm_unreachable("unhandled nullability");
spaceBeforePlaceHolder(OS);
@@ -1649,6 +1651,7 @@ void TypePrinter::printAttributedAfter(const AttributedType *T,
case attr::LifetimeBound:
case attr::TypeNonNull:
case attr::TypeNullable:
+ case attr::TypeNullableResult:
case attr::TypeNullUnspecified:
case attr::ObjCGC:
case attr::ObjCInertUnsafeUnretained:
diff --git a/clang/lib/Basic/Diagnostic.cpp b/clang/lib/Basic/Diagnostic.cpp
index 30a4c51..d3b2122 100644
--- a/clang/lib/Basic/Diagnostic.cpp
+++ b/clang/lib/Basic/Diagnostic.cpp
@@ -55,6 +55,12 @@ const StreamingDiagnostic &clang::operator<<(const StreamingDiagnostic &DB,
case NullabilityKind::Unspecified:
string = nullability.second ? "'null_unspecified'" : "'_Null_unspecified'";
break;
+
+ case NullabilityKind::NullableResult:
+ assert(!nullability.second &&
+ "_Nullable_result isn't supported as context-sensitive keyword");
+ string = "_Nullable_result";
+ break;
}
DB.AddString(string);
diff --git a/clang/lib/Basic/IdentifierTable.cpp b/clang/lib/Basic/IdentifierTable.cpp
index 36b26d9..51c6e02 100644
--- a/clang/lib/Basic/IdentifierTable.cpp
+++ b/clang/lib/Basic/IdentifierTable.cpp
@@ -714,6 +714,11 @@ StringRef clang::getNullabilitySpelling(NullabilityKind kind,
case NullabilityKind::Nullable:
return isContextSensitive ? "nullable" : "_Nullable";
+ case NullabilityKind::NullableResult:
+ assert(!isContextSensitive &&
+ "_Nullable_result isn't supported as context-sensitive keyword");
+ return "_Nullable_result";
+
case NullabilityKind::Unspecified:
return isContextSensitive ? "null_unspecified" : "_Null_unspecified";
}
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index c3c56dd..7ebf06a 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -833,6 +833,7 @@ void Parser::ParseNullabilityTypeSpecifiers(ParsedAttributes &attrs) {
switch (Tok.getKind()) {
case tok::kw__Nonnull:
case tok::kw__Nullable:
+ case tok::kw__Nullable_result:
case tok::kw__Null_unspecified: {
IdentifierInfo *AttrName = Tok.getIdentifierInfo();
SourceLocation AttrNameLoc = ConsumeToken();
@@ -3536,6 +3537,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
// Nullability type specifiers.
case tok::kw__Nonnull:
case tok::kw__Nullable:
+ case tok::kw__Nullable_result:
case tok::kw__Null_unspecified:
ParseNullabilityTypeSpecifiers(DS.getAttributes());
continue;
@@ -5022,6 +5024,7 @@ bool Parser::isTypeSpecifierQualifier() {
case tok::kw__Nonnull:
case tok::kw__Nullable:
+ case tok::kw__Nullable_result:
case tok::kw__Null_unspecified:
case tok::kw___kindof:
@@ -5249,6 +5252,7 @@ bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) {
case tok::kw__Nonnull:
case tok::kw__Nullable:
+ case tok::kw__Nullable_result:
case tok::kw__Null_unspecified:
case tok::kw___kindof:
@@ -5524,6 +5528,7 @@ void Parser::ParseTypeQualifierListOpt(
// Nullability type specifiers.
case tok::kw__Nonnull:
case tok::kw__Nullable:
+ case tok::kw__Nullable_result:
case tok::kw__Null_unspecified:
ParseNullabilityTypeSpecifiers(DS.getAttributes());
continue;
diff --git a/clang/lib/Parse/ParseTentative.cpp b/clang/lib/Parse/ParseTentative.cpp
index d0f1d2e..3bf2bc4 100644
--- a/clang/lib/Parse/ParseTentative.cpp
+++ b/clang/lib/Parse/ParseTentative.cpp
@@ -842,7 +842,8 @@ Parser::TPResult Parser::TryParsePtrOperatorSeq() {
while (Tok.isOneOf(tok::kw_const, tok::kw_volatile, tok::kw_restrict,
tok::kw__Nonnull, tok::kw__Nullable,
- tok::kw__Null_unspecified, tok::kw__Atomic))
+ tok::kw__Nullable_result, tok::kw__Null_unspecified,
+ tok::kw__Atomic))
ConsumeToken();
} else {
return TPResult::True;
@@ -1437,6 +1438,7 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult,
case tok::kw___unaligned:
case tok::kw__Nonnull:
case tok::kw__Nullable:
+ case tok::kw__Nullable_result:
case tok::kw__Null_unspecified:
case tok::kw___kindof:
return TPResult::True;
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp
index b99dc33..456daab 100644
--- a/clang/lib/Sema/Sema.cpp
+++ b/clang/lib/Sema/Sema.cpp
@@ -503,7 +503,8 @@ void Sema::diagnoseNullableToNonnullConversion(QualType DstType,
QualType SrcType,
SourceLocation Loc) {
Optional<NullabilityKind> ExprNullability = SrcType->getNullability(Context);
- if (!ExprNullability || *ExprNullability != NullabilityKind::Nullable)
+ if (!ExprNullability || (*ExprNullability != NullabilityKind::Nullable &&
+ *ExprNullability != NullabilityKind::NullableResult))
return;
Optional<NullabilityKind> TypeNullability = DstType->getNullability(Context);
diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp
index 10fd552..243f68d 100644
--- a/clang/lib/Sema/SemaCodeComplete.cpp
+++ b/clang/lib/Sema/SemaCodeComplete.cpp
@@ -2700,6 +2700,10 @@ static std::string formatObjCParamQualifiers(unsigned ObjCQuals,
case NullabilityKind::Unspecified:
Result += "null_unspecified ";
break;
+
+ case NullabilityKind::NullableResult:
+ llvm_unreachable("Not supported as a context-sensitive keyword!");
+ break;
}
}
}
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 3183b09..738fe87 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -8562,8 +8562,12 @@ static QualType computeConditionalNullability(QualType ResTy, bool IsBin,
auto GetNullability = [&Ctx](QualType Ty) {
Optional<NullabilityKind> Kind = Ty->getNullability(Ctx);
- if (Kind)
+ if (Kind) {
+ // For our purposes, treat _Nullable_result as _Nullable.
+ if (*Kind == NullabilityKind::NullableResult)
+ return NullabilityKind::Nullable;
return *Kind;
+ }
return NullabilityKind::Unspecified;
};
diff --git a/clang/lib/Sema/SemaExprObjC.cpp b/clang/lib/Sema/SemaExprObjC.cpp
index ced0952..f5456ee 100644
--- a/clang/lib/Sema/SemaExprObjC.cpp
+++ b/clang/lib/Sema/SemaExprObjC.cpp
@@ -1563,12 +1563,20 @@ QualType Sema::getMessageSendResultType(const Expr *Receiver,
// Map the nullability of the result into a table index.
unsigned receiverNullabilityIdx = 0;
- if (auto nullability = ReceiverType->getNullability(Context))
+ if (Optional<NullabilityKind> nullability =
+ ReceiverType->getNullability(Context)) {
+ if (*nullability == NullabilityKind::NullableResult)
+ nullability = NullabilityKind::Nullable;
receiverNullabilityIdx = 1 + static_cast<unsigned>(*nullability);
+ }
unsigned resultNullabilityIdx = 0;
- if (auto nullability = resultType->getNullability(Context))
+ if (Optional<NullabilityKind> nullability =
+ resultType->getNullability(Context)) {
+ if (*nullability == NullabilityKind::NullableResult)
+ nullability = NullabilityKind::Nullable;
resultNullabilityIdx = 1 + static_cast<unsigned>(*nullability);
+ }
// The table of nullability mappings, indexed by the receiver's nullability
// and then the result type's nullability.
diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index 0d80bce..df46aa3 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -147,6 +147,7 @@ static void diagnoseBadTypeAttribute(Sema &S, const ParsedAttr &attr,
#define NULLABILITY_TYPE_ATTRS_CASELIST \
case ParsedAttr::AT_TypeNonNull: \
case ParsedAttr::AT_TypeNullable: \
+ case ParsedAttr::AT_TypeNullableResult: \
case ParsedAttr::AT_TypeNullUnspecified
namespace {
@@ -3893,6 +3894,11 @@ IdentifierInfo *Sema::getNullabilityKeyword(NullabilityKind nullability) {
Ident__Nullable = PP.getIdentifierInfo("_Nullable");
return Ident__Nullable;
+ case NullabilityKind::NullableResult:
+ if (!Ident__Nullable_result)
+ Ident__Nullable_result = PP.getIdentifierInfo("_Nullable_result");
+ return Ident__Nullable_result;
+
case NullabilityKind::Unspecified:
if (!Ident__Null_unspecified)
Ident__Null_unspecified = PP.getIdentifierInfo("_Null_unspecified");
@@ -3915,6 +3921,7 @@ static bool hasNullabilityAttr(const ParsedAttributesView &attrs) {
for (const ParsedAttr &AL : attrs) {
if (AL.getKind() == ParsedAttr::AT_TypeNonNull ||
AL.getKind() == ParsedAttr::AT_TypeNullable ||
+ AL.getKind() == ParsedAttr::AT_TypeNullableResult ||
AL.getKind() == ParsedAttr::AT_TypeNullUnspecified)
return true;
}
@@ -4333,6 +4340,9 @@ static Attr *createNullabilityAttr(ASTContext &Ctx, ParsedAttr &Attr,
case NullabilityKind::Nullable:
return createSimpleAttr<TypeNullableAttr>(Ctx, Attr);
+ case NullabilityKind::NullableResult:
+ return createSimpleAttr<TypeNullableResultAttr>(Ctx, Attr);
+
case NullabilityKind::Unspecified:
return createSimpleAttr<TypeNullUnspecifiedAttr>(Ctx, Attr);
}
@@ -7008,6 +7018,9 @@ static NullabilityKind mapNullabilityAttrKind(ParsedAttr::Kind kind) {
case ParsedAttr::AT_TypeNullable:
return NullabilityKind::Nullable;
+ case ParsedAttr::AT_TypeNullableResult:
+ return NullabilityKind::NullableResult;
+
case ParsedAttr::AT_TypeNullUnspecified:
return NullabilityKind::Unspecified;