2009-06-02 17:58:47 +00:00
|
|
|
//===--- ExprObjC.h - Classes for representing ObjC expressions -*- C++ -*-===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// This file defines the ExprObjC interface and subclasses.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#ifndef LLVM_CLANG_AST_EXPROBJC_H
|
|
|
|
#define LLVM_CLANG_AST_EXPROBJC_H
|
|
|
|
|
2011-02-20 13:06:31 +00:00
|
|
|
#include "clang/AST/DeclObjC.h"
|
2009-06-02 17:58:47 +00:00
|
|
|
#include "clang/AST/Expr.h"
|
2011-10-20 21:14:49 +00:00
|
|
|
#include "clang/AST/SelectorLocationsKind.h"
|
2009-06-02 17:58:47 +00:00
|
|
|
#include "clang/Basic/IdentifierTable.h"
|
2012-04-14 14:01:31 +00:00
|
|
|
#include "llvm/Support/Compiler.h"
|
2009-06-02 17:58:47 +00:00
|
|
|
|
|
|
|
namespace clang {
|
|
|
|
class IdentifierInfo;
|
|
|
|
class ASTContext;
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
/// ObjCStringLiteral, used for Objective-C string literals
|
|
|
|
/// i.e. @"foo".
|
|
|
|
class ObjCStringLiteral : public Expr {
|
|
|
|
Stmt *String;
|
|
|
|
SourceLocation AtLoc;
|
|
|
|
public:
|
|
|
|
ObjCStringLiteral(StringLiteral *SL, QualType T, SourceLocation L)
|
2011-02-20 13:06:31 +00:00
|
|
|
: Expr(ObjCStringLiteralClass, T, VK_RValue, OK_Ordinary, false, false,
|
2011-07-17 15:40:56 +00:00
|
|
|
false, false),
|
2011-02-20 13:06:31 +00:00
|
|
|
String(SL), AtLoc(L) {}
|
2009-06-02 17:58:47 +00:00
|
|
|
explicit ObjCStringLiteral(EmptyShell Empty)
|
|
|
|
: Expr(ObjCStringLiteralClass, Empty) {}
|
|
|
|
|
|
|
|
StringLiteral *getString() { return cast<StringLiteral>(String); }
|
|
|
|
const StringLiteral *getString() const { return cast<StringLiteral>(String); }
|
|
|
|
void setString(StringLiteral *S) { String = S; }
|
|
|
|
|
|
|
|
SourceLocation getAtLoc() const { return AtLoc; }
|
|
|
|
void setAtLoc(SourceLocation L) { AtLoc = L; }
|
|
|
|
|
2013-04-08 18:45:10 +00:00
|
|
|
SourceLocation getLocStart() const LLVM_READONLY { return AtLoc; }
|
|
|
|
SourceLocation getLocEnd() const LLVM_READONLY { return String->getLocEnd(); }
|
2009-10-14 18:03:49 +00:00
|
|
|
|
|
|
|
static bool classof(const Stmt *T) {
|
|
|
|
return T->getStmtClass() == ObjCStringLiteralClass;
|
2009-06-02 17:58:47 +00:00
|
|
|
}
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
// Iterators
|
2011-02-20 13:06:31 +00:00
|
|
|
child_range children() { return child_range(&String, &String+1); }
|
2009-06-02 17:58:47 +00:00
|
|
|
};
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2012-04-14 14:01:31 +00:00
|
|
|
/// ObjCBoolLiteralExpr - Objective-C Boolean Literal.
|
|
|
|
///
|
|
|
|
class ObjCBoolLiteralExpr : public Expr {
|
|
|
|
bool Value;
|
|
|
|
SourceLocation Loc;
|
|
|
|
public:
|
|
|
|
ObjCBoolLiteralExpr(bool val, QualType Ty, SourceLocation l) :
|
|
|
|
Expr(ObjCBoolLiteralExprClass, Ty, VK_RValue, OK_Ordinary, false, false,
|
|
|
|
false, false), Value(val), Loc(l) {}
|
|
|
|
|
|
|
|
explicit ObjCBoolLiteralExpr(EmptyShell Empty)
|
|
|
|
: Expr(ObjCBoolLiteralExprClass, Empty) { }
|
|
|
|
|
|
|
|
bool getValue() const { return Value; }
|
|
|
|
void setValue(bool V) { Value = V; }
|
|
|
|
|
2013-04-08 18:45:10 +00:00
|
|
|
SourceLocation getLocStart() const LLVM_READONLY { return Loc; }
|
|
|
|
SourceLocation getLocEnd() const LLVM_READONLY { return Loc; }
|
|
|
|
|
2012-04-14 14:01:31 +00:00
|
|
|
SourceLocation getLocation() const { return Loc; }
|
|
|
|
void setLocation(SourceLocation L) { Loc = L; }
|
|
|
|
|
|
|
|
static bool classof(const Stmt *T) {
|
|
|
|
return T->getStmtClass() == ObjCBoolLiteralExprClass;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Iterators
|
|
|
|
child_range children() { return child_range(); }
|
|
|
|
};
|
|
|
|
|
2012-08-15 20:02:54 +00:00
|
|
|
/// ObjCBoxedExpr - used for generalized expression boxing.
|
2015-07-05 14:23:59 +00:00
|
|
|
/// as in: @(strdup("hello world")), @(random()) or @(view.frame)
|
2012-08-15 20:02:54 +00:00
|
|
|
/// Also used for boxing non-parenthesized numeric literals;
|
|
|
|
/// as in: @42 or \@true (c++/objc++) or \@__yes (c/objc).
|
|
|
|
class ObjCBoxedExpr : public Expr {
|
|
|
|
Stmt *SubExpr;
|
|
|
|
ObjCMethodDecl *BoxingMethod;
|
|
|
|
SourceRange Range;
|
2012-04-14 14:01:31 +00:00
|
|
|
public:
|
2012-08-15 20:02:54 +00:00
|
|
|
ObjCBoxedExpr(Expr *E, QualType T, ObjCMethodDecl *method,
|
|
|
|
SourceRange R)
|
|
|
|
: Expr(ObjCBoxedExprClass, T, VK_RValue, OK_Ordinary,
|
|
|
|
E->isTypeDependent(), E->isValueDependent(),
|
|
|
|
E->isInstantiationDependent(), E->containsUnexpandedParameterPack()),
|
|
|
|
SubExpr(E), BoxingMethod(method), Range(R) {}
|
|
|
|
explicit ObjCBoxedExpr(EmptyShell Empty)
|
|
|
|
: Expr(ObjCBoxedExprClass, Empty) {}
|
2012-04-14 14:01:31 +00:00
|
|
|
|
2012-08-15 20:02:54 +00:00
|
|
|
Expr *getSubExpr() { return cast<Expr>(SubExpr); }
|
|
|
|
const Expr *getSubExpr() const { return cast<Expr>(SubExpr); }
|
2012-04-14 14:01:31 +00:00
|
|
|
|
2012-08-15 20:02:54 +00:00
|
|
|
ObjCMethodDecl *getBoxingMethod() const {
|
|
|
|
return BoxingMethod;
|
2012-04-14 14:01:31 +00:00
|
|
|
}
|
2012-08-15 20:02:54 +00:00
|
|
|
|
|
|
|
SourceLocation getAtLoc() const { return Range.getBegin(); }
|
2012-04-14 14:01:31 +00:00
|
|
|
|
2013-04-08 18:45:10 +00:00
|
|
|
SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); }
|
|
|
|
SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); }
|
2012-04-14 14:01:31 +00:00
|
|
|
SourceRange getSourceRange() const LLVM_READONLY {
|
2012-08-15 20:02:54 +00:00
|
|
|
return Range;
|
2012-04-14 14:01:31 +00:00
|
|
|
}
|
2012-08-15 20:02:54 +00:00
|
|
|
|
2012-04-14 14:01:31 +00:00
|
|
|
static bool classof(const Stmt *T) {
|
2012-08-15 20:02:54 +00:00
|
|
|
return T->getStmtClass() == ObjCBoxedExprClass;
|
2012-04-14 14:01:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Iterators
|
2012-08-15 20:02:54 +00:00
|
|
|
child_range children() { return child_range(&SubExpr, &SubExpr+1); }
|
2015-01-18 16:23:48 +00:00
|
|
|
|
|
|
|
typedef ConstExprIterator const_arg_iterator;
|
|
|
|
|
|
|
|
const_arg_iterator arg_begin() const {
|
|
|
|
return reinterpret_cast<Stmt const * const*>(&SubExpr);
|
|
|
|
}
|
|
|
|
const_arg_iterator arg_end() const {
|
|
|
|
return reinterpret_cast<Stmt const * const*>(&SubExpr + 1);
|
|
|
|
}
|
2012-08-15 20:02:54 +00:00
|
|
|
|
2012-04-14 14:01:31 +00:00
|
|
|
friend class ASTStmtReader;
|
|
|
|
};
|
|
|
|
|
|
|
|
/// ObjCArrayLiteral - used for objective-c array containers; as in:
|
|
|
|
/// @[@"Hello", NSApp, [NSNumber numberWithInt:42]];
|
|
|
|
class ObjCArrayLiteral : public Expr {
|
|
|
|
unsigned NumElements;
|
|
|
|
SourceRange Range;
|
|
|
|
ObjCMethodDecl *ArrayWithObjectsMethod;
|
|
|
|
|
2013-04-08 18:45:10 +00:00
|
|
|
ObjCArrayLiteral(ArrayRef<Expr *> Elements,
|
2012-04-14 14:01:31 +00:00
|
|
|
QualType T, ObjCMethodDecl * Method,
|
|
|
|
SourceRange SR);
|
|
|
|
|
|
|
|
explicit ObjCArrayLiteral(EmptyShell Empty, unsigned NumElements)
|
|
|
|
: Expr(ObjCArrayLiteralClass, Empty), NumElements(NumElements) {}
|
|
|
|
|
|
|
|
public:
|
2013-12-22 00:07:40 +00:00
|
|
|
static ObjCArrayLiteral *Create(const ASTContext &C,
|
2013-04-08 18:45:10 +00:00
|
|
|
ArrayRef<Expr *> Elements,
|
2012-04-14 14:01:31 +00:00
|
|
|
QualType T, ObjCMethodDecl * Method,
|
|
|
|
SourceRange SR);
|
|
|
|
|
2013-12-22 00:07:40 +00:00
|
|
|
static ObjCArrayLiteral *CreateEmpty(const ASTContext &C,
|
|
|
|
unsigned NumElements);
|
2012-04-14 14:01:31 +00:00
|
|
|
|
2013-04-08 18:45:10 +00:00
|
|
|
SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); }
|
|
|
|
SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); }
|
2012-04-14 14:01:31 +00:00
|
|
|
SourceRange getSourceRange() const LLVM_READONLY { return Range; }
|
|
|
|
|
|
|
|
static bool classof(const Stmt *T) {
|
|
|
|
return T->getStmtClass() == ObjCArrayLiteralClass;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// \brief Retrieve elements of array of literals.
|
|
|
|
Expr **getElements() { return reinterpret_cast<Expr **>(this + 1); }
|
|
|
|
|
|
|
|
/// \brief Retrieve elements of array of literals.
|
|
|
|
const Expr * const *getElements() const {
|
|
|
|
return reinterpret_cast<const Expr * const*>(this + 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// getNumElements - Return number of elements of objective-c array literal.
|
|
|
|
unsigned getNumElements() const { return NumElements; }
|
|
|
|
|
|
|
|
/// getExpr - Return the Expr at the specified index.
|
|
|
|
Expr *getElement(unsigned Index) {
|
|
|
|
assert((Index < NumElements) && "Arg access out of range!");
|
|
|
|
return cast<Expr>(getElements()[Index]);
|
|
|
|
}
|
|
|
|
const Expr *getElement(unsigned Index) const {
|
|
|
|
assert((Index < NumElements) && "Arg access out of range!");
|
|
|
|
return cast<Expr>(getElements()[Index]);
|
|
|
|
}
|
|
|
|
|
|
|
|
ObjCMethodDecl *getArrayWithObjectsMethod() const {
|
|
|
|
return ArrayWithObjectsMethod;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Iterators
|
|
|
|
child_range children() {
|
|
|
|
return child_range((Stmt **)getElements(),
|
|
|
|
(Stmt **)getElements() + NumElements);
|
|
|
|
}
|
|
|
|
|
|
|
|
friend class ASTStmtReader;
|
|
|
|
};
|
|
|
|
|
|
|
|
/// \brief An element in an Objective-C dictionary literal.
|
|
|
|
///
|
|
|
|
struct ObjCDictionaryElement {
|
|
|
|
/// \brief The key for the dictionary element.
|
|
|
|
Expr *Key;
|
|
|
|
|
|
|
|
/// \brief The value of the dictionary element.
|
|
|
|
Expr *Value;
|
|
|
|
|
|
|
|
/// \brief The location of the ellipsis, if this is a pack expansion.
|
|
|
|
SourceLocation EllipsisLoc;
|
|
|
|
|
|
|
|
/// \brief The number of elements this pack expansion will expand to, if
|
|
|
|
/// this is a pack expansion and is known.
|
2013-04-08 18:45:10 +00:00
|
|
|
Optional<unsigned> NumExpansions;
|
2012-04-14 14:01:31 +00:00
|
|
|
|
|
|
|
/// \brief Determines whether this dictionary element is a pack expansion.
|
|
|
|
bool isPackExpansion() const { return EllipsisLoc.isValid(); }
|
|
|
|
};
|
2013-04-08 18:45:10 +00:00
|
|
|
} // end namespace clang
|
|
|
|
|
|
|
|
namespace llvm {
|
2014-11-24 09:15:30 +00:00
|
|
|
template <> struct isPodLike<clang::ObjCDictionaryElement> : std::true_type {};
|
2013-04-08 18:45:10 +00:00
|
|
|
}
|
2012-04-14 14:01:31 +00:00
|
|
|
|
2013-04-08 18:45:10 +00:00
|
|
|
namespace clang {
|
2012-04-14 14:01:31 +00:00
|
|
|
/// ObjCDictionaryLiteral - AST node to represent objective-c dictionary
|
|
|
|
/// literals; as in: @{@"name" : NSUserName(), @"date" : [NSDate date] };
|
|
|
|
class ObjCDictionaryLiteral : public Expr {
|
|
|
|
/// \brief Key/value pair used to store the key and value of a given element.
|
|
|
|
///
|
|
|
|
/// Objects of this type are stored directly after the expression.
|
|
|
|
struct KeyValuePair {
|
|
|
|
Expr *Key;
|
|
|
|
Expr *Value;
|
|
|
|
};
|
|
|
|
|
|
|
|
/// \brief Data that describes an element that is a pack expansion, used if any
|
|
|
|
/// of the elements in the dictionary literal are pack expansions.
|
|
|
|
struct ExpansionData {
|
|
|
|
/// \brief The location of the ellipsis, if this element is a pack
|
|
|
|
/// expansion.
|
|
|
|
SourceLocation EllipsisLoc;
|
|
|
|
|
|
|
|
/// \brief If non-zero, the number of elements that this pack
|
|
|
|
/// expansion will expand to (+1).
|
|
|
|
unsigned NumExpansionsPlusOne;
|
|
|
|
};
|
|
|
|
|
|
|
|
/// \brief The number of elements in this dictionary literal.
|
|
|
|
unsigned NumElements : 31;
|
|
|
|
|
|
|
|
/// \brief Determine whether this dictionary literal has any pack expansions.
|
|
|
|
///
|
|
|
|
/// If the dictionary literal has pack expansions, then there will
|
|
|
|
/// be an array of pack expansion data following the array of
|
|
|
|
/// key/value pairs, which provide the locations of the ellipses (if
|
|
|
|
/// any) and number of elements in the expansion (if known). If
|
|
|
|
/// there are no pack expansions, we optimize away this storage.
|
|
|
|
unsigned HasPackExpansions : 1;
|
|
|
|
|
|
|
|
SourceRange Range;
|
|
|
|
ObjCMethodDecl *DictWithObjectsMethod;
|
|
|
|
|
|
|
|
ObjCDictionaryLiteral(ArrayRef<ObjCDictionaryElement> VK,
|
|
|
|
bool HasPackExpansions,
|
|
|
|
QualType T, ObjCMethodDecl *method,
|
|
|
|
SourceRange SR);
|
|
|
|
|
|
|
|
explicit ObjCDictionaryLiteral(EmptyShell Empty, unsigned NumElements,
|
|
|
|
bool HasPackExpansions)
|
|
|
|
: Expr(ObjCDictionaryLiteralClass, Empty), NumElements(NumElements),
|
|
|
|
HasPackExpansions(HasPackExpansions) {}
|
|
|
|
|
|
|
|
KeyValuePair *getKeyValues() {
|
|
|
|
return reinterpret_cast<KeyValuePair *>(this + 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
const KeyValuePair *getKeyValues() const {
|
|
|
|
return reinterpret_cast<const KeyValuePair *>(this + 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
ExpansionData *getExpansionData() {
|
|
|
|
if (!HasPackExpansions)
|
2014-11-24 09:15:30 +00:00
|
|
|
return nullptr;
|
2012-04-14 14:01:31 +00:00
|
|
|
|
|
|
|
return reinterpret_cast<ExpansionData *>(getKeyValues() + NumElements);
|
|
|
|
}
|
|
|
|
|
|
|
|
const ExpansionData *getExpansionData() const {
|
|
|
|
if (!HasPackExpansions)
|
2014-11-24 09:15:30 +00:00
|
|
|
return nullptr;
|
2012-04-14 14:01:31 +00:00
|
|
|
|
|
|
|
return reinterpret_cast<const ExpansionData *>(getKeyValues()+NumElements);
|
|
|
|
}
|
|
|
|
|
|
|
|
public:
|
2013-12-22 00:07:40 +00:00
|
|
|
static ObjCDictionaryLiteral *Create(const ASTContext &C,
|
2012-04-14 14:01:31 +00:00
|
|
|
ArrayRef<ObjCDictionaryElement> VK,
|
|
|
|
bool HasPackExpansions,
|
|
|
|
QualType T, ObjCMethodDecl *method,
|
|
|
|
SourceRange SR);
|
|
|
|
|
2013-12-22 00:07:40 +00:00
|
|
|
static ObjCDictionaryLiteral *CreateEmpty(const ASTContext &C,
|
2012-04-14 14:01:31 +00:00
|
|
|
unsigned NumElements,
|
|
|
|
bool HasPackExpansions);
|
|
|
|
|
|
|
|
/// getNumElements - Return number of elements of objective-c dictionary
|
|
|
|
/// literal.
|
|
|
|
unsigned getNumElements() const { return NumElements; }
|
|
|
|
|
|
|
|
ObjCDictionaryElement getKeyValueElement(unsigned Index) const {
|
|
|
|
assert((Index < NumElements) && "Arg access out of range!");
|
|
|
|
const KeyValuePair &KV = getKeyValues()[Index];
|
2013-04-08 18:45:10 +00:00
|
|
|
ObjCDictionaryElement Result = { KV.Key, KV.Value, SourceLocation(), None };
|
2012-04-14 14:01:31 +00:00
|
|
|
if (HasPackExpansions) {
|
|
|
|
const ExpansionData &Expansion = getExpansionData()[Index];
|
|
|
|
Result.EllipsisLoc = Expansion.EllipsisLoc;
|
|
|
|
if (Expansion.NumExpansionsPlusOne > 0)
|
|
|
|
Result.NumExpansions = Expansion.NumExpansionsPlusOne - 1;
|
|
|
|
}
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|
|
|
|
ObjCMethodDecl *getDictWithObjectsMethod() const
|
|
|
|
{ return DictWithObjectsMethod; }
|
|
|
|
|
2013-04-08 18:45:10 +00:00
|
|
|
SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); }
|
|
|
|
SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); }
|
2012-04-14 14:01:31 +00:00
|
|
|
SourceRange getSourceRange() const LLVM_READONLY { return Range; }
|
|
|
|
|
|
|
|
static bool classof(const Stmt *T) {
|
|
|
|
return T->getStmtClass() == ObjCDictionaryLiteralClass;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Iterators
|
|
|
|
child_range children() {
|
|
|
|
// Note: we're taking advantage of the layout of the KeyValuePair struct
|
|
|
|
// here. If that struct changes, this code will need to change as well.
|
|
|
|
return child_range(reinterpret_cast<Stmt **>(this + 1),
|
|
|
|
reinterpret_cast<Stmt **>(this + 1) + NumElements * 2);
|
|
|
|
}
|
|
|
|
|
|
|
|
friend class ASTStmtReader;
|
|
|
|
friend class ASTStmtWriter;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2012-08-15 20:02:54 +00:00
|
|
|
/// ObjCEncodeExpr, used for \@encode in Objective-C. \@encode has the same
|
|
|
|
/// type and behavior as StringLiteral except that the string initializer is
|
|
|
|
/// obtained from ASTContext with the encoding type as an argument.
|
2009-06-02 17:58:47 +00:00
|
|
|
class ObjCEncodeExpr : public Expr {
|
2010-05-04 16:12:48 +00:00
|
|
|
TypeSourceInfo *EncodedType;
|
2009-06-02 17:58:47 +00:00
|
|
|
SourceLocation AtLoc, RParenLoc;
|
|
|
|
public:
|
2010-05-04 16:12:48 +00:00
|
|
|
ObjCEncodeExpr(QualType T, TypeSourceInfo *EncodedType,
|
2009-06-02 17:58:47 +00:00
|
|
|
SourceLocation at, SourceLocation rp)
|
2011-02-20 13:06:31 +00:00
|
|
|
: Expr(ObjCEncodeExprClass, T, VK_LValue, OK_Ordinary,
|
|
|
|
EncodedType->getType()->isDependentType(),
|
|
|
|
EncodedType->getType()->isDependentType(),
|
2011-07-17 15:40:56 +00:00
|
|
|
EncodedType->getType()->isInstantiationDependentType(),
|
2011-02-20 13:06:31 +00:00
|
|
|
EncodedType->getType()->containsUnexpandedParameterPack()),
|
2010-05-04 16:12:48 +00:00
|
|
|
EncodedType(EncodedType), AtLoc(at), RParenLoc(rp) {}
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
explicit ObjCEncodeExpr(EmptyShell Empty) : Expr(ObjCEncodeExprClass, Empty){}
|
|
|
|
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
SourceLocation getAtLoc() const { return AtLoc; }
|
|
|
|
void setAtLoc(SourceLocation L) { AtLoc = L; }
|
|
|
|
SourceLocation getRParenLoc() const { return RParenLoc; }
|
|
|
|
void setRParenLoc(SourceLocation L) { RParenLoc = L; }
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2010-05-04 16:12:48 +00:00
|
|
|
QualType getEncodedType() const { return EncodedType->getType(); }
|
2009-06-02 17:58:47 +00:00
|
|
|
|
2010-05-04 16:12:48 +00:00
|
|
|
TypeSourceInfo *getEncodedTypeSourceInfo() const { return EncodedType; }
|
|
|
|
void setEncodedTypeSourceInfo(TypeSourceInfo *EncType) {
|
|
|
|
EncodedType = EncType;
|
|
|
|
}
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2013-04-08 18:45:10 +00:00
|
|
|
SourceLocation getLocStart() const LLVM_READONLY { return AtLoc; }
|
|
|
|
SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; }
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
static bool classof(const Stmt *T) {
|
|
|
|
return T->getStmtClass() == ObjCEncodeExprClass;
|
|
|
|
}
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
// Iterators
|
2011-02-20 13:06:31 +00:00
|
|
|
child_range children() { return child_range(); }
|
2009-06-02 17:58:47 +00:00
|
|
|
};
|
|
|
|
|
2012-08-15 20:02:54 +00:00
|
|
|
/// ObjCSelectorExpr used for \@selector in Objective-C.
|
2009-06-02 17:58:47 +00:00
|
|
|
class ObjCSelectorExpr : public Expr {
|
|
|
|
Selector SelName;
|
|
|
|
SourceLocation AtLoc, RParenLoc;
|
|
|
|
public:
|
|
|
|
ObjCSelectorExpr(QualType T, Selector selInfo,
|
|
|
|
SourceLocation at, SourceLocation rp)
|
2011-02-20 13:06:31 +00:00
|
|
|
: Expr(ObjCSelectorExprClass, T, VK_RValue, OK_Ordinary, false, false,
|
2011-07-17 15:40:56 +00:00
|
|
|
false, false),
|
2011-02-20 13:06:31 +00:00
|
|
|
SelName(selInfo), AtLoc(at), RParenLoc(rp){}
|
2009-06-02 17:58:47 +00:00
|
|
|
explicit ObjCSelectorExpr(EmptyShell Empty)
|
|
|
|
: Expr(ObjCSelectorExprClass, Empty) {}
|
|
|
|
|
|
|
|
Selector getSelector() const { return SelName; }
|
|
|
|
void setSelector(Selector S) { SelName = S; }
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
SourceLocation getAtLoc() const { return AtLoc; }
|
|
|
|
SourceLocation getRParenLoc() const { return RParenLoc; }
|
|
|
|
void setAtLoc(SourceLocation L) { AtLoc = L; }
|
|
|
|
void setRParenLoc(SourceLocation L) { RParenLoc = L; }
|
|
|
|
|
2013-04-08 18:45:10 +00:00
|
|
|
SourceLocation getLocStart() const LLVM_READONLY { return AtLoc; }
|
|
|
|
SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; }
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
/// getNumArgs - Return the number of actual arguments to this call.
|
|
|
|
unsigned getNumArgs() const { return SelName.getNumArgs(); }
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
static bool classof(const Stmt *T) {
|
|
|
|
return T->getStmtClass() == ObjCSelectorExprClass;
|
|
|
|
}
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
// Iterators
|
2011-02-20 13:06:31 +00:00
|
|
|
child_range children() { return child_range(); }
|
2009-06-02 17:58:47 +00:00
|
|
|
};
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2013-04-08 18:45:10 +00:00
|
|
|
/// ObjCProtocolExpr used for protocol expression in Objective-C.
|
|
|
|
///
|
|
|
|
/// This is used as: \@protocol(foo), as in:
|
|
|
|
/// \code
|
|
|
|
/// [obj conformsToProtocol:@protocol(foo)]
|
|
|
|
/// \endcode
|
|
|
|
///
|
2009-06-02 17:58:47 +00:00
|
|
|
/// The return type is "Protocol*".
|
2009-10-14 18:03:49 +00:00
|
|
|
class ObjCProtocolExpr : public Expr {
|
|
|
|
ObjCProtocolDecl *TheProtocol;
|
2012-08-15 20:02:54 +00:00
|
|
|
SourceLocation AtLoc, ProtoLoc, RParenLoc;
|
2009-06-02 17:58:47 +00:00
|
|
|
public:
|
|
|
|
ObjCProtocolExpr(QualType T, ObjCProtocolDecl *protocol,
|
2012-08-15 20:02:54 +00:00
|
|
|
SourceLocation at, SourceLocation protoLoc, SourceLocation rp)
|
2011-02-20 13:06:31 +00:00
|
|
|
: Expr(ObjCProtocolExprClass, T, VK_RValue, OK_Ordinary, false, false,
|
2011-07-17 15:40:56 +00:00
|
|
|
false, false),
|
2012-08-15 20:02:54 +00:00
|
|
|
TheProtocol(protocol), AtLoc(at), ProtoLoc(protoLoc), RParenLoc(rp) {}
|
2009-06-02 17:58:47 +00:00
|
|
|
explicit ObjCProtocolExpr(EmptyShell Empty)
|
|
|
|
: Expr(ObjCProtocolExprClass, Empty) {}
|
|
|
|
|
2009-06-22 08:08:35 +00:00
|
|
|
ObjCProtocolDecl *getProtocol() const { return TheProtocol; }
|
|
|
|
void setProtocol(ObjCProtocolDecl *P) { TheProtocol = P; }
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2012-08-15 20:02:54 +00:00
|
|
|
SourceLocation getProtocolIdLoc() const { return ProtoLoc; }
|
2009-06-02 17:58:47 +00:00
|
|
|
SourceLocation getAtLoc() const { return AtLoc; }
|
|
|
|
SourceLocation getRParenLoc() const { return RParenLoc; }
|
|
|
|
void setAtLoc(SourceLocation L) { AtLoc = L; }
|
|
|
|
void setRParenLoc(SourceLocation L) { RParenLoc = L; }
|
|
|
|
|
2013-04-08 18:45:10 +00:00
|
|
|
SourceLocation getLocStart() const LLVM_READONLY { return AtLoc; }
|
|
|
|
SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; }
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
static bool classof(const Stmt *T) {
|
|
|
|
return T->getStmtClass() == ObjCProtocolExprClass;
|
|
|
|
}
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
// Iterators
|
2011-02-20 13:06:31 +00:00
|
|
|
child_range children() { return child_range(); }
|
2012-08-15 20:02:54 +00:00
|
|
|
|
|
|
|
friend class ASTStmtReader;
|
|
|
|
friend class ASTStmtWriter;
|
2009-06-02 17:58:47 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/// ObjCIvarRefExpr - A reference to an ObjC instance variable.
|
|
|
|
class ObjCIvarRefExpr : public Expr {
|
2012-04-14 14:01:31 +00:00
|
|
|
ObjCIvarDecl *D;
|
2009-06-02 17:58:47 +00:00
|
|
|
Stmt *Base;
|
2012-04-14 14:01:31 +00:00
|
|
|
SourceLocation Loc;
|
2013-04-08 18:45:10 +00:00
|
|
|
/// OpLoc - This is the location of '.' or '->'
|
|
|
|
SourceLocation OpLoc;
|
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
bool IsArrow:1; // True if this is "X->F", false if this is "X.F".
|
|
|
|
bool IsFreeIvar:1; // True if ivar reference has no base (self assumed).
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
public:
|
2011-02-20 13:06:31 +00:00
|
|
|
ObjCIvarRefExpr(ObjCIvarDecl *d, QualType t,
|
2013-04-08 18:45:10 +00:00
|
|
|
SourceLocation l, SourceLocation oploc,
|
|
|
|
Expr *base,
|
2009-10-14 18:03:49 +00:00
|
|
|
bool arrow = false, bool freeIvar = false) :
|
2013-06-10 20:45:12 +00:00
|
|
|
Expr(ObjCIvarRefExprClass, t, VK_LValue,
|
|
|
|
d->isBitField() ? OK_BitField : OK_Ordinary,
|
2011-02-20 13:06:31 +00:00
|
|
|
/*TypeDependent=*/false, base->isValueDependent(),
|
2011-07-17 15:40:56 +00:00
|
|
|
base->isInstantiationDependent(),
|
2011-02-20 13:06:31 +00:00
|
|
|
base->containsUnexpandedParameterPack()),
|
2013-04-08 18:45:10 +00:00
|
|
|
D(d), Base(base), Loc(l), OpLoc(oploc),
|
|
|
|
IsArrow(arrow), IsFreeIvar(freeIvar) {}
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
explicit ObjCIvarRefExpr(EmptyShell Empty)
|
|
|
|
: Expr(ObjCIvarRefExprClass, Empty) {}
|
|
|
|
|
|
|
|
ObjCIvarDecl *getDecl() { return D; }
|
|
|
|
const ObjCIvarDecl *getDecl() const { return D; }
|
|
|
|
void setDecl(ObjCIvarDecl *d) { D = d; }
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
const Expr *getBase() const { return cast<Expr>(Base); }
|
|
|
|
Expr *getBase() { return cast<Expr>(Base); }
|
|
|
|
void setBase(Expr * base) { Base = base; }
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
bool isArrow() const { return IsArrow; }
|
|
|
|
bool isFreeIvar() const { return IsFreeIvar; }
|
|
|
|
void setIsArrow(bool A) { IsArrow = A; }
|
|
|
|
void setIsFreeIvar(bool A) { IsFreeIvar = A; }
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
SourceLocation getLocation() const { return Loc; }
|
|
|
|
void setLocation(SourceLocation L) { Loc = L; }
|
|
|
|
|
2013-04-08 18:45:10 +00:00
|
|
|
SourceLocation getLocStart() const LLVM_READONLY {
|
|
|
|
return isFreeIvar() ? Loc : getBase()->getLocStart();
|
2009-06-02 17:58:47 +00:00
|
|
|
}
|
2013-04-08 18:45:10 +00:00
|
|
|
SourceLocation getLocEnd() const LLVM_READONLY { return Loc; }
|
|
|
|
|
|
|
|
SourceLocation getOpLoc() const { return OpLoc; }
|
|
|
|
void setOpLoc(SourceLocation L) { OpLoc = L; }
|
2009-10-14 18:03:49 +00:00
|
|
|
|
|
|
|
static bool classof(const Stmt *T) {
|
|
|
|
return T->getStmtClass() == ObjCIvarRefExprClass;
|
2009-06-02 17:58:47 +00:00
|
|
|
}
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
// Iterators
|
2011-02-20 13:06:31 +00:00
|
|
|
child_range children() { return child_range(&Base, &Base+1); }
|
2009-06-02 17:58:47 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/// ObjCPropertyRefExpr - A dot-syntax expression to access an ObjC
|
|
|
|
/// property.
|
|
|
|
class ObjCPropertyRefExpr : public Expr {
|
|
|
|
private:
|
2011-02-20 13:06:31 +00:00
|
|
|
/// If the bool is true, this is an implicit property reference; the
|
|
|
|
/// pointer is an (optional) ObjCMethodDecl and Setter may be set.
|
|
|
|
/// if the bool is false, this is an explicit property reference;
|
|
|
|
/// the pointer is an ObjCPropertyDecl and Setter is always null.
|
|
|
|
llvm::PointerIntPair<NamedDecl*, 1, bool> PropertyOrGetter;
|
2012-04-14 14:01:31 +00:00
|
|
|
|
|
|
|
/// \brief Indicates whether the property reference will result in a message
|
|
|
|
/// to the getter, the setter, or both.
|
|
|
|
/// This applies to both implicit and explicit property references.
|
|
|
|
enum MethodRefFlags {
|
|
|
|
MethodRef_None = 0,
|
|
|
|
MethodRef_Getter = 0x1,
|
|
|
|
MethodRef_Setter = 0x2
|
|
|
|
};
|
|
|
|
|
|
|
|
/// \brief Contains the Setter method pointer and MethodRefFlags bit flags.
|
|
|
|
llvm::PointerIntPair<ObjCMethodDecl *, 2, unsigned> SetterAndMethodRefFlags;
|
|
|
|
|
|
|
|
// FIXME: Maybe we should store the property identifier here,
|
|
|
|
// because it's not rederivable from the other data when there's an
|
|
|
|
// implicit property with no getter (because the 'foo' -> 'setFoo:'
|
|
|
|
// transformation is lossy on the first character).
|
2011-02-20 13:06:31 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
SourceLocation IdLoc;
|
2011-02-20 13:06:31 +00:00
|
|
|
|
|
|
|
/// \brief When the receiver in property access is 'super', this is
|
|
|
|
/// the location of the 'super' keyword. When it's an interface,
|
|
|
|
/// this is that interface.
|
|
|
|
SourceLocation ReceiverLoc;
|
|
|
|
llvm::PointerUnion3<Stmt*, const Type*, ObjCInterfaceDecl*> Receiver;
|
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
public:
|
2009-10-14 18:03:49 +00:00
|
|
|
ObjCPropertyRefExpr(ObjCPropertyDecl *PD, QualType t,
|
2011-02-20 13:06:31 +00:00
|
|
|
ExprValueKind VK, ExprObjectKind OK,
|
2009-06-02 17:58:47 +00:00
|
|
|
SourceLocation l, Expr *base)
|
2011-02-20 13:06:31 +00:00
|
|
|
: Expr(ObjCPropertyRefExprClass, t, VK, OK,
|
|
|
|
/*TypeDependent=*/false, base->isValueDependent(),
|
2011-07-17 15:40:56 +00:00
|
|
|
base->isInstantiationDependent(),
|
2011-02-20 13:06:31 +00:00
|
|
|
base->containsUnexpandedParameterPack()),
|
2012-04-14 14:01:31 +00:00
|
|
|
PropertyOrGetter(PD, false), SetterAndMethodRefFlags(),
|
2011-02-20 13:06:31 +00:00
|
|
|
IdLoc(l), ReceiverLoc(), Receiver(base) {
|
2012-04-14 14:01:31 +00:00
|
|
|
assert(t->isSpecificPlaceholderType(BuiltinType::PseudoObject));
|
2011-02-20 13:06:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ObjCPropertyRefExpr(ObjCPropertyDecl *PD, QualType t,
|
|
|
|
ExprValueKind VK, ExprObjectKind OK,
|
|
|
|
SourceLocation l, SourceLocation sl, QualType st)
|
|
|
|
: Expr(ObjCPropertyRefExprClass, t, VK, OK,
|
2011-07-17 15:40:56 +00:00
|
|
|
/*TypeDependent=*/false, false, st->isInstantiationDependentType(),
|
2011-02-20 13:06:31 +00:00
|
|
|
st->containsUnexpandedParameterPack()),
|
2012-04-14 14:01:31 +00:00
|
|
|
PropertyOrGetter(PD, false), SetterAndMethodRefFlags(),
|
2011-02-20 13:06:31 +00:00
|
|
|
IdLoc(l), ReceiverLoc(sl), Receiver(st.getTypePtr()) {
|
2012-04-14 14:01:31 +00:00
|
|
|
assert(t->isSpecificPlaceholderType(BuiltinType::PseudoObject));
|
2011-02-20 13:06:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ObjCPropertyRefExpr(ObjCMethodDecl *Getter, ObjCMethodDecl *Setter,
|
|
|
|
QualType T, ExprValueKind VK, ExprObjectKind OK,
|
|
|
|
SourceLocation IdLoc, Expr *Base)
|
|
|
|
: Expr(ObjCPropertyRefExprClass, T, VK, OK, false,
|
2011-07-17 15:40:56 +00:00
|
|
|
Base->isValueDependent(), Base->isInstantiationDependent(),
|
2011-02-20 13:06:31 +00:00
|
|
|
Base->containsUnexpandedParameterPack()),
|
2012-04-14 14:01:31 +00:00
|
|
|
PropertyOrGetter(Getter, true), SetterAndMethodRefFlags(Setter, 0),
|
2011-02-20 13:06:31 +00:00
|
|
|
IdLoc(IdLoc), ReceiverLoc(), Receiver(Base) {
|
2012-04-14 14:01:31 +00:00
|
|
|
assert(T->isSpecificPlaceholderType(BuiltinType::PseudoObject));
|
2011-02-20 13:06:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ObjCPropertyRefExpr(ObjCMethodDecl *Getter, ObjCMethodDecl *Setter,
|
|
|
|
QualType T, ExprValueKind VK, ExprObjectKind OK,
|
|
|
|
SourceLocation IdLoc,
|
|
|
|
SourceLocation SuperLoc, QualType SuperTy)
|
2011-07-17 15:40:56 +00:00
|
|
|
: Expr(ObjCPropertyRefExprClass, T, VK, OK, false, false, false, false),
|
2012-04-14 14:01:31 +00:00
|
|
|
PropertyOrGetter(Getter, true), SetterAndMethodRefFlags(Setter, 0),
|
2011-02-20 13:06:31 +00:00
|
|
|
IdLoc(IdLoc), ReceiverLoc(SuperLoc), Receiver(SuperTy.getTypePtr()) {
|
2012-04-14 14:01:31 +00:00
|
|
|
assert(T->isSpecificPlaceholderType(BuiltinType::PseudoObject));
|
2011-02-20 13:06:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ObjCPropertyRefExpr(ObjCMethodDecl *Getter, ObjCMethodDecl *Setter,
|
|
|
|
QualType T, ExprValueKind VK, ExprObjectKind OK,
|
|
|
|
SourceLocation IdLoc,
|
|
|
|
SourceLocation ReceiverLoc, ObjCInterfaceDecl *Receiver)
|
2011-07-17 15:40:56 +00:00
|
|
|
: Expr(ObjCPropertyRefExprClass, T, VK, OK, false, false, false, false),
|
2012-04-14 14:01:31 +00:00
|
|
|
PropertyOrGetter(Getter, true), SetterAndMethodRefFlags(Setter, 0),
|
2011-02-20 13:06:31 +00:00
|
|
|
IdLoc(IdLoc), ReceiverLoc(ReceiverLoc), Receiver(Receiver) {
|
2012-04-14 14:01:31 +00:00
|
|
|
assert(T->isSpecificPlaceholderType(BuiltinType::PseudoObject));
|
2009-06-02 17:58:47 +00:00
|
|
|
}
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
explicit ObjCPropertyRefExpr(EmptyShell Empty)
|
|
|
|
: Expr(ObjCPropertyRefExprClass, Empty) {}
|
|
|
|
|
2011-02-20 13:06:31 +00:00
|
|
|
bool isImplicitProperty() const { return PropertyOrGetter.getInt(); }
|
|
|
|
bool isExplicitProperty() const { return !PropertyOrGetter.getInt(); }
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2011-02-20 13:06:31 +00:00
|
|
|
ObjCPropertyDecl *getExplicitProperty() const {
|
|
|
|
assert(!isImplicitProperty());
|
|
|
|
return cast<ObjCPropertyDecl>(PropertyOrGetter.getPointer());
|
|
|
|
}
|
|
|
|
|
|
|
|
ObjCMethodDecl *getImplicitPropertyGetter() const {
|
|
|
|
assert(isImplicitProperty());
|
|
|
|
return cast_or_null<ObjCMethodDecl>(PropertyOrGetter.getPointer());
|
|
|
|
}
|
|
|
|
|
|
|
|
ObjCMethodDecl *getImplicitPropertySetter() const {
|
|
|
|
assert(isImplicitProperty());
|
2012-04-14 14:01:31 +00:00
|
|
|
return SetterAndMethodRefFlags.getPointer();
|
2011-02-20 13:06:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Selector getGetterSelector() const {
|
|
|
|
if (isImplicitProperty())
|
|
|
|
return getImplicitPropertyGetter()->getSelector();
|
|
|
|
return getExplicitProperty()->getGetterName();
|
|
|
|
}
|
|
|
|
|
|
|
|
Selector getSetterSelector() const {
|
|
|
|
if (isImplicitProperty())
|
|
|
|
return getImplicitPropertySetter()->getSelector();
|
|
|
|
return getExplicitProperty()->getSetterName();
|
|
|
|
}
|
|
|
|
|
2012-04-14 14:01:31 +00:00
|
|
|
/// \brief True if the property reference will result in a message to the
|
|
|
|
/// getter.
|
|
|
|
/// This applies to both implicit and explicit property references.
|
|
|
|
bool isMessagingGetter() const {
|
|
|
|
return SetterAndMethodRefFlags.getInt() & MethodRef_Getter;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// \brief True if the property reference will result in a message to the
|
|
|
|
/// setter.
|
|
|
|
/// This applies to both implicit and explicit property references.
|
|
|
|
bool isMessagingSetter() const {
|
|
|
|
return SetterAndMethodRefFlags.getInt() & MethodRef_Setter;
|
|
|
|
}
|
|
|
|
|
|
|
|
void setIsMessagingGetter(bool val = true) {
|
|
|
|
setMethodRefFlag(MethodRef_Getter, val);
|
|
|
|
}
|
|
|
|
|
|
|
|
void setIsMessagingSetter(bool val = true) {
|
|
|
|
setMethodRefFlag(MethodRef_Setter, val);
|
|
|
|
}
|
|
|
|
|
2011-02-20 13:06:31 +00:00
|
|
|
const Expr *getBase() const {
|
|
|
|
return cast<Expr>(Receiver.get<Stmt*>());
|
|
|
|
}
|
|
|
|
Expr *getBase() {
|
|
|
|
return cast<Expr>(Receiver.get<Stmt*>());
|
|
|
|
}
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
SourceLocation getLocation() const { return IdLoc; }
|
2011-02-20 13:06:31 +00:00
|
|
|
|
|
|
|
SourceLocation getReceiverLocation() const { return ReceiverLoc; }
|
|
|
|
QualType getSuperReceiverType() const {
|
|
|
|
return QualType(Receiver.get<const Type*>(), 0);
|
|
|
|
}
|
2015-08-07 23:02:44 +00:00
|
|
|
|
2011-02-20 13:06:31 +00:00
|
|
|
ObjCInterfaceDecl *getClassReceiver() const {
|
|
|
|
return Receiver.get<ObjCInterfaceDecl*>();
|
|
|
|
}
|
|
|
|
bool isObjectReceiver() const { return Receiver.is<Stmt*>(); }
|
|
|
|
bool isSuperReceiver() const { return Receiver.is<const Type*>(); }
|
|
|
|
bool isClassReceiver() const { return Receiver.is<ObjCInterfaceDecl*>(); }
|
2009-06-02 17:58:47 +00:00
|
|
|
|
2015-08-07 23:02:44 +00:00
|
|
|
/// Determine the type of the base, regardless of the kind of receiver.
|
|
|
|
QualType getReceiverType(const ASTContext &ctx) const;
|
|
|
|
|
2013-04-08 18:45:10 +00:00
|
|
|
SourceLocation getLocStart() const LLVM_READONLY {
|
|
|
|
return isObjectReceiver() ? getBase()->getLocStart() :getReceiverLocation();
|
2009-06-02 17:58:47 +00:00
|
|
|
}
|
2013-04-08 18:45:10 +00:00
|
|
|
SourceLocation getLocEnd() const LLVM_READONLY { return IdLoc; }
|
2009-10-14 18:03:49 +00:00
|
|
|
|
|
|
|
static bool classof(const Stmt *T) {
|
|
|
|
return T->getStmtClass() == ObjCPropertyRefExprClass;
|
2009-06-02 17:58:47 +00:00
|
|
|
}
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
// Iterators
|
2011-02-20 13:06:31 +00:00
|
|
|
child_range children() {
|
|
|
|
if (Receiver.is<Stmt*>()) {
|
|
|
|
Stmt **begin = reinterpret_cast<Stmt**>(&Receiver); // hack!
|
|
|
|
return child_range(begin, begin+1);
|
2009-06-02 17:58:47 +00:00
|
|
|
}
|
2011-02-20 13:06:31 +00:00
|
|
|
return child_range();
|
|
|
|
}
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2011-02-20 13:06:31 +00:00
|
|
|
private:
|
|
|
|
friend class ASTStmtReader;
|
2012-04-14 14:01:31 +00:00
|
|
|
friend class ASTStmtWriter;
|
|
|
|
void setExplicitProperty(ObjCPropertyDecl *D, unsigned methRefFlags) {
|
2011-02-20 13:06:31 +00:00
|
|
|
PropertyOrGetter.setPointer(D);
|
|
|
|
PropertyOrGetter.setInt(false);
|
2014-11-24 09:15:30 +00:00
|
|
|
SetterAndMethodRefFlags.setPointer(nullptr);
|
2012-04-14 14:01:31 +00:00
|
|
|
SetterAndMethodRefFlags.setInt(methRefFlags);
|
2011-02-20 13:06:31 +00:00
|
|
|
}
|
2012-04-14 14:01:31 +00:00
|
|
|
void setImplicitProperty(ObjCMethodDecl *Getter, ObjCMethodDecl *Setter,
|
|
|
|
unsigned methRefFlags) {
|
2011-02-20 13:06:31 +00:00
|
|
|
PropertyOrGetter.setPointer(Getter);
|
|
|
|
PropertyOrGetter.setInt(true);
|
2012-04-14 14:01:31 +00:00
|
|
|
SetterAndMethodRefFlags.setPointer(Setter);
|
|
|
|
SetterAndMethodRefFlags.setInt(methRefFlags);
|
2009-06-02 17:58:47 +00:00
|
|
|
}
|
2011-02-20 13:06:31 +00:00
|
|
|
void setBase(Expr *Base) { Receiver = Base; }
|
|
|
|
void setSuperReceiver(QualType T) { Receiver = T.getTypePtr(); }
|
|
|
|
void setClassReceiver(ObjCInterfaceDecl *D) { Receiver = D; }
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2011-02-20 13:06:31 +00:00
|
|
|
void setLocation(SourceLocation L) { IdLoc = L; }
|
|
|
|
void setReceiverLocation(SourceLocation Loc) { ReceiverLoc = Loc; }
|
2012-04-14 14:01:31 +00:00
|
|
|
|
|
|
|
void setMethodRefFlag(MethodRefFlags flag, bool val) {
|
|
|
|
unsigned f = SetterAndMethodRefFlags.getInt();
|
|
|
|
if (val)
|
|
|
|
f |= flag;
|
|
|
|
else
|
|
|
|
f &= ~flag;
|
|
|
|
SetterAndMethodRefFlags.setInt(f);
|
|
|
|
}
|
2009-06-02 17:58:47 +00:00
|
|
|
};
|
2012-04-14 14:01:31 +00:00
|
|
|
|
|
|
|
/// ObjCSubscriptRefExpr - used for array and dictionary subscripting.
|
|
|
|
/// array[4] = array[3]; dictionary[key] = dictionary[alt_key];
|
|
|
|
///
|
|
|
|
class ObjCSubscriptRefExpr : public Expr {
|
|
|
|
// Location of ']' in an indexing expression.
|
|
|
|
SourceLocation RBracket;
|
|
|
|
// array/dictionary base expression.
|
|
|
|
// for arrays, this is a numeric expression. For dictionaries, this is
|
|
|
|
// an objective-c object pointer expression.
|
|
|
|
enum { BASE, KEY, END_EXPR };
|
|
|
|
Stmt* SubExprs[END_EXPR];
|
|
|
|
|
|
|
|
ObjCMethodDecl *GetAtIndexMethodDecl;
|
|
|
|
|
|
|
|
// For immutable objects this is null. When ObjCSubscriptRefExpr is to read
|
|
|
|
// an indexed object this is null too.
|
|
|
|
ObjCMethodDecl *SetAtIndexMethodDecl;
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
ObjCSubscriptRefExpr(Expr *base, Expr *key, QualType T,
|
|
|
|
ExprValueKind VK, ExprObjectKind OK,
|
|
|
|
ObjCMethodDecl *getMethod,
|
|
|
|
ObjCMethodDecl *setMethod, SourceLocation RB)
|
|
|
|
: Expr(ObjCSubscriptRefExprClass, T, VK, OK,
|
|
|
|
base->isTypeDependent() || key->isTypeDependent(),
|
|
|
|
base->isValueDependent() || key->isValueDependent(),
|
|
|
|
base->isInstantiationDependent() || key->isInstantiationDependent(),
|
|
|
|
(base->containsUnexpandedParameterPack() ||
|
|
|
|
key->containsUnexpandedParameterPack())),
|
|
|
|
RBracket(RB),
|
|
|
|
GetAtIndexMethodDecl(getMethod),
|
|
|
|
SetAtIndexMethodDecl(setMethod)
|
|
|
|
{SubExprs[BASE] = base; SubExprs[KEY] = key;}
|
|
|
|
|
|
|
|
explicit ObjCSubscriptRefExpr(EmptyShell Empty)
|
|
|
|
: Expr(ObjCSubscriptRefExprClass, Empty) {}
|
|
|
|
|
2013-12-22 00:07:40 +00:00
|
|
|
static ObjCSubscriptRefExpr *Create(const ASTContext &C,
|
2012-04-14 14:01:31 +00:00
|
|
|
Expr *base,
|
|
|
|
Expr *key, QualType T,
|
|
|
|
ObjCMethodDecl *getMethod,
|
|
|
|
ObjCMethodDecl *setMethod,
|
|
|
|
SourceLocation RB);
|
|
|
|
|
|
|
|
SourceLocation getRBracket() const { return RBracket; }
|
|
|
|
void setRBracket(SourceLocation RB) { RBracket = RB; }
|
2013-04-08 18:45:10 +00:00
|
|
|
|
|
|
|
SourceLocation getLocStart() const LLVM_READONLY {
|
|
|
|
return SubExprs[BASE]->getLocStart();
|
2012-04-14 14:01:31 +00:00
|
|
|
}
|
2013-04-08 18:45:10 +00:00
|
|
|
SourceLocation getLocEnd() const LLVM_READONLY { return RBracket; }
|
|
|
|
|
2012-04-14 14:01:31 +00:00
|
|
|
static bool classof(const Stmt *T) {
|
|
|
|
return T->getStmtClass() == ObjCSubscriptRefExprClass;
|
|
|
|
}
|
|
|
|
|
|
|
|
Expr *getBaseExpr() const { return cast<Expr>(SubExprs[BASE]); }
|
|
|
|
void setBaseExpr(Stmt *S) { SubExprs[BASE] = S; }
|
|
|
|
|
|
|
|
Expr *getKeyExpr() const { return cast<Expr>(SubExprs[KEY]); }
|
|
|
|
void setKeyExpr(Stmt *S) { SubExprs[KEY] = S; }
|
|
|
|
|
|
|
|
ObjCMethodDecl *getAtIndexMethodDecl() const {
|
|
|
|
return GetAtIndexMethodDecl;
|
|
|
|
}
|
|
|
|
|
|
|
|
ObjCMethodDecl *setAtIndexMethodDecl() const {
|
|
|
|
return SetAtIndexMethodDecl;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool isArraySubscriptRefExpr() const {
|
|
|
|
return getKeyExpr()->getType()->isIntegralOrEnumerationType();
|
|
|
|
}
|
|
|
|
|
|
|
|
child_range children() {
|
|
|
|
return child_range(SubExprs, SubExprs+END_EXPR);
|
|
|
|
}
|
|
|
|
private:
|
|
|
|
friend class ASTStmtReader;
|
|
|
|
};
|
|
|
|
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2010-05-04 16:12:48 +00:00
|
|
|
/// \brief An expression that sends a message to the given Objective-C
|
|
|
|
/// object or class.
|
|
|
|
///
|
|
|
|
/// The following contains two message send expressions:
|
|
|
|
///
|
|
|
|
/// \code
|
|
|
|
/// [[NSString alloc] initWithString:@"Hello"]
|
|
|
|
/// \endcode
|
|
|
|
///
|
|
|
|
/// The innermost message send invokes the "alloc" class method on the
|
|
|
|
/// NSString class, while the outermost message send invokes the
|
|
|
|
/// "initWithString" instance method on the object returned from
|
|
|
|
/// NSString's "alloc". In all, an Objective-C message send can take
|
|
|
|
/// on four different (although related) forms:
|
|
|
|
///
|
|
|
|
/// 1. Send to an object instance.
|
|
|
|
/// 2. Send to a class.
|
|
|
|
/// 3. Send to the superclass instance of the current class.
|
|
|
|
/// 4. Send to the superclass of the current class.
|
|
|
|
///
|
|
|
|
/// All four kinds of message sends are modeled by the ObjCMessageExpr
|
|
|
|
/// class, and can be distinguished via \c getReceiverKind(). Example:
|
|
|
|
///
|
2009-06-02 17:58:47 +00:00
|
|
|
class ObjCMessageExpr : public Expr {
|
2011-10-20 21:14:49 +00:00
|
|
|
/// \brief Stores either the selector that this message is sending
|
|
|
|
/// to (when \c HasMethod is zero) or an \c ObjCMethodDecl pointer
|
|
|
|
/// referring to the method that we type-checked against.
|
|
|
|
uintptr_t SelectorOrMethod;
|
|
|
|
|
|
|
|
enum { NumArgsBitWidth = 16 };
|
|
|
|
|
2010-05-04 16:12:48 +00:00
|
|
|
/// \brief The number of arguments in the message send, not
|
|
|
|
/// including the receiver.
|
2011-10-20 21:14:49 +00:00
|
|
|
unsigned NumArgs : NumArgsBitWidth;
|
|
|
|
|
|
|
|
void setNumArgs(unsigned Num) {
|
|
|
|
assert((Num >> NumArgsBitWidth) == 0 && "Num of args is out of range!");
|
|
|
|
NumArgs = Num;
|
|
|
|
}
|
2010-05-04 16:12:48 +00:00
|
|
|
|
|
|
|
/// \brief The kind of message send this is, which is one of the
|
|
|
|
/// ReceiverKind values.
|
|
|
|
///
|
|
|
|
/// We pad this out to a byte to avoid excessive masking and shifting.
|
|
|
|
unsigned Kind : 8;
|
|
|
|
|
|
|
|
/// \brief Whether we have an actual method prototype in \c
|
|
|
|
/// SelectorOrMethod.
|
|
|
|
///
|
|
|
|
/// When non-zero, we have a method declaration; otherwise, we just
|
|
|
|
/// have a selector.
|
2011-07-17 15:40:56 +00:00
|
|
|
unsigned HasMethod : 1;
|
|
|
|
|
|
|
|
/// \brief Whether this message send is a "delegate init call",
|
|
|
|
/// i.e. a call of an init method on self from within an init method.
|
|
|
|
unsigned IsDelegateInitCall : 1;
|
2012-04-14 14:01:31 +00:00
|
|
|
|
|
|
|
/// \brief Whether this message send was implicitly generated by
|
|
|
|
/// the implementation rather than explicitly written by the user.
|
|
|
|
unsigned IsImplicit : 1;
|
|
|
|
|
2011-10-20 21:14:49 +00:00
|
|
|
/// \brief Whether the locations of the selector identifiers are in a
|
|
|
|
/// "standard" position, a enum SelectorLocationsKind.
|
|
|
|
unsigned SelLocsKind : 2;
|
2010-05-04 16:12:48 +00:00
|
|
|
|
|
|
|
/// \brief When the message expression is a send to 'super', this is
|
|
|
|
/// the location of the 'super' keyword.
|
|
|
|
SourceLocation SuperLoc;
|
|
|
|
|
|
|
|
/// \brief The source locations of the open and close square
|
|
|
|
/// brackets ('[' and ']', respectively).
|
|
|
|
SourceLocation LBracLoc, RBracLoc;
|
|
|
|
|
|
|
|
ObjCMessageExpr(EmptyShell Empty, unsigned NumArgs)
|
2011-10-20 21:14:49 +00:00
|
|
|
: Expr(ObjCMessageExprClass, Empty), SelectorOrMethod(0), Kind(0),
|
2012-04-14 14:01:31 +00:00
|
|
|
HasMethod(0), IsDelegateInitCall(0), IsImplicit(0), SelLocsKind(0) {
|
2011-10-20 21:14:49 +00:00
|
|
|
setNumArgs(NumArgs);
|
|
|
|
}
|
2010-05-04 16:12:48 +00:00
|
|
|
|
2011-02-20 13:06:31 +00:00
|
|
|
ObjCMessageExpr(QualType T, ExprValueKind VK,
|
2010-05-04 16:12:48 +00:00
|
|
|
SourceLocation LBracLoc,
|
|
|
|
SourceLocation SuperLoc,
|
|
|
|
bool IsInstanceSuper,
|
|
|
|
QualType SuperType,
|
|
|
|
Selector Sel,
|
2011-10-20 21:14:49 +00:00
|
|
|
ArrayRef<SourceLocation> SelLocs,
|
|
|
|
SelectorLocationsKind SelLocsK,
|
2010-05-04 16:12:48 +00:00
|
|
|
ObjCMethodDecl *Method,
|
2011-10-20 21:14:49 +00:00
|
|
|
ArrayRef<Expr *> Args,
|
2012-04-14 14:01:31 +00:00
|
|
|
SourceLocation RBracLoc,
|
|
|
|
bool isImplicit);
|
2011-02-20 13:06:31 +00:00
|
|
|
ObjCMessageExpr(QualType T, ExprValueKind VK,
|
2010-05-04 16:12:48 +00:00
|
|
|
SourceLocation LBracLoc,
|
|
|
|
TypeSourceInfo *Receiver,
|
|
|
|
Selector Sel,
|
2011-10-20 21:14:49 +00:00
|
|
|
ArrayRef<SourceLocation> SelLocs,
|
|
|
|
SelectorLocationsKind SelLocsK,
|
2010-05-04 16:12:48 +00:00
|
|
|
ObjCMethodDecl *Method,
|
2011-10-20 21:14:49 +00:00
|
|
|
ArrayRef<Expr *> Args,
|
2012-04-14 14:01:31 +00:00
|
|
|
SourceLocation RBracLoc,
|
|
|
|
bool isImplicit);
|
2011-02-20 13:06:31 +00:00
|
|
|
ObjCMessageExpr(QualType T, ExprValueKind VK,
|
2010-05-04 16:12:48 +00:00
|
|
|
SourceLocation LBracLoc,
|
|
|
|
Expr *Receiver,
|
|
|
|
Selector Sel,
|
2011-10-20 21:14:49 +00:00
|
|
|
ArrayRef<SourceLocation> SelLocs,
|
|
|
|
SelectorLocationsKind SelLocsK,
|
2010-05-04 16:12:48 +00:00
|
|
|
ObjCMethodDecl *Method,
|
2011-10-20 21:14:49 +00:00
|
|
|
ArrayRef<Expr *> Args,
|
2012-04-14 14:01:31 +00:00
|
|
|
SourceLocation RBracLoc,
|
|
|
|
bool isImplicit);
|
2010-05-04 16:12:48 +00:00
|
|
|
|
2011-10-20 21:14:49 +00:00
|
|
|
void initArgsAndSelLocs(ArrayRef<Expr *> Args,
|
|
|
|
ArrayRef<SourceLocation> SelLocs,
|
|
|
|
SelectorLocationsKind SelLocsK);
|
|
|
|
|
2010-05-04 16:12:48 +00:00
|
|
|
/// \brief Retrieve the pointer value of the message receiver.
|
|
|
|
void *getReceiverPointer() const {
|
|
|
|
return *const_cast<void **>(
|
|
|
|
reinterpret_cast<const void * const*>(this + 1));
|
|
|
|
}
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2010-05-04 16:12:48 +00:00
|
|
|
/// \brief Set the pointer value of the message receiver.
|
|
|
|
void setReceiverPointer(void *Value) {
|
|
|
|
*reinterpret_cast<void **>(this + 1) = Value;
|
|
|
|
}
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2011-10-20 21:14:49 +00:00
|
|
|
SelectorLocationsKind getSelLocsKind() const {
|
|
|
|
return (SelectorLocationsKind)SelLocsKind;
|
|
|
|
}
|
|
|
|
bool hasStandardSelLocs() const {
|
|
|
|
return getSelLocsKind() != SelLoc_NonStandard;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// \brief Get a pointer to the stored selector identifiers locations array.
|
|
|
|
/// No locations will be stored if HasStandardSelLocs is true.
|
|
|
|
SourceLocation *getStoredSelLocs() {
|
|
|
|
return reinterpret_cast<SourceLocation*>(getArgs() + getNumArgs());
|
|
|
|
}
|
|
|
|
const SourceLocation *getStoredSelLocs() const {
|
|
|
|
return reinterpret_cast<const SourceLocation*>(getArgs() + getNumArgs());
|
|
|
|
}
|
|
|
|
|
|
|
|
/// \brief Get the number of stored selector identifiers locations.
|
|
|
|
/// No locations will be stored if HasStandardSelLocs is true.
|
|
|
|
unsigned getNumStoredSelLocs() const {
|
|
|
|
if (hasStandardSelLocs())
|
|
|
|
return 0;
|
|
|
|
return getNumSelectorLocs();
|
|
|
|
}
|
|
|
|
|
2013-12-22 00:07:40 +00:00
|
|
|
static ObjCMessageExpr *alloc(const ASTContext &C,
|
2011-10-20 21:14:49 +00:00
|
|
|
ArrayRef<Expr *> Args,
|
|
|
|
SourceLocation RBraceLoc,
|
|
|
|
ArrayRef<SourceLocation> SelLocs,
|
|
|
|
Selector Sel,
|
|
|
|
SelectorLocationsKind &SelLocsK);
|
2013-12-22 00:07:40 +00:00
|
|
|
static ObjCMessageExpr *alloc(const ASTContext &C,
|
2011-10-20 21:14:49 +00:00
|
|
|
unsigned NumArgs,
|
|
|
|
unsigned NumStoredSelLocs);
|
|
|
|
|
2010-05-04 16:12:48 +00:00
|
|
|
public:
|
|
|
|
/// \brief The kind of receiver this message is sending to.
|
|
|
|
enum ReceiverKind {
|
|
|
|
/// \brief The receiver is a class.
|
|
|
|
Class = 0,
|
|
|
|
/// \brief The receiver is an object instance.
|
|
|
|
Instance,
|
|
|
|
/// \brief The receiver is a superclass.
|
|
|
|
SuperClass,
|
|
|
|
/// \brief The receiver is the instance of the superclass object.
|
|
|
|
SuperInstance
|
|
|
|
};
|
2010-03-10 17:45:58 +00:00
|
|
|
|
2010-05-04 16:12:48 +00:00
|
|
|
/// \brief Create a message send to super.
|
|
|
|
///
|
|
|
|
/// \param Context The ASTContext in which this expression will be created.
|
|
|
|
///
|
|
|
|
/// \param T The result type of this message.
|
|
|
|
///
|
2011-02-20 13:06:31 +00:00
|
|
|
/// \param VK The value kind of this message. A message returning
|
|
|
|
/// a l-value or r-value reference will be an l-value or x-value,
|
|
|
|
/// respectively.
|
|
|
|
///
|
2012-08-15 20:02:54 +00:00
|
|
|
/// \param LBracLoc The location of the open square bracket '['.
|
2010-05-04 16:12:48 +00:00
|
|
|
///
|
|
|
|
/// \param SuperLoc The location of the "super" keyword.
|
|
|
|
///
|
|
|
|
/// \param IsInstanceSuper Whether this is an instance "super"
|
|
|
|
/// message (otherwise, it's a class "super" message).
|
|
|
|
///
|
|
|
|
/// \param Sel The selector used to determine which method gets called.
|
|
|
|
///
|
|
|
|
/// \param Method The Objective-C method against which this message
|
|
|
|
/// send was type-checked. May be NULL.
|
|
|
|
///
|
|
|
|
/// \param Args The message send arguments.
|
|
|
|
///
|
|
|
|
/// \param RBracLoc The location of the closing square bracket ']'.
|
2013-12-22 00:07:40 +00:00
|
|
|
static ObjCMessageExpr *Create(const ASTContext &Context, QualType T,
|
2011-02-20 13:06:31 +00:00
|
|
|
ExprValueKind VK,
|
2010-05-04 16:12:48 +00:00
|
|
|
SourceLocation LBracLoc,
|
|
|
|
SourceLocation SuperLoc,
|
|
|
|
bool IsInstanceSuper,
|
|
|
|
QualType SuperType,
|
|
|
|
Selector Sel,
|
2011-10-20 21:14:49 +00:00
|
|
|
ArrayRef<SourceLocation> SelLocs,
|
2010-05-04 16:12:48 +00:00
|
|
|
ObjCMethodDecl *Method,
|
2011-10-20 21:14:49 +00:00
|
|
|
ArrayRef<Expr *> Args,
|
2012-04-14 14:01:31 +00:00
|
|
|
SourceLocation RBracLoc,
|
|
|
|
bool isImplicit);
|
2010-05-04 16:12:48 +00:00
|
|
|
|
|
|
|
/// \brief Create a class message send.
|
|
|
|
///
|
|
|
|
/// \param Context The ASTContext in which this expression will be created.
|
|
|
|
///
|
|
|
|
/// \param T The result type of this message.
|
|
|
|
///
|
2011-02-20 13:06:31 +00:00
|
|
|
/// \param VK The value kind of this message. A message returning
|
|
|
|
/// a l-value or r-value reference will be an l-value or x-value,
|
|
|
|
/// respectively.
|
|
|
|
///
|
2012-08-15 20:02:54 +00:00
|
|
|
/// \param LBracLoc The location of the open square bracket '['.
|
2010-05-04 16:12:48 +00:00
|
|
|
///
|
|
|
|
/// \param Receiver The type of the receiver, including
|
|
|
|
/// source-location information.
|
|
|
|
///
|
|
|
|
/// \param Sel The selector used to determine which method gets called.
|
|
|
|
///
|
|
|
|
/// \param Method The Objective-C method against which this message
|
|
|
|
/// send was type-checked. May be NULL.
|
|
|
|
///
|
|
|
|
/// \param Args The message send arguments.
|
|
|
|
///
|
|
|
|
/// \param RBracLoc The location of the closing square bracket ']'.
|
2013-12-22 00:07:40 +00:00
|
|
|
static ObjCMessageExpr *Create(const ASTContext &Context, QualType T,
|
2011-02-20 13:06:31 +00:00
|
|
|
ExprValueKind VK,
|
2010-05-04 16:12:48 +00:00
|
|
|
SourceLocation LBracLoc,
|
|
|
|
TypeSourceInfo *Receiver,
|
|
|
|
Selector Sel,
|
2011-10-20 21:14:49 +00:00
|
|
|
ArrayRef<SourceLocation> SelLocs,
|
2010-05-04 16:12:48 +00:00
|
|
|
ObjCMethodDecl *Method,
|
2011-10-20 21:14:49 +00:00
|
|
|
ArrayRef<Expr *> Args,
|
2012-04-14 14:01:31 +00:00
|
|
|
SourceLocation RBracLoc,
|
|
|
|
bool isImplicit);
|
2010-05-04 16:12:48 +00:00
|
|
|
|
|
|
|
/// \brief Create an instance message send.
|
|
|
|
///
|
|
|
|
/// \param Context The ASTContext in which this expression will be created.
|
|
|
|
///
|
|
|
|
/// \param T The result type of this message.
|
|
|
|
///
|
2011-02-20 13:06:31 +00:00
|
|
|
/// \param VK The value kind of this message. A message returning
|
|
|
|
/// a l-value or r-value reference will be an l-value or x-value,
|
|
|
|
/// respectively.
|
|
|
|
///
|
2012-08-15 20:02:54 +00:00
|
|
|
/// \param LBracLoc The location of the open square bracket '['.
|
2010-05-04 16:12:48 +00:00
|
|
|
///
|
|
|
|
/// \param Receiver The expression used to produce the object that
|
|
|
|
/// will receive this message.
|
|
|
|
///
|
|
|
|
/// \param Sel The selector used to determine which method gets called.
|
|
|
|
///
|
|
|
|
/// \param Method The Objective-C method against which this message
|
|
|
|
/// send was type-checked. May be NULL.
|
|
|
|
///
|
|
|
|
/// \param Args The message send arguments.
|
|
|
|
///
|
|
|
|
/// \param RBracLoc The location of the closing square bracket ']'.
|
2013-12-22 00:07:40 +00:00
|
|
|
static ObjCMessageExpr *Create(const ASTContext &Context, QualType T,
|
2011-02-20 13:06:31 +00:00
|
|
|
ExprValueKind VK,
|
2010-05-04 16:12:48 +00:00
|
|
|
SourceLocation LBracLoc,
|
|
|
|
Expr *Receiver,
|
|
|
|
Selector Sel,
|
2011-10-20 21:14:49 +00:00
|
|
|
ArrayRef<SourceLocation> SeLocs,
|
2010-05-04 16:12:48 +00:00
|
|
|
ObjCMethodDecl *Method,
|
2011-10-20 21:14:49 +00:00
|
|
|
ArrayRef<Expr *> Args,
|
2012-04-14 14:01:31 +00:00
|
|
|
SourceLocation RBracLoc,
|
|
|
|
bool isImplicit);
|
2010-05-04 16:12:48 +00:00
|
|
|
|
|
|
|
/// \brief Create an empty Objective-C message expression, to be
|
|
|
|
/// filled in by subsequent calls.
|
|
|
|
///
|
|
|
|
/// \param Context The context in which the message send will be created.
|
|
|
|
///
|
|
|
|
/// \param NumArgs The number of message arguments, not including
|
|
|
|
/// the receiver.
|
2013-12-22 00:07:40 +00:00
|
|
|
static ObjCMessageExpr *CreateEmpty(const ASTContext &Context,
|
2011-10-20 21:14:49 +00:00
|
|
|
unsigned NumArgs,
|
|
|
|
unsigned NumStoredSelLocs);
|
2010-05-04 16:12:48 +00:00
|
|
|
|
2012-04-14 14:01:31 +00:00
|
|
|
/// \brief Indicates whether the message send was implicitly
|
|
|
|
/// generated by the implementation. If false, it was written explicitly
|
|
|
|
/// in the source code.
|
|
|
|
bool isImplicit() const { return IsImplicit; }
|
|
|
|
|
2010-05-04 16:12:48 +00:00
|
|
|
/// \brief Determine the kind of receiver that this message is being
|
|
|
|
/// sent to.
|
|
|
|
ReceiverKind getReceiverKind() const { return (ReceiverKind)Kind; }
|
|
|
|
|
2011-02-20 13:06:31 +00:00
|
|
|
/// \brief Source range of the receiver.
|
|
|
|
SourceRange getReceiverRange() const;
|
|
|
|
|
2010-05-04 16:12:48 +00:00
|
|
|
/// \brief Determine whether this is an instance message to either a
|
|
|
|
/// computed object or to super.
|
|
|
|
bool isInstanceMessage() const {
|
|
|
|
return getReceiverKind() == Instance || getReceiverKind() == SuperInstance;
|
|
|
|
}
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2010-05-04 16:12:48 +00:00
|
|
|
/// \brief Determine whether this is an class message to either a
|
|
|
|
/// specified class or to super.
|
|
|
|
bool isClassMessage() const {
|
|
|
|
return getReceiverKind() == Class || getReceiverKind() == SuperClass;
|
|
|
|
}
|
2009-06-02 17:58:47 +00:00
|
|
|
|
2012-12-02 13:20:44 +00:00
|
|
|
/// \brief Returns the object expression (receiver) for an instance message,
|
|
|
|
/// or null for a message that is not an instance message.
|
2010-05-04 16:12:48 +00:00
|
|
|
Expr *getInstanceReceiver() {
|
|
|
|
if (getReceiverKind() == Instance)
|
|
|
|
return static_cast<Expr *>(getReceiverPointer());
|
2009-06-02 17:58:47 +00:00
|
|
|
|
2014-11-24 09:15:30 +00:00
|
|
|
return nullptr;
|
2010-05-04 16:12:48 +00:00
|
|
|
}
|
|
|
|
const Expr *getInstanceReceiver() const {
|
|
|
|
return const_cast<ObjCMessageExpr*>(this)->getInstanceReceiver();
|
|
|
|
}
|
2009-06-02 17:58:47 +00:00
|
|
|
|
2010-05-04 16:12:48 +00:00
|
|
|
/// \brief Turn this message send into an instance message that
|
|
|
|
/// computes the receiver object with the given expression.
|
|
|
|
void setInstanceReceiver(Expr *rec) {
|
|
|
|
Kind = Instance;
|
|
|
|
setReceiverPointer(rec);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// \brief Returns the type of a class message send, or NULL if the
|
|
|
|
/// message is not a class message.
|
|
|
|
QualType getClassReceiver() const {
|
|
|
|
if (TypeSourceInfo *TSInfo = getClassReceiverTypeInfo())
|
|
|
|
return TSInfo->getType();
|
|
|
|
|
|
|
|
return QualType();
|
|
|
|
}
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2010-05-04 16:12:48 +00:00
|
|
|
/// \brief Returns a type-source information of a class message
|
|
|
|
/// send, or NULL if the message is not a class message.
|
|
|
|
TypeSourceInfo *getClassReceiverTypeInfo() const {
|
|
|
|
if (getReceiverKind() == Class)
|
|
|
|
return reinterpret_cast<TypeSourceInfo *>(getReceiverPointer());
|
2014-11-24 09:15:30 +00:00
|
|
|
return nullptr;
|
2010-05-04 16:12:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void setClassReceiver(TypeSourceInfo *TSInfo) {
|
|
|
|
Kind = Class;
|
|
|
|
setReceiverPointer(TSInfo);
|
|
|
|
}
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2010-05-04 16:12:48 +00:00
|
|
|
/// \brief Retrieve the location of the 'super' keyword for a class
|
|
|
|
/// or instance message to 'super', otherwise an invalid source location.
|
|
|
|
SourceLocation getSuperLoc() const {
|
|
|
|
if (getReceiverKind() == SuperInstance || getReceiverKind() == SuperClass)
|
|
|
|
return SuperLoc;
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2010-05-04 16:12:48 +00:00
|
|
|
return SourceLocation();
|
|
|
|
}
|
2010-03-10 17:45:58 +00:00
|
|
|
|
2012-12-02 13:20:44 +00:00
|
|
|
/// \brief Retrieve the receiver type to which this message is being directed.
|
|
|
|
///
|
|
|
|
/// This routine cross-cuts all of the different kinds of message
|
|
|
|
/// sends to determine what the underlying (statically known) type
|
|
|
|
/// of the receiver will be; use \c getReceiverKind() to determine
|
|
|
|
/// whether the message is a class or an instance method, whether it
|
|
|
|
/// is a send to super or not, etc.
|
|
|
|
///
|
|
|
|
/// \returns The type of the receiver.
|
|
|
|
QualType getReceiverType() const;
|
|
|
|
|
2010-05-04 16:12:48 +00:00
|
|
|
/// \brief Retrieve the Objective-C interface to which this message
|
|
|
|
/// is being directed, if known.
|
|
|
|
///
|
|
|
|
/// This routine cross-cuts all of the different kinds of message
|
|
|
|
/// sends to determine what the underlying (statically known) type
|
|
|
|
/// of the receiver will be; use \c getReceiverKind() to determine
|
|
|
|
/// whether the message is a class or an instance method, whether it
|
|
|
|
/// is a send to super or not, etc.
|
|
|
|
///
|
|
|
|
/// \returns The Objective-C interface if known, otherwise NULL.
|
|
|
|
ObjCInterfaceDecl *getReceiverInterface() const;
|
|
|
|
|
|
|
|
/// \brief Retrieve the type referred to by 'super'.
|
|
|
|
///
|
|
|
|
/// The returned type will either be an ObjCInterfaceType (for an
|
|
|
|
/// class message to super) or an ObjCObjectPointerType that refers
|
|
|
|
/// to a class (for an instance message to super);
|
|
|
|
QualType getSuperType() const {
|
|
|
|
if (getReceiverKind() == SuperInstance || getReceiverKind() == SuperClass)
|
|
|
|
return QualType::getFromOpaquePtr(getReceiverPointer());
|
|
|
|
|
|
|
|
return QualType();
|
|
|
|
}
|
2010-03-10 17:45:58 +00:00
|
|
|
|
2010-05-04 16:12:48 +00:00
|
|
|
void setSuper(SourceLocation Loc, QualType T, bool IsInstanceSuper) {
|
|
|
|
Kind = IsInstanceSuper? SuperInstance : SuperClass;
|
|
|
|
SuperLoc = Loc;
|
|
|
|
setReceiverPointer(T.getAsOpaquePtr());
|
|
|
|
}
|
2010-03-10 17:45:58 +00:00
|
|
|
|
2010-05-04 16:12:48 +00:00
|
|
|
Selector getSelector() const;
|
2010-03-10 17:45:58 +00:00
|
|
|
|
2010-05-04 16:12:48 +00:00
|
|
|
void setSelector(Selector S) {
|
|
|
|
HasMethod = false;
|
|
|
|
SelectorOrMethod = reinterpret_cast<uintptr_t>(S.getAsOpaquePtr());
|
|
|
|
}
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2010-05-04 16:12:48 +00:00
|
|
|
const ObjCMethodDecl *getMethodDecl() const {
|
|
|
|
if (HasMethod)
|
|
|
|
return reinterpret_cast<const ObjCMethodDecl *>(SelectorOrMethod);
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2014-11-24 09:15:30 +00:00
|
|
|
return nullptr;
|
2009-06-02 17:58:47 +00:00
|
|
|
}
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2010-05-04 16:12:48 +00:00
|
|
|
ObjCMethodDecl *getMethodDecl() {
|
|
|
|
if (HasMethod)
|
|
|
|
return reinterpret_cast<ObjCMethodDecl *>(SelectorOrMethod);
|
|
|
|
|
2014-11-24 09:15:30 +00:00
|
|
|
return nullptr;
|
2010-05-04 16:12:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void setMethodDecl(ObjCMethodDecl *MD) {
|
|
|
|
HasMethod = true;
|
|
|
|
SelectorOrMethod = reinterpret_cast<uintptr_t>(MD);
|
|
|
|
}
|
|
|
|
|
2011-05-02 19:39:53 +00:00
|
|
|
ObjCMethodFamily getMethodFamily() const {
|
|
|
|
if (HasMethod) return getMethodDecl()->getMethodFamily();
|
|
|
|
return getSelector().getMethodFamily();
|
|
|
|
}
|
|
|
|
|
2010-05-04 16:12:48 +00:00
|
|
|
/// \brief Return the number of actual arguments in this message,
|
|
|
|
/// not counting the receiver.
|
2009-06-02 17:58:47 +00:00
|
|
|
unsigned getNumArgs() const { return NumArgs; }
|
2010-05-04 16:12:48 +00:00
|
|
|
|
|
|
|
/// \brief Retrieve the arguments to this message, not including the
|
|
|
|
/// receiver.
|
2011-02-20 13:06:31 +00:00
|
|
|
Expr **getArgs() {
|
|
|
|
return reinterpret_cast<Expr **>(this + 1) + 1;
|
2010-05-04 16:12:48 +00:00
|
|
|
}
|
2011-02-20 13:06:31 +00:00
|
|
|
const Expr * const *getArgs() const {
|
|
|
|
return reinterpret_cast<const Expr * const *>(this + 1) + 1;
|
2009-06-02 17:58:47 +00:00
|
|
|
}
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
/// getArg - Return the specified argument.
|
|
|
|
Expr *getArg(unsigned Arg) {
|
|
|
|
assert(Arg < NumArgs && "Arg access out of range!");
|
2010-05-04 16:12:48 +00:00
|
|
|
return cast<Expr>(getArgs()[Arg]);
|
2009-06-02 17:58:47 +00:00
|
|
|
}
|
|
|
|
const Expr *getArg(unsigned Arg) const {
|
|
|
|
assert(Arg < NumArgs && "Arg access out of range!");
|
2010-05-04 16:12:48 +00:00
|
|
|
return cast<Expr>(getArgs()[Arg]);
|
2009-06-02 17:58:47 +00:00
|
|
|
}
|
|
|
|
/// setArg - Set the specified argument.
|
|
|
|
void setArg(unsigned Arg, Expr *ArgExpr) {
|
|
|
|
assert(Arg < NumArgs && "Arg access out of range!");
|
2010-05-04 16:12:48 +00:00
|
|
|
getArgs()[Arg] = ArgExpr;
|
2009-06-02 17:58:47 +00:00
|
|
|
}
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2011-07-17 15:40:56 +00:00
|
|
|
/// isDelegateInitCall - Answers whether this message send has been
|
|
|
|
/// tagged as a "delegate init call", i.e. a call to a method in the
|
|
|
|
/// -init family on self from within an -init method implementation.
|
|
|
|
bool isDelegateInitCall() const { return IsDelegateInitCall; }
|
|
|
|
void setDelegateInitCall(bool isDelegate) { IsDelegateInitCall = isDelegate; }
|
|
|
|
|
2010-05-04 16:12:48 +00:00
|
|
|
SourceLocation getLeftLoc() const { return LBracLoc; }
|
|
|
|
SourceLocation getRightLoc() const { return RBracLoc; }
|
2011-10-20 21:14:49 +00:00
|
|
|
|
2012-04-14 14:01:31 +00:00
|
|
|
SourceLocation getSelectorStartLoc() const {
|
|
|
|
if (isImplicit())
|
|
|
|
return getLocStart();
|
|
|
|
return getSelectorLoc(0);
|
|
|
|
}
|
2011-10-20 21:14:49 +00:00
|
|
|
SourceLocation getSelectorLoc(unsigned Index) const {
|
|
|
|
assert(Index < getNumSelectorLocs() && "Index out of range!");
|
|
|
|
if (hasStandardSelLocs())
|
|
|
|
return getStandardSelectorLoc(Index, getSelector(),
|
|
|
|
getSelLocsKind() == SelLoc_StandardWithSpace,
|
|
|
|
llvm::makeArrayRef(const_cast<Expr**>(getArgs()),
|
|
|
|
getNumArgs()),
|
|
|
|
RBracLoc);
|
|
|
|
return getStoredSelLocs()[Index];
|
|
|
|
}
|
|
|
|
|
|
|
|
void getSelectorLocs(SmallVectorImpl<SourceLocation> &SelLocs) const;
|
|
|
|
|
|
|
|
unsigned getNumSelectorLocs() const {
|
2012-04-14 14:01:31 +00:00
|
|
|
if (isImplicit())
|
|
|
|
return 0;
|
2011-10-20 21:14:49 +00:00
|
|
|
Selector Sel = getSelector();
|
|
|
|
if (Sel.isUnarySelector())
|
|
|
|
return 1;
|
|
|
|
return Sel.getNumArgs();
|
|
|
|
}
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
void setSourceRange(SourceRange R) {
|
2010-05-04 16:12:48 +00:00
|
|
|
LBracLoc = R.getBegin();
|
|
|
|
RBracLoc = R.getEnd();
|
2009-06-02 17:58:47 +00:00
|
|
|
}
|
2013-04-08 18:45:10 +00:00
|
|
|
SourceLocation getLocStart() const LLVM_READONLY { return LBracLoc; }
|
|
|
|
SourceLocation getLocEnd() const LLVM_READONLY { return RBracLoc; }
|
2009-06-02 17:58:47 +00:00
|
|
|
|
|
|
|
static bool classof(const Stmt *T) {
|
|
|
|
return T->getStmtClass() == ObjCMessageExprClass;
|
|
|
|
}
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
// Iterators
|
2011-02-20 13:06:31 +00:00
|
|
|
child_range children();
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
typedef ExprIterator arg_iterator;
|
|
|
|
typedef ConstExprIterator const_arg_iterator;
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2011-02-20 13:06:31 +00:00
|
|
|
arg_iterator arg_begin() { return reinterpret_cast<Stmt **>(getArgs()); }
|
|
|
|
arg_iterator arg_end() {
|
|
|
|
return reinterpret_cast<Stmt **>(getArgs() + NumArgs);
|
|
|
|
}
|
|
|
|
const_arg_iterator arg_begin() const {
|
|
|
|
return reinterpret_cast<Stmt const * const*>(getArgs());
|
|
|
|
}
|
|
|
|
const_arg_iterator arg_end() const {
|
|
|
|
return reinterpret_cast<Stmt const * const*>(getArgs() + NumArgs);
|
2009-06-02 17:58:47 +00:00
|
|
|
}
|
|
|
|
|
2011-02-20 13:06:31 +00:00
|
|
|
friend class ASTStmtReader;
|
|
|
|
friend class ASTStmtWriter;
|
2009-06-02 17:58:47 +00:00
|
|
|
};
|
|
|
|
|
2009-10-14 18:03:49 +00:00
|
|
|
/// ObjCIsaExpr - Represent X->isa and X.isa when X is an ObjC 'id' type.
|
2011-05-02 19:39:53 +00:00
|
|
|
/// (similar in spirit to MemberExpr).
|
2009-10-14 18:03:49 +00:00
|
|
|
class ObjCIsaExpr : public Expr {
|
|
|
|
/// Base - the expression for the base object pointer.
|
|
|
|
Stmt *Base;
|
|
|
|
|
|
|
|
/// IsaMemberLoc - This is the location of the 'isa'.
|
|
|
|
SourceLocation IsaMemberLoc;
|
2013-04-08 18:45:10 +00:00
|
|
|
|
|
|
|
/// OpLoc - This is the location of '.' or '->'
|
|
|
|
SourceLocation OpLoc;
|
2009-10-14 18:03:49 +00:00
|
|
|
|
|
|
|
/// IsArrow - True if this is "X->F", false if this is "X.F".
|
|
|
|
bool IsArrow;
|
|
|
|
public:
|
2013-04-08 18:45:10 +00:00
|
|
|
ObjCIsaExpr(Expr *base, bool isarrow, SourceLocation l, SourceLocation oploc,
|
|
|
|
QualType ty)
|
2011-02-20 13:06:31 +00:00
|
|
|
: Expr(ObjCIsaExprClass, ty, VK_LValue, OK_Ordinary,
|
|
|
|
/*TypeDependent=*/false, base->isValueDependent(),
|
2011-07-17 15:40:56 +00:00
|
|
|
base->isInstantiationDependent(),
|
2011-02-20 13:06:31 +00:00
|
|
|
/*ContainsUnexpandedParameterPack=*/false),
|
2013-04-08 18:45:10 +00:00
|
|
|
Base(base), IsaMemberLoc(l), OpLoc(oploc), IsArrow(isarrow) {}
|
2009-10-14 18:03:49 +00:00
|
|
|
|
|
|
|
/// \brief Build an empty expression.
|
|
|
|
explicit ObjCIsaExpr(EmptyShell Empty) : Expr(ObjCIsaExprClass, Empty) { }
|
|
|
|
|
|
|
|
void setBase(Expr *E) { Base = E; }
|
|
|
|
Expr *getBase() const { return cast<Expr>(Base); }
|
|
|
|
|
|
|
|
bool isArrow() const { return IsArrow; }
|
|
|
|
void setArrow(bool A) { IsArrow = A; }
|
|
|
|
|
|
|
|
/// getMemberLoc - Return the location of the "member", in X->F, it is the
|
|
|
|
/// location of 'F'.
|
|
|
|
SourceLocation getIsaMemberLoc() const { return IsaMemberLoc; }
|
|
|
|
void setIsaMemberLoc(SourceLocation L) { IsaMemberLoc = L; }
|
2013-04-08 18:45:10 +00:00
|
|
|
|
|
|
|
SourceLocation getOpLoc() const { return OpLoc; }
|
|
|
|
void setOpLoc(SourceLocation L) { OpLoc = L; }
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2013-04-08 18:45:10 +00:00
|
|
|
SourceLocation getLocStart() const LLVM_READONLY {
|
|
|
|
return getBase()->getLocStart();
|
|
|
|
}
|
|
|
|
|
|
|
|
SourceLocation getBaseLocEnd() const LLVM_READONLY {
|
|
|
|
return getBase()->getLocEnd();
|
2009-10-14 18:03:49 +00:00
|
|
|
}
|
2013-04-08 18:45:10 +00:00
|
|
|
|
|
|
|
SourceLocation getLocEnd() const LLVM_READONLY { return IsaMemberLoc; }
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2012-04-14 14:01:31 +00:00
|
|
|
SourceLocation getExprLoc() const LLVM_READONLY { return IsaMemberLoc; }
|
2009-10-14 18:03:49 +00:00
|
|
|
|
|
|
|
static bool classof(const Stmt *T) {
|
|
|
|
return T->getStmtClass() == ObjCIsaExprClass;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Iterators
|
2011-02-20 13:06:31 +00:00
|
|
|
child_range children() { return child_range(&Base, &Base+1); }
|
2009-10-14 18:03:49 +00:00
|
|
|
};
|
|
|
|
|
2011-07-17 15:40:56 +00:00
|
|
|
|
|
|
|
/// ObjCIndirectCopyRestoreExpr - Represents the passing of a function
|
|
|
|
/// argument by indirect copy-restore in ARC. This is used to support
|
|
|
|
/// passing indirect arguments with the wrong lifetime, e.g. when
|
|
|
|
/// passing the address of a __strong local variable to an 'out'
|
|
|
|
/// parameter. This expression kind is only valid in an "argument"
|
|
|
|
/// position to some sort of call expression.
|
|
|
|
///
|
|
|
|
/// The parameter must have type 'pointer to T', and the argument must
|
|
|
|
/// have type 'pointer to U', where T and U agree except possibly in
|
|
|
|
/// qualification. If the argument value is null, then a null pointer
|
|
|
|
/// is passed; otherwise it points to an object A, and:
|
|
|
|
/// 1. A temporary object B of type T is initialized, either by
|
|
|
|
/// zero-initialization (used when initializing an 'out' parameter)
|
|
|
|
/// or copy-initialization (used when initializing an 'inout'
|
|
|
|
/// parameter).
|
|
|
|
/// 2. The address of the temporary is passed to the function.
|
|
|
|
/// 3. If the call completes normally, A is move-assigned from B.
|
|
|
|
/// 4. Finally, A is destroyed immediately.
|
|
|
|
///
|
|
|
|
/// Currently 'T' must be a retainable object lifetime and must be
|
|
|
|
/// __autoreleasing; this qualifier is ignored when initializing
|
|
|
|
/// the value.
|
|
|
|
class ObjCIndirectCopyRestoreExpr : public Expr {
|
|
|
|
Stmt *Operand;
|
|
|
|
|
|
|
|
// unsigned ObjCIndirectCopyRestoreBits.ShouldCopy : 1;
|
|
|
|
|
|
|
|
friend class ASTReader;
|
|
|
|
friend class ASTStmtReader;
|
|
|
|
|
|
|
|
void setShouldCopy(bool shouldCopy) {
|
|
|
|
ObjCIndirectCopyRestoreExprBits.ShouldCopy = shouldCopy;
|
|
|
|
}
|
|
|
|
|
|
|
|
explicit ObjCIndirectCopyRestoreExpr(EmptyShell Empty)
|
|
|
|
: Expr(ObjCIndirectCopyRestoreExprClass, Empty) { }
|
|
|
|
|
|
|
|
public:
|
|
|
|
ObjCIndirectCopyRestoreExpr(Expr *operand, QualType type, bool shouldCopy)
|
|
|
|
: Expr(ObjCIndirectCopyRestoreExprClass, type, VK_LValue, OK_Ordinary,
|
|
|
|
operand->isTypeDependent(), operand->isValueDependent(),
|
|
|
|
operand->isInstantiationDependent(),
|
|
|
|
operand->containsUnexpandedParameterPack()),
|
|
|
|
Operand(operand) {
|
|
|
|
setShouldCopy(shouldCopy);
|
|
|
|
}
|
|
|
|
|
|
|
|
Expr *getSubExpr() { return cast<Expr>(Operand); }
|
|
|
|
const Expr *getSubExpr() const { return cast<Expr>(Operand); }
|
|
|
|
|
|
|
|
/// shouldCopy - True if we should do the 'copy' part of the
|
|
|
|
/// copy-restore. If false, the temporary will be zero-initialized.
|
|
|
|
bool shouldCopy() const { return ObjCIndirectCopyRestoreExprBits.ShouldCopy; }
|
|
|
|
|
|
|
|
child_range children() { return child_range(&Operand, &Operand+1); }
|
|
|
|
|
|
|
|
// Source locations are determined by the subexpression.
|
2013-04-08 18:45:10 +00:00
|
|
|
SourceLocation getLocStart() const LLVM_READONLY {
|
|
|
|
return Operand->getLocStart();
|
2012-04-14 14:01:31 +00:00
|
|
|
}
|
2013-04-08 18:45:10 +00:00
|
|
|
SourceLocation getLocEnd() const LLVM_READONLY { return Operand->getLocEnd();}
|
|
|
|
|
2012-04-14 14:01:31 +00:00
|
|
|
SourceLocation getExprLoc() const LLVM_READONLY {
|
|
|
|
return getSubExpr()->getExprLoc();
|
|
|
|
}
|
2011-07-17 15:40:56 +00:00
|
|
|
|
|
|
|
static bool classof(const Stmt *s) {
|
|
|
|
return s->getStmtClass() == ObjCIndirectCopyRestoreExprClass;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
/// \brief An Objective-C "bridged" cast expression, which casts between
|
|
|
|
/// Objective-C pointers and C pointers, transferring ownership in the process.
|
|
|
|
///
|
|
|
|
/// \code
|
|
|
|
/// NSString *str = (__bridge_transfer NSString *)CFCreateString();
|
|
|
|
/// \endcode
|
|
|
|
class ObjCBridgedCastExpr : public ExplicitCastExpr {
|
|
|
|
SourceLocation LParenLoc;
|
|
|
|
SourceLocation BridgeKeywordLoc;
|
|
|
|
unsigned Kind : 2;
|
|
|
|
|
|
|
|
friend class ASTStmtReader;
|
|
|
|
friend class ASTStmtWriter;
|
|
|
|
|
|
|
|
public:
|
|
|
|
ObjCBridgedCastExpr(SourceLocation LParenLoc, ObjCBridgeCastKind Kind,
|
2011-10-20 21:14:49 +00:00
|
|
|
CastKind CK, SourceLocation BridgeKeywordLoc,
|
|
|
|
TypeSourceInfo *TSInfo, Expr *Operand)
|
2011-07-17 15:40:56 +00:00
|
|
|
: ExplicitCastExpr(ObjCBridgedCastExprClass, TSInfo->getType(), VK_RValue,
|
2011-10-20 21:14:49 +00:00
|
|
|
CK, Operand, 0, TSInfo),
|
2011-07-17 15:40:56 +00:00
|
|
|
LParenLoc(LParenLoc), BridgeKeywordLoc(BridgeKeywordLoc), Kind(Kind) { }
|
|
|
|
|
|
|
|
/// \brief Construct an empty Objective-C bridged cast.
|
|
|
|
explicit ObjCBridgedCastExpr(EmptyShell Shell)
|
|
|
|
: ExplicitCastExpr(ObjCBridgedCastExprClass, Shell, 0) { }
|
|
|
|
|
|
|
|
SourceLocation getLParenLoc() const { return LParenLoc; }
|
|
|
|
|
|
|
|
/// \brief Determine which kind of bridge is being performed via this cast.
|
|
|
|
ObjCBridgeCastKind getBridgeKind() const {
|
|
|
|
return static_cast<ObjCBridgeCastKind>(Kind);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// \brief Retrieve the kind of bridge being performed as a string.
|
2011-10-20 21:14:49 +00:00
|
|
|
StringRef getBridgeKindName() const;
|
2011-07-17 15:40:56 +00:00
|
|
|
|
|
|
|
/// \brief The location of the bridge keyword.
|
|
|
|
SourceLocation getBridgeKeywordLoc() const { return BridgeKeywordLoc; }
|
|
|
|
|
2013-04-08 18:45:10 +00:00
|
|
|
SourceLocation getLocStart() const LLVM_READONLY { return LParenLoc; }
|
|
|
|
SourceLocation getLocEnd() const LLVM_READONLY {
|
|
|
|
return getSubExpr()->getLocEnd();
|
2011-07-17 15:40:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static bool classof(const Stmt *T) {
|
|
|
|
return T->getStmtClass() == ObjCBridgedCastExprClass;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
} // end namespace clang
|
|
|
|
|
|
|
|
#endif
|