blob: 7f98f005feb7487243e5a5021c8ad34643bce4b5 [file] [log] [blame]
//===--- Expr.h - Classes for representing 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 Expr interface and subclasses.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_EXPR_H
#define LLVM_CLANG_AST_EXPR_H
#include "clang/AST/APValue.h"
#include "clang/AST/ASTVector.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclAccessPair.h"
#include "clang/AST/OperationKinds.h"
#include "clang/AST/Stmt.h"
#include "clang/AST/TemplateBase.h"
#include "clang/AST/Type.h"
#include "clang/Basic/CharInfo.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/TypeTraits.h"
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/AtomicOrdering.h"
#include "llvm/Support/Compiler.h"
namespace clang {
class APValue;
class ASTContext;
class BlockDecl;
class CXXBaseSpecifier;
class CXXMemberCallExpr;
class CXXOperatorCallExpr;
class CastExpr;
class Decl;
class IdentifierInfo;
class MaterializeTemporaryExpr;
class NamedDecl;
class ObjCPropertyRefExpr;
class OpaqueValueExpr;
class ParmVarDecl;
class StringLiteral;
class TargetInfo;
class ValueDecl;
/// \brief A simple array of base specifiers.
typedef SmallVector<CXXBaseSpecifier*, 4> CXXCastPath;
/// \brief An adjustment to be made to the temporary created when emitting a
/// reference binding, which accesses a particular subobject of that temporary.
struct SubobjectAdjustment {
enum {
DerivedToBaseAdjustment,
FieldAdjustment,
MemberPointerAdjustment
} Kind;
struct DTB {
const CastExpr *BasePath;
const CXXRecordDecl *DerivedClass;
};
struct P {
const MemberPointerType *MPT;
Expr *RHS;
};
union {
struct DTB DerivedToBase;
FieldDecl *Field;
struct P Ptr;
};
SubobjectAdjustment(const CastExpr *BasePath,
const CXXRecordDecl *DerivedClass)
: Kind(DerivedToBaseAdjustment) {
DerivedToBase.BasePath = BasePath;
DerivedToBase.DerivedClass = DerivedClass;
}
SubobjectAdjustment(FieldDecl *Field)
: Kind(FieldAdjustment) {
this->Field = Field;
}
SubobjectAdjustment(const MemberPointerType *MPT, Expr *RHS)
: Kind(MemberPointerAdjustment) {
this->Ptr.MPT = MPT;
this->Ptr.RHS = RHS;
}
};
/// Expr - This represents one expression. Note that Expr's are subclasses of
/// Stmt. This allows an expression to be transparently used any place a Stmt
/// is required.
///
class Expr : public Stmt {
QualType TR;
protected:
Expr(StmtClass SC, QualType T, ExprValueKind VK, ExprObjectKind OK,
bool TD, bool VD, bool ID, bool ContainsUnexpandedParameterPack)
: Stmt(SC)
{
ExprBits.TypeDependent = TD;
ExprBits.ValueDependent = VD;
ExprBits.InstantiationDependent = ID;
ExprBits.ValueKind = VK;
ExprBits.ObjectKind = OK;
ExprBits.ContainsUnexpandedParameterPack = ContainsUnexpandedParameterPack;
setType(T);
}
/// \brief Construct an empty expression.
explicit Expr(StmtClass SC, EmptyShell) : Stmt(SC) { }
public:
QualType getType() const { return TR; }
void setType(QualType t) {
// In C++, the type of an expression is always adjusted so that it
// will not have reference type (C++ [expr]p6). Use
// QualType::getNonReferenceType() to retrieve the non-reference
// type. Additionally, inspect Expr::isLvalue to determine whether
// an expression that is adjusted in this manner should be
// considered an lvalue.
assert((t.isNull() || !t->isReferenceType()) &&
"Expressions can't have reference type");
TR = t;
}
/// isValueDependent - Determines whether this expression is
/// value-dependent (C++ [temp.dep.constexpr]). For example, the
/// array bound of "Chars" in the following example is
/// value-dependent.
/// @code
/// template<int Size, char (&Chars)[Size]> struct meta_string;
/// @endcode
bool isValueDependent() const { return ExprBits.ValueDependent; }
/// \brief Set whether this expression is value-dependent or not.
void setValueDependent(bool VD) {
ExprBits.ValueDependent = VD;
}
/// isTypeDependent - Determines whether this expression is
/// type-dependent (C++ [temp.dep.expr]), which means that its type
/// could change from one template instantiation to the next. For
/// example, the expressions "x" and "x + y" are type-dependent in
/// the following code, but "y" is not type-dependent:
/// @code
/// template<typename T>
/// void add(T x, int y) {
/// x + y;
/// }
/// @endcode
bool isTypeDependent() const { return ExprBits.TypeDependent; }
/// \brief Set whether this expression is type-dependent or not.
void setTypeDependent(bool TD) {
ExprBits.TypeDependent = TD;
}
/// \brief Whether this expression is instantiation-dependent, meaning that
/// it depends in some way on a template parameter, even if neither its type
/// nor (constant) value can change due to the template instantiation.
///
/// In the following example, the expression \c sizeof(sizeof(T() + T())) is
/// instantiation-dependent (since it involves a template parameter \c T), but
/// is neither type- nor value-dependent, since the type of the inner
/// \c sizeof is known (\c std::size_t) and therefore the size of the outer
/// \c sizeof is known.
///
/// \code
/// template<typename T>
/// void f(T x, T y) {
/// sizeof(sizeof(T() + T());
/// }
/// \endcode
///
bool isInstantiationDependent() const {
return ExprBits.InstantiationDependent;
}
/// \brief Set whether this expression is instantiation-dependent or not.
void setInstantiationDependent(bool ID) {
ExprBits.InstantiationDependent = ID;
}
/// \brief Whether this expression contains an unexpanded parameter
/// pack (for C++11 variadic templates).
///
/// Given the following function template:
///
/// \code
/// template<typename F, typename ...Types>
/// void forward(const F &f, Types &&...args) {
/// f(static_cast<Types&&>(args)...);
/// }
/// \endcode
///
/// The expressions \c args and \c static_cast<Types&&>(args) both
/// contain parameter packs.
bool containsUnexpandedParameterPack() const {
return ExprBits.ContainsUnexpandedParameterPack;
}
/// \brief Set the bit that describes whether this expression
/// contains an unexpanded parameter pack.
void setContainsUnexpandedParameterPack(bool PP = true) {
ExprBits.ContainsUnexpandedParameterPack = PP;
}
/// getExprLoc - Return the preferred location for the arrow when diagnosing
/// a problem with a generic expression.
SourceLocation getExprLoc() const LLVM_READONLY;
/// isUnusedResultAWarning - Return true if this immediate expression should
/// be warned about if the result is unused. If so, fill in expr, location,
/// and ranges with expr to warn on and source locations/ranges appropriate
/// for a warning.
bool isUnusedResultAWarning(const Expr *&WarnExpr, SourceLocation &Loc,
SourceRange &R1, SourceRange &R2,
ASTContext &Ctx) const;
/// isLValue - True if this expression is an "l-value" according to
/// the rules of the current language. C and C++ give somewhat
/// different rules for this concept, but in general, the result of
/// an l-value expression identifies a specific object whereas the
/// result of an r-value expression is a value detached from any
/// specific storage.
///
/// C++11 divides the concept of "r-value" into pure r-values
/// ("pr-values") and so-called expiring values ("x-values"), which
/// identify specific objects that can be safely cannibalized for
/// their resources. This is an unfortunate abuse of terminology on
/// the part of the C++ committee. In Clang, when we say "r-value",
/// we generally mean a pr-value.
bool isLValue() const { return getValueKind() == VK_LValue; }
bool isRValue() const { return getValueKind() == VK_RValue; }
bool isXValue() const { return getValueKind() == VK_XValue; }
bool isGLValue() const { return getValueKind() != VK_RValue; }
enum LValueClassification {
LV_Valid,
LV_NotObjectType,
LV_IncompleteVoidType,
LV_DuplicateVectorComponents,
LV_InvalidExpression,
LV_InvalidMessageExpression,
LV_MemberFunction,
LV_SubObjCPropertySetting,
LV_ClassTemporary,
LV_ArrayTemporary
};
/// Reasons why an expression might not be an l-value.
LValueClassification ClassifyLValue(ASTContext &Ctx) const;
enum isModifiableLvalueResult {
MLV_Valid,
MLV_NotObjectType,
MLV_IncompleteVoidType,
MLV_DuplicateVectorComponents,
MLV_InvalidExpression,
MLV_LValueCast, // Specialized form of MLV_InvalidExpression.
MLV_IncompleteType,
MLV_ConstQualified,
MLV_ConstAddrSpace,
MLV_ArrayType,
MLV_NoSetterProperty,
MLV_MemberFunction,
MLV_SubObjCPropertySetting,
MLV_InvalidMessageExpression,
MLV_ClassTemporary,
MLV_ArrayTemporary
};
/// isModifiableLvalue - C99 6.3.2.1: an lvalue that does not have array type,
/// does not have an incomplete type, does not have a const-qualified type,
/// and if it is a structure or union, does not have any member (including,
/// recursively, any member or element of all contained aggregates or unions)
/// with a const-qualified type.
///
/// \param Loc [in,out] - A source location which *may* be filled
/// in with the location of the expression making this a
/// non-modifiable lvalue, if specified.
isModifiableLvalueResult
isModifiableLvalue(ASTContext &Ctx, SourceLocation *Loc = nullptr) const;
/// \brief The return type of classify(). Represents the C++11 expression
/// taxonomy.
class Classification {
public:
/// \brief The various classification results. Most of these mean prvalue.
enum Kinds {
CL_LValue,
CL_XValue,
CL_Function, // Functions cannot be lvalues in C.
CL_Void, // Void cannot be an lvalue in C.
CL_AddressableVoid, // Void expression whose address can be taken in C.
CL_DuplicateVectorComponents, // A vector shuffle with dupes.
CL_MemberFunction, // An expression referring to a member function
CL_SubObjCPropertySetting,
CL_ClassTemporary, // A temporary of class type, or subobject thereof.
CL_ArrayTemporary, // A temporary of array type.
CL_ObjCMessageRValue, // ObjC message is an rvalue
CL_PRValue // A prvalue for any other reason, of any other type
};
/// \brief The results of modification testing.
enum ModifiableType {
CM_Untested, // testModifiable was false.
CM_Modifiable,
CM_RValue, // Not modifiable because it's an rvalue
CM_Function, // Not modifiable because it's a function; C++ only
CM_LValueCast, // Same as CM_RValue, but indicates GCC cast-as-lvalue ext
CM_NoSetterProperty,// Implicit assignment to ObjC property without setter
CM_ConstQualified,
CM_ConstAddrSpace,
CM_ArrayType,
CM_IncompleteType
};
private:
friend class Expr;
unsigned short Kind;
unsigned short Modifiable;
explicit Classification(Kinds k, ModifiableType m)
: Kind(k), Modifiable(m)
{}
public:
Classification() {}
Kinds getKind() const { return static_cast<Kinds>(Kind); }
ModifiableType getModifiable() const {
assert(Modifiable != CM_Untested && "Did not test for modifiability.");
return static_cast<ModifiableType>(Modifiable);
}
bool isLValue() const { return Kind == CL_LValue; }
bool isXValue() const { return Kind == CL_XValue; }
bool isGLValue() const { return Kind <= CL_XValue; }
bool isPRValue() const { return Kind >= CL_Function; }
bool isRValue() const { return Kind >= CL_XValue; }
bool isModifiable() const { return getModifiable() == CM_Modifiable; }
/// \brief Create a simple, modifiably lvalue
static Classification makeSimpleLValue() {
return Classification(CL_LValue, CM_Modifiable);
}
};
/// \brief Classify - Classify this expression according to the C++11
/// expression taxonomy.
///
/// C++11 defines ([basic.lval]) a new taxonomy of expressions to replace the
/// old lvalue vs rvalue. This function determines the type of expression this
/// is. There are three expression types:
/// - lvalues are classical lvalues as in C++03.
/// - prvalues are equivalent to rvalues in C++03.
/// - xvalues are expressions yielding unnamed rvalue references, e.g. a
/// function returning an rvalue reference.
/// lvalues and xvalues are collectively referred to as glvalues, while
/// prvalues and xvalues together form rvalues.
Classification Classify(ASTContext &Ctx) const {
return ClassifyImpl(Ctx, nullptr);
}
/// \brief ClassifyModifiable - Classify this expression according to the
/// C++11 expression taxonomy, and see if it is valid on the left side
/// of an assignment.
///
/// This function extends classify in that it also tests whether the
/// expression is modifiable (C99 6.3.2.1p1).
/// \param Loc A source location that might be filled with a relevant location
/// if the expression is not modifiable.
Classification ClassifyModifiable(ASTContext &Ctx, SourceLocation &Loc) const{
return ClassifyImpl(Ctx, &Loc);
}
/// getValueKindForType - Given a formal return or parameter type,
/// give its value kind.
static ExprValueKind getValueKindForType(QualType T) {
if (const ReferenceType *RT = T->getAs<ReferenceType>())
return (isa<LValueReferenceType>(RT)
? VK_LValue
: (RT->getPointeeType()->isFunctionType()
? VK_LValue : VK_XValue));
return VK_RValue;
}
/// getValueKind - The value kind that this expression produces.
ExprValueKind getValueKind() const {
return static_cast<ExprValueKind>(ExprBits.ValueKind);
}
/// getObjectKind - The object kind that this expression produces.
/// Object kinds are meaningful only for expressions that yield an
/// l-value or x-value.
ExprObjectKind getObjectKind() const {
return static_cast<ExprObjectKind>(ExprBits.ObjectKind);
}
bool isOrdinaryOrBitFieldObject() const {
ExprObjectKind OK = getObjectKind();
return (OK == OK_Ordinary || OK == OK_BitField);
}
/// setValueKind - Set the value kind produced by this expression.
void setValueKind(ExprValueKind Cat) { ExprBits.ValueKind = Cat; }
/// setObjectKind - Set the object kind produced by this expression.
void setObjectKind(ExprObjectKind Cat) { ExprBits.ObjectKind = Cat; }
private:
Classification ClassifyImpl(ASTContext &Ctx, SourceLocation *Loc) const;
public:
/// \brief Returns true if this expression is a gl-value that
/// potentially refers to a bit-field.
///
/// In C++, whether a gl-value refers to a bitfield is essentially
/// an aspect of the value-kind type system.
bool refersToBitField() const { return getObjectKind() == OK_BitField; }
/// \brief If this expression refers to a bit-field, retrieve the
/// declaration of that bit-field.
///
/// Note that this returns a non-null pointer in subtly different
/// places than refersToBitField returns true. In particular, this can
/// return a non-null pointer even for r-values loaded from
/// bit-fields, but it will return null for a conditional bit-field.
FieldDecl *getSourceBitField();
const FieldDecl *getSourceBitField() const {
return const_cast<Expr*>(this)->getSourceBitField();
}
/// \brief If this expression is an l-value for an Objective C
/// property, find the underlying property reference expression.
const ObjCPropertyRefExpr *getObjCProperty() const;
/// \brief Check if this expression is the ObjC 'self' implicit parameter.
bool isObjCSelfExpr() const;
/// \brief Returns whether this expression refers to a vector element.
bool refersToVectorElement() const;
/// \brief Returns whether this expression refers to a global register
/// variable.
bool refersToGlobalRegisterVar() const;
/// \brief Returns whether this expression has a placeholder type.
bool hasPlaceholderType() const {
return getType()->isPlaceholderType();
}
/// \brief Returns whether this expression has a specific placeholder type.
bool hasPlaceholderType(BuiltinType::Kind K) const {
assert(BuiltinType::isPlaceholderTypeKind(K));
if (const BuiltinType *BT = dyn_cast<BuiltinType>(getType()))
return BT->getKind() == K;
return false;
}
/// isKnownToHaveBooleanValue - Return true if this is an integer expression
/// that is known to return 0 or 1. This happens for _Bool/bool expressions
/// but also int expressions which are produced by things like comparisons in
/// C.
bool isKnownToHaveBooleanValue() const;
/// isIntegerConstantExpr - Return true if this expression is a valid integer
/// constant expression, and, if so, return its value in Result. If not a
/// valid i-c-e, return false and fill in Loc (if specified) with the location
/// of the invalid expression.
///
/// Note: This does not perform the implicit conversions required by C++11
/// [expr.const]p5.
bool isIntegerConstantExpr(llvm::APSInt &Result, const ASTContext &Ctx,
SourceLocation *Loc = nullptr,
bool isEvaluated = true) const;
bool isIntegerConstantExpr(const ASTContext &Ctx,
SourceLocation *Loc = nullptr) const;
/// isCXX98IntegralConstantExpr - Return true if this expression is an
/// integral constant expression in C++98. Can only be used in C++.
bool isCXX98IntegralConstantExpr(const ASTContext &Ctx) const;
/// isCXX11ConstantExpr - Return true if this expression is a constant
/// expression in C++11. Can only be used in C++.
///
/// Note: This does not perform the implicit conversions required by C++11
/// [expr.const]p5.
bool isCXX11ConstantExpr(const ASTContext &Ctx, APValue *Result = nullptr,
SourceLocation *Loc = nullptr) const;
/// isPotentialConstantExpr - Return true if this function's definition
/// might be usable in a constant expression in C++11, if it were marked
/// constexpr. Return false if the function can never produce a constant
/// expression, along with diagnostics describing why not.
static bool isPotentialConstantExpr(const FunctionDecl *FD,
SmallVectorImpl<
PartialDiagnosticAt> &Diags);
/// isPotentialConstantExprUnevaluted - Return true if this expression might
/// be usable in a constant expression in C++11 in an unevaluated context, if
/// it were in function FD marked constexpr. Return false if the function can
/// never produce a constant expression, along with diagnostics describing
/// why not.
static bool isPotentialConstantExprUnevaluated(Expr *E,
const FunctionDecl *FD,
SmallVectorImpl<
PartialDiagnosticAt> &Diags);
/// isConstantInitializer - Returns true if this expression can be emitted to
/// IR as a constant, and thus can be used as a constant initializer in C.
/// If this expression is not constant and Culprit is non-null,
/// it is used to store the address of first non constant expr.
bool isConstantInitializer(ASTContext &Ctx, bool ForRef,
const Expr **Culprit = nullptr) const;
/// EvalStatus is a struct with detailed info about an evaluation in progress.
struct EvalStatus {
/// \brief Whether the evaluated expression has side effects.
/// For example, (f() && 0) can be folded, but it still has side effects.
bool HasSideEffects;
/// \brief Whether the evaluation hit undefined behavior.
/// For example, 1.0 / 0.0 can be folded to Inf, but has undefined behavior.
/// Likewise, INT_MAX + 1 can be folded to INT_MIN, but has UB.
bool HasUndefinedBehavior;
/// Diag - If this is non-null, it will be filled in with a stack of notes
/// indicating why evaluation failed (or why it failed to produce a constant
/// expression).
/// If the expression is unfoldable, the notes will indicate why it's not
/// foldable. If the expression is foldable, but not a constant expression,
/// the notes will describes why it isn't a constant expression. If the
/// expression *is* a constant expression, no notes will be produced.
SmallVectorImpl<PartialDiagnosticAt> *Diag;
EvalStatus()
: HasSideEffects(false), HasUndefinedBehavior(false), Diag(nullptr) {}
// hasSideEffects - Return true if the evaluated expression has
// side effects.
bool hasSideEffects() const {
return HasSideEffects;
}
};
/// EvalResult is a struct with detailed info about an evaluated expression.
struct EvalResult : EvalStatus {
/// Val - This is the value the expression can be folded to.
APValue Val;
// isGlobalLValue - Return true if the evaluated lvalue expression
// is global.
bool isGlobalLValue() const;
};
/// EvaluateAsRValue - Return true if this is a constant which we can fold to
/// an rvalue using any crazy technique (that has nothing to do with language
/// standards) that we want to, even if the expression has side-effects. If
/// this function returns true, it returns the folded constant in Result. If
/// the expression is a glvalue, an lvalue-to-rvalue conversion will be
/// applied.
bool EvaluateAsRValue(EvalResult &Result, const ASTContext &Ctx) const;
/// EvaluateAsBooleanCondition - Return true if this is a constant
/// which we we can fold and convert to a boolean condition using
/// any crazy technique that we want to, even if the expression has
/// side-effects.
bool EvaluateAsBooleanCondition(bool &Result, const ASTContext &Ctx) const;
enum SideEffectsKind {
SE_NoSideEffects, ///< Strictly evaluate the expression.
SE_AllowUndefinedBehavior, ///< Allow UB that we can give a value, but not
///< arbitrary unmodeled side effects.
SE_AllowSideEffects ///< Allow any unmodeled side effect.
};
/// EvaluateAsInt - Return true if this is a constant which we can fold and
/// convert to an integer, using any crazy technique that we want to.
bool EvaluateAsInt(llvm::APSInt &Result, const ASTContext &Ctx,
SideEffectsKind AllowSideEffects = SE_NoSideEffects) const;
/// EvaluateAsFloat - Return true if this is a constant which we can fold and
/// convert to a floating point value, using any crazy technique that we
/// want to.
bool
EvaluateAsFloat(llvm::APFloat &Result, const ASTContext &Ctx,
SideEffectsKind AllowSideEffects = SE_NoSideEffects) const;
/// isEvaluatable - Call EvaluateAsRValue to see if this expression can be
/// constant folded without side-effects, but discard the result.
bool isEvaluatable(const ASTContext &Ctx,
SideEffectsKind AllowSideEffects = SE_NoSideEffects) const;
/// HasSideEffects - This routine returns true for all those expressions
/// which have any effect other than producing a value. Example is a function
/// call, volatile variable read, or throwing an exception. If
/// IncludePossibleEffects is false, this call treats certain expressions with
/// potential side effects (such as function call-like expressions,
/// instantiation-dependent expressions, or invocations from a macro) as not
/// having side effects.
bool HasSideEffects(const ASTContext &Ctx,
bool IncludePossibleEffects = true) const;
/// \brief Determine whether this expression involves a call to any function
/// that is not trivial.
bool hasNonTrivialCall(const ASTContext &Ctx) const;
/// EvaluateKnownConstInt - Call EvaluateAsRValue and return the folded
/// integer. This must be called on an expression that constant folds to an
/// integer.
llvm::APSInt EvaluateKnownConstInt(const ASTContext &Ctx,
SmallVectorImpl<PartialDiagnosticAt> *Diag = nullptr) const;
void EvaluateForOverflow(const ASTContext &Ctx) const;
/// EvaluateAsLValue - Evaluate an expression to see if we can fold it to an
/// lvalue with link time known address, with no side-effects.
bool EvaluateAsLValue(EvalResult &Result, const ASTContext &Ctx) const;
/// EvaluateAsInitializer - Evaluate an expression as if it were the
/// initializer of the given declaration. Returns true if the initializer
/// can be folded to a constant, and produces any relevant notes. In C++11,
/// notes will be produced if the expression is not a constant expression.
bool EvaluateAsInitializer(APValue &Result, const ASTContext &Ctx,
const VarDecl *VD,
SmallVectorImpl<PartialDiagnosticAt> &Notes) const;
/// EvaluateWithSubstitution - Evaluate an expression as if from the context
/// of a call to the given function with the given arguments, inside an
/// unevaluated context. Returns true if the expression could be folded to a
/// constant.
bool EvaluateWithSubstitution(APValue &Value, ASTContext &Ctx,
const FunctionDecl *Callee,
ArrayRef<const Expr*> Args) const;
/// \brief If the current Expr is a pointer, this will try to statically
/// determine the number of bytes available where the pointer is pointing.
/// Returns true if all of the above holds and we were able to figure out the
/// size, false otherwise.
///
/// \param Type - How to evaluate the size of the Expr, as defined by the
/// "type" parameter of __builtin_object_size
bool tryEvaluateObjectSize(uint64_t &Result, ASTContext &Ctx,
unsigned Type) const;
/// \brief Enumeration used to describe the kind of Null pointer constant
/// returned from \c isNullPointerConstant().
enum NullPointerConstantKind {
/// \brief Expression is not a Null pointer constant.
NPCK_NotNull = 0,
/// \brief Expression is a Null pointer constant built from a zero integer
/// expression that is not a simple, possibly parenthesized, zero literal.
/// C++ Core Issue 903 will classify these expressions as "not pointers"
/// once it is adopted.
/// http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#903
NPCK_ZeroExpression,
/// \brief Expression is a Null pointer constant built from a literal zero.
NPCK_ZeroLiteral,
/// \brief Expression is a C++11 nullptr.
NPCK_CXX11_nullptr,
/// \brief Expression is a GNU-style __null constant.
NPCK_GNUNull
};
/// \brief Enumeration used to describe how \c isNullPointerConstant()
/// should cope with value-dependent expressions.
enum NullPointerConstantValueDependence {
/// \brief Specifies that the expression should never be value-dependent.
NPC_NeverValueDependent = 0,
/// \brief Specifies that a value-dependent expression of integral or
/// dependent type should be considered a null pointer constant.
NPC_ValueDependentIsNull,
/// \brief Specifies that a value-dependent expression should be considered
/// to never be a null pointer constant.
NPC_ValueDependentIsNotNull
};
/// isNullPointerConstant - C99 6.3.2.3p3 - Test if this reduces down to
/// a Null pointer constant. The return value can further distinguish the
/// kind of NULL pointer constant that was detected.
NullPointerConstantKind isNullPointerConstant(
ASTContext &Ctx,
NullPointerConstantValueDependence NPC) const;
/// isOBJCGCCandidate - Return true if this expression may be used in a read/
/// write barrier.
bool isOBJCGCCandidate(ASTContext &Ctx) const;
/// \brief Returns true if this expression is a bound member function.
bool isBoundMemberFunction(ASTContext &Ctx) const;
/// \brief Given an expression of bound-member type, find the type
/// of the member. Returns null if this is an *overloaded* bound
/// member expression.
static QualType findBoundMemberType(const Expr *expr);
/// IgnoreImpCasts - Skip past any implicit casts which might
/// surround this expression. Only skips ImplicitCastExprs.
Expr *IgnoreImpCasts() LLVM_READONLY;
/// IgnoreImplicit - Skip past any implicit AST nodes which might
/// surround this expression.
Expr *IgnoreImplicit() LLVM_READONLY {
return cast<Expr>(Stmt::IgnoreImplicit());
}
const Expr *IgnoreImplicit() const LLVM_READONLY {
return const_cast<Expr*>(this)->IgnoreImplicit();
}
/// IgnoreParens - Ignore parentheses. If this Expr is a ParenExpr, return
/// its subexpression. If that subexpression is also a ParenExpr,
/// then this method recursively returns its subexpression, and so forth.
/// Otherwise, the method returns the current Expr.
Expr *IgnoreParens() LLVM_READONLY;
/// IgnoreParenCasts - Ignore parentheses and casts. Strip off any ParenExpr
/// or CastExprs, returning their operand.
Expr *IgnoreParenCasts() LLVM_READONLY;
/// Ignore casts. Strip off any CastExprs, returning their operand.
Expr *IgnoreCasts() LLVM_READONLY;
/// IgnoreParenImpCasts - Ignore parentheses and implicit casts. Strip off
/// any ParenExpr or ImplicitCastExprs, returning their operand.
Expr *IgnoreParenImpCasts() LLVM_READONLY;
/// IgnoreConversionOperator - Ignore conversion operator. If this Expr is a
/// call to a conversion operator, return the argument.
Expr *IgnoreConversionOperator() LLVM_READONLY;
const Expr *IgnoreConversionOperator() const LLVM_READONLY {
return const_cast<Expr*>(this)->IgnoreConversionOperator();
}
const Expr *IgnoreParenImpCasts() const LLVM_READONLY {
return const_cast<Expr*>(this)->IgnoreParenImpCasts();
}
/// Ignore parentheses and lvalue casts. Strip off any ParenExpr and
/// CastExprs that represent lvalue casts, returning their operand.
Expr *IgnoreParenLValueCasts() LLVM_READONLY;
const Expr *IgnoreParenLValueCasts() const LLVM_READONLY {
return const_cast<Expr*>(this)->IgnoreParenLValueCasts();
}
/// IgnoreParenNoopCasts - Ignore parentheses and casts that do not change the
/// value (including ptr->int casts of the same size). Strip off any
/// ParenExpr or CastExprs, returning their operand.
Expr *IgnoreParenNoopCasts(ASTContext &Ctx) LLVM_READONLY;
/// Ignore parentheses and derived-to-base casts.
Expr *ignoreParenBaseCasts() LLVM_READONLY;
const Expr *ignoreParenBaseCasts() const LLVM_READONLY {
return const_cast<Expr*>(this)->ignoreParenBaseCasts();
}
/// \brief Determine whether this expression is a default function argument.
///
/// Default arguments are implicitly generated in the abstract syntax tree
/// by semantic analysis for function calls, object constructions, etc. in
/// C++. Default arguments are represented by \c CXXDefaultArgExpr nodes;
/// this routine also looks through any implicit casts to determine whether
/// the expression is a default argument.
bool isDefaultArgument() const;
/// \brief Determine whether the result of this expression is a
/// temporary object of the given class type.
bool isTemporaryObject(ASTContext &Ctx, const CXXRecordDecl *TempTy) const;
/// \brief Whether this expression is an implicit reference to 'this' in C++.
bool isImplicitCXXThis() const;
const Expr *IgnoreImpCasts() const LLVM_READONLY {
return const_cast<Expr*>(this)->IgnoreImpCasts();
}
const Expr *IgnoreParens() const LLVM_READONLY {
return const_cast<Expr*>(this)->IgnoreParens();
}
const Expr *IgnoreParenCasts() const LLVM_READONLY {
return const_cast<Expr*>(this)->IgnoreParenCasts();
}
/// Strip off casts, but keep parentheses.
const Expr *IgnoreCasts() const LLVM_READONLY {
return const_cast<Expr*>(this)->IgnoreCasts();
}
const Expr *IgnoreParenNoopCasts(ASTContext &Ctx) const LLVM_READONLY {
return const_cast<Expr*>(this)->IgnoreParenNoopCasts(Ctx);
}
static bool hasAnyTypeDependentArguments(ArrayRef<Expr *> Exprs);
/// \brief For an expression of class type or pointer to class type,
/// return the most derived class decl the expression is known to refer to.
///
/// If this expression is a cast, this method looks through it to find the
/// most derived decl that can be inferred from the expression.
/// This is valid because derived-to-base conversions have undefined
/// behavior if the object isn't dynamically of the derived type.
const CXXRecordDecl *getBestDynamicClassType() const;
/// Walk outwards from an expression we want to bind a reference to and
/// find the expression whose lifetime needs to be extended. Record
/// the LHSs of comma expressions and adjustments needed along the path.
const Expr *skipRValueSubobjectAdjustments(
SmallVectorImpl<const Expr *> &CommaLHS,
SmallVectorImpl<SubobjectAdjustment> &Adjustments) const;
static bool classof(const Stmt *T) {
return T->getStmtClass() >= firstExprConstant &&
T->getStmtClass() <= lastExprConstant;
}
};
//===----------------------------------------------------------------------===//
// Primary Expressions.
//===----------------------------------------------------------------------===//
/// OpaqueValueExpr - An expression referring to an opaque object of a
/// fixed type and value class. These don't correspond to concrete
/// syntax; instead they're used to express operations (usually copy
/// operations) on values whose source is generally obvious from
/// context.
class OpaqueValueExpr : public Expr {
friend class ASTStmtReader;
Expr *SourceExpr;
SourceLocation Loc;
public:
OpaqueValueExpr(SourceLocation Loc, QualType T, ExprValueKind VK,
ExprObjectKind OK = OK_Ordinary,
Expr *SourceExpr = nullptr)
: Expr(OpaqueValueExprClass, T, VK, OK,
T->isDependentType() ||
(SourceExpr && SourceExpr->isTypeDependent()),
T->isDependentType() ||
(SourceExpr && SourceExpr->isValueDependent()),
T->isInstantiationDependentType() ||
(SourceExpr && SourceExpr->isInstantiationDependent()),
false),
SourceExpr(SourceExpr), Loc(Loc) {
}
/// Given an expression which invokes a copy constructor --- i.e. a
/// CXXConstructExpr, possibly wrapped in an ExprWithCleanups ---
/// find the OpaqueValueExpr that's the source of the construction.
static const OpaqueValueExpr *findInCopyConstruct(const Expr *expr);
explicit OpaqueValueExpr(EmptyShell Empty)
: Expr(OpaqueValueExprClass, Empty) { }
/// \brief Retrieve the location of this expression.
SourceLocation getLocation() const { return Loc; }
SourceLocation getLocStart() const LLVM_READONLY {
return SourceExpr ? SourceExpr->getLocStart() : Loc;
}
SourceLocation getLocEnd() const LLVM_READONLY {
return SourceExpr ? SourceExpr->getLocEnd() : Loc;
}
SourceLocation getExprLoc() const LLVM_READONLY {
if (SourceExpr) return SourceExpr->getExprLoc();
return Loc;
}
child_range children() {
return child_range(child_iterator(), child_iterator());
}
/// The source expression of an opaque value expression is the
/// expression which originally generated the value. This is
/// provided as a convenience for analyses that don't wish to
/// precisely model the execution behavior of the program.
///
/// The source expression is typically set when building the
/// expression which binds the opaque value expression in the first
/// place.
Expr *getSourceExpr() const { return SourceExpr; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == OpaqueValueExprClass;
}
};
/// \brief A reference to a declared variable, function, enum, etc.
/// [C99 6.5.1p2]
///
/// This encodes all the information about how a declaration is referenced
/// within an expression.
///
/// There are several optional constructs attached to DeclRefExprs only when
/// they apply in order to conserve memory. These are laid out past the end of
/// the object, and flags in the DeclRefExprBitfield track whether they exist:
///
/// DeclRefExprBits.HasQualifier:
/// Specifies when this declaration reference expression has a C++
/// nested-name-specifier.
/// DeclRefExprBits.HasFoundDecl:
/// Specifies when this declaration reference expression has a record of
/// a NamedDecl (different from the referenced ValueDecl) which was found
/// during name lookup and/or overload resolution.
/// DeclRefExprBits.HasTemplateKWAndArgsInfo:
/// Specifies when this declaration reference expression has an explicit
/// C++ template keyword and/or template argument list.
/// DeclRefExprBits.RefersToEnclosingVariableOrCapture
/// Specifies when this declaration reference expression (validly)
/// refers to an enclosed local or a captured variable.
class DeclRefExpr final
: public Expr,
private llvm::TrailingObjects<DeclRefExpr, NestedNameSpecifierLoc,
NamedDecl *, ASTTemplateKWAndArgsInfo,
TemplateArgumentLoc> {
/// \brief The declaration that we are referencing.
ValueDecl *D;
/// \brief The location of the declaration name itself.
SourceLocation Loc;
/// \brief Provides source/type location info for the declaration name
/// embedded in D.
DeclarationNameLoc DNLoc;
size_t numTrailingObjects(OverloadToken<NestedNameSpecifierLoc>) const {
return hasQualifier() ? 1 : 0;
}
size_t numTrailingObjects(OverloadToken<NamedDecl *>) const {
return hasFoundDecl() ? 1 : 0;
}
size_t numTrailingObjects(OverloadToken<ASTTemplateKWAndArgsInfo>) const {
return hasTemplateKWAndArgsInfo() ? 1 : 0;
}
/// \brief Test whether there is a distinct FoundDecl attached to the end of
/// this DRE.
bool hasFoundDecl() const { return DeclRefExprBits.HasFoundDecl; }
DeclRefExpr(const ASTContext &Ctx,
NestedNameSpecifierLoc QualifierLoc,
SourceLocation TemplateKWLoc,
ValueDecl *D, bool RefersToEnlosingVariableOrCapture,
const DeclarationNameInfo &NameInfo,
NamedDecl *FoundD,
const TemplateArgumentListInfo *TemplateArgs,
QualType T, ExprValueKind VK);
/// \brief Construct an empty declaration reference expression.
explicit DeclRefExpr(EmptyShell Empty)
: Expr(DeclRefExprClass, Empty) { }
/// \brief Computes the type- and value-dependence flags for this
/// declaration reference expression.
void computeDependence(const ASTContext &C);
public:
DeclRefExpr(ValueDecl *D, bool RefersToEnclosingVariableOrCapture, QualType T,
ExprValueKind VK, SourceLocation L,
const DeclarationNameLoc &LocInfo = DeclarationNameLoc())
: Expr(DeclRefExprClass, T, VK, OK_Ordinary, false, false, false, false),
D(D), Loc(L), DNLoc(LocInfo) {
DeclRefExprBits.HasQualifier = 0;
DeclRefExprBits.HasTemplateKWAndArgsInfo = 0;
DeclRefExprBits.HasFoundDecl = 0;
DeclRefExprBits.HadMultipleCandidates = 0;
DeclRefExprBits.RefersToEnclosingVariableOrCapture =
RefersToEnclosingVariableOrCapture;
computeDependence(D->getASTContext());
}
static DeclRefExpr *
Create(const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc,
SourceLocation TemplateKWLoc, ValueDecl *D,
bool RefersToEnclosingVariableOrCapture, SourceLocation NameLoc,
QualType T, ExprValueKind VK, NamedDecl *FoundD = nullptr,
const TemplateArgumentListInfo *TemplateArgs = nullptr);
static DeclRefExpr *
Create(const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc,
SourceLocation TemplateKWLoc, ValueDecl *D,
bool RefersToEnclosingVariableOrCapture,
const DeclarationNameInfo &NameInfo, QualType T, ExprValueKind VK,
NamedDecl *FoundD = nullptr,
const TemplateArgumentListInfo *TemplateArgs = nullptr);
/// \brief Construct an empty declaration reference expression.
static DeclRefExpr *CreateEmpty(const ASTContext &Context,
bool HasQualifier,
bool HasFoundDecl,
bool HasTemplateKWAndArgsInfo,
unsigned NumTemplateArgs);
ValueDecl *getDecl() { return D; }
const ValueDecl *getDecl() const { return D; }
void setDecl(ValueDecl *NewD) { D = NewD; }
DeclarationNameInfo getNameInfo() const {
return DeclarationNameInfo(getDecl()->getDeclName(), Loc, DNLoc);
}
SourceLocation getLocation() const { return Loc; }
void setLocation(SourceLocation L) { Loc = L; }
SourceLocation getLocStart() const LLVM_READONLY;
SourceLocation getLocEnd() const LLVM_READONLY;
/// \brief Determine whether this declaration reference was preceded by a
/// C++ nested-name-specifier, e.g., \c N::foo.
bool hasQualifier() const { return DeclRefExprBits.HasQualifier; }
/// \brief If the name was qualified, retrieves the nested-name-specifier
/// that precedes the name, with source-location information.
NestedNameSpecifierLoc getQualifierLoc() const {
if (!hasQualifier())
return NestedNameSpecifierLoc();
return *getTrailingObjects<NestedNameSpecifierLoc>();
}
/// \brief If the name was qualified, retrieves the nested-name-specifier
/// that precedes the name. Otherwise, returns NULL.
NestedNameSpecifier *getQualifier() const {
return getQualifierLoc().getNestedNameSpecifier();
}
/// \brief Get the NamedDecl through which this reference occurred.
///
/// This Decl may be different from the ValueDecl actually referred to in the
/// presence of using declarations, etc. It always returns non-NULL, and may
/// simple return the ValueDecl when appropriate.
NamedDecl *getFoundDecl() {
return hasFoundDecl() ? *getTrailingObjects<NamedDecl *>() : D;
}
/// \brief Get the NamedDecl through which this reference occurred.
/// See non-const variant.
const NamedDecl *getFoundDecl() const {
return hasFoundDecl() ? *getTrailingObjects<NamedDecl *>() : D;
}
bool hasTemplateKWAndArgsInfo() const {
return DeclRefExprBits.HasTemplateKWAndArgsInfo;
}
/// \brief Retrieve the location of the template keyword preceding
/// this name, if any.
SourceLocation getTemplateKeywordLoc() const {
if (!hasTemplateKWAndArgsInfo()) return SourceLocation();
return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->TemplateKWLoc;
}
/// \brief Retrieve the location of the left angle bracket starting the
/// explicit template argument list following the name, if any.
SourceLocation getLAngleLoc() const {
if (!hasTemplateKWAndArgsInfo()) return SourceLocation();
return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->LAngleLoc;
}
/// \brief Retrieve the location of the right angle bracket ending the
/// explicit template argument list following the name, if any.
SourceLocation getRAngleLoc() const {
if (!hasTemplateKWAndArgsInfo()) return SourceLocation();
return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->RAngleLoc;
}
/// \brief Determines whether the name in this declaration reference
/// was preceded by the template keyword.
bool hasTemplateKeyword() const { return getTemplateKeywordLoc().isValid(); }
/// \brief Determines whether this declaration reference was followed by an
/// explicit template argument list.
bool hasExplicitTemplateArgs() const { return getLAngleLoc().isValid(); }
/// \brief Copies the template arguments (if present) into the given
/// structure.
void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const {
if (hasExplicitTemplateArgs())
getTrailingObjects<ASTTemplateKWAndArgsInfo>()->copyInto(
getTrailingObjects<TemplateArgumentLoc>(), List);
}
/// \brief Retrieve the template arguments provided as part of this
/// template-id.
const TemplateArgumentLoc *getTemplateArgs() const {
if (!hasExplicitTemplateArgs())
return nullptr;
return getTrailingObjects<TemplateArgumentLoc>();
}
/// \brief Retrieve the number of template arguments provided as part of this
/// template-id.
unsigned getNumTemplateArgs() const {
if (!hasExplicitTemplateArgs())
return 0;
return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->NumTemplateArgs;
}
ArrayRef<TemplateArgumentLoc> template_arguments() const {
return {getTemplateArgs(), getNumTemplateArgs()};
}
/// \brief Returns true if this expression refers to a function that
/// was resolved from an overloaded set having size greater than 1.
bool hadMultipleCandidates() const {
return DeclRefExprBits.HadMultipleCandidates;
}
/// \brief Sets the flag telling whether this expression refers to
/// a function that was resolved from an overloaded set having size
/// greater than 1.
void setHadMultipleCandidates(bool V = true) {
DeclRefExprBits.HadMultipleCandidates = V;
}
/// \brief Does this DeclRefExpr refer to an enclosing local or a captured
/// variable?
bool refersToEnclosingVariableOrCapture() const {
return DeclRefExprBits.RefersToEnclosingVariableOrCapture;
}
static bool classof(const Stmt *T) {
return T->getStmtClass() == DeclRefExprClass;
}
// Iterators
child_range children() {
return child_range(child_iterator(), child_iterator());
}
friend TrailingObjects;
friend class ASTStmtReader;
friend class ASTStmtWriter;
};
/// \brief [C99 6.4.2.2] - A predefined identifier such as __func__.
class PredefinedExpr : public Expr {
public:
enum IdentType {
Func,
Function,
LFunction, // Same as Function, but as wide string.
FuncDName,
FuncSig,
PrettyFunction,
/// \brief The same as PrettyFunction, except that the
/// 'virtual' keyword is omitted for virtual member functions.
PrettyFunctionNoVirtual
};
private:
SourceLocation Loc;
IdentType Type;
Stmt *FnName;
public:
PredefinedExpr(SourceLocation L, QualType FNTy, IdentType IT,
StringLiteral *SL);
/// \brief Construct an empty predefined expression.
explicit PredefinedExpr(EmptyShell Empty)
: Expr(PredefinedExprClass, Empty), Loc(), Type(Func), FnName(nullptr) {}
IdentType getIdentType() const { return Type; }
SourceLocation getLocation() const { return Loc; }
void setLocation(SourceLocation L) { Loc = L; }
StringLiteral *getFunctionName();
const StringLiteral *getFunctionName() const {
return const_cast<PredefinedExpr *>(this)->getFunctionName();
}
static StringRef getIdentTypeName(IdentType IT);
static std::string ComputeName(IdentType IT, const Decl *CurrentDecl);
SourceLocation getLocStart() const LLVM_READONLY { return Loc; }
SourceLocation getLocEnd() const LLVM_READONLY { return Loc; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == PredefinedExprClass;
}
// Iterators
child_range children() { return child_range(&FnName, &FnName + 1); }
friend class ASTStmtReader;
};
/// \brief Used by IntegerLiteral/FloatingLiteral to store the numeric without
/// leaking memory.
///
/// For large floats/integers, APFloat/APInt will allocate memory from the heap
/// to represent these numbers. Unfortunately, when we use a BumpPtrAllocator
/// to allocate IntegerLiteral/FloatingLiteral nodes the memory associated with
/// the APFloat/APInt values will never get freed. APNumericStorage uses
/// ASTContext's allocator for memory allocation.
class APNumericStorage {
union {
uint64_t VAL; ///< Used to store the <= 64 bits integer value.
uint64_t *pVal; ///< Used to store the >64 bits integer value.
};
unsigned BitWidth;
bool hasAllocation() const { return llvm::APInt::getNumWords(BitWidth) > 1; }
APNumericStorage(const APNumericStorage &) = delete;
void operator=(const APNumericStorage &) = delete;
protected:
APNumericStorage() : VAL(0), BitWidth(0) { }
llvm::APInt getIntValue() const {
unsigned NumWords = llvm::APInt::getNumWords(BitWidth);
if (NumWords > 1)
return llvm::APInt(BitWidth, NumWords, pVal);
else
return llvm::APInt(BitWidth, VAL);
}
void setIntValue(const ASTContext &C, const llvm::APInt &Val);
};
class APIntStorage : private APNumericStorage {
public:
llvm::APInt getValue() const { return getIntValue(); }
void setValue(const ASTContext &C, const llvm::APInt &Val) {
setIntValue(C, Val);
}
};
class APFloatStorage : private APNumericStorage {
public:
llvm::APFloat getValue(const llvm::fltSemantics &Semantics) const {
return llvm::APFloat(Semantics, getIntValue());
}
void setValue(const ASTContext &C, const llvm::APFloat &Val) {
setIntValue(C, Val.bitcastToAPInt());
}
};
class IntegerLiteral : public Expr, public APIntStorage {
SourceLocation Loc;
/// \brief Construct an empty integer literal.
explicit IntegerLiteral(EmptyShell Empty)
: Expr(IntegerLiteralClass, Empty) { }
public:
// type should be IntTy, LongTy, LongLongTy, UnsignedIntTy, UnsignedLongTy,
// or UnsignedLongLongTy
IntegerLiteral(const ASTContext &C, const llvm::APInt &V, QualType type,
SourceLocation l);
/// \brief Returns a new integer literal with value 'V' and type 'type'.
/// \param type - either IntTy, LongTy, LongLongTy, UnsignedIntTy,
/// UnsignedLongTy, or UnsignedLongLongTy which should match the size of V
/// \param V - the value that the returned integer literal contains.
static IntegerLiteral *Create(const ASTContext &C, const llvm::APInt &V,
QualType type, SourceLocation l);
/// \brief Returns a new empty integer literal.
static IntegerLiteral *Create(const ASTContext &C, EmptyShell Empty);
SourceLocation getLocStart() const LLVM_READONLY { return Loc; }
SourceLocation getLocEnd() const LLVM_READONLY { return Loc; }
/// \brief Retrieve the location of the literal.
SourceLocation getLocation() const { return Loc; }
void setLocation(SourceLocation Location) { Loc = Location; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == IntegerLiteralClass;
}
// Iterators
child_range children() {
return child_range(child_iterator(), child_iterator());
}
};
class CharacterLiteral : public Expr {
public:
enum CharacterKind {
Ascii,
Wide,
UTF8,
UTF16,
UTF32
};
private:
unsigned Value;
SourceLocation Loc;
public:
// type should be IntTy
CharacterLiteral(unsigned value, CharacterKind kind, QualType type,
SourceLocation l)
: Expr(CharacterLiteralClass, type, VK_RValue, OK_Ordinary, false, false,
false, false),
Value(value), Loc(l) {
CharacterLiteralBits.Kind = kind;
}
/// \brief Construct an empty character literal.
CharacterLiteral(EmptyShell Empty) : Expr(CharacterLiteralClass, Empty) { }
SourceLocation getLocation() const { return Loc; }
CharacterKind getKind() const {
return static_cast<CharacterKind>(CharacterLiteralBits.Kind);
}
SourceLocation getLocStart() const LLVM_READONLY { return Loc; }
SourceLocation getLocEnd() const LLVM_READONLY { return Loc; }
unsigned getValue() const { return Value; }
void setLocation(SourceLocation Location) { Loc = Location; }
void setKind(CharacterKind kind) { CharacterLiteralBits.Kind = kind; }
void setValue(unsigned Val) { Value = Val; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == CharacterLiteralClass;
}
// Iterators
child_range children() {
return child_range(child_iterator(), child_iterator());
}
};
class FloatingLiteral : public Expr, private APFloatStorage {
SourceLocation Loc;
FloatingLiteral(const ASTContext &C, const llvm::APFloat &V, bool isexact,
QualType Type, SourceLocation L);
/// \brief Construct an empty floating-point literal.
explicit FloatingLiteral(const ASTContext &C, EmptyShell Empty);
public:
static FloatingLiteral *Create(const ASTContext &C, const llvm::APFloat &V,
bool isexact, QualType Type, SourceLocation L);
static FloatingLiteral *Create(const ASTContext &C, EmptyShell Empty);
llvm::APFloat getValue() const {
return APFloatStorage::getValue(getSemantics());
}
void setValue(const ASTContext &C, const llvm::APFloat &Val) {
assert(&getSemantics() == &Val.getSemantics() && "Inconsistent semantics");
APFloatStorage::setValue(C, Val);
}
/// Get a raw enumeration value representing the floating-point semantics of
/// this literal (32-bit IEEE, x87, ...), suitable for serialisation.
APFloatSemantics getRawSemantics() const {
return static_cast<APFloatSemantics>(FloatingLiteralBits.Semantics);
}
/// Set the raw enumeration value representing the floating-point semantics of
/// this literal (32-bit IEEE, x87, ...), suitable for serialisation.
void setRawSemantics(APFloatSemantics Sem) {
FloatingLiteralBits.Semantics = Sem;
}
/// Return the APFloat semantics this literal uses.
const llvm::fltSemantics &getSemantics() const;
/// Set the APFloat semantics this literal uses.
void setSemantics(const llvm::fltSemantics &Sem);
bool isExact() const { return FloatingLiteralBits.IsExact; }
void setExact(bool E) { FloatingLiteralBits.IsExact = E; }
/// getValueAsApproximateDouble - This returns the value as an inaccurate
/// double. Note that this may cause loss of precision, but is useful for
/// debugging dumps, etc.
double getValueAsApproximateDouble() const;
SourceLocation getLocation() const { return Loc; }
void setLocation(SourceLocation L) { Loc = L; }
SourceLocation getLocStart() const LLVM_READONLY { return Loc; }
SourceLocation getLocEnd() const LLVM_READONLY { return Loc; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == FloatingLiteralClass;
}
// Iterators
child_range children() {
return child_range(child_iterator(), child_iterator());
}
};
/// ImaginaryLiteral - We support imaginary integer and floating point literals,
/// like "1.0i". We represent these as a wrapper around FloatingLiteral and
/// IntegerLiteral classes. Instances of this class always have a Complex type
/// whose element type matches the subexpression.
///
class ImaginaryLiteral : public Expr {
Stmt *Val;
public:
ImaginaryLiteral(Expr *val, QualType Ty)
: Expr(ImaginaryLiteralClass, Ty, VK_RValue, OK_Ordinary, false, false,
false, false),
Val(val) {}
/// \brief Build an empty imaginary literal.
explicit ImaginaryLiteral(EmptyShell Empty)
: Expr(ImaginaryLiteralClass, Empty) { }
const Expr *getSubExpr() const { return cast<Expr>(Val); }
Expr *getSubExpr() { return cast<Expr>(Val); }
void setSubExpr(Expr *E) { Val = E; }
SourceLocation getLocStart() const LLVM_READONLY { return Val->getLocStart(); }
SourceLocation getLocEnd() const LLVM_READONLY { return Val->getLocEnd(); }
static bool classof(const Stmt *T) {
return T->getStmtClass() == ImaginaryLiteralClass;
}
// Iterators
child_range children() { return child_range(&Val, &Val+1); }
};
/// StringLiteral - This represents a string literal expression, e.g. "foo"
/// or L"bar" (wide strings). The actual string is returned by getBytes()
/// is NOT null-terminated, and the length of the string is determined by
/// calling getByteLength(). The C type for a string is always a
/// ConstantArrayType. In C++, the char type is const qualified, in C it is
/// not.
///
/// Note that strings in C can be formed by concatenation of multiple string
/// literal pptokens in translation phase #6. This keeps track of the locations
/// of each of these pieces.
///
/// Strings in C can also be truncated and extended by assigning into arrays,
/// e.g. with constructs like:
/// char X[2] = "foobar";
/// In this case, getByteLength() will return 6, but the string literal will
/// have type "char[2]".
class StringLiteral : public Expr {
public:
enum StringKind {
Ascii,
Wide,
UTF8,
UTF16,
UTF32
};
private:
friend class ASTStmtReader;
union {
const char *asChar;
const uint16_t *asUInt16;
const uint32_t *asUInt32;
} StrData;
unsigned Length;
unsigned CharByteWidth : 4;
unsigned Kind : 3;
unsigned IsPascal : 1;
unsigned NumConcatenated;
SourceLocation TokLocs[1];
StringLiteral(QualType Ty) :
Expr(StringLiteralClass, Ty, VK_LValue, OK_Ordinary, false, false, false,
false) {}
static int mapCharByteWidth(TargetInfo const &target,StringKind k);
public:
/// This is the "fully general" constructor that allows representation of
/// strings formed from multiple concatenated tokens.
static StringLiteral *Create(const ASTContext &C, StringRef Str,
StringKind Kind, bool Pascal, QualType Ty,
const SourceLocation *Loc, unsigned NumStrs);
/// Simple constructor for string literals made from one token.
static StringLiteral *Create(const ASTContext &C, StringRef Str,
StringKind Kind, bool Pascal, QualType Ty,
SourceLocation Loc) {
return Create(C, Str, Kind, Pascal, Ty, &Loc, 1);
}
/// \brief Construct an empty string literal.
static StringLiteral *CreateEmpty(const ASTContext &C, unsigned NumStrs);
StringRef getString() const {
assert(CharByteWidth==1
&& "This function is used in places that assume strings use char");
return StringRef(StrData.asChar, getByteLength());
}
/// Allow access to clients that need the byte representation, such as
/// ASTWriterStmt::VisitStringLiteral().
StringRef getBytes() const {
// FIXME: StringRef may not be the right type to use as a result for this.
if (CharByteWidth == 1)
return StringRef(StrData.asChar, getByteLength());
if (CharByteWidth == 4)
return StringRef(reinterpret_cast<const char*>(StrData.asUInt32),
getByteLength());
assert(CharByteWidth == 2 && "unsupported CharByteWidth");
return StringRef(reinterpret_cast<const char*>(StrData.asUInt16),
getByteLength());
}
void outputString(raw_ostream &OS) const;
uint32_t getCodeUnit(size_t i) const {
assert(i < Length && "out of bounds access");
if (CharByteWidth == 1)
return static_cast<unsigned char>(StrData.asChar[i]);
if (CharByteWidth == 4)
return StrData.asUInt32[i];
assert(CharByteWidth == 2 && "unsupported CharByteWidth");
return StrData.asUInt16[i];
}
unsigned getByteLength() const { return CharByteWidth*Length; }
unsigned getLength() const { return Length; }
unsigned getCharByteWidth() const { return CharByteWidth; }
/// \brief Sets the string data to the given string data.
void setString(const ASTContext &C, StringRef Str,
StringKind Kind, bool IsPascal);
StringKind getKind() const { return static_cast<StringKind>(Kind); }
bool isAscii() const { return Kind == Ascii; }
bool isWide() const { return Kind == Wide; }
bool isUTF8() const { return Kind == UTF8; }
bool isUTF16() const { return Kind == UTF16; }
bool isUTF32() const { return Kind == UTF32; }
bool isPascal() const { return IsPascal; }
bool containsNonAsciiOrNull() const {
StringRef Str = getString();
for (unsigned i = 0, e = Str.size(); i != e; ++i)
if (!isASCII(Str[i]) || !Str[i])
return true;
return false;
}
/// getNumConcatenated - Get the number of string literal tokens that were
/// concatenated in translation phase #6 to form this string literal.
unsigned getNumConcatenated() const { return NumConcatenated; }
SourceLocation getStrTokenLoc(unsigned TokNum) const {
assert(TokNum < NumConcatenated && "Invalid tok number");
return TokLocs[TokNum];
}
void setStrTokenLoc(unsigned TokNum, SourceLocation L) {
assert(TokNum < NumConcatenated && "Invalid tok number");
TokLocs[TokNum] = L;
}
/// getLocationOfByte - Return a source location that points to the specified
/// byte of this string literal.
///
/// Strings are amazingly complex. They can be formed from multiple tokens
/// and can have escape sequences in them in addition to the usual trigraph
/// and escaped newline business. This routine handles this complexity.
///
SourceLocation
getLocationOfByte(unsigned ByteNo, const SourceManager &SM,
const LangOptions &Features, const TargetInfo &Target,
unsigned *StartToken = nullptr,
unsigned *StartTokenByteOffset = nullptr) const;
typedef const SourceLocation *tokloc_iterator;
tokloc_iterator tokloc_begin() const { return TokLocs; }
tokloc_iterator tokloc_end() const { return TokLocs + NumConcatenated; }
SourceLocation getLocStart() const LLVM_READONLY { return TokLocs[0]; }
SourceLocation getLocEnd() const LLVM_READONLY {
return TokLocs[NumConcatenated - 1];
}
static bool classof(const Stmt *T) {
return T->getStmtClass() == StringLiteralClass;
}
// Iterators
child_range children() {
return child_range(child_iterator(), child_iterator());
}
};
/// ParenExpr - This represents a parethesized expression, e.g. "(1)". This
/// AST node is only formed if full location information is requested.
class ParenExpr : public Expr {
SourceLocation L, R;
Stmt *Val;
public:
ParenExpr(SourceLocation l, SourceLocation r, Expr *val)
: Expr(ParenExprClass, val->getType(),
val->getValueKind(), val->getObjectKind(),
val->isTypeDependent(), val->isValueDependent(),
val->isInstantiationDependent(),
val->containsUnexpandedParameterPack()),
L(l), R(r), Val(val) {}
/// \brief Construct an empty parenthesized expression.
explicit ParenExpr(EmptyShell Empty)
: Expr(ParenExprClass, Empty) { }
const Expr *getSubExpr() const { return cast<Expr>(Val); }
Expr *getSubExpr() { return cast<Expr>(Val); }
void setSubExpr(Expr *E) { Val = E; }
SourceLocation getLocStart() const LLVM_READONLY { return L; }
SourceLocation getLocEnd() const LLVM_READONLY { return R; }
/// \brief Get the location of the left parentheses '('.
SourceLocation getLParen() const { return L; }
void setLParen(SourceLocation Loc) { L = Loc; }
/// \brief Get the location of the right parentheses ')'.
SourceLocation getRParen() const { return R; }
void setRParen(SourceLocation Loc) { R = Loc; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == ParenExprClass;
}
// Iterators
child_range children() { return child_range(&Val, &Val+1); }
};
/// UnaryOperator - This represents the unary-expression's (except sizeof and
/// alignof), the postinc/postdec operators from postfix-expression, and various
/// extensions.
///
/// Notes on various nodes:
///
/// Real/Imag - These return the real/imag part of a complex operand. If
/// applied to a non-complex value, the former returns its operand and the
/// later returns zero in the type of the operand.
///
class UnaryOperator : public Expr {
public:
typedef UnaryOperatorKind Opcode;
private:
unsigned Opc : 5;
SourceLocation Loc;
Stmt *Val;
public:
UnaryOperator(Expr *input, Opcode opc, QualType type,
ExprValueKind VK, ExprObjectKind OK, SourceLocation l)
: Expr(UnaryOperatorClass, type, VK, OK,
input->isTypeDependent() || type->isDependentType(),
input->isValueDependent(),
(input->isInstantiationDependent() ||
type->isInstantiationDependentType()),
input->containsUnexpandedParameterPack()),
Opc(opc), Loc(l), Val(input) {}
/// \brief Build an empty unary operator.
explicit UnaryOperator(EmptyShell Empty)
: Expr(UnaryOperatorClass, Empty), Opc(UO_AddrOf) { }
Opcode getOpcode() const { return static_cast<Opcode>(Opc); }
void setOpcode(Opcode O) { Opc = O; }
Expr *getSubExpr() const { return cast<Expr>(Val); }
void setSubExpr(Expr *E) { Val = E; }
/// getOperatorLoc - Return the location of the operator.
SourceLocation getOperatorLoc() const { return Loc; }
void setOperatorLoc(SourceLocation L) { Loc = L; }
/// isPostfix - Return true if this is a postfix operation, like x++.
static bool isPostfix(Opcode Op) {
return Op == UO_PostInc || Op == UO_PostDec;
}
/// isPrefix - Return true if this is a prefix operation, like --x.
static bool isPrefix(Opcode Op) {
return Op == UO_PreInc || Op == UO_PreDec;
}
bool isPrefix() const { return isPrefix(getOpcode()); }
bool isPostfix() const { return isPostfix(getOpcode()); }
static bool isIncrementOp(Opcode Op) {
return Op == UO_PreInc || Op == UO_PostInc;
}
bool isIncrementOp() const {
return isIncrementOp(getOpcode());
}
static bool isDecrementOp(Opcode Op) {
return Op == UO_PreDec || Op == UO_PostDec;
}
bool isDecrementOp() const {
return isDecrementOp(getOpcode());
}
static bool isIncrementDecrementOp(Opcode Op) { return Op <= UO_PreDec; }
bool isIncrementDecrementOp() const {
return isIncrementDecrementOp(getOpcode());
}
static bool isArithmeticOp(Opcode Op) {
return Op >= UO_Plus && Op <= UO_LNot;
}
bool isArithmeticOp() const { return isArithmeticOp(getOpcode()); }
/// getOpcodeStr - Turn an Opcode enum value into the punctuation char it
/// corresponds to, e.g. "sizeof" or "[pre]++"
static StringRef getOpcodeStr(Opcode Op);
/// \brief Retrieve the unary opcode that corresponds to the given
/// overloaded operator.
static Opcode getOverloadedOpcode(OverloadedOperatorKind OO, bool Postfix);
/// \brief Retrieve the overloaded operator kind that corresponds to
/// the given unary opcode.
static OverloadedOperatorKind getOverloadedOperator(Opcode Opc);
SourceLocation getLocStart() const LLVM_READONLY {
return isPostfix() ? Val->getLocStart() : Loc;
}
SourceLocation getLocEnd() const LLVM_READONLY {
return isPostfix() ? Loc : Val->getLocEnd();
}
SourceLocation getExprLoc() const LLVM_READONLY { return Loc; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == UnaryOperatorClass;
}
// Iterators
child_range children() { return child_range(&Val, &Val+1); }
};
/// Helper class for OffsetOfExpr.
// __builtin_offsetof(type, identifier(.identifier|[expr])*)
class OffsetOfNode {
public:
/// \brief The kind of offsetof node we have.
enum Kind {
/// \brief An index into an array.
Array = 0x00,
/// \brief A field.
Field = 0x01,
/// \brief A field in a dependent type, known only by its name.
Identifier = 0x02,
/// \brief An implicit indirection through a C++ base class, when the
/// field found is in a base class.
Base = 0x03
};
private:
enum { MaskBits = 2, Mask = 0x03 };
/// \brief The source range that covers this part of the designator.
SourceRange Range;
/// \brief The data describing the designator, which comes in three
/// different forms, depending on the lower two bits.
/// - An unsigned index into the array of Expr*'s stored after this node
/// in memory, for [constant-expression] designators.
/// - A FieldDecl*, for references to a known field.
/// - An IdentifierInfo*, for references to a field with a given name
/// when the class type is dependent.
/// - A CXXBaseSpecifier*, for references that look at a field in a
/// base class.
uintptr_t Data;
public:
/// \brief Create an offsetof node that refers to an array element.
OffsetOfNode(SourceLocation LBracketLoc, unsigned Index,
SourceLocation RBracketLoc)
: Range(LBracketLoc, RBracketLoc), Data((Index << 2) | Array) {}
/// \brief Create an offsetof node that refers to a field.
OffsetOfNode(SourceLocation DotLoc, FieldDecl *Field, SourceLocation NameLoc)
: Range(DotLoc.isValid() ? DotLoc : NameLoc, NameLoc),
Data(reinterpret_cast<uintptr_t>(Field) | OffsetOfNode::Field) {}
/// \brief Create an offsetof node that refers to an identifier.
OffsetOfNode(SourceLocation DotLoc, IdentifierInfo *Name,
SourceLocation NameLoc)
: Range(DotLoc.isValid() ? DotLoc : NameLoc, NameLoc),
Data(reinterpret_cast<uintptr_t>(Name) | Identifier) {}
/// \brief Create an offsetof node that refers into a C++ base class.
explicit OffsetOfNode(const CXXBaseSpecifier *Base)
: Range(), Data(reinterpret_cast<uintptr_t>(Base) | OffsetOfNode::Base) {}
/// \brief Determine what kind of offsetof node this is.
Kind getKind() const { return static_cast<Kind>(Data & Mask); }
/// \brief For an array element node, returns the index into the array
/// of expressions.
unsigned getArrayExprIndex() const {
assert(getKind() == Array);
return Data >> 2;
}
/// \brief For a field offsetof node, returns the field.
FieldDecl *getField() const {
assert(getKind() == Field);
return reinterpret_cast<FieldDecl *>(Data & ~(uintptr_t)Mask);
}
/// \brief For a field or identifier offsetof node, returns the name of
/// the field.
IdentifierInfo *getFieldName() const;
/// \brief For a base class node, returns the base specifier.
CXXBaseSpecifier *getBase() const {
assert(getKind() == Base);
return reinterpret_cast<CXXBaseSpecifier *>(Data & ~(uintptr_t)Mask);
}
/// \brief Retrieve the source range that covers this offsetof node.
///
/// For an array element node, the source range contains the locations of
/// the square brackets. For a field or identifier node, the source range
/// contains the location of the period (if there is one) and the
/// identifier.
SourceRange getSourceRange() const LLVM_READONLY { return Range; }
SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); }
SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); }
};
/// OffsetOfExpr - [C99 7.17] - This represents an expression of the form
/// offsetof(record-type, member-designator). For example, given:
/// @code
/// struct S {
/// float f;
/// double d;
/// };
/// struct T {
/// int i;
/// struct S s[10];
/// };
/// @endcode
/// we can represent and evaluate the expression @c offsetof(struct T, s[2].d).
class OffsetOfExpr final
: public Expr,
private llvm::TrailingObjects<OffsetOfExpr, OffsetOfNode, Expr *> {
SourceLocation OperatorLoc, RParenLoc;
// Base type;
TypeSourceInfo *TSInfo;
// Number of sub-components (i.e. instances of OffsetOfNode).
unsigned NumComps;
// Number of sub-expressions (i.e. array subscript expressions).
unsigned NumExprs;
size_t numTrailingObjects(OverloadToken<OffsetOfNode>) const {
return NumComps;
}
OffsetOfExpr(const ASTContext &C, QualType type,
SourceLocation OperatorLoc, TypeSourceInfo *tsi,
ArrayRef<OffsetOfNode> comps, ArrayRef<Expr*> exprs,
SourceLocation RParenLoc);
explicit OffsetOfExpr(unsigned numComps, unsigned numExprs)
: Expr(OffsetOfExprClass, EmptyShell()),
TSInfo(nullptr), NumComps(numComps), NumExprs(numExprs) {}
public:
static OffsetOfExpr *Create(const ASTContext &C, QualType type,
SourceLocation OperatorLoc, TypeSourceInfo *tsi,
ArrayRef<OffsetOfNode> comps,
ArrayRef<Expr*> exprs, SourceLocation RParenLoc);
static OffsetOfExpr *CreateEmpty(const ASTContext &C,
unsigned NumComps, unsigned NumExprs);
/// getOperatorLoc - Return the location of the operator.
SourceLocation getOperatorLoc() const { return OperatorLoc; }
void setOperatorLoc(SourceLocation L) { OperatorLoc = L; }
/// \brief Return the location of the right parentheses.
SourceLocation getRParenLoc() const { return RParenLoc; }
void setRParenLoc(SourceLocation R) { RParenLoc = R; }
TypeSourceInfo *getTypeSourceInfo() const {
return TSInfo;
}
void setTypeSourceInfo(TypeSourceInfo *tsi) {
TSInfo = tsi;
}
const OffsetOfNode &getComponent(unsigned Idx) const {
assert(Idx < NumComps && "Subscript out of range");
return getTrailingObjects<OffsetOfNode>()[Idx];
}
void setComponent(unsigned Idx, OffsetOfNode ON) {
assert(Idx < NumComps && "Subscript out of range");
getTrailingObjects<OffsetOfNode>()[Idx] = ON;
}
unsigned getNumComponents() const {
return NumComps;
}
Expr* getIndexExpr(unsigned Idx) {
assert(Idx < NumExprs && "Subscript out of range");
return getTrailingObjects<Expr *>()[Idx];
}
const Expr *getIndexExpr(unsigned Idx) const {
assert(Idx < NumExprs && "Subscript out of range");
return getTrailingObjects<Expr *>()[Idx];
}
void setIndexExpr(unsigned Idx, Expr* E) {
assert(Idx < NumComps && "Subscript out of range");
getTrailingObjects<Expr *>()[Idx] = E;
}
unsigned getNumExpressions() const {
return NumExprs;
}
SourceLocation getLocStart() const LLVM_READONLY { return OperatorLoc; }
SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == OffsetOfExprClass;
}
// Iterators
child_range children() {
Stmt **begin = reinterpret_cast<Stmt **>(getTrailingObjects<Expr *>());
return child_range(begin, begin + NumExprs);
}
friend TrailingObjects;
};
/// UnaryExprOrTypeTraitExpr - expression with either a type or (unevaluated)
/// expression operand. Used for sizeof/alignof (C99 6.5.3.4) and
/// vec_step (OpenCL 1.1 6.11.12).
class UnaryExprOrTypeTraitExpr : public Expr {
union {
TypeSourceInfo *Ty;
Stmt *Ex;
} Argument;
SourceLocation OpLoc, RParenLoc;
public:
UnaryExprOrTypeTraitExpr(UnaryExprOrTypeTrait ExprKind, TypeSourceInfo *TInfo,
QualType resultType, SourceLocation op,
SourceLocation rp) :
Expr(UnaryExprOrTypeTraitExprClass, resultType, VK_RValue, OK_Ordinary,
false, // Never type-dependent (C++ [temp.dep.expr]p3).
// Value-dependent if the argument is type-dependent.
TInfo->getType()->isDependentType(),
TInfo->getType()->isInstantiationDependentType(),
TInfo->getType()->containsUnexpandedParameterPack()),
OpLoc(op), RParenLoc(rp) {
UnaryExprOrTypeTraitExprBits.Kind = ExprKind;
UnaryExprOrTypeTraitExprBits.IsType = true;
Argument.Ty = TInfo;
}
UnaryExprOrTypeTraitExpr(UnaryExprOrTypeTrait ExprKind, Expr *E,
QualType resultType, SourceLocation op,
SourceLocation rp);
/// \brief Construct an empty sizeof/alignof expression.
explicit UnaryExprOrTypeTraitExpr(EmptyShell Empty)
: Expr(UnaryExprOrTypeTraitExprClass, Empty) { }
UnaryExprOrTypeTrait getKind() const {
return static_cast<UnaryExprOrTypeTrait>(UnaryExprOrTypeTraitExprBits.Kind);
}
void setKind(UnaryExprOrTypeTrait K) { UnaryExprOrTypeTraitExprBits.Kind = K;}
bool isArgumentType() const { return UnaryExprOrTypeTraitExprBits.IsType; }
QualType getArgumentType() const {
return getArgumentTypeInfo()->getType();
}
TypeSourceInfo *getArgumentTypeInfo() const {
assert(isArgumentType() && "calling getArgumentType() when arg is expr");
return Argument.Ty;
}
Expr *getArgumentExpr() {
assert(!isArgumentType() && "calling getArgumentExpr() when arg is type");
return static_cast<Expr*>(Argument.Ex);
}
const Expr *getArgumentExpr() const {
return const_cast<UnaryExprOrTypeTraitExpr*>(this)->getArgumentExpr();
}
void setArgument(Expr *E) {
Argument.Ex = E;
UnaryExprOrTypeTraitExprBits.IsType = false;
}
void setArgument(TypeSourceInfo *TInfo) {
Argument.Ty = TInfo;
UnaryExprOrTypeTraitExprBits.IsType = true;
}
/// Gets the argument type, or the type of the argument expression, whichever
/// is appropriate.
QualType getTypeOfArgument() const {
return isArgumentType() ? getArgumentType() : getArgumentExpr()->getType();
}
SourceLocation getOperatorLoc() const { return OpLoc; }
void setOperatorLoc(SourceLocation L) { OpLoc = L; }
SourceLocation getRParenLoc() const { return RParenLoc; }
void setRParenLoc(SourceLocation L) { RParenLoc = L; }
SourceLocation getLocStart() const LLVM_READONLY { return OpLoc; }
SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == UnaryExprOrTypeTraitExprClass;
}
// Iterators
child_range children();
};
//===----------------------------------------------------------------------===//
// Postfix Operators.
//===----------------------------------------------------------------------===//
/// ArraySubscriptExpr - [C99 6.5.2.1] Array Subscripting.
class ArraySubscriptExpr : public Expr {
enum { LHS, RHS, END_EXPR=2 };
Stmt* SubExprs[END_EXPR];
SourceLocation RBracketLoc;
public:
ArraySubscriptExpr(Expr *lhs, Expr *rhs, QualType t,
ExprValueKind VK, ExprObjectKind OK,
SourceLocation rbracketloc)
: Expr(ArraySubscriptExprClass, t, VK, OK,
lhs->isTypeDependent() || rhs->isTypeDependent(),
lhs->isValueDependent() || rhs->isValueDependent(),
(lhs->isInstantiationDependent() ||
rhs->isInstantiationDependent()),
(lhs->containsUnexpandedParameterPack() ||
rhs->containsUnexpandedParameterPack())),
RBracketLoc(rbracketloc) {
SubExprs[LHS] = lhs;
SubExprs[RHS] = rhs;
}
/// \brief Create an empty array subscript expression.
explicit ArraySubscriptExpr(EmptyShell Shell)
: Expr(ArraySubscriptExprClass, Shell) { }
/// An array access can be written A[4] or 4[A] (both are equivalent).
/// - getBase() and getIdx() always present the normalized view: A[4].
/// In this case getBase() returns "A" and getIdx() returns "4".
/// - getLHS() and getRHS() present the syntactic view. e.g. for
/// 4[A] getLHS() returns "4".
/// Note: Because vector element access is also written A[4] we must
/// predicate the format conversion in getBase and getIdx only on the
/// the type of the RHS, as it is possible for the LHS to be a vector of
/// integer type
Expr *getLHS() { return cast<Expr>(SubExprs[LHS]); }
const Expr *getLHS() const { return cast<Expr>(SubExprs[LHS]); }
void setLHS(Expr *E) { SubExprs[LHS] = E; }
Expr *getRHS() { return cast<Expr>(SubExprs[RHS]); }
const Expr *getRHS() const { return cast<Expr>(SubExprs[RHS]); }
void setRHS(Expr *E) { SubExprs[RHS] = E; }
Expr *getBase() {
return cast<Expr>(getRHS()->getType()->isIntegerType() ? getLHS():getRHS());
}
const Expr *getBase() const {
return cast<Expr>(getRHS()->getType()->isIntegerType() ? getLHS():getRHS());
}
Expr *getIdx() {
return cast<Expr>(getRHS()->getType()->isIntegerType() ? getRHS():getLHS());
}
const Expr *getIdx() const {
return cast<Expr>(getRHS()->getType()->isIntegerType() ? getRHS():getLHS());
}
SourceLocation getLocStart() const LLVM_READONLY {
return getLHS()->getLocStart();
}
SourceLocation getLocEnd() const LLVM_READONLY { return RBracketLoc; }
SourceLocation getRBracketLoc() const { return RBracketLoc; }
void setRBracketLoc(SourceLocation L) { RBracketLoc = L; }
SourceLocation getExprLoc() const LLVM_READONLY {
return getBase()->getExprLoc();
}
static bool classof(const Stmt *T) {
return T->getStmtClass() == ArraySubscriptExprClass;
}
// Iterators
child_range children() {
return child_range(&SubExprs[0], &SubExprs[0]+END_EXPR);
}
};
/// CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
/// CallExpr itself represents a normal function call, e.g., "f(x, 2)",
/// while its subclasses may represent alternative syntax that (semantically)
/// results in a function call. For example, CXXOperatorCallExpr is
/// a subclass for overloaded operator calls that use operator syntax, e.g.,
/// "str1 + str2" to resolve to a function call.
class CallExpr : public Expr {
enum { FN=0, PREARGS_START=1 };
Stmt **SubExprs;
unsigned NumArgs;
SourceLocation RParenLoc;
void updateDependenciesFromArg(Expr *Arg);
protected:
// These versions of the constructor are for derived classes.
CallExpr(const ASTContext &C, StmtClass SC, Expr *fn,
ArrayRef<Expr *> preargs, ArrayRef<Expr *> args, QualType t,
ExprValueKind VK, SourceLocation rparenloc);
CallExpr(const ASTContext &C, StmtClass SC, Expr *fn, ArrayRef<Expr *> args,
QualType t, ExprValueKind VK, SourceLocation rparenloc);
CallExpr(const ASTContext &C, StmtClass SC, unsigned NumPreArgs,
EmptyShell Empty);
Stmt *getPreArg(unsigned i) {
assert(i < getNumPreArgs() && "Prearg access out of range!");
return SubExprs[PREARGS_START+i];
}
const Stmt *getPreArg(unsigned i) const {
assert(i < getNumPreArgs() && "Prearg access out of range!");
return SubExprs[PREARGS_START+i];
}
void setPreArg(unsigned i, Stmt *PreArg) {
assert(i < getNumPreArgs() && "Prearg access out of range!");
SubExprs[PREARGS_START+i] = PreArg;
}
unsigned getNumPreArgs() const { return CallExprBits.NumPreArgs; }
public:
CallExpr(const ASTContext& C, Expr *fn, ArrayRef<Expr*> args, QualType t,
ExprValueKind VK, SourceLocation rparenloc);
/// \brief Build an empty call expression.
CallExpr(const ASTContext &C, StmtClass SC, EmptyShell Empty);
const Expr *getCallee() const { return cast<Expr>(SubExprs[FN]); }
Expr *getCallee() { return cast<Expr>(SubExprs[FN]); }
void setCallee(Expr *F) { SubExprs[FN] = F; }
Decl *getCalleeDecl();
const Decl *getCalleeDecl() const {
return const_cast<CallExpr*>(this)->getCalleeDecl();
}
/// \brief If the callee is a FunctionDecl, return it. Otherwise return 0.
FunctionDecl *getDirectCallee();
const FunctionDecl *getDirectCallee() const {
return const_cast<CallExpr*>(this)->getDirectCallee();
}
/// getNumArgs - Return the number of actual arguments to this call.
///
unsigned getNumArgs() const { return NumArgs; }
/// \brief Retrieve the call arguments.
Expr **getArgs() {
return reinterpret_cast<Expr **>(SubExprs+getNumPreArgs()+PREARGS_START);
}
const Expr *const *getArgs() const {
return reinterpret_cast<Expr **>(SubExprs + getNumPreArgs() +
PREARGS_START);
}
/// getArg - Return the specified argument.
Expr *getArg(unsigned Arg) {
assert(Arg < NumArgs && "Arg access out of range!");
return cast_or_null<Expr>(SubExprs[Arg + getNumPreArgs() + PREARGS_START]);
}
const Expr *getArg(unsigned Arg) const {
assert(Arg < NumArgs && "Arg access out of range!");
return cast_or_null<Expr>(SubExprs[Arg + getNumPreArgs() + PREARGS_START]);
}
/// setArg - Set the specified argument.
void setArg(unsigned Arg, Expr *ArgExpr) {
assert(Arg < NumArgs && "Arg access out of range!");
SubExprs[Arg+getNumPreArgs()+PREARGS_START] = ArgExpr;
}
/// setNumArgs - This changes the number of arguments present in this call.
/// Any orphaned expressions are deleted by this, and any new operands are set
/// to null.
void setNumArgs(const ASTContext& C, unsigned NumArgs);
typedef ExprIterator arg_iterator;
typedef ConstExprIterator const_arg_iterator;
typedef llvm::iterator_range<arg_iterator> arg_range;
typedef llvm::iterator_range<const_arg_iterator> arg_const_range;
arg_range arguments() { return arg_range(arg_begin(), arg_end()); }
arg_const_range arguments() const {
return arg_const_range(arg_begin(), arg_end());
}
arg_iterator arg_begin() { return SubExprs+PREARGS_START+getNumPreArgs(); }
arg_iterator arg_end() {
return SubExprs+PREARGS_START+getNumPreArgs()+getNumArgs();
}
const_arg_iterator arg_begin() const {
return SubExprs+PREARGS_START+getNumPreArgs();
}
const_arg_iterator arg_end() const {
return SubExprs+PREARGS_START+getNumPreArgs()+getNumArgs();
}
/// This method provides fast access to all the subexpressions of
/// a CallExpr without going through the slower virtual child_iterator
/// interface. This provides efficient reverse iteration of the
/// subexpressions. This is currently used for CFG construction.
ArrayRef<Stmt*> getRawSubExprs() {
return llvm::makeArrayRef(SubExprs,
getNumPreArgs() + PREARGS_START + getNumArgs());
}
/// getNumCommas - Return the number of commas that must have been present in
/// this function call.
unsigned getNumCommas() const { return NumArgs ? NumArgs - 1 : 0; }
/// getBuiltinCallee - If this is a call to a builtin, return the builtin ID
/// of the callee. If not, return 0.
unsigned getBuiltinCallee() const;
/// \brief Returns \c true if this is a call to a builtin which does not
/// evaluate side-effects within its arguments.
bool isUnevaluatedBuiltinCall(const ASTContext &Ctx) const;
/// getCallReturnType - Get the return type of the call expr. This is not
/// always the type of the expr itself, if the return type is a reference
/// type.
QualType getCallReturnType(const ASTContext &Ctx) const;
SourceLocation getRParenLoc() const { return RParenLoc; }
void setRParenLoc(SourceLocation L) { RParenLoc = L; }
SourceLocation getLocStart() const LLVM_READONLY;
SourceLocation getLocEnd() const LLVM_READONLY;
static bool classof(const Stmt *T) {
return T->getStmtClass() >= firstCallExprConstant &&
T->getStmtClass() <= lastCallExprConstant;
}
// Iterators
child_range children() {
return child_range(&SubExprs[0],
&SubExprs[0]+NumArgs+getNumPreArgs()+PREARGS_START);
}
};
/// Extra data stored in some MemberExpr objects.
struct MemberExprNameQualifier {
/// \brief The nested-name-specifier that qualifies the name, including
/// source-location information.
NestedNameSpecifierLoc QualifierLoc;
/// \brief The DeclAccessPair through which the MemberDecl was found due to
/// name qualifiers.
DeclAccessPair FoundDecl;
};
/// MemberExpr - [C99 6.5.2.3] Structure and Union Members. X->F and X.F.
///
class MemberExpr final
: public Expr,
private llvm::TrailingObjects<MemberExpr, MemberExprNameQualifier,
ASTTemplateKWAndArgsInfo,
TemplateArgumentLoc> {
/// Base - the expression for the base pointer or structure references. In
/// X.F, this is "X".
Stmt *Base;
/// MemberDecl - This is the decl being referenced by the field/member name.
/// In X.F, this is the decl referenced by F.
ValueDecl *MemberDecl;
/// MemberDNLoc - Provides source/type location info for the
/// declaration name embedded in MemberDecl.
DeclarationNameLoc MemberDNLoc;
/// MemberLoc - This is the location of the member name.
SourceLocation MemberLoc;
/// This is the location of the -> or . in the expression.
SourceLocation OperatorLoc;
/// IsArrow - True if this is "X->F", false if this is "X.F".
bool IsArrow : 1;
/// \brief True if this member expression used a nested-name-specifier to
/// refer to the member, e.g., "x->Base::f", or found its member via a using
/// declaration. When true, a MemberExprNameQualifier
/// structure is allocated immediately after the MemberExpr.
bool HasQualifierOrFoundDecl : 1;
/// \brief True if this member expression specified a template keyword
/// and/or a template argument list explicitly, e.g., x->f<int>,
/// x->template f, x->template f<int>.
/// When true, an ASTTemplateKWAndArgsInfo structure and its
/// TemplateArguments (if any) are present.
bool HasTemplateKWAndArgsInfo : 1;
/// \brief True if this member expression refers to a method that
/// was resolved from an overloaded set having size greater than 1.
bool HadMultipleCandidates : 1;
size_t numTrailingObjects(OverloadToken<MemberExprNameQualifier>) const {
return HasQualifierOrFoundDecl ? 1 : 0;
}
size_t numTrailingObjects(OverloadToken<ASTTemplateKWAndArgsInfo>) const {
return HasTemplateKWAndArgsInfo ? 1 : 0;
}
public:
MemberExpr(Expr *base, bool isarrow, SourceLocation operatorloc,
ValueDecl *memberdecl, const DeclarationNameInfo &NameInfo,
QualType ty, ExprValueKind VK, ExprObjectKind OK)
: Expr(MemberExprClass, ty, VK, OK, base->isTypeDependent(),
base->isValueDependent(), base->isInstantiationDependent(),
base->containsUnexpandedParameterPack()),
Base(base), MemberDecl(memberdecl), MemberDNLoc(NameInfo.getInfo()),
MemberLoc(NameInfo.getLoc()), OperatorLoc(operatorloc),
IsArrow(isarrow), HasQualifierOrFoundDecl(false),
HasTemplateKWAndArgsInfo(false), HadMultipleCandidates(false) {
assert(memberdecl->getDeclName() == NameInfo.getName());
}
// NOTE: this constructor should be used only when it is known that
// the member name can not provide additional syntactic info
// (i.e., source locations for C++ operator names or type source info
// for constructors, destructors and conversion operators).
MemberExpr(Expr *base, bool isarrow, SourceLocation operatorloc,
ValueDecl *memberdecl, SourceLocation l, QualType ty,
ExprValueKind VK, ExprObjectKind OK)
: Expr(MemberExprClass, ty, VK, OK, base->isTypeDependent(),
base->isValueDependent(), base->isInstantiationDependent(),
base->containsUnexpandedParameterPack()),
Base(base), MemberDecl(memberdecl), MemberDNLoc(), MemberLoc(l),
OperatorLoc(operatorloc), IsArrow(isarrow),
HasQualifierOrFoundDecl(false), HasTemplateKWAndArgsInfo(false),
HadMultipleCandidates(false) {}
static MemberExpr *Create(const ASTContext &C, Expr *base, bool isarrow,
SourceLocation OperatorLoc,
NestedNameSpecifierLoc QualifierLoc,
SourceLocation TemplateKWLoc, ValueDecl *memberdecl,
DeclAccessPair founddecl,
DeclarationNameInfo MemberNameInfo,
const TemplateArgumentListInfo *targs, QualType ty,
ExprValueKind VK, ExprObjectKind OK);
void setBase(Expr *E) { Base = E; }
Expr *getBase() const { return cast<Expr>(Base); }
/// \brief Retrieve the member declaration to which this expression refers.
///
/// The returned declaration will either be a FieldDecl or (in C++)
/// a CXXMethodDecl.
ValueDecl *getMemberDecl() const { return MemberDecl; }
void setMemberDecl(ValueDecl *D) { MemberDecl = D; }
/// \brief Retrieves the declaration found by lookup.
DeclAccessPair getFoundDecl() const {
if (!HasQualifierOrFoundDecl)
return DeclAccessPair::make(getMemberDecl(),
getMemberDecl()->getAccess());
return getTrailingObjects<MemberExprNameQualifier>()->FoundDecl;
}
/// \brief Determines whether this member expression actually had
/// a C++ nested-name-specifier prior to the name of the member, e.g.,
/// x->Base::foo.
bool hasQualifier() const { return getQualifier() != nullptr; }
/// \brief If the member name was qualified, retrieves the
/// nested-name-specifier that precedes the member name, with source-location
/// information.
NestedNameSpecifierLoc getQualifierLoc() const {
if (!HasQualifierOrFoundDecl)
return NestedNameSpecifierLoc();
return getTrailingObjects<MemberExprNameQualifier>()->QualifierLoc;
}
/// \brief If the member name was qualified, retrieves the
/// nested-name-specifier that precedes the member name. Otherwise, returns
/// NULL.
NestedNameSpecifier *getQualifier() const {
return getQualifierLoc().getNestedNameSpecifier();
}
/// \brief Retrieve the location of the template keyword preceding
/// the member name, if any.
SourceLocation getTemplateKeywordLoc() const {
if (!HasTemplateKWAndArgsInfo) return SourceLocation();
return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->TemplateKWLoc;
}
/// \brief Retrieve the location of the left angle bracket starting the
/// explicit template argument list following the member name, if any.
SourceLocation getLAngleLoc() const {
if (!HasTemplateKWAndArgsInfo) return SourceLocation();
return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->LAngleLoc;
}
/// \brief Retrieve the location of the right angle bracket ending the
/// explicit template argument list following the member name, if any.
SourceLocation getRAngleLoc() const {
if (!HasTemplateKWAndArgsInfo) return SourceLocation();
return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->RAngleLoc;
}
/// Determines whether the member name was preceded by the template keyword.
bool hasTemplateKeyword() const { return getTemplateKeywordLoc().isValid(); }
/// \brief Determines whether the member name was followed by an
/// explicit template argument list.
bool hasExplicitTemplateArgs() const { return getLAngleLoc().isValid(); }
/// \brief Copies the template arguments (if present) into the given
/// structure.
void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const {
if (hasExplicitTemplateArgs())
getTrailingObjects<ASTTemplateKWAndArgsInfo>()->copyInto(
getTrailingObjects<TemplateArgumentLoc>(), List);
}
/// \brief Retrieve the template arguments provided as part of this
/// template-id.
const TemplateArgumentLoc *getTemplateArgs() const {
if (!hasExplicitTemplateArgs())
return nullptr;
return getTrailingObjects<TemplateArgumentLoc>();
}
/// \brief Retrieve the number of template arguments provided as part of this
/// template-id.
unsigned getNumTemplateArgs() const {
if (!hasExplicitTemplateArgs())
return 0;
return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->NumTemplateArgs;
}
ArrayRef<TemplateArgumentLoc> template_arguments() const {
return {getTemplateArgs(), getNumTemplateArgs()};
}
/// \brief Retrieve the member declaration name info.
DeclarationNameInfo getMemberNameInfo() const {
return DeclarationNameInfo(MemberDecl->getDeclName(),
MemberLoc, MemberDNLoc);
}
SourceLocation getOperatorLoc() const LLVM_READONLY { return OperatorLoc; }
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 getMemberLoc() const { return MemberLoc; }
void setMemberLoc(SourceLocation L) { MemberLoc = L; }
SourceLocation getLocStart() const LLVM_READONLY;
SourceLocation getLocEnd() const LLVM_READONLY;
SourceLocation getExprLoc() const LLVM_READONLY { return MemberLoc; }
/// \brief Determine whether the base of this explicit is implicit.
bool isImplicitAccess() const {
return getBase() && getBase()->isImplicitCXXThis();
}
/// \brief Returns true if this member expression refers to a method that
/// was resolved from an overloaded set having size greater than 1.
bool hadMultipleCandidates() const {
return HadMultipleCandidates;
}
/// \brief Sets the flag telling whether this expression refers to
/// a method that was resolved from an overloaded set having size
/// greater than 1.
void setHadMultipleCandidates(bool V = true) {
HadMultipleCandidates = V;
}
/// \brief Returns true if virtual dispatch is performed.
/// If the member access is fully qualified, (i.e. X::f()), virtual
/// dispatching is not performed. In -fapple-kext mode qualified
/// calls to virtual method will still go through the vtable.
bool performsVirtualDispatch(const LangOptions &LO) const {
return LO.AppleKext || !hasQualifier();
}
static bool classof(const Stmt *T) {
return T->getStmtClass() == MemberExprClass;
}
// Iterators
child_range children() { return child_range(&Base, &Base+1); }
friend TrailingObjects;
friend class ASTReader;
friend class ASTStmtWriter;
};
/// CompoundLiteralExpr - [C99 6.5.2.5]
///
class CompoundLiteralExpr : public Expr {
/// LParenLoc - If non-null, this is the location of the left paren in a
/// compound literal like "(int){4}". This can be null if this is a
/// synthesized compound expression.
SourceLocation LParenLoc;
/// The type as written. This can be an incomplete array type, in
/// which case the actual expression type will be different.
/// The int part of the pair stores whether this expr is file scope.
llvm::PointerIntPair<TypeSourceInfo *, 1, bool> TInfoAndScope;
Stmt *Init;
public:
CompoundLiteralExpr(SourceLocation lparenloc, TypeSourceInfo *tinfo,
QualType T, ExprValueKind VK, Expr *init, bool fileScope)
: Expr(CompoundLiteralExprClass, T, VK, OK_Ordinary,
tinfo->getType()->isDependentType(),
init->isValueDependent(),
(init->isInstantiationDependent() ||
tinfo->getType()->isInstantiationDependentType()),
init->containsUnexpandedParameterPack()),
LParenLoc(lparenloc), TInfoAndScope(tinfo, fileScope), Init(init) {}
/// \brief Construct an empty compound literal.
explicit CompoundLiteralExpr(EmptyShell Empty)
: Expr(CompoundLiteralExprClass, Empty) { }
const Expr *getInitializer() const { return cast<Expr>(Init); }
Expr *getInitializer() { return cast<Expr>(Init); }
void setInitializer(Expr *E) { Init = E; }
bool isFileScope() const { return TInfoAndScope.getInt(); }
void setFileScope(bool FS) { TInfoAndScope.setInt(FS); }
SourceLocation getLParenLoc() const { return LParenLoc; }
void setLParenLoc(SourceLocation L) { LParenLoc = L; }
TypeSourceInfo *getTypeSourceInfo() const {
return TInfoAndScope.getPointer();
}
void setTypeSourceInfo(TypeSourceInfo *tinfo) {
TInfoAndScope.setPointer(tinfo);
}
SourceLocation getLocStart() const LLVM_READONLY {
// FIXME: Init should never be null.
if (!Init)
return SourceLocation();
if (LParenLoc.isInvalid())
return Init->getLocStart();
return LParenLoc;
}
SourceLocation getLocEnd() const LLVM_READONLY {
// FIXME: Init should never be null.
if (!Init)
return SourceLocation();
return Init->getLocEnd();
}
static bool classof(const Stmt *T) {
return T->getStmtClass() == CompoundLiteralExprClass;
}
// Iterators
child_range children() { return child_range(&Init, &Init+1); }
};
/// CastExpr - Base class for type casts, including both implicit
/// casts (ImplicitCastExpr) and explicit casts that have some
/// representation in the source code (ExplicitCastExpr's derived
/// classes).
class CastExpr : public Expr {
private:
Stmt *Op;
bool CastConsistency() const;
const CXXBaseSpecifier * const *path_buffer() const {
return const_cast<CastExpr*>(this)->path_buffer();
}
CXXBaseSpecifier **path_buffer();
void setBasePathSize(unsigned basePathSize) {
CastExprBits.BasePathSize = basePathSize;
assert(CastExprBits.BasePathSize == basePathSize &&
"basePathSize doesn't fit in bits of CastExprBits.BasePathSize!");
}
protected:
CastExpr(StmtClass SC, QualType ty, ExprValueKind VK, const CastKind kind,
Expr *op, unsigned BasePathSize)
: Expr(SC, ty, VK, OK_Ordinary,
// Cast expressions are type-dependent if the type is
// dependent (C++ [temp.dep.expr]p3).
ty->isDependentType(),
// Cast expressions are value-dependent if the type is
// dependent or if the subexpression is value-dependent.
ty->isDependentType() || (op && op->isValueDependent()),
(ty->isInstantiationDependentType() ||
(op && op->isInstantiationDependent())),
// An implicit cast expression doesn't (lexically) contain an
// unexpanded pack, even if its target type does.
((SC != ImplicitCastExprClass &&
ty->containsUnexpandedParameterPack()) ||
(op && op->containsUnexpandedParameterPack()))),
Op(op) {
assert(kind != CK_Invalid && "creating cast with invalid cast kind");
CastExprBits.Kind = kind;
setBasePathSize(BasePathSize);
assert(CastConsistency());
}
/// \brief Construct an empty cast.
CastExpr(StmtClass SC, EmptyShell Empty, unsigned BasePathSize)
: Expr(SC, Empty) {
setBasePathSize(BasePathSize);
}
public:
CastKind getCastKind() const { return (CastKind) CastExprBits.Kind; }
void setCastKind(CastKind K) { CastExprBits.Kind = K; }
const char *getCastKindName() const;
Expr *getSubExpr() { return cast<Expr>(Op); }
const Expr *getSubExpr() const { return cast<Expr>(Op); }
void setSubExpr(Expr *E) { Op = E; }
/// \brief Retrieve the cast subexpression as it was written in the source
/// code, looking through any implicit casts or other intermediate nodes
/// introduced by semantic analysis.
Expr *getSubExprAsWritten();
const Expr *getSubExprAsWritten() const {
return const_cast<CastExpr *>(this)->getSubExprAsWritten();
}
typedef CXXBaseSpecifier **path_iterator;
typedef const CXXBaseSpecifier * const *path_const_iterator;
bool path_empty() const { return CastExprBits.BasePathSize == 0; }
unsigned path_size() const { return CastExprBits.BasePathSize; }
path_iterator path_begin() { return path_buffer(); }
path_iterator path_end() { return path_buffer() + path_size(); }
path_const_iterator path_begin() const { return path_buffer(); }
path_const_iterator path_end() const { return path_buffer() + path_size(); }
static bool classof(const Stmt *T) {
return T->getStmtClass() >= firstCastExprConstant &&
T->getStmtClass() <= lastCastExprConstant;
}
// Iterators
child_range children() { return child_range(&Op, &Op+1); }
};
/// ImplicitCastExpr - Allows us to explicitly represent implicit type
/// conversions, which have no direct representation in the original
/// source code. For example: converting T[]->T*, void f()->void
/// (*f)(), float->double, short->int, etc.
///
/// In C, implicit casts always produce rvalues. However, in C++, an
/// implicit cast whose result is being bound to a reference will be
/// an lvalue or xvalue. For example:
///
/// @code
/// class Base { };
/// class Derived : public Base { };
/// Derived &&ref();
/// void f(Derived d) {
/// Base& b = d; // initializer is an ImplicitCastExpr
/// // to an lvalue of type Base
/// Base&& r = ref(); // initializer is an ImplicitCastExpr
/// // to an xvalue of type Base
/// }
/// @endcode
class ImplicitCastExpr final
: public CastExpr,
private llvm::TrailingObjects<ImplicitCastExpr, CXXBaseSpecifier *> {
private:
ImplicitCastExpr(QualType ty, CastKind kind, Expr *op,
unsigned BasePathLength, ExprValueKind VK)
: CastExpr(ImplicitCastExprClass, ty, VK, kind, op, BasePathLength) {
}
/// \brief Construct an empty implicit cast.
explicit ImplicitCastExpr(EmptyShell Shell, unsigned PathSize)
: CastExpr(ImplicitCastExprClass, Shell, PathSize) { }
public:
enum OnStack_t { OnStack };
ImplicitCastExpr(OnStack_t _, QualType ty, CastKind kind, Expr *op,
ExprValueKind VK)
: CastExpr(ImplicitCastExprClass, ty, VK, kind, op, 0) {
}
static ImplicitCastExpr *Create(const ASTContext &Context, QualType T,
CastKind Kind, Expr *Operand,
const CXXCastPath *BasePath,
ExprValueKind Cat);
static ImplicitCastExpr *CreateEmpty(const ASTContext &Context,
unsigned PathSize);
SourceLocation getLocStart() const LLVM_READONLY {
return getSubExpr()->getLocStart();
}
SourceLocation getLocEnd() const LLVM_READONLY {
return getSubExpr()->getLocEnd();
}
static bool classof(const Stmt *T) {
return T->getStmtClass() == ImplicitCastExprClass;
}
friend TrailingObjects;
friend class CastExpr;
};
inline Expr *Expr::IgnoreImpCasts() {
Expr *e = this;
while (ImplicitCastExpr *ice = dyn_cast<ImplicitCastExpr>(e))
e = ice->getSubExpr();
return e;
}
/// ExplicitCastExpr - An explicit cast written in the source
/// code.
///
/// This class is effectively an abstract class, because it provides
/// the basic representation of an explicitly-written cast without
/// specifying which kind of cast (C cast, functional cast, static
/// cast, etc.) was written; specific derived classes represent the
/// particular style of cast and its location information.
///
/// Unlike implicit casts, explicit cast nodes have two different
/// types: the type that was written into the source code, and the
/// actual type of the expression as determined by semantic
/// analysis. These types may differ slightly. For example, in C++ one
/// can cast to a reference type, which indicates that the resulting
/// expression will be an lvalue or xvalue. The reference type, however,
/// will not be used as the type of the expression.
class ExplicitCastExpr : public CastExpr {
/// TInfo - Source type info for the (written) type
/// this expression is casting to.
TypeSourceInfo *TInfo;
protected:
ExplicitCastExpr(StmtClass SC, QualType exprTy, ExprValueKind VK,
CastKind kind, Expr *op, unsigned PathSize,
TypeSourceInfo *writtenTy)
: CastExpr(SC, exprTy, VK, kind, op, PathSize), TInfo(writtenTy) {}
/// \brief Construct an empty explicit cast.
ExplicitCastExpr(StmtClass SC, EmptyShell Shell, unsigned PathSize)
: CastExpr(SC, Shell, PathSize) { }
public:
/// getTypeInfoAsWritten - Returns the type source info for the type
/// that this expression is casting to.
TypeSourceInfo *getTypeInfoAsWritten() const { return TInfo; }
void setTypeInfoAsWritten(TypeSourceInfo *writtenTy) { TInfo = writtenTy; }
/// getTypeAsWritten - Returns the type that this expression is
/// casting to, as written in the source code.
QualType getTypeAsWritten() const { return TInfo->getType(); }
static bool classof(const Stmt *T) {
return T->getStmtClass() >= firstExplicitCastExprConstant &&
T->getStmtClass() <= lastExplicitCastExprConstant;
}
};
/// CStyleCastExpr - An explicit cast in C (C99 6.5.4) or a C-style
/// cast in C++ (C++ [expr.cast]), which uses the syntax
/// (Type)expr. For example: @c (int)f.
class CStyleCastExpr final
: public ExplicitCastExpr,
private llvm::TrailingObjects<CStyleCastExpr, CXXBaseSpecifier *> {
SourceLocation LPLoc; // the location of the left paren
SourceLocation RPLoc; // the location of the right paren
CStyleCastExpr(QualType exprTy, ExprValueKind vk, CastKind kind, Expr *op,
unsigned PathSize, TypeSourceInfo *writtenTy,
SourceLocation l, SourceLocation r)
: ExplicitCastExpr(CStyleCastExprClass, exprTy, vk, kind, op, PathSize,
writtenTy), LPLoc(l), RPLoc(r) {}
/// \brief Construct an empty C-style explicit cast.
explicit CStyleCastExpr(EmptyShell Shell, unsigned PathSize)
: ExplicitCastExpr(CStyleCastExprClass, Shell, PathSize) { }
public:
static CStyleCastExpr *Create(const ASTContext &Context, QualType T,
ExprValueKind VK, CastKind K,
Expr *Op, const CXXCastPath *BasePath,
TypeSourceInfo *WrittenTy, SourceLocation L,
SourceLocation R);
static CStyleCastExpr *CreateEmpty(const ASTContext &Context,
unsigned PathSize);
SourceLocation getLParenLoc() const { return LPLoc; }
void setLParenLoc(SourceLocation L) { LPLoc = L; }
SourceLocation getRParenLoc() const { return RPLoc; }