2008-01-05 06:32:30 +08:00
|
|
|
//===--- 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.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// This file implements semantic analysis for Objective-C expressions.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2010-08-26 06:03:47 +08:00
|
|
|
#include "clang/Sema/SemaInternal.h"
|
2008-01-05 06:32:30 +08:00
|
|
|
#include "clang/AST/ASTContext.h"
|
|
|
|
#include "clang/AST/DeclObjC.h"
|
2008-05-30 05:12:08 +08:00
|
|
|
#include "clang/AST/ExprObjC.h"
|
2011-06-16 07:02:42 +08:00
|
|
|
#include "clang/AST/StmtVisitor.h"
|
Rework the Parser-Sema interaction for Objective-C message
sends. Major changes include:
- Expanded the interface from two actions (ActOnInstanceMessage,
ActOnClassMessage), where ActOnClassMessage also handled sends to
"super" by checking whether the identifier was "super", to three
actions (ActOnInstanceMessage, ActOnClassMessage,
ActOnSuperMessage). Code completion has the same changes.
- The parser now resolves the type to which we are sending a class
message, so ActOnClassMessage now accepts a TypeTy* (rather than
an IdentifierInfo *). This opens the door to more interesting
types (for Objective-C++ support).
- Split ActOnInstanceMessage and ActOnClassMessage into parser
action functions (with their original names) and semantic
functions (BuildInstanceMessage and BuildClassMessage,
respectively). At present, this split is onyl used by
ActOnSuperMessage, which decides which kind of super message it
has and forwards to the appropriate Build*Message. In the future,
Build*Message will be used by template instantiation.
- Use getObjCMessageKind() within the disambiguation of Objective-C
message sends vs. array designators.
Two notes about substandard bits in this patch:
- There is some redundancy in the code in ParseObjCMessageExpr and
ParseInitializerWithPotentialDesignator; this will be addressed
shortly by centralizing the mapping from identifiers to type names
for the message receiver.
- There is some #if 0'd code that won't likely ever be used---it
handles the use of 'super' in methods whose class does not have a
superclass---but could be used to model GCC's behavior more
closely. This code will die in my next check-in, but I want it in
Subversion.
llvm-svn: 102021
2010-04-22 03:57:20 +08:00
|
|
|
#include "clang/AST/TypeLoc.h"
|
2012-12-04 17:13:33 +08:00
|
|
|
#include "clang/Analysis/DomainSpecific/CocoaConventions.h"
|
|
|
|
#include "clang/Edit/Commit.h"
|
|
|
|
#include "clang/Edit/Rewriters.h"
|
2009-03-10 05:12:44 +08:00
|
|
|
#include "clang/Lex/Preprocessor.h"
|
2012-12-04 17:13:33 +08:00
|
|
|
#include "clang/Sema/Initialization.h"
|
|
|
|
#include "clang/Sema/Lookup.h"
|
|
|
|
#include "clang/Sema/Scope.h"
|
|
|
|
#include "clang/Sema/ScopeInfo.h"
|
|
|
|
#include "llvm/ADT/SmallString.h"
|
2009-03-10 05:12:44 +08:00
|
|
|
|
2008-01-05 06:32:30 +08:00
|
|
|
using namespace clang;
|
2011-02-03 17:00:02 +08:00
|
|
|
using namespace sema;
|
2011-10-03 14:36:45 +08:00
|
|
|
using llvm::makeArrayRef;
|
2008-01-05 06:32:30 +08:00
|
|
|
|
2010-08-27 07:41:50 +08:00
|
|
|
ExprResult Sema::ParseObjCStringLiteral(SourceLocation *AtLocs,
|
|
|
|
Expr **strings,
|
|
|
|
unsigned NumStrings) {
|
2009-02-18 14:48:40 +08:00
|
|
|
StringLiteral **Strings = reinterpret_cast<StringLiteral**>(strings);
|
|
|
|
|
2009-02-18 14:13:04 +08:00
|
|
|
// Most ObjC strings are formed out of a single piece. However, we *can*
|
|
|
|
// have strings formed out of multiple @ strings with multiple pptokens in
|
|
|
|
// each one, e.g. @"foo" "bar" @"baz" "qux" which need to be turned into one
|
|
|
|
// StringLiteral for ObjCStringLiteral to hold onto.
|
2009-02-18 14:48:40 +08:00
|
|
|
StringLiteral *S = Strings[0];
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-02-18 14:13:04 +08:00
|
|
|
// If we have a multi-part string, merge it all together.
|
|
|
|
if (NumStrings != 1) {
|
2008-01-05 06:32:30 +08:00
|
|
|
// Concatenate objc strings.
|
2012-02-05 10:13:05 +08:00
|
|
|
SmallString<128> StrBuf;
|
2011-07-23 18:55:15 +08:00
|
|
|
SmallVector<SourceLocation, 8> StrLocs;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-02-18 13:49:11 +08:00
|
|
|
for (unsigned i = 0; i != NumStrings; ++i) {
|
2009-02-18 14:48:40 +08:00
|
|
|
S = Strings[i];
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-07-27 13:40:30 +08:00
|
|
|
// ObjC strings can't be wide or UTF.
|
|
|
|
if (!S->isAscii()) {
|
2009-02-18 14:13:04 +08:00
|
|
|
Diag(S->getLocStart(), diag::err_cfstring_literal_not_string_constant)
|
|
|
|
<< S->getSourceRange();
|
|
|
|
return true;
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-08-17 20:54:38 +08:00
|
|
|
// Append the string.
|
|
|
|
StrBuf += S->getString();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-02-18 14:48:40 +08:00
|
|
|
// Get the locations of the string tokens.
|
|
|
|
StrLocs.append(S->tokloc_begin(), S->tokloc_end());
|
2008-01-05 06:32:30 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-02-18 14:48:40 +08:00
|
|
|
// Create the aggregate string with the appropriate content and location
|
|
|
|
// information.
|
2011-06-21 23:13:30 +08:00
|
|
|
S = StringLiteral::Create(Context, StrBuf,
|
2011-07-27 13:40:30 +08:00
|
|
|
StringLiteral::Ascii, /*Pascal=*/false,
|
2009-02-18 14:40:38 +08:00
|
|
|
Context.getPointerType(Context.CharTy),
|
2009-02-18 14:48:40 +08:00
|
|
|
&StrLocs[0], StrLocs.size());
|
2008-01-05 06:32:30 +08:00
|
|
|
}
|
2012-03-07 04:05:56 +08:00
|
|
|
|
|
|
|
return BuildObjCStringLiteral(AtLocs[0], S);
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2012-03-07 04:05:56 +08:00
|
|
|
ExprResult Sema::BuildObjCStringLiteral(SourceLocation AtLoc, StringLiteral *S){
|
2009-02-18 14:01:06 +08:00
|
|
|
// Verify that this composite string is acceptable for ObjC strings.
|
|
|
|
if (CheckObjCString(S))
|
2008-01-05 06:32:30 +08:00
|
|
|
return true;
|
2009-02-18 14:06:56 +08:00
|
|
|
|
|
|
|
// Initialize the constant string interface lazily. This assumes
|
2009-04-07 22:18:33 +08:00
|
|
|
// the NSString interface is seen in this translation unit. Note: We
|
|
|
|
// don't use NSConstantString, since the runtime team considers this
|
|
|
|
// interface private (even though it appears in the header files).
|
2009-02-18 14:06:56 +08:00
|
|
|
QualType Ty = Context.getObjCConstantStringInterface();
|
|
|
|
if (!Ty.isNull()) {
|
2009-07-11 07:34:53 +08:00
|
|
|
Ty = Context.getObjCObjectPointerType(Ty);
|
2012-03-11 15:00:24 +08:00
|
|
|
} else if (getLangOpts().NoConstantCFStrings) {
|
2010-10-20 01:19:29 +08:00
|
|
|
IdentifierInfo *NSIdent=0;
|
2012-03-11 15:00:24 +08:00
|
|
|
std::string StringClass(getLangOpts().ObjCConstantStringClass);
|
2010-10-20 01:19:29 +08:00
|
|
|
|
|
|
|
if (StringClass.empty())
|
|
|
|
NSIdent = &Context.Idents.get("NSConstantString");
|
|
|
|
else
|
|
|
|
NSIdent = &Context.Idents.get(StringClass);
|
|
|
|
|
2012-03-07 04:05:56 +08:00
|
|
|
NamedDecl *IF = LookupSingleName(TUScope, NSIdent, AtLoc,
|
2010-04-24 07:19:04 +08:00
|
|
|
LookupOrdinaryName);
|
|
|
|
if (ObjCInterfaceDecl *StrIF = dyn_cast_or_null<ObjCInterfaceDecl>(IF)) {
|
|
|
|
Context.setObjCConstantStringInterface(StrIF);
|
|
|
|
Ty = Context.getObjCConstantStringInterface();
|
|
|
|
Ty = Context.getObjCObjectPointerType(Ty);
|
|
|
|
} else {
|
|
|
|
// If there is no NSConstantString interface defined then treat this
|
|
|
|
// as error and recover from it.
|
|
|
|
Diag(S->getLocStart(), diag::err_no_nsconstant_string_class) << NSIdent
|
|
|
|
<< S->getSourceRange();
|
|
|
|
Ty = Context.getObjCIdType();
|
|
|
|
}
|
2008-06-22 05:44:18 +08:00
|
|
|
} else {
|
2012-04-19 08:25:12 +08:00
|
|
|
IdentifierInfo *NSIdent = NSAPIObj->getNSClassId(NSAPI::ClassId_NSString);
|
2012-03-07 04:05:56 +08:00
|
|
|
NamedDecl *IF = LookupSingleName(TUScope, NSIdent, AtLoc,
|
2010-04-16 06:33:43 +08:00
|
|
|
LookupOrdinaryName);
|
2009-02-18 14:06:56 +08:00
|
|
|
if (ObjCInterfaceDecl *StrIF = dyn_cast_or_null<ObjCInterfaceDecl>(IF)) {
|
|
|
|
Context.setObjCConstantStringInterface(StrIF);
|
|
|
|
Ty = Context.getObjCConstantStringInterface();
|
2009-07-11 07:34:53 +08:00
|
|
|
Ty = Context.getObjCObjectPointerType(Ty);
|
2009-02-18 14:06:56 +08:00
|
|
|
} else {
|
2012-02-24 06:51:36 +08:00
|
|
|
// If there is no NSString interface defined, implicitly declare
|
|
|
|
// a @class NSString; and use that instead. This is to make sure
|
|
|
|
// type of an NSString literal is represented correctly, instead of
|
|
|
|
// being an 'id' type.
|
|
|
|
Ty = Context.getObjCNSStringType();
|
|
|
|
if (Ty.isNull()) {
|
|
|
|
ObjCInterfaceDecl *NSStringIDecl =
|
|
|
|
ObjCInterfaceDecl::Create (Context,
|
|
|
|
Context.getTranslationUnitDecl(),
|
|
|
|
SourceLocation(), NSIdent,
|
|
|
|
0, SourceLocation());
|
|
|
|
Ty = Context.getObjCInterfaceType(NSStringIDecl);
|
|
|
|
Context.setObjCNSStringType(Ty);
|
|
|
|
}
|
|
|
|
Ty = Context.getObjCObjectPointerType(Ty);
|
2009-02-18 14:06:56 +08:00
|
|
|
}
|
2008-06-22 05:44:18 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2012-03-07 04:05:56 +08:00
|
|
|
return new (Context) ObjCStringLiteral(S, Ty, AtLoc);
|
|
|
|
}
|
|
|
|
|
2012-05-13 01:32:44 +08:00
|
|
|
/// \brief Emits an error if the given method does not exist, or if the return
|
|
|
|
/// type is not an Objective-C object.
|
|
|
|
static bool validateBoxingMethod(Sema &S, SourceLocation Loc,
|
|
|
|
const ObjCInterfaceDecl *Class,
|
|
|
|
Selector Sel, const ObjCMethodDecl *Method) {
|
|
|
|
if (!Method) {
|
|
|
|
// FIXME: Is there a better way to avoid quotes than using getName()?
|
|
|
|
S.Diag(Loc, diag::err_undeclared_boxing_method) << Sel << Class->getName();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Make sure the return type is reasonable.
|
|
|
|
QualType ReturnType = Method->getResultType();
|
|
|
|
if (!ReturnType->isObjCObjectPointerType()) {
|
|
|
|
S.Diag(Loc, diag::err_objc_literal_method_sig)
|
|
|
|
<< Sel;
|
|
|
|
S.Diag(Method->getLocation(), diag::note_objc_literal_method_return)
|
|
|
|
<< ReturnType;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2012-03-07 04:05:56 +08:00
|
|
|
/// \brief Retrieve the NSNumber factory method that should be used to create
|
|
|
|
/// an Objective-C literal for the given type.
|
|
|
|
static ObjCMethodDecl *getNSNumberFactoryMethod(Sema &S, SourceLocation Loc,
|
2012-04-19 08:25:12 +08:00
|
|
|
QualType NumberType,
|
|
|
|
bool isLiteral = false,
|
|
|
|
SourceRange R = SourceRange()) {
|
2013-02-21 06:23:23 +08:00
|
|
|
Optional<NSAPI::NSNumberLiteralMethodKind> Kind =
|
|
|
|
S.NSAPIObj->getNSNumberFactoryMethodKind(NumberType);
|
|
|
|
|
2012-03-07 04:05:56 +08:00
|
|
|
if (!Kind) {
|
2012-04-19 08:25:12 +08:00
|
|
|
if (isLiteral) {
|
|
|
|
S.Diag(Loc, diag::err_invalid_nsnumber_type)
|
|
|
|
<< NumberType << R;
|
|
|
|
}
|
2012-03-07 04:05:56 +08:00
|
|
|
return 0;
|
|
|
|
}
|
2012-04-19 08:25:12 +08:00
|
|
|
|
2012-03-07 04:05:56 +08:00
|
|
|
// If we already looked up this method, we're done.
|
|
|
|
if (S.NSNumberLiteralMethods[*Kind])
|
|
|
|
return S.NSNumberLiteralMethods[*Kind];
|
|
|
|
|
|
|
|
Selector Sel = S.NSAPIObj->getNSNumberLiteralSelector(*Kind,
|
|
|
|
/*Instance=*/false);
|
|
|
|
|
2012-04-19 08:25:12 +08:00
|
|
|
ASTContext &CX = S.Context;
|
|
|
|
|
|
|
|
// Look up the NSNumber class, if we haven't done so already. It's cached
|
|
|
|
// in the Sema instance.
|
|
|
|
if (!S.NSNumberDecl) {
|
2012-05-13 01:32:52 +08:00
|
|
|
IdentifierInfo *NSNumberId =
|
|
|
|
S.NSAPIObj->getNSClassId(NSAPI::ClassId_NSNumber);
|
2012-04-19 08:25:12 +08:00
|
|
|
NamedDecl *IF = S.LookupSingleName(S.TUScope, NSNumberId,
|
|
|
|
Loc, Sema::LookupOrdinaryName);
|
|
|
|
S.NSNumberDecl = dyn_cast_or_null<ObjCInterfaceDecl>(IF);
|
|
|
|
if (!S.NSNumberDecl) {
|
|
|
|
if (S.getLangOpts().DebuggerObjCLiteral) {
|
|
|
|
// Create a stub definition of NSNumber.
|
2012-05-13 01:32:52 +08:00
|
|
|
S.NSNumberDecl = ObjCInterfaceDecl::Create(CX,
|
|
|
|
CX.getTranslationUnitDecl(),
|
|
|
|
SourceLocation(), NSNumberId,
|
|
|
|
0, SourceLocation());
|
2012-04-19 08:25:12 +08:00
|
|
|
} else {
|
|
|
|
// Otherwise, require a declaration of NSNumber.
|
|
|
|
S.Diag(Loc, diag::err_undeclared_nsnumber);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
} else if (!S.NSNumberDecl->hasDefinition()) {
|
|
|
|
S.Diag(Loc, diag::err_undeclared_nsnumber);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// generate the pointer to NSNumber type.
|
2012-05-13 01:32:52 +08:00
|
|
|
QualType NSNumberObject = CX.getObjCInterfaceType(S.NSNumberDecl);
|
|
|
|
S.NSNumberPointer = CX.getObjCObjectPointerType(NSNumberObject);
|
2012-04-19 08:25:12 +08:00
|
|
|
}
|
|
|
|
|
2012-03-07 04:05:56 +08:00
|
|
|
// Look for the appropriate method within NSNumber.
|
2012-05-13 01:32:52 +08:00
|
|
|
ObjCMethodDecl *Method = S.NSNumberDecl->lookupClassMethod(Sel);
|
2012-03-11 15:00:24 +08:00
|
|
|
if (!Method && S.getLangOpts().DebuggerObjCLiteral) {
|
2012-04-19 08:25:12 +08:00
|
|
|
// create a stub definition this NSNumber factory method.
|
2012-03-07 04:05:56 +08:00
|
|
|
TypeSourceInfo *ResultTInfo = 0;
|
2012-04-19 08:25:12 +08:00
|
|
|
Method = ObjCMethodDecl::Create(CX, SourceLocation(), SourceLocation(), Sel,
|
2012-05-13 01:32:52 +08:00
|
|
|
S.NSNumberPointer, ResultTInfo,
|
|
|
|
S.NSNumberDecl,
|
2012-04-19 08:25:12 +08:00
|
|
|
/*isInstance=*/false, /*isVariadic=*/false,
|
2012-10-11 00:42:25 +08:00
|
|
|
/*isPropertyAccessor=*/false,
|
2012-04-19 08:25:12 +08:00
|
|
|
/*isImplicitlyDeclared=*/true,
|
2012-05-13 01:32:52 +08:00
|
|
|
/*isDefined=*/false,
|
|
|
|
ObjCMethodDecl::Required,
|
2012-04-19 08:25:12 +08:00
|
|
|
/*HasRelatedResultType=*/false);
|
2012-03-07 04:05:56 +08:00
|
|
|
ParmVarDecl *value = ParmVarDecl::Create(S.Context, Method,
|
|
|
|
SourceLocation(), SourceLocation(),
|
2012-04-19 08:25:12 +08:00
|
|
|
&CX.Idents.get("value"),
|
2012-05-13 01:32:52 +08:00
|
|
|
NumberType, /*TInfo=*/0, SC_None,
|
2013-04-04 03:27:57 +08:00
|
|
|
0);
|
2013-05-05 08:41:58 +08:00
|
|
|
Method->setMethodParams(S.Context, value, None);
|
2012-03-07 04:05:56 +08:00
|
|
|
}
|
|
|
|
|
2012-05-13 01:32:44 +08:00
|
|
|
if (!validateBoxingMethod(S, Loc, S.NSNumberDecl, Sel, Method))
|
2012-03-07 04:05:56 +08:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
// Note: if the parameter type is out-of-line, we'll catch it later in the
|
|
|
|
// implicit conversion.
|
|
|
|
|
|
|
|
S.NSNumberLiteralMethods[*Kind] = Method;
|
|
|
|
return Method;
|
|
|
|
}
|
|
|
|
|
2012-04-19 08:25:12 +08:00
|
|
|
/// BuildObjCNumericLiteral - builds an ObjCBoxedExpr AST node for the
|
|
|
|
/// numeric literal expression. Type of the expression will be "NSNumber *".
|
2012-03-07 04:05:56 +08:00
|
|
|
ExprResult Sema::BuildObjCNumericLiteral(SourceLocation AtLoc, Expr *Number) {
|
|
|
|
// Determine the type of the literal.
|
|
|
|
QualType NumberType = Number->getType();
|
|
|
|
if (CharacterLiteral *Char = dyn_cast<CharacterLiteral>(Number)) {
|
|
|
|
// In C, character literals have type 'int'. That's not the type we want
|
|
|
|
// to use to determine the Objective-c literal kind.
|
|
|
|
switch (Char->getKind()) {
|
|
|
|
case CharacterLiteral::Ascii:
|
|
|
|
NumberType = Context.CharTy;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CharacterLiteral::Wide:
|
2013-05-10 18:08:40 +08:00
|
|
|
NumberType = Context.getWideCharType();
|
2012-03-07 04:05:56 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case CharacterLiteral::UTF16:
|
|
|
|
NumberType = Context.Char16Ty;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CharacterLiteral::UTF32:
|
|
|
|
NumberType = Context.Char32Ty;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Look for the appropriate method within NSNumber.
|
|
|
|
// Construct the literal.
|
2012-05-02 05:47:19 +08:00
|
|
|
SourceRange NR(Number->getSourceRange());
|
2012-04-19 08:25:12 +08:00
|
|
|
ObjCMethodDecl *Method = getNSNumberFactoryMethod(*this, AtLoc, NumberType,
|
2012-05-02 05:47:19 +08:00
|
|
|
true, NR);
|
2012-03-07 04:05:56 +08:00
|
|
|
if (!Method)
|
|
|
|
return ExprError();
|
|
|
|
|
|
|
|
// Convert the number to the type that the parameter expects.
|
2012-05-02 05:47:19 +08:00
|
|
|
ParmVarDecl *ParamDecl = Method->param_begin()[0];
|
|
|
|
InitializedEntity Entity = InitializedEntity::InitializeParameter(Context,
|
|
|
|
ParamDecl);
|
|
|
|
ExprResult ConvertedNumber = PerformCopyInitialization(Entity,
|
|
|
|
SourceLocation(),
|
|
|
|
Owned(Number));
|
2012-03-07 04:05:56 +08:00
|
|
|
if (ConvertedNumber.isInvalid())
|
|
|
|
return ExprError();
|
|
|
|
Number = ConvertedNumber.get();
|
|
|
|
|
2012-05-02 05:47:19 +08:00
|
|
|
// Use the effective source range of the literal, including the leading '@'.
|
2012-03-07 04:05:56 +08:00
|
|
|
return MaybeBindToTemporary(
|
2012-05-02 05:47:19 +08:00
|
|
|
new (Context) ObjCBoxedExpr(Number, NSNumberPointer, Method,
|
|
|
|
SourceRange(AtLoc, NR.getEnd())));
|
2012-03-07 04:05:56 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
ExprResult Sema::ActOnObjCBoolLiteral(SourceLocation AtLoc,
|
|
|
|
SourceLocation ValueLoc,
|
|
|
|
bool Value) {
|
|
|
|
ExprResult Inner;
|
2012-03-11 15:00:24 +08:00
|
|
|
if (getLangOpts().CPlusPlus) {
|
2012-03-07 04:05:56 +08:00
|
|
|
Inner = ActOnCXXBoolLiteral(ValueLoc, Value? tok::kw_true : tok::kw_false);
|
|
|
|
} else {
|
|
|
|
// C doesn't actually have a way to represent literal values of type
|
|
|
|
// _Bool. So, we'll use 0/1 and implicit cast to _Bool.
|
|
|
|
Inner = ActOnIntegerConstant(ValueLoc, Value? 1 : 0);
|
|
|
|
Inner = ImpCastExprToType(Inner.get(), Context.BoolTy,
|
|
|
|
CK_IntegralToBoolean);
|
|
|
|
}
|
|
|
|
|
|
|
|
return BuildObjCNumericLiteral(AtLoc, Inner.get());
|
|
|
|
}
|
|
|
|
|
|
|
|
/// \brief Check that the given expression is a valid element of an Objective-C
|
|
|
|
/// collection literal.
|
|
|
|
static ExprResult CheckObjCCollectionLiteralElement(Sema &S, Expr *Element,
|
2013-08-14 07:44:55 +08:00
|
|
|
QualType T,
|
|
|
|
bool ArrayLiteral = false) {
|
2012-03-07 04:05:56 +08:00
|
|
|
// If the expression is type-dependent, there's nothing for us to do.
|
|
|
|
if (Element->isTypeDependent())
|
|
|
|
return Element;
|
|
|
|
|
|
|
|
ExprResult Result = S.CheckPlaceholderExpr(Element);
|
|
|
|
if (Result.isInvalid())
|
|
|
|
return ExprError();
|
|
|
|
Element = Result.get();
|
|
|
|
|
|
|
|
// In C++, check for an implicit conversion to an Objective-C object pointer
|
|
|
|
// type.
|
2012-03-11 15:00:24 +08:00
|
|
|
if (S.getLangOpts().CPlusPlus && Element->getType()->isRecordType()) {
|
2012-03-07 04:05:56 +08:00
|
|
|
InitializedEntity Entity
|
2012-05-13 01:32:52 +08:00
|
|
|
= InitializedEntity::InitializeParameter(S.Context, T,
|
|
|
|
/*Consumed=*/false);
|
2012-03-07 04:05:56 +08:00
|
|
|
InitializationKind Kind
|
2012-05-13 01:32:52 +08:00
|
|
|
= InitializationKind::CreateCopy(Element->getLocStart(),
|
|
|
|
SourceLocation());
|
2013-05-03 23:05:50 +08:00
|
|
|
InitializationSequence Seq(S, Entity, Kind, Element);
|
2012-03-07 04:05:56 +08:00
|
|
|
if (!Seq.Failed())
|
2012-08-24 07:38:35 +08:00
|
|
|
return Seq.Perform(S, Entity, Kind, Element);
|
2012-03-07 04:05:56 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
Expr *OrigElement = Element;
|
|
|
|
|
|
|
|
// Perform lvalue-to-rvalue conversion.
|
|
|
|
Result = S.DefaultLvalueConversion(Element);
|
|
|
|
if (Result.isInvalid())
|
|
|
|
return ExprError();
|
|
|
|
Element = Result.get();
|
|
|
|
|
|
|
|
// Make sure that we have an Objective-C pointer type or block.
|
|
|
|
if (!Element->getType()->isObjCObjectPointerType() &&
|
|
|
|
!Element->getType()->isBlockPointerType()) {
|
|
|
|
bool Recovered = false;
|
|
|
|
|
|
|
|
// If this is potentially an Objective-C numeric literal, add the '@'.
|
|
|
|
if (isa<IntegerLiteral>(OrigElement) ||
|
|
|
|
isa<CharacterLiteral>(OrigElement) ||
|
|
|
|
isa<FloatingLiteral>(OrigElement) ||
|
|
|
|
isa<ObjCBoolLiteralExpr>(OrigElement) ||
|
|
|
|
isa<CXXBoolLiteralExpr>(OrigElement)) {
|
|
|
|
if (S.NSAPIObj->getNSNumberFactoryMethodKind(OrigElement->getType())) {
|
|
|
|
int Which = isa<CharacterLiteral>(OrigElement) ? 1
|
|
|
|
: (isa<CXXBoolLiteralExpr>(OrigElement) ||
|
|
|
|
isa<ObjCBoolLiteralExpr>(OrigElement)) ? 2
|
|
|
|
: 3;
|
|
|
|
|
|
|
|
S.Diag(OrigElement->getLocStart(), diag::err_box_literal_collection)
|
|
|
|
<< Which << OrigElement->getSourceRange()
|
|
|
|
<< FixItHint::CreateInsertion(OrigElement->getLocStart(), "@");
|
|
|
|
|
|
|
|
Result = S.BuildObjCNumericLiteral(OrigElement->getLocStart(),
|
|
|
|
OrigElement);
|
|
|
|
if (Result.isInvalid())
|
|
|
|
return ExprError();
|
|
|
|
|
|
|
|
Element = Result.get();
|
|
|
|
Recovered = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// If this is potentially an Objective-C string literal, add the '@'.
|
|
|
|
else if (StringLiteral *String = dyn_cast<StringLiteral>(OrigElement)) {
|
|
|
|
if (String->isAscii()) {
|
|
|
|
S.Diag(OrigElement->getLocStart(), diag::err_box_literal_collection)
|
|
|
|
<< 0 << OrigElement->getSourceRange()
|
|
|
|
<< FixItHint::CreateInsertion(OrigElement->getLocStart(), "@");
|
|
|
|
|
|
|
|
Result = S.BuildObjCStringLiteral(OrigElement->getLocStart(), String);
|
|
|
|
if (Result.isInvalid())
|
|
|
|
return ExprError();
|
|
|
|
|
|
|
|
Element = Result.get();
|
|
|
|
Recovered = true;
|
|
|
|
}
|
|
|
|
}
|
2013-08-14 07:44:55 +08:00
|
|
|
|
2012-03-07 04:05:56 +08:00
|
|
|
if (!Recovered) {
|
|
|
|
S.Diag(Element->getLocStart(), diag::err_invalid_collection_element)
|
|
|
|
<< Element->getType();
|
|
|
|
return ExprError();
|
|
|
|
}
|
|
|
|
}
|
2013-08-14 07:44:55 +08:00
|
|
|
if (ArrayLiteral)
|
2013-10-10 06:34:33 +08:00
|
|
|
if (ObjCStringLiteral *getString =
|
|
|
|
dyn_cast<ObjCStringLiteral>(OrigElement)) {
|
|
|
|
if (StringLiteral *SL = getString->getString()) {
|
|
|
|
unsigned numConcat = SL->getNumConcatenated();
|
|
|
|
if (numConcat > 1) {
|
|
|
|
// Only warn if the concatenated string doesn't come from a macro.
|
|
|
|
bool hasMacro = false;
|
|
|
|
for (unsigned i = 0; i < numConcat ; ++i)
|
|
|
|
if (SL->getStrTokenLoc(i).isMacroID()) {
|
|
|
|
hasMacro = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (!hasMacro)
|
|
|
|
S.Diag(Element->getLocStart(),
|
|
|
|
diag::warn_concatenated_nsarray_literal)
|
|
|
|
<< Element->getType();
|
|
|
|
}
|
|
|
|
}
|
2013-08-14 07:44:55 +08:00
|
|
|
}
|
|
|
|
|
2012-03-07 04:05:56 +08:00
|
|
|
// Make sure that the element has the type that the container factory
|
|
|
|
// function expects.
|
|
|
|
return S.PerformCopyInitialization(
|
|
|
|
InitializedEntity::InitializeParameter(S.Context, T,
|
|
|
|
/*Consumed=*/false),
|
|
|
|
Element->getLocStart(), Element);
|
|
|
|
}
|
|
|
|
|
2012-04-19 08:25:12 +08:00
|
|
|
ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) {
|
|
|
|
if (ValueExpr->isTypeDependent()) {
|
|
|
|
ObjCBoxedExpr *BoxedExpr =
|
|
|
|
new (Context) ObjCBoxedExpr(ValueExpr, Context.DependentTy, NULL, SR);
|
|
|
|
return Owned(BoxedExpr);
|
|
|
|
}
|
|
|
|
ObjCMethodDecl *BoxingMethod = NULL;
|
|
|
|
QualType BoxedType;
|
|
|
|
// Convert the expression to an RValue, so we can check for pointer types...
|
|
|
|
ExprResult RValue = DefaultFunctionArrayLvalueConversion(ValueExpr);
|
|
|
|
if (RValue.isInvalid()) {
|
|
|
|
return ExprError();
|
|
|
|
}
|
|
|
|
ValueExpr = RValue.get();
|
2012-05-02 05:47:19 +08:00
|
|
|
QualType ValueType(ValueExpr->getType());
|
2012-04-19 08:25:12 +08:00
|
|
|
if (const PointerType *PT = ValueType->getAs<PointerType>()) {
|
|
|
|
QualType PointeeType = PT->getPointeeType();
|
|
|
|
if (Context.hasSameUnqualifiedType(PointeeType, Context.CharTy)) {
|
|
|
|
|
|
|
|
if (!NSStringDecl) {
|
|
|
|
IdentifierInfo *NSStringId =
|
|
|
|
NSAPIObj->getNSClassId(NSAPI::ClassId_NSString);
|
|
|
|
NamedDecl *Decl = LookupSingleName(TUScope, NSStringId,
|
|
|
|
SR.getBegin(), LookupOrdinaryName);
|
|
|
|
NSStringDecl = dyn_cast_or_null<ObjCInterfaceDecl>(Decl);
|
|
|
|
if (!NSStringDecl) {
|
|
|
|
if (getLangOpts().DebuggerObjCLiteral) {
|
|
|
|
// Support boxed expressions in the debugger w/o NSString declaration.
|
2012-05-13 01:32:52 +08:00
|
|
|
DeclContext *TU = Context.getTranslationUnitDecl();
|
|
|
|
NSStringDecl = ObjCInterfaceDecl::Create(Context, TU,
|
|
|
|
SourceLocation(),
|
|
|
|
NSStringId,
|
2012-04-19 08:25:12 +08:00
|
|
|
0, SourceLocation());
|
|
|
|
} else {
|
|
|
|
Diag(SR.getBegin(), diag::err_undeclared_nsstring);
|
|
|
|
return ExprError();
|
|
|
|
}
|
|
|
|
} else if (!NSStringDecl->hasDefinition()) {
|
|
|
|
Diag(SR.getBegin(), diag::err_undeclared_nsstring);
|
|
|
|
return ExprError();
|
|
|
|
}
|
|
|
|
assert(NSStringDecl && "NSStringDecl should not be NULL");
|
2012-05-13 01:32:52 +08:00
|
|
|
QualType NSStringObject = Context.getObjCInterfaceType(NSStringDecl);
|
|
|
|
NSStringPointer = Context.getObjCObjectPointerType(NSStringObject);
|
2012-04-19 08:25:12 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!StringWithUTF8StringMethod) {
|
|
|
|
IdentifierInfo *II = &Context.Idents.get("stringWithUTF8String");
|
|
|
|
Selector stringWithUTF8String = Context.Selectors.getUnarySelector(II);
|
|
|
|
|
|
|
|
// Look for the appropriate method within NSString.
|
2012-05-13 01:32:44 +08:00
|
|
|
BoxingMethod = NSStringDecl->lookupClassMethod(stringWithUTF8String);
|
|
|
|
if (!BoxingMethod && getLangOpts().DebuggerObjCLiteral) {
|
2012-04-19 08:25:12 +08:00
|
|
|
// Debugger needs to work even if NSString hasn't been defined.
|
|
|
|
TypeSourceInfo *ResultTInfo = 0;
|
|
|
|
ObjCMethodDecl *M =
|
|
|
|
ObjCMethodDecl::Create(Context, SourceLocation(), SourceLocation(),
|
|
|
|
stringWithUTF8String, NSStringPointer,
|
|
|
|
ResultTInfo, NSStringDecl,
|
|
|
|
/*isInstance=*/false, /*isVariadic=*/false,
|
2012-10-11 00:42:25 +08:00
|
|
|
/*isPropertyAccessor=*/false,
|
2012-04-19 08:25:12 +08:00
|
|
|
/*isImplicitlyDeclared=*/true,
|
|
|
|
/*isDefined=*/false,
|
|
|
|
ObjCMethodDecl::Required,
|
|
|
|
/*HasRelatedResultType=*/false);
|
2012-05-13 01:32:52 +08:00
|
|
|
QualType ConstCharType = Context.CharTy.withConst();
|
2012-04-19 08:25:12 +08:00
|
|
|
ParmVarDecl *value =
|
|
|
|
ParmVarDecl::Create(Context, M,
|
|
|
|
SourceLocation(), SourceLocation(),
|
|
|
|
&Context.Idents.get("value"),
|
2012-05-13 01:32:52 +08:00
|
|
|
Context.getPointerType(ConstCharType),
|
2012-04-19 08:25:12 +08:00
|
|
|
/*TInfo=*/0,
|
2013-04-04 03:27:57 +08:00
|
|
|
SC_None, 0);
|
2013-05-05 08:41:58 +08:00
|
|
|
M->setMethodParams(Context, value, None);
|
2012-05-13 01:32:44 +08:00
|
|
|
BoxingMethod = M;
|
2012-04-19 08:25:12 +08:00
|
|
|
}
|
2012-05-12 23:53:41 +08:00
|
|
|
|
2012-05-13 01:32:44 +08:00
|
|
|
if (!validateBoxingMethod(*this, SR.getBegin(), NSStringDecl,
|
|
|
|
stringWithUTF8String, BoxingMethod))
|
|
|
|
return ExprError();
|
|
|
|
|
|
|
|
StringWithUTF8StringMethod = BoxingMethod;
|
2012-04-19 08:25:12 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
BoxingMethod = StringWithUTF8StringMethod;
|
|
|
|
BoxedType = NSStringPointer;
|
|
|
|
}
|
2012-05-02 05:47:19 +08:00
|
|
|
} else if (ValueType->isBuiltinType()) {
|
2012-04-19 08:25:12 +08:00
|
|
|
// The other types we support are numeric, char and BOOL/bool. We could also
|
|
|
|
// provide limited support for structure types, such as NSRange, NSRect, and
|
|
|
|
// NSSize. See NSValue (NSValueGeometryExtensions) in <Foundation/NSGeometry.h>
|
|
|
|
// for more details.
|
|
|
|
|
|
|
|
// Check for a top-level character literal.
|
|
|
|
if (const CharacterLiteral *Char =
|
|
|
|
dyn_cast<CharacterLiteral>(ValueExpr->IgnoreParens())) {
|
|
|
|
// In C, character literals have type 'int'. That's not the type we want
|
|
|
|
// to use to determine the Objective-c literal kind.
|
|
|
|
switch (Char->getKind()) {
|
|
|
|
case CharacterLiteral::Ascii:
|
|
|
|
ValueType = Context.CharTy;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CharacterLiteral::Wide:
|
2013-05-10 18:08:40 +08:00
|
|
|
ValueType = Context.getWideCharType();
|
2012-04-19 08:25:12 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case CharacterLiteral::UTF16:
|
|
|
|
ValueType = Context.Char16Ty;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CharacterLiteral::UTF32:
|
|
|
|
ValueType = Context.Char32Ty;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// FIXME: Do I need to do anything special with BoolTy expressions?
|
|
|
|
|
|
|
|
// Look for the appropriate method within NSNumber.
|
|
|
|
BoxingMethod = getNSNumberFactoryMethod(*this, SR.getBegin(), ValueType);
|
|
|
|
BoxedType = NSNumberPointer;
|
2012-05-16 03:17:44 +08:00
|
|
|
|
|
|
|
} else if (const EnumType *ET = ValueType->getAs<EnumType>()) {
|
|
|
|
if (!ET->getDecl()->isComplete()) {
|
|
|
|
Diag(SR.getBegin(), diag::err_objc_incomplete_boxed_expression_type)
|
|
|
|
<< ValueType << ValueExpr->getSourceRange();
|
|
|
|
return ExprError();
|
|
|
|
}
|
|
|
|
|
|
|
|
BoxingMethod = getNSNumberFactoryMethod(*this, SR.getBegin(),
|
|
|
|
ET->getDecl()->getIntegerType());
|
|
|
|
BoxedType = NSNumberPointer;
|
2012-04-19 08:25:12 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!BoxingMethod) {
|
|
|
|
Diag(SR.getBegin(), diag::err_objc_illegal_boxed_expression_type)
|
|
|
|
<< ValueType << ValueExpr->getSourceRange();
|
|
|
|
return ExprError();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Convert the expression to the type that the parameter requires.
|
2012-05-02 05:47:19 +08:00
|
|
|
ParmVarDecl *ParamDecl = BoxingMethod->param_begin()[0];
|
|
|
|
InitializedEntity Entity = InitializedEntity::InitializeParameter(Context,
|
|
|
|
ParamDecl);
|
|
|
|
ExprResult ConvertedValueExpr = PerformCopyInitialization(Entity,
|
|
|
|
SourceLocation(),
|
|
|
|
Owned(ValueExpr));
|
2012-04-19 08:25:12 +08:00
|
|
|
if (ConvertedValueExpr.isInvalid())
|
|
|
|
return ExprError();
|
|
|
|
ValueExpr = ConvertedValueExpr.get();
|
|
|
|
|
|
|
|
ObjCBoxedExpr *BoxedExpr =
|
|
|
|
new (Context) ObjCBoxedExpr(ValueExpr, BoxedType,
|
|
|
|
BoxingMethod, SR);
|
|
|
|
return MaybeBindToTemporary(BoxedExpr);
|
|
|
|
}
|
|
|
|
|
2012-07-31 13:14:30 +08:00
|
|
|
/// Build an ObjC subscript pseudo-object expression, given that
|
|
|
|
/// that's supported by the runtime.
|
2012-03-07 04:05:56 +08:00
|
|
|
ExprResult Sema::BuildObjCSubscriptExpression(SourceLocation RB, Expr *BaseExpr,
|
|
|
|
Expr *IndexExpr,
|
|
|
|
ObjCMethodDecl *getterMethod,
|
|
|
|
ObjCMethodDecl *setterMethod) {
|
2013-11-02 05:58:17 +08:00
|
|
|
assert(!LangOpts.isSubscriptPointerArithmetic());
|
2012-06-20 14:18:46 +08:00
|
|
|
|
2012-07-31 13:14:30 +08:00
|
|
|
// We can't get dependent types here; our callers should have
|
|
|
|
// filtered them out.
|
|
|
|
assert((!BaseExpr->isTypeDependent() && !IndexExpr->isTypeDependent()) &&
|
|
|
|
"base or index cannot have dependent type here");
|
|
|
|
|
|
|
|
// Filter out placeholders in the index. In theory, overloads could
|
|
|
|
// be preserved here, although that might not actually work correctly.
|
2012-03-07 04:05:56 +08:00
|
|
|
ExprResult Result = CheckPlaceholderExpr(IndexExpr);
|
|
|
|
if (Result.isInvalid())
|
|
|
|
return ExprError();
|
|
|
|
IndexExpr = Result.get();
|
|
|
|
|
2012-07-31 13:14:30 +08:00
|
|
|
// Perform lvalue-to-rvalue conversion on the base.
|
2012-03-07 04:05:56 +08:00
|
|
|
Result = DefaultLvalueConversion(BaseExpr);
|
|
|
|
if (Result.isInvalid())
|
|
|
|
return ExprError();
|
|
|
|
BaseExpr = Result.get();
|
2012-07-31 13:14:30 +08:00
|
|
|
|
|
|
|
// Build the pseudo-object expression.
|
2012-03-07 04:05:56 +08:00
|
|
|
return Owned(ObjCSubscriptRefExpr::Create(Context,
|
|
|
|
BaseExpr,
|
|
|
|
IndexExpr,
|
|
|
|
Context.PseudoObjectTy,
|
|
|
|
getterMethod,
|
|
|
|
setterMethod, RB));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
ExprResult Sema::BuildObjCArrayLiteral(SourceRange SR, MultiExprArg Elements) {
|
|
|
|
// Look up the NSArray class, if we haven't done so already.
|
|
|
|
if (!NSArrayDecl) {
|
|
|
|
NamedDecl *IF = LookupSingleName(TUScope,
|
|
|
|
NSAPIObj->getNSClassId(NSAPI::ClassId_NSArray),
|
|
|
|
SR.getBegin(),
|
|
|
|
LookupOrdinaryName);
|
|
|
|
NSArrayDecl = dyn_cast_or_null<ObjCInterfaceDecl>(IF);
|
2012-03-11 15:00:24 +08:00
|
|
|
if (!NSArrayDecl && getLangOpts().DebuggerObjCLiteral)
|
2012-03-07 04:05:56 +08:00
|
|
|
NSArrayDecl = ObjCInterfaceDecl::Create (Context,
|
|
|
|
Context.getTranslationUnitDecl(),
|
|
|
|
SourceLocation(),
|
|
|
|
NSAPIObj->getNSClassId(NSAPI::ClassId_NSArray),
|
|
|
|
0, SourceLocation());
|
|
|
|
|
|
|
|
if (!NSArrayDecl) {
|
|
|
|
Diag(SR.getBegin(), diag::err_undeclared_nsarray);
|
|
|
|
return ExprError();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Find the arrayWithObjects:count: method, if we haven't done so already.
|
|
|
|
QualType IdT = Context.getObjCIdType();
|
|
|
|
if (!ArrayWithObjectsMethod) {
|
|
|
|
Selector
|
|
|
|
Sel = NSAPIObj->getNSArraySelector(NSAPI::NSArr_arrayWithObjectsCount);
|
2012-05-13 01:32:44 +08:00
|
|
|
ObjCMethodDecl *Method = NSArrayDecl->lookupClassMethod(Sel);
|
|
|
|
if (!Method && getLangOpts().DebuggerObjCLiteral) {
|
2012-03-07 04:05:56 +08:00
|
|
|
TypeSourceInfo *ResultTInfo = 0;
|
2012-05-13 01:32:44 +08:00
|
|
|
Method = ObjCMethodDecl::Create(Context,
|
2012-03-07 04:05:56 +08:00
|
|
|
SourceLocation(), SourceLocation(), Sel,
|
|
|
|
IdT,
|
|
|
|
ResultTInfo,
|
|
|
|
Context.getTranslationUnitDecl(),
|
|
|
|
false /*Instance*/, false/*isVariadic*/,
|
2012-10-11 00:42:25 +08:00
|
|
|
/*isPropertyAccessor=*/false,
|
2012-03-07 04:05:56 +08:00
|
|
|
/*isImplicitlyDeclared=*/true, /*isDefined=*/false,
|
|
|
|
ObjCMethodDecl::Required,
|
|
|
|
false);
|
|
|
|
SmallVector<ParmVarDecl *, 2> Params;
|
2012-05-13 01:32:44 +08:00
|
|
|
ParmVarDecl *objects = ParmVarDecl::Create(Context, Method,
|
2012-05-13 01:32:52 +08:00
|
|
|
SourceLocation(),
|
|
|
|
SourceLocation(),
|
|
|
|
&Context.Idents.get("objects"),
|
|
|
|
Context.getPointerType(IdT),
|
2013-04-04 03:27:57 +08:00
|
|
|
/*TInfo=*/0, SC_None, 0);
|
2012-03-07 04:05:56 +08:00
|
|
|
Params.push_back(objects);
|
2012-05-13 01:32:44 +08:00
|
|
|
ParmVarDecl *cnt = ParmVarDecl::Create(Context, Method,
|
2012-05-13 01:32:52 +08:00
|
|
|
SourceLocation(),
|
|
|
|
SourceLocation(),
|
|
|
|
&Context.Idents.get("cnt"),
|
|
|
|
Context.UnsignedLongTy,
|
2013-04-04 03:27:57 +08:00
|
|
|
/*TInfo=*/0, SC_None, 0);
|
2012-03-07 04:05:56 +08:00
|
|
|
Params.push_back(cnt);
|
2013-05-05 08:41:58 +08:00
|
|
|
Method->setMethodParams(Context, Params, None);
|
2012-03-07 04:05:56 +08:00
|
|
|
}
|
|
|
|
|
2012-05-13 01:32:44 +08:00
|
|
|
if (!validateBoxingMethod(*this, SR.getBegin(), NSArrayDecl, Sel, Method))
|
2012-03-07 04:05:56 +08:00
|
|
|
return ExprError();
|
2012-05-13 01:32:44 +08:00
|
|
|
|
2012-05-13 01:32:56 +08:00
|
|
|
// Dig out the type that all elements should be converted to.
|
|
|
|
QualType T = Method->param_begin()[0]->getType();
|
|
|
|
const PointerType *PtrT = T->getAs<PointerType>();
|
|
|
|
if (!PtrT ||
|
|
|
|
!Context.hasSameUnqualifiedType(PtrT->getPointeeType(), IdT)) {
|
|
|
|
Diag(SR.getBegin(), diag::err_objc_literal_method_sig)
|
|
|
|
<< Sel;
|
|
|
|
Diag(Method->param_begin()[0]->getLocation(),
|
|
|
|
diag::note_objc_literal_method_param)
|
|
|
|
<< 0 << T
|
|
|
|
<< Context.getPointerType(IdT.withConst());
|
|
|
|
return ExprError();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check that the 'count' parameter is integral.
|
|
|
|
if (!Method->param_begin()[1]->getType()->isIntegerType()) {
|
|
|
|
Diag(SR.getBegin(), diag::err_objc_literal_method_sig)
|
|
|
|
<< Sel;
|
|
|
|
Diag(Method->param_begin()[1]->getLocation(),
|
|
|
|
diag::note_objc_literal_method_param)
|
|
|
|
<< 1
|
|
|
|
<< Method->param_begin()[1]->getType()
|
|
|
|
<< "integral";
|
|
|
|
return ExprError();
|
|
|
|
}
|
|
|
|
|
|
|
|
// We've found a good +arrayWithObjects:count: method. Save it!
|
2012-05-13 01:32:44 +08:00
|
|
|
ArrayWithObjectsMethod = Method;
|
2012-03-07 04:05:56 +08:00
|
|
|
}
|
|
|
|
|
2012-05-13 01:32:56 +08:00
|
|
|
QualType ObjectsType = ArrayWithObjectsMethod->param_begin()[0]->getType();
|
|
|
|
QualType RequiredType = ObjectsType->castAs<PointerType>()->getPointeeType();
|
2012-03-07 04:05:56 +08:00
|
|
|
|
|
|
|
// Check that each of the elements provided is valid in a collection literal,
|
|
|
|
// performing conversions as necessary.
|
2012-08-24 07:38:35 +08:00
|
|
|
Expr **ElementsBuffer = Elements.data();
|
2012-03-07 04:05:56 +08:00
|
|
|
for (unsigned I = 0, N = Elements.size(); I != N; ++I) {
|
|
|
|
ExprResult Converted = CheckObjCCollectionLiteralElement(*this,
|
|
|
|
ElementsBuffer[I],
|
2013-08-14 07:44:55 +08:00
|
|
|
RequiredType, true);
|
2012-03-07 04:05:56 +08:00
|
|
|
if (Converted.isInvalid())
|
|
|
|
return ExprError();
|
|
|
|
|
|
|
|
ElementsBuffer[I] = Converted.get();
|
|
|
|
}
|
|
|
|
|
|
|
|
QualType Ty
|
|
|
|
= Context.getObjCObjectPointerType(
|
|
|
|
Context.getObjCInterfaceType(NSArrayDecl));
|
|
|
|
|
|
|
|
return MaybeBindToTemporary(
|
2012-08-24 07:38:35 +08:00
|
|
|
ObjCArrayLiteral::Create(Context, Elements, Ty,
|
|
|
|
ArrayWithObjectsMethod, SR));
|
2012-03-07 04:05:56 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
ExprResult Sema::BuildObjCDictionaryLiteral(SourceRange SR,
|
|
|
|
ObjCDictionaryElement *Elements,
|
|
|
|
unsigned NumElements) {
|
|
|
|
// Look up the NSDictionary class, if we haven't done so already.
|
|
|
|
if (!NSDictionaryDecl) {
|
|
|
|
NamedDecl *IF = LookupSingleName(TUScope,
|
|
|
|
NSAPIObj->getNSClassId(NSAPI::ClassId_NSDictionary),
|
|
|
|
SR.getBegin(), LookupOrdinaryName);
|
|
|
|
NSDictionaryDecl = dyn_cast_or_null<ObjCInterfaceDecl>(IF);
|
2012-03-11 15:00:24 +08:00
|
|
|
if (!NSDictionaryDecl && getLangOpts().DebuggerObjCLiteral)
|
2012-03-07 04:05:56 +08:00
|
|
|
NSDictionaryDecl = ObjCInterfaceDecl::Create (Context,
|
|
|
|
Context.getTranslationUnitDecl(),
|
|
|
|
SourceLocation(),
|
|
|
|
NSAPIObj->getNSClassId(NSAPI::ClassId_NSDictionary),
|
|
|
|
0, SourceLocation());
|
|
|
|
|
|
|
|
if (!NSDictionaryDecl) {
|
|
|
|
Diag(SR.getBegin(), diag::err_undeclared_nsdictionary);
|
|
|
|
return ExprError();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Find the dictionaryWithObjects:forKeys:count: method, if we haven't done
|
|
|
|
// so already.
|
|
|
|
QualType IdT = Context.getObjCIdType();
|
|
|
|
if (!DictionaryWithObjectsMethod) {
|
|
|
|
Selector Sel = NSAPIObj->getNSDictionarySelector(
|
2012-05-13 01:32:52 +08:00
|
|
|
NSAPI::NSDict_dictionaryWithObjectsForKeysCount);
|
2012-05-13 01:32:44 +08:00
|
|
|
ObjCMethodDecl *Method = NSDictionaryDecl->lookupClassMethod(Sel);
|
|
|
|
if (!Method && getLangOpts().DebuggerObjCLiteral) {
|
|
|
|
Method = ObjCMethodDecl::Create(Context,
|
2012-03-07 04:05:56 +08:00
|
|
|
SourceLocation(), SourceLocation(), Sel,
|
|
|
|
IdT,
|
|
|
|
0 /*TypeSourceInfo */,
|
|
|
|
Context.getTranslationUnitDecl(),
|
|
|
|
false /*Instance*/, false/*isVariadic*/,
|
2012-10-11 00:42:25 +08:00
|
|
|
/*isPropertyAccessor=*/false,
|
2012-03-07 04:05:56 +08:00
|
|
|
/*isImplicitlyDeclared=*/true, /*isDefined=*/false,
|
|
|
|
ObjCMethodDecl::Required,
|
|
|
|
false);
|
|
|
|
SmallVector<ParmVarDecl *, 3> Params;
|
2012-05-13 01:32:44 +08:00
|
|
|
ParmVarDecl *objects = ParmVarDecl::Create(Context, Method,
|
2012-05-13 01:32:52 +08:00
|
|
|
SourceLocation(),
|
|
|
|
SourceLocation(),
|
|
|
|
&Context.Idents.get("objects"),
|
|
|
|
Context.getPointerType(IdT),
|
2013-04-04 03:27:57 +08:00
|
|
|
/*TInfo=*/0, SC_None, 0);
|
2012-03-07 04:05:56 +08:00
|
|
|
Params.push_back(objects);
|
2012-05-13 01:32:44 +08:00
|
|
|
ParmVarDecl *keys = ParmVarDecl::Create(Context, Method,
|
2012-05-13 01:32:52 +08:00
|
|
|
SourceLocation(),
|
|
|
|
SourceLocation(),
|
|
|
|
&Context.Idents.get("keys"),
|
|
|
|
Context.getPointerType(IdT),
|
2013-04-04 03:27:57 +08:00
|
|
|
/*TInfo=*/0, SC_None, 0);
|
2012-03-07 04:05:56 +08:00
|
|
|
Params.push_back(keys);
|
2012-05-13 01:32:44 +08:00
|
|
|
ParmVarDecl *cnt = ParmVarDecl::Create(Context, Method,
|
2012-05-13 01:32:52 +08:00
|
|
|
SourceLocation(),
|
|
|
|
SourceLocation(),
|
|
|
|
&Context.Idents.get("cnt"),
|
|
|
|
Context.UnsignedLongTy,
|
2013-04-04 03:27:57 +08:00
|
|
|
/*TInfo=*/0, SC_None, 0);
|
2012-03-07 04:05:56 +08:00
|
|
|
Params.push_back(cnt);
|
2013-05-05 08:41:58 +08:00
|
|
|
Method->setMethodParams(Context, Params, None);
|
2012-03-07 04:05:56 +08:00
|
|
|
}
|
|
|
|
|
2012-05-13 01:32:44 +08:00
|
|
|
if (!validateBoxingMethod(*this, SR.getBegin(), NSDictionaryDecl, Sel,
|
|
|
|
Method))
|
|
|
|
return ExprError();
|
|
|
|
|
2012-05-13 01:32:56 +08:00
|
|
|
// Dig out the type that all values should be converted to.
|
|
|
|
QualType ValueT = Method->param_begin()[0]->getType();
|
|
|
|
const PointerType *PtrValue = ValueT->getAs<PointerType>();
|
|
|
|
if (!PtrValue ||
|
|
|
|
!Context.hasSameUnqualifiedType(PtrValue->getPointeeType(), IdT)) {
|
|
|
|
Diag(SR.getBegin(), diag::err_objc_literal_method_sig)
|
|
|
|
<< Sel;
|
|
|
|
Diag(Method->param_begin()[0]->getLocation(),
|
|
|
|
diag::note_objc_literal_method_param)
|
|
|
|
<< 0 << ValueT
|
|
|
|
<< Context.getPointerType(IdT.withConst());
|
|
|
|
return ExprError();
|
|
|
|
}
|
2012-03-07 04:05:56 +08:00
|
|
|
|
2012-05-13 01:32:56 +08:00
|
|
|
// Dig out the type that all keys should be converted to.
|
|
|
|
QualType KeyT = Method->param_begin()[1]->getType();
|
|
|
|
const PointerType *PtrKey = KeyT->getAs<PointerType>();
|
|
|
|
if (!PtrKey ||
|
|
|
|
!Context.hasSameUnqualifiedType(PtrKey->getPointeeType(),
|
|
|
|
IdT)) {
|
|
|
|
bool err = true;
|
|
|
|
if (PtrKey) {
|
|
|
|
if (QIDNSCopying.isNull()) {
|
|
|
|
// key argument of selector is id<NSCopying>?
|
|
|
|
if (ObjCProtocolDecl *NSCopyingPDecl =
|
|
|
|
LookupProtocol(&Context.Idents.get("NSCopying"), SR.getBegin())) {
|
|
|
|
ObjCProtocolDecl *PQ[] = {NSCopyingPDecl};
|
|
|
|
QIDNSCopying =
|
|
|
|
Context.getObjCObjectType(Context.ObjCBuiltinIdTy,
|
|
|
|
(ObjCProtocolDecl**) PQ,1);
|
|
|
|
QIDNSCopying = Context.getObjCObjectPointerType(QIDNSCopying);
|
|
|
|
}
|
2012-03-07 04:05:56 +08:00
|
|
|
}
|
2012-05-13 01:32:56 +08:00
|
|
|
if (!QIDNSCopying.isNull())
|
|
|
|
err = !Context.hasSameUnqualifiedType(PtrKey->getPointeeType(),
|
|
|
|
QIDNSCopying);
|
2012-03-07 04:05:56 +08:00
|
|
|
}
|
|
|
|
|
2012-05-13 01:32:56 +08:00
|
|
|
if (err) {
|
|
|
|
Diag(SR.getBegin(), diag::err_objc_literal_method_sig)
|
|
|
|
<< Sel;
|
|
|
|
Diag(Method->param_begin()[1]->getLocation(),
|
|
|
|
diag::note_objc_literal_method_param)
|
|
|
|
<< 1 << KeyT
|
|
|
|
<< Context.getPointerType(IdT.withConst());
|
|
|
|
return ExprError();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check that the 'count' parameter is integral.
|
|
|
|
QualType CountType = Method->param_begin()[2]->getType();
|
|
|
|
if (!CountType->isIntegerType()) {
|
2012-03-07 04:05:56 +08:00
|
|
|
Diag(SR.getBegin(), diag::err_objc_literal_method_sig)
|
2012-05-13 01:32:56 +08:00
|
|
|
<< Sel;
|
|
|
|
Diag(Method->param_begin()[2]->getLocation(),
|
2012-03-07 04:05:56 +08:00
|
|
|
diag::note_objc_literal_method_param)
|
2012-05-13 01:32:56 +08:00
|
|
|
<< 2 << CountType
|
|
|
|
<< "integral";
|
2012-03-07 04:05:56 +08:00
|
|
|
return ExprError();
|
|
|
|
}
|
2012-05-13 01:32:56 +08:00
|
|
|
|
|
|
|
// We've found a good +dictionaryWithObjects:keys:count: method; save it!
|
|
|
|
DictionaryWithObjectsMethod = Method;
|
2012-03-07 04:05:56 +08:00
|
|
|
}
|
2012-05-13 01:32:56 +08:00
|
|
|
|
|
|
|
QualType ValuesT = DictionaryWithObjectsMethod->param_begin()[0]->getType();
|
|
|
|
QualType ValueT = ValuesT->castAs<PointerType>()->getPointeeType();
|
|
|
|
QualType KeysT = DictionaryWithObjectsMethod->param_begin()[1]->getType();
|
|
|
|
QualType KeyT = KeysT->castAs<PointerType>()->getPointeeType();
|
2012-03-07 04:05:56 +08:00
|
|
|
|
|
|
|
// Check that each of the keys and values provided is valid in a collection
|
|
|
|
// literal, performing conversions as necessary.
|
|
|
|
bool HasPackExpansions = false;
|
|
|
|
for (unsigned I = 0, N = NumElements; I != N; ++I) {
|
|
|
|
// Check the key.
|
|
|
|
ExprResult Key = CheckObjCCollectionLiteralElement(*this, Elements[I].Key,
|
|
|
|
KeyT);
|
|
|
|
if (Key.isInvalid())
|
|
|
|
return ExprError();
|
|
|
|
|
|
|
|
// Check the value.
|
|
|
|
ExprResult Value
|
|
|
|
= CheckObjCCollectionLiteralElement(*this, Elements[I].Value, ValueT);
|
|
|
|
if (Value.isInvalid())
|
|
|
|
return ExprError();
|
|
|
|
|
|
|
|
Elements[I].Key = Key.get();
|
|
|
|
Elements[I].Value = Value.get();
|
|
|
|
|
|
|
|
if (Elements[I].EllipsisLoc.isInvalid())
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (!Elements[I].Key->containsUnexpandedParameterPack() &&
|
|
|
|
!Elements[I].Value->containsUnexpandedParameterPack()) {
|
|
|
|
Diag(Elements[I].EllipsisLoc,
|
|
|
|
diag::err_pack_expansion_without_parameter_packs)
|
|
|
|
<< SourceRange(Elements[I].Key->getLocStart(),
|
|
|
|
Elements[I].Value->getLocEnd());
|
|
|
|
return ExprError();
|
|
|
|
}
|
|
|
|
|
|
|
|
HasPackExpansions = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
QualType Ty
|
|
|
|
= Context.getObjCObjectPointerType(
|
2013-08-19 15:57:02 +08:00
|
|
|
Context.getObjCInterfaceType(NSDictionaryDecl));
|
|
|
|
return MaybeBindToTemporary(ObjCDictionaryLiteral::Create(
|
|
|
|
Context, makeArrayRef(Elements, NumElements), HasPackExpansions, Ty,
|
|
|
|
DictionaryWithObjectsMethod, SR));
|
2008-01-05 06:32:30 +08:00
|
|
|
}
|
|
|
|
|
2011-05-15 04:32:39 +08:00
|
|
|
ExprResult Sema::BuildObjCEncodeExpression(SourceLocation AtLoc,
|
2010-04-20 23:39:42 +08:00
|
|
|
TypeSourceInfo *EncodedTypeInfo,
|
2009-06-08 02:45:35 +08:00
|
|
|
SourceLocation RParenLoc) {
|
2010-04-20 23:39:42 +08:00
|
|
|
QualType EncodedType = EncodedTypeInfo->getType();
|
2009-06-08 02:45:35 +08:00
|
|
|
QualType StrTy;
|
2009-09-09 23:08:12 +08:00
|
|
|
if (EncodedType->isDependentType())
|
2009-06-08 02:45:35 +08:00
|
|
|
StrTy = Context.DependentTy;
|
|
|
|
else {
|
2011-06-17 06:34:44 +08:00
|
|
|
if (!EncodedType->getAsArrayTypeUnsafe() && //// Incomplete array is handled.
|
|
|
|
!EncodedType->isVoidType()) // void is handled too.
|
2011-05-15 04:32:39 +08:00
|
|
|
if (RequireCompleteType(AtLoc, EncodedType,
|
2012-05-05 00:32:21 +08:00
|
|
|
diag::err_incomplete_type_objc_at_encode,
|
|
|
|
EncodedTypeInfo->getTypeLoc()))
|
2011-05-15 04:32:39 +08:00
|
|
|
return ExprError();
|
|
|
|
|
2009-06-08 02:45:35 +08:00
|
|
|
std::string Str;
|
|
|
|
Context.getObjCEncodingForType(EncodedType, Str);
|
|
|
|
|
|
|
|
// The type of @encode is the same as the type of the corresponding string,
|
|
|
|
// which is an array type.
|
|
|
|
StrTy = Context.CharTy;
|
|
|
|
// A C++ string literal has a const-qualified element type (C++ 2.13.4p1).
|
2012-03-11 15:00:24 +08:00
|
|
|
if (getLangOpts().CPlusPlus || getLangOpts().ConstStrings)
|
2009-06-08 02:45:35 +08:00
|
|
|
StrTy.addConst();
|
|
|
|
StrTy = Context.getConstantArrayType(StrTy, llvm::APInt(32, Str.size()+1),
|
|
|
|
ArrayType::Normal, 0);
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-04-20 23:39:42 +08:00
|
|
|
return new (Context) ObjCEncodeExpr(StrTy, EncodedTypeInfo, AtLoc, RParenLoc);
|
2009-06-08 02:45:35 +08:00
|
|
|
}
|
|
|
|
|
2010-08-27 07:41:50 +08:00
|
|
|
ExprResult Sema::ParseObjCEncodeExpression(SourceLocation AtLoc,
|
|
|
|
SourceLocation EncodeLoc,
|
|
|
|
SourceLocation LParenLoc,
|
|
|
|
ParsedType ty,
|
|
|
|
SourceLocation RParenLoc) {
|
2009-08-19 09:28:28 +08:00
|
|
|
// FIXME: Preserve type source info ?
|
2010-04-20 23:39:42 +08:00
|
|
|
TypeSourceInfo *TInfo;
|
|
|
|
QualType EncodedType = GetTypeFromParser(ty, &TInfo);
|
|
|
|
if (!TInfo)
|
|
|
|
TInfo = Context.getTrivialTypeSourceInfo(EncodedType,
|
|
|
|
PP.getLocForEndOfToken(LParenLoc));
|
2008-01-05 06:32:30 +08:00
|
|
|
|
2010-04-20 23:39:42 +08:00
|
|
|
return BuildObjCEncodeExpression(AtLoc, TInfo, RParenLoc);
|
2008-01-05 06:32:30 +08:00
|
|
|
}
|
|
|
|
|
2010-08-27 07:41:50 +08:00
|
|
|
ExprResult Sema::ParseObjCSelectorExpression(Selector Sel,
|
|
|
|
SourceLocation AtLoc,
|
|
|
|
SourceLocation SelLoc,
|
|
|
|
SourceLocation LParenLoc,
|
2013-01-23 02:35:43 +08:00
|
|
|
SourceLocation RParenLoc) {
|
|
|
|
ObjCMethodDecl *Method = LookupInstanceMethodInGlobalPool(Sel,
|
|
|
|
SourceRange(LParenLoc, RParenLoc), false, false);
|
|
|
|
if (!Method)
|
|
|
|
Method = LookupFactoryMethodInGlobalPool(Sel,
|
2009-06-17 00:25:00 +08:00
|
|
|
SourceRange(LParenLoc, RParenLoc));
|
2013-06-06 02:46:14 +08:00
|
|
|
if (!Method) {
|
|
|
|
if (const ObjCMethodDecl *OM = SelectorsForTypoCorrection(Sel)) {
|
|
|
|
Selector MatchedSel = OM->getSelector();
|
|
|
|
SourceRange SelectorRange(LParenLoc.getLocWithOffset(1),
|
|
|
|
RParenLoc.getLocWithOffset(-1));
|
|
|
|
Diag(SelLoc, diag::warn_undeclared_selector_with_typo)
|
|
|
|
<< Sel << MatchedSel
|
|
|
|
<< FixItHint::CreateReplacement(SelectorRange, MatchedSel.getAsString());
|
|
|
|
|
|
|
|
} else
|
|
|
|
Diag(SelLoc, diag::warn_undeclared_selector) << Sel;
|
|
|
|
}
|
2011-07-14 03:05:43 +08:00
|
|
|
|
2013-01-23 02:35:43 +08:00
|
|
|
if (!Method ||
|
|
|
|
Method->getImplementationControl() != ObjCMethodDecl::Optional) {
|
|
|
|
llvm::DenseMap<Selector, SourceLocation>::iterator Pos
|
|
|
|
= ReferencedSelectors.find(Sel);
|
|
|
|
if (Pos == ReferencedSelectors.end())
|
|
|
|
ReferencedSelectors.insert(std::make_pair(Sel, AtLoc));
|
2011-07-14 03:05:43 +08:00
|
|
|
}
|
2010-07-23 02:24:20 +08:00
|
|
|
|
2013-01-23 02:35:43 +08:00
|
|
|
// In ARC, forbid the user from using @selector for
|
2011-06-16 07:02:42 +08:00
|
|
|
// retain/release/autorelease/dealloc/retainCount.
|
2012-03-11 15:00:24 +08:00
|
|
|
if (getLangOpts().ObjCAutoRefCount) {
|
2011-06-16 07:02:42 +08:00
|
|
|
switch (Sel.getMethodFamily()) {
|
|
|
|
case OMF_retain:
|
|
|
|
case OMF_release:
|
|
|
|
case OMF_autorelease:
|
|
|
|
case OMF_retainCount:
|
|
|
|
case OMF_dealloc:
|
|
|
|
Diag(AtLoc, diag::err_arc_illegal_selector) <<
|
|
|
|
Sel << SourceRange(LParenLoc, RParenLoc);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OMF_None:
|
|
|
|
case OMF_alloc:
|
|
|
|
case OMF_copy:
|
2011-08-29 06:35:17 +08:00
|
|
|
case OMF_finalize:
|
2011-06-16 07:02:42 +08:00
|
|
|
case OMF_init:
|
|
|
|
case OMF_mutableCopy:
|
|
|
|
case OMF_new:
|
|
|
|
case OMF_self:
|
2011-07-06 06:38:59 +08:00
|
|
|
case OMF_performSelector:
|
2011-06-16 07:02:42 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2009-02-18 14:06:56 +08:00
|
|
|
QualType Ty = Context.getObjCSelType();
|
2010-02-04 04:11:42 +08:00
|
|
|
return new (Context) ObjCSelectorExpr(Ty, Sel, AtLoc, RParenLoc);
|
2008-01-05 06:32:30 +08:00
|
|
|
}
|
|
|
|
|
2010-08-27 07:41:50 +08:00
|
|
|
ExprResult Sema::ParseObjCProtocolExpression(IdentifierInfo *ProtocolId,
|
|
|
|
SourceLocation AtLoc,
|
|
|
|
SourceLocation ProtoLoc,
|
|
|
|
SourceLocation LParenLoc,
|
2012-05-16 08:50:02 +08:00
|
|
|
SourceLocation ProtoIdLoc,
|
2010-08-27 07:41:50 +08:00
|
|
|
SourceLocation RParenLoc) {
|
2012-05-16 08:50:02 +08:00
|
|
|
ObjCProtocolDecl* PDecl = LookupProtocol(ProtocolId, ProtoIdLoc);
|
2008-01-05 06:32:30 +08:00
|
|
|
if (!PDecl) {
|
2008-11-19 16:23:25 +08:00
|
|
|
Diag(ProtoLoc, diag::err_undeclared_protocol) << ProtocolId;
|
2008-01-05 06:32:30 +08:00
|
|
|
return true;
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-02-18 14:06:56 +08:00
|
|
|
QualType Ty = Context.getObjCProtoType();
|
|
|
|
if (Ty.isNull())
|
2008-01-05 06:32:30 +08:00
|
|
|
return true;
|
2009-07-11 07:34:53 +08:00
|
|
|
Ty = Context.getObjCObjectPointerType(Ty);
|
2012-05-16 08:50:02 +08:00
|
|
|
return new (Context) ObjCProtocolExpr(Ty, PDecl, AtLoc, ProtoIdLoc, RParenLoc);
|
2008-01-05 06:32:30 +08:00
|
|
|
}
|
|
|
|
|
2011-02-03 17:00:02 +08:00
|
|
|
/// Try to capture an implicit reference to 'self'.
|
2012-02-04 06:47:37 +08:00
|
|
|
ObjCMethodDecl *Sema::tryCaptureObjCSelf(SourceLocation Loc) {
|
|
|
|
DeclContext *DC = getFunctionLevelDeclContext();
|
2011-02-03 17:00:02 +08:00
|
|
|
|
|
|
|
// If we're not in an ObjC method, error out. Note that, unlike the
|
|
|
|
// C++ case, we don't require an instance method --- class methods
|
|
|
|
// still have a 'self', and we really do still need to capture it!
|
|
|
|
ObjCMethodDecl *method = dyn_cast<ObjCMethodDecl>(DC);
|
|
|
|
if (!method)
|
|
|
|
return 0;
|
|
|
|
|
2012-02-18 17:37:24 +08:00
|
|
|
tryCaptureVariable(method->getSelfDecl(), Loc);
|
2011-02-03 17:00:02 +08:00
|
|
|
|
|
|
|
return method;
|
|
|
|
}
|
|
|
|
|
2011-09-10 04:05:21 +08:00
|
|
|
static QualType stripObjCInstanceType(ASTContext &Context, QualType T) {
|
|
|
|
if (T == Context.getObjCInstanceType())
|
|
|
|
return Context.getObjCIdType();
|
|
|
|
|
|
|
|
return T;
|
|
|
|
}
|
|
|
|
|
2011-06-11 09:09:30 +08:00
|
|
|
QualType Sema::getMessageSendResultType(QualType ReceiverType,
|
|
|
|
ObjCMethodDecl *Method,
|
|
|
|
bool isClassMessage, bool isSuperMessage) {
|
|
|
|
assert(Method && "Must have a method");
|
|
|
|
if (!Method->hasRelatedResultType())
|
|
|
|
return Method->getSendResultType();
|
|
|
|
|
|
|
|
// If a method has a related return type:
|
|
|
|
// - if the method found is an instance method, but the message send
|
|
|
|
// was a class message send, T is the declared return type of the method
|
|
|
|
// found
|
|
|
|
if (Method->isInstanceMethod() && isClassMessage)
|
2011-09-10 04:05:21 +08:00
|
|
|
return stripObjCInstanceType(Context, Method->getSendResultType());
|
2011-06-11 09:09:30 +08:00
|
|
|
|
|
|
|
// - if the receiver is super, T is a pointer to the class of the
|
|
|
|
// enclosing method definition
|
|
|
|
if (isSuperMessage) {
|
|
|
|
if (ObjCMethodDecl *CurMethod = getCurMethodDecl())
|
|
|
|
if (ObjCInterfaceDecl *Class = CurMethod->getClassInterface())
|
|
|
|
return Context.getObjCObjectPointerType(
|
|
|
|
Context.getObjCInterfaceType(Class));
|
|
|
|
}
|
|
|
|
|
|
|
|
// - if the receiver is the name of a class U, T is a pointer to U
|
|
|
|
if (ReceiverType->getAs<ObjCInterfaceType>() ||
|
|
|
|
ReceiverType->isObjCQualifiedInterfaceType())
|
|
|
|
return Context.getObjCObjectPointerType(ReceiverType);
|
|
|
|
// - if the receiver is of type Class or qualified Class type,
|
|
|
|
// T is the declared return type of the method.
|
|
|
|
if (ReceiverType->isObjCClassType() ||
|
|
|
|
ReceiverType->isObjCQualifiedClassType())
|
2011-09-10 04:05:21 +08:00
|
|
|
return stripObjCInstanceType(Context, Method->getSendResultType());
|
2011-06-11 09:09:30 +08:00
|
|
|
|
|
|
|
// - if the receiver is id, qualified id, Class, or qualified Class, T
|
|
|
|
// is the receiver type, otherwise
|
|
|
|
// - T is the type of the receiver expression.
|
|
|
|
return ReceiverType;
|
|
|
|
}
|
|
|
|
|
2013-03-19 15:04:25 +08:00
|
|
|
/// Look for an ObjC method whose result type exactly matches the given type.
|
|
|
|
static const ObjCMethodDecl *
|
|
|
|
findExplicitInstancetypeDeclarer(const ObjCMethodDecl *MD,
|
|
|
|
QualType instancetype) {
|
|
|
|
if (MD->getResultType() == instancetype) return MD;
|
|
|
|
|
|
|
|
// For these purposes, a method in an @implementation overrides a
|
|
|
|
// declaration in the @interface.
|
|
|
|
if (const ObjCImplDecl *impl =
|
|
|
|
dyn_cast<ObjCImplDecl>(MD->getDeclContext())) {
|
|
|
|
const ObjCContainerDecl *iface;
|
|
|
|
if (const ObjCCategoryImplDecl *catImpl =
|
|
|
|
dyn_cast<ObjCCategoryImplDecl>(impl)) {
|
|
|
|
iface = catImpl->getCategoryDecl();
|
|
|
|
} else {
|
|
|
|
iface = impl->getClassInterface();
|
|
|
|
}
|
|
|
|
|
|
|
|
const ObjCMethodDecl *ifaceMD =
|
|
|
|
iface->getMethod(MD->getSelector(), MD->isInstanceMethod());
|
|
|
|
if (ifaceMD) return findExplicitInstancetypeDeclarer(ifaceMD, instancetype);
|
|
|
|
}
|
|
|
|
|
|
|
|
SmallVector<const ObjCMethodDecl *, 4> overrides;
|
|
|
|
MD->getOverriddenMethods(overrides);
|
|
|
|
for (unsigned i = 0, e = overrides.size(); i != e; ++i) {
|
|
|
|
if (const ObjCMethodDecl *result =
|
|
|
|
findExplicitInstancetypeDeclarer(overrides[i], instancetype))
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Sema::EmitRelatedResultTypeNoteForReturn(QualType destType) {
|
|
|
|
// Only complain if we're in an ObjC method and the required return
|
|
|
|
// type doesn't match the method's declared return type.
|
|
|
|
ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(CurContext);
|
|
|
|
if (!MD || !MD->hasRelatedResultType() ||
|
|
|
|
Context.hasSameUnqualifiedType(destType, MD->getResultType()))
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Look for a method overridden by this method which explicitly uses
|
|
|
|
// 'instancetype'.
|
|
|
|
if (const ObjCMethodDecl *overridden =
|
|
|
|
findExplicitInstancetypeDeclarer(MD, Context.getObjCInstanceType())) {
|
|
|
|
SourceLocation loc;
|
|
|
|
SourceRange range;
|
|
|
|
if (TypeSourceInfo *TSI = overridden->getResultTypeSourceInfo()) {
|
|
|
|
range = TSI->getTypeLoc().getSourceRange();
|
|
|
|
loc = range.getBegin();
|
|
|
|
}
|
|
|
|
if (loc.isInvalid())
|
|
|
|
loc = overridden->getLocation();
|
|
|
|
Diag(loc, diag::note_related_result_type_explicit)
|
|
|
|
<< /*current method*/ 1 << range;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Otherwise, if we have an interesting method family, note that.
|
|
|
|
// This should always trigger if the above didn't.
|
|
|
|
if (ObjCMethodFamily family = MD->getMethodFamily())
|
|
|
|
Diag(MD->getLocation(), diag::note_related_result_type_family)
|
|
|
|
<< /*current method*/ 1
|
|
|
|
<< family;
|
|
|
|
}
|
|
|
|
|
2011-06-11 09:09:30 +08:00
|
|
|
void Sema::EmitRelatedResultTypeNote(const Expr *E) {
|
|
|
|
E = E->IgnoreParenImpCasts();
|
|
|
|
const ObjCMessageExpr *MsgSend = dyn_cast<ObjCMessageExpr>(E);
|
|
|
|
if (!MsgSend)
|
|
|
|
return;
|
|
|
|
|
|
|
|
const ObjCMethodDecl *Method = MsgSend->getMethodDecl();
|
|
|
|
if (!Method)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (!Method->hasRelatedResultType())
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (Context.hasSameUnqualifiedType(Method->getResultType()
|
|
|
|
.getNonReferenceType(),
|
|
|
|
MsgSend->getType()))
|
|
|
|
return;
|
|
|
|
|
2011-09-08 09:46:34 +08:00
|
|
|
if (!Context.hasSameUnqualifiedType(Method->getResultType(),
|
|
|
|
Context.getObjCInstanceType()))
|
|
|
|
return;
|
|
|
|
|
2011-06-11 09:09:30 +08:00
|
|
|
Diag(Method->getLocation(), diag::note_related_result_type_inferred)
|
|
|
|
<< Method->isInstanceMethod() << Method->getSelector()
|
|
|
|
<< MsgSend->getType();
|
|
|
|
}
|
2011-02-03 17:00:02 +08:00
|
|
|
|
2011-06-11 09:09:30 +08:00
|
|
|
bool Sema::CheckMessageArgumentTypes(QualType ReceiverType,
|
2013-05-10 08:27:15 +08:00
|
|
|
MultiExprArg Args,
|
|
|
|
Selector Sel,
|
2012-09-01 01:03:18 +08:00
|
|
|
ArrayRef<SourceLocation> SelectorLocs,
|
|
|
|
ObjCMethodDecl *Method,
|
2011-06-11 09:09:30 +08:00
|
|
|
bool isClassMessage, bool isSuperMessage,
|
2008-09-11 08:01:56 +08:00
|
|
|
SourceLocation lbrac, SourceLocation rbrac,
|
2010-11-18 14:31:45 +08:00
|
|
|
QualType &ReturnType, ExprValueKind &VK) {
|
2013-05-01 08:24:09 +08:00
|
|
|
SourceLocation SelLoc;
|
|
|
|
if (!SelectorLocs.empty() && SelectorLocs.front().isValid())
|
|
|
|
SelLoc = SelectorLocs.front();
|
|
|
|
else
|
|
|
|
SelLoc = lbrac;
|
|
|
|
|
2008-09-11 08:01:56 +08:00
|
|
|
if (!Method) {
|
2008-09-11 08:04:36 +08:00
|
|
|
// Apply default argument promotion as for (C99 6.5.2.2p6).
|
2013-05-10 08:27:15 +08:00
|
|
|
for (unsigned i = 0, e = Args.size(); i != e; i++) {
|
2010-04-23 00:44:27 +08:00
|
|
|
if (Args[i]->isTypeDependent())
|
|
|
|
continue;
|
|
|
|
|
2013-03-04 15:34:02 +08:00
|
|
|
ExprResult result;
|
|
|
|
if (getLangOpts().DebuggerSupport) {
|
|
|
|
QualType paramTy; // ignored
|
2013-05-01 08:24:09 +08:00
|
|
|
result = checkUnknownAnyArg(SelLoc, Args[i], paramTy);
|
2013-03-04 15:34:02 +08:00
|
|
|
} else {
|
|
|
|
result = DefaultArgumentPromotion(Args[i]);
|
|
|
|
}
|
|
|
|
if (result.isInvalid())
|
2011-04-09 02:41:53 +08:00
|
|
|
return true;
|
2013-03-04 15:34:02 +08:00
|
|
|
Args[i] = result.take();
|
2010-04-23 00:44:27 +08:00
|
|
|
}
|
2008-09-11 08:04:36 +08:00
|
|
|
|
2011-06-16 07:02:42 +08:00
|
|
|
unsigned DiagID;
|
2012-03-11 15:00:24 +08:00
|
|
|
if (getLangOpts().ObjCAutoRefCount)
|
2011-06-16 07:02:42 +08:00
|
|
|
DiagID = diag::err_arc_method_not_found;
|
|
|
|
else
|
|
|
|
DiagID = isClassMessage ? diag::warn_class_method_not_found
|
|
|
|
: diag::warn_inst_method_not_found;
|
2013-05-15 07:24:17 +08:00
|
|
|
if (!getLangOpts().DebuggerSupport) {
|
2013-06-18 23:31:36 +08:00
|
|
|
const ObjCMethodDecl *OMD = SelectorsForTypoCorrection(Sel, ReceiverType);
|
2013-06-19 01:10:58 +08:00
|
|
|
if (OMD && !OMD->isInvalidDecl()) {
|
2013-06-18 23:31:36 +08:00
|
|
|
if (getLangOpts().ObjCAutoRefCount)
|
|
|
|
DiagID = diag::error_method_not_found_with_typo;
|
|
|
|
else
|
|
|
|
DiagID = isClassMessage ? diag::warn_class_method_not_found_with_typo
|
|
|
|
: diag::warn_instance_method_not_found_with_typo;
|
2013-06-18 01:10:54 +08:00
|
|
|
Selector MatchedSel = OMD->getSelector();
|
|
|
|
SourceRange SelectorRange(SelectorLocs.front(), SelectorLocs.back());
|
2013-06-18 23:31:36 +08:00
|
|
|
Diag(SelLoc, DiagID)
|
|
|
|
<< Sel<< isClassMessage << MatchedSel
|
2013-06-18 01:10:54 +08:00
|
|
|
<< FixItHint::CreateReplacement(SelectorRange, MatchedSel.getAsString());
|
|
|
|
}
|
|
|
|
else
|
|
|
|
Diag(SelLoc, DiagID)
|
|
|
|
<< Sel << isClassMessage << SourceRange(SelectorLocs.front(),
|
2012-09-01 01:03:18 +08:00
|
|
|
SelectorLocs.back());
|
2013-05-15 07:24:17 +08:00
|
|
|
// Find the class to which we are sending this message.
|
|
|
|
if (ReceiverType->isObjCObjectPointerType()) {
|
2013-05-15 23:27:35 +08:00
|
|
|
if (ObjCInterfaceDecl *Class =
|
|
|
|
ReceiverType->getAs<ObjCObjectPointerType>()->getInterfaceDecl())
|
|
|
|
Diag(Class->getLocation(), diag::note_receiver_class_declared);
|
2013-05-15 07:24:17 +08:00
|
|
|
}
|
|
|
|
}
|
2011-07-14 01:56:40 +08:00
|
|
|
|
|
|
|
// In debuggers, we want to use __unknown_anytype for these
|
|
|
|
// results so that clients can cast them.
|
2012-03-11 15:00:24 +08:00
|
|
|
if (getLangOpts().DebuggerSupport) {
|
2011-07-14 01:56:40 +08:00
|
|
|
ReturnType = Context.UnknownAnyTy;
|
|
|
|
} else {
|
|
|
|
ReturnType = Context.getObjCIdType();
|
|
|
|
}
|
2010-11-18 14:31:45 +08:00
|
|
|
VK = VK_RValue;
|
2008-09-11 08:01:56 +08:00
|
|
|
return false;
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-06-11 09:09:30 +08:00
|
|
|
ReturnType = getMessageSendResultType(ReceiverType, Method, isClassMessage,
|
|
|
|
isSuperMessage);
|
2010-11-18 14:31:45 +08:00
|
|
|
VK = Expr::getValueKindForType(Method->getResultType());
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-09-11 08:50:25 +08:00
|
|
|
unsigned NumNamedArgs = Sel.getNumArgs();
|
2010-04-08 08:30:06 +08:00
|
|
|
// Method might have more arguments than selector indicates. This is due
|
|
|
|
// to addition of c-style arguments in method.
|
|
|
|
if (Method->param_size() > Sel.getNumArgs())
|
|
|
|
NumNamedArgs = Method->param_size();
|
|
|
|
// FIXME. This need be cleaned up.
|
2013-05-10 08:27:15 +08:00
|
|
|
if (Args.size() < NumNamedArgs) {
|
2013-05-01 08:24:09 +08:00
|
|
|
Diag(SelLoc, diag::err_typecheck_call_too_few_args)
|
2013-05-10 08:27:15 +08:00
|
|
|
<< 2 << NumNamedArgs << static_cast<unsigned>(Args.size());
|
2010-04-08 08:30:06 +08:00
|
|
|
return false;
|
|
|
|
}
|
2008-09-11 08:50:25 +08:00
|
|
|
|
2009-04-12 16:11:20 +08:00
|
|
|
bool IsError = false;
|
2008-09-11 08:50:25 +08:00
|
|
|
for (unsigned i = 0; i < NumNamedArgs; i++) {
|
2010-04-23 00:44:27 +08:00
|
|
|
// We can't do any type-checking on a type-dependent argument.
|
|
|
|
if (Args[i]->isTypeDependent())
|
|
|
|
continue;
|
|
|
|
|
2008-01-05 06:32:30 +08:00
|
|
|
Expr *argExpr = Args[i];
|
2010-04-23 00:44:27 +08:00
|
|
|
|
2011-10-18 02:40:02 +08:00
|
|
|
ParmVarDecl *param = Method->param_begin()[i];
|
2008-01-05 06:32:30 +08:00
|
|
|
assert(argExpr && "CheckMessageArgumentTypes(): missing expression");
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-10-18 02:40:02 +08:00
|
|
|
// Strip the unbridged-cast placeholder expression off unless it's
|
|
|
|
// a consumed argument.
|
|
|
|
if (argExpr->hasPlaceholderType(BuiltinType::ARCUnbridgedCast) &&
|
|
|
|
!param->hasAttr<CFConsumedAttr>())
|
|
|
|
argExpr = stripARCUnbridgedCast(argExpr);
|
|
|
|
|
2012-11-14 08:49:39 +08:00
|
|
|
// If the parameter is __unknown_anytype, infer its type
|
|
|
|
// from the argument.
|
|
|
|
if (param->getType() == Context.UnknownAnyTy) {
|
2013-03-04 15:34:02 +08:00
|
|
|
QualType paramType;
|
2013-05-01 08:24:09 +08:00
|
|
|
ExprResult argE = checkUnknownAnyArg(SelLoc, argExpr, paramType);
|
2013-03-04 15:34:02 +08:00
|
|
|
if (argE.isInvalid()) {
|
2012-11-14 08:49:39 +08:00
|
|
|
IsError = true;
|
2013-03-04 15:34:02 +08:00
|
|
|
} else {
|
|
|
|
Args[i] = argE.take();
|
2012-11-14 08:49:39 +08:00
|
|
|
|
2013-03-04 15:34:02 +08:00
|
|
|
// Update the parameter type in-place.
|
|
|
|
param->setType(paramType);
|
|
|
|
}
|
|
|
|
continue;
|
2012-11-14 08:49:39 +08:00
|
|
|
}
|
|
|
|
|
2010-04-22 07:24:10 +08:00
|
|
|
if (RequireCompleteType(argExpr->getSourceRange().getBegin(),
|
2011-10-18 02:40:02 +08:00
|
|
|
param->getType(),
|
2012-05-05 00:32:21 +08:00
|
|
|
diag::err_call_incomplete_argument, argExpr))
|
2010-04-22 07:24:10 +08:00
|
|
|
return true;
|
|
|
|
|
2010-09-25 01:30:16 +08:00
|
|
|
InitializedEntity Entity = InitializedEntity::InitializeParameter(Context,
|
2011-10-18 02:40:02 +08:00
|
|
|
param);
|
2013-05-01 08:24:09 +08:00
|
|
|
ExprResult ArgE = PerformCopyInitialization(Entity, SelLoc, Owned(argExpr));
|
2010-04-22 07:24:10 +08:00
|
|
|
if (ArgE.isInvalid())
|
|
|
|
IsError = true;
|
|
|
|
else
|
|
|
|
Args[i] = ArgE.takeAs<Expr>();
|
2008-01-05 06:32:30 +08:00
|
|
|
}
|
2008-09-11 08:50:25 +08:00
|
|
|
|
|
|
|
// Promote additional arguments to variadic methods.
|
|
|
|
if (Method->isVariadic()) {
|
2013-05-10 08:27:15 +08:00
|
|
|
for (unsigned i = NumNamedArgs, e = Args.size(); i < e; ++i) {
|
2010-04-23 00:44:27 +08:00
|
|
|
if (Args[i]->isTypeDependent())
|
|
|
|
continue;
|
|
|
|
|
2012-05-13 01:32:52 +08:00
|
|
|
ExprResult Arg = DefaultVariadicArgumentPromotion(Args[i], VariadicMethod,
|
|
|
|
0);
|
2011-04-09 02:41:53 +08:00
|
|
|
IsError |= Arg.isInvalid();
|
|
|
|
Args[i] = Arg.take();
|
2010-04-23 00:44:27 +08:00
|
|
|
}
|
2008-09-11 08:50:25 +08:00
|
|
|
} else {
|
|
|
|
// Check for extra arguments to non-variadic methods.
|
2013-05-10 08:27:15 +08:00
|
|
|
if (Args.size() != NumNamedArgs) {
|
2009-09-09 23:08:12 +08:00
|
|
|
Diag(Args[NumNamedArgs]->getLocStart(),
|
2008-11-19 13:08:23 +08:00
|
|
|
diag::err_typecheck_call_too_many_args)
|
2013-05-10 08:27:15 +08:00
|
|
|
<< 2 /*method*/ << NumNamedArgs << static_cast<unsigned>(Args.size())
|
2010-04-16 12:56:46 +08:00
|
|
|
<< Method->getSourceRange()
|
2008-11-19 13:08:23 +08:00
|
|
|
<< SourceRange(Args[NumNamedArgs]->getLocStart(),
|
2013-05-10 08:27:15 +08:00
|
|
|
Args.back()->getLocEnd());
|
2008-09-11 08:50:25 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-05-10 08:27:15 +08:00
|
|
|
DiagnoseSentinelCalls(Method, SelLoc, Args);
|
2012-01-18 04:03:31 +08:00
|
|
|
|
|
|
|
// Do additional checkings on method.
|
2013-05-10 08:27:15 +08:00
|
|
|
IsError |= CheckObjCMethodCall(
|
2013-08-19 15:57:02 +08:00
|
|
|
Method, SelLoc, makeArrayRef<const Expr *>(Args.data(), Args.size()));
|
2012-01-18 04:03:31 +08:00
|
|
|
|
2009-04-12 16:11:20 +08:00
|
|
|
return IsError;
|
2008-01-05 06:32:30 +08:00
|
|
|
}
|
|
|
|
|
2011-09-28 00:10:05 +08:00
|
|
|
bool Sema::isSelfExpr(Expr *receiver) {
|
2011-03-28 03:53:47 +08:00
|
|
|
// 'self' is objc 'self' in an objc method only.
|
2011-11-06 17:01:30 +08:00
|
|
|
ObjCMethodDecl *method =
|
2013-05-03 15:33:41 +08:00
|
|
|
dyn_cast_or_null<ObjCMethodDecl>(CurContext->getNonClosureAncestor());
|
2011-11-06 17:01:30 +08:00
|
|
|
if (!method) return false;
|
|
|
|
|
2011-06-16 07:02:42 +08:00
|
|
|
receiver = receiver->IgnoreParenLValueCasts();
|
|
|
|
if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(receiver))
|
2011-11-06 17:01:30 +08:00
|
|
|
if (DRE->getDecl() == method->getSelfDecl())
|
2011-09-28 00:10:05 +08:00
|
|
|
return true;
|
|
|
|
return false;
|
2009-03-04 23:11:40 +08:00
|
|
|
}
|
|
|
|
|
2011-10-26 01:37:35 +08:00
|
|
|
/// LookupMethodInType - Look up a method in an ObjCObjectType.
|
|
|
|
ObjCMethodDecl *Sema::LookupMethodInObjectType(Selector sel, QualType type,
|
|
|
|
bool isInstance) {
|
|
|
|
const ObjCObjectType *objType = type->castAs<ObjCObjectType>();
|
|
|
|
if (ObjCInterfaceDecl *iface = objType->getInterface()) {
|
|
|
|
// Look it up in the main interface (and categories, etc.)
|
|
|
|
if (ObjCMethodDecl *method = iface->lookupMethod(sel, isInstance))
|
|
|
|
return method;
|
|
|
|
|
|
|
|
// Okay, look for "private" methods declared in any
|
|
|
|
// @implementations we've seen.
|
2012-07-28 03:07:44 +08:00
|
|
|
if (ObjCMethodDecl *method = iface->lookupPrivateMethod(sel, isInstance))
|
|
|
|
return method;
|
2011-10-26 01:37:35 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Check qualifiers.
|
|
|
|
for (ObjCObjectType::qual_iterator
|
|
|
|
i = objType->qual_begin(), e = objType->qual_end(); i != e; ++i)
|
|
|
|
if (ObjCMethodDecl *method = (*i)->lookupMethod(sel, isInstance))
|
|
|
|
return method;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-03-10 04:18:06 +08:00
|
|
|
/// LookupMethodInQualifiedType - Lookups up a method in protocol qualifier
|
|
|
|
/// list of a qualified objective pointer type.
|
|
|
|
ObjCMethodDecl *Sema::LookupMethodInQualifiedType(Selector Sel,
|
|
|
|
const ObjCObjectPointerType *OPT,
|
|
|
|
bool Instance)
|
|
|
|
{
|
|
|
|
ObjCMethodDecl *MD = 0;
|
|
|
|
for (ObjCObjectPointerType::qual_iterator I = OPT->qual_begin(),
|
|
|
|
E = OPT->qual_end(); I != E; ++I) {
|
|
|
|
ObjCProtocolDecl *PROTO = (*I);
|
|
|
|
if ((MD = PROTO->lookupMethod(Sel, Instance))) {
|
|
|
|
return MD;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-04-20 07:49:39 +08:00
|
|
|
static void DiagnoseARCUseOfWeakReceiver(Sema &S, Expr *Receiver) {
|
|
|
|
if (!Receiver)
|
2012-04-20 05:44:57 +08:00
|
|
|
return;
|
|
|
|
|
2012-06-05 03:16:34 +08:00
|
|
|
if (OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(Receiver))
|
|
|
|
Receiver = OVE->getSourceExpr();
|
|
|
|
|
2012-04-20 07:49:39 +08:00
|
|
|
Expr *RExpr = Receiver->IgnoreParenImpCasts();
|
|
|
|
SourceLocation Loc = RExpr->getLocStart();
|
|
|
|
QualType T = RExpr->getType();
|
2012-10-11 00:42:54 +08:00
|
|
|
const ObjCPropertyDecl *PDecl = 0;
|
|
|
|
const ObjCMethodDecl *GDecl = 0;
|
2012-04-20 07:49:39 +08:00
|
|
|
if (PseudoObjectExpr *POE = dyn_cast<PseudoObjectExpr>(RExpr)) {
|
|
|
|
RExpr = POE->getSyntacticForm();
|
|
|
|
if (ObjCPropertyRefExpr *PRE = dyn_cast<ObjCPropertyRefExpr>(RExpr)) {
|
|
|
|
if (PRE->isImplicitProperty()) {
|
|
|
|
GDecl = PRE->getImplicitPropertyGetter();
|
|
|
|
if (GDecl) {
|
|
|
|
T = GDecl->getResultType();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
PDecl = PRE->getExplicitProperty();
|
|
|
|
if (PDecl) {
|
|
|
|
T = PDecl->getType();
|
|
|
|
}
|
|
|
|
}
|
2012-04-20 05:44:57 +08:00
|
|
|
}
|
2012-04-20 07:49:39 +08:00
|
|
|
}
|
2012-06-05 03:16:34 +08:00
|
|
|
else if (ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(RExpr)) {
|
|
|
|
// See if receiver is a method which envokes a synthesized getter
|
|
|
|
// backing a 'weak' property.
|
|
|
|
ObjCMethodDecl *Method = ME->getMethodDecl();
|
2012-10-11 00:42:54 +08:00
|
|
|
if (Method && Method->getSelector().getNumArgs() == 0) {
|
|
|
|
PDecl = Method->findPropertyDecl();
|
2012-06-05 03:16:34 +08:00
|
|
|
if (PDecl)
|
|
|
|
T = PDecl->getType();
|
|
|
|
}
|
|
|
|
}
|
2012-04-20 07:49:39 +08:00
|
|
|
|
2012-09-29 06:21:42 +08:00
|
|
|
if (T.getObjCLifetime() != Qualifiers::OCL_Weak) {
|
|
|
|
if (!PDecl)
|
|
|
|
return;
|
|
|
|
if (!(PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_weak))
|
|
|
|
return;
|
2012-04-20 05:44:57 +08:00
|
|
|
}
|
2012-09-29 06:21:42 +08:00
|
|
|
|
|
|
|
S.Diag(Loc, diag::warn_receiver_is_weak)
|
|
|
|
<< ((!PDecl && !GDecl) ? 0 : (PDecl ? 1 : 2));
|
|
|
|
|
|
|
|
if (PDecl)
|
2012-04-20 07:49:39 +08:00
|
|
|
S.Diag(PDecl->getLocation(), diag::note_property_declare);
|
2012-09-29 06:21:42 +08:00
|
|
|
else if (GDecl)
|
|
|
|
S.Diag(GDecl->getLocation(), diag::note_method_declared_at) << GDecl;
|
|
|
|
|
|
|
|
S.Diag(Loc, diag::note_arc_assign_to_strong);
|
2012-04-20 05:44:57 +08:00
|
|
|
}
|
|
|
|
|
2010-04-11 15:45:24 +08:00
|
|
|
/// HandleExprPropertyRefExpr - Handle foo.bar where foo is a pointer to an
|
|
|
|
/// objective C interface. This is a property reference expression.
|
2010-08-24 14:29:42 +08:00
|
|
|
ExprResult Sema::
|
2010-04-11 15:45:24 +08:00
|
|
|
HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT,
|
2011-06-28 08:00:52 +08:00
|
|
|
Expr *BaseExpr, SourceLocation OpLoc,
|
|
|
|
DeclarationName MemberName,
|
2010-10-15 00:04:05 +08:00
|
|
|
SourceLocation MemberLoc,
|
|
|
|
SourceLocation SuperLoc, QualType SuperType,
|
|
|
|
bool Super) {
|
2010-04-11 15:45:24 +08:00
|
|
|
const ObjCInterfaceType *IFaceT = OPT->getInterfaceType();
|
|
|
|
ObjCInterfaceDecl *IFace = IFaceT->getDecl();
|
2012-05-20 00:03:58 +08:00
|
|
|
|
2012-05-20 00:34:46 +08:00
|
|
|
if (!MemberName.isIdentifier()) {
|
2011-04-21 02:19:55 +08:00
|
|
|
Diag(MemberLoc, diag::err_invalid_property_name)
|
|
|
|
<< MemberName << QualType(OPT, 0);
|
|
|
|
return ExprError();
|
|
|
|
}
|
2012-05-20 00:34:46 +08:00
|
|
|
|
|
|
|
IdentifierInfo *Member = MemberName.getAsIdentifierInfo();
|
2011-04-21 02:19:55 +08:00
|
|
|
|
2011-11-15 06:10:01 +08:00
|
|
|
SourceRange BaseRange = Super? SourceRange(SuperLoc)
|
|
|
|
: BaseExpr->getSourceRange();
|
|
|
|
if (RequireCompleteType(MemberLoc, OPT->getPointeeType(),
|
2012-05-05 00:32:21 +08:00
|
|
|
diag::err_property_not_found_forward_class,
|
|
|
|
MemberName, BaseRange))
|
2010-12-16 08:56:28 +08:00
|
|
|
return ExprError();
|
2011-11-15 06:10:01 +08:00
|
|
|
|
2010-04-11 15:45:24 +08:00
|
|
|
// Search for a declared property first.
|
2012-05-25 06:48:38 +08:00
|
|
|
if (ObjCPropertyDecl *PD = IFace->FindPropertyDeclaration(Member)) {
|
2010-04-11 15:45:24 +08:00
|
|
|
// Check whether we can reference this property.
|
|
|
|
if (DiagnoseUseOfDecl(PD, MemberLoc))
|
|
|
|
return ExprError();
|
2010-10-15 00:04:05 +08:00
|
|
|
if (Super)
|
2011-10-26 01:37:35 +08:00
|
|
|
return Owned(new (Context) ObjCPropertyRefExpr(PD, Context.PseudoObjectTy,
|
2010-11-18 14:31:45 +08:00
|
|
|
VK_LValue, OK_ObjCProperty,
|
2010-10-15 00:04:05 +08:00
|
|
|
MemberLoc,
|
|
|
|
SuperLoc, SuperType));
|
|
|
|
else
|
2011-10-26 01:37:35 +08:00
|
|
|
return Owned(new (Context) ObjCPropertyRefExpr(PD, Context.PseudoObjectTy,
|
2010-11-18 14:31:45 +08:00
|
|
|
VK_LValue, OK_ObjCProperty,
|
2010-10-15 00:04:05 +08:00
|
|
|
MemberLoc, BaseExpr));
|
2010-04-11 15:45:24 +08:00
|
|
|
}
|
|
|
|
// Check protocols on qualified interfaces.
|
|
|
|
for (ObjCObjectPointerType::qual_iterator I = OPT->qual_begin(),
|
|
|
|
E = OPT->qual_end(); I != E; ++I)
|
|
|
|
if (ObjCPropertyDecl *PD = (*I)->FindPropertyDeclaration(Member)) {
|
|
|
|
// Check whether we can reference this property.
|
|
|
|
if (DiagnoseUseOfDecl(PD, MemberLoc))
|
|
|
|
return ExprError();
|
2012-04-20 05:44:57 +08:00
|
|
|
|
2010-10-15 00:04:05 +08:00
|
|
|
if (Super)
|
2011-10-26 01:37:35 +08:00
|
|
|
return Owned(new (Context) ObjCPropertyRefExpr(PD,
|
|
|
|
Context.PseudoObjectTy,
|
2010-11-18 14:31:45 +08:00
|
|
|
VK_LValue,
|
|
|
|
OK_ObjCProperty,
|
|
|
|
MemberLoc,
|
|
|
|
SuperLoc, SuperType));
|
2010-10-15 00:04:05 +08:00
|
|
|
else
|
2011-10-26 01:37:35 +08:00
|
|
|
return Owned(new (Context) ObjCPropertyRefExpr(PD,
|
|
|
|
Context.PseudoObjectTy,
|
2010-11-18 14:31:45 +08:00
|
|
|
VK_LValue,
|
|
|
|
OK_ObjCProperty,
|
2010-10-15 00:04:05 +08:00
|
|
|
MemberLoc,
|
|
|
|
BaseExpr));
|
2010-04-11 15:45:24 +08:00
|
|
|
}
|
|
|
|
// If that failed, look for an "implicit" property by seeing if the nullary
|
|
|
|
// selector is implemented.
|
|
|
|
|
|
|
|
// FIXME: The logic for looking up nullary and unary selectors should be
|
|
|
|
// shared with the code in ActOnInstanceMessage.
|
|
|
|
|
|
|
|
Selector Sel = PP.getSelectorTable().getNullarySelector(Member);
|
|
|
|
ObjCMethodDecl *Getter = IFace->lookupInstanceMethod(Sel);
|
2011-03-10 06:17:12 +08:00
|
|
|
|
|
|
|
// May be founf in property's qualified list.
|
|
|
|
if (!Getter)
|
|
|
|
Getter = LookupMethodInQualifiedType(Sel, OPT, true);
|
2010-04-11 15:45:24 +08:00
|
|
|
|
|
|
|
// If this reference is in an @implementation, check for 'private' methods.
|
|
|
|
if (!Getter)
|
2010-12-04 07:37:08 +08:00
|
|
|
Getter = IFace->lookupPrivateMethod(Sel);
|
2010-04-11 15:45:24 +08:00
|
|
|
|
|
|
|
if (Getter) {
|
|
|
|
// Check if we can reference this property.
|
|
|
|
if (DiagnoseUseOfDecl(Getter, MemberLoc))
|
|
|
|
return ExprError();
|
|
|
|
}
|
|
|
|
// If we found a getter then this may be a valid dot-reference, we
|
|
|
|
// will look for the matching setter, in case it is needed.
|
|
|
|
Selector SetterSel =
|
2013-06-08 06:29:12 +08:00
|
|
|
SelectorTable::constructSetterSelector(PP.getIdentifierTable(),
|
|
|
|
PP.getSelectorTable(), Member);
|
2010-04-11 15:45:24 +08:00
|
|
|
ObjCMethodDecl *Setter = IFace->lookupInstanceMethod(SetterSel);
|
2012-05-25 06:48:38 +08:00
|
|
|
|
2011-03-10 06:17:12 +08:00
|
|
|
// May be founf in property's qualified list.
|
|
|
|
if (!Setter)
|
|
|
|
Setter = LookupMethodInQualifiedType(SetterSel, OPT, true);
|
|
|
|
|
2010-04-11 15:45:24 +08:00
|
|
|
if (!Setter) {
|
|
|
|
// If this reference is in an @implementation, also check for 'private'
|
|
|
|
// methods.
|
2010-12-04 07:37:08 +08:00
|
|
|
Setter = IFace->lookupPrivateMethod(SetterSel);
|
2010-04-11 15:45:24 +08:00
|
|
|
}
|
2011-03-10 06:17:12 +08:00
|
|
|
|
2010-04-11 15:45:24 +08:00
|
|
|
if (Setter && DiagnoseUseOfDecl(Setter, MemberLoc))
|
|
|
|
return ExprError();
|
|
|
|
|
2010-12-23 03:46:35 +08:00
|
|
|
if (Getter || Setter) {
|
2010-10-15 00:04:05 +08:00
|
|
|
if (Super)
|
2010-12-02 09:19:52 +08:00
|
|
|
return Owned(new (Context) ObjCPropertyRefExpr(Getter, Setter,
|
2011-10-26 01:37:35 +08:00
|
|
|
Context.PseudoObjectTy,
|
|
|
|
VK_LValue, OK_ObjCProperty,
|
2010-12-02 09:19:52 +08:00
|
|
|
MemberLoc,
|
|
|
|
SuperLoc, SuperType));
|
2010-10-15 00:04:05 +08:00
|
|
|
else
|
2010-12-02 09:19:52 +08:00
|
|
|
return Owned(new (Context) ObjCPropertyRefExpr(Getter, Setter,
|
2011-10-26 01:37:35 +08:00
|
|
|
Context.PseudoObjectTy,
|
|
|
|
VK_LValue, OK_ObjCProperty,
|
2010-12-02 09:19:52 +08:00
|
|
|
MemberLoc, BaseExpr));
|
2010-10-15 00:04:05 +08:00
|
|
|
|
2010-04-11 15:45:24 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Attempt to correct for typos in property names.
|
2012-01-13 09:32:50 +08:00
|
|
|
DeclFilterCCC<ObjCPropertyDecl> Validator;
|
|
|
|
if (TypoCorrection Corrected = CorrectTypo(
|
2013-08-17 08:46:16 +08:00
|
|
|
DeclarationNameInfo(MemberName, MemberLoc), LookupOrdinaryName, NULL,
|
|
|
|
NULL, Validator, IFace, false, OPT)) {
|
|
|
|
diagnoseTypo(Corrected, PDiag(diag::err_property_not_found_suggest)
|
|
|
|
<< MemberName << QualType(OPT, 0));
|
2011-06-29 00:20:02 +08:00
|
|
|
DeclarationName TypoResult = Corrected.getCorrection();
|
2011-06-28 08:00:52 +08:00
|
|
|
return HandleExprPropertyRefExpr(OPT, BaseExpr, OpLoc,
|
|
|
|
TypoResult, MemberLoc,
|
2010-10-15 00:04:05 +08:00
|
|
|
SuperLoc, SuperType, Super);
|
2010-04-11 15:45:24 +08:00
|
|
|
}
|
2011-02-17 09:26:14 +08:00
|
|
|
ObjCInterfaceDecl *ClassDeclared;
|
|
|
|
if (ObjCIvarDecl *Ivar =
|
|
|
|
IFace->lookupInstanceVariable(Member, ClassDeclared)) {
|
|
|
|
QualType T = Ivar->getType();
|
|
|
|
if (const ObjCObjectPointerType * OBJPT =
|
|
|
|
T->getAsObjCInterfacePointerType()) {
|
2011-11-15 06:10:01 +08:00
|
|
|
if (RequireCompleteType(MemberLoc, OBJPT->getPointeeType(),
|
2012-05-05 00:32:21 +08:00
|
|
|
diag::err_property_not_as_forward_class,
|
|
|
|
MemberName, BaseExpr))
|
2011-11-15 06:10:01 +08:00
|
|
|
return ExprError();
|
2011-02-17 09:26:14 +08:00
|
|
|
}
|
2011-06-28 08:00:52 +08:00
|
|
|
Diag(MemberLoc,
|
|
|
|
diag::err_ivar_access_using_property_syntax_suggest)
|
|
|
|
<< MemberName << QualType(OPT, 0) << Ivar->getDeclName()
|
|
|
|
<< FixItHint::CreateReplacement(OpLoc, "->");
|
|
|
|
return ExprError();
|
2011-02-17 09:26:14 +08:00
|
|
|
}
|
2010-04-11 15:51:10 +08:00
|
|
|
|
2010-04-11 15:45:24 +08:00
|
|
|
Diag(MemberLoc, diag::err_property_not_found)
|
|
|
|
<< MemberName << QualType(OPT, 0);
|
2010-12-23 03:46:35 +08:00
|
|
|
if (Setter)
|
2010-04-11 15:45:24 +08:00
|
|
|
Diag(Setter->getLocation(), diag::note_getter_unavailable)
|
2010-12-23 03:46:35 +08:00
|
|
|
<< MemberName << BaseExpr->getSourceRange();
|
2010-04-11 15:45:24 +08:00
|
|
|
return ExprError();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2010-08-24 14:29:42 +08:00
|
|
|
ExprResult Sema::
|
2010-04-11 16:28:14 +08:00
|
|
|
ActOnClassPropertyRefExpr(IdentifierInfo &receiverName,
|
|
|
|
IdentifierInfo &propertyName,
|
|
|
|
SourceLocation receiverNameLoc,
|
|
|
|
SourceLocation propertyNameLoc) {
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-01-04 02:01:57 +08:00
|
|
|
IdentifierInfo *receiverNamePtr = &receiverName;
|
2010-04-16 06:33:43 +08:00
|
|
|
ObjCInterfaceDecl *IFace = getObjCInterfaceDecl(receiverNamePtr,
|
|
|
|
receiverNameLoc);
|
2011-06-11 09:09:30 +08:00
|
|
|
|
|
|
|
bool IsSuper = false;
|
2010-04-11 16:28:14 +08:00
|
|
|
if (IFace == 0) {
|
|
|
|
// If the "receiver" is 'super' in a method, handle it as an expression-like
|
|
|
|
// property reference.
|
2011-02-03 17:00:02 +08:00
|
|
|
if (receiverNamePtr->isStr("super")) {
|
2011-06-11 09:09:30 +08:00
|
|
|
IsSuper = true;
|
|
|
|
|
2012-02-04 06:47:37 +08:00
|
|
|
if (ObjCMethodDecl *CurMethod = tryCaptureObjCSelf(receiverNameLoc)) {
|
2010-04-11 16:28:14 +08:00
|
|
|
if (CurMethod->isInstanceMethod()) {
|
2013-03-12 06:26:33 +08:00
|
|
|
ObjCInterfaceDecl *Super =
|
|
|
|
CurMethod->getClassInterface()->getSuperClass();
|
|
|
|
if (!Super) {
|
|
|
|
// The current class does not have a superclass.
|
|
|
|
Diag(receiverNameLoc, diag::error_root_class_cannot_use_super)
|
|
|
|
<< CurMethod->getClassInterface()->getIdentifier();
|
|
|
|
return ExprError();
|
|
|
|
}
|
|
|
|
QualType T = Context.getObjCInterfaceType(Super);
|
2010-04-11 16:28:14 +08:00
|
|
|
T = Context.getObjCObjectPointerType(T);
|
|
|
|
|
|
|
|
return HandleExprPropertyRefExpr(T->getAsObjCInterfacePointerType(),
|
2011-06-28 08:00:52 +08:00
|
|
|
/*BaseExpr*/0,
|
|
|
|
SourceLocation()/*OpLoc*/,
|
|
|
|
&propertyName,
|
2010-10-15 00:04:05 +08:00
|
|
|
propertyNameLoc,
|
|
|
|
receiverNameLoc, T, true);
|
2010-04-11 16:28:14 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Otherwise, if this is a class method, try dispatching to our
|
|
|
|
// superclass.
|
|
|
|
IFace = CurMethod->getClassInterface()->getSuperClass();
|
|
|
|
}
|
2011-02-03 17:00:02 +08:00
|
|
|
}
|
2010-04-11 16:28:14 +08:00
|
|
|
|
|
|
|
if (IFace == 0) {
|
|
|
|
Diag(receiverNameLoc, diag::err_expected_ident_or_lparen);
|
|
|
|
return ExprError();
|
|
|
|
}
|
2010-03-23 05:02:34 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-04-11 16:28:14 +08:00
|
|
|
// Search for a declared property first.
|
2009-03-10 05:12:44 +08:00
|
|
|
Selector Sel = PP.getSelectorTable().getNullarySelector(&propertyName);
|
2009-06-30 10:36:12 +08:00
|
|
|
ObjCMethodDecl *Getter = IFace->lookupClassMethod(Sel);
|
2009-03-10 05:12:44 +08:00
|
|
|
|
|
|
|
// If this reference is in an @implementation, check for 'private' methods.
|
|
|
|
if (!Getter)
|
|
|
|
if (ObjCMethodDecl *CurMeth = getCurMethodDecl())
|
|
|
|
if (ObjCInterfaceDecl *ClassDecl = CurMeth->getClassInterface())
|
2009-07-21 08:06:04 +08:00
|
|
|
if (ObjCImplementationDecl *ImpDecl = ClassDecl->getImplementation())
|
2009-06-30 10:36:12 +08:00
|
|
|
Getter = ImpDecl->getClassMethod(Sel);
|
2009-03-10 05:12:44 +08:00
|
|
|
|
|
|
|
if (Getter) {
|
|
|
|
// FIXME: refactor/share with ActOnMemberReference().
|
|
|
|
// Check if we can reference this property.
|
|
|
|
if (DiagnoseUseOfDecl(Getter, propertyNameLoc))
|
|
|
|
return ExprError();
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-03-10 05:12:44 +08:00
|
|
|
// Look for the matching setter, in case it is needed.
|
2009-09-09 23:08:12 +08:00
|
|
|
Selector SetterSel =
|
2013-06-08 06:29:12 +08:00
|
|
|
SelectorTable::constructSetterSelector(PP.getIdentifierTable(),
|
|
|
|
PP.getSelectorTable(),
|
|
|
|
&propertyName);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-06-30 10:36:12 +08:00
|
|
|
ObjCMethodDecl *Setter = IFace->lookupClassMethod(SetterSel);
|
2009-03-10 05:12:44 +08:00
|
|
|
if (!Setter) {
|
|
|
|
// If this reference is in an @implementation, also check for 'private'
|
|
|
|
// methods.
|
|
|
|
if (ObjCMethodDecl *CurMeth = getCurMethodDecl())
|
|
|
|
if (ObjCInterfaceDecl *ClassDecl = CurMeth->getClassInterface())
|
2009-07-21 08:06:04 +08:00
|
|
|
if (ObjCImplementationDecl *ImpDecl = ClassDecl->getImplementation())
|
2009-06-30 10:36:12 +08:00
|
|
|
Setter = ImpDecl->getClassMethod(SetterSel);
|
2009-03-10 05:12:44 +08:00
|
|
|
}
|
|
|
|
// Look through local category implementations associated with the class.
|
2009-07-21 08:06:20 +08:00
|
|
|
if (!Setter)
|
|
|
|
Setter = IFace->getCategoryClassMethod(SetterSel);
|
2009-03-10 05:12:44 +08:00
|
|
|
|
|
|
|
if (Setter && DiagnoseUseOfDecl(Setter, propertyNameLoc))
|
|
|
|
return ExprError();
|
|
|
|
|
|
|
|
if (Getter || Setter) {
|
2011-06-11 09:09:30 +08:00
|
|
|
if (IsSuper)
|
|
|
|
return Owned(new (Context) ObjCPropertyRefExpr(Getter, Setter,
|
2011-10-26 01:37:35 +08:00
|
|
|
Context.PseudoObjectTy,
|
|
|
|
VK_LValue, OK_ObjCProperty,
|
2011-06-11 09:09:30 +08:00
|
|
|
propertyNameLoc,
|
|
|
|
receiverNameLoc,
|
|
|
|
Context.getObjCInterfaceType(IFace)));
|
|
|
|
|
2010-12-02 09:19:52 +08:00
|
|
|
return Owned(new (Context) ObjCPropertyRefExpr(Getter, Setter,
|
2011-10-26 01:37:35 +08:00
|
|
|
Context.PseudoObjectTy,
|
|
|
|
VK_LValue, OK_ObjCProperty,
|
2010-12-02 09:19:52 +08:00
|
|
|
propertyNameLoc,
|
|
|
|
receiverNameLoc, IFace));
|
2009-03-10 05:12:44 +08:00
|
|
|
}
|
|
|
|
return ExprError(Diag(propertyNameLoc, diag::err_property_not_found)
|
|
|
|
<< &propertyName << Context.getObjCInterfaceType(IFace));
|
|
|
|
}
|
|
|
|
|
2012-01-13 09:32:50 +08:00
|
|
|
namespace {
|
|
|
|
|
|
|
|
class ObjCInterfaceOrSuperCCC : public CorrectionCandidateCallback {
|
|
|
|
public:
|
|
|
|
ObjCInterfaceOrSuperCCC(ObjCMethodDecl *Method) {
|
|
|
|
// Determine whether "super" is acceptable in the current context.
|
|
|
|
if (Method && Method->getClassInterface())
|
|
|
|
WantObjCSuper = Method->getClassInterface()->getSuperClass();
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual bool ValidateCandidate(const TypoCorrection &candidate) {
|
|
|
|
return candidate.getCorrectionDeclAs<ObjCInterfaceDecl>() ||
|
|
|
|
candidate.isKeyword("super");
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2010-04-14 10:46:37 +08:00
|
|
|
Sema::ObjCMessageKind Sema::getObjCMessageKind(Scope *S,
|
2010-04-22 04:38:13 +08:00
|
|
|
IdentifierInfo *Name,
|
2010-04-14 10:46:37 +08:00
|
|
|
SourceLocation NameLoc,
|
|
|
|
bool IsSuper,
|
2010-04-22 04:38:13 +08:00
|
|
|
bool HasTrailingDot,
|
2010-08-24 13:47:05 +08:00
|
|
|
ParsedType &ReceiverType) {
|
|
|
|
ReceiverType = ParsedType();
|
2010-04-22 04:38:13 +08:00
|
|
|
|
2010-04-14 10:46:37 +08:00
|
|
|
// If the identifier is "super" and there is no trailing dot, we're
|
2010-10-15 06:11:03 +08:00
|
|
|
// messaging super. If the identifier is "super" and there is a
|
|
|
|
// trailing dot, it's an instance message.
|
|
|
|
if (IsSuper && S->isInObjcMethodScope())
|
|
|
|
return HasTrailingDot? ObjCInstanceMessage : ObjCSuperMessage;
|
2010-04-14 10:46:37 +08:00
|
|
|
|
|
|
|
LookupResult Result(*this, Name, NameLoc, LookupOrdinaryName);
|
|
|
|
LookupName(Result, S);
|
|
|
|
|
|
|
|
switch (Result.getResultKind()) {
|
|
|
|
case LookupResult::NotFound:
|
2010-04-20 04:09:36 +08:00
|
|
|
// Normal name lookup didn't find anything. If we're in an
|
|
|
|
// Objective-C method, look for ivars. If we find one, we're done!
|
2010-10-15 06:11:03 +08:00
|
|
|
// FIXME: This is a hack. Ivar lookup should be part of normal
|
|
|
|
// lookup.
|
2010-04-20 04:09:36 +08:00
|
|
|
if (ObjCMethodDecl *Method = getCurMethodDecl()) {
|
2011-11-09 08:22:48 +08:00
|
|
|
if (!Method->getClassInterface()) {
|
|
|
|
// Fall back: let the parser try to parse it as an instance message.
|
|
|
|
return ObjCInstanceMessage;
|
|
|
|
}
|
|
|
|
|
2010-04-20 04:09:36 +08:00
|
|
|
ObjCInterfaceDecl *ClassDeclared;
|
|
|
|
if (Method->getClassInterface()->lookupInstanceVariable(Name,
|
|
|
|
ClassDeclared))
|
|
|
|
return ObjCInstanceMessage;
|
|
|
|
}
|
2010-10-15 06:11:03 +08:00
|
|
|
|
2010-04-14 10:46:37 +08:00
|
|
|
// Break out; we'll perform typo correction below.
|
|
|
|
break;
|
|
|
|
|
|
|
|
case LookupResult::NotFoundInCurrentInstantiation:
|
|
|
|
case LookupResult::FoundOverloaded:
|
|
|
|
case LookupResult::FoundUnresolvedValue:
|
|
|
|
case LookupResult::Ambiguous:
|
|
|
|
Result.suppressDiagnostics();
|
|
|
|
return ObjCInstanceMessage;
|
|
|
|
|
|
|
|
case LookupResult::Found: {
|
2011-02-08 08:23:07 +08:00
|
|
|
// If the identifier is a class or not, and there is a trailing dot,
|
|
|
|
// it's an instance message.
|
|
|
|
if (HasTrailingDot)
|
|
|
|
return ObjCInstanceMessage;
|
2010-04-14 10:46:37 +08:00
|
|
|
// We found something. If it's a type, then we have a class
|
|
|
|
// message. Otherwise, it's an instance message.
|
|
|
|
NamedDecl *ND = Result.getFoundDecl();
|
2010-04-22 04:38:13 +08:00
|
|
|
QualType T;
|
|
|
|
if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(ND))
|
|
|
|
T = Context.getObjCInterfaceType(Class);
|
2013-04-05 02:45:52 +08:00
|
|
|
else if (TypeDecl *Type = dyn_cast<TypeDecl>(ND)) {
|
2010-04-22 04:38:13 +08:00
|
|
|
T = Context.getTypeDeclType(Type);
|
2013-04-05 02:45:52 +08:00
|
|
|
DiagnoseUseOfDecl(Type, NameLoc);
|
|
|
|
}
|
|
|
|
else
|
2010-04-22 04:38:13 +08:00
|
|
|
return ObjCInstanceMessage;
|
|
|
|
|
|
|
|
// We have a class message, and T is the type we're
|
|
|
|
// messaging. Build source-location information for it.
|
|
|
|
TypeSourceInfo *TSInfo = Context.getTrivialTypeSourceInfo(T, NameLoc);
|
2010-08-24 13:47:05 +08:00
|
|
|
ReceiverType = CreateParsedType(T, TSInfo);
|
2010-04-22 04:38:13 +08:00
|
|
|
return ObjCClassMessage;
|
2010-04-14 10:46:37 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-01-13 09:32:50 +08:00
|
|
|
ObjCInterfaceOrSuperCCC Validator(getCurMethodDecl());
|
2013-09-28 03:40:08 +08:00
|
|
|
if (TypoCorrection Corrected =
|
|
|
|
CorrectTypo(Result.getLookupNameInfo(), Result.getLookupKind(), S,
|
|
|
|
NULL, Validator, NULL, false, NULL, false)) {
|
2012-01-13 09:32:50 +08:00
|
|
|
if (Corrected.isKeyword()) {
|
|
|
|
// If we've found the keyword "super" (the only keyword that would be
|
|
|
|
// returned by CorrectTypo), this is a send to super.
|
2013-08-17 08:46:16 +08:00
|
|
|
diagnoseTypo(Corrected,
|
|
|
|
PDiag(diag::err_unknown_receiver_suggest) << Name);
|
2010-04-15 04:04:41 +08:00
|
|
|
return ObjCSuperMessage;
|
2012-01-13 09:32:50 +08:00
|
|
|
} else if (ObjCInterfaceDecl *Class =
|
2013-08-17 08:46:16 +08:00
|
|
|
Corrected.getCorrectionDeclAs<ObjCInterfaceDecl>()) {
|
2012-01-13 09:32:50 +08:00
|
|
|
// If we found a declaration, correct when it refers to an Objective-C
|
|
|
|
// class.
|
2013-08-17 08:46:16 +08:00
|
|
|
diagnoseTypo(Corrected,
|
|
|
|
PDiag(diag::err_unknown_receiver_suggest) << Name);
|
2012-01-13 09:32:50 +08:00
|
|
|
QualType T = Context.getObjCInterfaceType(Class);
|
|
|
|
TypeSourceInfo *TSInfo = Context.getTrivialTypeSourceInfo(T, NameLoc);
|
|
|
|
ReceiverType = CreateParsedType(T, TSInfo);
|
|
|
|
return ObjCClassMessage;
|
2010-04-14 10:46:37 +08:00
|
|
|
}
|
|
|
|
}
|
2013-08-17 08:46:16 +08:00
|
|
|
|
2010-04-14 10:46:37 +08:00
|
|
|
// Fall back: let the parser try to parse it as an instance message.
|
|
|
|
return ObjCInstanceMessage;
|
|
|
|
}
|
2009-03-10 05:12:44 +08:00
|
|
|
|
2010-08-24 14:29:42 +08:00
|
|
|
ExprResult Sema::ActOnSuperMessage(Scope *S,
|
2010-09-15 22:51:05 +08:00
|
|
|
SourceLocation SuperLoc,
|
|
|
|
Selector Sel,
|
|
|
|
SourceLocation LBracLoc,
|
2011-10-03 14:36:17 +08:00
|
|
|
ArrayRef<SourceLocation> SelectorLocs,
|
2010-09-15 22:51:05 +08:00
|
|
|
SourceLocation RBracLoc,
|
|
|
|
MultiExprArg Args) {
|
Rework the Parser-Sema interaction for Objective-C message
sends. Major changes include:
- Expanded the interface from two actions (ActOnInstanceMessage,
ActOnClassMessage), where ActOnClassMessage also handled sends to
"super" by checking whether the identifier was "super", to three
actions (ActOnInstanceMessage, ActOnClassMessage,
ActOnSuperMessage). Code completion has the same changes.
- The parser now resolves the type to which we are sending a class
message, so ActOnClassMessage now accepts a TypeTy* (rather than
an IdentifierInfo *). This opens the door to more interesting
types (for Objective-C++ support).
- Split ActOnInstanceMessage and ActOnClassMessage into parser
action functions (with their original names) and semantic
functions (BuildInstanceMessage and BuildClassMessage,
respectively). At present, this split is onyl used by
ActOnSuperMessage, which decides which kind of super message it
has and forwards to the appropriate Build*Message. In the future,
Build*Message will be used by template instantiation.
- Use getObjCMessageKind() within the disambiguation of Objective-C
message sends vs. array designators.
Two notes about substandard bits in this patch:
- There is some redundancy in the code in ParseObjCMessageExpr and
ParseInitializerWithPotentialDesignator; this will be addressed
shortly by centralizing the mapping from identifiers to type names
for the message receiver.
- There is some #if 0'd code that won't likely ever be used---it
handles the use of 'super' in methods whose class does not have a
superclass---but could be used to model GCC's behavior more
closely. This code will die in my next check-in, but I want it in
Subversion.
llvm-svn: 102021
2010-04-22 03:57:20 +08:00
|
|
|
// Determine whether we are inside a method or not.
|
2012-02-04 06:47:37 +08:00
|
|
|
ObjCMethodDecl *Method = tryCaptureObjCSelf(SuperLoc);
|
2010-04-22 04:01:04 +08:00
|
|
|
if (!Method) {
|
|
|
|
Diag(SuperLoc, diag::err_invalid_receiver_to_message_super);
|
|
|
|
return ExprError();
|
|
|
|
}
|
Rework the Parser-Sema interaction for Objective-C message
sends. Major changes include:
- Expanded the interface from two actions (ActOnInstanceMessage,
ActOnClassMessage), where ActOnClassMessage also handled sends to
"super" by checking whether the identifier was "super", to three
actions (ActOnInstanceMessage, ActOnClassMessage,
ActOnSuperMessage). Code completion has the same changes.
- The parser now resolves the type to which we are sending a class
message, so ActOnClassMessage now accepts a TypeTy* (rather than
an IdentifierInfo *). This opens the door to more interesting
types (for Objective-C++ support).
- Split ActOnInstanceMessage and ActOnClassMessage into parser
action functions (with their original names) and semantic
functions (BuildInstanceMessage and BuildClassMessage,
respectively). At present, this split is onyl used by
ActOnSuperMessage, which decides which kind of super message it
has and forwards to the appropriate Build*Message. In the future,
Build*Message will be used by template instantiation.
- Use getObjCMessageKind() within the disambiguation of Objective-C
message sends vs. array designators.
Two notes about substandard bits in this patch:
- There is some redundancy in the code in ParseObjCMessageExpr and
ParseInitializerWithPotentialDesignator; this will be addressed
shortly by centralizing the mapping from identifiers to type names
for the message receiver.
- There is some #if 0'd code that won't likely ever be used---it
handles the use of 'super' in methods whose class does not have a
superclass---but could be used to model GCC's behavior more
closely. This code will die in my next check-in, but I want it in
Subversion.
llvm-svn: 102021
2010-04-22 03:57:20 +08:00
|
|
|
|
2010-04-22 04:01:04 +08:00
|
|
|
ObjCInterfaceDecl *Class = Method->getClassInterface();
|
|
|
|
if (!Class) {
|
|
|
|
Diag(SuperLoc, diag::error_no_super_class_message)
|
|
|
|
<< Method->getDeclName();
|
Rework the Parser-Sema interaction for Objective-C message
sends. Major changes include:
- Expanded the interface from two actions (ActOnInstanceMessage,
ActOnClassMessage), where ActOnClassMessage also handled sends to
"super" by checking whether the identifier was "super", to three
actions (ActOnInstanceMessage, ActOnClassMessage,
ActOnSuperMessage). Code completion has the same changes.
- The parser now resolves the type to which we are sending a class
message, so ActOnClassMessage now accepts a TypeTy* (rather than
an IdentifierInfo *). This opens the door to more interesting
types (for Objective-C++ support).
- Split ActOnInstanceMessage and ActOnClassMessage into parser
action functions (with their original names) and semantic
functions (BuildInstanceMessage and BuildClassMessage,
respectively). At present, this split is onyl used by
ActOnSuperMessage, which decides which kind of super message it
has and forwards to the appropriate Build*Message. In the future,
Build*Message will be used by template instantiation.
- Use getObjCMessageKind() within the disambiguation of Objective-C
message sends vs. array designators.
Two notes about substandard bits in this patch:
- There is some redundancy in the code in ParseObjCMessageExpr and
ParseInitializerWithPotentialDesignator; this will be addressed
shortly by centralizing the mapping from identifiers to type names
for the message receiver.
- There is some #if 0'd code that won't likely ever be used---it
handles the use of 'super' in methods whose class does not have a
superclass---but could be used to model GCC's behavior more
closely. This code will die in my next check-in, but I want it in
Subversion.
llvm-svn: 102021
2010-04-22 03:57:20 +08:00
|
|
|
return ExprError();
|
2010-04-12 13:38:43 +08:00
|
|
|
}
|
Rework the Parser-Sema interaction for Objective-C message
sends. Major changes include:
- Expanded the interface from two actions (ActOnInstanceMessage,
ActOnClassMessage), where ActOnClassMessage also handled sends to
"super" by checking whether the identifier was "super", to three
actions (ActOnInstanceMessage, ActOnClassMessage,
ActOnSuperMessage). Code completion has the same changes.
- The parser now resolves the type to which we are sending a class
message, so ActOnClassMessage now accepts a TypeTy* (rather than
an IdentifierInfo *). This opens the door to more interesting
types (for Objective-C++ support).
- Split ActOnInstanceMessage and ActOnClassMessage into parser
action functions (with their original names) and semantic
functions (BuildInstanceMessage and BuildClassMessage,
respectively). At present, this split is onyl used by
ActOnSuperMessage, which decides which kind of super message it
has and forwards to the appropriate Build*Message. In the future,
Build*Message will be used by template instantiation.
- Use getObjCMessageKind() within the disambiguation of Objective-C
message sends vs. array designators.
Two notes about substandard bits in this patch:
- There is some redundancy in the code in ParseObjCMessageExpr and
ParseInitializerWithPotentialDesignator; this will be addressed
shortly by centralizing the mapping from identifiers to type names
for the message receiver.
- There is some #if 0'd code that won't likely ever be used---it
handles the use of 'super' in methods whose class does not have a
superclass---but could be used to model GCC's behavior more
closely. This code will die in my next check-in, but I want it in
Subversion.
llvm-svn: 102021
2010-04-22 03:57:20 +08:00
|
|
|
|
2010-04-22 04:01:04 +08:00
|
|
|
ObjCInterfaceDecl *Super = Class->getSuperClass();
|
Rework the Parser-Sema interaction for Objective-C message
sends. Major changes include:
- Expanded the interface from two actions (ActOnInstanceMessage,
ActOnClassMessage), where ActOnClassMessage also handled sends to
"super" by checking whether the identifier was "super", to three
actions (ActOnInstanceMessage, ActOnClassMessage,
ActOnSuperMessage). Code completion has the same changes.
- The parser now resolves the type to which we are sending a class
message, so ActOnClassMessage now accepts a TypeTy* (rather than
an IdentifierInfo *). This opens the door to more interesting
types (for Objective-C++ support).
- Split ActOnInstanceMessage and ActOnClassMessage into parser
action functions (with their original names) and semantic
functions (BuildInstanceMessage and BuildClassMessage,
respectively). At present, this split is onyl used by
ActOnSuperMessage, which decides which kind of super message it
has and forwards to the appropriate Build*Message. In the future,
Build*Message will be used by template instantiation.
- Use getObjCMessageKind() within the disambiguation of Objective-C
message sends vs. array designators.
Two notes about substandard bits in this patch:
- There is some redundancy in the code in ParseObjCMessageExpr and
ParseInitializerWithPotentialDesignator; this will be addressed
shortly by centralizing the mapping from identifiers to type names
for the message receiver.
- There is some #if 0'd code that won't likely ever be used---it
handles the use of 'super' in methods whose class does not have a
superclass---but could be used to model GCC's behavior more
closely. This code will die in my next check-in, but I want it in
Subversion.
llvm-svn: 102021
2010-04-22 03:57:20 +08:00
|
|
|
if (!Super) {
|
2010-04-22 04:01:04 +08:00
|
|
|
// The current class does not have a superclass.
|
2011-01-24 01:21:34 +08:00
|
|
|
Diag(SuperLoc, diag::error_root_class_cannot_use_super)
|
|
|
|
<< Class->getIdentifier();
|
Rework the Parser-Sema interaction for Objective-C message
sends. Major changes include:
- Expanded the interface from two actions (ActOnInstanceMessage,
ActOnClassMessage), where ActOnClassMessage also handled sends to
"super" by checking whether the identifier was "super", to three
actions (ActOnInstanceMessage, ActOnClassMessage,
ActOnSuperMessage). Code completion has the same changes.
- The parser now resolves the type to which we are sending a class
message, so ActOnClassMessage now accepts a TypeTy* (rather than
an IdentifierInfo *). This opens the door to more interesting
types (for Objective-C++ support).
- Split ActOnInstanceMessage and ActOnClassMessage into parser
action functions (with their original names) and semantic
functions (BuildInstanceMessage and BuildClassMessage,
respectively). At present, this split is onyl used by
ActOnSuperMessage, which decides which kind of super message it
has and forwards to the appropriate Build*Message. In the future,
Build*Message will be used by template instantiation.
- Use getObjCMessageKind() within the disambiguation of Objective-C
message sends vs. array designators.
Two notes about substandard bits in this patch:
- There is some redundancy in the code in ParseObjCMessageExpr and
ParseInitializerWithPotentialDesignator; this will be addressed
shortly by centralizing the mapping from identifiers to type names
for the message receiver.
- There is some #if 0'd code that won't likely ever be used---it
handles the use of 'super' in methods whose class does not have a
superclass---but could be used to model GCC's behavior more
closely. This code will die in my next check-in, but I want it in
Subversion.
llvm-svn: 102021
2010-04-22 03:57:20 +08:00
|
|
|
return ExprError();
|
|
|
|
}
|
|
|
|
|
2010-04-22 04:01:04 +08:00
|
|
|
// We are in a method whose class has a superclass, so 'super'
|
|
|
|
// is acting as a keyword.
|
2012-10-20 00:05:26 +08:00
|
|
|
if (Method->getSelector() == Sel)
|
|
|
|
getCurFunction()->ObjCShouldCallSuper = false;
|
2011-08-23 01:25:57 +08:00
|
|
|
|
2012-10-20 00:05:26 +08:00
|
|
|
if (Method->isInstanceMethod()) {
|
2010-04-22 04:01:04 +08:00
|
|
|
// Since we are in an instance method, this is an instance
|
|
|
|
// message to the superclass instance.
|
|
|
|
QualType SuperTy = Context.getObjCInterfaceType(Super);
|
|
|
|
SuperTy = Context.getObjCObjectPointerType(SuperTy);
|
2010-08-24 07:25:46 +08:00
|
|
|
return BuildInstanceMessage(0, SuperTy, SuperLoc,
|
2010-12-11 04:08:27 +08:00
|
|
|
Sel, /*Method=*/0,
|
2012-08-24 05:35:17 +08:00
|
|
|
LBracLoc, SelectorLocs, RBracLoc, Args);
|
Rework the Parser-Sema interaction for Objective-C message
sends. Major changes include:
- Expanded the interface from two actions (ActOnInstanceMessage,
ActOnClassMessage), where ActOnClassMessage also handled sends to
"super" by checking whether the identifier was "super", to three
actions (ActOnInstanceMessage, ActOnClassMessage,
ActOnSuperMessage). Code completion has the same changes.
- The parser now resolves the type to which we are sending a class
message, so ActOnClassMessage now accepts a TypeTy* (rather than
an IdentifierInfo *). This opens the door to more interesting
types (for Objective-C++ support).
- Split ActOnInstanceMessage and ActOnClassMessage into parser
action functions (with their original names) and semantic
functions (BuildInstanceMessage and BuildClassMessage,
respectively). At present, this split is onyl used by
ActOnSuperMessage, which decides which kind of super message it
has and forwards to the appropriate Build*Message. In the future,
Build*Message will be used by template instantiation.
- Use getObjCMessageKind() within the disambiguation of Objective-C
message sends vs. array designators.
Two notes about substandard bits in this patch:
- There is some redundancy in the code in ParseObjCMessageExpr and
ParseInitializerWithPotentialDesignator; this will be addressed
shortly by centralizing the mapping from identifiers to type names
for the message receiver.
- There is some #if 0'd code that won't likely ever be used---it
handles the use of 'super' in methods whose class does not have a
superclass---but could be used to model GCC's behavior more
closely. This code will die in my next check-in, but I want it in
Subversion.
llvm-svn: 102021
2010-04-22 03:57:20 +08:00
|
|
|
}
|
2010-04-22 04:01:04 +08:00
|
|
|
|
|
|
|
// Since we are in a class method, this is a class message to
|
|
|
|
// the superclass.
|
|
|
|
return BuildClassMessage(/*ReceiverTypeInfo=*/0,
|
|
|
|
Context.getObjCInterfaceType(Super),
|
2010-12-11 04:08:27 +08:00
|
|
|
SuperLoc, Sel, /*Method=*/0,
|
2012-08-24 05:35:17 +08:00
|
|
|
LBracLoc, SelectorLocs, RBracLoc, Args);
|
Rework the Parser-Sema interaction for Objective-C message
sends. Major changes include:
- Expanded the interface from two actions (ActOnInstanceMessage,
ActOnClassMessage), where ActOnClassMessage also handled sends to
"super" by checking whether the identifier was "super", to three
actions (ActOnInstanceMessage, ActOnClassMessage,
ActOnSuperMessage). Code completion has the same changes.
- The parser now resolves the type to which we are sending a class
message, so ActOnClassMessage now accepts a TypeTy* (rather than
an IdentifierInfo *). This opens the door to more interesting
types (for Objective-C++ support).
- Split ActOnInstanceMessage and ActOnClassMessage into parser
action functions (with their original names) and semantic
functions (BuildInstanceMessage and BuildClassMessage,
respectively). At present, this split is onyl used by
ActOnSuperMessage, which decides which kind of super message it
has and forwards to the appropriate Build*Message. In the future,
Build*Message will be used by template instantiation.
- Use getObjCMessageKind() within the disambiguation of Objective-C
message sends vs. array designators.
Two notes about substandard bits in this patch:
- There is some redundancy in the code in ParseObjCMessageExpr and
ParseInitializerWithPotentialDesignator; this will be addressed
shortly by centralizing the mapping from identifiers to type names
for the message receiver.
- There is some #if 0'd code that won't likely ever be used---it
handles the use of 'super' in methods whose class does not have a
superclass---but could be used to model GCC's behavior more
closely. This code will die in my next check-in, but I want it in
Subversion.
llvm-svn: 102021
2010-04-22 03:57:20 +08:00
|
|
|
}
|
|
|
|
|
2012-01-12 10:34:39 +08:00
|
|
|
|
|
|
|
ExprResult Sema::BuildClassMessageImplicit(QualType ReceiverType,
|
|
|
|
bool isSuperReceiver,
|
|
|
|
SourceLocation Loc,
|
|
|
|
Selector Sel,
|
|
|
|
ObjCMethodDecl *Method,
|
|
|
|
MultiExprArg Args) {
|
|
|
|
TypeSourceInfo *receiverTypeInfo = 0;
|
|
|
|
if (!ReceiverType.isNull())
|
|
|
|
receiverTypeInfo = Context.getTrivialTypeSourceInfo(ReceiverType);
|
|
|
|
|
|
|
|
return BuildClassMessage(receiverTypeInfo, ReceiverType,
|
|
|
|
/*SuperLoc=*/isSuperReceiver ? Loc : SourceLocation(),
|
|
|
|
Sel, Method, Loc, Loc, Loc, Args,
|
|
|
|
/*isImplicit=*/true);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2012-03-07 04:05:56 +08:00
|
|
|
static void applyCocoaAPICheck(Sema &S, const ObjCMessageExpr *Msg,
|
|
|
|
unsigned DiagID,
|
|
|
|
bool (*refactor)(const ObjCMessageExpr *,
|
|
|
|
const NSAPI &, edit::Commit &)) {
|
|
|
|
SourceLocation MsgLoc = Msg->getExprLoc();
|
|
|
|
if (S.Diags.getDiagnosticLevel(DiagID, MsgLoc) == DiagnosticsEngine::Ignored)
|
|
|
|
return;
|
|
|
|
|
|
|
|
SourceManager &SM = S.SourceMgr;
|
|
|
|
edit::Commit ECommit(SM, S.LangOpts);
|
|
|
|
if (refactor(Msg,*S.NSAPIObj, ECommit)) {
|
|
|
|
DiagnosticBuilder Builder = S.Diag(MsgLoc, DiagID)
|
|
|
|
<< Msg->getSelector() << Msg->getSourceRange();
|
|
|
|
// FIXME: Don't emit diagnostic at all if fixits are non-commitable.
|
|
|
|
if (!ECommit.isCommitable())
|
|
|
|
return;
|
|
|
|
for (edit::Commit::edit_iterator
|
|
|
|
I = ECommit.edit_begin(), E = ECommit.edit_end(); I != E; ++I) {
|
|
|
|
const edit::Commit::Edit &Edit = *I;
|
|
|
|
switch (Edit.Kind) {
|
|
|
|
case edit::Commit::Act_Insert:
|
|
|
|
Builder.AddFixItHint(FixItHint::CreateInsertion(Edit.OrigLoc,
|
|
|
|
Edit.Text,
|
|
|
|
Edit.BeforePrev));
|
|
|
|
break;
|
|
|
|
case edit::Commit::Act_InsertFromRange:
|
|
|
|
Builder.AddFixItHint(
|
|
|
|
FixItHint::CreateInsertionFromRange(Edit.OrigLoc,
|
|
|
|
Edit.getInsertFromRange(SM),
|
|
|
|
Edit.BeforePrev));
|
|
|
|
break;
|
|
|
|
case edit::Commit::Act_Remove:
|
|
|
|
Builder.AddFixItHint(FixItHint::CreateRemoval(Edit.getFileRange(SM)));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void checkCocoaAPI(Sema &S, const ObjCMessageExpr *Msg) {
|
|
|
|
applyCocoaAPICheck(S, Msg, diag::warn_objc_redundant_literal_use,
|
|
|
|
edit::rewriteObjCRedundantCallWithLiteral);
|
|
|
|
}
|
|
|
|
|
Rework the Parser-Sema interaction for Objective-C message
sends. Major changes include:
- Expanded the interface from two actions (ActOnInstanceMessage,
ActOnClassMessage), where ActOnClassMessage also handled sends to
"super" by checking whether the identifier was "super", to three
actions (ActOnInstanceMessage, ActOnClassMessage,
ActOnSuperMessage). Code completion has the same changes.
- The parser now resolves the type to which we are sending a class
message, so ActOnClassMessage now accepts a TypeTy* (rather than
an IdentifierInfo *). This opens the door to more interesting
types (for Objective-C++ support).
- Split ActOnInstanceMessage and ActOnClassMessage into parser
action functions (with their original names) and semantic
functions (BuildInstanceMessage and BuildClassMessage,
respectively). At present, this split is onyl used by
ActOnSuperMessage, which decides which kind of super message it
has and forwards to the appropriate Build*Message. In the future,
Build*Message will be used by template instantiation.
- Use getObjCMessageKind() within the disambiguation of Objective-C
message sends vs. array designators.
Two notes about substandard bits in this patch:
- There is some redundancy in the code in ParseObjCMessageExpr and
ParseInitializerWithPotentialDesignator; this will be addressed
shortly by centralizing the mapping from identifiers to type names
for the message receiver.
- There is some #if 0'd code that won't likely ever be used---it
handles the use of 'super' in methods whose class does not have a
superclass---but could be used to model GCC's behavior more
closely. This code will die in my next check-in, but I want it in
Subversion.
llvm-svn: 102021
2010-04-22 03:57:20 +08:00
|
|
|
/// \brief Build an Objective-C class message expression.
|
|
|
|
///
|
|
|
|
/// This routine takes care of both normal class messages and
|
|
|
|
/// class messages to the superclass.
|
|
|
|
///
|
|
|
|
/// \param ReceiverTypeInfo Type source information that describes the
|
|
|
|
/// receiver of this message. This may be NULL, in which case we are
|
|
|
|
/// sending to the superclass and \p SuperLoc must be a valid source
|
|
|
|
/// location.
|
|
|
|
|
|
|
|
/// \param ReceiverType The type of the object receiving the
|
|
|
|
/// message. When \p ReceiverTypeInfo is non-NULL, this is the same
|
|
|
|
/// type as that refers to. For a superclass send, this is the type of
|
|
|
|
/// the superclass.
|
|
|
|
///
|
|
|
|
/// \param SuperLoc The location of the "super" keyword in a
|
|
|
|
/// superclass message.
|
|
|
|
///
|
|
|
|
/// \param Sel The selector to which the message is being sent.
|
|
|
|
///
|
2010-04-23 01:01:48 +08:00
|
|
|
/// \param Method The method that this class message is invoking, if
|
|
|
|
/// already known.
|
|
|
|
///
|
Rework the Parser-Sema interaction for Objective-C message
sends. Major changes include:
- Expanded the interface from two actions (ActOnInstanceMessage,
ActOnClassMessage), where ActOnClassMessage also handled sends to
"super" by checking whether the identifier was "super", to three
actions (ActOnInstanceMessage, ActOnClassMessage,
ActOnSuperMessage). Code completion has the same changes.
- The parser now resolves the type to which we are sending a class
message, so ActOnClassMessage now accepts a TypeTy* (rather than
an IdentifierInfo *). This opens the door to more interesting
types (for Objective-C++ support).
- Split ActOnInstanceMessage and ActOnClassMessage into parser
action functions (with their original names) and semantic
functions (BuildInstanceMessage and BuildClassMessage,
respectively). At present, this split is onyl used by
ActOnSuperMessage, which decides which kind of super message it
has and forwards to the appropriate Build*Message. In the future,
Build*Message will be used by template instantiation.
- Use getObjCMessageKind() within the disambiguation of Objective-C
message sends vs. array designators.
Two notes about substandard bits in this patch:
- There is some redundancy in the code in ParseObjCMessageExpr and
ParseInitializerWithPotentialDesignator; this will be addressed
shortly by centralizing the mapping from identifiers to type names
for the message receiver.
- There is some #if 0'd code that won't likely ever be used---it
handles the use of 'super' in methods whose class does not have a
superclass---but could be used to model GCC's behavior more
closely. This code will die in my next check-in, but I want it in
Subversion.
llvm-svn: 102021
2010-04-22 03:57:20 +08:00
|
|
|
/// \param LBracLoc The location of the opening square bracket ']'.
|
|
|
|
///
|
2012-06-22 16:10:18 +08:00
|
|
|
/// \param RBracLoc The location of the closing square bracket ']'.
|
Rework the Parser-Sema interaction for Objective-C message
sends. Major changes include:
- Expanded the interface from two actions (ActOnInstanceMessage,
ActOnClassMessage), where ActOnClassMessage also handled sends to
"super" by checking whether the identifier was "super", to three
actions (ActOnInstanceMessage, ActOnClassMessage,
ActOnSuperMessage). Code completion has the same changes.
- The parser now resolves the type to which we are sending a class
message, so ActOnClassMessage now accepts a TypeTy* (rather than
an IdentifierInfo *). This opens the door to more interesting
types (for Objective-C++ support).
- Split ActOnInstanceMessage and ActOnClassMessage into parser
action functions (with their original names) and semantic
functions (BuildInstanceMessage and BuildClassMessage,
respectively). At present, this split is onyl used by
ActOnSuperMessage, which decides which kind of super message it
has and forwards to the appropriate Build*Message. In the future,
Build*Message will be used by template instantiation.
- Use getObjCMessageKind() within the disambiguation of Objective-C
message sends vs. array designators.
Two notes about substandard bits in this patch:
- There is some redundancy in the code in ParseObjCMessageExpr and
ParseInitializerWithPotentialDesignator; this will be addressed
shortly by centralizing the mapping from identifiers to type names
for the message receiver.
- There is some #if 0'd code that won't likely ever be used---it
handles the use of 'super' in methods whose class does not have a
superclass---but could be used to model GCC's behavior more
closely. This code will die in my next check-in, but I want it in
Subversion.
llvm-svn: 102021
2010-04-22 03:57:20 +08:00
|
|
|
///
|
2012-06-22 16:10:18 +08:00
|
|
|
/// \param ArgsIn The message arguments.
|
2010-08-24 14:29:42 +08:00
|
|
|
ExprResult Sema::BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo,
|
2010-09-15 22:51:05 +08:00
|
|
|
QualType ReceiverType,
|
|
|
|
SourceLocation SuperLoc,
|
|
|
|
Selector Sel,
|
|
|
|
ObjCMethodDecl *Method,
|
|
|
|
SourceLocation LBracLoc,
|
2011-10-03 14:36:17 +08:00
|
|
|
ArrayRef<SourceLocation> SelectorLocs,
|
2010-09-15 22:51:05 +08:00
|
|
|
SourceLocation RBracLoc,
|
2012-01-12 10:34:39 +08:00
|
|
|
MultiExprArg ArgsIn,
|
|
|
|
bool isImplicit) {
|
2010-09-15 22:51:05 +08:00
|
|
|
SourceLocation Loc = SuperLoc.isValid()? SuperLoc
|
2010-09-16 09:51:54 +08:00
|
|
|
: ReceiverTypeInfo->getTypeLoc().getSourceRange().getBegin();
|
2010-09-15 22:51:05 +08:00
|
|
|
if (LBracLoc.isInvalid()) {
|
|
|
|
Diag(Loc, diag::err_missing_open_square_message_send)
|
|
|
|
<< FixItHint::CreateInsertion(Loc, "[");
|
|
|
|
LBracLoc = Loc;
|
|
|
|
}
|
2013-05-01 08:24:09 +08:00
|
|
|
SourceLocation SelLoc;
|
|
|
|
if (!SelectorLocs.empty() && SelectorLocs.front().isValid())
|
|
|
|
SelLoc = SelectorLocs.front();
|
|
|
|
else
|
|
|
|
SelLoc = Loc;
|
|
|
|
|
2010-04-23 00:44:27 +08:00
|
|
|
if (ReceiverType->isDependentType()) {
|
|
|
|
// If the receiver type is dependent, we can't type-check anything
|
|
|
|
// at this point. Build a dependent expression.
|
|
|
|
unsigned NumArgs = ArgsIn.size();
|
2012-08-24 07:38:35 +08:00
|
|
|
Expr **Args = ArgsIn.data();
|
2010-04-23 00:44:27 +08:00
|
|
|
assert(SuperLoc.isInvalid() && "Message to super with dependent type");
|
2010-11-18 14:31:45 +08:00
|
|
|
return Owned(ObjCMessageExpr::Create(Context, ReceiverType,
|
|
|
|
VK_RValue, LBracLoc, ReceiverTypeInfo,
|
2011-10-03 14:36:17 +08:00
|
|
|
Sel, SelectorLocs, /*Method=*/0,
|
2012-01-12 10:34:39 +08:00
|
|
|
makeArrayRef(Args, NumArgs),RBracLoc,
|
|
|
|
isImplicit));
|
2010-04-23 00:44:27 +08:00
|
|
|
}
|
2010-04-12 13:38:43 +08:00
|
|
|
|
Rework the Parser-Sema interaction for Objective-C message
sends. Major changes include:
- Expanded the interface from two actions (ActOnInstanceMessage,
ActOnClassMessage), where ActOnClassMessage also handled sends to
"super" by checking whether the identifier was "super", to three
actions (ActOnInstanceMessage, ActOnClassMessage,
ActOnSuperMessage). Code completion has the same changes.
- The parser now resolves the type to which we are sending a class
message, so ActOnClassMessage now accepts a TypeTy* (rather than
an IdentifierInfo *). This opens the door to more interesting
types (for Objective-C++ support).
- Split ActOnInstanceMessage and ActOnClassMessage into parser
action functions (with their original names) and semantic
functions (BuildInstanceMessage and BuildClassMessage,
respectively). At present, this split is onyl used by
ActOnSuperMessage, which decides which kind of super message it
has and forwards to the appropriate Build*Message. In the future,
Build*Message will be used by template instantiation.
- Use getObjCMessageKind() within the disambiguation of Objective-C
message sends vs. array designators.
Two notes about substandard bits in this patch:
- There is some redundancy in the code in ParseObjCMessageExpr and
ParseInitializerWithPotentialDesignator; this will be addressed
shortly by centralizing the mapping from identifiers to type names
for the message receiver.
- There is some #if 0'd code that won't likely ever be used---it
handles the use of 'super' in methods whose class does not have a
superclass---but could be used to model GCC's behavior more
closely. This code will die in my next check-in, but I want it in
Subversion.
llvm-svn: 102021
2010-04-22 03:57:20 +08:00
|
|
|
// Find the class to which we are sending this message.
|
|
|
|
ObjCInterfaceDecl *Class = 0;
|
2010-05-15 19:32:37 +08:00
|
|
|
const ObjCObjectType *ClassType = ReceiverType->getAs<ObjCObjectType>();
|
|
|
|
if (!ClassType || !(Class = ClassType->getInterface())) {
|
Rework the Parser-Sema interaction for Objective-C message
sends. Major changes include:
- Expanded the interface from two actions (ActOnInstanceMessage,
ActOnClassMessage), where ActOnClassMessage also handled sends to
"super" by checking whether the identifier was "super", to three
actions (ActOnInstanceMessage, ActOnClassMessage,
ActOnSuperMessage). Code completion has the same changes.
- The parser now resolves the type to which we are sending a class
message, so ActOnClassMessage now accepts a TypeTy* (rather than
an IdentifierInfo *). This opens the door to more interesting
types (for Objective-C++ support).
- Split ActOnInstanceMessage and ActOnClassMessage into parser
action functions (with their original names) and semantic
functions (BuildInstanceMessage and BuildClassMessage,
respectively). At present, this split is onyl used by
ActOnSuperMessage, which decides which kind of super message it
has and forwards to the appropriate Build*Message. In the future,
Build*Message will be used by template instantiation.
- Use getObjCMessageKind() within the disambiguation of Objective-C
message sends vs. array designators.
Two notes about substandard bits in this patch:
- There is some redundancy in the code in ParseObjCMessageExpr and
ParseInitializerWithPotentialDesignator; this will be addressed
shortly by centralizing the mapping from identifiers to type names
for the message receiver.
- There is some #if 0'd code that won't likely ever be used---it
handles the use of 'super' in methods whose class does not have a
superclass---but could be used to model GCC's behavior more
closely. This code will die in my next check-in, but I want it in
Subversion.
llvm-svn: 102021
2010-04-22 03:57:20 +08:00
|
|
|
Diag(Loc, diag::err_invalid_receiver_class_message)
|
|
|
|
<< ReceiverType;
|
|
|
|
return ExprError();
|
2008-07-26 03:39:00 +08:00
|
|
|
}
|
Rework the Parser-Sema interaction for Objective-C message
sends. Major changes include:
- Expanded the interface from two actions (ActOnInstanceMessage,
ActOnClassMessage), where ActOnClassMessage also handled sends to
"super" by checking whether the identifier was "super", to three
actions (ActOnInstanceMessage, ActOnClassMessage,
ActOnSuperMessage). Code completion has the same changes.
- The parser now resolves the type to which we are sending a class
message, so ActOnClassMessage now accepts a TypeTy* (rather than
an IdentifierInfo *). This opens the door to more interesting
types (for Objective-C++ support).
- Split ActOnInstanceMessage and ActOnClassMessage into parser
action functions (with their original names) and semantic
functions (BuildInstanceMessage and BuildClassMessage,
respectively). At present, this split is onyl used by
ActOnSuperMessage, which decides which kind of super message it
has and forwards to the appropriate Build*Message. In the future,
Build*Message will be used by template instantiation.
- Use getObjCMessageKind() within the disambiguation of Objective-C
message sends vs. array designators.
Two notes about substandard bits in this patch:
- There is some redundancy in the code in ParseObjCMessageExpr and
ParseInitializerWithPotentialDesignator; this will be addressed
shortly by centralizing the mapping from identifiers to type names
for the message receiver.
- There is some #if 0'd code that won't likely ever be used---it
handles the use of 'super' in methods whose class does not have a
superclass---but could be used to model GCC's behavior more
closely. This code will die in my next check-in, but I want it in
Subversion.
llvm-svn: 102021
2010-04-22 03:57:20 +08:00
|
|
|
assert(Class && "We don't know which class we're messaging?");
|
2011-10-16 03:18:36 +08:00
|
|
|
// objc++ diagnoses during typename annotation.
|
2012-03-11 15:00:24 +08:00
|
|
|
if (!getLangOpts().CPlusPlus)
|
2013-05-01 08:24:09 +08:00
|
|
|
(void)DiagnoseUseOfDecl(Class, SelLoc);
|
Rework the Parser-Sema interaction for Objective-C message
sends. Major changes include:
- Expanded the interface from two actions (ActOnInstanceMessage,
ActOnClassMessage), where ActOnClassMessage also handled sends to
"super" by checking whether the identifier was "super", to three
actions (ActOnInstanceMessage, ActOnClassMessage,
ActOnSuperMessage). Code completion has the same changes.
- The parser now resolves the type to which we are sending a class
message, so ActOnClassMessage now accepts a TypeTy* (rather than
an IdentifierInfo *). This opens the door to more interesting
types (for Objective-C++ support).
- Split ActOnInstanceMessage and ActOnClassMessage into parser
action functions (with their original names) and semantic
functions (BuildInstanceMessage and BuildClassMessage,
respectively). At present, this split is onyl used by
ActOnSuperMessage, which decides which kind of super message it
has and forwards to the appropriate Build*Message. In the future,
Build*Message will be used by template instantiation.
- Use getObjCMessageKind() within the disambiguation of Objective-C
message sends vs. array designators.
Two notes about substandard bits in this patch:
- There is some redundancy in the code in ParseObjCMessageExpr and
ParseInitializerWithPotentialDesignator; this will be addressed
shortly by centralizing the mapping from identifiers to type names
for the message receiver.
- There is some #if 0'd code that won't likely ever be used---it
handles the use of 'super' in methods whose class does not have a
superclass---but could be used to model GCC's behavior more
closely. This code will die in my next check-in, but I want it in
Subversion.
llvm-svn: 102021
2010-04-22 03:57:20 +08:00
|
|
|
// Find the method we are messaging.
|
2010-04-23 01:01:48 +08:00
|
|
|
if (!Method) {
|
2011-11-15 06:10:01 +08:00
|
|
|
SourceRange TypeRange
|
|
|
|
= SuperLoc.isValid()? SourceRange(SuperLoc)
|
|
|
|
: ReceiverTypeInfo->getTypeLoc().getSourceRange();
|
2012-05-05 00:32:21 +08:00
|
|
|
if (RequireCompleteType(Loc, Context.getObjCInterfaceType(Class),
|
2012-03-11 15:00:24 +08:00
|
|
|
(getLangOpts().ObjCAutoRefCount
|
2012-05-05 00:32:21 +08:00
|
|
|
? diag::err_arc_receiver_forward_class
|
|
|
|
: diag::warn_receiver_forward_class),
|
|
|
|
TypeRange)) {
|
2010-04-23 01:01:48 +08:00
|
|
|
// A forward class used in messaging is treated as a 'Class'
|
|
|
|
Method = LookupFactoryMethodInGlobalPool(Sel,
|
|
|
|
SourceRange(LBracLoc, RBracLoc));
|
2012-03-11 15:00:24 +08:00
|
|
|
if (Method && !getLangOpts().ObjCAutoRefCount)
|
2010-04-23 01:01:48 +08:00
|
|
|
Diag(Method->getLocation(), diag::note_method_sent_forward_class)
|
|
|
|
<< Method->getDeclName();
|
|
|
|
}
|
|
|
|
if (!Method)
|
|
|
|
Method = Class->lookupClassMethod(Sel);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-04-23 01:01:48 +08:00
|
|
|
// If we have an implementation in scope, check "private" methods.
|
|
|
|
if (!Method)
|
2012-07-28 03:07:44 +08:00
|
|
|
Method = Class->lookupPrivateClassMethod(Sel);
|
2008-07-26 03:39:00 +08:00
|
|
|
|
2013-05-01 08:24:09 +08:00
|
|
|
if (Method && DiagnoseUseOfDecl(Method, SelLoc))
|
2010-04-23 01:01:48 +08:00
|
|
|
return ExprError();
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
Rework the Parser-Sema interaction for Objective-C message
sends. Major changes include:
- Expanded the interface from two actions (ActOnInstanceMessage,
ActOnClassMessage), where ActOnClassMessage also handled sends to
"super" by checking whether the identifier was "super", to three
actions (ActOnInstanceMessage, ActOnClassMessage,
ActOnSuperMessage). Code completion has the same changes.
- The parser now resolves the type to which we are sending a class
message, so ActOnClassMessage now accepts a TypeTy* (rather than
an IdentifierInfo *). This opens the door to more interesting
types (for Objective-C++ support).
- Split ActOnInstanceMessage and ActOnClassMessage into parser
action functions (with their original names) and semantic
functions (BuildInstanceMessage and BuildClassMessage,
respectively). At present, this split is onyl used by
ActOnSuperMessage, which decides which kind of super message it
has and forwards to the appropriate Build*Message. In the future,
Build*Message will be used by template instantiation.
- Use getObjCMessageKind() within the disambiguation of Objective-C
message sends vs. array designators.
Two notes about substandard bits in this patch:
- There is some redundancy in the code in ParseObjCMessageExpr and
ParseInitializerWithPotentialDesignator; this will be addressed
shortly by centralizing the mapping from identifiers to type names
for the message receiver.
- There is some #if 0'd code that won't likely ever be used---it
handles the use of 'super' in methods whose class does not have a
superclass---but could be used to model GCC's behavior more
closely. This code will die in my next check-in, but I want it in
Subversion.
llvm-svn: 102021
2010-04-22 03:57:20 +08:00
|
|
|
// Check the argument types and determine the result type.
|
|
|
|
QualType ReturnType;
|
2010-11-18 14:31:45 +08:00
|
|
|
ExprValueKind VK = VK_RValue;
|
|
|
|
|
Rework the Parser-Sema interaction for Objective-C message
sends. Major changes include:
- Expanded the interface from two actions (ActOnInstanceMessage,
ActOnClassMessage), where ActOnClassMessage also handled sends to
"super" by checking whether the identifier was "super", to three
actions (ActOnInstanceMessage, ActOnClassMessage,
ActOnSuperMessage). Code completion has the same changes.
- The parser now resolves the type to which we are sending a class
message, so ActOnClassMessage now accepts a TypeTy* (rather than
an IdentifierInfo *). This opens the door to more interesting
types (for Objective-C++ support).
- Split ActOnInstanceMessage and ActOnClassMessage into parser
action functions (with their original names) and semantic
functions (BuildInstanceMessage and BuildClassMessage,
respectively). At present, this split is onyl used by
ActOnSuperMessage, which decides which kind of super message it
has and forwards to the appropriate Build*Message. In the future,
Build*Message will be used by template instantiation.
- Use getObjCMessageKind() within the disambiguation of Objective-C
message sends vs. array designators.
Two notes about substandard bits in this patch:
- There is some redundancy in the code in ParseObjCMessageExpr and
ParseInitializerWithPotentialDesignator; this will be addressed
shortly by centralizing the mapping from identifiers to type names
for the message receiver.
- There is some #if 0'd code that won't likely ever be used---it
handles the use of 'super' in methods whose class does not have a
superclass---but could be used to model GCC's behavior more
closely. This code will die in my next check-in, but I want it in
Subversion.
llvm-svn: 102021
2010-04-22 03:57:20 +08:00
|
|
|
unsigned NumArgs = ArgsIn.size();
|
2012-08-24 07:38:35 +08:00
|
|
|
Expr **Args = ArgsIn.data();
|
2013-05-10 08:27:15 +08:00
|
|
|
if (CheckMessageArgumentTypes(ReceiverType, MultiExprArg(Args, NumArgs),
|
|
|
|
Sel, SelectorLocs,
|
2012-09-01 01:03:18 +08:00
|
|
|
Method, true,
|
2011-06-11 09:09:30 +08:00
|
|
|
SuperLoc.isValid(), LBracLoc, RBracLoc,
|
|
|
|
ReturnType, VK))
|
Rework the Parser-Sema interaction for Objective-C message
sends. Major changes include:
- Expanded the interface from two actions (ActOnInstanceMessage,
ActOnClassMessage), where ActOnClassMessage also handled sends to
"super" by checking whether the identifier was "super", to three
actions (ActOnInstanceMessage, ActOnClassMessage,
ActOnSuperMessage). Code completion has the same changes.
- The parser now resolves the type to which we are sending a class
message, so ActOnClassMessage now accepts a TypeTy* (rather than
an IdentifierInfo *). This opens the door to more interesting
types (for Objective-C++ support).
- Split ActOnInstanceMessage and ActOnClassMessage into parser
action functions (with their original names) and semantic
functions (BuildInstanceMessage and BuildClassMessage,
respectively). At present, this split is onyl used by
ActOnSuperMessage, which decides which kind of super message it
has and forwards to the appropriate Build*Message. In the future,
Build*Message will be used by template instantiation.
- Use getObjCMessageKind() within the disambiguation of Objective-C
message sends vs. array designators.
Two notes about substandard bits in this patch:
- There is some redundancy in the code in ParseObjCMessageExpr and
ParseInitializerWithPotentialDesignator; this will be addressed
shortly by centralizing the mapping from identifiers to type names
for the message receiver.
- There is some #if 0'd code that won't likely ever be used---it
handles the use of 'super' in methods whose class does not have a
superclass---but could be used to model GCC's behavior more
closely. This code will die in my next check-in, but I want it in
Subversion.
llvm-svn: 102021
2010-04-22 03:57:20 +08:00
|
|
|
return ExprError();
|
2008-06-24 23:50:53 +08:00
|
|
|
|
2011-01-11 11:23:19 +08:00
|
|
|
if (Method && !Method->getResultType()->isVoidType() &&
|
|
|
|
RequireCompleteType(LBracLoc, Method->getResultType(),
|
|
|
|
diag::err_illegal_message_expr_incomplete_type))
|
|
|
|
return ExprError();
|
|
|
|
|
Rework the Parser-Sema interaction for Objective-C message
sends. Major changes include:
- Expanded the interface from two actions (ActOnInstanceMessage,
ActOnClassMessage), where ActOnClassMessage also handled sends to
"super" by checking whether the identifier was "super", to three
actions (ActOnInstanceMessage, ActOnClassMessage,
ActOnSuperMessage). Code completion has the same changes.
- The parser now resolves the type to which we are sending a class
message, so ActOnClassMessage now accepts a TypeTy* (rather than
an IdentifierInfo *). This opens the door to more interesting
types (for Objective-C++ support).
- Split ActOnInstanceMessage and ActOnClassMessage into parser
action functions (with their original names) and semantic
functions (BuildInstanceMessage and BuildClassMessage,
respectively). At present, this split is onyl used by
ActOnSuperMessage, which decides which kind of super message it
has and forwards to the appropriate Build*Message. In the future,
Build*Message will be used by template instantiation.
- Use getObjCMessageKind() within the disambiguation of Objective-C
message sends vs. array designators.
Two notes about substandard bits in this patch:
- There is some redundancy in the code in ParseObjCMessageExpr and
ParseInitializerWithPotentialDesignator; this will be addressed
shortly by centralizing the mapping from identifiers to type names
for the message receiver.
- There is some #if 0'd code that won't likely ever be used---it
handles the use of 'super' in methods whose class does not have a
superclass---but could be used to model GCC's behavior more
closely. This code will die in my next check-in, but I want it in
Subversion.
llvm-svn: 102021
2010-04-22 03:57:20 +08:00
|
|
|
// Construct the appropriate ObjCMessageExpr.
|
2012-03-07 04:05:56 +08:00
|
|
|
ObjCMessageExpr *Result;
|
Rework the Parser-Sema interaction for Objective-C message
sends. Major changes include:
- Expanded the interface from two actions (ActOnInstanceMessage,
ActOnClassMessage), where ActOnClassMessage also handled sends to
"super" by checking whether the identifier was "super", to three
actions (ActOnInstanceMessage, ActOnClassMessage,
ActOnSuperMessage). Code completion has the same changes.
- The parser now resolves the type to which we are sending a class
message, so ActOnClassMessage now accepts a TypeTy* (rather than
an IdentifierInfo *). This opens the door to more interesting
types (for Objective-C++ support).
- Split ActOnInstanceMessage and ActOnClassMessage into parser
action functions (with their original names) and semantic
functions (BuildInstanceMessage and BuildClassMessage,
respectively). At present, this split is onyl used by
ActOnSuperMessage, which decides which kind of super message it
has and forwards to the appropriate Build*Message. In the future,
Build*Message will be used by template instantiation.
- Use getObjCMessageKind() within the disambiguation of Objective-C
message sends vs. array designators.
Two notes about substandard bits in this patch:
- There is some redundancy in the code in ParseObjCMessageExpr and
ParseInitializerWithPotentialDesignator; this will be addressed
shortly by centralizing the mapping from identifiers to type names
for the message receiver.
- There is some #if 0'd code that won't likely ever be used---it
handles the use of 'super' in methods whose class does not have a
superclass---but could be used to model GCC's behavior more
closely. This code will die in my next check-in, but I want it in
Subversion.
llvm-svn: 102021
2010-04-22 03:57:20 +08:00
|
|
|
if (SuperLoc.isValid())
|
2010-11-18 14:31:45 +08:00
|
|
|
Result = ObjCMessageExpr::Create(Context, ReturnType, VK, LBracLoc,
|
2010-05-22 13:17:18 +08:00
|
|
|
SuperLoc, /*IsInstanceSuper=*/false,
|
2011-10-03 14:36:17 +08:00
|
|
|
ReceiverType, Sel, SelectorLocs,
|
2011-10-03 14:36:45 +08:00
|
|
|
Method, makeArrayRef(Args, NumArgs),
|
2012-01-12 10:34:39 +08:00
|
|
|
RBracLoc, isImplicit);
|
2012-03-07 04:05:56 +08:00
|
|
|
else {
|
2010-11-18 14:31:45 +08:00
|
|
|
Result = ObjCMessageExpr::Create(Context, ReturnType, VK, LBracLoc,
|
2011-10-03 14:36:17 +08:00
|
|
|
ReceiverTypeInfo, Sel, SelectorLocs,
|
2011-10-03 14:36:45 +08:00
|
|
|
Method, makeArrayRef(Args, NumArgs),
|
2012-01-12 10:34:39 +08:00
|
|
|
RBracLoc, isImplicit);
|
2012-03-07 04:05:56 +08:00
|
|
|
if (!isImplicit)
|
|
|
|
checkCocoaAPI(*this, Result);
|
|
|
|
}
|
2010-05-22 13:17:18 +08:00
|
|
|
return MaybeBindToTemporary(Result);
|
2008-01-05 06:32:30 +08:00
|
|
|
}
|
|
|
|
|
Rework the Parser-Sema interaction for Objective-C message
sends. Major changes include:
- Expanded the interface from two actions (ActOnInstanceMessage,
ActOnClassMessage), where ActOnClassMessage also handled sends to
"super" by checking whether the identifier was "super", to three
actions (ActOnInstanceMessage, ActOnClassMessage,
ActOnSuperMessage). Code completion has the same changes.
- The parser now resolves the type to which we are sending a class
message, so ActOnClassMessage now accepts a TypeTy* (rather than
an IdentifierInfo *). This opens the door to more interesting
types (for Objective-C++ support).
- Split ActOnInstanceMessage and ActOnClassMessage into parser
action functions (with their original names) and semantic
functions (BuildInstanceMessage and BuildClassMessage,
respectively). At present, this split is onyl used by
ActOnSuperMessage, which decides which kind of super message it
has and forwards to the appropriate Build*Message. In the future,
Build*Message will be used by template instantiation.
- Use getObjCMessageKind() within the disambiguation of Objective-C
message sends vs. array designators.
Two notes about substandard bits in this patch:
- There is some redundancy in the code in ParseObjCMessageExpr and
ParseInitializerWithPotentialDesignator; this will be addressed
shortly by centralizing the mapping from identifiers to type names
for the message receiver.
- There is some #if 0'd code that won't likely ever be used---it
handles the use of 'super' in methods whose class does not have a
superclass---but could be used to model GCC's behavior more
closely. This code will die in my next check-in, but I want it in
Subversion.
llvm-svn: 102021
2010-04-22 03:57:20 +08:00
|
|
|
// ActOnClassMessage - used for both unary and keyword messages.
|
2008-01-05 06:32:30 +08:00
|
|
|
// ArgExprs is optional - if it is present, the number of expressions
|
|
|
|
// is obtained from Sel.getNumArgs().
|
2010-08-24 14:29:42 +08:00
|
|
|
ExprResult Sema::ActOnClassMessage(Scope *S,
|
2010-09-16 07:19:31 +08:00
|
|
|
ParsedType Receiver,
|
|
|
|
Selector Sel,
|
|
|
|
SourceLocation LBracLoc,
|
2011-10-03 14:36:17 +08:00
|
|
|
ArrayRef<SourceLocation> SelectorLocs,
|
2010-09-16 07:19:31 +08:00
|
|
|
SourceLocation RBracLoc,
|
|
|
|
MultiExprArg Args) {
|
Rework the Parser-Sema interaction for Objective-C message
sends. Major changes include:
- Expanded the interface from two actions (ActOnInstanceMessage,
ActOnClassMessage), where ActOnClassMessage also handled sends to
"super" by checking whether the identifier was "super", to three
actions (ActOnInstanceMessage, ActOnClassMessage,
ActOnSuperMessage). Code completion has the same changes.
- The parser now resolves the type to which we are sending a class
message, so ActOnClassMessage now accepts a TypeTy* (rather than
an IdentifierInfo *). This opens the door to more interesting
types (for Objective-C++ support).
- Split ActOnInstanceMessage and ActOnClassMessage into parser
action functions (with their original names) and semantic
functions (BuildInstanceMessage and BuildClassMessage,
respectively). At present, this split is onyl used by
ActOnSuperMessage, which decides which kind of super message it
has and forwards to the appropriate Build*Message. In the future,
Build*Message will be used by template instantiation.
- Use getObjCMessageKind() within the disambiguation of Objective-C
message sends vs. array designators.
Two notes about substandard bits in this patch:
- There is some redundancy in the code in ParseObjCMessageExpr and
ParseInitializerWithPotentialDesignator; this will be addressed
shortly by centralizing the mapping from identifiers to type names
for the message receiver.
- There is some #if 0'd code that won't likely ever be used---it
handles the use of 'super' in methods whose class does not have a
superclass---but could be used to model GCC's behavior more
closely. This code will die in my next check-in, but I want it in
Subversion.
llvm-svn: 102021
2010-04-22 03:57:20 +08:00
|
|
|
TypeSourceInfo *ReceiverTypeInfo;
|
|
|
|
QualType ReceiverType = GetTypeFromParser(Receiver, &ReceiverTypeInfo);
|
|
|
|
if (ReceiverType.isNull())
|
|
|
|
return ExprError();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
|
|
|
Rework the Parser-Sema interaction for Objective-C message
sends. Major changes include:
- Expanded the interface from two actions (ActOnInstanceMessage,
ActOnClassMessage), where ActOnClassMessage also handled sends to
"super" by checking whether the identifier was "super", to three
actions (ActOnInstanceMessage, ActOnClassMessage,
ActOnSuperMessage). Code completion has the same changes.
- The parser now resolves the type to which we are sending a class
message, so ActOnClassMessage now accepts a TypeTy* (rather than
an IdentifierInfo *). This opens the door to more interesting
types (for Objective-C++ support).
- Split ActOnInstanceMessage and ActOnClassMessage into parser
action functions (with their original names) and semantic
functions (BuildInstanceMessage and BuildClassMessage,
respectively). At present, this split is onyl used by
ActOnSuperMessage, which decides which kind of super message it
has and forwards to the appropriate Build*Message. In the future,
Build*Message will be used by template instantiation.
- Use getObjCMessageKind() within the disambiguation of Objective-C
message sends vs. array designators.
Two notes about substandard bits in this patch:
- There is some redundancy in the code in ParseObjCMessageExpr and
ParseInitializerWithPotentialDesignator; this will be addressed
shortly by centralizing the mapping from identifiers to type names
for the message receiver.
- There is some #if 0'd code that won't likely ever be used---it
handles the use of 'super' in methods whose class does not have a
superclass---but could be used to model GCC's behavior more
closely. This code will die in my next check-in, but I want it in
Subversion.
llvm-svn: 102021
2010-04-22 03:57:20 +08:00
|
|
|
if (!ReceiverTypeInfo)
|
|
|
|
ReceiverTypeInfo = Context.getTrivialTypeSourceInfo(ReceiverType, LBracLoc);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
Rework the Parser-Sema interaction for Objective-C message
sends. Major changes include:
- Expanded the interface from two actions (ActOnInstanceMessage,
ActOnClassMessage), where ActOnClassMessage also handled sends to
"super" by checking whether the identifier was "super", to three
actions (ActOnInstanceMessage, ActOnClassMessage,
ActOnSuperMessage). Code completion has the same changes.
- The parser now resolves the type to which we are sending a class
message, so ActOnClassMessage now accepts a TypeTy* (rather than
an IdentifierInfo *). This opens the door to more interesting
types (for Objective-C++ support).
- Split ActOnInstanceMessage and ActOnClassMessage into parser
action functions (with their original names) and semantic
functions (BuildInstanceMessage and BuildClassMessage,
respectively). At present, this split is onyl used by
ActOnSuperMessage, which decides which kind of super message it
has and forwards to the appropriate Build*Message. In the future,
Build*Message will be used by template instantiation.
- Use getObjCMessageKind() within the disambiguation of Objective-C
message sends vs. array designators.
Two notes about substandard bits in this patch:
- There is some redundancy in the code in ParseObjCMessageExpr and
ParseInitializerWithPotentialDesignator; this will be addressed
shortly by centralizing the mapping from identifiers to type names
for the message receiver.
- There is some #if 0'd code that won't likely ever be used---it
handles the use of 'super' in methods whose class does not have a
superclass---but could be used to model GCC's behavior more
closely. This code will die in my next check-in, but I want it in
Subversion.
llvm-svn: 102021
2010-04-22 03:57:20 +08:00
|
|
|
return BuildClassMessage(ReceiverTypeInfo, ReceiverType,
|
2010-04-23 01:01:48 +08:00
|
|
|
/*SuperLoc=*/SourceLocation(), Sel, /*Method=*/0,
|
2012-08-24 05:35:17 +08:00
|
|
|
LBracLoc, SelectorLocs, RBracLoc, Args);
|
Rework the Parser-Sema interaction for Objective-C message
sends. Major changes include:
- Expanded the interface from two actions (ActOnInstanceMessage,
ActOnClassMessage), where ActOnClassMessage also handled sends to
"super" by checking whether the identifier was "super", to three
actions (ActOnInstanceMessage, ActOnClassMessage,
ActOnSuperMessage). Code completion has the same changes.
- The parser now resolves the type to which we are sending a class
message, so ActOnClassMessage now accepts a TypeTy* (rather than
an IdentifierInfo *). This opens the door to more interesting
types (for Objective-C++ support).
- Split ActOnInstanceMessage and ActOnClassMessage into parser
action functions (with their original names) and semantic
functions (BuildInstanceMessage and BuildClassMessage,
respectively). At present, this split is onyl used by
ActOnSuperMessage, which decides which kind of super message it
has and forwards to the appropriate Build*Message. In the future,
Build*Message will be used by template instantiation.
- Use getObjCMessageKind() within the disambiguation of Objective-C
message sends vs. array designators.
Two notes about substandard bits in this patch:
- There is some redundancy in the code in ParseObjCMessageExpr and
ParseInitializerWithPotentialDesignator; this will be addressed
shortly by centralizing the mapping from identifiers to type names
for the message receiver.
- There is some #if 0'd code that won't likely ever be used---it
handles the use of 'super' in methods whose class does not have a
superclass---but could be used to model GCC's behavior more
closely. This code will die in my next check-in, but I want it in
Subversion.
llvm-svn: 102021
2010-04-22 03:57:20 +08:00
|
|
|
}
|
2008-11-18 06:29:32 +08:00
|
|
|
|
2012-01-12 10:34:39 +08:00
|
|
|
ExprResult Sema::BuildInstanceMessageImplicit(Expr *Receiver,
|
|
|
|
QualType ReceiverType,
|
|
|
|
SourceLocation Loc,
|
|
|
|
Selector Sel,
|
|
|
|
ObjCMethodDecl *Method,
|
|
|
|
MultiExprArg Args) {
|
|
|
|
return BuildInstanceMessage(Receiver, ReceiverType,
|
|
|
|
/*SuperLoc=*/!Receiver ? Loc : SourceLocation(),
|
|
|
|
Sel, Method, Loc, Loc, Loc, Args,
|
|
|
|
/*isImplicit=*/true);
|
|
|
|
}
|
|
|
|
|
Rework the Parser-Sema interaction for Objective-C message
sends. Major changes include:
- Expanded the interface from two actions (ActOnInstanceMessage,
ActOnClassMessage), where ActOnClassMessage also handled sends to
"super" by checking whether the identifier was "super", to three
actions (ActOnInstanceMessage, ActOnClassMessage,
ActOnSuperMessage). Code completion has the same changes.
- The parser now resolves the type to which we are sending a class
message, so ActOnClassMessage now accepts a TypeTy* (rather than
an IdentifierInfo *). This opens the door to more interesting
types (for Objective-C++ support).
- Split ActOnInstanceMessage and ActOnClassMessage into parser
action functions (with their original names) and semantic
functions (BuildInstanceMessage and BuildClassMessage,
respectively). At present, this split is onyl used by
ActOnSuperMessage, which decides which kind of super message it
has and forwards to the appropriate Build*Message. In the future,
Build*Message will be used by template instantiation.
- Use getObjCMessageKind() within the disambiguation of Objective-C
message sends vs. array designators.
Two notes about substandard bits in this patch:
- There is some redundancy in the code in ParseObjCMessageExpr and
ParseInitializerWithPotentialDesignator; this will be addressed
shortly by centralizing the mapping from identifiers to type names
for the message receiver.
- There is some #if 0'd code that won't likely ever be used---it
handles the use of 'super' in methods whose class does not have a
superclass---but could be used to model GCC's behavior more
closely. This code will die in my next check-in, but I want it in
Subversion.
llvm-svn: 102021
2010-04-22 03:57:20 +08:00
|
|
|
/// \brief Build an Objective-C instance message expression.
|
|
|
|
///
|
|
|
|
/// This routine takes care of both normal instance messages and
|
|
|
|
/// instance messages to the superclass instance.
|
|
|
|
///
|
|
|
|
/// \param Receiver The expression that computes the object that will
|
|
|
|
/// receive this message. This may be empty, in which case we are
|
|
|
|
/// sending to the superclass instance and \p SuperLoc must be a valid
|
|
|
|
/// source location.
|
|
|
|
///
|
|
|
|
/// \param ReceiverType The (static) type of the object receiving the
|
|
|
|
/// message. When a \p Receiver expression is provided, this is the
|
|
|
|
/// same type as that expression. For a superclass instance send, this
|
|
|
|
/// is a pointer to the type of the superclass.
|
|
|
|
///
|
|
|
|
/// \param SuperLoc The location of the "super" keyword in a
|
|
|
|
/// superclass instance message.
|
|
|
|
///
|
|
|
|
/// \param Sel The selector to which the message is being sent.
|
|
|
|
///
|
2010-04-23 01:01:48 +08:00
|
|
|
/// \param Method The method that this instance message is invoking, if
|
|
|
|
/// already known.
|
|
|
|
///
|
Rework the Parser-Sema interaction for Objective-C message
sends. Major changes include:
- Expanded the interface from two actions (ActOnInstanceMessage,
ActOnClassMessage), where ActOnClassMessage also handled sends to
"super" by checking whether the identifier was "super", to three
actions (ActOnInstanceMessage, ActOnClassMessage,
ActOnSuperMessage). Code completion has the same changes.
- The parser now resolves the type to which we are sending a class
message, so ActOnClassMessage now accepts a TypeTy* (rather than
an IdentifierInfo *). This opens the door to more interesting
types (for Objective-C++ support).
- Split ActOnInstanceMessage and ActOnClassMessage into parser
action functions (with their original names) and semantic
functions (BuildInstanceMessage and BuildClassMessage,
respectively). At present, this split is onyl used by
ActOnSuperMessage, which decides which kind of super message it
has and forwards to the appropriate Build*Message. In the future,
Build*Message will be used by template instantiation.
- Use getObjCMessageKind() within the disambiguation of Objective-C
message sends vs. array designators.
Two notes about substandard bits in this patch:
- There is some redundancy in the code in ParseObjCMessageExpr and
ParseInitializerWithPotentialDesignator; this will be addressed
shortly by centralizing the mapping from identifiers to type names
for the message receiver.
- There is some #if 0'd code that won't likely ever be used---it
handles the use of 'super' in methods whose class does not have a
superclass---but could be used to model GCC's behavior more
closely. This code will die in my next check-in, but I want it in
Subversion.
llvm-svn: 102021
2010-04-22 03:57:20 +08:00
|
|
|
/// \param LBracLoc The location of the opening square bracket ']'.
|
|
|
|
///
|
2012-06-22 16:10:18 +08:00
|
|
|
/// \param RBracLoc The location of the closing square bracket ']'.
|
Rework the Parser-Sema interaction for Objective-C message
sends. Major changes include:
- Expanded the interface from two actions (ActOnInstanceMessage,
ActOnClassMessage), where ActOnClassMessage also handled sends to
"super" by checking whether the identifier was "super", to three
actions (ActOnInstanceMessage, ActOnClassMessage,
ActOnSuperMessage). Code completion has the same changes.
- The parser now resolves the type to which we are sending a class
message, so ActOnClassMessage now accepts a TypeTy* (rather than
an IdentifierInfo *). This opens the door to more interesting
types (for Objective-C++ support).
- Split ActOnInstanceMessage and ActOnClassMessage into parser
action functions (with their original names) and semantic
functions (BuildInstanceMessage and BuildClassMessage,
respectively). At present, this split is onyl used by
ActOnSuperMessage, which decides which kind of super message it
has and forwards to the appropriate Build*Message. In the future,
Build*Message will be used by template instantiation.
- Use getObjCMessageKind() within the disambiguation of Objective-C
message sends vs. array designators.
Two notes about substandard bits in this patch:
- There is some redundancy in the code in ParseObjCMessageExpr and
ParseInitializerWithPotentialDesignator; this will be addressed
shortly by centralizing the mapping from identifiers to type names
for the message receiver.
- There is some #if 0'd code that won't likely ever be used---it
handles the use of 'super' in methods whose class does not have a
superclass---but could be used to model GCC's behavior more
closely. This code will die in my next check-in, but I want it in
Subversion.
llvm-svn: 102021
2010-04-22 03:57:20 +08:00
|
|
|
///
|
2012-06-22 16:10:18 +08:00
|
|
|
/// \param ArgsIn The message arguments.
|
2010-08-24 14:29:42 +08:00
|
|
|
ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
|
2010-12-11 04:08:27 +08:00
|
|
|
QualType ReceiverType,
|
|
|
|
SourceLocation SuperLoc,
|
|
|
|
Selector Sel,
|
|
|
|
ObjCMethodDecl *Method,
|
|
|
|
SourceLocation LBracLoc,
|
2011-10-03 14:36:17 +08:00
|
|
|
ArrayRef<SourceLocation> SelectorLocs,
|
2010-12-11 04:08:27 +08:00
|
|
|
SourceLocation RBracLoc,
|
2012-01-12 10:34:39 +08:00
|
|
|
MultiExprArg ArgsIn,
|
|
|
|
bool isImplicit) {
|
2010-09-15 22:51:05 +08:00
|
|
|
// The location of the receiver.
|
|
|
|
SourceLocation Loc = SuperLoc.isValid()? SuperLoc : Receiver->getLocStart();
|
2013-05-01 08:24:09 +08:00
|
|
|
SourceRange RecRange =
|
|
|
|
SuperLoc.isValid()? SuperLoc : Receiver->getSourceRange();
|
|
|
|
SourceLocation SelLoc;
|
|
|
|
if (!SelectorLocs.empty() && SelectorLocs.front().isValid())
|
|
|
|
SelLoc = SelectorLocs.front();
|
|
|
|
else
|
|
|
|
SelLoc = Loc;
|
|
|
|
|
2010-09-15 22:51:05 +08:00
|
|
|
if (LBracLoc.isInvalid()) {
|
|
|
|
Diag(Loc, diag::err_missing_open_square_message_send)
|
|
|
|
<< FixItHint::CreateInsertion(Loc, "[");
|
|
|
|
LBracLoc = Loc;
|
|
|
|
}
|
|
|
|
|
Rework the Parser-Sema interaction for Objective-C message
sends. Major changes include:
- Expanded the interface from two actions (ActOnInstanceMessage,
ActOnClassMessage), where ActOnClassMessage also handled sends to
"super" by checking whether the identifier was "super", to three
actions (ActOnInstanceMessage, ActOnClassMessage,
ActOnSuperMessage). Code completion has the same changes.
- The parser now resolves the type to which we are sending a class
message, so ActOnClassMessage now accepts a TypeTy* (rather than
an IdentifierInfo *). This opens the door to more interesting
types (for Objective-C++ support).
- Split ActOnInstanceMessage and ActOnClassMessage into parser
action functions (with their original names) and semantic
functions (BuildInstanceMessage and BuildClassMessage,
respectively). At present, this split is onyl used by
ActOnSuperMessage, which decides which kind of super message it
has and forwards to the appropriate Build*Message. In the future,
Build*Message will be used by template instantiation.
- Use getObjCMessageKind() within the disambiguation of Objective-C
message sends vs. array designators.
Two notes about substandard bits in this patch:
- There is some redundancy in the code in ParseObjCMessageExpr and
ParseInitializerWithPotentialDesignator; this will be addressed
shortly by centralizing the mapping from identifiers to type names
for the message receiver.
- There is some #if 0'd code that won't likely ever be used---it
handles the use of 'super' in methods whose class does not have a
superclass---but could be used to model GCC's behavior more
closely. This code will die in my next check-in, but I want it in
Subversion.
llvm-svn: 102021
2010-04-22 03:57:20 +08:00
|
|
|
// If we have a receiver expression, perform appropriate promotions
|
|
|
|
// and determine receiver type.
|
|
|
|
if (Receiver) {
|
2011-10-18 02:40:02 +08:00
|
|
|
if (Receiver->hasPlaceholderType()) {
|
2011-12-01 09:37:36 +08:00
|
|
|
ExprResult Result;
|
|
|
|
if (Receiver->getType() == Context.UnknownAnyTy)
|
|
|
|
Result = forceUnknownAnyToType(Receiver, Context.getObjCIdType());
|
|
|
|
else
|
|
|
|
Result = CheckPlaceholderExpr(Receiver);
|
|
|
|
if (Result.isInvalid()) return ExprError();
|
|
|
|
Receiver = Result.take();
|
2011-10-18 02:40:02 +08:00
|
|
|
}
|
|
|
|
|
2010-04-23 00:44:27 +08:00
|
|
|
if (Receiver->isTypeDependent()) {
|
|
|
|
// If the receiver is type-dependent, we can't type-check anything
|
|
|
|
// at this point. Build a dependent expression.
|
|
|
|
unsigned NumArgs = ArgsIn.size();
|
2012-08-24 07:38:35 +08:00
|
|
|
Expr **Args = ArgsIn.data();
|
2010-04-23 00:44:27 +08:00
|
|
|
assert(SuperLoc.isInvalid() && "Message to super with dependent type");
|
|
|
|
return Owned(ObjCMessageExpr::Create(Context, Context.DependentTy,
|
2010-11-18 14:31:45 +08:00
|
|
|
VK_RValue, LBracLoc, Receiver, Sel,
|
2011-10-03 14:36:17 +08:00
|
|
|
SelectorLocs, /*Method=*/0,
|
2011-10-03 14:36:45 +08:00
|
|
|
makeArrayRef(Args, NumArgs),
|
2012-01-12 10:34:39 +08:00
|
|
|
RBracLoc, isImplicit));
|
2010-04-23 00:44:27 +08:00
|
|
|
}
|
|
|
|
|
Rework the Parser-Sema interaction for Objective-C message
sends. Major changes include:
- Expanded the interface from two actions (ActOnInstanceMessage,
ActOnClassMessage), where ActOnClassMessage also handled sends to
"super" by checking whether the identifier was "super", to three
actions (ActOnInstanceMessage, ActOnClassMessage,
ActOnSuperMessage). Code completion has the same changes.
- The parser now resolves the type to which we are sending a class
message, so ActOnClassMessage now accepts a TypeTy* (rather than
an IdentifierInfo *). This opens the door to more interesting
types (for Objective-C++ support).
- Split ActOnInstanceMessage and ActOnClassMessage into parser
action functions (with their original names) and semantic
functions (BuildInstanceMessage and BuildClassMessage,
respectively). At present, this split is onyl used by
ActOnSuperMessage, which decides which kind of super message it
has and forwards to the appropriate Build*Message. In the future,
Build*Message will be used by template instantiation.
- Use getObjCMessageKind() within the disambiguation of Objective-C
message sends vs. array designators.
Two notes about substandard bits in this patch:
- There is some redundancy in the code in ParseObjCMessageExpr and
ParseInitializerWithPotentialDesignator; this will be addressed
shortly by centralizing the mapping from identifiers to type names
for the message receiver.
- There is some #if 0'd code that won't likely ever be used---it
handles the use of 'super' in methods whose class does not have a
superclass---but could be used to model GCC's behavior more
closely. This code will die in my next check-in, but I want it in
Subversion.
llvm-svn: 102021
2010-04-22 03:57:20 +08:00
|
|
|
// If necessary, apply function/array conversion to the receiver.
|
|
|
|
// C99 6.7.5.3p[7,8].
|
2011-04-09 02:41:53 +08:00
|
|
|
ExprResult Result = DefaultFunctionArrayLvalueConversion(Receiver);
|
|
|
|
if (Result.isInvalid())
|
|
|
|
return ExprError();
|
|
|
|
Receiver = Result.take();
|
Rework the Parser-Sema interaction for Objective-C message
sends. Major changes include:
- Expanded the interface from two actions (ActOnInstanceMessage,
ActOnClassMessage), where ActOnClassMessage also handled sends to
"super" by checking whether the identifier was "super", to three
actions (ActOnInstanceMessage, ActOnClassMessage,
ActOnSuperMessage). Code completion has the same changes.
- The parser now resolves the type to which we are sending a class
message, so ActOnClassMessage now accepts a TypeTy* (rather than
an IdentifierInfo *). This opens the door to more interesting
types (for Objective-C++ support).
- Split ActOnInstanceMessage and ActOnClassMessage into parser
action functions (with their original names) and semantic
functions (BuildInstanceMessage and BuildClassMessage,
respectively). At present, this split is onyl used by
ActOnSuperMessage, which decides which kind of super message it
has and forwards to the appropriate Build*Message. In the future,
Build*Message will be used by template instantiation.
- Use getObjCMessageKind() within the disambiguation of Objective-C
message sends vs. array designators.
Two notes about substandard bits in this patch:
- There is some redundancy in the code in ParseObjCMessageExpr and
ParseInitializerWithPotentialDesignator; this will be addressed
shortly by centralizing the mapping from identifiers to type names
for the message receiver.
- There is some #if 0'd code that won't likely ever be used---it
handles the use of 'super' in methods whose class does not have a
superclass---but could be used to model GCC's behavior more
closely. This code will die in my next check-in, but I want it in
Subversion.
llvm-svn: 102021
2010-04-22 03:57:20 +08:00
|
|
|
ReceiverType = Receiver->getType();
|
2013-03-01 17:20:14 +08:00
|
|
|
|
|
|
|
// If the receiver is an ObjC pointer, a block pointer, or an
|
|
|
|
// __attribute__((NSObject)) pointer, we don't need to do any
|
|
|
|
// special conversion in order to look up a receiver.
|
|
|
|
if (ReceiverType->isObjCRetainableType()) {
|
|
|
|
// do nothing
|
|
|
|
} else if (!getLangOpts().ObjCAutoRefCount &&
|
|
|
|
!Context.getObjCIdType().isNull() &&
|
|
|
|
(ReceiverType->isPointerType() ||
|
|
|
|
ReceiverType->isIntegerType())) {
|
|
|
|
// Implicitly convert integers and pointers to 'id' but emit a warning.
|
|
|
|
// But not in ARC.
|
|
|
|
Diag(Loc, diag::warn_bad_receiver_type)
|
|
|
|
<< ReceiverType
|
|
|
|
<< Receiver->getSourceRange();
|
|
|
|
if (ReceiverType->isPointerType()) {
|
|
|
|
Receiver = ImpCastExprToType(Receiver, Context.getObjCIdType(),
|
|
|
|
CK_CPointerToObjCPointerCast).take();
|
|
|
|
} else {
|
|
|
|
// TODO: specialized warning on null receivers?
|
|
|
|
bool IsNull = Receiver->isNullPointerConstant(Context,
|
|
|
|
Expr::NPC_ValueDependentIsNull);
|
|
|
|
CastKind Kind = IsNull ? CK_NullToPointer : CK_IntegralToPointer;
|
|
|
|
Receiver = ImpCastExprToType(Receiver, Context.getObjCIdType(),
|
|
|
|
Kind).take();
|
|
|
|
}
|
|
|
|
ReceiverType = Receiver->getType();
|
|
|
|
} else if (getLangOpts().CPlusPlus) {
|
2013-11-08 06:34:54 +08:00
|
|
|
// The receiver must be a complete type.
|
|
|
|
if (RequireCompleteType(Loc, Receiver->getType(),
|
|
|
|
diag::err_incomplete_receiver_type))
|
|
|
|
return ExprError();
|
|
|
|
|
2013-03-01 17:20:14 +08:00
|
|
|
ExprResult result = PerformContextuallyConvertToObjCPointer(Receiver);
|
|
|
|
if (result.isUsable()) {
|
|
|
|
Receiver = result.take();
|
|
|
|
ReceiverType = Receiver->getType();
|
|
|
|
}
|
|
|
|
}
|
Rework the Parser-Sema interaction for Objective-C message
sends. Major changes include:
- Expanded the interface from two actions (ActOnInstanceMessage,
ActOnClassMessage), where ActOnClassMessage also handled sends to
"super" by checking whether the identifier was "super", to three
actions (ActOnInstanceMessage, ActOnClassMessage,
ActOnSuperMessage). Code completion has the same changes.
- The parser now resolves the type to which we are sending a class
message, so ActOnClassMessage now accepts a TypeTy* (rather than
an IdentifierInfo *). This opens the door to more interesting
types (for Objective-C++ support).
- Split ActOnInstanceMessage and ActOnClassMessage into parser
action functions (with their original names) and semantic
functions (BuildInstanceMessage and BuildClassMessage,
respectively). At present, this split is onyl used by
ActOnSuperMessage, which decides which kind of super message it
has and forwards to the appropriate Build*Message. In the future,
Build*Message will be used by template instantiation.
- Use getObjCMessageKind() within the disambiguation of Objective-C
message sends vs. array designators.
Two notes about substandard bits in this patch:
- There is some redundancy in the code in ParseObjCMessageExpr and
ParseInitializerWithPotentialDesignator; this will be addressed
shortly by centralizing the mapping from identifiers to type names
for the message receiver.
- There is some #if 0'd code that won't likely ever be used---it
handles the use of 'super' in methods whose class does not have a
superclass---but could be used to model GCC's behavior more
closely. This code will die in my next check-in, but I want it in
Subversion.
llvm-svn: 102021
2010-04-22 03:57:20 +08:00
|
|
|
}
|
Overhaul the AST representation of Objective-C message send
expressions, to improve source-location information, clarify the
actual receiver of the message, and pave the way for proper C++
support. The ObjCMessageExpr node represents four different kinds of
message sends in a single AST node:
1) Send to a object instance described by an expression (e.g., [x method:5])
2) Send to a class described by the class name (e.g., [NSString method:5])
3) Send to a superclass class (e.g, [super method:5] in class method)
4) Send to a superclass instance (e.g., [super method:5] in instance method)
Previously these four cases where tangled together. Now, they have
more distinct representations. Specific changes:
1) Unchanged; the object instance is represented by an Expr*.
2) Previously stored the ObjCInterfaceDecl* referring to the class
receiving the message. Now stores a TypeSourceInfo* so that we know
how the class was spelled. This both maintains typedef information
and opens the door for more complicated C++ types (e.g., dependent
types). There was an alternative, unused representation of these
sends by naming the class via an IdentifierInfo *. In practice, we
either had an ObjCInterfaceDecl *, from which we would get the
IdentifierInfo *, or we fell into the case below...
3) Previously represented by a class message whose IdentifierInfo *
referred to "super". Sema and CodeGen would use isStr("super") to
determine if they had a send to super. Now represented as a
"class super" send, where we have both the location of the "super"
keyword and the ObjCInterfaceDecl* of the superclass we're
targetting (statically).
4) Previously represented by an instance message whose receiver is a
an ObjCSuperExpr, which Sema and CodeGen would check for via
isa<ObjCSuperExpr>(). Now represented as an "instance super" send,
where we have both the location of the "super" keyword and the
ObjCInterfaceDecl* of the superclass we're targetting
(statically). Note that ObjCSuperExpr only has one remaining use in
the AST, which is for "super.prop" references.
The new representation of ObjCMessageExpr is 2 pointers smaller than
the old one, since it combines more storage. It also eliminates a leak
when we loaded message-send expressions from a precompiled header. The
representation also feels much cleaner to me; comments welcome!
This patch attempts to maintain the same semantics we previously had
with Objective-C message sends. In several places, there are massive
changes that boil down to simply replacing a nested-if structure such
as:
if (message has a receiver expression) {
// instance message
if (isa<ObjCSuperExpr>(...)) {
// send to super
} else {
// send to an object
}
} else {
// class message
if (name->isStr("super")) {
// class send to super
} else {
// send to class
}
}
with a switch
switch (E->getReceiverKind()) {
case ObjCMessageExpr::SuperInstance: ...
case ObjCMessageExpr::Instance: ...
case ObjCMessageExpr::SuperClass: ...
case ObjCMessageExpr::Class:...
}
There are quite a few places (particularly in the checkers) where
send-to-super is effectively ignored. I've placed FIXMEs in most of
them, and attempted to address send-to-super in a reasonable way. This
could use some review.
llvm-svn: 101972
2010-04-21 08:45:42 +08:00
|
|
|
|
2013-03-01 17:20:14 +08:00
|
|
|
// There's a somewhat weird interaction here where we assume that we
|
|
|
|
// won't actually have a method unless we also don't need to do some
|
|
|
|
// of the more detailed type-checking on the receiver.
|
|
|
|
|
2010-04-23 01:01:48 +08:00
|
|
|
if (!Method) {
|
|
|
|
// Handle messages to id.
|
2010-08-11 02:10:50 +08:00
|
|
|
bool receiverIsId = ReceiverType->isObjCIdType();
|
2010-08-10 07:27:58 +08:00
|
|
|
if (receiverIsId || ReceiverType->isBlockPointerType() ||
|
2010-04-23 01:01:48 +08:00
|
|
|
(Receiver && Context.isObjCNSObjectType(Receiver->getType()))) {
|
|
|
|
Method = LookupInstanceMethodInGlobalPool(Sel,
|
2010-08-10 07:27:58 +08:00
|
|
|
SourceRange(LBracLoc, RBracLoc),
|
|
|
|
receiverIsId);
|
2010-04-23 01:01:48 +08:00
|
|
|
if (!Method)
|
Rework the Parser-Sema interaction for Objective-C message
sends. Major changes include:
- Expanded the interface from two actions (ActOnInstanceMessage,
ActOnClassMessage), where ActOnClassMessage also handled sends to
"super" by checking whether the identifier was "super", to three
actions (ActOnInstanceMessage, ActOnClassMessage,
ActOnSuperMessage). Code completion has the same changes.
- The parser now resolves the type to which we are sending a class
message, so ActOnClassMessage now accepts a TypeTy* (rather than
an IdentifierInfo *). This opens the door to more interesting
types (for Objective-C++ support).
- Split ActOnInstanceMessage and ActOnClassMessage into parser
action functions (with their original names) and semantic
functions (BuildInstanceMessage and BuildClassMessage,
respectively). At present, this split is onyl used by
ActOnSuperMessage, which decides which kind of super message it
has and forwards to the appropriate Build*Message. In the future,
Build*Message will be used by template instantiation.
- Use getObjCMessageKind() within the disambiguation of Objective-C
message sends vs. array designators.
Two notes about substandard bits in this patch:
- There is some redundancy in the code in ParseObjCMessageExpr and
ParseInitializerWithPotentialDesignator; this will be addressed
shortly by centralizing the mapping from identifiers to type names
for the message receiver.
- There is some #if 0'd code that won't likely ever be used---it
handles the use of 'super' in methods whose class does not have a
superclass---but could be used to model GCC's behavior more
closely. This code will die in my next check-in, but I want it in
Subversion.
llvm-svn: 102021
2010-04-22 03:57:20 +08:00
|
|
|
Method = LookupFactoryMethodInGlobalPool(Sel,
|
2012-05-13 01:32:52 +08:00
|
|
|
SourceRange(LBracLoc,RBracLoc),
|
2010-08-10 07:27:58 +08:00
|
|
|
receiverIsId);
|
2010-04-23 01:01:48 +08:00
|
|
|
} else if (ReceiverType->isObjCClassType() ||
|
|
|
|
ReceiverType->isObjCQualifiedClassType()) {
|
|
|
|
// Handle messages to Class.
|
2011-04-07 02:40:08 +08:00
|
|
|
// We allow sending a message to a qualified Class ("Class<foo>"), which
|
|
|
|
// is ok as long as one of the protocols implements the selector (if not, warn).
|
|
|
|
if (const ObjCObjectPointerType *QClassTy
|
|
|
|
= ReceiverType->getAsObjCQualifiedClassType()) {
|
|
|
|
// Search protocols for class methods.
|
|
|
|
Method = LookupMethodInQualifiedType(Sel, QClassTy, false);
|
|
|
|
if (!Method) {
|
|
|
|
Method = LookupMethodInQualifiedType(Sel, QClassTy, true);
|
|
|
|
// warn if instance method found for a Class message.
|
|
|
|
if (Method) {
|
2013-05-01 08:24:09 +08:00
|
|
|
Diag(SelLoc, diag::warn_instance_method_on_class_found)
|
2011-04-07 02:40:08 +08:00
|
|
|
<< Method->getSelector() << Sel;
|
2012-02-28 06:55:11 +08:00
|
|
|
Diag(Method->getLocation(), diag::note_method_declared_at)
|
|
|
|
<< Method->getDeclName();
|
2011-04-07 02:40:08 +08:00
|
|
|
}
|
2009-03-04 23:11:40 +08:00
|
|
|
}
|
2011-04-07 02:40:08 +08:00
|
|
|
} else {
|
|
|
|
if (ObjCMethodDecl *CurMeth = getCurMethodDecl()) {
|
|
|
|
if (ObjCInterfaceDecl *ClassDecl = CurMeth->getClassInterface()) {
|
|
|
|
// First check the public methods in the class interface.
|
|
|
|
Method = ClassDecl->lookupClassMethod(Sel);
|
|
|
|
|
|
|
|
if (!Method)
|
2012-07-28 03:07:44 +08:00
|
|
|
Method = ClassDecl->lookupPrivateClassMethod(Sel);
|
2011-04-07 02:40:08 +08:00
|
|
|
}
|
2013-05-01 08:24:09 +08:00
|
|
|
if (Method && DiagnoseUseOfDecl(Method, SelLoc))
|
2011-04-07 02:40:08 +08:00
|
|
|
return ExprError();
|
|
|
|
}
|
|
|
|
if (!Method) {
|
|
|
|
// If not messaging 'self', look for any factory method named 'Sel'.
|
2011-09-28 00:10:05 +08:00
|
|
|
if (!Receiver || !isSelfExpr(Receiver)) {
|
2011-04-07 02:40:08 +08:00
|
|
|
Method = LookupFactoryMethodInGlobalPool(Sel,
|
|
|
|
SourceRange(LBracLoc, RBracLoc),
|
|
|
|
true);
|
|
|
|
if (!Method) {
|
|
|
|
// If no class (factory) method was found, check if an _instance_
|
|
|
|
// method of the same name exists in the root class only.
|
|
|
|
Method = LookupInstanceMethodInGlobalPool(Sel,
|
2010-08-10 07:27:58 +08:00
|
|
|
SourceRange(LBracLoc, RBracLoc),
|
2011-04-07 02:40:08 +08:00
|
|
|
true);
|
|
|
|
if (Method)
|
|
|
|
if (const ObjCInterfaceDecl *ID =
|
|
|
|
dyn_cast<ObjCInterfaceDecl>(Method->getDeclContext())) {
|
|
|
|
if (ID->getSuperClass())
|
2013-05-01 08:24:09 +08:00
|
|
|
Diag(SelLoc, diag::warn_root_inst_method_not_found)
|
2011-04-07 02:40:08 +08:00
|
|
|
<< Sel << SourceRange(LBracLoc, RBracLoc);
|
|
|
|
}
|
|
|
|
}
|
Overhaul the AST representation of Objective-C message send
expressions, to improve source-location information, clarify the
actual receiver of the message, and pave the way for proper C++
support. The ObjCMessageExpr node represents four different kinds of
message sends in a single AST node:
1) Send to a object instance described by an expression (e.g., [x method:5])
2) Send to a class described by the class name (e.g., [NSString method:5])
3) Send to a superclass class (e.g, [super method:5] in class method)
4) Send to a superclass instance (e.g., [super method:5] in instance method)
Previously these four cases where tangled together. Now, they have
more distinct representations. Specific changes:
1) Unchanged; the object instance is represented by an Expr*.
2) Previously stored the ObjCInterfaceDecl* referring to the class
receiving the message. Now stores a TypeSourceInfo* so that we know
how the class was spelled. This both maintains typedef information
and opens the door for more complicated C++ types (e.g., dependent
types). There was an alternative, unused representation of these
sends by naming the class via an IdentifierInfo *. In practice, we
either had an ObjCInterfaceDecl *, from which we would get the
IdentifierInfo *, or we fell into the case below...
3) Previously represented by a class message whose IdentifierInfo *
referred to "super". Sema and CodeGen would use isStr("super") to
determine if they had a send to super. Now represented as a
"class super" send, where we have both the location of the "super"
keyword and the ObjCInterfaceDecl* of the superclass we're
targetting (statically).
4) Previously represented by an instance message whose receiver is a
an ObjCSuperExpr, which Sema and CodeGen would check for via
isa<ObjCSuperExpr>(). Now represented as an "instance super" send,
where we have both the location of the "super" keyword and the
ObjCInterfaceDecl* of the superclass we're targetting
(statically). Note that ObjCSuperExpr only has one remaining use in
the AST, which is for "super.prop" references.
The new representation of ObjCMessageExpr is 2 pointers smaller than
the old one, since it combines more storage. It also eliminates a leak
when we loaded message-send expressions from a precompiled header. The
representation also feels much cleaner to me; comments welcome!
This patch attempts to maintain the same semantics we previously had
with Objective-C message sends. In several places, there are massive
changes that boil down to simply replacing a nested-if structure such
as:
if (message has a receiver expression) {
// instance message
if (isa<ObjCSuperExpr>(...)) {
// send to super
} else {
// send to an object
}
} else {
// class message
if (name->isStr("super")) {
// class send to super
} else {
// send to class
}
}
with a switch
switch (E->getReceiverKind()) {
case ObjCMessageExpr::SuperInstance: ...
case ObjCMessageExpr::Instance: ...
case ObjCMessageExpr::SuperClass: ...
case ObjCMessageExpr::Class:...
}
There are quite a few places (particularly in the checkers) where
send-to-super is effectively ignored. I've placed FIXMEs in most of
them, and attempted to address send-to-super in a reasonable way. This
could use some review.
llvm-svn: 101972
2010-04-21 08:45:42 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
2010-04-23 01:01:48 +08:00
|
|
|
ObjCInterfaceDecl* ClassDecl = 0;
|
|
|
|
|
|
|
|
// We allow sending a message to a qualified ID ("id<foo>"), which is ok as
|
|
|
|
// long as one of the protocols implements the selector (if not, warn).
|
2012-06-24 02:39:57 +08:00
|
|
|
// And as long as message is not deprecated/unavailable (warn if it is).
|
2010-04-23 01:01:48 +08:00
|
|
|
if (const ObjCObjectPointerType *QIdTy
|
|
|
|
= ReceiverType->getAsObjCQualifiedIdType()) {
|
|
|
|
// Search protocols for instance methods.
|
2011-03-10 06:17:12 +08:00
|
|
|
Method = LookupMethodInQualifiedType(Sel, QIdTy, true);
|
|
|
|
if (!Method)
|
|
|
|
Method = LookupMethodInQualifiedType(Sel, QIdTy, false);
|
2013-05-01 08:24:09 +08:00
|
|
|
if (Method && DiagnoseUseOfDecl(Method, SelLoc))
|
2012-06-24 02:39:57 +08:00
|
|
|
return ExprError();
|
2010-04-23 01:01:48 +08:00
|
|
|
} else if (const ObjCObjectPointerType *OCIType
|
|
|
|
= ReceiverType->getAsObjCInterfacePointerType()) {
|
|
|
|
// We allow sending a message to a pointer to an interface (an object).
|
|
|
|
ClassDecl = OCIType->getInterfaceDecl();
|
2011-06-16 07:02:42 +08:00
|
|
|
|
2011-11-15 06:10:01 +08:00
|
|
|
// Try to complete the type. Under ARC, this is a hard error from which
|
|
|
|
// we don't try to recover.
|
|
|
|
const ObjCInterfaceDecl *forwardClass = 0;
|
|
|
|
if (RequireCompleteType(Loc, OCIType->getPointeeType(),
|
2012-03-11 15:00:24 +08:00
|
|
|
getLangOpts().ObjCAutoRefCount
|
2012-05-05 00:32:21 +08:00
|
|
|
? diag::err_arc_receiver_forward_instance
|
|
|
|
: diag::warn_receiver_forward_instance,
|
|
|
|
Receiver? Receiver->getSourceRange()
|
|
|
|
: SourceRange(SuperLoc))) {
|
2012-03-11 15:00:24 +08:00
|
|
|
if (getLangOpts().ObjCAutoRefCount)
|
2011-11-15 06:10:01 +08:00
|
|
|
return ExprError();
|
|
|
|
|
|
|
|
forwardClass = OCIType->getInterfaceDecl();
|
2012-02-03 09:02:44 +08:00
|
|
|
Diag(Receiver ? Receiver->getLocStart()
|
|
|
|
: SuperLoc, diag::note_receiver_is_id);
|
2011-12-15 13:27:12 +08:00
|
|
|
Method = 0;
|
|
|
|
} else {
|
|
|
|
Method = ClassDecl->lookupInstanceMethod(Sel);
|
2011-06-16 07:02:42 +08:00
|
|
|
}
|
2010-04-23 01:01:48 +08:00
|
|
|
|
2011-03-10 06:17:12 +08:00
|
|
|
if (!Method)
|
2010-04-23 01:01:48 +08:00
|
|
|
// Search protocol qualifiers.
|
2011-03-10 06:17:12 +08:00
|
|
|
Method = LookupMethodInQualifiedType(Sel, OCIType, true);
|
|
|
|
|
2010-04-23 01:01:48 +08:00
|
|
|
if (!Method) {
|
|
|
|
// If we have implementations in scope, check "private" methods.
|
2012-07-28 03:07:44 +08:00
|
|
|
Method = ClassDecl->lookupPrivateMethod(Sel);
|
2010-04-23 01:01:48 +08:00
|
|
|
|
2012-03-11 15:00:24 +08:00
|
|
|
if (!Method && getLangOpts().ObjCAutoRefCount) {
|
2013-05-01 08:24:09 +08:00
|
|
|
Diag(SelLoc, diag::err_arc_may_not_respond)
|
|
|
|
<< OCIType->getPointeeType() << Sel << RecRange
|
2012-11-28 09:27:44 +08:00
|
|
|
<< SourceRange(SelectorLocs.front(), SelectorLocs.back());
|
2011-06-16 07:02:42 +08:00
|
|
|
return ExprError();
|
|
|
|
}
|
|
|
|
|
2011-09-28 00:10:05 +08:00
|
|
|
if (!Method && (!Receiver || !isSelfExpr(Receiver))) {
|
2010-04-23 01:01:48 +08:00
|
|
|
// If we still haven't found a method, look in the global pool. This
|
|
|
|
// behavior isn't very desirable, however we need it for GCC
|
|
|
|
// compatibility. FIXME: should we deviate??
|
|
|
|
if (OCIType->qual_empty()) {
|
|
|
|
Method = LookupInstanceMethodInGlobalPool(Sel,
|
2012-05-13 01:32:52 +08:00
|
|
|
SourceRange(LBracLoc, RBracLoc));
|
2010-12-21 08:44:01 +08:00
|
|
|
if (Method && !forwardClass)
|
2013-05-01 08:24:09 +08:00
|
|
|
Diag(SelLoc, diag::warn_maynot_respond)
|
|
|
|
<< OCIType->getInterfaceDecl()->getIdentifier()
|
|
|
|
<< Sel << RecRange;
|
2010-04-23 01:01:48 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2013-05-01 08:24:09 +08:00
|
|
|
if (Method && DiagnoseUseOfDecl(Method, SelLoc, forwardClass))
|
2010-04-23 01:01:48 +08:00
|
|
|
return ExprError();
|
2011-09-09 14:11:02 +08:00
|
|
|
} else {
|
2013-03-01 17:20:14 +08:00
|
|
|
// Reject other random receiver types (e.g. structs).
|
|
|
|
Diag(Loc, diag::err_bad_receiver_type)
|
|
|
|
<< ReceiverType << Receiver->getSourceRange();
|
|
|
|
return ExprError();
|
2010-04-23 01:01:48 +08:00
|
|
|
}
|
Overhaul the AST representation of Objective-C message send
expressions, to improve source-location information, clarify the
actual receiver of the message, and pave the way for proper C++
support. The ObjCMessageExpr node represents four different kinds of
message sends in a single AST node:
1) Send to a object instance described by an expression (e.g., [x method:5])
2) Send to a class described by the class name (e.g., [NSString method:5])
3) Send to a superclass class (e.g, [super method:5] in class method)
4) Send to a superclass instance (e.g., [super method:5] in instance method)
Previously these four cases where tangled together. Now, they have
more distinct representations. Specific changes:
1) Unchanged; the object instance is represented by an Expr*.
2) Previously stored the ObjCInterfaceDecl* referring to the class
receiving the message. Now stores a TypeSourceInfo* so that we know
how the class was spelled. This both maintains typedef information
and opens the door for more complicated C++ types (e.g., dependent
types). There was an alternative, unused representation of these
sends by naming the class via an IdentifierInfo *. In practice, we
either had an ObjCInterfaceDecl *, from which we would get the
IdentifierInfo *, or we fell into the case below...
3) Previously represented by a class message whose IdentifierInfo *
referred to "super". Sema and CodeGen would use isStr("super") to
determine if they had a send to super. Now represented as a
"class super" send, where we have both the location of the "super"
keyword and the ObjCInterfaceDecl* of the superclass we're
targetting (statically).
4) Previously represented by an instance message whose receiver is a
an ObjCSuperExpr, which Sema and CodeGen would check for via
isa<ObjCSuperExpr>(). Now represented as an "instance super" send,
where we have both the location of the "super" keyword and the
ObjCInterfaceDecl* of the superclass we're targetting
(statically). Note that ObjCSuperExpr only has one remaining use in
the AST, which is for "super.prop" references.
The new representation of ObjCMessageExpr is 2 pointers smaller than
the old one, since it combines more storage. It also eliminates a leak
when we loaded message-send expressions from a precompiled header. The
representation also feels much cleaner to me; comments welcome!
This patch attempts to maintain the same semantics we previously had
with Objective-C message sends. In several places, there are massive
changes that boil down to simply replacing a nested-if structure such
as:
if (message has a receiver expression) {
// instance message
if (isa<ObjCSuperExpr>(...)) {
// send to super
} else {
// send to an object
}
} else {
// class message
if (name->isStr("super")) {
// class send to super
} else {
// send to class
}
}
with a switch
switch (E->getReceiverKind()) {
case ObjCMessageExpr::SuperInstance: ...
case ObjCMessageExpr::Instance: ...
case ObjCMessageExpr::SuperClass: ...
case ObjCMessageExpr::Class:...
}
There are quite a few places (particularly in the checkers) where
send-to-super is effectively ignored. I've placed FIXMEs in most of
them, and attempted to address send-to-super in a reasonable way. This
could use some review.
llvm-svn: 101972
2010-04-21 08:45:42 +08:00
|
|
|
}
|
2008-07-21 13:57:44 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2013-12-04 05:11:43 +08:00
|
|
|
if (Method && Method->getMethodFamily() == OMF_init &&
|
|
|
|
getCurFunction()->ObjCIsDesignatedInit &&
|
|
|
|
(SuperLoc.isValid() || isSelfExpr(Receiver))) {
|
|
|
|
bool isDesignatedInitChain = false;
|
|
|
|
if (SuperLoc.isValid()) {
|
|
|
|
if (const ObjCObjectPointerType *
|
|
|
|
OCIType = ReceiverType->getAsObjCInterfacePointerType()) {
|
|
|
|
if (const ObjCInterfaceDecl *ID = OCIType->getInterfaceDecl()) {
|
2013-12-13 11:48:17 +08:00
|
|
|
// Either we know this is a designated initializer or we
|
|
|
|
// conservatively assume it because we don't know for sure.
|
|
|
|
if (!ID->declaresOrInheritsDesignatedInitializers() ||
|
|
|
|
ID->isDesignatedInitializer(Sel)) {
|
2013-12-04 05:11:43 +08:00
|
|
|
isDesignatedInitChain = true;
|
|
|
|
getCurFunction()->ObjCWarnForNoDesignatedInitChain = false;
|
|
|
|
}
|
|
|
|
}
|
2013-12-04 05:11:36 +08:00
|
|
|
}
|
|
|
|
}
|
2013-12-04 05:11:43 +08:00
|
|
|
if (!isDesignatedInitChain) {
|
|
|
|
const ObjCMethodDecl *InitMethod = 0;
|
|
|
|
bool isDesignated =
|
|
|
|
getCurMethodDecl()->isDesignatedInitializerForTheInterface(&InitMethod);
|
|
|
|
assert(isDesignated && InitMethod);
|
|
|
|
(void)isDesignated;
|
|
|
|
Diag(SelLoc, SuperLoc.isValid() ?
|
|
|
|
diag::warn_objc_designated_init_non_designated_init_call :
|
|
|
|
diag::warn_objc_designated_init_non_super_designated_init_call);
|
|
|
|
Diag(InitMethod->getLocation(),
|
|
|
|
diag::note_objc_designated_init_marked_here);
|
|
|
|
}
|
2013-12-04 05:11:36 +08:00
|
|
|
}
|
|
|
|
|
2013-12-04 05:11:49 +08:00
|
|
|
if (Method && Method->getMethodFamily() == OMF_init &&
|
|
|
|
getCurFunction()->ObjCIsSecondaryInit &&
|
|
|
|
(SuperLoc.isValid() || isSelfExpr(Receiver))) {
|
|
|
|
if (SuperLoc.isValid()) {
|
|
|
|
Diag(SelLoc, diag::warn_objc_secondary_init_super_init_call);
|
|
|
|
} else {
|
|
|
|
getCurFunction()->ObjCWarnForNoInitDelegation = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Rework the Parser-Sema interaction for Objective-C message
sends. Major changes include:
- Expanded the interface from two actions (ActOnInstanceMessage,
ActOnClassMessage), where ActOnClassMessage also handled sends to
"super" by checking whether the identifier was "super", to three
actions (ActOnInstanceMessage, ActOnClassMessage,
ActOnSuperMessage). Code completion has the same changes.
- The parser now resolves the type to which we are sending a class
message, so ActOnClassMessage now accepts a TypeTy* (rather than
an IdentifierInfo *). This opens the door to more interesting
types (for Objective-C++ support).
- Split ActOnInstanceMessage and ActOnClassMessage into parser
action functions (with their original names) and semantic
functions (BuildInstanceMessage and BuildClassMessage,
respectively). At present, this split is onyl used by
ActOnSuperMessage, which decides which kind of super message it
has and forwards to the appropriate Build*Message. In the future,
Build*Message will be used by template instantiation.
- Use getObjCMessageKind() within the disambiguation of Objective-C
message sends vs. array designators.
Two notes about substandard bits in this patch:
- There is some redundancy in the code in ParseObjCMessageExpr and
ParseInitializerWithPotentialDesignator; this will be addressed
shortly by centralizing the mapping from identifiers to type names
for the message receiver.
- There is some #if 0'd code that won't likely ever be used---it
handles the use of 'super' in methods whose class does not have a
superclass---but could be used to model GCC's behavior more
closely. This code will die in my next check-in, but I want it in
Subversion.
llvm-svn: 102021
2010-04-22 03:57:20 +08:00
|
|
|
// Check the message arguments.
|
|
|
|
unsigned NumArgs = ArgsIn.size();
|
2012-08-24 07:38:35 +08:00
|
|
|
Expr **Args = ArgsIn.data();
|
Rework the Parser-Sema interaction for Objective-C message
sends. Major changes include:
- Expanded the interface from two actions (ActOnInstanceMessage,
ActOnClassMessage), where ActOnClassMessage also handled sends to
"super" by checking whether the identifier was "super", to three
actions (ActOnInstanceMessage, ActOnClassMessage,
ActOnSuperMessage). Code completion has the same changes.
- The parser now resolves the type to which we are sending a class
message, so ActOnClassMessage now accepts a TypeTy* (rather than
an IdentifierInfo *). This opens the door to more interesting
types (for Objective-C++ support).
- Split ActOnInstanceMessage and ActOnClassMessage into parser
action functions (with their original names) and semantic
functions (BuildInstanceMessage and BuildClassMessage,
respectively). At present, this split is onyl used by
ActOnSuperMessage, which decides which kind of super message it
has and forwards to the appropriate Build*Message. In the future,
Build*Message will be used by template instantiation.
- Use getObjCMessageKind() within the disambiguation of Objective-C
message sends vs. array designators.
Two notes about substandard bits in this patch:
- There is some redundancy in the code in ParseObjCMessageExpr and
ParseInitializerWithPotentialDesignator; this will be addressed
shortly by centralizing the mapping from identifiers to type names
for the message receiver.
- There is some #if 0'd code that won't likely ever be used---it
handles the use of 'super' in methods whose class does not have a
superclass---but could be used to model GCC's behavior more
closely. This code will die in my next check-in, but I want it in
Subversion.
llvm-svn: 102021
2010-04-22 03:57:20 +08:00
|
|
|
QualType ReturnType;
|
2010-11-18 14:31:45 +08:00
|
|
|
ExprValueKind VK = VK_RValue;
|
2010-12-01 09:07:24 +08:00
|
|
|
bool ClassMessage = (ReceiverType->isObjCClassType() ||
|
|
|
|
ReceiverType->isObjCQualifiedClassType());
|
2013-05-10 08:27:15 +08:00
|
|
|
if (CheckMessageArgumentTypes(ReceiverType, MultiExprArg(Args, NumArgs),
|
|
|
|
Sel, SelectorLocs, Method,
|
2011-06-11 09:09:30 +08:00
|
|
|
ClassMessage, SuperLoc.isValid(),
|
2010-11-18 14:31:45 +08:00
|
|
|
LBracLoc, RBracLoc, ReturnType, VK))
|
Rework the Parser-Sema interaction for Objective-C message
sends. Major changes include:
- Expanded the interface from two actions (ActOnInstanceMessage,
ActOnClassMessage), where ActOnClassMessage also handled sends to
"super" by checking whether the identifier was "super", to three
actions (ActOnInstanceMessage, ActOnClassMessage,
ActOnSuperMessage). Code completion has the same changes.
- The parser now resolves the type to which we are sending a class
message, so ActOnClassMessage now accepts a TypeTy* (rather than
an IdentifierInfo *). This opens the door to more interesting
types (for Objective-C++ support).
- Split ActOnInstanceMessage and ActOnClassMessage into parser
action functions (with their original names) and semantic
functions (BuildInstanceMessage and BuildClassMessage,
respectively). At present, this split is onyl used by
ActOnSuperMessage, which decides which kind of super message it
has and forwards to the appropriate Build*Message. In the future,
Build*Message will be used by template instantiation.
- Use getObjCMessageKind() within the disambiguation of Objective-C
message sends vs. array designators.
Two notes about substandard bits in this patch:
- There is some redundancy in the code in ParseObjCMessageExpr and
ParseInitializerWithPotentialDesignator; this will be addressed
shortly by centralizing the mapping from identifiers to type names
for the message receiver.
- There is some #if 0'd code that won't likely ever be used---it
handles the use of 'super' in methods whose class does not have a
superclass---but could be used to model GCC's behavior more
closely. This code will die in my next check-in, but I want it in
Subversion.
llvm-svn: 102021
2010-04-22 03:57:20 +08:00
|
|
|
return ExprError();
|
2010-06-17 03:56:08 +08:00
|
|
|
|
2011-01-11 11:23:19 +08:00
|
|
|
if (Method && !Method->getResultType()->isVoidType() &&
|
|
|
|
RequireCompleteType(LBracLoc, Method->getResultType(),
|
|
|
|
diag::err_illegal_message_expr_incomplete_type))
|
|
|
|
return ExprError();
|
Overhaul the AST representation of Objective-C message send
expressions, to improve source-location information, clarify the
actual receiver of the message, and pave the way for proper C++
support. The ObjCMessageExpr node represents four different kinds of
message sends in a single AST node:
1) Send to a object instance described by an expression (e.g., [x method:5])
2) Send to a class described by the class name (e.g., [NSString method:5])
3) Send to a superclass class (e.g, [super method:5] in class method)
4) Send to a superclass instance (e.g., [super method:5] in instance method)
Previously these four cases where tangled together. Now, they have
more distinct representations. Specific changes:
1) Unchanged; the object instance is represented by an Expr*.
2) Previously stored the ObjCInterfaceDecl* referring to the class
receiving the message. Now stores a TypeSourceInfo* so that we know
how the class was spelled. This both maintains typedef information
and opens the door for more complicated C++ types (e.g., dependent
types). There was an alternative, unused representation of these
sends by naming the class via an IdentifierInfo *. In practice, we
either had an ObjCInterfaceDecl *, from which we would get the
IdentifierInfo *, or we fell into the case below...
3) Previously represented by a class message whose IdentifierInfo *
referred to "super". Sema and CodeGen would use isStr("super") to
determine if they had a send to super. Now represented as a
"class super" send, where we have both the location of the "super"
keyword and the ObjCInterfaceDecl* of the superclass we're
targetting (statically).
4) Previously represented by an instance message whose receiver is a
an ObjCSuperExpr, which Sema and CodeGen would check for via
isa<ObjCSuperExpr>(). Now represented as an "instance super" send,
where we have both the location of the "super" keyword and the
ObjCInterfaceDecl* of the superclass we're targetting
(statically). Note that ObjCSuperExpr only has one remaining use in
the AST, which is for "super.prop" references.
The new representation of ObjCMessageExpr is 2 pointers smaller than
the old one, since it combines more storage. It also eliminates a leak
when we loaded message-send expressions from a precompiled header. The
representation also feels much cleaner to me; comments welcome!
This patch attempts to maintain the same semantics we previously had
with Objective-C message sends. In several places, there are massive
changes that boil down to simply replacing a nested-if structure such
as:
if (message has a receiver expression) {
// instance message
if (isa<ObjCSuperExpr>(...)) {
// send to super
} else {
// send to an object
}
} else {
// class message
if (name->isStr("super")) {
// class send to super
} else {
// send to class
}
}
with a switch
switch (E->getReceiverKind()) {
case ObjCMessageExpr::SuperInstance: ...
case ObjCMessageExpr::Instance: ...
case ObjCMessageExpr::SuperClass: ...
case ObjCMessageExpr::Class:...
}
There are quite a few places (particularly in the checkers) where
send-to-super is effectively ignored. I've placed FIXMEs in most of
them, and attempted to address send-to-super in a reasonable way. This
could use some review.
llvm-svn: 101972
2010-04-21 08:45:42 +08:00
|
|
|
|
2011-06-16 07:02:42 +08:00
|
|
|
// In ARC, forbid the user from sending messages to
|
|
|
|
// retain/release/autorelease/dealloc/retainCount explicitly.
|
2012-03-11 15:00:24 +08:00
|
|
|
if (getLangOpts().ObjCAutoRefCount) {
|
2011-06-16 07:02:42 +08:00
|
|
|
ObjCMethodFamily family =
|
|
|
|
(Method ? Method->getMethodFamily() : Sel.getMethodFamily());
|
|
|
|
switch (family) {
|
|
|
|
case OMF_init:
|
|
|
|
if (Method)
|
|
|
|
checkInitMethod(Method, ReceiverType);
|
|
|
|
|
|
|
|
case OMF_None:
|
|
|
|
case OMF_alloc:
|
|
|
|
case OMF_copy:
|
2011-08-29 06:35:17 +08:00
|
|
|
case OMF_finalize:
|
2011-06-16 07:02:42 +08:00
|
|
|
case OMF_mutableCopy:
|
|
|
|
case OMF_new:
|
|
|
|
case OMF_self:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OMF_dealloc:
|
|
|
|
case OMF_retain:
|
|
|
|
case OMF_release:
|
|
|
|
case OMF_autorelease:
|
|
|
|
case OMF_retainCount:
|
2013-05-01 08:24:09 +08:00
|
|
|
Diag(SelLoc, diag::err_arc_illegal_explicit_message)
|
|
|
|
<< Sel << RecRange;
|
2011-06-16 07:02:42 +08:00
|
|
|
break;
|
2011-07-06 06:38:59 +08:00
|
|
|
|
|
|
|
case OMF_performSelector:
|
|
|
|
if (Method && NumArgs >= 1) {
|
|
|
|
if (ObjCSelectorExpr *SelExp = dyn_cast<ObjCSelectorExpr>(Args[0])) {
|
|
|
|
Selector ArgSel = SelExp->getSelector();
|
|
|
|
ObjCMethodDecl *SelMethod =
|
|
|
|
LookupInstanceMethodInGlobalPool(ArgSel,
|
|
|
|
SelExp->getSourceRange());
|
|
|
|
if (!SelMethod)
|
|
|
|
SelMethod =
|
|
|
|
LookupFactoryMethodInGlobalPool(ArgSel,
|
|
|
|
SelExp->getSourceRange());
|
|
|
|
if (SelMethod) {
|
|
|
|
ObjCMethodFamily SelFamily = SelMethod->getMethodFamily();
|
|
|
|
switch (SelFamily) {
|
|
|
|
case OMF_alloc:
|
|
|
|
case OMF_copy:
|
|
|
|
case OMF_mutableCopy:
|
|
|
|
case OMF_new:
|
|
|
|
case OMF_self:
|
|
|
|
case OMF_init:
|
|
|
|
// Issue error, unless ns_returns_not_retained.
|
|
|
|
if (!SelMethod->hasAttr<NSReturnsNotRetainedAttr>()) {
|
|
|
|
// selector names a +1 method
|
2011-10-03 14:36:17 +08:00
|
|
|
Diag(SelLoc,
|
2011-07-06 06:38:59 +08:00
|
|
|
diag::err_arc_perform_selector_retains);
|
2012-02-28 06:55:11 +08:00
|
|
|
Diag(SelMethod->getLocation(), diag::note_method_declared_at)
|
|
|
|
<< SelMethod->getDeclName();
|
2011-07-06 06:38:59 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
// +0 call. OK. unless ns_returns_retained.
|
|
|
|
if (SelMethod->hasAttr<NSReturnsRetainedAttr>()) {
|
|
|
|
// selector names a +1 method
|
2011-10-03 14:36:17 +08:00
|
|
|
Diag(SelLoc,
|
2011-07-06 06:38:59 +08:00
|
|
|
diag::err_arc_perform_selector_retains);
|
2012-02-28 06:55:11 +08:00
|
|
|
Diag(SelMethod->getLocation(), diag::note_method_declared_at)
|
|
|
|
<< SelMethod->getDeclName();
|
2011-07-06 06:38:59 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// error (may leak).
|
2011-10-03 14:36:17 +08:00
|
|
|
Diag(SelLoc, diag::warn_arc_perform_selector_leaks);
|
2011-07-06 06:38:59 +08:00
|
|
|
Diag(Args[0]->getExprLoc(), diag::note_used_here);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2011-06-16 07:02:42 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Rework the Parser-Sema interaction for Objective-C message
sends. Major changes include:
- Expanded the interface from two actions (ActOnInstanceMessage,
ActOnClassMessage), where ActOnClassMessage also handled sends to
"super" by checking whether the identifier was "super", to three
actions (ActOnInstanceMessage, ActOnClassMessage,
ActOnSuperMessage). Code completion has the same changes.
- The parser now resolves the type to which we are sending a class
message, so ActOnClassMessage now accepts a TypeTy* (rather than
an IdentifierInfo *). This opens the door to more interesting
types (for Objective-C++ support).
- Split ActOnInstanceMessage and ActOnClassMessage into parser
action functions (with their original names) and semantic
functions (BuildInstanceMessage and BuildClassMessage,
respectively). At present, this split is onyl used by
ActOnSuperMessage, which decides which kind of super message it
has and forwards to the appropriate Build*Message. In the future,
Build*Message will be used by template instantiation.
- Use getObjCMessageKind() within the disambiguation of Objective-C
message sends vs. array designators.
Two notes about substandard bits in this patch:
- There is some redundancy in the code in ParseObjCMessageExpr and
ParseInitializerWithPotentialDesignator; this will be addressed
shortly by centralizing the mapping from identifiers to type names
for the message receiver.
- There is some #if 0'd code that won't likely ever be used---it
handles the use of 'super' in methods whose class does not have a
superclass---but could be used to model GCC's behavior more
closely. This code will die in my next check-in, but I want it in
Subversion.
llvm-svn: 102021
2010-04-22 03:57:20 +08:00
|
|
|
// Construct the appropriate ObjCMessageExpr instance.
|
2011-06-16 07:02:42 +08:00
|
|
|
ObjCMessageExpr *Result;
|
Rework the Parser-Sema interaction for Objective-C message
sends. Major changes include:
- Expanded the interface from two actions (ActOnInstanceMessage,
ActOnClassMessage), where ActOnClassMessage also handled sends to
"super" by checking whether the identifier was "super", to three
actions (ActOnInstanceMessage, ActOnClassMessage,
ActOnSuperMessage). Code completion has the same changes.
- The parser now resolves the type to which we are sending a class
message, so ActOnClassMessage now accepts a TypeTy* (rather than
an IdentifierInfo *). This opens the door to more interesting
types (for Objective-C++ support).
- Split ActOnInstanceMessage and ActOnClassMessage into parser
action functions (with their original names) and semantic
functions (BuildInstanceMessage and BuildClassMessage,
respectively). At present, this split is onyl used by
ActOnSuperMessage, which decides which kind of super message it
has and forwards to the appropriate Build*Message. In the future,
Build*Message will be used by template instantiation.
- Use getObjCMessageKind() within the disambiguation of Objective-C
message sends vs. array designators.
Two notes about substandard bits in this patch:
- There is some redundancy in the code in ParseObjCMessageExpr and
ParseInitializerWithPotentialDesignator; this will be addressed
shortly by centralizing the mapping from identifiers to type names
for the message receiver.
- There is some #if 0'd code that won't likely ever be used---it
handles the use of 'super' in methods whose class does not have a
superclass---but could be used to model GCC's behavior more
closely. This code will die in my next check-in, but I want it in
Subversion.
llvm-svn: 102021
2010-04-22 03:57:20 +08:00
|
|
|
if (SuperLoc.isValid())
|
2010-11-18 14:31:45 +08:00
|
|
|
Result = ObjCMessageExpr::Create(Context, ReturnType, VK, LBracLoc,
|
2010-05-22 13:17:18 +08:00
|
|
|
SuperLoc, /*IsInstanceSuper=*/true,
|
2011-10-03 14:36:17 +08:00
|
|
|
ReceiverType, Sel, SelectorLocs, Method,
|
2012-01-12 10:34:39 +08:00
|
|
|
makeArrayRef(Args, NumArgs), RBracLoc,
|
|
|
|
isImplicit);
|
2012-03-07 04:05:56 +08:00
|
|
|
else {
|
2010-11-18 14:31:45 +08:00
|
|
|
Result = ObjCMessageExpr::Create(Context, ReturnType, VK, LBracLoc,
|
2011-10-03 14:36:17 +08:00
|
|
|
Receiver, Sel, SelectorLocs, Method,
|
2012-01-12 10:34:39 +08:00
|
|
|
makeArrayRef(Args, NumArgs), RBracLoc,
|
|
|
|
isImplicit);
|
2012-03-07 04:05:56 +08:00
|
|
|
if (!isImplicit)
|
|
|
|
checkCocoaAPI(*this, Result);
|
|
|
|
}
|
2011-06-16 07:02:42 +08:00
|
|
|
|
2012-03-11 15:00:24 +08:00
|
|
|
if (getLangOpts().ObjCAutoRefCount) {
|
2012-04-20 07:49:39 +08:00
|
|
|
DiagnoseARCUseOfWeakReceiver(*this, Receiver);
|
2012-04-05 04:05:25 +08:00
|
|
|
|
2011-06-16 07:02:42 +08:00
|
|
|
// In ARC, annotate delegate init calls.
|
|
|
|
if (Result->getMethodFamily() == OMF_init &&
|
2011-09-28 00:10:05 +08:00
|
|
|
(SuperLoc.isValid() || isSelfExpr(Receiver))) {
|
2011-06-16 07:02:42 +08:00
|
|
|
// Only consider init calls *directly* in init implementations,
|
|
|
|
// not within blocks.
|
|
|
|
ObjCMethodDecl *method = dyn_cast<ObjCMethodDecl>(CurContext);
|
|
|
|
if (method && method->getMethodFamily() == OMF_init) {
|
|
|
|
// The implicit assignment to self means we also don't want to
|
|
|
|
// consume the result.
|
|
|
|
Result->setDelegateInitCall(true);
|
|
|
|
return Owned(Result);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// In ARC, check for message sends which are likely to introduce
|
|
|
|
// retain cycles.
|
|
|
|
checkRetainCycles(Result);
|
-Warc-repeated-use-of-weak: Check messages to property accessors as well.
Previously, [foo weakProp] was not being treated the same as foo.weakProp.
Now, for every explicit message send, we check if it's a property access,
and if so, if the property is weak. Then for every assignment of a
message, we have to do the same thing again.
This is a potentially expensive increase because determining whether a
method is a property accessor requires searching through the methods it
overrides. However, without it -Warc-repeated-use-of-weak will miss cases
from people who prefer not to use dot syntax. If this turns out to be
too expensive, we can try caching the result somewhere, or even lose
precision by not checking superclass methods. The warning is off-by-default,
though.
<rdar://problem/12407765>
llvm-svn: 165718
2012-10-12 00:06:21 +08:00
|
|
|
|
|
|
|
if (!isImplicit && Method) {
|
|
|
|
if (const ObjCPropertyDecl *Prop = Method->findPropertyDecl()) {
|
|
|
|
bool IsWeak =
|
|
|
|
Prop->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_weak;
|
|
|
|
if (!IsWeak && Sel.isUnarySelector())
|
|
|
|
IsWeak = ReturnType.getObjCLifetime() & Qualifiers::OCL_Weak;
|
|
|
|
|
|
|
|
if (IsWeak) {
|
|
|
|
DiagnosticsEngine::Level Level =
|
|
|
|
Diags.getDiagnosticLevel(diag::warn_arc_repeated_use_of_weak,
|
|
|
|
LBracLoc);
|
|
|
|
if (Level != DiagnosticsEngine::Ignored)
|
|
|
|
getCurFunction()->recordUseOfWeak(Result, Prop);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2011-06-16 07:02:42 +08:00
|
|
|
}
|
|
|
|
|
2010-05-22 13:17:18 +08:00
|
|
|
return MaybeBindToTemporary(Result);
|
Rework the Parser-Sema interaction for Objective-C message
sends. Major changes include:
- Expanded the interface from two actions (ActOnInstanceMessage,
ActOnClassMessage), where ActOnClassMessage also handled sends to
"super" by checking whether the identifier was "super", to three
actions (ActOnInstanceMessage, ActOnClassMessage,
ActOnSuperMessage). Code completion has the same changes.
- The parser now resolves the type to which we are sending a class
message, so ActOnClassMessage now accepts a TypeTy* (rather than
an IdentifierInfo *). This opens the door to more interesting
types (for Objective-C++ support).
- Split ActOnInstanceMessage and ActOnClassMessage into parser
action functions (with their original names) and semantic
functions (BuildInstanceMessage and BuildClassMessage,
respectively). At present, this split is onyl used by
ActOnSuperMessage, which decides which kind of super message it
has and forwards to the appropriate Build*Message. In the future,
Build*Message will be used by template instantiation.
- Use getObjCMessageKind() within the disambiguation of Objective-C
message sends vs. array designators.
Two notes about substandard bits in this patch:
- There is some redundancy in the code in ParseObjCMessageExpr and
ParseInitializerWithPotentialDesignator; this will be addressed
shortly by centralizing the mapping from identifiers to type names
for the message receiver.
- There is some #if 0'd code that won't likely ever be used---it
handles the use of 'super' in methods whose class does not have a
superclass---but could be used to model GCC's behavior more
closely. This code will die in my next check-in, but I want it in
Subversion.
llvm-svn: 102021
2010-04-22 03:57:20 +08:00
|
|
|
}
|
|
|
|
|
2013-01-23 02:35:43 +08:00
|
|
|
static void RemoveSelectorFromWarningCache(Sema &S, Expr* Arg) {
|
|
|
|
if (ObjCSelectorExpr *OSE =
|
|
|
|
dyn_cast<ObjCSelectorExpr>(Arg->IgnoreParenCasts())) {
|
|
|
|
Selector Sel = OSE->getSelector();
|
|
|
|
SourceLocation Loc = OSE->getAtLoc();
|
|
|
|
llvm::DenseMap<Selector, SourceLocation>::iterator Pos
|
|
|
|
= S.ReferencedSelectors.find(Sel);
|
|
|
|
if (Pos != S.ReferencedSelectors.end() && Pos->second == Loc)
|
|
|
|
S.ReferencedSelectors.erase(Pos);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Rework the Parser-Sema interaction for Objective-C message
sends. Major changes include:
- Expanded the interface from two actions (ActOnInstanceMessage,
ActOnClassMessage), where ActOnClassMessage also handled sends to
"super" by checking whether the identifier was "super", to three
actions (ActOnInstanceMessage, ActOnClassMessage,
ActOnSuperMessage). Code completion has the same changes.
- The parser now resolves the type to which we are sending a class
message, so ActOnClassMessage now accepts a TypeTy* (rather than
an IdentifierInfo *). This opens the door to more interesting
types (for Objective-C++ support).
- Split ActOnInstanceMessage and ActOnClassMessage into parser
action functions (with their original names) and semantic
functions (BuildInstanceMessage and BuildClassMessage,
respectively). At present, this split is onyl used by
ActOnSuperMessage, which decides which kind of super message it
has and forwards to the appropriate Build*Message. In the future,
Build*Message will be used by template instantiation.
- Use getObjCMessageKind() within the disambiguation of Objective-C
message sends vs. array designators.
Two notes about substandard bits in this patch:
- There is some redundancy in the code in ParseObjCMessageExpr and
ParseInitializerWithPotentialDesignator; this will be addressed
shortly by centralizing the mapping from identifiers to type names
for the message receiver.
- There is some #if 0'd code that won't likely ever be used---it
handles the use of 'super' in methods whose class does not have a
superclass---but could be used to model GCC's behavior more
closely. This code will die in my next check-in, but I want it in
Subversion.
llvm-svn: 102021
2010-04-22 03:57:20 +08:00
|
|
|
// ActOnInstanceMessage - used for both unary and keyword messages.
|
|
|
|
// ArgExprs is optional - if it is present, the number of expressions
|
|
|
|
// is obtained from Sel.getNumArgs().
|
2010-08-24 14:29:42 +08:00
|
|
|
ExprResult Sema::ActOnInstanceMessage(Scope *S,
|
|
|
|
Expr *Receiver,
|
|
|
|
Selector Sel,
|
|
|
|
SourceLocation LBracLoc,
|
2011-10-03 14:36:17 +08:00
|
|
|
ArrayRef<SourceLocation> SelectorLocs,
|
2010-08-24 14:29:42 +08:00
|
|
|
SourceLocation RBracLoc,
|
|
|
|
MultiExprArg Args) {
|
Rework the Parser-Sema interaction for Objective-C message
sends. Major changes include:
- Expanded the interface from two actions (ActOnInstanceMessage,
ActOnClassMessage), where ActOnClassMessage also handled sends to
"super" by checking whether the identifier was "super", to three
actions (ActOnInstanceMessage, ActOnClassMessage,
ActOnSuperMessage). Code completion has the same changes.
- The parser now resolves the type to which we are sending a class
message, so ActOnClassMessage now accepts a TypeTy* (rather than
an IdentifierInfo *). This opens the door to more interesting
types (for Objective-C++ support).
- Split ActOnInstanceMessage and ActOnClassMessage into parser
action functions (with their original names) and semantic
functions (BuildInstanceMessage and BuildClassMessage,
respectively). At present, this split is onyl used by
ActOnSuperMessage, which decides which kind of super message it
has and forwards to the appropriate Build*Message. In the future,
Build*Message will be used by template instantiation.
- Use getObjCMessageKind() within the disambiguation of Objective-C
message sends vs. array designators.
Two notes about substandard bits in this patch:
- There is some redundancy in the code in ParseObjCMessageExpr and
ParseInitializerWithPotentialDesignator; this will be addressed
shortly by centralizing the mapping from identifiers to type names
for the message receiver.
- There is some #if 0'd code that won't likely ever be used---it
handles the use of 'super' in methods whose class does not have a
superclass---but could be used to model GCC's behavior more
closely. This code will die in my next check-in, but I want it in
Subversion.
llvm-svn: 102021
2010-04-22 03:57:20 +08:00
|
|
|
if (!Receiver)
|
|
|
|
return ExprError();
|
2013-02-16 02:34:15 +08:00
|
|
|
|
|
|
|
// A ParenListExpr can show up while doing error recovery with invalid code.
|
|
|
|
if (isa<ParenListExpr>(Receiver)) {
|
|
|
|
ExprResult Result = MaybeConvertParenListExprToParenExpr(S, Receiver);
|
|
|
|
if (Result.isInvalid()) return ExprError();
|
|
|
|
Receiver = Result.take();
|
|
|
|
}
|
2013-01-23 03:05:17 +08:00
|
|
|
|
|
|
|
if (RespondsToSelectorSel.isNull()) {
|
|
|
|
IdentifierInfo *SelectorId = &Context.Idents.get("respondsToSelector");
|
|
|
|
RespondsToSelectorSel = Context.Selectors.getUnarySelector(SelectorId);
|
|
|
|
}
|
|
|
|
if (Sel == RespondsToSelectorSel)
|
2013-01-23 02:35:43 +08:00
|
|
|
RemoveSelectorFromWarningCache(*this, Args[0]);
|
|
|
|
|
2010-08-24 07:25:46 +08:00
|
|
|
return BuildInstanceMessage(Receiver, Receiver->getType(),
|
2010-04-23 01:01:48 +08:00
|
|
|
/*SuperLoc=*/SourceLocation(), Sel, /*Method=*/0,
|
2012-08-24 05:35:17 +08:00
|
|
|
LBracLoc, SelectorLocs, RBracLoc, Args);
|
2008-01-05 06:32:30 +08:00
|
|
|
}
|
2008-04-07 13:30:13 +08:00
|
|
|
|
2011-06-16 07:02:42 +08:00
|
|
|
enum ARCConversionTypeClass {
|
2011-10-01 09:01:08 +08:00
|
|
|
/// int, void, struct A
|
2011-06-16 07:02:42 +08:00
|
|
|
ACTC_none,
|
2011-10-01 09:01:08 +08:00
|
|
|
|
|
|
|
/// id, void (^)()
|
2011-06-16 07:02:42 +08:00
|
|
|
ACTC_retainable,
|
2011-10-01 09:01:08 +08:00
|
|
|
|
|
|
|
/// id*, id***, void (^*)(),
|
|
|
|
ACTC_indirectRetainable,
|
|
|
|
|
|
|
|
/// void* might be a normal C type, or it might a CF type.
|
|
|
|
ACTC_voidPtr,
|
|
|
|
|
|
|
|
/// struct A*
|
|
|
|
ACTC_coreFoundation
|
2011-06-16 07:02:42 +08:00
|
|
|
};
|
2011-10-01 09:01:08 +08:00
|
|
|
static bool isAnyRetainable(ARCConversionTypeClass ACTC) {
|
|
|
|
return (ACTC == ACTC_retainable ||
|
|
|
|
ACTC == ACTC_coreFoundation ||
|
|
|
|
ACTC == ACTC_voidPtr);
|
|
|
|
}
|
|
|
|
static bool isAnyCLike(ARCConversionTypeClass ACTC) {
|
|
|
|
return ACTC == ACTC_none ||
|
|
|
|
ACTC == ACTC_voidPtr ||
|
|
|
|
ACTC == ACTC_coreFoundation;
|
|
|
|
}
|
|
|
|
|
2011-06-16 07:02:42 +08:00
|
|
|
static ARCConversionTypeClass classifyTypeForARCConversion(QualType type) {
|
2011-10-01 09:01:08 +08:00
|
|
|
bool isIndirect = false;
|
2011-06-16 07:02:42 +08:00
|
|
|
|
|
|
|
// Ignore an outermost reference type.
|
2011-10-01 09:01:08 +08:00
|
|
|
if (const ReferenceType *ref = type->getAs<ReferenceType>()) {
|
2011-06-16 07:02:42 +08:00
|
|
|
type = ref->getPointeeType();
|
2011-10-01 09:01:08 +08:00
|
|
|
isIndirect = true;
|
|
|
|
}
|
2011-06-16 07:02:42 +08:00
|
|
|
|
|
|
|
// Drill through pointers and arrays recursively.
|
|
|
|
while (true) {
|
|
|
|
if (const PointerType *ptr = type->getAs<PointerType>()) {
|
|
|
|
type = ptr->getPointeeType();
|
2011-10-01 09:01:08 +08:00
|
|
|
|
|
|
|
// The first level of pointer may be the innermost pointer on a CF type.
|
|
|
|
if (!isIndirect) {
|
|
|
|
if (type->isVoidType()) return ACTC_voidPtr;
|
|
|
|
if (type->isRecordType()) return ACTC_coreFoundation;
|
|
|
|
}
|
2011-06-16 07:02:42 +08:00
|
|
|
} else if (const ArrayType *array = type->getAsArrayTypeUnsafe()) {
|
|
|
|
type = QualType(array->getElementType()->getBaseElementTypeUnsafe(), 0);
|
|
|
|
} else {
|
|
|
|
break;
|
|
|
|
}
|
2011-10-01 09:01:08 +08:00
|
|
|
isIndirect = true;
|
2011-06-16 07:02:42 +08:00
|
|
|
}
|
|
|
|
|
2011-10-01 09:01:08 +08:00
|
|
|
if (isIndirect) {
|
|
|
|
if (type->isObjCARCBridgableType())
|
|
|
|
return ACTC_indirectRetainable;
|
|
|
|
return ACTC_none;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (type->isObjCARCBridgableType())
|
|
|
|
return ACTC_retainable;
|
|
|
|
|
|
|
|
return ACTC_none;
|
2011-06-16 07:02:42 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
namespace {
|
2011-10-01 09:01:08 +08:00
|
|
|
/// A result from the cast checker.
|
|
|
|
enum ACCResult {
|
|
|
|
/// Cannot be casted.
|
|
|
|
ACC_invalid,
|
|
|
|
|
|
|
|
/// Can be safely retained or not retained.
|
|
|
|
ACC_bottom,
|
|
|
|
|
|
|
|
/// Can be casted at +0.
|
|
|
|
ACC_plusZero,
|
|
|
|
|
|
|
|
/// Can be casted at +1.
|
|
|
|
ACC_plusOne
|
|
|
|
};
|
|
|
|
ACCResult merge(ACCResult left, ACCResult right) {
|
|
|
|
if (left == right) return left;
|
|
|
|
if (left == ACC_bottom) return right;
|
|
|
|
if (right == ACC_bottom) return left;
|
|
|
|
return ACC_invalid;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// A checker which white-lists certain expressions whose conversion
|
|
|
|
/// to or from retainable type would otherwise be forbidden in ARC.
|
|
|
|
class ARCCastChecker : public StmtVisitor<ARCCastChecker, ACCResult> {
|
|
|
|
typedef StmtVisitor<ARCCastChecker, ACCResult> super;
|
|
|
|
|
2011-06-16 07:02:42 +08:00
|
|
|
ASTContext &Context;
|
2011-10-01 09:01:08 +08:00
|
|
|
ARCConversionTypeClass SourceClass;
|
|
|
|
ARCConversionTypeClass TargetClass;
|
2012-07-28 06:37:07 +08:00
|
|
|
bool Diagnose;
|
2011-10-01 09:01:08 +08:00
|
|
|
|
|
|
|
static bool isCFType(QualType type) {
|
|
|
|
// Someday this can use ns_bridged. For now, it has to do this.
|
|
|
|
return type->isCARCBridgableType();
|
2011-06-16 07:02:42 +08:00
|
|
|
}
|
2011-10-01 09:01:08 +08:00
|
|
|
|
|
|
|
public:
|
|
|
|
ARCCastChecker(ASTContext &Context, ARCConversionTypeClass source,
|
2012-07-28 06:37:07 +08:00
|
|
|
ARCConversionTypeClass target, bool diagnose)
|
|
|
|
: Context(Context), SourceClass(source), TargetClass(target),
|
|
|
|
Diagnose(diagnose) {}
|
2011-10-01 09:01:08 +08:00
|
|
|
|
|
|
|
using super::Visit;
|
|
|
|
ACCResult Visit(Expr *e) {
|
|
|
|
return super::Visit(e->IgnoreParens());
|
2011-06-16 07:02:42 +08:00
|
|
|
}
|
2011-10-01 09:01:08 +08:00
|
|
|
|
|
|
|
ACCResult VisitStmt(Stmt *s) {
|
|
|
|
return ACC_invalid;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Null pointer constants can be casted however you please.
|
|
|
|
ACCResult VisitExpr(Expr *e) {
|
|
|
|
if (e->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNotNull))
|
|
|
|
return ACC_bottom;
|
|
|
|
return ACC_invalid;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Objective-C string literals can be safely casted.
|
|
|
|
ACCResult VisitObjCStringLiteral(ObjCStringLiteral *e) {
|
|
|
|
// If we're casting to any retainable type, go ahead. Global
|
|
|
|
// strings are immune to retains, so this is bottom.
|
|
|
|
if (isAnyRetainable(TargetClass)) return ACC_bottom;
|
|
|
|
|
|
|
|
return ACC_invalid;
|
2011-06-16 07:02:42 +08:00
|
|
|
}
|
2011-10-01 09:01:08 +08:00
|
|
|
|
|
|
|
/// Look through certain implicit and explicit casts.
|
|
|
|
ACCResult VisitCastExpr(CastExpr *e) {
|
2011-06-16 07:02:42 +08:00
|
|
|
switch (e->getCastKind()) {
|
|
|
|
case CK_NullToPointer:
|
2011-10-01 09:01:08 +08:00
|
|
|
return ACC_bottom;
|
|
|
|
|
2011-06-16 07:02:42 +08:00
|
|
|
case CK_NoOp:
|
|
|
|
case CK_LValueToRValue:
|
|
|
|
case CK_BitCast:
|
2011-09-09 13:25:32 +08:00
|
|
|
case CK_CPointerToObjCPointerCast:
|
|
|
|
case CK_BlockPointerToObjCPointerCast:
|
2011-06-16 07:02:42 +08:00
|
|
|
case CK_AnyPointerToBlockPointerCast:
|
|
|
|
return Visit(e->getSubExpr());
|
2011-10-01 09:01:08 +08:00
|
|
|
|
2011-06-16 07:02:42 +08:00
|
|
|
default:
|
2011-10-01 09:01:08 +08:00
|
|
|
return ACC_invalid;
|
2011-06-16 07:02:42 +08:00
|
|
|
}
|
|
|
|
}
|
2011-10-01 09:01:08 +08:00
|
|
|
|
|
|
|
/// Look through unary extension.
|
|
|
|
ACCResult VisitUnaryExtension(UnaryOperator *e) {
|
2011-06-16 07:02:42 +08:00
|
|
|
return Visit(e->getSubExpr());
|
|
|
|
}
|
2011-10-01 09:01:08 +08:00
|
|
|
|
|
|
|
/// Ignore the LHS of a comma operator.
|
|
|
|
ACCResult VisitBinComma(BinaryOperator *e) {
|
2011-06-16 07:02:42 +08:00
|
|
|
return Visit(e->getRHS());
|
|
|
|
}
|
2011-10-01 09:01:08 +08:00
|
|
|
|
|
|
|
/// Conditional operators are okay if both sides are okay.
|
|
|
|
ACCResult VisitConditionalOperator(ConditionalOperator *e) {
|
|
|
|
ACCResult left = Visit(e->getTrueExpr());
|
|
|
|
if (left == ACC_invalid) return ACC_invalid;
|
|
|
|
return merge(left, Visit(e->getFalseExpr()));
|
2011-06-16 07:02:42 +08:00
|
|
|
}
|
2011-10-01 09:01:08 +08:00
|
|
|
|
2011-11-06 17:01:30 +08:00
|
|
|
/// Look through pseudo-objects.
|
|
|
|
ACCResult VisitPseudoObjectExpr(PseudoObjectExpr *e) {
|
|
|
|
// If we're getting here, we should always have a result.
|
|
|
|
return Visit(e->getResultExpr());
|
|
|
|
}
|
|
|
|
|
2011-10-01 09:01:08 +08:00
|
|
|
/// Statement expressions are okay if their result expression is okay.
|
|
|
|
ACCResult VisitStmtExpr(StmtExpr *e) {
|
2011-06-16 07:02:42 +08:00
|
|
|
return Visit(e->getSubStmt()->body_back());
|
|
|
|
}
|
2011-10-01 09:01:08 +08:00
|
|
|
|
|
|
|
/// Some declaration references are okay.
|
|
|
|
ACCResult VisitDeclRefExpr(DeclRefExpr *e) {
|
|
|
|
// References to global constants from system headers are okay.
|
|
|
|
// These are things like 'kCFStringTransformToLatin'. They are
|
|
|
|
// can also be assumed to be immune to retains.
|
|
|
|
VarDecl *var = dyn_cast<VarDecl>(e->getDecl());
|
|
|
|
if (isAnyRetainable(TargetClass) &&
|
|
|
|
isAnyRetainable(SourceClass) &&
|
|
|
|
var &&
|
|
|
|
var->getStorageClass() == SC_Extern &&
|
|
|
|
var->getType().isConstQualified() &&
|
|
|
|
Context.getSourceManager().isInSystemHeader(var->getLocation())) {
|
|
|
|
return ACC_bottom;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Nothing else.
|
|
|
|
return ACC_invalid;
|
2011-06-16 07:02:42 +08:00
|
|
|
}
|
|
|
|
|
2011-10-01 09:01:08 +08:00
|
|
|
/// Some calls are okay.
|
|
|
|
ACCResult VisitCallExpr(CallExpr *e) {
|
|
|
|
if (FunctionDecl *fn = e->getDirectCallee())
|
|
|
|
if (ACCResult result = checkCallToFunction(fn))
|
|
|
|
return result;
|
|
|
|
|
|
|
|
return super::VisitCallExpr(e);
|
2011-06-22 03:42:38 +08:00
|
|
|
}
|
2011-10-01 09:01:08 +08:00
|
|
|
|
|
|
|
ACCResult checkCallToFunction(FunctionDecl *fn) {
|
|
|
|
// Require a CF*Ref return type.
|
|
|
|
if (!isCFType(fn->getResultType()))
|
|
|
|
return ACC_invalid;
|
|
|
|
|
|
|
|
if (!isAnyRetainable(TargetClass))
|
|
|
|
return ACC_invalid;
|
|
|
|
|
|
|
|
// Honor an explicit 'not retained' attribute.
|
|
|
|
if (fn->hasAttr<CFReturnsNotRetainedAttr>())
|
|
|
|
return ACC_plusZero;
|
|
|
|
|
|
|
|
// Honor an explicit 'retained' attribute, except that for
|
|
|
|
// now we're not going to permit implicit handling of +1 results,
|
|
|
|
// because it's a bit frightening.
|
|
|
|
if (fn->hasAttr<CFReturnsRetainedAttr>())
|
2012-07-28 07:55:46 +08:00
|
|
|
return Diagnose ? ACC_plusOne
|
|
|
|
: ACC_invalid; // ACC_plusOne if we start accepting this
|
2011-10-01 09:01:08 +08:00
|
|
|
|
|
|
|
// Recognize this specific builtin function, which is used by CFSTR.
|
|
|
|
unsigned builtinID = fn->getBuiltinID();
|
|
|
|
if (builtinID == Builtin::BI__builtin___CFStringMakeConstantString)
|
|
|
|
return ACC_bottom;
|
|
|
|
|
2012-07-28 07:55:46 +08:00
|
|
|
// Otherwise, don't do anything implicit with an unaudited function.
|
|
|
|
if (!fn->hasAttr<CFAuditedTransferAttr>())
|
|
|
|
return ACC_invalid;
|
|
|
|
|
2012-07-28 06:37:07 +08:00
|
|
|
// Otherwise, it's +0 unless it follows the create convention.
|
|
|
|
if (ento::coreFoundation::followsCreateRule(fn))
|
|
|
|
return Diagnose ? ACC_plusOne
|
|
|
|
: ACC_invalid; // ACC_plusOne if we start accepting this
|
2011-10-01 09:01:08 +08:00
|
|
|
|
|
|
|
return ACC_plusZero;
|
|
|
|
}
|
|
|
|
|
|
|
|
ACCResult VisitObjCMessageExpr(ObjCMessageExpr *e) {
|
|
|
|
return checkCallToMethod(e->getMethodDecl());
|
|
|
|
}
|
|
|
|
|
|
|
|
ACCResult VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *e) {
|
|
|
|
ObjCMethodDecl *method;
|
|
|
|
if (e->isExplicitProperty())
|
|
|
|
method = e->getExplicitProperty()->getGetterMethodDecl();
|
|
|
|
else
|
|
|
|
method = e->getImplicitPropertyGetter();
|
|
|
|
return checkCallToMethod(method);
|
|
|
|
}
|
|
|
|
|
|
|
|
ACCResult checkCallToMethod(ObjCMethodDecl *method) {
|
|
|
|
if (!method) return ACC_invalid;
|
|
|
|
|
|
|
|
// Check for message sends to functions returning CF types. We
|
|
|
|
// just obey the Cocoa conventions with these, even though the
|
|
|
|
// return type is CF.
|
|
|
|
if (!isAnyRetainable(TargetClass) || !isCFType(method->getResultType()))
|
|
|
|
return ACC_invalid;
|
|
|
|
|
|
|
|
// If the method is explicitly marked not-retained, it's +0.
|
|
|
|
if (method->hasAttr<CFReturnsNotRetainedAttr>())
|
|
|
|
return ACC_plusZero;
|
|
|
|
|
|
|
|
// If the method is explicitly marked as returning retained, or its
|
|
|
|
// selector follows a +1 Cocoa convention, treat it as +1.
|
|
|
|
if (method->hasAttr<CFReturnsRetainedAttr>())
|
|
|
|
return ACC_plusOne;
|
|
|
|
|
|
|
|
switch (method->getSelector().getMethodFamily()) {
|
|
|
|
case OMF_alloc:
|
|
|
|
case OMF_copy:
|
|
|
|
case OMF_mutableCopy:
|
|
|
|
case OMF_new:
|
|
|
|
return ACC_plusOne;
|
|
|
|
|
|
|
|
default:
|
|
|
|
// Otherwise, treat it as +0.
|
|
|
|
return ACC_plusZero;
|
2011-06-22 03:42:38 +08:00
|
|
|
}
|
2011-06-22 01:38:29 +08:00
|
|
|
}
|
2011-10-01 09:01:08 +08:00
|
|
|
};
|
2011-06-21 04:54:42 +08:00
|
|
|
}
|
|
|
|
|
2012-06-01 08:10:47 +08:00
|
|
|
bool Sema::isKnownName(StringRef name) {
|
|
|
|
if (name.empty())
|
|
|
|
return false;
|
|
|
|
LookupResult R(*this, &Context.Idents.get(name), SourceLocation(),
|
2012-02-02 06:56:20 +08:00
|
|
|
Sema::LookupOrdinaryName);
|
2012-06-01 08:10:47 +08:00
|
|
|
return LookupName(R, TUScope, false);
|
2012-02-02 06:56:20 +08:00
|
|
|
}
|
|
|
|
|
2012-02-17 01:31:07 +08:00
|
|
|
static void addFixitForObjCARCConversion(Sema &S,
|
|
|
|
DiagnosticBuilder &DiagB,
|
|
|
|
Sema::CheckedConversionKind CCK,
|
|
|
|
SourceLocation afterLParen,
|
|
|
|
QualType castType,
|
|
|
|
Expr *castExpr,
|
2013-02-23 06:02:53 +08:00
|
|
|
Expr *realCast,
|
2012-02-17 01:31:07 +08:00
|
|
|
const char *bridgeKeyword,
|
|
|
|
const char *CFBridgeName) {
|
|
|
|
// We handle C-style and implicit casts here.
|
|
|
|
switch (CCK) {
|
|
|
|
case Sema::CCK_ImplicitConversion:
|
|
|
|
case Sema::CCK_CStyleCast:
|
2013-02-23 06:02:53 +08:00
|
|
|
case Sema::CCK_OtherCast:
|
2012-02-17 01:31:07 +08:00
|
|
|
break;
|
|
|
|
case Sema::CCK_FunctionalCast:
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (CFBridgeName) {
|
2013-02-23 06:02:53 +08:00
|
|
|
if (CCK == Sema::CCK_OtherCast) {
|
|
|
|
if (const CXXNamedCastExpr *NCE = dyn_cast<CXXNamedCastExpr>(realCast)) {
|
|
|
|
SourceRange range(NCE->getOperatorLoc(),
|
|
|
|
NCE->getAngleBrackets().getEnd());
|
|
|
|
SmallString<32> BridgeCall;
|
|
|
|
|
|
|
|
SourceManager &SM = S.getSourceManager();
|
|
|
|
char PrevChar = *SM.getCharacterData(range.getBegin().getLocWithOffset(-1));
|
|
|
|
if (Lexer::isIdentifierBodyChar(PrevChar, S.getLangOpts()))
|
|
|
|
BridgeCall += ' ';
|
|
|
|
|
|
|
|
BridgeCall += CFBridgeName;
|
|
|
|
DiagB.AddFixItHint(FixItHint::CreateReplacement(range, BridgeCall));
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
2012-02-17 01:31:07 +08:00
|
|
|
Expr *castedE = castExpr;
|
|
|
|
if (CStyleCastExpr *CCE = dyn_cast<CStyleCastExpr>(castedE))
|
|
|
|
castedE = CCE->getSubExpr();
|
|
|
|
castedE = castedE->IgnoreImpCasts();
|
|
|
|
SourceRange range = castedE->getSourceRange();
|
2012-06-07 09:10:31 +08:00
|
|
|
|
|
|
|
SmallString<32> BridgeCall;
|
|
|
|
|
|
|
|
SourceManager &SM = S.getSourceManager();
|
|
|
|
char PrevChar = *SM.getCharacterData(range.getBegin().getLocWithOffset(-1));
|
|
|
|
if (Lexer::isIdentifierBodyChar(PrevChar, S.getLangOpts()))
|
|
|
|
BridgeCall += ' ';
|
|
|
|
|
|
|
|
BridgeCall += CFBridgeName;
|
|
|
|
|
2012-02-17 01:31:07 +08:00
|
|
|
if (isa<ParenExpr>(castedE)) {
|
|
|
|
DiagB.AddFixItHint(FixItHint::CreateInsertion(range.getBegin(),
|
2012-06-07 09:10:31 +08:00
|
|
|
BridgeCall));
|
2012-02-17 01:31:07 +08:00
|
|
|
} else {
|
2012-06-07 09:10:31 +08:00
|
|
|
BridgeCall += '(';
|
2012-02-17 01:31:07 +08:00
|
|
|
DiagB.AddFixItHint(FixItHint::CreateInsertion(range.getBegin(),
|
2012-06-07 09:10:31 +08:00
|
|
|
BridgeCall));
|
2012-02-17 01:31:07 +08:00
|
|
|
DiagB.AddFixItHint(FixItHint::CreateInsertion(
|
|
|
|
S.PP.getLocForEndOfToken(range.getEnd()),
|
|
|
|
")"));
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (CCK == Sema::CCK_CStyleCast) {
|
|
|
|
DiagB.AddFixItHint(FixItHint::CreateInsertion(afterLParen, bridgeKeyword));
|
2013-02-23 06:02:53 +08:00
|
|
|
} else if (CCK == Sema::CCK_OtherCast) {
|
|
|
|
if (const CXXNamedCastExpr *NCE = dyn_cast<CXXNamedCastExpr>(realCast)) {
|
|
|
|
std::string castCode = "(";
|
|
|
|
castCode += bridgeKeyword;
|
|
|
|
castCode += castType.getAsString();
|
|
|
|
castCode += ")";
|
|
|
|
SourceRange Range(NCE->getOperatorLoc(),
|
|
|
|
NCE->getAngleBrackets().getEnd());
|
|
|
|
DiagB.AddFixItHint(FixItHint::CreateReplacement(Range, castCode));
|
|
|
|
}
|
2012-02-17 01:31:07 +08:00
|
|
|
} else {
|
|
|
|
std::string castCode = "(";
|
|
|
|
castCode += bridgeKeyword;
|
|
|
|
castCode += castType.getAsString();
|
|
|
|
castCode += ")";
|
|
|
|
Expr *castedE = castExpr->IgnoreImpCasts();
|
|
|
|
SourceRange range = castedE->getSourceRange();
|
|
|
|
if (isa<ParenExpr>(castedE)) {
|
|
|
|
DiagB.AddFixItHint(FixItHint::CreateInsertion(range.getBegin(),
|
|
|
|
castCode));
|
|
|
|
} else {
|
|
|
|
castCode += "(";
|
|
|
|
DiagB.AddFixItHint(FixItHint::CreateInsertion(range.getBegin(),
|
|
|
|
castCode));
|
|
|
|
DiagB.AddFixItHint(FixItHint::CreateInsertion(
|
|
|
|
S.PP.getLocForEndOfToken(range.getEnd()),
|
|
|
|
")"));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-12-10 06:04:26 +08:00
|
|
|
template <typename T>
|
|
|
|
static inline T *getObjCBridgeAttr(const TypedefType *TD) {
|
|
|
|
TypedefNameDecl *TDNDecl = TD->getDecl();
|
|
|
|
QualType QT = TDNDecl->getUnderlyingType();
|
|
|
|
if (QT->isPointerType()) {
|
|
|
|
QT = QT->getPointeeType();
|
|
|
|
if (const RecordType *RT = QT->getAs<RecordType>())
|
|
|
|
if (RecordDecl *RD = RT->getDecl())
|
|
|
|
if (RD->hasAttr<T>())
|
|
|
|
return RD->getAttr<T>();
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ObjCBridgeRelatedAttr *ObjCBridgeRelatedAttrFromType(QualType T,
|
|
|
|
TypedefNameDecl *&TDNDecl) {
|
|
|
|
while (const TypedefType *TD = dyn_cast<TypedefType>(T.getTypePtr())) {
|
|
|
|
TDNDecl = TD->getDecl();
|
|
|
|
if (ObjCBridgeRelatedAttr *ObjCBAttr =
|
|
|
|
getObjCBridgeAttr<ObjCBridgeRelatedAttr>(TD))
|
|
|
|
return ObjCBAttr;
|
|
|
|
T = TDNDecl->getUnderlyingType();
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-10-18 02:40:02 +08:00
|
|
|
static void
|
|
|
|
diagnoseObjCARCConversion(Sema &S, SourceRange castRange,
|
|
|
|
QualType castType, ARCConversionTypeClass castACTC,
|
2013-02-23 06:02:53 +08:00
|
|
|
Expr *castExpr, Expr *realCast,
|
|
|
|
ARCConversionTypeClass exprACTC,
|
2011-10-18 02:40:02 +08:00
|
|
|
Sema::CheckedConversionKind CCK) {
|
|
|
|
SourceLocation loc =
|
|
|
|
(castRange.isValid() ? castRange.getBegin() : castExpr->getExprLoc());
|
|
|
|
|
|
|
|
if (S.makeUnavailableInSystemHeader(loc,
|
|
|
|
"converts between Objective-C and C pointers in -fobjc-arc"))
|
|
|
|
return;
|
|
|
|
|
|
|
|
QualType castExprType = castExpr->getType();
|
2013-12-10 06:04:26 +08:00
|
|
|
TypedefNameDecl *TDNDecl = 0;
|
|
|
|
if ((castACTC == ACTC_coreFoundation && exprACTC == ACTC_retainable &&
|
|
|
|
ObjCBridgeRelatedAttrFromType(castType, TDNDecl)) ||
|
|
|
|
(exprACTC == ACTC_coreFoundation && castACTC == ACTC_retainable &&
|
|
|
|
ObjCBridgeRelatedAttrFromType(castExprType, TDNDecl)))
|
|
|
|
return;
|
2011-10-18 02:40:02 +08:00
|
|
|
|
|
|
|
unsigned srcKind = 0;
|
|
|
|
switch (exprACTC) {
|
|
|
|
case ACTC_none:
|
|
|
|
case ACTC_coreFoundation:
|
|
|
|
case ACTC_voidPtr:
|
|
|
|
srcKind = (castExprType->isPointerType() ? 1 : 0);
|
|
|
|
break;
|
|
|
|
case ACTC_retainable:
|
|
|
|
srcKind = (castExprType->isBlockPointerType() ? 2 : 3);
|
|
|
|
break;
|
|
|
|
case ACTC_indirectRetainable:
|
|
|
|
srcKind = 4;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check whether this could be fixed with a bridge cast.
|
|
|
|
SourceLocation afterLParen = S.PP.getLocForEndOfToken(castRange.getBegin());
|
|
|
|
SourceLocation noteLoc = afterLParen.isValid() ? afterLParen : loc;
|
|
|
|
|
|
|
|
// Bridge from an ARC type to a CF type.
|
|
|
|
if (castACTC == ACTC_retainable && isAnyRetainable(exprACTC)) {
|
2012-02-02 06:56:20 +08:00
|
|
|
|
2011-10-18 02:40:02 +08:00
|
|
|
S.Diag(loc, diag::err_arc_cast_requires_bridge)
|
|
|
|
<< unsigned(CCK == Sema::CCK_ImplicitConversion) // cast|implicit
|
|
|
|
<< 2 // of C pointer type
|
|
|
|
<< castExprType
|
|
|
|
<< unsigned(castType->isBlockPointerType()) // to ObjC|block type
|
|
|
|
<< castType
|
|
|
|
<< castRange
|
|
|
|
<< castExpr->getSourceRange();
|
2012-06-01 08:10:47 +08:00
|
|
|
bool br = S.isKnownName("CFBridgingRelease");
|
2012-07-31 09:07:43 +08:00
|
|
|
ACCResult CreateRule =
|
2012-07-28 07:55:46 +08:00
|
|
|
ARCCastChecker(S.Context, exprACTC, castACTC, true).Visit(castExpr);
|
2012-07-31 09:07:43 +08:00
|
|
|
assert(CreateRule != ACC_bottom && "This cast should already be accepted.");
|
2012-07-28 07:55:46 +08:00
|
|
|
if (CreateRule != ACC_plusOne)
|
2012-07-28 05:34:23 +08:00
|
|
|
{
|
2013-02-22 09:22:48 +08:00
|
|
|
DiagnosticBuilder DiagB =
|
|
|
|
(CCK != Sema::CCK_OtherCast) ? S.Diag(noteLoc, diag::note_arc_bridge)
|
|
|
|
: S.Diag(noteLoc, diag::note_arc_cstyle_bridge);
|
|
|
|
|
2012-07-28 05:34:23 +08:00
|
|
|
addFixitForObjCARCConversion(S, DiagB, CCK, afterLParen,
|
2013-02-23 06:02:53 +08:00
|
|
|
castType, castExpr, realCast, "__bridge ", 0);
|
2012-07-28 05:34:23 +08:00
|
|
|
}
|
2012-07-29 02:59:49 +08:00
|
|
|
if (CreateRule != ACC_plusZero)
|
2012-07-28 05:34:23 +08:00
|
|
|
{
|
2013-02-22 09:22:48 +08:00
|
|
|
DiagnosticBuilder DiagB =
|
|
|
|
(CCK == Sema::CCK_OtherCast && !br) ?
|
|
|
|
S.Diag(noteLoc, diag::note_arc_cstyle_bridge_transfer) << castExprType :
|
|
|
|
S.Diag(br ? castExpr->getExprLoc() : noteLoc,
|
|
|
|
diag::note_arc_bridge_transfer)
|
|
|
|
<< castExprType << br;
|
|
|
|
|
2012-07-28 05:34:23 +08:00
|
|
|
addFixitForObjCARCConversion(S, DiagB, CCK, afterLParen,
|
2013-02-23 06:02:53 +08:00
|
|
|
castType, castExpr, realCast, "__bridge_transfer ",
|
2012-07-28 05:34:23 +08:00
|
|
|
br ? "CFBridgingRelease" : 0);
|
|
|
|
}
|
2011-10-18 02:40:02 +08:00
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Bridge from a CF type to an ARC type.
|
|
|
|
if (exprACTC == ACTC_retainable && isAnyRetainable(castACTC)) {
|
2012-06-01 08:10:47 +08:00
|
|
|
bool br = S.isKnownName("CFBridgingRetain");
|
2011-10-18 02:40:02 +08:00
|
|
|
S.Diag(loc, diag::err_arc_cast_requires_bridge)
|
|
|
|
<< unsigned(CCK == Sema::CCK_ImplicitConversion) // cast|implicit
|
|
|
|
<< unsigned(castExprType->isBlockPointerType()) // of ObjC|block type
|
|
|
|
<< castExprType
|
|
|
|
<< 2 // to C pointer type
|
|
|
|
<< castType
|
|
|
|
<< castRange
|
|
|
|
<< castExpr->getSourceRange();
|
2012-07-28 07:55:46 +08:00
|
|
|
ACCResult CreateRule =
|
|
|
|
ARCCastChecker(S.Context, exprACTC, castACTC, true).Visit(castExpr);
|
2012-07-31 09:07:43 +08:00
|
|
|
assert(CreateRule != ACC_bottom && "This cast should already be accepted.");
|
2012-07-28 07:55:46 +08:00
|
|
|
if (CreateRule != ACC_plusOne)
|
2012-07-28 05:34:23 +08:00
|
|
|
{
|
2013-02-22 09:22:48 +08:00
|
|
|
DiagnosticBuilder DiagB =
|
|
|
|
(CCK != Sema::CCK_OtherCast) ? S.Diag(noteLoc, diag::note_arc_bridge)
|
|
|
|
: S.Diag(noteLoc, diag::note_arc_cstyle_bridge);
|
2012-07-28 05:34:23 +08:00
|
|
|
addFixitForObjCARCConversion(S, DiagB, CCK, afterLParen,
|
2013-02-23 06:02:53 +08:00
|
|
|
castType, castExpr, realCast, "__bridge ", 0);
|
2012-07-28 05:34:23 +08:00
|
|
|
}
|
2012-07-29 02:59:49 +08:00
|
|
|
if (CreateRule != ACC_plusZero)
|
2012-07-28 05:34:23 +08:00
|
|
|
{
|
2013-02-22 09:22:48 +08:00
|
|
|
DiagnosticBuilder DiagB =
|
|
|
|
(CCK == Sema::CCK_OtherCast && !br) ?
|
|
|
|
S.Diag(noteLoc, diag::note_arc_cstyle_bridge_retained) << castType :
|
|
|
|
S.Diag(br ? castExpr->getExprLoc() : noteLoc,
|
|
|
|
diag::note_arc_bridge_retained)
|
|
|
|
<< castType << br;
|
|
|
|
|
2012-07-28 05:34:23 +08:00
|
|
|
addFixitForObjCARCConversion(S, DiagB, CCK, afterLParen,
|
2013-02-23 06:02:53 +08:00
|
|
|
castType, castExpr, realCast, "__bridge_retained ",
|
2012-07-28 05:34:23 +08:00
|
|
|
br ? "CFBridgingRetain" : 0);
|
|
|
|
}
|
2011-10-18 02:40:02 +08:00
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
S.Diag(loc, diag::err_arc_mismatched_cast)
|
|
|
|
<< (CCK != Sema::CCK_ImplicitConversion)
|
|
|
|
<< srcKind << castExprType << castType
|
|
|
|
<< castRange << castExpr->getSourceRange();
|
|
|
|
}
|
|
|
|
|
2013-11-22 04:50:32 +08:00
|
|
|
template <typename TB>
|
2013-11-17 03:16:32 +08:00
|
|
|
static bool CheckObjCBridgeNSCast(Sema &S, QualType castType, Expr *castExpr) {
|
2013-11-16 06:18:17 +08:00
|
|
|
QualType T = castExpr->getType();
|
|
|
|
while (const TypedefType *TD = dyn_cast<TypedefType>(T.getTypePtr())) {
|
|
|
|
TypedefNameDecl *TDNDecl = TD->getDecl();
|
2013-11-22 04:50:32 +08:00
|
|
|
if (TB *ObjCBAttr = getObjCBridgeAttr<TB>(TD)) {
|
2013-11-19 08:09:48 +08:00
|
|
|
if (IdentifierInfo *Parm = ObjCBAttr->getBridgedType()) {
|
|
|
|
NamedDecl *Target = 0;
|
2013-11-16 06:18:17 +08:00
|
|
|
// Check for an existing type with this name.
|
|
|
|
LookupResult R(S, DeclarationName(Parm), SourceLocation(),
|
|
|
|
Sema::LookupOrdinaryName);
|
|
|
|
if (S.LookupName(R, S.TUScope)) {
|
2013-11-16 09:45:25 +08:00
|
|
|
Target = R.getFoundDecl();
|
|
|
|
if (Target && isa<ObjCInterfaceDecl>(Target)) {
|
|
|
|
ObjCInterfaceDecl *ExprClass = cast<ObjCInterfaceDecl>(Target);
|
|
|
|
if (const ObjCObjectPointerType *InterfacePointerType =
|
|
|
|
castType->getAsObjCInterfacePointerType()) {
|
|
|
|
ObjCInterfaceDecl *CastClass
|
|
|
|
= InterfacePointerType->getObjectType()->getInterface();
|
2013-11-20 08:32:12 +08:00
|
|
|
if ((CastClass == ExprClass) ||
|
|
|
|
(CastClass && ExprClass->isSuperClassOf(CastClass)))
|
2013-11-16 09:45:25 +08:00
|
|
|
return true;
|
|
|
|
S.Diag(castExpr->getLocStart(), diag::warn_objc_invalid_bridge)
|
2013-11-19 09:23:07 +08:00
|
|
|
<< T << Target->getName() << castType->getPointeeType();
|
2013-11-16 09:45:25 +08:00
|
|
|
return true;
|
2013-11-20 08:32:12 +08:00
|
|
|
} else if (castType->isObjCIdType() ||
|
|
|
|
(S.Context.ObjCObjectAdoptsQTypeProtocols(
|
|
|
|
castType, ExprClass)))
|
|
|
|
// ok to cast to 'id'.
|
|
|
|
// casting to id<p-list> is ok if bridge type adopts all of
|
|
|
|
// p-list protocols.
|
|
|
|
return true;
|
|
|
|
else {
|
2013-11-17 07:22:37 +08:00
|
|
|
S.Diag(castExpr->getLocStart(), diag::warn_objc_invalid_bridge)
|
2013-11-19 09:23:07 +08:00
|
|
|
<< T << Target->getName() << castType;
|
2013-11-20 08:32:12 +08:00
|
|
|
S.Diag(TDNDecl->getLocStart(), diag::note_declared_at);
|
|
|
|
S.Diag(Target->getLocStart(), diag::note_declared_at);
|
2013-11-17 07:22:37 +08:00
|
|
|
return true;
|
|
|
|
}
|
2013-11-16 06:18:17 +08:00
|
|
|
}
|
|
|
|
}
|
2013-11-17 03:16:32 +08:00
|
|
|
S.Diag(castExpr->getLocStart(), diag::err_objc_cf_bridged_not_interface)
|
2013-11-16 09:45:25 +08:00
|
|
|
<< castExpr->getType() << Parm->getName();
|
|
|
|
S.Diag(TDNDecl->getLocStart(), diag::note_declared_at);
|
|
|
|
if (Target)
|
|
|
|
S.Diag(Target->getLocStart(), diag::note_declared_at);
|
2013-11-16 06:18:17 +08:00
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
T = TDNDecl->getUnderlyingType();
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2013-11-22 04:50:32 +08:00
|
|
|
template <typename TB>
|
2013-11-17 03:16:32 +08:00
|
|
|
static bool CheckObjCBridgeCFCast(Sema &S, QualType castType, Expr *castExpr) {
|
|
|
|
QualType T = castType;
|
|
|
|
while (const TypedefType *TD = dyn_cast<TypedefType>(T.getTypePtr())) {
|
|
|
|
TypedefNameDecl *TDNDecl = TD->getDecl();
|
2013-11-22 04:50:32 +08:00
|
|
|
if (TB *ObjCBAttr = getObjCBridgeAttr<TB>(TD)) {
|
2013-11-19 08:09:48 +08:00
|
|
|
if (IdentifierInfo *Parm = ObjCBAttr->getBridgedType()) {
|
|
|
|
NamedDecl *Target = 0;
|
2013-11-17 03:16:32 +08:00
|
|
|
// Check for an existing type with this name.
|
|
|
|
LookupResult R(S, DeclarationName(Parm), SourceLocation(),
|
|
|
|
Sema::LookupOrdinaryName);
|
|
|
|
if (S.LookupName(R, S.TUScope)) {
|
|
|
|
Target = R.getFoundDecl();
|
|
|
|
if (Target && isa<ObjCInterfaceDecl>(Target)) {
|
|
|
|
ObjCInterfaceDecl *CastClass = cast<ObjCInterfaceDecl>(Target);
|
|
|
|
if (const ObjCObjectPointerType *InterfacePointerType =
|
|
|
|
castExpr->getType()->getAsObjCInterfacePointerType()) {
|
|
|
|
ObjCInterfaceDecl *ExprClass
|
|
|
|
= InterfacePointerType->getObjectType()->getInterface();
|
2013-11-20 08:32:12 +08:00
|
|
|
if ((CastClass == ExprClass) ||
|
|
|
|
(ExprClass && CastClass->isSuperClassOf(ExprClass)))
|
2013-11-17 03:16:32 +08:00
|
|
|
return true;
|
|
|
|
S.Diag(castExpr->getLocStart(), diag::warn_objc_invalid_bridge_to_cf)
|
2013-11-19 09:23:07 +08:00
|
|
|
<< castExpr->getType()->getPointeeType() << T;
|
2013-11-17 03:16:32 +08:00
|
|
|
S.Diag(TDNDecl->getLocStart(), diag::note_declared_at);
|
|
|
|
return true;
|
2013-11-20 08:32:12 +08:00
|
|
|
} else if (castExpr->getType()->isObjCIdType() ||
|
|
|
|
(S.Context.QIdProtocolsAdoptObjCObjectProtocols(
|
|
|
|
castExpr->getType(), CastClass)))
|
|
|
|
// ok to cast an 'id' expression to a CFtype.
|
|
|
|
// ok to cast an 'id<plist>' expression to CFtype provided plist
|
|
|
|
// adopts all of CFtype's ObjetiveC's class plist.
|
|
|
|
return true;
|
|
|
|
else {
|
2013-11-17 07:22:37 +08:00
|
|
|
S.Diag(castExpr->getLocStart(), diag::warn_objc_invalid_bridge_to_cf)
|
|
|
|
<< castExpr->getType() << castType;
|
|
|
|
S.Diag(TDNDecl->getLocStart(), diag::note_declared_at);
|
2013-11-20 08:32:12 +08:00
|
|
|
S.Diag(Target->getLocStart(), diag::note_declared_at);
|
2013-11-17 07:22:37 +08:00
|
|
|
return true;
|
2013-11-17 03:16:32 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
S.Diag(castExpr->getLocStart(), diag::err_objc_ns_bridged_invalid_cfobject)
|
|
|
|
<< castExpr->getType() << castType;
|
|
|
|
S.Diag(TDNDecl->getLocStart(), diag::note_declared_at);
|
|
|
|
if (Target)
|
|
|
|
S.Diag(Target->getLocStart(), diag::note_declared_at);
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
T = TDNDecl->getUnderlyingType();
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2013-11-21 08:39:36 +08:00
|
|
|
void Sema::CheckTollFreeBridgeCast(QualType castType, Expr *castExpr) {
|
2013-12-06 00:25:25 +08:00
|
|
|
// warn in presence of __bridge casting to or from a toll free bridge cast.
|
2013-11-21 08:39:36 +08:00
|
|
|
ARCConversionTypeClass exprACTC = classifyTypeForARCConversion(castExpr->getType());
|
|
|
|
ARCConversionTypeClass castACTC = classifyTypeForARCConversion(castType);
|
2013-11-22 04:50:32 +08:00
|
|
|
if (castACTC == ACTC_retainable && exprACTC == ACTC_coreFoundation) {
|
|
|
|
(void)CheckObjCBridgeNSCast<ObjCBridgeAttr>(*this, castType, castExpr);
|
|
|
|
(void)CheckObjCBridgeNSCast<ObjCBridgeMutableAttr>(*this, castType, castExpr);
|
|
|
|
}
|
|
|
|
else if (castACTC == ACTC_coreFoundation && exprACTC == ACTC_retainable) {
|
|
|
|
(void)CheckObjCBridgeCFCast<ObjCBridgeAttr>(*this, castType, castExpr);
|
|
|
|
(void)CheckObjCBridgeCFCast<ObjCBridgeMutableAttr>(*this, castType, castExpr);
|
|
|
|
}
|
2013-11-21 08:39:36 +08:00
|
|
|
}
|
|
|
|
|
2013-12-07 08:34:23 +08:00
|
|
|
|
|
|
|
bool Sema::checkObjCBridgeRelatedComponents(SourceLocation Loc,
|
|
|
|
QualType DestType, QualType SrcType,
|
|
|
|
ObjCInterfaceDecl *&RelatedClass,
|
|
|
|
ObjCMethodDecl *&ClassMethod,
|
|
|
|
ObjCMethodDecl *&InstanceMethod,
|
|
|
|
TypedefNameDecl *&TDNDecl,
|
|
|
|
bool CfToNs) {
|
|
|
|
QualType T = CfToNs ? SrcType : DestType;
|
2013-12-10 06:04:26 +08:00
|
|
|
ObjCBridgeRelatedAttr *ObjCBAttr = ObjCBridgeRelatedAttrFromType(T, TDNDecl);
|
|
|
|
if (!ObjCBAttr)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
IdentifierInfo *RCId = ObjCBAttr->getRelatedClass();
|
|
|
|
IdentifierInfo *CMId = ObjCBAttr->getClassMethod();
|
|
|
|
IdentifierInfo *IMId = ObjCBAttr->getInstanceMethod();
|
|
|
|
if (!RCId)
|
|
|
|
return false;
|
|
|
|
NamedDecl *Target = 0;
|
|
|
|
// Check for an existing type with this name.
|
|
|
|
LookupResult R(*this, DeclarationName(RCId), SourceLocation(),
|
|
|
|
Sema::LookupOrdinaryName);
|
|
|
|
if (!LookupName(R, TUScope)) {
|
|
|
|
Diag(Loc, diag::err_objc_bridged_related_invalid_class) << RCId
|
2013-12-07 08:34:23 +08:00
|
|
|
<< SrcType << DestType;
|
2013-12-10 06:04:26 +08:00
|
|
|
Diag(TDNDecl->getLocStart(), diag::note_declared_at);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
Target = R.getFoundDecl();
|
|
|
|
if (Target && isa<ObjCInterfaceDecl>(Target))
|
|
|
|
RelatedClass = cast<ObjCInterfaceDecl>(Target);
|
|
|
|
else {
|
|
|
|
Diag(Loc, diag::err_objc_bridged_related_invalid_class_name) << RCId
|
2013-12-07 08:34:23 +08:00
|
|
|
<< SrcType << DestType;
|
2013-12-10 06:04:26 +08:00
|
|
|
Diag(TDNDecl->getLocStart(), diag::note_declared_at);
|
|
|
|
if (Target)
|
|
|
|
Diag(Target->getLocStart(), diag::note_declared_at);
|
|
|
|
return false;
|
|
|
|
}
|
2013-12-07 08:34:23 +08:00
|
|
|
|
2013-12-10 06:04:26 +08:00
|
|
|
// Check for an existing class method with the given selector name.
|
|
|
|
if (CfToNs && CMId) {
|
|
|
|
Selector Sel = Context.Selectors.getUnarySelector(CMId);
|
|
|
|
ClassMethod = RelatedClass->lookupMethod(Sel, false);
|
|
|
|
if (!ClassMethod) {
|
|
|
|
Diag(Loc, diag::err_objc_bridged_related_known_method)
|
2013-12-11 03:22:41 +08:00
|
|
|
<< SrcType << DestType << Sel << false;
|
2013-12-10 06:04:26 +08:00
|
|
|
Diag(TDNDecl->getLocStart(), diag::note_declared_at);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
2013-12-07 08:34:23 +08:00
|
|
|
|
2013-12-10 06:04:26 +08:00
|
|
|
// Check for an existing instance method with the given selector name.
|
|
|
|
if (!CfToNs && IMId) {
|
|
|
|
Selector Sel = Context.Selectors.getNullarySelector(IMId);
|
|
|
|
InstanceMethod = RelatedClass->lookupMethod(Sel, true);
|
|
|
|
if (!InstanceMethod) {
|
|
|
|
Diag(Loc, diag::err_objc_bridged_related_known_method)
|
2013-12-11 03:22:41 +08:00
|
|
|
<< SrcType << DestType << Sel << true;
|
2013-12-10 06:04:26 +08:00
|
|
|
Diag(TDNDecl->getLocStart(), diag::note_declared_at);
|
|
|
|
return false;
|
2013-12-07 08:34:23 +08:00
|
|
|
}
|
|
|
|
}
|
2013-12-10 06:04:26 +08:00
|
|
|
return true;
|
2013-12-07 08:34:23 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
Sema::CheckObjCBridgeRelatedConversions(SourceLocation Loc,
|
2013-12-11 01:08:13 +08:00
|
|
|
QualType DestType, QualType SrcType,
|
2013-12-17 06:54:37 +08:00
|
|
|
Expr *&SrcExpr) {
|
2013-12-07 08:34:23 +08:00
|
|
|
ARCConversionTypeClass rhsExprACTC = classifyTypeForARCConversion(SrcType);
|
|
|
|
ARCConversionTypeClass lhsExprACTC = classifyTypeForARCConversion(DestType);
|
|
|
|
bool CfToNs = (rhsExprACTC == ACTC_coreFoundation && lhsExprACTC == ACTC_retainable);
|
|
|
|
bool NsToCf = (rhsExprACTC == ACTC_retainable && lhsExprACTC == ACTC_coreFoundation);
|
|
|
|
if (!CfToNs && !NsToCf)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
ObjCInterfaceDecl *RelatedClass;
|
|
|
|
ObjCMethodDecl *ClassMethod = 0;
|
|
|
|
ObjCMethodDecl *InstanceMethod = 0;
|
|
|
|
TypedefNameDecl *TDNDecl = 0;
|
|
|
|
if (!checkObjCBridgeRelatedComponents(Loc, DestType, SrcType, RelatedClass,
|
|
|
|
ClassMethod, InstanceMethod, TDNDecl, CfToNs))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (CfToNs) {
|
|
|
|
// Implicit conversion from CF to ObjC object is needed.
|
2013-12-11 01:08:13 +08:00
|
|
|
if (ClassMethod) {
|
|
|
|
std::string ExpressionString = "[";
|
|
|
|
ExpressionString += RelatedClass->getNameAsString();
|
|
|
|
ExpressionString += " ";
|
|
|
|
ExpressionString += ClassMethod->getSelector().getAsString();
|
|
|
|
SourceLocation SrcExprEndLoc = PP.getLocForEndOfToken(SrcExpr->getLocEnd());
|
|
|
|
// Provide a fixit: [RelatedClass ClassMethod SrcExpr]
|
2013-12-07 08:34:23 +08:00
|
|
|
Diag(Loc, diag::err_objc_bridged_related_known_method)
|
2013-12-11 03:22:41 +08:00
|
|
|
<< SrcType << DestType << ClassMethod->getSelector() << false
|
2013-12-11 01:08:13 +08:00
|
|
|
<< FixItHint::CreateInsertion(SrcExpr->getLocStart(), ExpressionString)
|
|
|
|
<< FixItHint::CreateInsertion(SrcExprEndLoc, "]");
|
2013-12-17 06:54:37 +08:00
|
|
|
Diag(RelatedClass->getLocStart(), diag::note_declared_at);
|
|
|
|
Diag(TDNDecl->getLocStart(), diag::note_declared_at);
|
|
|
|
|
|
|
|
QualType receiverType =
|
|
|
|
Context.getObjCInterfaceType(RelatedClass);
|
|
|
|
// Argument.
|
|
|
|
Expr *args[] = { SrcExpr };
|
|
|
|
ExprResult msg = BuildClassMessageImplicit(receiverType, false,
|
|
|
|
ClassMethod->getLocation(),
|
|
|
|
ClassMethod->getSelector(), ClassMethod,
|
|
|
|
MultiExprArg(args, 1));
|
|
|
|
SrcExpr = msg.take();
|
|
|
|
return true;
|
2013-12-11 01:08:13 +08:00
|
|
|
}
|
2013-12-07 08:34:23 +08:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
// Implicit conversion from ObjC type to CF object is needed.
|
2013-12-11 01:08:13 +08:00
|
|
|
if (InstanceMethod) {
|
2013-12-11 07:18:06 +08:00
|
|
|
std::string ExpressionString;
|
2013-12-11 01:08:13 +08:00
|
|
|
SourceLocation SrcExprEndLoc = PP.getLocForEndOfToken(SrcExpr->getLocEnd());
|
2013-12-11 07:18:06 +08:00
|
|
|
if (InstanceMethod->isPropertyAccessor())
|
|
|
|
if (const ObjCPropertyDecl *PDecl = InstanceMethod->findPropertyDecl()) {
|
|
|
|
// fixit: ObjectExpr.propertyname when it is aproperty accessor.
|
|
|
|
ExpressionString = ".";
|
|
|
|
ExpressionString += PDecl->getNameAsString();
|
|
|
|
Diag(Loc, diag::err_objc_bridged_related_known_method)
|
|
|
|
<< SrcType << DestType << InstanceMethod->getSelector() << true
|
|
|
|
<< FixItHint::CreateInsertion(SrcExprEndLoc, ExpressionString);
|
|
|
|
}
|
|
|
|
if (ExpressionString.empty()) {
|
|
|
|
// Provide a fixit: [ObjectExpr InstanceMethod]
|
|
|
|
ExpressionString = " ";
|
|
|
|
ExpressionString += InstanceMethod->getSelector().getAsString();
|
|
|
|
ExpressionString += "]";
|
2013-12-11 01:08:13 +08:00
|
|
|
|
2013-12-11 07:18:06 +08:00
|
|
|
Diag(Loc, diag::err_objc_bridged_related_known_method)
|
|
|
|
<< SrcType << DestType << InstanceMethod->getSelector() << true
|
|
|
|
<< FixItHint::CreateInsertion(SrcExpr->getLocStart(), "[")
|
|
|
|
<< FixItHint::CreateInsertion(SrcExprEndLoc, ExpressionString);
|
|
|
|
}
|
2013-12-17 06:54:37 +08:00
|
|
|
Diag(RelatedClass->getLocStart(), diag::note_declared_at);
|
|
|
|
Diag(TDNDecl->getLocStart(), diag::note_declared_at);
|
|
|
|
|
|
|
|
ExprResult msg =
|
|
|
|
BuildInstanceMessageImplicit(SrcExpr, SrcType,
|
|
|
|
InstanceMethod->getLocation(),
|
|
|
|
InstanceMethod->getSelector(),
|
|
|
|
InstanceMethod, None);
|
|
|
|
SrcExpr = msg.take();
|
|
|
|
return true;
|
2013-12-11 01:08:13 +08:00
|
|
|
}
|
2013-12-07 08:34:23 +08:00
|
|
|
}
|
2013-12-17 06:54:37 +08:00
|
|
|
return false;
|
2013-12-07 08:34:23 +08:00
|
|
|
}
|
|
|
|
|
2011-10-18 02:40:02 +08:00
|
|
|
Sema::ARCConversionResult
|
2011-06-16 07:02:42 +08:00
|
|
|
Sema::CheckObjCARCConversion(SourceRange castRange, QualType castType,
|
2013-08-01 05:40:51 +08:00
|
|
|
Expr *&castExpr, CheckedConversionKind CCK,
|
|
|
|
bool DiagnoseCFAudited) {
|
2011-06-16 07:02:42 +08:00
|
|
|
QualType castExprType = castExpr->getType();
|
2011-10-01 09:01:08 +08:00
|
|
|
|
|
|
|
// For the purposes of the classification, we assume reference types
|
|
|
|
// will bind to temporaries.
|
|
|
|
QualType effCastType = castType;
|
|
|
|
if (const ReferenceType *ref = castType->getAs<ReferenceType>())
|
|
|
|
effCastType = ref->getPointeeType();
|
2011-06-16 07:02:42 +08:00
|
|
|
|
|
|
|
ARCConversionTypeClass exprACTC = classifyTypeForARCConversion(castExprType);
|
2011-10-01 09:01:08 +08:00
|
|
|
ARCConversionTypeClass castACTC = classifyTypeForARCConversion(effCastType);
|
2011-10-29 04:06:07 +08:00
|
|
|
if (exprACTC == castACTC) {
|
|
|
|
// check for viablity and report error if casting an rvalue to a
|
|
|
|
// life-time qualifier.
|
2011-10-29 08:06:10 +08:00
|
|
|
if ((castACTC == ACTC_retainable) &&
|
2011-10-29 04:06:07 +08:00
|
|
|
(CCK == CCK_CStyleCast || CCK == CCK_OtherCast) &&
|
2011-10-29 08:06:10 +08:00
|
|
|
(castType != castExprType)) {
|
|
|
|
const Type *DT = castType.getTypePtr();
|
|
|
|
QualType QDT = castType;
|
|
|
|
// We desugar some types but not others. We ignore those
|
|
|
|
// that cannot happen in a cast; i.e. auto, and those which
|
|
|
|
// should not be de-sugared; i.e typedef.
|
|
|
|
if (const ParenType *PT = dyn_cast<ParenType>(DT))
|
|
|
|
QDT = PT->desugar();
|
|
|
|
else if (const TypeOfType *TP = dyn_cast<TypeOfType>(DT))
|
|
|
|
QDT = TP->desugar();
|
|
|
|
else if (const AttributedType *AT = dyn_cast<AttributedType>(DT))
|
|
|
|
QDT = AT->desugar();
|
|
|
|
if (QDT != castType &&
|
|
|
|
QDT.getObjCLifetime() != Qualifiers::OCL_None) {
|
|
|
|
SourceLocation loc =
|
|
|
|
(castRange.isValid() ? castRange.getBegin()
|
|
|
|
: castExpr->getExprLoc());
|
|
|
|
Diag(loc, diag::err_arc_nolifetime_behavior);
|
|
|
|
}
|
2011-10-29 04:06:07 +08:00
|
|
|
}
|
|
|
|
return ACR_okay;
|
|
|
|
}
|
|
|
|
|
2011-10-18 02:40:02 +08:00
|
|
|
if (isAnyCLike(exprACTC) && isAnyCLike(castACTC)) return ACR_okay;
|
2011-10-01 09:01:08 +08:00
|
|
|
|
|
|
|
// Allow all of these types to be cast to integer types (but not
|
|
|
|
// vice-versa).
|
|
|
|
if (castACTC == ACTC_none && castType->isIntegralType(Context))
|
2011-10-18 02:40:02 +08:00
|
|
|
return ACR_okay;
|
2011-06-16 07:02:42 +08:00
|
|
|
|
|
|
|
// Allow casts between pointers to lifetime types (e.g., __strong id*)
|
|
|
|
// and pointers to void (e.g., cv void *). Casting from void* to lifetime*
|
|
|
|
// must be explicit.
|
2011-10-01 09:01:08 +08:00
|
|
|
if (exprACTC == ACTC_indirectRetainable && castACTC == ACTC_voidPtr)
|
2011-10-18 02:40:02 +08:00
|
|
|
return ACR_okay;
|
2011-10-01 09:01:08 +08:00
|
|
|
if (castACTC == ACTC_indirectRetainable && exprACTC == ACTC_voidPtr &&
|
|
|
|
CCK != CCK_ImplicitConversion)
|
2011-10-18 02:40:02 +08:00
|
|
|
return ACR_okay;
|
2013-11-16 06:18:17 +08:00
|
|
|
|
|
|
|
if (castACTC == ACTC_retainable && exprACTC == ACTC_coreFoundation &&
|
|
|
|
(CCK == CCK_CStyleCast || CCK == CCK_FunctionalCast))
|
2013-11-22 04:50:32 +08:00
|
|
|
if (CheckObjCBridgeNSCast<ObjCBridgeAttr>(*this, castType, castExpr) ||
|
|
|
|
CheckObjCBridgeNSCast<ObjCBridgeMutableAttr>(*this, castType, castExpr))
|
2013-11-17 03:16:32 +08:00
|
|
|
return ACR_okay;
|
|
|
|
|
|
|
|
if (castACTC == ACTC_coreFoundation && exprACTC == ACTC_retainable &&
|
|
|
|
(CCK == CCK_CStyleCast || CCK == CCK_FunctionalCast))
|
2013-11-22 04:50:32 +08:00
|
|
|
if (CheckObjCBridgeCFCast<ObjCBridgeAttr>(*this, castType, castExpr) ||
|
|
|
|
CheckObjCBridgeCFCast<ObjCBridgeMutableAttr>(*this, castType, castExpr))
|
2013-11-16 06:18:17 +08:00
|
|
|
return ACR_okay;
|
|
|
|
|
2011-10-01 09:01:08 +08:00
|
|
|
|
2012-07-28 06:37:07 +08:00
|
|
|
switch (ARCCastChecker(Context, exprACTC, castACTC, false).Visit(castExpr)) {
|
2011-10-01 09:01:08 +08:00
|
|
|
// For invalid casts, fall through.
|
|
|
|
case ACC_invalid:
|
|
|
|
break;
|
|
|
|
|
|
|
|
// Do nothing for both bottom and +0.
|
|
|
|
case ACC_bottom:
|
|
|
|
case ACC_plusZero:
|
2011-10-18 02:40:02 +08:00
|
|
|
return ACR_okay;
|
2011-10-01 09:01:08 +08:00
|
|
|
|
|
|
|
// If the result is +1, consume it here.
|
|
|
|
case ACC_plusOne:
|
|
|
|
castExpr = ImplicitCastExpr::Create(Context, castExpr->getType(),
|
|
|
|
CK_ARCConsumeObject, castExpr,
|
|
|
|
0, VK_RValue);
|
|
|
|
ExprNeedsCleanups = true;
|
2011-10-18 02:40:02 +08:00
|
|
|
return ACR_okay;
|
2011-10-01 09:01:08 +08:00
|
|
|
}
|
2011-10-18 02:40:02 +08:00
|
|
|
|
|
|
|
// If this is a non-implicit cast from id or block type to a
|
|
|
|
// CoreFoundation type, delay complaining in case the cast is used
|
|
|
|
// in an acceptable context.
|
|
|
|
if (exprACTC == ACTC_retainable && isAnyRetainable(castACTC) &&
|
|
|
|
CCK != CCK_ImplicitConversion)
|
|
|
|
return ACR_unbridged;
|
|
|
|
|
2013-12-18 03:33:43 +08:00
|
|
|
// Do not issue bridge cast" diagnostic when implicit casting a cstring
|
|
|
|
// to 'NSString *'. Let caller issue a normal mismatched diagnostic with
|
|
|
|
// suitable fix-it.
|
|
|
|
if (castACTC == ACTC_retainable && exprACTC == ACTC_none) {
|
|
|
|
bool IsNSString = false;
|
|
|
|
FixItHint Hint;
|
|
|
|
if (ConversionToObjCStringLiteralCheck(
|
|
|
|
castType, castExpr, Hint, IsNSString) && IsNSString)
|
|
|
|
return ACR_okay;
|
|
|
|
}
|
|
|
|
|
2013-08-01 05:40:51 +08:00
|
|
|
// Do not issue "bridge cast" diagnostic when implicit casting
|
|
|
|
// a retainable object to a CF type parameter belonging to an audited
|
|
|
|
// CF API function. Let caller issue a normal type mismatched diagnostic
|
|
|
|
// instead.
|
|
|
|
if (!DiagnoseCFAudited || exprACTC != ACTC_retainable ||
|
|
|
|
castACTC != ACTC_coreFoundation)
|
|
|
|
diagnoseObjCARCConversion(*this, castRange, castType, castACTC,
|
|
|
|
castExpr, castExpr, exprACTC, CCK);
|
2011-10-18 02:40:02 +08:00
|
|
|
return ACR_okay;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Given that we saw an expression with the ARCUnbridgedCastTy
|
|
|
|
/// placeholder type, complain bitterly.
|
|
|
|
void Sema::diagnoseARCUnbridgedCast(Expr *e) {
|
|
|
|
// We expect the spurious ImplicitCastExpr to already have been stripped.
|
|
|
|
assert(!e->hasPlaceholderType(BuiltinType::ARCUnbridgedCast));
|
|
|
|
CastExpr *realCast = cast<CastExpr>(e->IgnoreParens());
|
|
|
|
|
|
|
|
SourceRange castRange;
|
|
|
|
QualType castType;
|
|
|
|
CheckedConversionKind CCK;
|
|
|
|
|
|
|
|
if (CStyleCastExpr *cast = dyn_cast<CStyleCastExpr>(realCast)) {
|
|
|
|
castRange = SourceRange(cast->getLParenLoc(), cast->getRParenLoc());
|
|
|
|
castType = cast->getTypeAsWritten();
|
|
|
|
CCK = CCK_CStyleCast;
|
|
|
|
} else if (ExplicitCastExpr *cast = dyn_cast<ExplicitCastExpr>(realCast)) {
|
|
|
|
castRange = cast->getTypeInfoAsWritten()->getTypeLoc().getSourceRange();
|
|
|
|
castType = cast->getTypeAsWritten();
|
|
|
|
CCK = CCK_OtherCast;
|
|
|
|
} else {
|
|
|
|
castType = cast->getType();
|
|
|
|
CCK = CCK_ImplicitConversion;
|
2011-06-16 07:02:42 +08:00
|
|
|
}
|
2011-10-18 02:40:02 +08:00
|
|
|
|
|
|
|
ARCConversionTypeClass castACTC =
|
|
|
|
classifyTypeForARCConversion(castType.getNonReferenceType());
|
|
|
|
|
|
|
|
Expr *castExpr = realCast->getSubExpr();
|
|
|
|
assert(classifyTypeForARCConversion(castExpr->getType()) == ACTC_retainable);
|
|
|
|
|
|
|
|
diagnoseObjCARCConversion(*this, castRange, castType, castACTC,
|
2013-02-23 06:02:53 +08:00
|
|
|
castExpr, realCast, ACTC_retainable, CCK);
|
2011-10-18 02:40:02 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// stripARCUnbridgedCast - Given an expression of ARCUnbridgedCast
|
|
|
|
/// type, remove the placeholder cast.
|
|
|
|
Expr *Sema::stripARCUnbridgedCast(Expr *e) {
|
|
|
|
assert(e->hasPlaceholderType(BuiltinType::ARCUnbridgedCast));
|
|
|
|
|
|
|
|
if (ParenExpr *pe = dyn_cast<ParenExpr>(e)) {
|
|
|
|
Expr *sub = stripARCUnbridgedCast(pe->getSubExpr());
|
|
|
|
return new (Context) ParenExpr(pe->getLParen(), pe->getRParen(), sub);
|
|
|
|
} else if (UnaryOperator *uo = dyn_cast<UnaryOperator>(e)) {
|
|
|
|
assert(uo->getOpcode() == UO_Extension);
|
|
|
|
Expr *sub = stripARCUnbridgedCast(uo->getSubExpr());
|
|
|
|
return new (Context) UnaryOperator(sub, UO_Extension, sub->getType(),
|
|
|
|
sub->getValueKind(), sub->getObjectKind(),
|
|
|
|
uo->getOperatorLoc());
|
|
|
|
} else if (GenericSelectionExpr *gse = dyn_cast<GenericSelectionExpr>(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())
|
|
|
|
sub = stripARCUnbridgedCast(sub);
|
|
|
|
subExprs[i] = sub;
|
2011-06-16 07:02:42 +08:00
|
|
|
}
|
2011-10-18 02:40:02 +08:00
|
|
|
|
|
|
|
return new (Context) GenericSelectionExpr(Context, gse->getGenericLoc(),
|
|
|
|
gse->getControllingExpr(),
|
2012-08-24 19:54:20 +08:00
|
|
|
subTypes, subExprs,
|
|
|
|
gse->getDefaultLoc(),
|
2011-10-18 02:40:02 +08:00
|
|
|
gse->getRParenLoc(),
|
|
|
|
gse->containsUnexpandedParameterPack(),
|
|
|
|
gse->getResultIndex());
|
|
|
|
} else {
|
|
|
|
assert(isa<ImplicitCastExpr>(e) && "bad form of unbridged cast!");
|
|
|
|
return cast<ImplicitCastExpr>(e)->getSubExpr();
|
2011-06-16 07:02:42 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-07-08 07:04:17 +08:00
|
|
|
bool Sema::CheckObjCARCUnavailableWeakConversion(QualType castType,
|
|
|
|
QualType exprType) {
|
|
|
|
QualType canCastType =
|
|
|
|
Context.getCanonicalType(castType).getUnqualifiedType();
|
|
|
|
QualType canExprType =
|
|
|
|
Context.getCanonicalType(exprType).getUnqualifiedType();
|
|
|
|
if (isa<ObjCObjectPointerType>(canCastType) &&
|
|
|
|
castType.getObjCLifetime() == Qualifiers::OCL_Weak &&
|
|
|
|
canExprType->isObjCObjectPointerType()) {
|
|
|
|
if (const ObjCObjectPointerType *ObjT =
|
|
|
|
canExprType->getAs<ObjCObjectPointerType>())
|
2012-08-23 14:16:52 +08:00
|
|
|
if (const ObjCInterfaceDecl *ObjI = ObjT->getInterfaceDecl())
|
|
|
|
return !ObjI->isArcWeakrefUnavailable();
|
2011-07-08 07:04:17 +08:00
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2011-07-07 14:58:02 +08:00
|
|
|
/// Look for an ObjCReclaimReturnedObject cast and destroy it.
|
|
|
|
static Expr *maybeUndoReclaimObject(Expr *e) {
|
|
|
|
// For now, we just undo operands that are *immediately* reclaim
|
|
|
|
// expressions, which prevents the vast majority of potential
|
|
|
|
// problems here. To catch them all, we'd need to rebuild arbitrary
|
|
|
|
// value-propagating subexpressions --- we can't reliably rebuild
|
|
|
|
// in-place because of expression sharing.
|
|
|
|
if (ImplicitCastExpr *ice = dyn_cast<ImplicitCastExpr>(e))
|
2011-09-10 14:18:15 +08:00
|
|
|
if (ice->getCastKind() == CK_ARCReclaimReturnedObject)
|
2011-07-07 14:58:02 +08:00
|
|
|
return ice->getSubExpr();
|
|
|
|
|
|
|
|
return e;
|
|
|
|
}
|
|
|
|
|
2011-06-16 07:02:42 +08:00
|
|
|
ExprResult Sema::BuildObjCBridgedCast(SourceLocation LParenLoc,
|
|
|
|
ObjCBridgeCastKind Kind,
|
|
|
|
SourceLocation BridgeKeywordLoc,
|
|
|
|
TypeSourceInfo *TSInfo,
|
|
|
|
Expr *SubExpr) {
|
2011-08-26 08:48:42 +08:00
|
|
|
ExprResult SubResult = UsualUnaryConversions(SubExpr);
|
|
|
|
if (SubResult.isInvalid()) return ExprError();
|
|
|
|
SubExpr = SubResult.take();
|
|
|
|
|
2011-06-16 07:02:42 +08:00
|
|
|
QualType T = TSInfo->getType();
|
|
|
|
QualType FromType = SubExpr->getType();
|
|
|
|
|
2011-09-09 13:25:32 +08:00
|
|
|
CastKind CK;
|
|
|
|
|
2011-06-16 07:02:42 +08:00
|
|
|
bool MustConsume = false;
|
|
|
|
if (T->isDependentType() || SubExpr->isTypeDependent()) {
|
|
|
|
// Okay: we'll build a dependent expression type.
|
2011-09-09 13:25:32 +08:00
|
|
|
CK = CK_Dependent;
|
2011-06-16 07:02:42 +08:00
|
|
|
} else if (T->isObjCARCBridgableType() && FromType->isCARCBridgableType()) {
|
|
|
|
// Casting CF -> id
|
2011-09-09 13:25:32 +08:00
|
|
|
CK = (T->isBlockPointerType() ? CK_AnyPointerToBlockPointerCast
|
|
|
|
: CK_CPointerToObjCPointerCast);
|
2011-06-16 07:02:42 +08:00
|
|
|
switch (Kind) {
|
|
|
|
case OBC_Bridge:
|
|
|
|
break;
|
|
|
|
|
2012-02-02 06:56:20 +08:00
|
|
|
case OBC_BridgeRetained: {
|
2012-06-01 08:10:47 +08:00
|
|
|
bool br = isKnownName("CFBridgingRelease");
|
2011-06-16 07:02:42 +08:00
|
|
|
Diag(BridgeKeywordLoc, diag::err_arc_bridge_cast_wrong_kind)
|
|
|
|
<< 2
|
|
|
|
<< FromType
|
|
|
|
<< (T->isBlockPointerType()? 1 : 0)
|
|
|
|
<< T
|
|
|
|
<< SubExpr->getSourceRange()
|
|
|
|
<< Kind;
|
|
|
|
Diag(BridgeKeywordLoc, diag::note_arc_bridge)
|
|
|
|
<< FixItHint::CreateReplacement(BridgeKeywordLoc, "__bridge");
|
|
|
|
Diag(BridgeKeywordLoc, diag::note_arc_bridge_transfer)
|
2012-02-02 06:56:20 +08:00
|
|
|
<< FromType << br
|
2011-06-16 07:02:42 +08:00
|
|
|
<< FixItHint::CreateReplacement(BridgeKeywordLoc,
|
2012-02-02 06:56:20 +08:00
|
|
|
br ? "CFBridgingRelease "
|
|
|
|
: "__bridge_transfer ");
|
2011-06-16 07:02:42 +08:00
|
|
|
|
|
|
|
Kind = OBC_Bridge;
|
|
|
|
break;
|
2012-02-02 06:56:20 +08:00
|
|
|
}
|
2011-06-16 07:02:42 +08:00
|
|
|
|
|
|
|
case OBC_BridgeTransfer:
|
|
|
|
// We must consume the Objective-C object produced by the cast.
|
|
|
|
MustConsume = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else if (T->isCARCBridgableType() && FromType->isObjCARCBridgableType()) {
|
|
|
|
// Okay: id -> CF
|
2011-09-09 13:25:32 +08:00
|
|
|
CK = CK_BitCast;
|
2011-06-16 07:02:42 +08:00
|
|
|
switch (Kind) {
|
|
|
|
case OBC_Bridge:
|
2011-07-07 14:58:02 +08:00
|
|
|
// Reclaiming a value that's going to be __bridge-casted to CF
|
|
|
|
// is very dangerous, so we don't do it.
|
|
|
|
SubExpr = maybeUndoReclaimObject(SubExpr);
|
2011-06-16 07:02:42 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case OBC_BridgeRetained:
|
|
|
|
// Produce the object before casting it.
|
|
|
|
SubExpr = ImplicitCastExpr::Create(Context, FromType,
|
2011-09-10 14:18:15 +08:00
|
|
|
CK_ARCProduceObject,
|
2011-06-16 07:02:42 +08:00
|
|
|
SubExpr, 0, VK_RValue);
|
|
|
|
break;
|
|
|
|
|
2012-02-02 06:56:20 +08:00
|
|
|
case OBC_BridgeTransfer: {
|
2012-06-01 08:10:47 +08:00
|
|
|
bool br = isKnownName("CFBridgingRetain");
|
2011-06-16 07:02:42 +08:00
|
|
|
Diag(BridgeKeywordLoc, diag::err_arc_bridge_cast_wrong_kind)
|
|
|
|
<< (FromType->isBlockPointerType()? 1 : 0)
|
|
|
|
<< FromType
|
|
|
|
<< 2
|
|
|
|
<< T
|
|
|
|
<< SubExpr->getSourceRange()
|
|
|
|
<< Kind;
|
|
|
|
|
|
|
|
Diag(BridgeKeywordLoc, diag::note_arc_bridge)
|
|
|
|
<< FixItHint::CreateReplacement(BridgeKeywordLoc, "__bridge ");
|
|
|
|
Diag(BridgeKeywordLoc, diag::note_arc_bridge_retained)
|
2012-02-02 06:56:20 +08:00
|
|
|
<< T << br
|
|
|
|
<< FixItHint::CreateReplacement(BridgeKeywordLoc,
|
|
|
|
br ? "CFBridgingRetain " : "__bridge_retained");
|
2011-06-16 07:02:42 +08:00
|
|
|
|
|
|
|
Kind = OBC_Bridge;
|
|
|
|
break;
|
|
|
|
}
|
2012-02-02 06:56:20 +08:00
|
|
|
}
|
2011-06-16 07:02:42 +08:00
|
|
|
} else {
|
|
|
|
Diag(LParenLoc, diag::err_arc_bridge_cast_incompatible)
|
|
|
|
<< FromType << T << Kind
|
|
|
|
<< SubExpr->getSourceRange()
|
|
|
|
<< TSInfo->getTypeLoc().getSourceRange();
|
|
|
|
return ExprError();
|
|
|
|
}
|
|
|
|
|
2011-09-09 13:25:32 +08:00
|
|
|
Expr *Result = new (Context) ObjCBridgedCastExpr(LParenLoc, Kind, CK,
|
2011-06-16 07:02:42 +08:00
|
|
|
BridgeKeywordLoc,
|
|
|
|
TSInfo, SubExpr);
|
|
|
|
|
|
|
|
if (MustConsume) {
|
|
|
|
ExprNeedsCleanups = true;
|
2011-09-10 14:18:15 +08:00
|
|
|
Result = ImplicitCastExpr::Create(Context, T, CK_ARCConsumeObject, Result,
|
2011-06-16 07:02:42 +08:00
|
|
|
0, VK_RValue);
|
|
|
|
}
|
|
|
|
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|
|
|
|
ExprResult Sema::ActOnObjCBridgedCast(Scope *S,
|
|
|
|
SourceLocation LParenLoc,
|
|
|
|
ObjCBridgeCastKind Kind,
|
|
|
|
SourceLocation BridgeKeywordLoc,
|
|
|
|
ParsedType Type,
|
|
|
|
SourceLocation RParenLoc,
|
|
|
|
Expr *SubExpr) {
|
|
|
|
TypeSourceInfo *TSInfo = 0;
|
|
|
|
QualType T = GetTypeFromParser(Type, &TSInfo);
|
2013-11-21 08:39:36 +08:00
|
|
|
if (Kind == OBC_Bridge)
|
|
|
|
CheckTollFreeBridgeCast(T, SubExpr);
|
2011-06-16 07:02:42 +08:00
|
|
|
if (!TSInfo)
|
|
|
|
TSInfo = Context.getTrivialTypeSourceInfo(T, LParenLoc);
|
|
|
|
return BuildObjCBridgedCast(LParenLoc, Kind, BridgeKeywordLoc, TSInfo,
|
|
|
|
SubExpr);
|
|
|
|
}
|