diff options
author | vitalyisaev <vitalyisaev@yandex-team.com> | 2023-06-29 10:00:50 +0300 |
---|---|---|
committer | vitalyisaev <vitalyisaev@yandex-team.com> | 2023-06-29 10:00:50 +0300 |
commit | 6ffe9e53658409f212834330e13564e4952558f6 (patch) | |
tree | 85b1e00183517648b228aafa7c8fb07f5276f419 /contrib/libs/clang16/include/clang/AST/ExprObjC.h | |
parent | 726057070f9c5a91fc10fde0d5024913d10f1ab9 (diff) | |
download | ydb-6ffe9e53658409f212834330e13564e4952558f6.tar.gz |
YQ Connector: support managed ClickHouse
Со стороны dqrun можно обратиться к инстансу коннектора, который работает на streaming стенде, и извлечь данные из облачного CH.
Diffstat (limited to 'contrib/libs/clang16/include/clang/AST/ExprObjC.h')
-rw-r--r-- | contrib/libs/clang16/include/clang/AST/ExprObjC.h | 1736 |
1 files changed, 1736 insertions, 0 deletions
diff --git a/contrib/libs/clang16/include/clang/AST/ExprObjC.h b/contrib/libs/clang16/include/clang/AST/ExprObjC.h new file mode 100644 index 0000000000..b85b3d931d --- /dev/null +++ b/contrib/libs/clang16/include/clang/AST/ExprObjC.h @@ -0,0 +1,1736 @@ +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===- ExprObjC.h - Classes for representing ObjC expressions ---*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines the ExprObjC interface and subclasses. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_EXPROBJC_H +#define LLVM_CLANG_AST_EXPROBJC_H + +#include "clang/AST/ComputeDependence.h" +#include "clang/AST/Decl.h" +#include "clang/AST/DeclObjC.h" +#include "clang/AST/DependenceFlags.h" +#include "clang/AST/Expr.h" +#include "clang/AST/OperationKinds.h" +#include "clang/AST/SelectorLocationsKind.h" +#include "clang/AST/Stmt.h" +#include "clang/AST/Type.h" +#include "clang/Basic/IdentifierTable.h" +#include "clang/Basic/LLVM.h" +#include "clang/Basic/SourceLocation.h" +#include "clang/Basic/Specifiers.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/PointerIntPair.h" +#include "llvm/ADT/PointerUnion.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/iterator_range.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/TrailingObjects.h" +#include "llvm/Support/VersionTuple.h" +#include "llvm/Support/type_traits.h" +#include <cassert> +#include <cstddef> +#include <cstdint> +#include <optional> + +namespace clang { + +class ASTContext; +class CXXBaseSpecifier; + +/// 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) + : Expr(ObjCStringLiteralClass, T, VK_PRValue, OK_Ordinary), String(SL), + AtLoc(L) { + setDependence(ExprDependence::None); + } + 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; } + + SourceLocation getBeginLoc() const LLVM_READONLY { return AtLoc; } + SourceLocation getEndLoc() const LLVM_READONLY { return String->getEndLoc(); } + + // Iterators + child_range children() { return child_range(&String, &String+1); } + + const_child_range children() const { + return const_child_range(&String, &String + 1); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == ObjCStringLiteralClass; + } +}; + +/// 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_PRValue, OK_Ordinary), Value(val), + Loc(l) { + setDependence(ExprDependence::None); + } + explicit ObjCBoolLiteralExpr(EmptyShell Empty) + : Expr(ObjCBoolLiteralExprClass, Empty) {} + + bool getValue() const { return Value; } + void setValue(bool V) { Value = V; } + + SourceLocation getBeginLoc() const LLVM_READONLY { return Loc; } + SourceLocation getEndLoc() const LLVM_READONLY { return Loc; } + + SourceLocation getLocation() const { return Loc; } + void setLocation(SourceLocation L) { Loc = L; } + + // Iterators + child_range children() { + return child_range(child_iterator(), child_iterator()); + } + + const_child_range children() const { + return const_child_range(const_child_iterator(), const_child_iterator()); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == ObjCBoolLiteralExprClass; + } +}; + +/// ObjCBoxedExpr - used for generalized expression boxing. +/// as in: @(strdup("hello world")), @(random()) or @(view.frame) +/// Also used for boxing non-parenthesized numeric literals; +/// as in: @42 or \@true (c++/objc++) or \@__objc_yes (c/objc). +class ObjCBoxedExpr : public Expr { + Stmt *SubExpr; + ObjCMethodDecl *BoxingMethod; + SourceRange Range; + +public: + friend class ASTStmtReader; + + ObjCBoxedExpr(Expr *E, QualType T, ObjCMethodDecl *method, SourceRange R) + : Expr(ObjCBoxedExprClass, T, VK_PRValue, OK_Ordinary), SubExpr(E), + BoxingMethod(method), Range(R) { + setDependence(computeDependence(this)); + } + explicit ObjCBoxedExpr(EmptyShell Empty) + : Expr(ObjCBoxedExprClass, Empty) {} + + Expr *getSubExpr() { return cast<Expr>(SubExpr); } + const Expr *getSubExpr() const { return cast<Expr>(SubExpr); } + + ObjCMethodDecl *getBoxingMethod() const { + return BoxingMethod; + } + + // Indicates whether this boxed expression can be emitted as a compile-time + // constant. + bool isExpressibleAsConstantInitializer() const { + return !BoxingMethod && SubExpr; + } + + SourceLocation getAtLoc() const { return Range.getBegin(); } + + SourceLocation getBeginLoc() const LLVM_READONLY { return Range.getBegin(); } + SourceLocation getEndLoc() const LLVM_READONLY { return Range.getEnd(); } + + SourceRange getSourceRange() const LLVM_READONLY { + return Range; + } + + // Iterators + child_range children() { return child_range(&SubExpr, &SubExpr+1); } + + const_child_range children() const { + return const_child_range(&SubExpr, &SubExpr + 1); + } + + using const_arg_iterator = ConstExprIterator; + + 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); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == ObjCBoxedExprClass; + } +}; + +/// ObjCArrayLiteral - used for objective-c array containers; as in: +/// @[@"Hello", NSApp, [NSNumber numberWithInt:42]]; +class ObjCArrayLiteral final + : public Expr, + private llvm::TrailingObjects<ObjCArrayLiteral, Expr *> { + unsigned NumElements; + SourceRange Range; + ObjCMethodDecl *ArrayWithObjectsMethod; + + ObjCArrayLiteral(ArrayRef<Expr *> Elements, + QualType T, ObjCMethodDecl * Method, + SourceRange SR); + + explicit ObjCArrayLiteral(EmptyShell Empty, unsigned NumElements) + : Expr(ObjCArrayLiteralClass, Empty), NumElements(NumElements) {} + +public: + friend class ASTStmtReader; + friend TrailingObjects; + + static ObjCArrayLiteral *Create(const ASTContext &C, + ArrayRef<Expr *> Elements, + QualType T, ObjCMethodDecl * Method, + SourceRange SR); + + static ObjCArrayLiteral *CreateEmpty(const ASTContext &C, + unsigned NumElements); + + SourceLocation getBeginLoc() const LLVM_READONLY { return Range.getBegin(); } + SourceLocation getEndLoc() const LLVM_READONLY { return Range.getEnd(); } + SourceRange getSourceRange() const LLVM_READONLY { return Range; } + + /// Retrieve elements of array of literals. + Expr **getElements() { return getTrailingObjects<Expr *>(); } + + /// Retrieve elements of array of literals. + const Expr * const *getElements() const { + return getTrailingObjects<Expr *>(); + } + + /// getNumElements - Return number of elements of objective-c array literal. + unsigned getNumElements() const { return NumElements; } + + /// getElement - Return the Element at the specified index. + Expr *getElement(unsigned Index) { + assert((Index < NumElements) && "Arg access out of range!"); + return getElements()[Index]; + } + const Expr *getElement(unsigned Index) const { + assert((Index < NumElements) && "Arg access out of range!"); + return getElements()[Index]; + } + + ObjCMethodDecl *getArrayWithObjectsMethod() const { + return ArrayWithObjectsMethod; + } + + // Iterators + child_range children() { + return child_range(reinterpret_cast<Stmt **>(getElements()), + reinterpret_cast<Stmt **>(getElements()) + NumElements); + } + + const_child_range children() const { + auto Children = const_cast<ObjCArrayLiteral *>(this)->children(); + return const_child_range(Children.begin(), Children.end()); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == ObjCArrayLiteralClass; + } +}; + +/// An element in an Objective-C dictionary literal. +/// +struct ObjCDictionaryElement { + /// The key for the dictionary element. + Expr *Key; + + /// The value of the dictionary element. + Expr *Value; + + /// The location of the ellipsis, if this is a pack expansion. + SourceLocation EllipsisLoc; + + /// The number of elements this pack expansion will expand to, if + /// this is a pack expansion and is known. + std::optional<unsigned> NumExpansions; + + /// Determines whether this dictionary element is a pack expansion. + bool isPackExpansion() const { return EllipsisLoc.isValid(); } +}; + +} // namespace clang + +namespace clang { + +/// Internal struct for storing Key/value pair. +struct ObjCDictionaryLiteral_KeyValuePair { + Expr *Key; + Expr *Value; +}; + +/// Internal struct to describes an element that is a pack +/// expansion, used if any of the elements in the dictionary literal +/// are pack expansions. +struct ObjCDictionaryLiteral_ExpansionData { + /// The location of the ellipsis, if this element is a pack + /// expansion. + SourceLocation EllipsisLoc; + + /// If non-zero, the number of elements that this pack + /// expansion will expand to (+1). + unsigned NumExpansionsPlusOne; +}; + +/// ObjCDictionaryLiteral - AST node to represent objective-c dictionary +/// literals; as in: @{@"name" : NSUserName(), @"date" : [NSDate date] }; +class ObjCDictionaryLiteral final + : public Expr, + private llvm::TrailingObjects<ObjCDictionaryLiteral, + ObjCDictionaryLiteral_KeyValuePair, + ObjCDictionaryLiteral_ExpansionData> { + /// The number of elements in this dictionary literal. + unsigned NumElements : 31; + + /// 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; + + using KeyValuePair = ObjCDictionaryLiteral_KeyValuePair; + using ExpansionData = ObjCDictionaryLiteral_ExpansionData; + + 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) {} + + size_t numTrailingObjects(OverloadToken<KeyValuePair>) const { + return NumElements; + } + +public: + friend class ASTStmtReader; + friend class ASTStmtWriter; + friend TrailingObjects; + + static ObjCDictionaryLiteral *Create(const ASTContext &C, + ArrayRef<ObjCDictionaryElement> VK, + bool HasPackExpansions, + QualType T, ObjCMethodDecl *method, + SourceRange SR); + + static ObjCDictionaryLiteral *CreateEmpty(const ASTContext &C, + 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 = getTrailingObjects<KeyValuePair>()[Index]; + ObjCDictionaryElement Result = {KV.Key, KV.Value, SourceLocation(), + std::nullopt}; + if (HasPackExpansions) { + const ExpansionData &Expansion = + getTrailingObjects<ExpansionData>()[Index]; + Result.EllipsisLoc = Expansion.EllipsisLoc; + if (Expansion.NumExpansionsPlusOne > 0) + Result.NumExpansions = Expansion.NumExpansionsPlusOne - 1; + } + return Result; + } + + ObjCMethodDecl *getDictWithObjectsMethod() const { + return DictWithObjectsMethod; + } + + SourceLocation getBeginLoc() const LLVM_READONLY { return Range.getBegin(); } + SourceLocation getEndLoc() const LLVM_READONLY { return Range.getEnd(); } + SourceRange getSourceRange() const LLVM_READONLY { return Range; } + + // 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. + static_assert(sizeof(KeyValuePair) == sizeof(Stmt *) * 2, + "KeyValuePair is expected size"); + return child_range( + reinterpret_cast<Stmt **>(getTrailingObjects<KeyValuePair>()), + reinterpret_cast<Stmt **>(getTrailingObjects<KeyValuePair>()) + + NumElements * 2); + } + + const_child_range children() const { + auto Children = const_cast<ObjCDictionaryLiteral *>(this)->children(); + return const_child_range(Children.begin(), Children.end()); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == ObjCDictionaryLiteralClass; + } +}; + +/// 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. +class ObjCEncodeExpr : public Expr { + TypeSourceInfo *EncodedType; + SourceLocation AtLoc, RParenLoc; + +public: + ObjCEncodeExpr(QualType T, TypeSourceInfo *EncodedType, SourceLocation at, + SourceLocation rp) + : Expr(ObjCEncodeExprClass, T, VK_LValue, OK_Ordinary), + EncodedType(EncodedType), AtLoc(at), RParenLoc(rp) { + setDependence(computeDependence(this)); + } + + explicit ObjCEncodeExpr(EmptyShell Empty) : Expr(ObjCEncodeExprClass, Empty){} + + SourceLocation getAtLoc() const { return AtLoc; } + void setAtLoc(SourceLocation L) { AtLoc = L; } + SourceLocation getRParenLoc() const { return RParenLoc; } + void setRParenLoc(SourceLocation L) { RParenLoc = L; } + + QualType getEncodedType() const { return EncodedType->getType(); } + + TypeSourceInfo *getEncodedTypeSourceInfo() const { return EncodedType; } + + void setEncodedTypeSourceInfo(TypeSourceInfo *EncType) { + EncodedType = EncType; + } + + SourceLocation getBeginLoc() const LLVM_READONLY { return AtLoc; } + SourceLocation getEndLoc() const LLVM_READONLY { return RParenLoc; } + + // Iterators + child_range children() { + return child_range(child_iterator(), child_iterator()); + } + + const_child_range children() const { + return const_child_range(const_child_iterator(), const_child_iterator()); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == ObjCEncodeExprClass; + } +}; + +/// ObjCSelectorExpr used for \@selector in Objective-C. +class ObjCSelectorExpr : public Expr { + Selector SelName; + SourceLocation AtLoc, RParenLoc; + +public: + ObjCSelectorExpr(QualType T, Selector selInfo, SourceLocation at, + SourceLocation rp) + : Expr(ObjCSelectorExprClass, T, VK_PRValue, OK_Ordinary), + SelName(selInfo), AtLoc(at), RParenLoc(rp) { + setDependence(ExprDependence::None); + } + explicit ObjCSelectorExpr(EmptyShell Empty) + : Expr(ObjCSelectorExprClass, Empty) {} + + Selector getSelector() const { return SelName; } + void setSelector(Selector S) { SelName = S; } + + SourceLocation getAtLoc() const { return AtLoc; } + SourceLocation getRParenLoc() const { return RParenLoc; } + void setAtLoc(SourceLocation L) { AtLoc = L; } + void setRParenLoc(SourceLocation L) { RParenLoc = L; } + + SourceLocation getBeginLoc() const LLVM_READONLY { return AtLoc; } + SourceLocation getEndLoc() const LLVM_READONLY { return RParenLoc; } + + /// getNumArgs - Return the number of actual arguments to this call. + unsigned getNumArgs() const { return SelName.getNumArgs(); } + + // Iterators + child_range children() { + return child_range(child_iterator(), child_iterator()); + } + + const_child_range children() const { + return const_child_range(const_child_iterator(), const_child_iterator()); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == ObjCSelectorExprClass; + } +}; + +/// ObjCProtocolExpr used for protocol expression in Objective-C. +/// +/// This is used as: \@protocol(foo), as in: +/// \code +/// [obj conformsToProtocol:@protocol(foo)] +/// \endcode +/// +/// The return type is "Protocol*". +class ObjCProtocolExpr : public Expr { + ObjCProtocolDecl *TheProtocol; + SourceLocation AtLoc, ProtoLoc, RParenLoc; + +public: + friend class ASTStmtReader; + friend class ASTStmtWriter; + + ObjCProtocolExpr(QualType T, ObjCProtocolDecl *protocol, SourceLocation at, + SourceLocation protoLoc, SourceLocation rp) + : Expr(ObjCProtocolExprClass, T, VK_PRValue, OK_Ordinary), + TheProtocol(protocol), AtLoc(at), ProtoLoc(protoLoc), RParenLoc(rp) { + setDependence(ExprDependence::None); + } + explicit ObjCProtocolExpr(EmptyShell Empty) + : Expr(ObjCProtocolExprClass, Empty) {} + + ObjCProtocolDecl *getProtocol() const { return TheProtocol; } + void setProtocol(ObjCProtocolDecl *P) { TheProtocol = P; } + + SourceLocation getProtocolIdLoc() const { return ProtoLoc; } + SourceLocation getAtLoc() const { return AtLoc; } + SourceLocation getRParenLoc() const { return RParenLoc; } + void setAtLoc(SourceLocation L) { AtLoc = L; } + void setRParenLoc(SourceLocation L) { RParenLoc = L; } + + SourceLocation getBeginLoc() const LLVM_READONLY { return AtLoc; } + SourceLocation getEndLoc() const LLVM_READONLY { return RParenLoc; } + + // Iterators + child_range children() { + return child_range(child_iterator(), child_iterator()); + } + + const_child_range children() const { + return const_child_range(const_child_iterator(), const_child_iterator()); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == ObjCProtocolExprClass; + } +}; + +/// ObjCIvarRefExpr - A reference to an ObjC instance variable. +class ObjCIvarRefExpr : public Expr { + ObjCIvarDecl *D; + Stmt *Base; + SourceLocation Loc; + + /// OpLoc - This is the location of '.' or '->' + SourceLocation OpLoc; + + // True if this is "X->F", false if this is "X.F". + bool IsArrow : 1; + + // True if ivar reference has no base (self assumed). + bool IsFreeIvar : 1; + +public: + ObjCIvarRefExpr(ObjCIvarDecl *d, QualType t, SourceLocation l, + SourceLocation oploc, Expr *base, bool arrow = false, + bool freeIvar = false) + : Expr(ObjCIvarRefExprClass, t, VK_LValue, + d->isBitField() ? OK_BitField : OK_Ordinary), + D(d), Base(base), Loc(l), OpLoc(oploc), IsArrow(arrow), + IsFreeIvar(freeIvar) { + setDependence(computeDependence(this)); + } + + explicit ObjCIvarRefExpr(EmptyShell Empty) + : Expr(ObjCIvarRefExprClass, Empty) {} + + ObjCIvarDecl *getDecl() { return D; } + const ObjCIvarDecl *getDecl() const { return D; } + void setDecl(ObjCIvarDecl *d) { D = d; } + + const Expr *getBase() const { return cast<Expr>(Base); } + Expr *getBase() { return cast<Expr>(Base); } + void setBase(Expr * base) { Base = base; } + + bool isArrow() const { return IsArrow; } + bool isFreeIvar() const { return IsFreeIvar; } + void setIsArrow(bool A) { IsArrow = A; } + void setIsFreeIvar(bool A) { IsFreeIvar = A; } + + SourceLocation getLocation() const { return Loc; } + void setLocation(SourceLocation L) { Loc = L; } + + SourceLocation getBeginLoc() const LLVM_READONLY { + return isFreeIvar() ? Loc : getBase()->getBeginLoc(); + } + SourceLocation getEndLoc() const LLVM_READONLY { return Loc; } + + SourceLocation getOpLoc() const { return OpLoc; } + void setOpLoc(SourceLocation L) { OpLoc = L; } + + // Iterators + child_range children() { return child_range(&Base, &Base+1); } + + const_child_range children() const { + return const_child_range(&Base, &Base + 1); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == ObjCIvarRefExprClass; + } +}; + +/// ObjCPropertyRefExpr - A dot-syntax expression to access an ObjC +/// property. +class ObjCPropertyRefExpr : public Expr { +private: + /// 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; + + /// 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 + }; + + /// 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). + + SourceLocation IdLoc; + + /// 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::PointerUnion<Stmt *, const Type *, ObjCInterfaceDecl *> Receiver; + +public: + ObjCPropertyRefExpr(ObjCPropertyDecl *PD, QualType t, ExprValueKind VK, + ExprObjectKind OK, SourceLocation l, Expr *base) + : Expr(ObjCPropertyRefExprClass, t, VK, OK), PropertyOrGetter(PD, false), + IdLoc(l), Receiver(base) { + assert(t->isSpecificPlaceholderType(BuiltinType::PseudoObject)); + setDependence(computeDependence(this)); + } + + ObjCPropertyRefExpr(ObjCPropertyDecl *PD, QualType t, ExprValueKind VK, + ExprObjectKind OK, SourceLocation l, SourceLocation sl, + QualType st) + : Expr(ObjCPropertyRefExprClass, t, VK, OK), PropertyOrGetter(PD, false), + IdLoc(l), ReceiverLoc(sl), Receiver(st.getTypePtr()) { + assert(t->isSpecificPlaceholderType(BuiltinType::PseudoObject)); + setDependence(computeDependence(this)); + } + + ObjCPropertyRefExpr(ObjCMethodDecl *Getter, ObjCMethodDecl *Setter, + QualType T, ExprValueKind VK, ExprObjectKind OK, + SourceLocation IdLoc, Expr *Base) + : Expr(ObjCPropertyRefExprClass, T, VK, OK), + PropertyOrGetter(Getter, true), SetterAndMethodRefFlags(Setter, 0), + IdLoc(IdLoc), Receiver(Base) { + assert(T->isSpecificPlaceholderType(BuiltinType::PseudoObject)); + setDependence(computeDependence(this)); + } + + ObjCPropertyRefExpr(ObjCMethodDecl *Getter, ObjCMethodDecl *Setter, + QualType T, ExprValueKind VK, ExprObjectKind OK, + SourceLocation IdLoc, SourceLocation SuperLoc, + QualType SuperTy) + : Expr(ObjCPropertyRefExprClass, T, VK, OK), + PropertyOrGetter(Getter, true), SetterAndMethodRefFlags(Setter, 0), + IdLoc(IdLoc), ReceiverLoc(SuperLoc), Receiver(SuperTy.getTypePtr()) { + assert(T->isSpecificPlaceholderType(BuiltinType::PseudoObject)); + setDependence(computeDependence(this)); + } + + ObjCPropertyRefExpr(ObjCMethodDecl *Getter, ObjCMethodDecl *Setter, + QualType T, ExprValueKind VK, ExprObjectKind OK, + SourceLocation IdLoc, SourceLocation ReceiverLoc, + ObjCInterfaceDecl *Receiver) + : Expr(ObjCPropertyRefExprClass, T, VK, OK), + PropertyOrGetter(Getter, true), SetterAndMethodRefFlags(Setter, 0), + IdLoc(IdLoc), ReceiverLoc(ReceiverLoc), Receiver(Receiver) { + assert(T->isSpecificPlaceholderType(BuiltinType::PseudoObject)); + setDependence(computeDependence(this)); + } + + explicit ObjCPropertyRefExpr(EmptyShell Empty) + : Expr(ObjCPropertyRefExprClass, Empty) {} + + bool isImplicitProperty() const { return PropertyOrGetter.getInt(); } + bool isExplicitProperty() const { return !PropertyOrGetter.getInt(); } + + 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()); + return SetterAndMethodRefFlags.getPointer(); + } + + Selector getGetterSelector() const { + if (isImplicitProperty()) + return getImplicitPropertyGetter()->getSelector(); + return getExplicitProperty()->getGetterName(); + } + + Selector getSetterSelector() const { + if (isImplicitProperty()) + return getImplicitPropertySetter()->getSelector(); + return getExplicitProperty()->getSetterName(); + } + + /// 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; + } + + /// 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); + } + + const Expr *getBase() const { + return cast<Expr>(Receiver.get<Stmt*>()); + } + Expr *getBase() { + return cast<Expr>(Receiver.get<Stmt*>()); + } + + SourceLocation getLocation() const { return IdLoc; } + + SourceLocation getReceiverLocation() const { return ReceiverLoc; } + + QualType getSuperReceiverType() const { + return QualType(Receiver.get<const Type*>(), 0); + } + + 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*>(); } + + /// Determine the type of the base, regardless of the kind of receiver. + QualType getReceiverType(const ASTContext &ctx) const; + + SourceLocation getBeginLoc() const LLVM_READONLY { + return isObjectReceiver() ? getBase()->getBeginLoc() + : getReceiverLocation(); + } + + SourceLocation getEndLoc() const LLVM_READONLY { return IdLoc; } + + // Iterators + child_range children() { + if (Receiver.is<Stmt*>()) { + Stmt **begin = reinterpret_cast<Stmt**>(&Receiver); // hack! + return child_range(begin, begin+1); + } + return child_range(child_iterator(), child_iterator()); + } + + const_child_range children() const { + auto Children = const_cast<ObjCPropertyRefExpr *>(this)->children(); + return const_child_range(Children.begin(), Children.end()); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == ObjCPropertyRefExprClass; + } + +private: + friend class ASTStmtReader; + friend class ASTStmtWriter; + + void setExplicitProperty(ObjCPropertyDecl *D, unsigned methRefFlags) { + PropertyOrGetter.setPointer(D); + PropertyOrGetter.setInt(false); + SetterAndMethodRefFlags.setPointer(nullptr); + SetterAndMethodRefFlags.setInt(methRefFlags); + } + + void setImplicitProperty(ObjCMethodDecl *Getter, ObjCMethodDecl *Setter, + unsigned methRefFlags) { + PropertyOrGetter.setPointer(Getter); + PropertyOrGetter.setInt(true); + SetterAndMethodRefFlags.setPointer(Setter); + SetterAndMethodRefFlags.setInt(methRefFlags); + } + + void setBase(Expr *Base) { Receiver = Base; } + void setSuperReceiver(QualType T) { Receiver = T.getTypePtr(); } + void setClassReceiver(ObjCInterfaceDecl *D) { Receiver = D; } + + void setLocation(SourceLocation L) { IdLoc = L; } + void setReceiverLocation(SourceLocation Loc) { ReceiverLoc = Loc; } + + void setMethodRefFlag(MethodRefFlags flag, bool val) { + unsigned f = SetterAndMethodRefFlags.getInt(); + if (val) + f |= flag; + else + f &= ~flag; + SetterAndMethodRefFlags.setInt(f); + } +}; + +/// 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), RBracket(RB), + GetAtIndexMethodDecl(getMethod), SetAtIndexMethodDecl(setMethod) { + SubExprs[BASE] = base; + SubExprs[KEY] = key; + setDependence(computeDependence(this)); + } + + explicit ObjCSubscriptRefExpr(EmptyShell Empty) + : Expr(ObjCSubscriptRefExprClass, Empty) {} + + SourceLocation getRBracket() const { return RBracket; } + void setRBracket(SourceLocation RB) { RBracket = RB; } + + SourceLocation getBeginLoc() const LLVM_READONLY { + return SubExprs[BASE]->getBeginLoc(); + } + + SourceLocation getEndLoc() const LLVM_READONLY { return RBracket; } + + 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); + } + + const_child_range children() const { + return const_child_range(SubExprs, SubExprs + END_EXPR); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == ObjCSubscriptRefExprClass; + } + +private: + friend class ASTStmtReader; +}; + +/// 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: +/// +/// The "void *" trailing objects are actually ONE void * (the +/// receiver pointer), and NumArgs Expr *. But due to the +/// implementation of children(), these must be together contiguously. +class ObjCMessageExpr final + : public Expr, + private llvm::TrailingObjects<ObjCMessageExpr, void *, SourceLocation> { + /// 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 = 0; + + enum { NumArgsBitWidth = 16 }; + + /// The number of arguments in the message send, not + /// including the receiver. + unsigned NumArgs : NumArgsBitWidth; + + /// 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; + + /// Whether we have an actual method prototype in \c + /// SelectorOrMethod. + /// + /// When non-zero, we have a method declaration; otherwise, we just + /// have a selector. + unsigned HasMethod : 1; + + /// 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; + + /// Whether this message send was implicitly generated by + /// the implementation rather than explicitly written by the user. + unsigned IsImplicit : 1; + + /// Whether the locations of the selector identifiers are in a + /// "standard" position, a enum SelectorLocationsKind. + unsigned SelLocsKind : 2; + + /// When the message expression is a send to 'super', this is + /// the location of the 'super' keyword. + SourceLocation SuperLoc; + + /// The source locations of the open and close square + /// brackets ('[' and ']', respectively). + SourceLocation LBracLoc, RBracLoc; + + ObjCMessageExpr(EmptyShell Empty, unsigned NumArgs) + : Expr(ObjCMessageExprClass, Empty), Kind(0), HasMethod(false), + IsDelegateInitCall(false), IsImplicit(false), SelLocsKind(0) { + setNumArgs(NumArgs); + } + + ObjCMessageExpr(QualType T, ExprValueKind VK, + SourceLocation LBracLoc, + SourceLocation SuperLoc, + bool IsInstanceSuper, + QualType SuperType, + Selector Sel, + ArrayRef<SourceLocation> SelLocs, + SelectorLocationsKind SelLocsK, + ObjCMethodDecl *Method, + ArrayRef<Expr *> Args, + SourceLocation RBracLoc, + bool isImplicit); + ObjCMessageExpr(QualType T, ExprValueKind VK, + SourceLocation LBracLoc, + TypeSourceInfo *Receiver, + Selector Sel, + ArrayRef<SourceLocation> SelLocs, + SelectorLocationsKind SelLocsK, + ObjCMethodDecl *Method, + ArrayRef<Expr *> Args, + SourceLocation RBracLoc, + bool isImplicit); + ObjCMessageExpr(QualType T, ExprValueKind VK, + SourceLocation LBracLoc, + Expr *Receiver, + Selector Sel, + ArrayRef<SourceLocation> SelLocs, + SelectorLocationsKind SelLocsK, + ObjCMethodDecl *Method, + ArrayRef<Expr *> Args, + SourceLocation RBracLoc, + bool isImplicit); + + size_t numTrailingObjects(OverloadToken<void *>) const { return NumArgs + 1; } + + void setNumArgs(unsigned Num) { + assert((Num >> NumArgsBitWidth) == 0 && "Num of args is out of range!"); + NumArgs = Num; + } + + void initArgsAndSelLocs(ArrayRef<Expr *> Args, + ArrayRef<SourceLocation> SelLocs, + SelectorLocationsKind SelLocsK); + + /// Retrieve the pointer value of the message receiver. + void *getReceiverPointer() const { return *getTrailingObjects<void *>(); } + + /// Set the pointer value of the message receiver. + void setReceiverPointer(void *Value) { + *getTrailingObjects<void *>() = Value; + } + + SelectorLocationsKind getSelLocsKind() const { + return (SelectorLocationsKind)SelLocsKind; + } + + bool hasStandardSelLocs() const { + return getSelLocsKind() != SelLoc_NonStandard; + } + + /// Get a pointer to the stored selector identifiers locations array. + /// No locations will be stored if HasStandardSelLocs is true. + SourceLocation *getStoredSelLocs() { + return getTrailingObjects<SourceLocation>(); + } + const SourceLocation *getStoredSelLocs() const { + return getTrailingObjects<SourceLocation>(); + } + + /// 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(); + } + + static ObjCMessageExpr *alloc(const ASTContext &C, + ArrayRef<Expr *> Args, + SourceLocation RBraceLoc, + ArrayRef<SourceLocation> SelLocs, + Selector Sel, + SelectorLocationsKind &SelLocsK); + static ObjCMessageExpr *alloc(const ASTContext &C, + unsigned NumArgs, + unsigned NumStoredSelLocs); + +public: + friend class ASTStmtReader; + friend class ASTStmtWriter; + friend TrailingObjects; + + /// The kind of receiver this message is sending to. + enum ReceiverKind { + /// The receiver is a class. + Class = 0, + + /// The receiver is an object instance. + Instance, + + /// The receiver is a superclass. + SuperClass, + + /// The receiver is the instance of the superclass object. + SuperInstance + }; + + /// 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. + /// + /// \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. + /// + /// \param LBracLoc The location of the open square bracket '['. + /// + /// \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 nullptr. + /// + /// \param Args The message send arguments. + /// + /// \param RBracLoc The location of the closing square bracket ']'. + static ObjCMessageExpr *Create(const ASTContext &Context, QualType T, + ExprValueKind VK, + SourceLocation LBracLoc, + SourceLocation SuperLoc, + bool IsInstanceSuper, + QualType SuperType, + Selector Sel, + ArrayRef<SourceLocation> SelLocs, + ObjCMethodDecl *Method, + ArrayRef<Expr *> Args, + SourceLocation RBracLoc, + bool isImplicit); + + /// Create a class message send. + /// + /// \param Context The ASTContext in which this expression will be created. + /// + /// \param T The result type of this message. + /// + /// \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. + /// + /// \param LBracLoc The location of the open square bracket '['. + /// + /// \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 nullptr. + /// + /// \param Args The message send arguments. + /// + /// \param RBracLoc The location of the closing square bracket ']'. + static ObjCMessageExpr *Create(const ASTContext &Context, QualType T, + ExprValueKind VK, + SourceLocation LBracLoc, + TypeSourceInfo *Receiver, + Selector Sel, + ArrayRef<SourceLocation> SelLocs, + ObjCMethodDecl *Method, + ArrayRef<Expr *> Args, + SourceLocation RBracLoc, + bool isImplicit); + + /// Create an instance message send. + /// + /// \param Context The ASTContext in which this expression will be created. + /// + /// \param T The result type of this message. + /// + /// \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. + /// + /// \param LBracLoc The location of the open square bracket '['. + /// + /// \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 nullptr. + /// + /// \param Args The message send arguments. + /// + /// \param RBracLoc The location of the closing square bracket ']'. + static ObjCMessageExpr *Create(const ASTContext &Context, QualType T, + ExprValueKind VK, + SourceLocation LBracLoc, + Expr *Receiver, + Selector Sel, + ArrayRef<SourceLocation> SeLocs, + ObjCMethodDecl *Method, + ArrayRef<Expr *> Args, + SourceLocation RBracLoc, + bool isImplicit); + + /// 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. + static ObjCMessageExpr *CreateEmpty(const ASTContext &Context, + unsigned NumArgs, + unsigned NumStoredSelLocs); + + /// 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; } + + /// Determine the kind of receiver that this message is being + /// sent to. + ReceiverKind getReceiverKind() const { return (ReceiverKind)Kind; } + + /// \return the return type of the message being sent. + /// This is not always the type of the message expression itself because + /// of references (the expression would not have a reference type). + /// It is also not always the declared return type of the method because + /// of `instancetype` (in that case it's an expression type). + QualType getCallReturnType(ASTContext &Ctx) const; + + /// Source range of the receiver. + SourceRange getReceiverRange() const; + + /// Determine whether this is an instance message to either a + /// computed object or to super. + bool isInstanceMessage() const { + return getReceiverKind() == Instance || getReceiverKind() == SuperInstance; + } + + /// Determine whether this is an class message to either a + /// specified class or to super. + bool isClassMessage() const { + return getReceiverKind() == Class || getReceiverKind() == SuperClass; + } + + /// Returns the object expression (receiver) for an instance message, + /// or null for a message that is not an instance message. + Expr *getInstanceReceiver() { + if (getReceiverKind() == Instance) + return static_cast<Expr *>(getReceiverPointer()); + + return nullptr; + } + const Expr *getInstanceReceiver() const { + return const_cast<ObjCMessageExpr*>(this)->getInstanceReceiver(); + } + + /// 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); + } + + /// 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 {}; + } + + /// Returns a type-source information of a class message + /// send, or nullptr if the message is not a class message. + TypeSourceInfo *getClassReceiverTypeInfo() const { + if (getReceiverKind() == Class) + return reinterpret_cast<TypeSourceInfo *>(getReceiverPointer()); + return nullptr; + } + + void setClassReceiver(TypeSourceInfo *TSInfo) { + Kind = Class; + setReceiverPointer(TSInfo); + } + + /// 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; + + return SourceLocation(); + } + + /// 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; + + /// 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 nullptr. + ObjCInterfaceDecl *getReceiverInterface() const; + + /// 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(); + } + + void setSuper(SourceLocation Loc, QualType T, bool IsInstanceSuper) { + Kind = IsInstanceSuper? SuperInstance : SuperClass; + SuperLoc = Loc; + setReceiverPointer(T.getAsOpaquePtr()); + } + + Selector getSelector() const; + + void setSelector(Selector S) { + HasMethod = false; + SelectorOrMethod = reinterpret_cast<uintptr_t>(S.getAsOpaquePtr()); + } + + const ObjCMethodDecl *getMethodDecl() const { + if (HasMethod) + return reinterpret_cast<const ObjCMethodDecl *>(SelectorOrMethod); + + return nullptr; + } + + ObjCMethodDecl *getMethodDecl() { + if (HasMethod) + return reinterpret_cast<ObjCMethodDecl *>(SelectorOrMethod); + + return nullptr; + } + + void setMethodDecl(ObjCMethodDecl *MD) { + HasMethod = true; + SelectorOrMethod = reinterpret_cast<uintptr_t>(MD); + } + + ObjCMethodFamily getMethodFamily() const { + if (HasMethod) return getMethodDecl()->getMethodFamily(); + return getSelector().getMethodFamily(); + } + + /// Return the number of actual arguments in this message, + /// not counting the receiver. + unsigned getNumArgs() const { return NumArgs; } + + /// Retrieve the arguments to this message, not including the + /// receiver. + Expr **getArgs() { + return reinterpret_cast<Expr **>(getTrailingObjects<void *>() + 1); + } + const Expr * const *getArgs() const { + return reinterpret_cast<const Expr *const *>(getTrailingObjects<void *>() + + 1); + } + + /// getArg - Return the specified argument. + Expr *getArg(unsigned Arg) { + assert(Arg < NumArgs && "Arg access out of range!"); + return getArgs()[Arg]; + } + const Expr *getArg(unsigned Arg) const { + assert(Arg < NumArgs && "Arg access out of range!"); + return getArgs()[Arg]; + } + + /// setArg - Set the specified argument. + void setArg(unsigned Arg, Expr *ArgExpr) { + assert(Arg < NumArgs && "Arg access out of range!"); + getArgs()[Arg] = ArgExpr; + } + + /// 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; } + + SourceLocation getLeftLoc() const { return LBracLoc; } + SourceLocation getRightLoc() const { return RBracLoc; } + + SourceLocation getSelectorStartLoc() const { + if (isImplicit()) + return getBeginLoc(); + return getSelectorLoc(0); + } + + SourceLocation getSelectorLoc(unsigned Index) const { + assert(Index < getNumSelectorLocs() && "Index out of range!"); + if (hasStandardSelLocs()) + return getStandardSelectorLoc( + Index, getSelector(), getSelLocsKind() == SelLoc_StandardWithSpace, + llvm::ArrayRef(const_cast<Expr **>(getArgs()), getNumArgs()), + RBracLoc); + return getStoredSelLocs()[Index]; + } + + void getSelectorLocs(SmallVectorImpl<SourceLocation> &SelLocs) const; + + unsigned getNumSelectorLocs() const { + if (isImplicit()) + return 0; + Selector Sel = getSelector(); + if (Sel.isUnarySelector()) + return 1; + return Sel.getNumArgs(); + } + + void setSourceRange(SourceRange R) { + LBracLoc = R.getBegin(); + RBracLoc = R.getEnd(); + } + + SourceLocation getBeginLoc() const LLVM_READONLY { return LBracLoc; } + SourceLocation getEndLoc() const LLVM_READONLY { return RBracLoc; } + + // Iterators + child_range children(); + + const_child_range children() const; + + using arg_iterator = ExprIterator; + using const_arg_iterator = ConstExprIterator; + + llvm::iterator_range<arg_iterator> arguments() { + return llvm::make_range(arg_begin(), arg_end()); + } + + llvm::iterator_range<const_arg_iterator> arguments() const { + return llvm::make_range(arg_begin(), arg_end()); + } + + 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); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == ObjCMessageExprClass; + } +}; + +/// ObjCIsaExpr - Represent X->isa and X.isa when X is an ObjC 'id' type. +/// (similar in spirit to MemberExpr). +class ObjCIsaExpr : public Expr { + /// Base - the expression for the base object pointer. + Stmt *Base; + + /// IsaMemberLoc - This is the location of the 'isa'. + SourceLocation IsaMemberLoc; + + /// OpLoc - This is the location of '.' or '->' + SourceLocation OpLoc; + + /// IsArrow - True if this is "X->F", false if this is "X.F". + bool IsArrow; + +public: + ObjCIsaExpr(Expr *base, bool isarrow, SourceLocation l, SourceLocation oploc, + QualType ty) + : Expr(ObjCIsaExprClass, ty, VK_LValue, OK_Ordinary), Base(base), + IsaMemberLoc(l), OpLoc(oploc), IsArrow(isarrow) { + setDependence(computeDependence(this)); + } + + /// 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; } + + SourceLocation getOpLoc() const { return OpLoc; } + void setOpLoc(SourceLocation L) { OpLoc = L; } + + SourceLocation getBeginLoc() const LLVM_READONLY { + return getBase()->getBeginLoc(); + } + + SourceLocation getBaseLocEnd() const LLVM_READONLY { + return getBase()->getEndLoc(); + } + + SourceLocation getEndLoc() const LLVM_READONLY { return IsaMemberLoc; } + + SourceLocation getExprLoc() const LLVM_READONLY { return IsaMemberLoc; } + + // Iterators + child_range children() { return child_range(&Base, &Base+1); } + + const_child_range children() const { + return const_child_range(&Base, &Base + 1); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == ObjCIsaExprClass; + } +}; + +/// 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 { + friend class ASTReader; + friend class ASTStmtReader; + + Stmt *Operand; + + // unsigned ObjCIndirectCopyRestoreBits.ShouldCopy : 1; + + explicit ObjCIndirectCopyRestoreExpr(EmptyShell Empty) + : Expr(ObjCIndirectCopyRestoreExprClass, Empty) {} + + void setShouldCopy(bool shouldCopy) { + ObjCIndirectCopyRestoreExprBits.ShouldCopy = shouldCopy; + } + +public: + ObjCIndirectCopyRestoreExpr(Expr *operand, QualType type, bool shouldCopy) + : Expr(ObjCIndirectCopyRestoreExprClass, type, VK_LValue, OK_Ordinary), + Operand(operand) { + setShouldCopy(shouldCopy); + setDependence(computeDependence(this)); + } + + 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); } + + const_child_range children() const { + return const_child_range(&Operand, &Operand + 1); + } + + // Source locations are determined by the subexpression. + SourceLocation getBeginLoc() const LLVM_READONLY { + return Operand->getBeginLoc(); + } + SourceLocation getEndLoc() const LLVM_READONLY { + return Operand->getEndLoc(); + } + + SourceLocation getExprLoc() const LLVM_READONLY { + return getSubExpr()->getExprLoc(); + } + + static bool classof(const Stmt *s) { + return s->getStmtClass() == ObjCIndirectCopyRestoreExprClass; + } +}; + +/// 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 final + : public ExplicitCastExpr, + private llvm::TrailingObjects<ObjCBridgedCastExpr, CXXBaseSpecifier *> { + friend class ASTStmtReader; + friend class ASTStmtWriter; + friend class CastExpr; + friend TrailingObjects; + + SourceLocation LParenLoc; + SourceLocation BridgeKeywordLoc; + unsigned Kind : 2; + +public: + ObjCBridgedCastExpr(SourceLocation LParenLoc, ObjCBridgeCastKind Kind, + CastKind CK, SourceLocation BridgeKeywordLoc, + TypeSourceInfo *TSInfo, Expr *Operand) + : ExplicitCastExpr(ObjCBridgedCastExprClass, TSInfo->getType(), + VK_PRValue, CK, Operand, 0, false, TSInfo), + LParenLoc(LParenLoc), BridgeKeywordLoc(BridgeKeywordLoc), Kind(Kind) {} + + /// Construct an empty Objective-C bridged cast. + explicit ObjCBridgedCastExpr(EmptyShell Shell) + : ExplicitCastExpr(ObjCBridgedCastExprClass, Shell, 0, false) {} + + SourceLocation getLParenLoc() const { return LParenLoc; } + + /// Determine which kind of bridge is being performed via this cast. + ObjCBridgeCastKind getBridgeKind() const { + return static_cast<ObjCBridgeCastKind>(Kind); + } + + /// Retrieve the kind of bridge being performed as a string. + StringRef getBridgeKindName() const; + + /// The location of the bridge keyword. + SourceLocation getBridgeKeywordLoc() const { return BridgeKeywordLoc; } + + SourceLocation getBeginLoc() const LLVM_READONLY { return LParenLoc; } + + SourceLocation getEndLoc() const LLVM_READONLY { + return getSubExpr()->getEndLoc(); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == ObjCBridgedCastExprClass; + } +}; + +/// A runtime availability query. +/// +/// There are 2 ways to spell this node: +/// \code +/// @available(macos 10.10, ios 8, *); // Objective-C +/// __builtin_available(macos 10.10, ios 8, *); // C, C++, and Objective-C +/// \endcode +/// +/// Note that we only need to keep track of one \c VersionTuple here, which is +/// the one that corresponds to the current deployment target. This is meant to +/// be used in the condition of an \c if, but it is also usable as top level +/// expressions. +/// +class ObjCAvailabilityCheckExpr : public Expr { + friend class ASTStmtReader; + + VersionTuple VersionToCheck; + SourceLocation AtLoc, RParen; + +public: + ObjCAvailabilityCheckExpr(VersionTuple VersionToCheck, SourceLocation AtLoc, + SourceLocation RParen, QualType Ty) + : Expr(ObjCAvailabilityCheckExprClass, Ty, VK_PRValue, OK_Ordinary), + VersionToCheck(VersionToCheck), AtLoc(AtLoc), RParen(RParen) { + setDependence(ExprDependence::None); + } + + explicit ObjCAvailabilityCheckExpr(EmptyShell Shell) + : Expr(ObjCAvailabilityCheckExprClass, Shell) {} + + SourceLocation getBeginLoc() const { return AtLoc; } + SourceLocation getEndLoc() const { return RParen; } + SourceRange getSourceRange() const { return {AtLoc, RParen}; } + + /// This may be '*', in which case this should fold to true. + bool hasVersion() const { return !VersionToCheck.empty(); } + VersionTuple getVersion() const { return VersionToCheck; } + + child_range children() { + return child_range(child_iterator(), child_iterator()); + } + + const_child_range children() const { + return const_child_range(const_child_iterator(), const_child_iterator()); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == ObjCAvailabilityCheckExprClass; + } +}; + +} // namespace clang + +#endif // LLVM_CLANG_AST_EXPROBJC_H + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif |