summaryrefslogtreecommitdiffstats
path: root/lib/Sema/SemaExprObjC.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Sema/SemaExprObjC.cpp')
-rw-r--r--lib/Sema/SemaExprObjC.cpp85
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();