diff options
Diffstat (limited to 'lib/Sema/SemaExprObjC.cpp')
-rw-r--r-- | lib/Sema/SemaExprObjC.cpp | 85 |
1 files changed, 55 insertions, 30 deletions
diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp index ed780efd4c..818a981b49 100644 --- a/lib/Sema/SemaExprObjC.cpp +++ b/lib/Sema/SemaExprObjC.cpp @@ -1,9 +1,8 @@ //===--- SemaExprObjC.cpp - Semantic Analysis for ObjC Expressions --------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -26,6 +25,7 @@ #include "clang/Sema/Scope.h" #include "clang/Sema/ScopeInfo.h" #include "llvm/ADT/SmallString.h" +#include "llvm/Support/ConvertUTF.h" using namespace clang; using namespace sema; @@ -525,6 +525,30 @@ ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) { NSStringPointer = Context.getObjCObjectPointerType(NSStringObject); } + // The boxed expression can be emitted as a compile time constant if it is + // a string literal whose character encoding is compatible with UTF-8. + if (auto *CE = dyn_cast<ImplicitCastExpr>(ValueExpr)) + if (CE->getCastKind() == CK_ArrayToPointerDecay) + if (auto *SL = + dyn_cast<StringLiteral>(CE->getSubExpr()->IgnoreParens())) { + assert((SL->isAscii() || SL->isUTF8()) && + "unexpected character encoding"); + StringRef Str = SL->getString(); + const llvm::UTF8 *StrBegin = Str.bytes_begin(); + const llvm::UTF8 *StrEnd = Str.bytes_end(); + // Check that this is a valid UTF-8 string. + if (llvm::isLegalUTF8String(&StrBegin, StrEnd)) { + BoxedType = Context.getAttributedType( + AttributedType::getNullabilityAttrKind( + NullabilityKind::NonNull), + NSStringPointer, NSStringPointer); + return new (Context) ObjCBoxedExpr(CE, BoxedType, nullptr, SR); + } + + Diag(SL->getBeginLoc(), diag::warn_objc_boxing_invalid_utf8_string) + << NSStringPointer << SL->getSourceRange(); + } + if (!StringWithUTF8StringMethod) { IdentifierInfo *II = &Context.Idents.get("stringWithUTF8String"); Selector stringWithUTF8String = Context.Selectors.getUnarySelector(II); @@ -1922,11 +1946,10 @@ HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT, } // Attempt to correct for typos in property names. - if (TypoCorrection Corrected = - CorrectTypo(DeclarationNameInfo(MemberName, MemberLoc), - LookupOrdinaryName, nullptr, nullptr, - llvm::make_unique<DeclFilterCCC<ObjCPropertyDecl>>(), - CTK_ErrorRecovery, IFace, false, OPT)) { + DeclFilterCCC<ObjCPropertyDecl> CCC{}; + if (TypoCorrection Corrected = CorrectTypo( + DeclarationNameInfo(MemberName, MemberLoc), LookupOrdinaryName, + nullptr, nullptr, CCC, CTK_ErrorRecovery, IFace, false, OPT)) { DeclarationName TypoResult = Corrected.getCorrection(); if (TypoResult.isIdentifier() && TypoResult.getAsIdentifierInfo() == Member) { @@ -2083,7 +2106,7 @@ ActOnClassPropertyRefExpr(IdentifierInfo &receiverName, namespace { -class ObjCInterfaceOrSuperCCC : public CorrectionCandidateCallback { +class ObjCInterfaceOrSuperCCC final : public CorrectionCandidateCallback { public: ObjCInterfaceOrSuperCCC(ObjCMethodDecl *Method) { // Determine whether "super" is acceptable in the current context. @@ -2095,6 +2118,10 @@ class ObjCInterfaceOrSuperCCC : public CorrectionCandidateCallback { return candidate.getCorrectionDeclAs<ObjCInterfaceDecl>() || candidate.isKeyword("super"); } + + std::unique_ptr<CorrectionCandidateCallback> clone() override { + return llvm::make_unique<ObjCInterfaceOrSuperCCC>(*this); + } }; } // end anonymous namespace @@ -2170,9 +2197,9 @@ Sema::ObjCMessageKind Sema::getObjCMessageKind(Scope *S, } } + ObjCInterfaceOrSuperCCC CCC(getCurMethodDecl()); if (TypoCorrection Corrected = CorrectTypo( - Result.getLookupNameInfo(), Result.getLookupKind(), S, nullptr, - llvm::make_unique<ObjCInterfaceOrSuperCCC>(getCurMethodDecl()), + Result.getLookupNameInfo(), Result.getLookupKind(), S, nullptr, CCC, CTK_ErrorRecovery, nullptr, false, nullptr, false)) { if (Corrected.isKeyword()) { // If we've found the keyword "super" (the only keyword that would be @@ -2806,8 +2833,8 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, } else { if (ObjCMethodDecl *CurMeth = getCurMethodDecl()) { if (ObjCInterfaceDecl *ClassDecl = CurMeth->getClassInterface()) { - // FIXME: Is this correct? Why are we assuming that a message to - // Class will call a method in the current interface? + // As a guess, try looking for the method in the current interface. + // This very well may not produce the "right" method. // First check the public methods in the class interface. Method = ClassDecl->lookupClassMethod(Sel); @@ -2815,8 +2842,7 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, if (!Method) Method = ClassDecl->lookupPrivateClassMethod(Sel); - if (Method && DiagnoseUseOfDecl(Method, SelectorSlotLocs, nullptr, - false, false, ClassDecl)) + if (Method && DiagnoseUseOfDecl(Method, SelectorSlotLocs)) return ExprError(); } } @@ -4333,23 +4359,22 @@ Expr *Sema::stripARCUnbridgedCast(Expr *e) { assert(!gse->isResultDependent()); unsigned n = gse->getNumAssocs(); - SmallVector<Expr*, 4> subExprs(n); - SmallVector<TypeSourceInfo*, 4> subTypes(n); - for (unsigned i = 0; i != n; ++i) { - subTypes[i] = gse->getAssocTypeSourceInfo(i); - Expr *sub = gse->getAssocExpr(i); - if (i == gse->getResultIndex()) + SmallVector<Expr *, 4> subExprs; + SmallVector<TypeSourceInfo *, 4> subTypes; + subExprs.reserve(n); + subTypes.reserve(n); + for (const GenericSelectionExpr::Association &assoc : gse->associations()) { + subTypes.push_back(assoc.getTypeSourceInfo()); + Expr *sub = assoc.getAssociationExpr(); + if (assoc.isSelected()) sub = stripARCUnbridgedCast(sub); - subExprs[i] = sub; + subExprs.push_back(sub); } - return new (Context) GenericSelectionExpr(Context, gse->getGenericLoc(), - gse->getControllingExpr(), - subTypes, subExprs, - gse->getDefaultLoc(), - gse->getRParenLoc(), - gse->containsUnexpandedParameterPack(), - gse->getResultIndex()); + return GenericSelectionExpr::Create( + Context, gse->getGenericLoc(), gse->getControllingExpr(), subTypes, + subExprs, gse->getDefaultLoc(), gse->getRParenLoc(), + gse->containsUnexpandedParameterPack(), gse->getResultIndex()); } else { assert(isa<ImplicitCastExpr>(e) && "bad form of unbridged cast!"); return cast<ImplicitCastExpr>(e)->getSubExpr(); |