diff options
author | Akira Hatanaka <ahatanaka@apple.com> | 2016-07-20 01:48:11 +0000 |
---|---|---|
committer | Akira Hatanaka <ahatanaka@apple.com> | 2016-07-20 01:48:11 +0000 |
commit | 73118fd10e593d56cce5dd47cdba98e769a120c5 (patch) | |
tree | 05b0e97179f1c9a3b7932415cd645452995e5cdc /clang/lib | |
parent | 6d9ca182fe70de60ed76e635fc7311fa8669a3cd (diff) | |
download | bcm5719-llvm-73118fd10e593d56cce5dd47cdba98e769a120c5.tar.gz bcm5719-llvm-73118fd10e593d56cce5dd47cdba98e769a120c5.zip |
[Sema] Compute the nullability of a conditional expression based on the
nullabilities of its operands.
This patch defines a function to compute the nullability of conditional
expressions, which enables Sema to precisely detect implicit conversions
of nullable conditional expressions to nonnull pointers.
rdar://problem/25166556
Differential Revision: https://reviews.llvm.org/D22392
llvm-svn: 276076
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 53 |
1 files changed, 53 insertions, 0 deletions
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index e882f2e28c5..d748b3c18e5 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -7002,6 +7002,55 @@ static void DiagnoseConditionalPrecedence(Sema &Self, SourceRange(CondRHS->getLocStart(), RHSExpr->getLocEnd())); } +/// Compute the nullability of a conditional expression. +static QualType computeConditionalNullability(QualType ResTy, bool IsBin, + QualType LHSTy, QualType RHSTy, + ASTContext &Ctx) { + if (!ResTy->isPointerType()) + return ResTy; + + auto GetNullability = [&Ctx](QualType Ty) { + Optional<NullabilityKind> Kind = Ty->getNullability(Ctx); + if (Kind) + return *Kind; + return NullabilityKind::Unspecified; + }; + + auto LHSKind = GetNullability(LHSTy), RHSKind = GetNullability(RHSTy); + NullabilityKind MergedKind; + + // Compute nullability of a binary conditional expression. + if (IsBin) { + if (LHSKind == NullabilityKind::NonNull) + MergedKind = NullabilityKind::NonNull; + else + MergedKind = RHSKind; + // Compute nullability of a normal conditional expression. + } else { + if (LHSKind == NullabilityKind::Nullable || + RHSKind == NullabilityKind::Nullable) + MergedKind = NullabilityKind::Nullable; + else if (LHSKind == NullabilityKind::NonNull) + MergedKind = RHSKind; + else if (RHSKind == NullabilityKind::NonNull) + MergedKind = LHSKind; + else + MergedKind = NullabilityKind::Unspecified; + } + + // Return if ResTy already has the correct nullability. + if (GetNullability(ResTy) == MergedKind) + return ResTy; + + // Strip all nullability from ResTy. + while (ResTy->getNullability(Ctx)) + ResTy = ResTy.getSingleStepDesugaredType(Ctx); + + // Create a new AttributedType with the new nullability kind. + auto NewAttr = AttributedType::getNullabilityAttrKind(MergedKind); + return Ctx.getAttributedType(NewAttr, ResTy, ResTy); +} + /// ActOnConditionalOp - Parse a ?: operation. Note that 'LHS' may be null /// in the case of a the GNU conditional expr extension. ExprResult Sema::ActOnConditionalOp(SourceLocation QuestionLoc, @@ -7069,6 +7118,7 @@ ExprResult Sema::ActOnConditionalOp(SourceLocation QuestionLoc, LHSExpr = CondExpr = opaqueValue; } + QualType LHSTy = LHSExpr->getType(), RHSTy = RHSExpr->getType(); ExprValueKind VK = VK_RValue; ExprObjectKind OK = OK_Ordinary; ExprResult Cond = CondExpr, LHS = LHSExpr, RHS = RHSExpr; @@ -7083,6 +7133,9 @@ ExprResult Sema::ActOnConditionalOp(SourceLocation QuestionLoc, CheckBoolLikeConversion(Cond.get(), QuestionLoc); + result = computeConditionalNullability(result, commonExpr, LHSTy, RHSTy, + Context); + if (!commonExpr) return new (Context) ConditionalOperator(Cond.get(), QuestionLoc, LHS.get(), ColonLoc, |