2009-06-02 17:58:47 +00:00
|
|
|
//===--- 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"
|
2012-08-15 20:02:54 +00:00
|
|
|
#include "clang/AST/Decl.h"
|
2009-06-02 17:58:47 +00:00
|
|
|
#include "clang/AST/Stmt.h"
|
|
|
|
#include "clang/AST/Type.h"
|
2010-05-04 16:12:48 +00:00
|
|
|
#include "clang/AST/DeclAccessPair.h"
|
2010-09-17 15:54:40 +00:00
|
|
|
#include "clang/AST/OperationKinds.h"
|
2010-05-04 16:12:48 +00:00
|
|
|
#include "clang/AST/ASTVector.h"
|
2011-10-20 21:14:49 +00:00
|
|
|
#include "clang/AST/TemplateBase.h"
|
2012-04-14 14:01:31 +00:00
|
|
|
#include "clang/Basic/TargetInfo.h"
|
2011-05-02 19:39:53 +00:00
|
|
|
#include "clang/Basic/TypeTraits.h"
|
2009-06-02 17:58:47 +00:00
|
|
|
#include "llvm/ADT/APSInt.h"
|
|
|
|
#include "llvm/ADT/APFloat.h"
|
|
|
|
#include "llvm/ADT/SmallVector.h"
|
2009-10-14 18:03:49 +00:00
|
|
|
#include "llvm/ADT/StringRef.h"
|
2012-04-14 14:01:31 +00:00
|
|
|
#include "llvm/Support/Compiler.h"
|
2011-02-20 13:06:31 +00:00
|
|
|
#include <cctype>
|
2009-06-02 17:58:47 +00:00
|
|
|
|
|
|
|
namespace clang {
|
|
|
|
class ASTContext;
|
|
|
|
class APValue;
|
2012-12-02 13:20:44 +00:00
|
|
|
class CastExpr;
|
2009-06-02 17:58:47 +00:00
|
|
|
class Decl;
|
|
|
|
class IdentifierInfo;
|
|
|
|
class ParmVarDecl;
|
|
|
|
class NamedDecl;
|
|
|
|
class ValueDecl;
|
|
|
|
class BlockDecl;
|
2010-05-04 16:12:48 +00:00
|
|
|
class CXXBaseSpecifier;
|
2009-06-02 17:58:47 +00:00
|
|
|
class CXXOperatorCallExpr;
|
2012-12-02 13:20:44 +00:00
|
|
|
class MaterializeTemporaryExpr;
|
2009-06-02 17:58:47 +00:00
|
|
|
class CXXMemberCallExpr;
|
2011-02-20 13:06:31 +00:00
|
|
|
class ObjCPropertyRefExpr;
|
|
|
|
class OpaqueValueExpr;
|
2009-06-02 17:58:47 +00:00
|
|
|
|
2010-05-04 16:12:48 +00:00
|
|
|
/// \brief A simple array of base specifiers.
|
2011-10-20 21:14:49 +00:00
|
|
|
typedef SmallVector<CXXBaseSpecifier*, 4> CXXCastPath;
|
2010-05-04 16:12:48 +00:00
|
|
|
|
2012-12-02 13:20:44 +00:00
|
|
|
/// \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;
|
|
|
|
|
|
|
|
union {
|
|
|
|
struct {
|
|
|
|
const CastExpr *BasePath;
|
|
|
|
const CXXRecordDecl *DerivedClass;
|
|
|
|
} DerivedToBase;
|
|
|
|
|
|
|
|
FieldDecl *Field;
|
|
|
|
|
|
|
|
struct {
|
|
|
|
const MemberPointerType *MPT;
|
|
|
|
Expr *RHS;
|
|
|
|
} 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;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
/// 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:
|
2011-02-20 13:06:31 +00:00
|
|
|
Expr(StmtClass SC, QualType T, ExprValueKind VK, ExprObjectKind OK,
|
2012-04-14 14:01:31 +00:00
|
|
|
bool TD, bool VD, bool ID, bool ContainsUnexpandedParameterPack)
|
|
|
|
: Stmt(SC)
|
2011-07-17 15:40:56 +00:00
|
|
|
{
|
2011-02-20 13:06:31 +00:00
|
|
|
ExprBits.TypeDependent = TD;
|
|
|
|
ExprBits.ValueDependent = VD;
|
2011-07-17 15:40:56 +00:00
|
|
|
ExprBits.InstantiationDependent = ID;
|
2011-02-20 13:06:31 +00:00
|
|
|
ExprBits.ValueKind = VK;
|
|
|
|
ExprBits.ObjectKind = OK;
|
|
|
|
ExprBits.ContainsUnexpandedParameterPack = ContainsUnexpandedParameterPack;
|
2009-06-02 17:58:47 +00:00
|
|
|
setType(T);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// \brief Construct an empty expression.
|
|
|
|
explicit Expr(StmtClass SC, EmptyShell) : Stmt(SC) { }
|
|
|
|
|
2009-10-14 18:03:49 +00:00
|
|
|
public:
|
2009-06-02 17:58:47 +00:00
|
|
|
QualType getType() const { return TR; }
|
2009-10-14 18:03:49 +00:00
|
|
|
void setType(QualType t) {
|
2009-06-02 17:58:47 +00:00
|
|
|
// In C++, the type of an expression is always adjusted so that it
|
|
|
|
// will not have reference type an expression will never 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.
|
2009-11-18 14:59:57 +00:00
|
|
|
assert((t.isNull() || !t->isReferenceType()) &&
|
2009-06-02 17:58:47 +00:00
|
|
|
"Expressions can't have reference type");
|
|
|
|
|
2009-10-14 18:03:49 +00:00
|
|
|
TR = t;
|
2009-06-02 17:58:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// isValueDependent - Determines whether this expression is
|
|
|
|
/// value-dependent (C++ [temp.dep.constexpr]). For example, the
|
|
|
|
/// array bound of "Chars" in the following example is
|
2009-10-14 18:03:49 +00:00
|
|
|
/// value-dependent.
|
2009-06-02 17:58:47 +00:00
|
|
|
/// @code
|
|
|
|
/// template<int Size, char (&Chars)[Size]> struct meta_string;
|
|
|
|
/// @endcode
|
2011-02-20 13:06:31 +00:00
|
|
|
bool isValueDependent() const { return ExprBits.ValueDependent; }
|
2009-06-02 17:58:47 +00:00
|
|
|
|
|
|
|
/// \brief Set whether this expression is value-dependent or not.
|
2012-04-14 14:01:31 +00:00
|
|
|
void setValueDependent(bool VD) {
|
|
|
|
ExprBits.ValueDependent = VD;
|
2011-07-17 15:40:56 +00:00
|
|
|
if (VD)
|
|
|
|
ExprBits.InstantiationDependent = true;
|
|
|
|
}
|
2009-06-02 17:58:47 +00:00
|
|
|
|
|
|
|
/// 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
|
2009-10-14 18:03:49 +00:00
|
|
|
/// template<typename T>
|
2009-06-02 17:58:47 +00:00
|
|
|
/// void add(T x, int y) {
|
|
|
|
/// x + y;
|
|
|
|
/// }
|
|
|
|
/// @endcode
|
2011-02-20 13:06:31 +00:00
|
|
|
bool isTypeDependent() const { return ExprBits.TypeDependent; }
|
2009-06-02 17:58:47 +00:00
|
|
|
|
|
|
|
/// \brief Set whether this expression is type-dependent or not.
|
2012-04-14 14:01:31 +00:00
|
|
|
void setTypeDependent(bool TD) {
|
|
|
|
ExprBits.TypeDependent = TD;
|
2011-07-17 15:40:56 +00:00
|
|
|
if (TD)
|
|
|
|
ExprBits.InstantiationDependent = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// \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
|
|
|
|
///
|
2012-04-14 14:01:31 +00:00
|
|
|
bool isInstantiationDependent() const {
|
|
|
|
return ExprBits.InstantiationDependent;
|
2011-07-17 15:40:56 +00:00
|
|
|
}
|
2012-04-14 14:01:31 +00:00
|
|
|
|
2011-07-17 15:40:56 +00:00
|
|
|
/// \brief Set whether this expression is instantiation-dependent or not.
|
2012-04-14 14:01:31 +00:00
|
|
|
void setInstantiationDependent(bool ID) {
|
2011-07-17 15:40:56 +00:00
|
|
|
ExprBits.InstantiationDependent = ID;
|
|
|
|
}
|
2011-02-20 13:06:31 +00:00
|
|
|
|
|
|
|
/// \brief Whether this expression contains an unexpanded parameter
|
|
|
|
/// pack (for C++0x 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.
|
2012-04-14 14:01:31 +00:00
|
|
|
bool containsUnexpandedParameterPack() const {
|
|
|
|
return ExprBits.ContainsUnexpandedParameterPack;
|
2011-02-20 13:06:31 +00:00
|
|
|
}
|
2009-06-02 17:58:47 +00:00
|
|
|
|
2011-02-20 13:06:31 +00:00
|
|
|
/// \brief Set the bit that describes whether this expression
|
|
|
|
/// contains an unexpanded parameter pack.
|
|
|
|
void setContainsUnexpandedParameterPack(bool PP = true) {
|
|
|
|
ExprBits.ContainsUnexpandedParameterPack = PP;
|
|
|
|
}
|
2009-06-02 17:58:47 +00:00
|
|
|
|
|
|
|
/// getExprLoc - Return the preferred location for the arrow when diagnosing
|
|
|
|
/// a problem with a generic expression.
|
2012-04-14 14:01:31 +00:00
|
|
|
SourceLocation getExprLoc() const LLVM_READONLY;
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
/// isUnusedResultAWarning - Return true if this immediate expression should
|
2012-08-15 20:02:54 +00:00
|
|
|
/// 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;
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2011-02-20 13:06:31 +00:00
|
|
|
/// 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.
|
2009-06-02 17:58:47 +00:00
|
|
|
///
|
2011-02-20 13:06:31 +00:00
|
|
|
/// C++0x 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 {
|
2009-06-02 17:58:47 +00:00
|
|
|
LV_Valid,
|
|
|
|
LV_NotObjectType,
|
|
|
|
LV_IncompleteVoidType,
|
|
|
|
LV_DuplicateVectorComponents,
|
|
|
|
LV_InvalidExpression,
|
2011-05-02 19:39:53 +00:00
|
|
|
LV_InvalidMessageExpression,
|
2010-01-01 10:34:51 +00:00
|
|
|
LV_MemberFunction,
|
2010-02-16 09:31:36 +00:00
|
|
|
LV_SubObjCPropertySetting,
|
2012-08-15 20:02:54 +00:00
|
|
|
LV_ClassTemporary,
|
|
|
|
LV_ArrayTemporary
|
2009-06-02 17:58:47 +00:00
|
|
|
};
|
2011-02-20 13:06:31 +00:00
|
|
|
/// Reasons why an expression might not be an l-value.
|
|
|
|
LValueClassification ClassifyLValue(ASTContext &Ctx) const;
|
2009-06-02 17:58:47 +00:00
|
|
|
|
|
|
|
enum isModifiableLvalueResult {
|
|
|
|
MLV_Valid,
|
|
|
|
MLV_NotObjectType,
|
|
|
|
MLV_IncompleteVoidType,
|
|
|
|
MLV_DuplicateVectorComponents,
|
|
|
|
MLV_InvalidExpression,
|
|
|
|
MLV_LValueCast, // Specialized form of MLV_InvalidExpression.
|
|
|
|
MLV_IncompleteType,
|
|
|
|
MLV_ConstQualified,
|
|
|
|
MLV_ArrayType,
|
|
|
|
MLV_ReadonlyProperty,
|
|
|
|
MLV_NoSetterProperty,
|
2010-01-01 10:34:51 +00:00
|
|
|
MLV_MemberFunction,
|
2010-02-16 09:31:36 +00:00
|
|
|
MLV_SubObjCPropertySetting,
|
2011-05-02 19:39:53 +00:00
|
|
|
MLV_InvalidMessageExpression,
|
2012-08-15 20:02:54 +00:00
|
|
|
MLV_ClassTemporary,
|
|
|
|
MLV_ArrayTemporary
|
2009-06-02 17:58:47 +00:00
|
|
|
};
|
2012-12-02 13:20:44 +00:00
|
|
|
/// 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.
|
2009-06-02 17:58:47 +00:00
|
|
|
isModifiableLvalueResult isModifiableLvalue(ASTContext &Ctx,
|
|
|
|
SourceLocation *Loc = 0) const;
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2010-07-13 17:21:42 +00:00
|
|
|
/// \brief The return type of classify(). Represents the C++0x 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.
|
2011-05-02 19:39:53 +00:00
|
|
|
CL_AddressableVoid, // Void expression whose address can be taken in C.
|
2010-07-13 17:21:42 +00:00
|
|
|
CL_DuplicateVectorComponents, // A vector shuffle with dupes.
|
|
|
|
CL_MemberFunction, // An expression referring to a member function
|
|
|
|
CL_SubObjCPropertySetting,
|
2012-08-15 20:02:54 +00:00
|
|
|
CL_ClassTemporary, // A temporary of class type, or subobject thereof.
|
|
|
|
CL_ArrayTemporary, // A temporary of array type.
|
2011-05-02 19:39:53 +00:00
|
|
|
CL_ObjCMessageRValue, // ObjC message is an rvalue
|
2010-07-13 17:21:42 +00:00
|
|
|
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_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; }
|
2012-04-14 14:01:31 +00:00
|
|
|
|
2011-02-20 13:06:31 +00:00
|
|
|
/// \brief Create a simple, modifiably lvalue
|
|
|
|
static Classification makeSimpleLValue() {
|
|
|
|
return Classification(CL_LValue, CM_Modifiable);
|
|
|
|
}
|
2012-04-14 14:01:31 +00:00
|
|
|
|
2010-07-13 17:21:42 +00:00
|
|
|
};
|
2011-02-20 13:06:31 +00:00
|
|
|
/// \brief Classify - Classify this expression according to the C++0x
|
2010-07-13 17:21:42 +00:00
|
|
|
/// expression taxonomy.
|
|
|
|
///
|
|
|
|
/// C++0x 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, 0);
|
|
|
|
}
|
|
|
|
|
2011-02-20 13:06:31 +00:00
|
|
|
/// \brief ClassifyModifiable - Classify this expression according to the
|
2010-07-13 17:21:42 +00:00
|
|
|
/// C++0x 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);
|
|
|
|
}
|
|
|
|
|
2011-02-20 13:06:31 +00:00
|
|
|
/// 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; }
|
|
|
|
|
2010-07-13 17:21:42 +00:00
|
|
|
private:
|
|
|
|
Classification ClassifyImpl(ASTContext &Ctx, SourceLocation *Loc) const;
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
/// \brief If this expression refers to a bit-field, retrieve the
|
|
|
|
/// declaration of that bit-field.
|
|
|
|
FieldDecl *getBitField();
|
|
|
|
|
|
|
|
const FieldDecl *getBitField() const {
|
|
|
|
return const_cast<Expr*>(this)->getBitField();
|
|
|
|
}
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2011-02-20 13:06:31 +00:00
|
|
|
/// \brief If this expression is an l-value for an Objective C
|
|
|
|
/// property, find the underlying property reference expression.
|
|
|
|
const ObjCPropertyRefExpr *getObjCProperty() const;
|
|
|
|
|
2012-12-02 13:20:44 +00:00
|
|
|
/// \brief Check if this expression is the ObjC 'self' implicit parameter.
|
|
|
|
bool isObjCSelfExpr() const;
|
|
|
|
|
2010-02-16 09:31:36 +00:00
|
|
|
/// \brief Returns whether this expression refers to a vector element.
|
|
|
|
bool refersToVectorElement() const;
|
2012-04-14 14:01:31 +00:00
|
|
|
|
|
|
|
/// \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;
|
|
|
|
}
|
|
|
|
|
2010-05-04 16:12:48 +00:00
|
|
|
/// 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;
|
2012-04-14 14:01:31 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
/// 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.
|
2012-04-14 14:01:31 +00:00
|
|
|
///
|
|
|
|
/// Note: This does not perform the implicit conversions required by C++11
|
|
|
|
/// [expr.const]p5.
|
2009-06-02 17:58:47 +00:00
|
|
|
bool isIntegerConstantExpr(llvm::APSInt &Result, ASTContext &Ctx,
|
|
|
|
SourceLocation *Loc = 0,
|
|
|
|
bool isEvaluated = true) const;
|
2012-04-14 14:01:31 +00:00
|
|
|
bool isIntegerConstantExpr(ASTContext &Ctx, SourceLocation *Loc = 0) const;
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2012-04-14 14:01:31 +00:00
|
|
|
/// isCXX98IntegralConstantExpr - Return true if this expression is an
|
|
|
|
/// integral constant expression in C++98. Can only be used in C++.
|
|
|
|
bool isCXX98IntegralConstantExpr(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(ASTContext &Ctx, APValue *Result = 0,
|
|
|
|
SourceLocation *Loc = 0) 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,
|
|
|
|
llvm::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.
|
|
|
|
bool isConstantInitializer(ASTContext &Ctx, bool ForRef) const;
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2012-04-14 14:01:31 +00:00
|
|
|
/// EvalStatus is a struct with detailed info about an evaluation in progress.
|
|
|
|
struct EvalStatus {
|
2009-06-02 17:58:47 +00:00
|
|
|
/// HasSideEffects - Whether the evaluated expression has side effects.
|
|
|
|
/// For example, (f() && 0) can be folded, but it still has side effects.
|
|
|
|
bool HasSideEffects;
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2012-04-14 14:01:31 +00:00
|
|
|
/// 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.
|
|
|
|
llvm::SmallVectorImpl<PartialDiagnosticAt> *Diag;
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2012-04-14 14:01:31 +00:00
|
|
|
EvalStatus() : HasSideEffects(false), Diag(0) {}
|
2010-05-27 15:17:06 +00:00
|
|
|
|
|
|
|
// hasSideEffects - Return true if the evaluated expression has
|
|
|
|
// side effects.
|
|
|
|
bool hasSideEffects() const {
|
|
|
|
return HasSideEffects;
|
|
|
|
}
|
2009-06-02 17:58:47 +00:00
|
|
|
};
|
|
|
|
|
2012-04-14 14:01:31 +00:00
|
|
|
/// 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;
|
2009-06-02 17:58:47 +00:00
|
|
|
|
2010-01-15 15:39:40 +00:00
|
|
|
/// EvaluateAsBooleanCondition - Return true if this is a constant
|
|
|
|
/// which we we can fold and convert to a boolean condition using
|
2011-10-20 21:14:49 +00:00
|
|
|
/// any crazy technique that we want to, even if the expression has
|
|
|
|
/// side-effects.
|
2011-02-20 13:06:31 +00:00
|
|
|
bool EvaluateAsBooleanCondition(bool &Result, const ASTContext &Ctx) const;
|
2010-01-15 15:39:40 +00:00
|
|
|
|
2012-04-14 14:01:31 +00:00
|
|
|
enum SideEffectsKind { SE_NoSideEffects, SE_AllowSideEffects };
|
|
|
|
|
2011-10-20 21:14:49 +00:00
|
|
|
/// EvaluateAsInt - Return true if this is a constant which we can fold and
|
2012-04-14 14:01:31 +00:00
|
|
|
/// 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;
|
2011-10-20 21:14:49 +00:00
|
|
|
|
2012-04-14 14:01:31 +00:00
|
|
|
/// isEvaluatable - Call EvaluateAsRValue to see if this expression can be
|
|
|
|
/// constant folded without side-effects, but discard the result.
|
2011-02-20 13:06:31 +00:00
|
|
|
bool isEvaluatable(const ASTContext &Ctx) const;
|
2009-06-02 17:58:47 +00:00
|
|
|
|
2009-11-18 14:59:57 +00:00
|
|
|
/// HasSideEffects - This routine returns true for all those expressions
|
2012-08-15 20:02:54 +00:00
|
|
|
/// which have any effect other than producing a value. Example is a function
|
|
|
|
/// call, volatile variable read, or throwing an exception.
|
2011-02-20 13:06:31 +00:00
|
|
|
bool HasSideEffects(const ASTContext &Ctx) const;
|
2012-04-14 14:01:31 +00:00
|
|
|
|
|
|
|
/// \brief Determine whether this expression involves a call to any function
|
|
|
|
/// that is not trivial.
|
|
|
|
bool hasNonTrivialCall(ASTContext &Ctx);
|
2009-11-18 14:59:57 +00:00
|
|
|
|
2012-04-14 14:01:31 +00:00
|
|
|
/// EvaluateKnownConstInt - Call EvaluateAsRValue and return the folded
|
|
|
|
/// integer. This must be called on an expression that constant folds to an
|
|
|
|
/// integer.
|
2011-10-20 21:14:49 +00:00
|
|
|
llvm::APSInt EvaluateKnownConstInt(const ASTContext &Ctx) const;
|
2009-06-02 17:58:47 +00:00
|
|
|
|
2012-04-14 14:01:31 +00:00
|
|
|
/// EvaluateAsLValue - Evaluate an expression to see if we can fold it to an
|
|
|
|
/// lvalue with link time known address, with no side-effects.
|
2011-02-20 13:06:31 +00:00
|
|
|
bool EvaluateAsLValue(EvalResult &Result, const ASTContext &Ctx) const;
|
2009-06-02 17:58:47 +00:00
|
|
|
|
2012-04-14 14:01:31 +00:00
|
|
|
/// 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,
|
|
|
|
llvm::SmallVectorImpl<PartialDiagnosticAt> &Notes) const;
|
2011-02-20 13:06:31 +00:00
|
|
|
|
|
|
|
/// \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,
|
|
|
|
|
2012-08-15 20:02:54 +00:00
|
|
|
/// \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,
|
2011-02-20 13:06:31 +00:00
|
|
|
|
|
|
|
/// \brief Expression is a C++0X nullptr.
|
|
|
|
NPCK_CXX0X_nullptr,
|
|
|
|
|
|
|
|
/// \brief Expression is a GNU-style __null constant.
|
|
|
|
NPCK_GNUNull
|
|
|
|
};
|
2009-10-14 18:03:49 +00:00
|
|
|
|
|
|
|
/// \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,
|
2012-04-14 14:01:31 +00:00
|
|
|
|
2009-10-14 18:03:49 +00:00
|
|
|
/// \brief Specifies that a value-dependent expression of integral or
|
|
|
|
/// dependent type should be considered a null pointer constant.
|
|
|
|
NPC_ValueDependentIsNull,
|
2012-04-14 14:01:31 +00:00
|
|
|
|
2009-10-14 18:03:49 +00:00
|
|
|
/// \brief Specifies that a value-dependent expression should be considered
|
|
|
|
/// to never be a null pointer constant.
|
|
|
|
NPC_ValueDependentIsNotNull
|
|
|
|
};
|
2012-04-14 14:01:31 +00:00
|
|
|
|
2011-02-20 13:06:31 +00:00
|
|
|
/// 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;
|
2009-06-02 17:58:47 +00:00
|
|
|
|
|
|
|
/// isOBJCGCCandidate - Return true if this expression may be used in a read/
|
2009-10-14 18:03:49 +00:00
|
|
|
/// write barrier.
|
2009-06-02 17:58:47 +00:00
|
|
|
bool isOBJCGCCandidate(ASTContext &Ctx) const;
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2011-02-20 13:06:31 +00:00
|
|
|
/// \brief Returns true if this expression is a bound member function.
|
|
|
|
bool isBoundMemberFunction(ASTContext &Ctx) const;
|
|
|
|
|
2011-05-02 19:39:53 +00:00
|
|
|
/// \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);
|
|
|
|
|
2011-07-17 15:40:56 +00:00
|
|
|
/// IgnoreImpCasts - Skip past any implicit casts which might
|
|
|
|
/// surround this expression. Only skips ImplicitCastExprs.
|
2012-04-14 14:01:31 +00:00
|
|
|
Expr *IgnoreImpCasts() LLVM_READONLY;
|
2011-07-17 15:40:56 +00:00
|
|
|
|
|
|
|
/// IgnoreImplicit - Skip past any implicit AST nodes which might
|
|
|
|
/// surround this expression.
|
2012-04-14 14:01:31 +00:00
|
|
|
Expr *IgnoreImplicit() LLVM_READONLY {
|
|
|
|
return cast<Expr>(Stmt::IgnoreImplicit());
|
|
|
|
}
|
2011-07-17 15:40:56 +00:00
|
|
|
|
2012-08-15 20:02:54 +00:00
|
|
|
const Expr *IgnoreImplicit() const LLVM_READONLY {
|
|
|
|
return const_cast<Expr*>(this)->IgnoreImplicit();
|
|
|
|
}
|
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
/// IgnoreParens - Ignore parentheses. If this Expr is a ParenExpr, return
|
2009-10-14 18:03:49 +00:00
|
|
|
/// its subexpression. If that subexpression is also a ParenExpr,
|
2009-06-02 17:58:47 +00:00
|
|
|
/// then this method recursively returns its subexpression, and so forth.
|
|
|
|
/// Otherwise, the method returns the current Expr.
|
2012-04-14 14:01:31 +00:00
|
|
|
Expr *IgnoreParens() LLVM_READONLY;
|
2009-06-02 17:58:47 +00:00
|
|
|
|
|
|
|
/// IgnoreParenCasts - Ignore parentheses and casts. Strip off any ParenExpr
|
|
|
|
/// or CastExprs, returning their operand.
|
2012-04-14 14:01:31 +00:00
|
|
|
Expr *IgnoreParenCasts() LLVM_READONLY;
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2012-04-14 14:01:31 +00:00
|
|
|
/// IgnoreParenImpCasts - Ignore parentheses and implicit casts. Strip off
|
|
|
|
/// any ParenExpr or ImplicitCastExprs, returning their operand.
|
|
|
|
Expr *IgnoreParenImpCasts() LLVM_READONLY;
|
2010-05-27 15:17:06 +00:00
|
|
|
|
2011-06-12 15:46:16 +00:00
|
|
|
/// IgnoreConversionOperator - Ignore conversion operator. If this Expr is a
|
|
|
|
/// call to a conversion operator, return the argument.
|
2012-04-14 14:01:31 +00:00
|
|
|
Expr *IgnoreConversionOperator() LLVM_READONLY;
|
2011-06-12 15:46:16 +00:00
|
|
|
|
2012-04-14 14:01:31 +00:00
|
|
|
const Expr *IgnoreConversionOperator() const LLVM_READONLY {
|
2011-06-12 15:46:16 +00:00
|
|
|
return const_cast<Expr*>(this)->IgnoreConversionOperator();
|
|
|
|
}
|
|
|
|
|
2012-04-14 14:01:31 +00:00
|
|
|
const Expr *IgnoreParenImpCasts() const LLVM_READONLY {
|
2011-02-20 13:06:31 +00:00
|
|
|
return const_cast<Expr*>(this)->IgnoreParenImpCasts();
|
|
|
|
}
|
2012-04-14 14:01:31 +00:00
|
|
|
|
2011-02-20 13:06:31 +00:00
|
|
|
/// Ignore parentheses and lvalue casts. Strip off any ParenExpr and
|
|
|
|
/// CastExprs that represent lvalue casts, returning their operand.
|
2012-04-14 14:01:31 +00:00
|
|
|
Expr *IgnoreParenLValueCasts() LLVM_READONLY;
|
|
|
|
|
|
|
|
const Expr *IgnoreParenLValueCasts() const LLVM_READONLY {
|
2011-02-20 13:06:31 +00:00
|
|
|
return const_cast<Expr*>(this)->IgnoreParenLValueCasts();
|
|
|
|
}
|
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
/// 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.
|
2012-04-14 14:01:31 +00:00
|
|
|
Expr *IgnoreParenNoopCasts(ASTContext &Ctx) LLVM_READONLY;
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2012-08-15 20:02:54 +00:00
|
|
|
/// Ignore parentheses and derived-to-base casts.
|
|
|
|
Expr *ignoreParenBaseCasts() LLVM_READONLY;
|
|
|
|
|
|
|
|
const Expr *ignoreParenBaseCasts() const LLVM_READONLY {
|
|
|
|
return const_cast<Expr*>(this)->ignoreParenBaseCasts();
|
|
|
|
}
|
|
|
|
|
2009-12-15 18:49:47 +00:00
|
|
|
/// \brief Determine whether this expression is a default function argument.
|
|
|
|
///
|
|
|
|
/// Default arguments are implicitly generated in the abstract syntax tree
|
2012-04-14 14:01:31 +00:00
|
|
|
/// by semantic analysis for function calls, object constructions, etc. in
|
2009-12-15 18:49:47 +00:00
|
|
|
/// 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;
|
2012-04-14 14:01:31 +00:00
|
|
|
|
2011-02-20 13:06:31 +00:00
|
|
|
/// \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;
|
2010-04-03 07:51:34 +00:00
|
|
|
|
2011-05-02 19:39:53 +00:00
|
|
|
/// \brief Whether this expression is an implicit reference to 'this' in C++.
|
|
|
|
bool isImplicitCXXThis() const;
|
2011-07-17 15:40:56 +00:00
|
|
|
|
2012-04-14 14:01:31 +00:00
|
|
|
const Expr *IgnoreImpCasts() const LLVM_READONLY {
|
2011-07-17 15:40:56 +00:00
|
|
|
return const_cast<Expr*>(this)->IgnoreImpCasts();
|
|
|
|
}
|
2012-04-14 14:01:31 +00:00
|
|
|
const Expr *IgnoreParens() const LLVM_READONLY {
|
2009-06-02 17:58:47 +00:00
|
|
|
return const_cast<Expr*>(this)->IgnoreParens();
|
|
|
|
}
|
2012-04-14 14:01:31 +00:00
|
|
|
const Expr *IgnoreParenCasts() const LLVM_READONLY {
|
2009-06-02 17:58:47 +00:00
|
|
|
return const_cast<Expr*>(this)->IgnoreParenCasts();
|
|
|
|
}
|
2012-04-14 14:01:31 +00:00
|
|
|
const Expr *IgnoreParenNoopCasts(ASTContext &Ctx) const LLVM_READONLY {
|
2009-06-02 17:58:47 +00:00
|
|
|
return const_cast<Expr*>(this)->IgnoreParenNoopCasts(Ctx);
|
|
|
|
}
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2012-04-14 14:01:31 +00:00
|
|
|
static bool hasAnyTypeDependentArguments(llvm::ArrayRef<Expr *> Exprs);
|
2009-06-02 17:58:47 +00:00
|
|
|
|
2012-08-15 20:02:54 +00:00
|
|
|
/// \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;
|
|
|
|
|
2012-12-02 13:20:44 +00:00
|
|
|
/// Walk outwards from an expression we want to bind a reference to and
|
|
|
|
/// find the expression whose lifetime needs to be extended. Record
|
|
|
|
/// the adjustments needed along the path.
|
|
|
|
const Expr *
|
|
|
|
skipRValueSubobjectAdjustments(
|
|
|
|
SmallVectorImpl<SubobjectAdjustment> &Adjustments) const;
|
|
|
|
|
|
|
|
/// Skip irrelevant expressions to find what should be materialize for
|
|
|
|
/// binding with a reference.
|
|
|
|
const Expr *
|
|
|
|
findMaterializedTemporary(const MaterializeTemporaryExpr *&MTE) const;
|
|
|
|
|
2009-10-14 18:03:49 +00:00
|
|
|
static bool classof(const Stmt *T) {
|
2009-06-02 17:58:47 +00:00
|
|
|
return T->getStmtClass() >= firstExprConstant &&
|
2009-10-14 18:03:49 +00:00
|
|
|
T->getStmtClass() <= lastExprConstant;
|
2009-06-02 17:58:47 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Primary Expressions.
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2011-02-20 13:06:31 +00:00
|
|
|
/// 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;
|
2012-04-14 14:01:31 +00:00
|
|
|
|
2011-02-20 13:06:31 +00:00
|
|
|
public:
|
2012-04-14 14:01:31 +00:00
|
|
|
OpaqueValueExpr(SourceLocation Loc, QualType T, ExprValueKind VK,
|
|
|
|
ExprObjectKind OK = OK_Ordinary,
|
|
|
|
Expr *SourceExpr = 0)
|
2011-02-20 13:06:31 +00:00
|
|
|
: Expr(OpaqueValueExprClass, T, VK, OK,
|
2012-04-14 14:01:31 +00:00
|
|
|
T->isDependentType(),
|
|
|
|
T->isDependentType() ||
|
|
|
|
(SourceExpr && SourceExpr->isValueDependent()),
|
2011-07-17 15:40:56 +00:00
|
|
|
T->isInstantiationDependentType(),
|
2012-04-14 14:01:31 +00:00
|
|
|
false),
|
|
|
|
SourceExpr(SourceExpr), Loc(Loc) {
|
2011-02-20 13:06:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// 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; }
|
2012-04-14 14:01:31 +00:00
|
|
|
|
|
|
|
SourceRange getSourceRange() const LLVM_READONLY {
|
2011-02-20 13:06:31 +00:00
|
|
|
if (SourceExpr) return SourceExpr->getSourceRange();
|
|
|
|
return Loc;
|
|
|
|
}
|
2012-04-14 14:01:31 +00:00
|
|
|
SourceLocation getExprLoc() const LLVM_READONLY {
|
2011-02-20 13:06:31 +00:00
|
|
|
if (SourceExpr) return SourceExpr->getExprLoc();
|
|
|
|
return Loc;
|
|
|
|
}
|
|
|
|
|
|
|
|
child_range children() { return child_range(); }
|
|
|
|
|
|
|
|
/// 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;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2011-05-02 19:39:53 +00:00
|
|
|
/// \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.
|
2012-04-14 14:01:31 +00:00
|
|
|
/// DeclRefExprBits.HasTemplateKWAndArgsInfo:
|
2011-05-02 19:39:53 +00:00
|
|
|
/// Specifies when this declaration reference expression has an explicit
|
2012-04-14 14:01:31 +00:00
|
|
|
/// C++ template keyword and/or template argument list.
|
|
|
|
/// DeclRefExprBits.RefersToEnclosingLocal
|
|
|
|
/// Specifies when this declaration reference expression (validly)
|
|
|
|
/// refers to a local variable from a different function.
|
2009-06-02 17:58:47 +00:00
|
|
|
class DeclRefExpr : public Expr {
|
2011-05-02 19:39:53 +00:00
|
|
|
/// \brief The declaration that we are referencing.
|
|
|
|
ValueDecl *D;
|
2010-09-17 15:54:40 +00:00
|
|
|
|
2011-05-02 19:39:53 +00:00
|
|
|
/// \brief The location of the declaration name itself.
|
2009-06-02 17:58:47 +00:00
|
|
|
SourceLocation Loc;
|
|
|
|
|
2011-05-02 19:39:53 +00:00
|
|
|
/// \brief Provides source/type location info for the declaration name
|
|
|
|
/// embedded in D.
|
2010-09-17 15:54:40 +00:00
|
|
|
DeclarationNameLoc DNLoc;
|
|
|
|
|
2011-05-02 19:39:53 +00:00
|
|
|
/// \brief Helper to retrieve the optional NestedNameSpecifierLoc.
|
|
|
|
NestedNameSpecifierLoc &getInternalQualifierLoc() {
|
|
|
|
assert(hasQualifier());
|
|
|
|
return *reinterpret_cast<NestedNameSpecifierLoc *>(this + 1);
|
2009-11-04 15:04:32 +00:00
|
|
|
}
|
2011-05-02 19:39:53 +00:00
|
|
|
|
|
|
|
/// \brief Helper to retrieve the optional NestedNameSpecifierLoc.
|
|
|
|
const NestedNameSpecifierLoc &getInternalQualifierLoc() const {
|
|
|
|
return const_cast<DeclRefExpr *>(this)->getInternalQualifierLoc();
|
2009-11-04 15:04:32 +00:00
|
|
|
}
|
2010-09-17 15:54:40 +00:00
|
|
|
|
2011-05-02 19:39:53 +00:00
|
|
|
/// \brief Test whether there is a distinct FoundDecl attached to the end of
|
|
|
|
/// this DRE.
|
|
|
|
bool hasFoundDecl() const { return DeclRefExprBits.HasFoundDecl; }
|
2010-07-13 17:21:42 +00:00
|
|
|
|
2011-05-02 19:39:53 +00:00
|
|
|
/// \brief Helper to retrieve the optional NamedDecl through which this
|
|
|
|
/// reference occured.
|
|
|
|
NamedDecl *&getInternalFoundDecl() {
|
|
|
|
assert(hasFoundDecl());
|
|
|
|
if (hasQualifier())
|
|
|
|
return *reinterpret_cast<NamedDecl **>(&getInternalQualifierLoc() + 1);
|
|
|
|
return *reinterpret_cast<NamedDecl **>(this + 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// \brief Helper to retrieve the optional NamedDecl through which this
|
|
|
|
/// reference occured.
|
|
|
|
NamedDecl *getInternalFoundDecl() const {
|
|
|
|
return const_cast<DeclRefExpr *>(this)->getInternalFoundDecl();
|
|
|
|
}
|
|
|
|
|
2012-04-14 14:01:31 +00:00
|
|
|
DeclRefExpr(ASTContext &Ctx,
|
|
|
|
NestedNameSpecifierLoc QualifierLoc,
|
|
|
|
SourceLocation TemplateKWLoc,
|
|
|
|
ValueDecl *D, bool refersToEnclosingLocal,
|
|
|
|
const DeclarationNameInfo &NameInfo,
|
2011-05-02 19:39:53 +00:00
|
|
|
NamedDecl *FoundD,
|
2010-09-17 15:54:40 +00:00
|
|
|
const TemplateArgumentListInfo *TemplateArgs,
|
2011-02-20 13:06:31 +00:00
|
|
|
QualType T, ExprValueKind VK);
|
2010-09-17 15:54:40 +00:00
|
|
|
|
2010-07-13 17:21:42 +00:00
|
|
|
/// \brief Construct an empty declaration reference expression.
|
|
|
|
explicit DeclRefExpr(EmptyShell Empty)
|
|
|
|
: Expr(DeclRefExprClass, Empty) { }
|
2011-05-02 19:39:53 +00:00
|
|
|
|
2009-12-01 11:08:04 +00:00
|
|
|
/// \brief Computes the type- and value-dependence flags for this
|
|
|
|
/// declaration reference expression.
|
2012-04-14 14:01:31 +00:00
|
|
|
void computeDependence(ASTContext &C);
|
2009-06-02 17:58:47 +00:00
|
|
|
|
|
|
|
public:
|
2012-04-14 14:01:31 +00:00
|
|
|
DeclRefExpr(ValueDecl *D, bool refersToEnclosingLocal, QualType T,
|
|
|
|
ExprValueKind VK, SourceLocation L,
|
2011-07-17 15:40:56 +00:00
|
|
|
const DeclarationNameLoc &LocInfo = DeclarationNameLoc())
|
|
|
|
: Expr(DeclRefExprClass, T, VK, OK_Ordinary, false, false, false, false),
|
|
|
|
D(D), Loc(L), DNLoc(LocInfo) {
|
2011-05-02 19:39:53 +00:00
|
|
|
DeclRefExprBits.HasQualifier = 0;
|
2012-04-14 14:01:31 +00:00
|
|
|
DeclRefExprBits.HasTemplateKWAndArgsInfo = 0;
|
2011-05-02 19:39:53 +00:00
|
|
|
DeclRefExprBits.HasFoundDecl = 0;
|
2011-10-20 21:14:49 +00:00
|
|
|
DeclRefExprBits.HadMultipleCandidates = 0;
|
2012-04-14 14:01:31 +00:00
|
|
|
DeclRefExprBits.RefersToEnclosingLocal = refersToEnclosingLocal;
|
|
|
|
computeDependence(D->getASTContext());
|
2009-12-01 11:08:04 +00:00
|
|
|
}
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2009-11-04 15:04:32 +00:00
|
|
|
static DeclRefExpr *Create(ASTContext &Context,
|
2011-05-02 19:39:53 +00:00
|
|
|
NestedNameSpecifierLoc QualifierLoc,
|
2012-04-14 14:01:31 +00:00
|
|
|
SourceLocation TemplateKWLoc,
|
2009-12-15 18:49:47 +00:00
|
|
|
ValueDecl *D,
|
2012-04-14 14:01:31 +00:00
|
|
|
bool isEnclosingLocal,
|
2009-11-04 15:04:32 +00:00
|
|
|
SourceLocation NameLoc,
|
2011-02-20 13:06:31 +00:00
|
|
|
QualType T, ExprValueKind VK,
|
2011-05-02 19:39:53 +00:00
|
|
|
NamedDecl *FoundD = 0,
|
2009-12-01 11:08:04 +00:00
|
|
|
const TemplateArgumentListInfo *TemplateArgs = 0);
|
2010-07-13 17:21:42 +00:00
|
|
|
|
2010-09-17 15:54:40 +00:00
|
|
|
static DeclRefExpr *Create(ASTContext &Context,
|
2011-05-02 19:39:53 +00:00
|
|
|
NestedNameSpecifierLoc QualifierLoc,
|
2012-04-14 14:01:31 +00:00
|
|
|
SourceLocation TemplateKWLoc,
|
2010-09-17 15:54:40 +00:00
|
|
|
ValueDecl *D,
|
2012-04-14 14:01:31 +00:00
|
|
|
bool isEnclosingLocal,
|
2010-09-17 15:54:40 +00:00
|
|
|
const DeclarationNameInfo &NameInfo,
|
2011-02-20 13:06:31 +00:00
|
|
|
QualType T, ExprValueKind VK,
|
2011-05-02 19:39:53 +00:00
|
|
|
NamedDecl *FoundD = 0,
|
2010-09-17 15:54:40 +00:00
|
|
|
const TemplateArgumentListInfo *TemplateArgs = 0);
|
|
|
|
|
2010-07-13 17:21:42 +00:00
|
|
|
/// \brief Construct an empty declaration reference expression.
|
|
|
|
static DeclRefExpr *CreateEmpty(ASTContext &Context,
|
2011-05-02 19:39:53 +00:00
|
|
|
bool HasQualifier,
|
|
|
|
bool HasFoundDecl,
|
2012-04-14 14:01:31 +00:00
|
|
|
bool HasTemplateKWAndArgsInfo,
|
2011-02-20 13:06:31 +00:00
|
|
|
unsigned NumTemplateArgs);
|
2011-05-02 19:39:53 +00:00
|
|
|
|
|
|
|
ValueDecl *getDecl() { return D; }
|
|
|
|
const ValueDecl *getDecl() const { return D; }
|
|
|
|
void setDecl(ValueDecl *NewD) { D = NewD; }
|
2009-06-02 17:58:47 +00:00
|
|
|
|
2010-09-17 15:54:40 +00:00
|
|
|
DeclarationNameInfo getNameInfo() const {
|
|
|
|
return DeclarationNameInfo(getDecl()->getDeclName(), Loc, DNLoc);
|
|
|
|
}
|
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
SourceLocation getLocation() const { return Loc; }
|
|
|
|
void setLocation(SourceLocation L) { Loc = L; }
|
2012-04-14 14:01:31 +00:00
|
|
|
SourceRange getSourceRange() const LLVM_READONLY;
|
|
|
|
SourceLocation getLocStart() const LLVM_READONLY;
|
|
|
|
SourceLocation getLocEnd() const LLVM_READONLY;
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2009-11-04 15:04:32 +00:00
|
|
|
/// \brief Determine whether this declaration reference was preceded by a
|
|
|
|
/// C++ nested-name-specifier, e.g., \c N::foo.
|
2011-05-02 19:39:53 +00:00
|
|
|
bool hasQualifier() const { return DeclRefExprBits.HasQualifier; }
|
|
|
|
|
|
|
|
/// \brief If the name was qualified, retrieves the nested-name-specifier
|
2009-11-04 15:04:32 +00:00
|
|
|
/// that precedes the name. Otherwise, returns NULL.
|
|
|
|
NestedNameSpecifier *getQualifier() const {
|
|
|
|
if (!hasQualifier())
|
|
|
|
return 0;
|
2011-05-02 19:39:53 +00:00
|
|
|
|
|
|
|
return getInternalQualifierLoc().getNestedNameSpecifier();
|
2009-11-04 15:04:32 +00:00
|
|
|
}
|
2011-05-02 19:39:53 +00:00
|
|
|
|
|
|
|
/// \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 getInternalQualifierLoc();
|
|
|
|
}
|
|
|
|
|
|
|
|
/// \brief Get the NamedDecl through which this reference occured.
|
|
|
|
///
|
|
|
|
/// 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() ? getInternalFoundDecl() : D;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// \brief Get the NamedDecl through which this reference occurred.
|
|
|
|
/// See non-const variant.
|
|
|
|
const NamedDecl *getFoundDecl() const {
|
|
|
|
return hasFoundDecl() ? getInternalFoundDecl() : D;
|
|
|
|
}
|
|
|
|
|
2012-04-14 14:01:31 +00:00
|
|
|
bool hasTemplateKWAndArgsInfo() const {
|
|
|
|
return DeclRefExprBits.HasTemplateKWAndArgsInfo;
|
2010-09-17 15:54:40 +00:00
|
|
|
}
|
2011-05-02 19:39:53 +00:00
|
|
|
|
2012-04-14 14:01:31 +00:00
|
|
|
/// \brief Return the optional template keyword and arguments info.
|
|
|
|
ASTTemplateKWAndArgsInfo *getTemplateKWAndArgsInfo() {
|
|
|
|
if (!hasTemplateKWAndArgsInfo())
|
|
|
|
return 0;
|
|
|
|
|
2011-05-02 19:39:53 +00:00
|
|
|
if (hasFoundDecl())
|
2012-04-14 14:01:31 +00:00
|
|
|
return reinterpret_cast<ASTTemplateKWAndArgsInfo *>(
|
2011-05-02 19:39:53 +00:00
|
|
|
&getInternalFoundDecl() + 1);
|
2010-09-17 15:54:40 +00:00
|
|
|
|
2011-05-02 19:39:53 +00:00
|
|
|
if (hasQualifier())
|
2012-04-14 14:01:31 +00:00
|
|
|
return reinterpret_cast<ASTTemplateKWAndArgsInfo *>(
|
2011-05-02 19:39:53 +00:00
|
|
|
&getInternalQualifierLoc() + 1);
|
|
|
|
|
2012-04-14 14:01:31 +00:00
|
|
|
return reinterpret_cast<ASTTemplateKWAndArgsInfo *>(this + 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// \brief Return the optional template keyword and arguments info.
|
|
|
|
const ASTTemplateKWAndArgsInfo *getTemplateKWAndArgsInfo() const {
|
|
|
|
return const_cast<DeclRefExpr*>(this)->getTemplateKWAndArgsInfo();
|
|
|
|
}
|
|
|
|
|
|
|
|
/// \brief Retrieve the location of the template keyword preceding
|
|
|
|
/// this name, if any.
|
|
|
|
SourceLocation getTemplateKeywordLoc() const {
|
|
|
|
if (!hasTemplateKWAndArgsInfo()) return SourceLocation();
|
|
|
|
return getTemplateKWAndArgsInfo()->getTemplateKeywordLoc();
|
|
|
|
}
|
|
|
|
|
|
|
|
/// \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 getTemplateKWAndArgsInfo()->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 getTemplateKWAndArgsInfo()->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 Retrieve the explicit template argument list that followed the
|
|
|
|
/// member template name.
|
|
|
|
ASTTemplateArgumentListInfo &getExplicitTemplateArgs() {
|
|
|
|
assert(hasExplicitTemplateArgs());
|
|
|
|
return *getTemplateKWAndArgsInfo();
|
2010-09-17 15:54:40 +00:00
|
|
|
}
|
2011-05-02 19:39:53 +00:00
|
|
|
|
2010-09-17 15:54:40 +00:00
|
|
|
/// \brief Retrieve the explicit template argument list that followed the
|
|
|
|
/// member template name.
|
2011-10-20 21:14:49 +00:00
|
|
|
const ASTTemplateArgumentListInfo &getExplicitTemplateArgs() const {
|
2010-09-17 15:54:40 +00:00
|
|
|
return const_cast<DeclRefExpr *>(this)->getExplicitTemplateArgs();
|
2009-11-04 15:04:32 +00:00
|
|
|
}
|
2009-12-01 11:08:04 +00:00
|
|
|
|
2010-09-17 15:54:40 +00:00
|
|
|
/// \brief Retrieves the optional explicit template arguments.
|
|
|
|
/// This points to the same data as getExplicitTemplateArgs(), but
|
|
|
|
/// returns null if there are no explicit template arguments.
|
2012-04-14 14:01:31 +00:00
|
|
|
const ASTTemplateArgumentListInfo *getOptionalExplicitTemplateArgs() const {
|
2010-09-17 15:54:40 +00:00
|
|
|
if (!hasExplicitTemplateArgs()) return 0;
|
|
|
|
return &getExplicitTemplateArgs();
|
|
|
|
}
|
2011-05-02 19:39:53 +00:00
|
|
|
|
2009-12-01 11:08:04 +00:00
|
|
|
/// \brief Copies the template arguments (if present) into the given
|
|
|
|
/// structure.
|
|
|
|
void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const {
|
2010-09-17 15:54:40 +00:00
|
|
|
if (hasExplicitTemplateArgs())
|
|
|
|
getExplicitTemplateArgs().copyInto(List);
|
2009-12-01 11:08:04 +00:00
|
|
|
}
|
2011-05-02 19:39:53 +00:00
|
|
|
|
2009-11-04 15:04:32 +00:00
|
|
|
/// \brief Retrieve the template arguments provided as part of this
|
|
|
|
/// template-id.
|
|
|
|
const TemplateArgumentLoc *getTemplateArgs() const {
|
2010-09-17 15:54:40 +00:00
|
|
|
if (!hasExplicitTemplateArgs())
|
2009-11-04 15:04:32 +00:00
|
|
|
return 0;
|
2011-05-02 19:39:53 +00:00
|
|
|
|
2010-09-17 15:54:40 +00:00
|
|
|
return getExplicitTemplateArgs().getTemplateArgs();
|
2009-11-04 15:04:32 +00:00
|
|
|
}
|
2011-05-02 19:39:53 +00:00
|
|
|
|
2009-11-04 15:04:32 +00:00
|
|
|
/// \brief Retrieve the number of template arguments provided as part of this
|
|
|
|
/// template-id.
|
|
|
|
unsigned getNumTemplateArgs() const {
|
2010-09-17 15:54:40 +00:00
|
|
|
if (!hasExplicitTemplateArgs())
|
2009-11-04 15:04:32 +00:00
|
|
|
return 0;
|
2011-05-02 19:39:53 +00:00
|
|
|
|
2010-09-17 15:54:40 +00:00
|
|
|
return getExplicitTemplateArgs().NumTemplateArgs;
|
2009-11-04 15:04:32 +00:00
|
|
|
}
|
2011-05-02 19:39:53 +00:00
|
|
|
|
2011-10-20 21:14:49 +00:00
|
|
|
/// \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;
|
|
|
|
}
|
|
|
|
|
2012-04-14 14:01:31 +00:00
|
|
|
/// Does this DeclRefExpr refer to a local declaration from an
|
|
|
|
/// enclosing function scope?
|
|
|
|
bool refersToEnclosingLocal() const {
|
|
|
|
return DeclRefExprBits.RefersToEnclosingLocal;
|
|
|
|
}
|
|
|
|
|
2009-10-14 18:03:49 +00:00
|
|
|
static bool classof(const Stmt *T) {
|
2009-12-01 11:08:04 +00:00
|
|
|
return T->getStmtClass() == DeclRefExprClass;
|
2009-06-02 17:58:47 +00:00
|
|
|
}
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
// Iterators
|
2011-02-20 13:06:31 +00:00
|
|
|
child_range children() { return child_range(); }
|
2011-05-02 19:39:53 +00:00
|
|
|
|
2010-09-17 15:54:40 +00:00
|
|
|
friend class ASTStmtReader;
|
|
|
|
friend class ASTStmtWriter;
|
2009-06-02 17:58:47 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/// PredefinedExpr - [C99 6.4.2.2] - A predefined identifier such as __func__.
|
|
|
|
class PredefinedExpr : public Expr {
|
|
|
|
public:
|
|
|
|
enum IdentType {
|
|
|
|
Func,
|
|
|
|
Function,
|
2012-08-15 20:02:54 +00:00
|
|
|
LFunction, // Same as Function, but as wide string.
|
2010-02-16 09:31:36 +00:00
|
|
|
PrettyFunction,
|
|
|
|
/// PrettyFunctionNoVirtual - The same as PrettyFunction, except that the
|
|
|
|
/// 'virtual' keyword is omitted for virtual member functions.
|
|
|
|
PrettyFunctionNoVirtual
|
2009-06-02 17:58:47 +00:00
|
|
|
};
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
private:
|
|
|
|
SourceLocation Loc;
|
|
|
|
IdentType Type;
|
|
|
|
public:
|
2009-10-14 18:03:49 +00:00
|
|
|
PredefinedExpr(SourceLocation l, QualType type, IdentType IT)
|
2011-02-20 13:06:31 +00:00
|
|
|
: Expr(PredefinedExprClass, type, VK_LValue, OK_Ordinary,
|
2012-04-14 14:01:31 +00:00
|
|
|
type->isDependentType(), type->isDependentType(),
|
2011-07-17 15:40:56 +00:00
|
|
|
type->isInstantiationDependentType(),
|
2011-02-20 13:06:31 +00:00
|
|
|
/*ContainsUnexpandedParameterPack=*/false),
|
|
|
|
Loc(l), Type(IT) {}
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
/// \brief Construct an empty predefined expression.
|
2009-10-14 18:03:49 +00:00
|
|
|
explicit PredefinedExpr(EmptyShell Empty)
|
2009-06-02 17:58:47 +00:00
|
|
|
: Expr(PredefinedExprClass, Empty) { }
|
|
|
|
|
|
|
|
IdentType getIdentType() const { return Type; }
|
|
|
|
void setIdentType(IdentType IT) { Type = IT; }
|
|
|
|
|
|
|
|
SourceLocation getLocation() const { return Loc; }
|
|
|
|
void setLocation(SourceLocation L) { Loc = L; }
|
|
|
|
|
2010-02-16 09:31:36 +00:00
|
|
|
static std::string ComputeName(IdentType IT, const Decl *CurrentDecl);
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2012-04-14 14:01:31 +00:00
|
|
|
SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(Loc); }
|
2009-06-02 17:58:47 +00:00
|
|
|
|
2009-10-14 18:03:49 +00:00
|
|
|
static bool classof(const Stmt *T) {
|
|
|
|
return T->getStmtClass() == PredefinedExprClass;
|
2009-06-02 17:58:47 +00:00
|
|
|
}
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
// Iterators
|
2011-02-20 13:06:31 +00:00
|
|
|
child_range children() { return child_range(); }
|
2009-06-02 17:58:47 +00:00
|
|
|
};
|
|
|
|
|
2010-09-17 15:54:40 +00:00
|
|
|
/// \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.
|
|
|
|
};
|
2012-04-14 14:01:31 +00:00
|
|
|
unsigned BitWidth;
|
2010-09-17 15:54:40 +00:00
|
|
|
|
|
|
|
bool hasAllocation() const { return llvm::APInt::getNumWords(BitWidth) > 1; }
|
|
|
|
|
2012-12-02 13:20:44 +00:00
|
|
|
APNumericStorage(const APNumericStorage &) LLVM_DELETED_FUNCTION;
|
|
|
|
void operator=(const APNumericStorage &) LLVM_DELETED_FUNCTION;
|
2010-09-17 15:54:40 +00:00
|
|
|
|
|
|
|
protected:
|
2012-04-14 14:01:31 +00:00
|
|
|
APNumericStorage() : VAL(0), BitWidth(0) { }
|
2010-09-17 15:54:40 +00:00
|
|
|
|
|
|
|
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(ASTContext &C, const llvm::APInt &Val);
|
|
|
|
};
|
|
|
|
|
2012-04-14 14:01:31 +00:00
|
|
|
class APIntStorage : private APNumericStorage {
|
|
|
|
public:
|
|
|
|
llvm::APInt getValue() const { return getIntValue(); }
|
2010-09-17 15:54:40 +00:00
|
|
|
void setValue(ASTContext &C, const llvm::APInt &Val) { setIntValue(C, Val); }
|
|
|
|
};
|
|
|
|
|
2012-04-14 14:01:31 +00:00
|
|
|
class APFloatStorage : private APNumericStorage {
|
|
|
|
public:
|
|
|
|
llvm::APFloat getValue(bool IsIEEE) const {
|
|
|
|
return llvm::APFloat(getIntValue(), IsIEEE);
|
|
|
|
}
|
2010-09-17 15:54:40 +00:00
|
|
|
void setValue(ASTContext &C, const llvm::APFloat &Val) {
|
|
|
|
setIntValue(C, Val.bitcastToAPInt());
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2012-04-14 14:01:31 +00:00
|
|
|
class IntegerLiteral : public Expr, public APIntStorage {
|
2009-06-02 17:58:47 +00:00
|
|
|
SourceLocation Loc;
|
2010-09-17 15:54:40 +00:00
|
|
|
|
|
|
|
/// \brief Construct an empty integer literal.
|
|
|
|
explicit IntegerLiteral(EmptyShell Empty)
|
|
|
|
: Expr(IntegerLiteralClass, Empty) { }
|
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
public:
|
2009-10-14 18:03:49 +00:00
|
|
|
// type should be IntTy, LongTy, LongLongTy, UnsignedIntTy, UnsignedLongTy,
|
2009-06-02 17:58:47 +00:00
|
|
|
// or UnsignedLongLongTy
|
2012-08-15 20:02:54 +00:00
|
|
|
IntegerLiteral(ASTContext &C, const llvm::APInt &V, QualType type,
|
|
|
|
SourceLocation l);
|
2009-06-02 17:58:47 +00:00
|
|
|
|
2011-06-12 15:46:16 +00:00
|
|
|
/// \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.
|
2010-09-17 15:54:40 +00:00
|
|
|
static IntegerLiteral *Create(ASTContext &C, const llvm::APInt &V,
|
|
|
|
QualType type, SourceLocation l);
|
2011-06-12 15:46:16 +00:00
|
|
|
/// \brief Returns a new empty integer literal.
|
2010-09-17 15:54:40 +00:00
|
|
|
static IntegerLiteral *Create(ASTContext &C, EmptyShell Empty);
|
2009-06-02 17:58:47 +00:00
|
|
|
|
2012-04-14 14:01:31 +00:00
|
|
|
SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(Loc); }
|
2009-06-02 17:58:47 +00:00
|
|
|
|
|
|
|
/// \brief Retrieve the location of the literal.
|
|
|
|
SourceLocation getLocation() const { return Loc; }
|
|
|
|
|
|
|
|
void setLocation(SourceLocation Location) { Loc = Location; }
|
|
|
|
|
2009-10-14 18:03:49 +00:00
|
|
|
static bool classof(const Stmt *T) {
|
|
|
|
return T->getStmtClass() == IntegerLiteralClass;
|
2009-06-02 17:58:47 +00:00
|
|
|
}
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
// Iterators
|
2011-02-20 13:06:31 +00:00
|
|
|
child_range children() { return child_range(); }
|
2009-06-02 17:58:47 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
class CharacterLiteral : public Expr {
|
2011-10-20 21:14:49 +00:00
|
|
|
public:
|
|
|
|
enum CharacterKind {
|
|
|
|
Ascii,
|
|
|
|
Wide,
|
|
|
|
UTF16,
|
|
|
|
UTF32
|
|
|
|
};
|
|
|
|
|
|
|
|
private:
|
2009-06-02 17:58:47 +00:00
|
|
|
unsigned Value;
|
|
|
|
SourceLocation Loc;
|
|
|
|
public:
|
|
|
|
// type should be IntTy
|
2011-10-20 21:14:49 +00:00
|
|
|
CharacterLiteral(unsigned value, CharacterKind kind, QualType type,
|
|
|
|
SourceLocation l)
|
2011-02-20 13:06:31 +00:00
|
|
|
: Expr(CharacterLiteralClass, type, VK_RValue, OK_Ordinary, false, false,
|
2011-07-17 15:40:56 +00:00
|
|
|
false, false),
|
2012-04-14 14:01:31 +00:00
|
|
|
Value(value), Loc(l) {
|
|
|
|
CharacterLiteralBits.Kind = kind;
|
2009-06-02 17:58:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// \brief Construct an empty character literal.
|
|
|
|
CharacterLiteral(EmptyShell Empty) : Expr(CharacterLiteralClass, Empty) { }
|
|
|
|
|
2009-10-14 18:03:49 +00:00
|
|
|
SourceLocation getLocation() const { return Loc; }
|
2012-04-14 14:01:31 +00:00
|
|
|
CharacterKind getKind() const {
|
|
|
|
return static_cast<CharacterKind>(CharacterLiteralBits.Kind);
|
|
|
|
}
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2012-04-14 14:01:31 +00:00
|
|
|
SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(Loc); }
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
unsigned getValue() const { return Value; }
|
|
|
|
|
|
|
|
void setLocation(SourceLocation Location) { Loc = Location; }
|
2012-04-14 14:01:31 +00:00
|
|
|
void setKind(CharacterKind kind) { CharacterLiteralBits.Kind = kind; }
|
2009-06-02 17:58:47 +00:00
|
|
|
void setValue(unsigned Val) { Value = Val; }
|
|
|
|
|
2009-10-14 18:03:49 +00:00
|
|
|
static bool classof(const Stmt *T) {
|
|
|
|
return T->getStmtClass() == CharacterLiteralClass;
|
2009-06-02 17:58:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Iterators
|
2011-02-20 13:06:31 +00:00
|
|
|
child_range children() { return child_range(); }
|
2009-06-02 17:58:47 +00:00
|
|
|
};
|
|
|
|
|
2012-04-14 14:01:31 +00:00
|
|
|
class FloatingLiteral : public Expr, private APFloatStorage {
|
2009-06-02 17:58:47 +00:00
|
|
|
SourceLocation Loc;
|
2010-09-17 15:54:40 +00:00
|
|
|
|
|
|
|
FloatingLiteral(ASTContext &C, const llvm::APFloat &V, bool isexact,
|
2012-08-15 20:02:54 +00:00
|
|
|
QualType Type, SourceLocation L);
|
2009-06-02 17:58:47 +00:00
|
|
|
|
|
|
|
/// \brief Construct an empty floating-point literal.
|
2012-08-15 20:02:54 +00:00
|
|
|
explicit FloatingLiteral(ASTContext &C, EmptyShell Empty);
|
2009-06-02 17:58:47 +00:00
|
|
|
|
2010-09-17 15:54:40 +00:00
|
|
|
public:
|
|
|
|
static FloatingLiteral *Create(ASTContext &C, const llvm::APFloat &V,
|
|
|
|
bool isexact, QualType Type, SourceLocation L);
|
|
|
|
static FloatingLiteral *Create(ASTContext &C, EmptyShell Empty);
|
|
|
|
|
2012-04-14 14:01:31 +00:00
|
|
|
llvm::APFloat getValue() const {
|
|
|
|
return APFloatStorage::getValue(FloatingLiteralBits.IsIEEE);
|
|
|
|
}
|
2010-09-17 15:54:40 +00:00
|
|
|
void setValue(ASTContext &C, const llvm::APFloat &Val) {
|
2012-04-14 14:01:31 +00:00
|
|
|
APFloatStorage::setValue(C, Val);
|
2010-09-17 15:54:40 +00:00
|
|
|
}
|
2009-06-02 17:58:47 +00:00
|
|
|
|
2012-04-14 14:01:31 +00:00
|
|
|
bool isExact() const { return FloatingLiteralBits.IsExact; }
|
|
|
|
void setExact(bool E) { FloatingLiteralBits.IsExact = E; }
|
2009-06-02 17:58:47 +00:00
|
|
|
|
|
|
|
/// 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;
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
SourceLocation getLocation() const { return Loc; }
|
|
|
|
void setLocation(SourceLocation L) { Loc = L; }
|
|
|
|
|
2012-04-14 14:01:31 +00:00
|
|
|
SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(Loc); }
|
2009-06-02 17:58:47 +00:00
|
|
|
|
2009-10-14 18:03:49 +00:00
|
|
|
static bool classof(const Stmt *T) {
|
|
|
|
return T->getStmtClass() == FloatingLiteralClass;
|
2009-06-02 17:58:47 +00:00
|
|
|
}
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
// Iterators
|
2011-02-20 13:06:31 +00:00
|
|
|
child_range children() { return child_range(); }
|
2009-06-02 17:58:47 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/// 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)
|
2011-02-20 13:06:31 +00:00
|
|
|
: Expr(ImaginaryLiteralClass, Ty, VK_RValue, OK_Ordinary, false, false,
|
2011-07-17 15:40:56 +00:00
|
|
|
false, false),
|
2011-02-20 13:06:31 +00:00
|
|
|
Val(val) {}
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
/// \brief Build an empty imaginary literal.
|
2009-10-14 18:03:49 +00:00
|
|
|
explicit ImaginaryLiteral(EmptyShell Empty)
|
2009-06-02 17:58:47 +00:00
|
|
|
: Expr(ImaginaryLiteralClass, Empty) { }
|
|
|
|
|
|
|
|
const Expr *getSubExpr() const { return cast<Expr>(Val); }
|
|
|
|
Expr *getSubExpr() { return cast<Expr>(Val); }
|
|
|
|
void setSubExpr(Expr *E) { Val = E; }
|
|
|
|
|
2012-04-14 14:01:31 +00:00
|
|
|
SourceRange getSourceRange() const LLVM_READONLY { return Val->getSourceRange(); }
|
2009-10-14 18:03:49 +00:00
|
|
|
static bool classof(const Stmt *T) {
|
|
|
|
return T->getStmtClass() == ImaginaryLiteralClass;
|
2009-06-02 17:58:47 +00:00
|
|
|
}
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
// Iterators
|
2011-02-20 13:06:31 +00:00
|
|
|
child_range children() { return child_range(&Val, &Val+1); }
|
2009-06-02 17:58:47 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/// StringLiteral - This represents a string literal expression, e.g. "foo"
|
|
|
|
/// or L"bar" (wide strings). The actual string is returned by getStrData()
|
|
|
|
/// 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 {
|
2011-10-20 21:14:49 +00:00
|
|
|
public:
|
|
|
|
enum StringKind {
|
|
|
|
Ascii,
|
|
|
|
Wide,
|
|
|
|
UTF8,
|
|
|
|
UTF16,
|
|
|
|
UTF32
|
|
|
|
};
|
|
|
|
|
|
|
|
private:
|
2011-05-02 19:39:53 +00:00
|
|
|
friend class ASTStmtReader;
|
|
|
|
|
2012-04-14 14:01:31 +00:00
|
|
|
union {
|
|
|
|
const char *asChar;
|
|
|
|
const uint16_t *asUInt16;
|
|
|
|
const uint32_t *asUInt32;
|
|
|
|
} StrData;
|
|
|
|
unsigned Length;
|
|
|
|
unsigned CharByteWidth : 4;
|
2011-10-20 21:14:49 +00:00
|
|
|
unsigned Kind : 3;
|
2012-04-14 14:01:31 +00:00
|
|
|
unsigned IsPascal : 1;
|
|
|
|
unsigned NumConcatenated;
|
2009-06-02 17:58:47 +00:00
|
|
|
SourceLocation TokLocs[1];
|
|
|
|
|
2011-02-20 13:06:31 +00:00
|
|
|
StringLiteral(QualType Ty) :
|
2011-07-17 15:40:56 +00:00
|
|
|
Expr(StringLiteralClass, Ty, VK_LValue, OK_Ordinary, false, false, false,
|
|
|
|
false) {}
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2012-04-14 14:01:31 +00:00
|
|
|
static int mapCharByteWidth(TargetInfo const &target,StringKind k);
|
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
public:
|
|
|
|
/// This is the "fully general" constructor that allows representation of
|
|
|
|
/// strings formed from multiple concatenated tokens.
|
2011-10-20 21:14:49 +00:00
|
|
|
static StringLiteral *Create(ASTContext &C, StringRef Str, StringKind Kind,
|
2011-07-17 15:40:56 +00:00
|
|
|
bool Pascal, QualType Ty,
|
2009-06-02 17:58:47 +00:00
|
|
|
const SourceLocation *Loc, unsigned NumStrs);
|
|
|
|
|
|
|
|
/// Simple constructor for string literals made from one token.
|
2011-10-20 21:14:49 +00:00
|
|
|
static StringLiteral *Create(ASTContext &C, StringRef Str, StringKind Kind,
|
|
|
|
bool Pascal, QualType Ty,
|
|
|
|
SourceLocation Loc) {
|
|
|
|
return Create(C, Str, Kind, Pascal, Ty, &Loc, 1);
|
2009-06-02 17:58:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// \brief Construct an empty string literal.
|
|
|
|
static StringLiteral *CreateEmpty(ASTContext &C, unsigned NumStrs);
|
|
|
|
|
2011-10-20 21:14:49 +00:00
|
|
|
StringRef getString() const {
|
2012-04-14 14:01:31 +00:00
|
|
|
assert(CharByteWidth==1
|
|
|
|
&& "This function is used in places that assume strings use char");
|
|
|
|
return StringRef(StrData.asChar, getByteLength());
|
|
|
|
}
|
|
|
|
|
2012-08-15 20:02:54 +00:00
|
|
|
/// Allow access to clients that need the byte representation, such as
|
|
|
|
/// ASTWriterStmt::VisitStringLiteral().
|
2012-04-14 14:01:31 +00:00
|
|
|
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());
|
|
|
|
}
|
|
|
|
|
2012-08-15 20:02:54 +00:00
|
|
|
void outputString(raw_ostream &OS);
|
|
|
|
|
2012-04-14 14:01:31 +00:00
|
|
|
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; }
|
2009-06-02 17:58:47 +00:00
|
|
|
|
|
|
|
/// \brief Sets the string data to the given string data.
|
2012-04-14 14:01:31 +00:00
|
|
|
void setString(ASTContext &C, StringRef Str,
|
|
|
|
StringKind Kind, bool IsPascal);
|
2011-10-20 21:14:49 +00:00
|
|
|
|
|
|
|
StringKind getKind() const { return static_cast<StringKind>(Kind); }
|
2012-04-14 14:01:31 +00:00
|
|
|
|
|
|
|
|
2011-10-20 21:14:49 +00:00
|
|
|
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; }
|
2011-05-02 19:39:53 +00:00
|
|
|
bool isPascal() const { return IsPascal; }
|
2011-10-20 21:14:49 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
bool containsNonAsciiOrNull() const {
|
2011-10-20 21:14:49 +00:00
|
|
|
StringRef Str = getString();
|
2009-10-14 18:03:49 +00:00
|
|
|
for (unsigned i = 0, e = Str.size(); i != e; ++i)
|
|
|
|
if (!isascii(Str[i]) || !Str[i])
|
2009-06-02 17:58:47 +00:00
|
|
|
return true;
|
|
|
|
return false;
|
|
|
|
}
|
2012-04-14 14:01:31 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
/// 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; }
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
SourceLocation getStrTokenLoc(unsigned TokNum) const {
|
|
|
|
assert(TokNum < NumConcatenated && "Invalid tok number");
|
|
|
|
return TokLocs[TokNum];
|
|
|
|
}
|
2009-10-14 18:03:49 +00:00
|
|
|
void setStrTokenLoc(unsigned TokNum, SourceLocation L) {
|
2009-06-02 17:58:47 +00:00
|
|
|
assert(TokNum < NumConcatenated && "Invalid tok number");
|
|
|
|
TokLocs[TokNum] = L;
|
|
|
|
}
|
2012-04-14 14:01:31 +00:00
|
|
|
|
2011-02-20 13:06:31 +00:00
|
|
|
/// 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) const;
|
2009-06-02 17:58:47 +00:00
|
|
|
|
|
|
|
typedef const SourceLocation *tokloc_iterator;
|
|
|
|
tokloc_iterator tokloc_begin() const { return TokLocs; }
|
|
|
|
tokloc_iterator tokloc_end() const { return TokLocs+NumConcatenated; }
|
|
|
|
|
2012-04-14 14:01:31 +00:00
|
|
|
SourceRange getSourceRange() const LLVM_READONLY {
|
2009-10-14 18:03:49 +00:00
|
|
|
return SourceRange(TokLocs[0], TokLocs[NumConcatenated-1]);
|
2009-06-02 17:58:47 +00:00
|
|
|
}
|
2009-10-14 18:03:49 +00:00
|
|
|
static bool classof(const Stmt *T) {
|
|
|
|
return T->getStmtClass() == StringLiteralClass;
|
2009-06-02 17:58:47 +00:00
|
|
|
}
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
// Iterators
|
2011-02-20 13:06:31 +00:00
|
|
|
child_range children() { return child_range(); }
|
2009-06-02 17:58:47 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/// 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(),
|
2011-02-20 13:06:31 +00:00
|
|
|
val->getValueKind(), val->getObjectKind(),
|
|
|
|
val->isTypeDependent(), val->isValueDependent(),
|
2011-07-17 15:40:56 +00:00
|
|
|
val->isInstantiationDependent(),
|
2011-02-20 13:06:31 +00:00
|
|
|
val->containsUnexpandedParameterPack()),
|
2009-06-02 17:58:47 +00:00
|
|
|
L(l), R(r), Val(val) {}
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
/// \brief Construct an empty parenthesized expression.
|
2009-10-14 18:03:49 +00:00
|
|
|
explicit ParenExpr(EmptyShell Empty)
|
2009-06-02 17:58:47 +00:00
|
|
|
: Expr(ParenExprClass, Empty) { }
|
|
|
|
|
|
|
|
const Expr *getSubExpr() const { return cast<Expr>(Val); }
|
|
|
|
Expr *getSubExpr() { return cast<Expr>(Val); }
|
|
|
|
void setSubExpr(Expr *E) { Val = E; }
|
|
|
|
|
2012-04-14 14:01:31 +00:00
|
|
|
SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(L, R); }
|
2009-06-02 17:58:47 +00:00
|
|
|
|
|
|
|
/// \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; }
|
|
|
|
|
2009-10-14 18:03:49 +00:00
|
|
|
static bool classof(const Stmt *T) {
|
|
|
|
return T->getStmtClass() == ParenExprClass;
|
2009-06-02 17:58:47 +00:00
|
|
|
}
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
// Iterators
|
2011-02-20 13:06:31 +00:00
|
|
|
child_range children() { return child_range(&Val, &Val+1); }
|
2009-06-02 17:58:47 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/// 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:
|
2010-09-17 15:54:40 +00:00
|
|
|
typedef UnaryOperatorKind Opcode;
|
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
private:
|
2010-09-17 15:54:40 +00:00
|
|
|
unsigned Opc : 5;
|
2009-06-02 17:58:47 +00:00
|
|
|
SourceLocation Loc;
|
2010-09-17 15:54:40 +00:00
|
|
|
Stmt *Val;
|
2009-10-14 18:03:49 +00:00
|
|
|
public:
|
2009-06-02 17:58:47 +00:00
|
|
|
|
2011-02-20 13:06:31 +00:00
|
|
|
UnaryOperator(Expr *input, Opcode opc, QualType type,
|
|
|
|
ExprValueKind VK, ExprObjectKind OK, SourceLocation l)
|
|
|
|
: Expr(UnaryOperatorClass, type, VK, OK,
|
2010-09-17 15:54:40 +00:00
|
|
|
input->isTypeDependent() || type->isDependentType(),
|
2011-02-20 13:06:31 +00:00
|
|
|
input->isValueDependent(),
|
2012-04-14 14:01:31 +00:00
|
|
|
(input->isInstantiationDependent() ||
|
2011-07-17 15:40:56 +00:00
|
|
|
type->isInstantiationDependentType()),
|
2011-02-20 13:06:31 +00:00
|
|
|
input->containsUnexpandedParameterPack()),
|
2010-09-17 15:54:40 +00:00
|
|
|
Opc(opc), Loc(l), Val(input) {}
|
2009-06-02 17:58:47 +00:00
|
|
|
|
|
|
|
/// \brief Build an empty unary operator.
|
2009-10-14 18:03:49 +00:00
|
|
|
explicit UnaryOperator(EmptyShell Empty)
|
2010-09-17 15:54:40 +00:00
|
|
|
: Expr(UnaryOperatorClass, Empty), Opc(UO_AddrOf) { }
|
2009-06-02 17:58:47 +00:00
|
|
|
|
2010-09-17 15:54:40 +00:00
|
|
|
Opcode getOpcode() const { return static_cast<Opcode>(Opc); }
|
2009-06-02 17:58:47 +00:00
|
|
|
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) {
|
2010-09-17 15:54:40 +00:00
|
|
|
return Op == UO_PostInc || Op == UO_PostDec;
|
2009-06-02 17:58:47 +00:00
|
|
|
}
|
|
|
|
|
2011-02-20 13:06:31 +00:00
|
|
|
/// isPrefix - Return true if this is a prefix operation, like --x.
|
2009-06-02 17:58:47 +00:00
|
|
|
static bool isPrefix(Opcode Op) {
|
2010-09-17 15:54:40 +00:00
|
|
|
return Op == UO_PreInc || Op == UO_PreDec;
|
2009-06-02 17:58:47 +00:00
|
|
|
}
|
|
|
|
|
2010-09-17 15:54:40 +00:00
|
|
|
bool isPrefix() const { return isPrefix(getOpcode()); }
|
|
|
|
bool isPostfix() const { return isPostfix(getOpcode()); }
|
2012-04-14 14:01:31 +00:00
|
|
|
|
|
|
|
static bool isIncrementOp(Opcode Op) {
|
|
|
|
return Op == UO_PreInc || Op == UO_PostInc;
|
|
|
|
}
|
2010-09-17 15:54:40 +00:00
|
|
|
bool isIncrementOp() const {
|
2012-04-14 14:01:31 +00:00
|
|
|
return isIncrementOp(getOpcode());
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool isDecrementOp(Opcode Op) {
|
|
|
|
return Op == UO_PreDec || Op == UO_PostDec;
|
|
|
|
}
|
|
|
|
bool isDecrementOp() const {
|
|
|
|
return isDecrementOp(getOpcode());
|
2010-09-17 15:54:40 +00:00
|
|
|
}
|
2012-04-14 14:01:31 +00:00
|
|
|
|
|
|
|
static bool isIncrementDecrementOp(Opcode Op) { return Op <= UO_PreDec; }
|
2010-09-17 15:54:40 +00:00
|
|
|
bool isIncrementDecrementOp() const {
|
2012-04-14 14:01:31 +00:00
|
|
|
return isIncrementDecrementOp(getOpcode());
|
2010-09-17 15:54:40 +00:00
|
|
|
}
|
2012-04-14 14:01:31 +00:00
|
|
|
|
2010-09-17 15:54:40 +00:00
|
|
|
static bool isArithmeticOp(Opcode Op) {
|
|
|
|
return Op >= UO_Plus && Op <= UO_LNot;
|
|
|
|
}
|
|
|
|
bool isArithmeticOp() const { return isArithmeticOp(getOpcode()); }
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
/// getOpcodeStr - Turn an Opcode enum value into the punctuation char it
|
|
|
|
/// corresponds to, e.g. "sizeof" or "[pre]++"
|
2012-12-02 13:20:44 +00:00
|
|
|
static StringRef getOpcodeStr(Opcode Op);
|
2009-06-02 17:58:47 +00:00
|
|
|
|
|
|
|
/// \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);
|
|
|
|
|
2012-04-14 14:01:31 +00:00
|
|
|
SourceRange getSourceRange() const LLVM_READONLY {
|
2009-06-02 17:58:47 +00:00
|
|
|
if (isPostfix())
|
|
|
|
return SourceRange(Val->getLocStart(), Loc);
|
|
|
|
else
|
|
|
|
return SourceRange(Loc, Val->getLocEnd());
|
|
|
|
}
|
2012-04-14 14:01:31 +00:00
|
|
|
SourceLocation getExprLoc() const LLVM_READONLY { return Loc; }
|
2009-10-14 18:03:49 +00:00
|
|
|
|
|
|
|
static bool classof(const Stmt *T) {
|
|
|
|
return T->getStmtClass() == UnaryOperatorClass;
|
2009-06-02 17:58:47 +00:00
|
|
|
}
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
// Iterators
|
2011-02-20 13:06:31 +00:00
|
|
|
child_range children() { return child_range(&Val, &Val+1); }
|
2009-06-02 17:58:47 +00:00
|
|
|
};
|
|
|
|
|
2010-05-04 16:12:48 +00:00
|
|
|
/// OffsetOfExpr - [C99 7.17] - This represents an expression of the form
|
|
|
|
/// offsetof(record-type, member-designator). For example, given:
|
|
|
|
/// @code
|
|
|
|
/// struct S {
|
|
|
|
/// float f;
|
2012-04-14 14:01:31 +00:00
|
|
|
/// double d;
|
2010-05-04 16:12:48 +00:00
|
|
|
/// };
|
|
|
|
/// struct T {
|
|
|
|
/// int i;
|
|
|
|
/// struct S s[10];
|
|
|
|
/// };
|
|
|
|
/// @endcode
|
2012-04-14 14:01:31 +00:00
|
|
|
/// we can represent and evaluate the expression @c offsetof(struct T, s[2].d).
|
2010-05-04 16:12:48 +00:00
|
|
|
|
|
|
|
class OffsetOfExpr : public Expr {
|
|
|
|
public:
|
|
|
|
// __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 };
|
2012-04-14 14:01:31 +00:00
|
|
|
|
2010-05-04 16:12:48 +00:00
|
|
|
/// \brief The source range that covers this part of the designator.
|
|
|
|
SourceRange Range;
|
2012-04-14 14:01:31 +00:00
|
|
|
|
2010-05-04 16:12:48 +00:00
|
|
|
/// \brief The data describing the designator, which comes in three
|
|
|
|
/// different forms, depending on the lower two bits.
|
2012-04-14 14:01:31 +00:00
|
|
|
/// - An unsigned index into the array of Expr*'s stored after this node
|
2010-05-04 16:12:48 +00:00
|
|
|
/// 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.
|
2012-04-14 14:01:31 +00:00
|
|
|
/// - A CXXBaseSpecifier*, for references that look at a field in a
|
2010-05-04 16:12:48 +00:00
|
|
|
/// base class.
|
|
|
|
uintptr_t Data;
|
2012-04-14 14:01:31 +00:00
|
|
|
|
2010-05-04 16:12:48 +00:00
|
|
|
public:
|
|
|
|
/// \brief Create an offsetof node that refers to an array element.
|
2012-04-14 14:01:31 +00:00
|
|
|
OffsetOfNode(SourceLocation LBracketLoc, unsigned Index,
|
2010-05-04 16:12:48 +00:00
|
|
|
SourceLocation RBracketLoc)
|
|
|
|
: Range(LBracketLoc, RBracketLoc), Data((Index << 2) | Array) { }
|
2012-04-14 14:01:31 +00:00
|
|
|
|
2010-05-04 16:12:48 +00:00
|
|
|
/// \brief Create an offsetof node that refers to a field.
|
2012-04-14 14:01:31 +00:00
|
|
|
OffsetOfNode(SourceLocation DotLoc, FieldDecl *Field,
|
2010-05-04 16:12:48 +00:00
|
|
|
SourceLocation NameLoc)
|
2012-04-14 14:01:31 +00:00
|
|
|
: Range(DotLoc.isValid()? DotLoc : NameLoc, NameLoc),
|
2010-05-04 16:12:48 +00:00
|
|
|
Data(reinterpret_cast<uintptr_t>(Field) | OffsetOfNode::Field) { }
|
2012-04-14 14:01:31 +00:00
|
|
|
|
2010-05-04 16:12:48 +00:00
|
|
|
/// \brief Create an offsetof node that refers to an identifier.
|
|
|
|
OffsetOfNode(SourceLocation DotLoc, IdentifierInfo *Name,
|
|
|
|
SourceLocation NameLoc)
|
2012-04-14 14:01:31 +00:00
|
|
|
: Range(DotLoc.isValid()? DotLoc : NameLoc, NameLoc),
|
2010-05-04 16:12:48 +00:00
|
|
|
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) {}
|
2012-04-14 14:01:31 +00:00
|
|
|
|
2010-05-04 16:12:48 +00:00
|
|
|
/// \brief Determine what kind of offsetof node this is.
|
2012-04-14 14:01:31 +00:00
|
|
|
Kind getKind() const {
|
2010-05-04 16:12:48 +00:00
|
|
|
return static_cast<Kind>(Data & Mask);
|
|
|
|
}
|
2012-04-14 14:01:31 +00:00
|
|
|
|
2010-05-04 16:12:48 +00:00
|
|
|
/// \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);
|
|
|
|
}
|
2012-04-14 14:01:31 +00:00
|
|
|
|
2010-05-04 16:12:48 +00:00
|
|
|
/// \brief For a field or identifier offsetof node, returns the name of
|
|
|
|
/// the field.
|
|
|
|
IdentifierInfo *getFieldName() const;
|
2012-04-14 14:01:31 +00:00
|
|
|
|
2010-05-04 16:12:48 +00:00
|
|
|
/// \brief For a base class node, returns the base specifier.
|
|
|
|
CXXBaseSpecifier *getBase() const {
|
|
|
|
assert(getKind() == Base);
|
2012-04-14 14:01:31 +00:00
|
|
|
return reinterpret_cast<CXXBaseSpecifier *>(Data & ~(uintptr_t)Mask);
|
2010-05-04 16:12:48 +00:00
|
|
|
}
|
2012-04-14 14:01:31 +00:00
|
|
|
|
2010-05-04 16:12:48 +00:00
|
|
|
/// \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
|
2012-04-14 14:01:31 +00:00
|
|
|
/// contains the location of the period (if there is one) and the
|
2010-05-04 16:12:48 +00:00
|
|
|
/// identifier.
|
2012-04-14 14:01:31 +00:00
|
|
|
SourceRange getSourceRange() const LLVM_READONLY { return Range; }
|
2010-05-04 16:12:48 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
private:
|
2012-04-14 14:01:31 +00:00
|
|
|
|
2010-05-04 16:12:48 +00:00
|
|
|
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;
|
2012-04-14 14:01:31 +00:00
|
|
|
|
|
|
|
OffsetOfExpr(ASTContext &C, QualType type,
|
2010-05-04 16:12:48 +00:00
|
|
|
SourceLocation OperatorLoc, TypeSourceInfo *tsi,
|
2012-12-02 13:20:44 +00:00
|
|
|
ArrayRef<OffsetOfNode> comps, ArrayRef<Expr*> exprs,
|
2010-05-04 16:12:48 +00:00
|
|
|
SourceLocation RParenLoc);
|
|
|
|
|
|
|
|
explicit OffsetOfExpr(unsigned numComps, unsigned numExprs)
|
|
|
|
: Expr(OffsetOfExprClass, EmptyShell()),
|
2012-04-14 14:01:31 +00:00
|
|
|
TSInfo(0), NumComps(numComps), NumExprs(numExprs) {}
|
2010-05-04 16:12:48 +00:00
|
|
|
|
|
|
|
public:
|
2012-04-14 14:01:31 +00:00
|
|
|
|
|
|
|
static OffsetOfExpr *Create(ASTContext &C, QualType type,
|
|
|
|
SourceLocation OperatorLoc, TypeSourceInfo *tsi,
|
2012-12-02 13:20:44 +00:00
|
|
|
ArrayRef<OffsetOfNode> comps,
|
|
|
|
ArrayRef<Expr*> exprs, SourceLocation RParenLoc);
|
2010-05-04 16:12:48 +00:00
|
|
|
|
2012-04-14 14:01:31 +00:00
|
|
|
static OffsetOfExpr *CreateEmpty(ASTContext &C,
|
2010-05-04 16:12:48 +00:00
|
|
|
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; }
|
2012-04-14 14:01:31 +00:00
|
|
|
|
2010-05-04 16:12:48 +00:00
|
|
|
TypeSourceInfo *getTypeSourceInfo() const {
|
|
|
|
return TSInfo;
|
|
|
|
}
|
|
|
|
void setTypeSourceInfo(TypeSourceInfo *tsi) {
|
|
|
|
TSInfo = tsi;
|
|
|
|
}
|
2012-04-14 14:01:31 +00:00
|
|
|
|
2011-06-12 15:46:16 +00:00
|
|
|
const OffsetOfNode &getComponent(unsigned Idx) const {
|
2010-05-04 16:12:48 +00:00
|
|
|
assert(Idx < NumComps && "Subscript out of range");
|
2011-06-12 15:46:16 +00:00
|
|
|
return reinterpret_cast<const OffsetOfNode *> (this + 1)[Idx];
|
2010-05-04 16:12:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void setComponent(unsigned Idx, OffsetOfNode ON) {
|
|
|
|
assert(Idx < NumComps && "Subscript out of range");
|
|
|
|
reinterpret_cast<OffsetOfNode *> (this + 1)[Idx] = ON;
|
|
|
|
}
|
2012-04-14 14:01:31 +00:00
|
|
|
|
2010-05-04 16:12:48 +00:00
|
|
|
unsigned getNumComponents() const {
|
|
|
|
return NumComps;
|
|
|
|
}
|
|
|
|
|
|
|
|
Expr* getIndexExpr(unsigned Idx) {
|
|
|
|
assert(Idx < NumExprs && "Subscript out of range");
|
|
|
|
return reinterpret_cast<Expr **>(
|
|
|
|
reinterpret_cast<OffsetOfNode *>(this+1) + NumComps)[Idx];
|
|
|
|
}
|
2011-06-12 15:46:16 +00:00
|
|
|
const Expr *getIndexExpr(unsigned Idx) const {
|
|
|
|
return const_cast<OffsetOfExpr*>(this)->getIndexExpr(Idx);
|
|
|
|
}
|
2010-05-04 16:12:48 +00:00
|
|
|
|
|
|
|
void setIndexExpr(unsigned Idx, Expr* E) {
|
|
|
|
assert(Idx < NumComps && "Subscript out of range");
|
|
|
|
reinterpret_cast<Expr **>(
|
|
|
|
reinterpret_cast<OffsetOfNode *>(this+1) + NumComps)[Idx] = E;
|
|
|
|
}
|
2012-04-14 14:01:31 +00:00
|
|
|
|
2010-05-04 16:12:48 +00:00
|
|
|
unsigned getNumExpressions() const {
|
|
|
|
return NumExprs;
|
|
|
|
}
|
|
|
|
|
2012-04-14 14:01:31 +00:00
|
|
|
SourceRange getSourceRange() const LLVM_READONLY {
|
2010-05-04 16:12:48 +00:00
|
|
|
return SourceRange(OperatorLoc, RParenLoc);
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool classof(const Stmt *T) {
|
|
|
|
return T->getStmtClass() == OffsetOfExprClass;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Iterators
|
2011-02-20 13:06:31 +00:00
|
|
|
child_range children() {
|
|
|
|
Stmt **begin =
|
|
|
|
reinterpret_cast<Stmt**>(reinterpret_cast<OffsetOfNode*>(this + 1)
|
|
|
|
+ NumComps);
|
|
|
|
return child_range(begin, begin + NumExprs);
|
|
|
|
}
|
2010-05-04 16:12:48 +00:00
|
|
|
};
|
|
|
|
|
2011-05-02 19:39:53 +00:00
|
|
|
/// 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 {
|
2009-06-02 17:58:47 +00:00
|
|
|
union {
|
2009-12-15 18:49:47 +00:00
|
|
|
TypeSourceInfo *Ty;
|
2009-06-02 17:58:47 +00:00
|
|
|
Stmt *Ex;
|
|
|
|
} Argument;
|
|
|
|
SourceLocation OpLoc, RParenLoc;
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
public:
|
2011-05-02 19:39:53 +00:00
|
|
|
UnaryExprOrTypeTraitExpr(UnaryExprOrTypeTrait ExprKind, TypeSourceInfo *TInfo,
|
|
|
|
QualType resultType, SourceLocation op,
|
|
|
|
SourceLocation rp) :
|
|
|
|
Expr(UnaryExprOrTypeTraitExprClass, resultType, VK_RValue, OK_Ordinary,
|
2009-06-02 17:58:47 +00:00
|
|
|
false, // Never type-dependent (C++ [temp.dep.expr]p3).
|
|
|
|
// Value-dependent if the argument is type-dependent.
|
2011-02-20 13:06:31 +00:00
|
|
|
TInfo->getType()->isDependentType(),
|
2011-07-17 15:40:56 +00:00
|
|
|
TInfo->getType()->isInstantiationDependentType(),
|
2011-02-20 13:06:31 +00:00
|
|
|
TInfo->getType()->containsUnexpandedParameterPack()),
|
2012-04-14 14:01:31 +00:00
|
|
|
OpLoc(op), RParenLoc(rp) {
|
|
|
|
UnaryExprOrTypeTraitExprBits.Kind = ExprKind;
|
|
|
|
UnaryExprOrTypeTraitExprBits.IsType = true;
|
2009-12-15 18:49:47 +00:00
|
|
|
Argument.Ty = TInfo;
|
2009-06-02 17:58:47 +00:00
|
|
|
}
|
|
|
|
|
2011-05-02 19:39:53 +00:00
|
|
|
UnaryExprOrTypeTraitExpr(UnaryExprOrTypeTrait ExprKind, Expr *E,
|
|
|
|
QualType resultType, SourceLocation op,
|
|
|
|
SourceLocation rp) :
|
|
|
|
Expr(UnaryExprOrTypeTraitExprClass, resultType, VK_RValue, OK_Ordinary,
|
2009-06-02 17:58:47 +00:00
|
|
|
false, // Never type-dependent (C++ [temp.dep.expr]p3).
|
|
|
|
// Value-dependent if the argument is type-dependent.
|
2011-02-20 13:06:31 +00:00
|
|
|
E->isTypeDependent(),
|
2011-07-17 15:40:56 +00:00
|
|
|
E->isInstantiationDependent(),
|
2011-02-20 13:06:31 +00:00
|
|
|
E->containsUnexpandedParameterPack()),
|
2012-04-14 14:01:31 +00:00
|
|
|
OpLoc(op), RParenLoc(rp) {
|
|
|
|
UnaryExprOrTypeTraitExprBits.Kind = ExprKind;
|
|
|
|
UnaryExprOrTypeTraitExprBits.IsType = false;
|
2009-06-02 17:58:47 +00:00
|
|
|
Argument.Ex = E;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// \brief Construct an empty sizeof/alignof expression.
|
2011-05-02 19:39:53 +00:00
|
|
|
explicit UnaryExprOrTypeTraitExpr(EmptyShell Empty)
|
|
|
|
: Expr(UnaryExprOrTypeTraitExprClass, Empty) { }
|
2009-06-02 17:58:47 +00:00
|
|
|
|
2011-05-02 19:39:53 +00:00
|
|
|
UnaryExprOrTypeTrait getKind() const {
|
2012-04-14 14:01:31 +00:00
|
|
|
return static_cast<UnaryExprOrTypeTrait>(UnaryExprOrTypeTraitExprBits.Kind);
|
2011-05-02 19:39:53 +00:00
|
|
|
}
|
2012-04-14 14:01:31 +00:00
|
|
|
void setKind(UnaryExprOrTypeTrait K) { UnaryExprOrTypeTraitExprBits.Kind = K;}
|
2009-06-02 17:58:47 +00:00
|
|
|
|
2012-04-14 14:01:31 +00:00
|
|
|
bool isArgumentType() const { return UnaryExprOrTypeTraitExprBits.IsType; }
|
2009-06-02 17:58:47 +00:00
|
|
|
QualType getArgumentType() const {
|
2009-11-04 15:04:32 +00:00
|
|
|
return getArgumentTypeInfo()->getType();
|
|
|
|
}
|
2009-12-15 18:49:47 +00:00
|
|
|
TypeSourceInfo *getArgumentTypeInfo() const {
|
2009-06-02 17:58:47 +00:00
|
|
|
assert(isArgumentType() && "calling getArgumentType() when arg is expr");
|
2009-11-04 15:04:32 +00:00
|
|
|
return Argument.Ty;
|
2009-06-02 17:58:47 +00:00
|
|
|
}
|
|
|
|
Expr *getArgumentExpr() {
|
|
|
|
assert(!isArgumentType() && "calling getArgumentExpr() when arg is type");
|
|
|
|
return static_cast<Expr*>(Argument.Ex);
|
|
|
|
}
|
|
|
|
const Expr *getArgumentExpr() const {
|
2011-05-02 19:39:53 +00:00
|
|
|
return const_cast<UnaryExprOrTypeTraitExpr*>(this)->getArgumentExpr();
|
2009-06-02 17:58:47 +00:00
|
|
|
}
|
|
|
|
|
2012-04-14 14:01:31 +00:00
|
|
|
void setArgument(Expr *E) {
|
|
|
|
Argument.Ex = E;
|
|
|
|
UnaryExprOrTypeTraitExprBits.IsType = false;
|
|
|
|
}
|
2009-12-15 18:49:47 +00:00
|
|
|
void setArgument(TypeSourceInfo *TInfo) {
|
|
|
|
Argument.Ty = TInfo;
|
2012-04-14 14:01:31 +00:00
|
|
|
UnaryExprOrTypeTraitExprBits.IsType = true;
|
2009-06-02 17:58:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// 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; }
|
|
|
|
|
2012-04-14 14:01:31 +00:00
|
|
|
SourceRange getSourceRange() const LLVM_READONLY {
|
2009-06-02 17:58:47 +00:00
|
|
|
return SourceRange(OpLoc, RParenLoc);
|
|
|
|
}
|
|
|
|
|
2009-10-14 18:03:49 +00:00
|
|
|
static bool classof(const Stmt *T) {
|
2011-05-02 19:39:53 +00:00
|
|
|
return T->getStmtClass() == UnaryExprOrTypeTraitExprClass;
|
2009-06-02 17:58:47 +00:00
|
|
|
}
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
// Iterators
|
2011-02-20 13:06:31 +00:00
|
|
|
child_range children();
|
2009-06-02 17:58:47 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Postfix Operators.
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
/// ArraySubscriptExpr - [C99 6.5.2.1] Array Subscripting.
|
|
|
|
class ArraySubscriptExpr : public Expr {
|
|
|
|
enum { LHS, RHS, END_EXPR=2 };
|
2009-10-14 18:03:49 +00:00
|
|
|
Stmt* SubExprs[END_EXPR];
|
2009-06-02 17:58:47 +00:00
|
|
|
SourceLocation RBracketLoc;
|
|
|
|
public:
|
|
|
|
ArraySubscriptExpr(Expr *lhs, Expr *rhs, QualType t,
|
2011-02-20 13:06:31 +00:00
|
|
|
ExprValueKind VK, ExprObjectKind OK,
|
2009-06-02 17:58:47 +00:00
|
|
|
SourceLocation rbracketloc)
|
2011-02-20 13:06:31 +00:00
|
|
|
: Expr(ArraySubscriptExprClass, t, VK, OK,
|
2009-06-02 17:58:47 +00:00
|
|
|
lhs->isTypeDependent() || rhs->isTypeDependent(),
|
2011-02-20 13:06:31 +00:00
|
|
|
lhs->isValueDependent() || rhs->isValueDependent(),
|
2011-07-17 15:40:56 +00:00
|
|
|
(lhs->isInstantiationDependent() ||
|
|
|
|
rhs->isInstantiationDependent()),
|
2011-02-20 13:06:31 +00:00
|
|
|
(lhs->containsUnexpandedParameterPack() ||
|
|
|
|
rhs->containsUnexpandedParameterPack())),
|
2009-06-02 17:58:47 +00:00
|
|
|
RBracketLoc(rbracketloc) {
|
|
|
|
SubExprs[LHS] = lhs;
|
|
|
|
SubExprs[RHS] = rhs;
|
|
|
|
}
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
/// \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; }
|
2009-10-14 18:03:49 +00:00
|
|
|
|
|
|
|
Expr *getBase() {
|
2009-06-02 17:58:47 +00:00
|
|
|
return cast<Expr>(getRHS()->getType()->isIntegerType() ? getLHS():getRHS());
|
|
|
|
}
|
2009-10-14 18:03:49 +00:00
|
|
|
|
|
|
|
const Expr *getBase() const {
|
2009-06-02 17:58:47 +00:00
|
|
|
return cast<Expr>(getRHS()->getType()->isIntegerType() ? getLHS():getRHS());
|
|
|
|
}
|
2009-10-14 18:03:49 +00:00
|
|
|
|
|
|
|
Expr *getIdx() {
|
2009-06-02 17:58:47 +00:00
|
|
|
return cast<Expr>(getRHS()->getType()->isIntegerType() ? getRHS():getLHS());
|
|
|
|
}
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
const Expr *getIdx() const {
|
|
|
|
return cast<Expr>(getRHS()->getType()->isIntegerType() ? getRHS():getLHS());
|
2009-10-14 18:03:49 +00:00
|
|
|
}
|
|
|
|
|
2012-04-14 14:01:31 +00:00
|
|
|
SourceRange getSourceRange() const LLVM_READONLY {
|
2009-06-02 17:58:47 +00:00
|
|
|
return SourceRange(getLHS()->getLocStart(), RBracketLoc);
|
|
|
|
}
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
SourceLocation getRBracketLoc() const { return RBracketLoc; }
|
|
|
|
void setRBracketLoc(SourceLocation L) { RBracketLoc = L; }
|
|
|
|
|
2012-04-14 14:01:31 +00:00
|
|
|
SourceLocation getExprLoc() const LLVM_READONLY { return getBase()->getExprLoc(); }
|
2009-06-02 17:58:47 +00:00
|
|
|
|
2009-10-14 18:03:49 +00:00
|
|
|
static bool classof(const Stmt *T) {
|
|
|
|
return T->getStmtClass() == ArraySubscriptExprClass;
|
2009-06-02 17:58:47 +00:00
|
|
|
}
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
// Iterators
|
2011-02-20 13:06:31 +00:00
|
|
|
child_range children() {
|
|
|
|
return child_range(&SubExprs[0], &SubExprs[0]+END_EXPR);
|
|
|
|
}
|
2009-06-02 17:58:47 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/// CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
|
2009-10-14 18:03:49 +00:00
|
|
|
/// CallExpr itself represents a normal function call, e.g., "f(x, 2)",
|
2009-06-02 17:58:47 +00:00
|
|
|
/// while its subclasses may represent alternative syntax that (semantically)
|
2009-10-14 18:03:49 +00:00
|
|
|
/// results in a function call. For example, CXXOperatorCallExpr is
|
2009-06-02 17:58:47 +00:00
|
|
|
/// a subclass for overloaded operator calls that use operator syntax, e.g.,
|
|
|
|
/// "str1 + str2" to resolve to a function call.
|
|
|
|
class CallExpr : public Expr {
|
2011-02-20 13:06:31 +00:00
|
|
|
enum { FN=0, PREARGS_START=1 };
|
2009-06-02 17:58:47 +00:00
|
|
|
Stmt **SubExprs;
|
|
|
|
unsigned NumArgs;
|
|
|
|
SourceLocation RParenLoc;
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
protected:
|
2011-02-20 13:06:31 +00:00
|
|
|
// These versions of the constructor are for derived classes.
|
|
|
|
CallExpr(ASTContext& C, StmtClass SC, Expr *fn, unsigned NumPreArgs,
|
2012-12-02 13:20:44 +00:00
|
|
|
ArrayRef<Expr*> args, QualType t, ExprValueKind VK,
|
2011-02-20 13:06:31 +00:00
|
|
|
SourceLocation rparenloc);
|
|
|
|
CallExpr(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; }
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
public:
|
2012-12-02 13:20:44 +00:00
|
|
|
CallExpr(ASTContext& C, Expr *fn, ArrayRef<Expr*> args, QualType t,
|
2011-02-20 13:06:31 +00:00
|
|
|
ExprValueKind VK, SourceLocation rparenloc);
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
/// \brief Build an empty call expression.
|
2009-10-14 18:03:49 +00:00
|
|
|
CallExpr(ASTContext &C, StmtClass SC, EmptyShell Empty);
|
2009-06-02 17:58:47 +00:00
|
|
|
|
|
|
|
const Expr *getCallee() const { return cast<Expr>(SubExprs[FN]); }
|
|
|
|
Expr *getCallee() { return cast<Expr>(SubExprs[FN]); }
|
|
|
|
void setCallee(Expr *F) { SubExprs[FN] = F; }
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2010-01-01 10:34:51 +00:00
|
|
|
Decl *getCalleeDecl();
|
|
|
|
const Decl *getCalleeDecl() const {
|
|
|
|
return const_cast<CallExpr*>(this)->getCalleeDecl();
|
|
|
|
}
|
|
|
|
|
2009-10-14 18:03:49 +00:00
|
|
|
/// \brief If the callee is a FunctionDecl, return it. Otherwise return 0.
|
|
|
|
FunctionDecl *getDirectCallee();
|
|
|
|
const FunctionDecl *getDirectCallee() const {
|
|
|
|
return const_cast<CallExpr*>(this)->getDirectCallee();
|
|
|
|
}
|
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
/// getNumArgs - Return the number of actual arguments to this call.
|
|
|
|
///
|
|
|
|
unsigned getNumArgs() const { return NumArgs; }
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2011-02-20 13:06:31 +00:00
|
|
|
/// \brief Retrieve the call arguments.
|
|
|
|
Expr **getArgs() {
|
|
|
|
return reinterpret_cast<Expr **>(SubExprs+getNumPreArgs()+PREARGS_START);
|
|
|
|
}
|
2012-04-14 14:01:31 +00:00
|
|
|
const Expr *const *getArgs() const {
|
|
|
|
return const_cast<CallExpr*>(this)->getArgs();
|
|
|
|
}
|
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
/// getArg - Return the specified argument.
|
|
|
|
Expr *getArg(unsigned Arg) {
|
|
|
|
assert(Arg < NumArgs && "Arg access out of range!");
|
2011-02-20 13:06:31 +00:00
|
|
|
return cast<Expr>(SubExprs[Arg+getNumPreArgs()+PREARGS_START]);
|
2009-06-02 17:58:47 +00:00
|
|
|
}
|
|
|
|
const Expr *getArg(unsigned Arg) const {
|
|
|
|
assert(Arg < NumArgs && "Arg access out of range!");
|
2011-02-20 13:06:31 +00:00
|
|
|
return cast<Expr>(SubExprs[Arg+getNumPreArgs()+PREARGS_START]);
|
2009-06-02 17:58:47 +00:00
|
|
|
}
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
/// setArg - Set the specified argument.
|
|
|
|
void setArg(unsigned Arg, Expr *ArgExpr) {
|
|
|
|
assert(Arg < NumArgs && "Arg access out of range!");
|
2011-02-20 13:06:31 +00:00
|
|
|
SubExprs[Arg+getNumPreArgs()+PREARGS_START] = ArgExpr;
|
2009-06-02 17:58:47 +00:00
|
|
|
}
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
/// 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(ASTContext& C, unsigned NumArgs);
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
typedef ExprIterator arg_iterator;
|
|
|
|
typedef ConstExprIterator const_arg_iterator;
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2011-02-20 13:06:31 +00:00
|
|
|
arg_iterator arg_begin() { return 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();
|
|
|
|
}
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
/// getNumCommas - Return the number of commas that must have been present in
|
|
|
|
/// this function call.
|
|
|
|
unsigned getNumCommas() const { return NumArgs ? NumArgs - 1 : 0; }
|
|
|
|
|
|
|
|
/// isBuiltinCall - If this is a call to a builtin, return the builtin ID. If
|
|
|
|
/// not, return 0.
|
2012-04-14 14:01:31 +00:00
|
|
|
unsigned isBuiltinCall() const;
|
2009-10-14 18:03:49 +00:00
|
|
|
|
|
|
|
/// 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
|
2009-06-02 17:58:47 +00:00
|
|
|
/// type.
|
|
|
|
QualType getCallReturnType() const;
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
SourceLocation getRParenLoc() const { return RParenLoc; }
|
|
|
|
void setRParenLoc(SourceLocation L) { RParenLoc = L; }
|
|
|
|
|
2012-04-14 14:01:31 +00:00
|
|
|
SourceRange getSourceRange() const LLVM_READONLY;
|
|
|
|
SourceLocation getLocStart() const LLVM_READONLY;
|
|
|
|
SourceLocation getLocEnd() const LLVM_READONLY;
|
2009-10-14 18:03:49 +00:00
|
|
|
|
|
|
|
static bool classof(const Stmt *T) {
|
2010-05-27 15:17:06 +00:00
|
|
|
return T->getStmtClass() >= firstCallExprConstant &&
|
|
|
|
T->getStmtClass() <= lastCallExprConstant;
|
2009-06-02 17:58:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Iterators
|
2011-02-20 13:06:31 +00:00
|
|
|
child_range children() {
|
|
|
|
return child_range(&SubExprs[0],
|
|
|
|
&SubExprs[0]+NumArgs+getNumPreArgs()+PREARGS_START);
|
|
|
|
}
|
2009-06-02 17:58:47 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/// MemberExpr - [C99 6.5.2.3] Structure and Union Members. X->F and X.F.
|
|
|
|
///
|
|
|
|
class MemberExpr : public Expr {
|
2010-04-02 08:55:10 +00:00
|
|
|
/// Extra data stored in some member expressions.
|
2011-05-02 19:39:53 +00:00
|
|
|
struct MemberNameQualifier {
|
|
|
|
/// \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.
|
2010-05-04 16:12:48 +00:00
|
|
|
DeclAccessPair FoundDecl;
|
2010-04-02 08:55:10 +00:00
|
|
|
};
|
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
/// Base - the expression for the base pointer or structure references. In
|
|
|
|
/// X.F, this is "X".
|
|
|
|
Stmt *Base;
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
/// MemberDecl - This is the decl being referenced by the field/member name.
|
|
|
|
/// In X.F, this is the decl referenced by F.
|
2009-12-15 18:49:47 +00:00
|
|
|
ValueDecl *MemberDecl;
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2010-09-17 15:54:40 +00:00
|
|
|
/// MemberDNLoc - Provides source/type location info for the
|
|
|
|
/// declaration name embedded in MemberDecl.
|
|
|
|
DeclarationNameLoc MemberDNLoc;
|
|
|
|
|
2012-04-14 14:01:31 +00:00
|
|
|
/// MemberLoc - This is the location of the member name.
|
|
|
|
SourceLocation MemberLoc;
|
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
/// IsArrow - True if this is "X->F", false if this is "X.F".
|
2009-10-14 18:03:49 +00:00
|
|
|
bool IsArrow : 1;
|
|
|
|
|
|
|
|
/// \brief True if this member expression used a nested-name-specifier to
|
2010-04-02 08:55:10 +00:00
|
|
|
/// refer to the member, e.g., "x->Base::f", or found its member via a using
|
|
|
|
/// declaration. When true, a MemberNameQualifier
|
2009-10-14 18:03:49 +00:00
|
|
|
/// structure is allocated immediately after the MemberExpr.
|
2010-04-02 08:55:10 +00:00
|
|
|
bool HasQualifierOrFoundDecl : 1;
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2012-04-14 14:01:31 +00:00
|
|
|
/// \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 allocated immediately after
|
|
|
|
/// the MemberExpr or, if the member expression also has a qualifier,
|
|
|
|
/// after the MemberNameQualifier structure.
|
|
|
|
bool HasTemplateKWAndArgsInfo : 1;
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2011-10-20 21:14:49 +00:00
|
|
|
/// \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;
|
|
|
|
|
2009-10-14 18:03:49 +00:00
|
|
|
/// \brief Retrieve the qualifier that preceded the member name, if any.
|
2010-04-02 08:55:10 +00:00
|
|
|
MemberNameQualifier *getMemberQualifier() {
|
|
|
|
assert(HasQualifierOrFoundDecl);
|
|
|
|
return reinterpret_cast<MemberNameQualifier *> (this + 1);
|
2009-10-14 18:03:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// \brief Retrieve the qualifier that preceded the member name, if any.
|
2010-04-02 08:55:10 +00:00
|
|
|
const MemberNameQualifier *getMemberQualifier() const {
|
2009-10-14 18:03:49 +00:00
|
|
|
return const_cast<MemberExpr *>(this)->getMemberQualifier();
|
|
|
|
}
|
|
|
|
|
2010-09-17 15:54:40 +00:00
|
|
|
public:
|
|
|
|
MemberExpr(Expr *base, bool isarrow, ValueDecl *memberdecl,
|
2011-02-20 13:06:31 +00:00
|
|
|
const DeclarationNameInfo &NameInfo, QualType ty,
|
|
|
|
ExprValueKind VK, ExprObjectKind OK)
|
|
|
|
: Expr(MemberExprClass, ty, VK, OK,
|
2012-04-14 14:01:31 +00:00
|
|
|
base->isTypeDependent(),
|
2011-07-17 15:40:56 +00:00
|
|
|
base->isValueDependent(),
|
|
|
|
base->isInstantiationDependent(),
|
2011-02-20 13:06:31 +00:00
|
|
|
base->containsUnexpandedParameterPack()),
|
2012-04-14 14:01:31 +00:00
|
|
|
Base(base), MemberDecl(memberdecl), MemberDNLoc(NameInfo.getInfo()),
|
|
|
|
MemberLoc(NameInfo.getLoc()), IsArrow(isarrow),
|
|
|
|
HasQualifierOrFoundDecl(false), HasTemplateKWAndArgsInfo(false),
|
2011-10-20 21:14:49 +00:00
|
|
|
HadMultipleCandidates(false) {
|
2010-09-17 15:54:40 +00:00
|
|
|
assert(memberdecl->getDeclName() == NameInfo.getName());
|
2009-10-14 18:03:49 +00:00
|
|
|
}
|
|
|
|
|
2010-09-17 15:54:40 +00:00
|
|
|
// 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
|
2012-04-14 14:01:31 +00:00
|
|
|
// for constructors, destructors and conversion operators).
|
2009-12-15 18:49:47 +00:00
|
|
|
MemberExpr(Expr *base, bool isarrow, ValueDecl *memberdecl,
|
2011-02-20 13:06:31 +00:00
|
|
|
SourceLocation l, QualType ty,
|
|
|
|
ExprValueKind VK, ExprObjectKind OK)
|
|
|
|
: Expr(MemberExprClass, ty, VK, OK,
|
|
|
|
base->isTypeDependent(), base->isValueDependent(),
|
2011-07-17 15:40:56 +00:00
|
|
|
base->isInstantiationDependent(),
|
2011-02-20 13:06:31 +00:00
|
|
|
base->containsUnexpandedParameterPack()),
|
2012-04-14 14:01:31 +00:00
|
|
|
Base(base), MemberDecl(memberdecl), MemberDNLoc(), MemberLoc(l),
|
2010-09-17 15:54:40 +00:00
|
|
|
IsArrow(isarrow),
|
2012-04-14 14:01:31 +00:00
|
|
|
HasQualifierOrFoundDecl(false), HasTemplateKWAndArgsInfo(false),
|
2011-10-20 21:14:49 +00:00
|
|
|
HadMultipleCandidates(false) {}
|
2009-06-02 17:58:47 +00:00
|
|
|
|
2009-10-14 18:03:49 +00:00
|
|
|
static MemberExpr *Create(ASTContext &C, Expr *base, bool isarrow,
|
2011-05-02 19:39:53 +00:00
|
|
|
NestedNameSpecifierLoc QualifierLoc,
|
2012-04-14 14:01:31 +00:00
|
|
|
SourceLocation TemplateKWLoc,
|
2010-05-04 16:12:48 +00:00
|
|
|
ValueDecl *memberdecl, DeclAccessPair founddecl,
|
2010-09-17 15:54:40 +00:00
|
|
|
DeclarationNameInfo MemberNameInfo,
|
2009-12-01 11:08:04 +00:00
|
|
|
const TemplateArgumentListInfo *targs,
|
2011-02-20 13:06:31 +00:00
|
|
|
QualType ty, ExprValueKind VK, ExprObjectKind OK);
|
2009-06-02 17:58:47 +00:00
|
|
|
|
|
|
|
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.
|
2009-12-15 18:49:47 +00:00
|
|
|
ValueDecl *getMemberDecl() const { return MemberDecl; }
|
|
|
|
void setMemberDecl(ValueDecl *D) { MemberDecl = D; }
|
2009-06-02 17:58:47 +00:00
|
|
|
|
2010-04-02 08:55:10 +00:00
|
|
|
/// \brief Retrieves the declaration found by lookup.
|
2010-05-04 16:12:48 +00:00
|
|
|
DeclAccessPair getFoundDecl() const {
|
2010-04-02 08:55:10 +00:00
|
|
|
if (!HasQualifierOrFoundDecl)
|
2010-05-04 16:12:48 +00:00
|
|
|
return DeclAccessPair::make(getMemberDecl(),
|
|
|
|
getMemberDecl()->getAccess());
|
2010-04-02 08:55:10 +00:00
|
|
|
return getMemberQualifier()->FoundDecl;
|
|
|
|
}
|
|
|
|
|
2009-10-14 18:03:49 +00:00
|
|
|
/// \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.
|
2010-04-02 08:55:10 +00:00
|
|
|
bool hasQualifier() const { return getQualifier() != 0; }
|
2009-10-14 18:03:49 +00:00
|
|
|
|
|
|
|
/// \brief If the member name was qualified, retrieves the
|
|
|
|
/// nested-name-specifier that precedes the member name. Otherwise, returns
|
|
|
|
/// NULL.
|
|
|
|
NestedNameSpecifier *getQualifier() const {
|
2010-04-02 08:55:10 +00:00
|
|
|
if (!HasQualifierOrFoundDecl)
|
2009-10-14 18:03:49 +00:00
|
|
|
return 0;
|
|
|
|
|
2011-05-02 19:39:53 +00:00
|
|
|
return getMemberQualifier()->QualifierLoc.getNestedNameSpecifier();
|
|
|
|
}
|
|
|
|
|
2012-04-14 14:01:31 +00:00
|
|
|
/// \brief If the member name was qualified, retrieves the
|
2011-05-02 19:39:53 +00:00
|
|
|
/// nested-name-specifier that precedes the member name, with source-location
|
|
|
|
/// information.
|
|
|
|
NestedNameSpecifierLoc getQualifierLoc() const {
|
|
|
|
if (!hasQualifier())
|
|
|
|
return NestedNameSpecifierLoc();
|
2012-04-14 14:01:31 +00:00
|
|
|
|
2011-05-02 19:39:53 +00:00
|
|
|
return getMemberQualifier()->QualifierLoc;
|
2009-10-14 18:03:49 +00:00
|
|
|
}
|
|
|
|
|
2012-04-14 14:01:31 +00:00
|
|
|
/// \brief Return the optional template keyword and arguments info.
|
|
|
|
ASTTemplateKWAndArgsInfo *getTemplateKWAndArgsInfo() {
|
|
|
|
if (!HasTemplateKWAndArgsInfo)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (!HasQualifierOrFoundDecl)
|
|
|
|
return reinterpret_cast<ASTTemplateKWAndArgsInfo *>(this + 1);
|
|
|
|
|
|
|
|
return reinterpret_cast<ASTTemplateKWAndArgsInfo *>(
|
|
|
|
getMemberQualifier() + 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// \brief Return the optional template keyword and arguments info.
|
|
|
|
const ASTTemplateKWAndArgsInfo *getTemplateKWAndArgsInfo() const {
|
|
|
|
return const_cast<MemberExpr*>(this)->getTemplateKWAndArgsInfo();
|
|
|
|
}
|
|
|
|
|
|
|
|
/// \brief Retrieve the location of the template keyword preceding
|
|
|
|
/// the member name, if any.
|
|
|
|
SourceLocation getTemplateKeywordLoc() const {
|
|
|
|
if (!HasTemplateKWAndArgsInfo) return SourceLocation();
|
|
|
|
return getTemplateKWAndArgsInfo()->getTemplateKeywordLoc();
|
|
|
|
}
|
|
|
|
|
|
|
|
/// \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 getTemplateKWAndArgsInfo()->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 getTemplateKWAndArgsInfo()->RAngleLoc;
|
2009-10-14 18:03:49 +00:00
|
|
|
}
|
|
|
|
|
2012-04-14 14:01:31 +00:00
|
|
|
/// 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(); }
|
|
|
|
|
2009-12-01 11:08:04 +00:00
|
|
|
/// \brief Copies the template arguments (if present) into the given
|
|
|
|
/// structure.
|
|
|
|
void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const {
|
2010-09-17 15:54:40 +00:00
|
|
|
if (hasExplicitTemplateArgs())
|
|
|
|
getExplicitTemplateArgs().copyInto(List);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// \brief Retrieve the explicit template argument list that
|
|
|
|
/// follow the member template name. This must only be called on an
|
|
|
|
/// expression with explicit template arguments.
|
2011-10-20 21:14:49 +00:00
|
|
|
ASTTemplateArgumentListInfo &getExplicitTemplateArgs() {
|
2012-04-14 14:01:31 +00:00
|
|
|
assert(hasExplicitTemplateArgs());
|
|
|
|
return *getTemplateKWAndArgsInfo();
|
2010-09-17 15:54:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// \brief Retrieve the explicit template argument list that
|
|
|
|
/// followed the member template name. This must only be called on
|
|
|
|
/// an expression with explicit template arguments.
|
2011-10-20 21:14:49 +00:00
|
|
|
const ASTTemplateArgumentListInfo &getExplicitTemplateArgs() const {
|
2010-09-17 15:54:40 +00:00
|
|
|
return const_cast<MemberExpr *>(this)->getExplicitTemplateArgs();
|
|
|
|
}
|
|
|
|
|
|
|
|
/// \brief Retrieves the optional explicit template arguments.
|
|
|
|
/// This points to the same data as getExplicitTemplateArgs(), but
|
|
|
|
/// returns null if there are no explicit template arguments.
|
2011-10-20 21:14:49 +00:00
|
|
|
const ASTTemplateArgumentListInfo *getOptionalExplicitTemplateArgs() const {
|
2010-09-17 15:54:40 +00:00
|
|
|
if (!hasExplicitTemplateArgs()) return 0;
|
|
|
|
return &getExplicitTemplateArgs();
|
2009-12-01 11:08:04 +00:00
|
|
|
}
|
2009-10-14 18:03:49 +00:00
|
|
|
|
|
|
|
/// \brief Retrieve the template arguments provided as part of this
|
|
|
|
/// template-id.
|
2009-11-04 15:04:32 +00:00
|
|
|
const TemplateArgumentLoc *getTemplateArgs() const {
|
2012-04-14 14:01:31 +00:00
|
|
|
if (!hasExplicitTemplateArgs())
|
2009-10-14 18:03:49 +00:00
|
|
|
return 0;
|
|
|
|
|
2010-09-17 15:54:40 +00:00
|
|
|
return getExplicitTemplateArgs().getTemplateArgs();
|
2009-10-14 18:03:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// \brief Retrieve the number of template arguments provided as part of this
|
|
|
|
/// template-id.
|
|
|
|
unsigned getNumTemplateArgs() const {
|
2012-04-14 14:01:31 +00:00
|
|
|
if (!hasExplicitTemplateArgs())
|
2009-10-14 18:03:49 +00:00
|
|
|
return 0;
|
|
|
|
|
2010-09-17 15:54:40 +00:00
|
|
|
return getExplicitTemplateArgs().NumTemplateArgs;
|
2009-10-14 18:03:49 +00:00
|
|
|
}
|
|
|
|
|
2010-09-17 15:54:40 +00:00
|
|
|
/// \brief Retrieve the member declaration name info.
|
|
|
|
DeclarationNameInfo getMemberNameInfo() const {
|
|
|
|
return DeclarationNameInfo(MemberDecl->getDeclName(),
|
|
|
|
MemberLoc, MemberDNLoc);
|
2009-10-14 18:03:49 +00:00
|
|
|
}
|
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
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; }
|
|
|
|
|
2012-04-14 14:01:31 +00:00
|
|
|
SourceRange getSourceRange() const LLVM_READONLY;
|
|
|
|
SourceLocation getLocStart() const LLVM_READONLY;
|
|
|
|
SourceLocation getLocEnd() const LLVM_READONLY;
|
|
|
|
|
|
|
|
SourceLocation getExprLoc() const LLVM_READONLY { return MemberLoc; }
|
2009-06-02 17:58:47 +00:00
|
|
|
|
2011-05-02 19:39:53 +00:00
|
|
|
/// \brief Determine whether the base of this explicit is implicit.
|
|
|
|
bool isImplicitAccess() const {
|
|
|
|
return getBase() && getBase()->isImplicitCXXThis();
|
|
|
|
}
|
2011-10-20 21:14:49 +00:00
|
|
|
|
|
|
|
/// \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;
|
|
|
|
}
|
|
|
|
|
2009-10-14 18:03:49 +00:00
|
|
|
static bool classof(const Stmt *T) {
|
|
|
|
return T->getStmtClass() == MemberExprClass;
|
2009-06-02 17:58:47 +00:00
|
|
|
}
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
// Iterators
|
2011-02-20 13:06:31 +00:00
|
|
|
child_range children() { return child_range(&Base, &Base+1); }
|
|
|
|
|
|
|
|
friend class ASTReader;
|
|
|
|
friend class ASTStmtWriter;
|
2009-06-02 17:58:47 +00:00
|
|
|
};
|
|
|
|
|
2009-10-14 18:03:49 +00:00
|
|
|
/// CompoundLiteralExpr - [C99 6.5.2.5]
|
2009-06-02 17:58:47 +00:00
|
|
|
///
|
|
|
|
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;
|
2010-01-23 11:10:26 +00:00
|
|
|
|
|
|
|
/// The type as written. This can be an incomplete array type, in
|
|
|
|
/// which case the actual expression type will be different.
|
2012-04-14 14:01:31 +00:00
|
|
|
/// The int part of the pair stores whether this expr is file scope.
|
|
|
|
llvm::PointerIntPair<TypeSourceInfo *, 1, bool> TInfoAndScope;
|
2009-06-02 17:58:47 +00:00
|
|
|
Stmt *Init;
|
|
|
|
public:
|
2010-01-23 11:10:26 +00:00
|
|
|
CompoundLiteralExpr(SourceLocation lparenloc, TypeSourceInfo *tinfo,
|
2011-02-20 13:06:31 +00:00
|
|
|
QualType T, ExprValueKind VK, Expr *init, bool fileScope)
|
|
|
|
: Expr(CompoundLiteralExprClass, T, VK, OK_Ordinary,
|
2012-04-14 14:01:31 +00:00
|
|
|
tinfo->getType()->isDependentType(),
|
2011-02-20 13:06:31 +00:00
|
|
|
init->isValueDependent(),
|
2011-07-17 15:40:56 +00:00
|
|
|
(init->isInstantiationDependent() ||
|
|
|
|
tinfo->getType()->isInstantiationDependentType()),
|
2011-02-20 13:06:31 +00:00
|
|
|
init->containsUnexpandedParameterPack()),
|
2012-04-14 14:01:31 +00:00
|
|
|
LParenLoc(lparenloc), TInfoAndScope(tinfo, fileScope), Init(init) {}
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
/// \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; }
|
|
|
|
|
2012-04-14 14:01:31 +00:00
|
|
|
bool isFileScope() const { return TInfoAndScope.getInt(); }
|
|
|
|
void setFileScope(bool FS) { TInfoAndScope.setInt(FS); }
|
2009-06-02 17:58:47 +00:00
|
|
|
|
|
|
|
SourceLocation getLParenLoc() const { return LParenLoc; }
|
|
|
|
void setLParenLoc(SourceLocation L) { LParenLoc = L; }
|
|
|
|
|
2012-04-14 14:01:31 +00:00
|
|
|
TypeSourceInfo *getTypeSourceInfo() const {
|
|
|
|
return TInfoAndScope.getPointer();
|
|
|
|
}
|
|
|
|
void setTypeSourceInfo(TypeSourceInfo *tinfo) {
|
|
|
|
TInfoAndScope.setPointer(tinfo);
|
|
|
|
}
|
2010-01-23 11:10:26 +00:00
|
|
|
|
2012-04-14 14:01:31 +00:00
|
|
|
SourceRange getSourceRange() const LLVM_READONLY {
|
2009-06-02 17:58:47 +00:00
|
|
|
// FIXME: Init should never be null.
|
|
|
|
if (!Init)
|
|
|
|
return SourceRange();
|
|
|
|
if (LParenLoc.isInvalid())
|
|
|
|
return Init->getSourceRange();
|
|
|
|
return SourceRange(LParenLoc, Init->getLocEnd());
|
|
|
|
}
|
|
|
|
|
2009-10-14 18:03:49 +00:00
|
|
|
static bool classof(const Stmt *T) {
|
|
|
|
return T->getStmtClass() == CompoundLiteralExprClass;
|
2009-06-02 17:58:47 +00:00
|
|
|
}
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
// Iterators
|
2011-02-20 13:06:31 +00:00
|
|
|
child_range children() { return child_range(&Init, &Init+1); }
|
2009-06-02 17:58:47 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/// 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 {
|
2009-10-14 18:03:49 +00:00
|
|
|
public:
|
2010-09-17 15:54:40 +00:00
|
|
|
typedef clang::CastKind CastKind;
|
2009-10-14 18:03:49 +00:00
|
|
|
|
|
|
|
private:
|
2009-06-02 17:58:47 +00:00
|
|
|
Stmt *Op;
|
2010-05-04 16:12:48 +00:00
|
|
|
|
2011-10-20 21:14:49 +00:00
|
|
|
void CheckCastConsistency() const;
|
2010-05-04 16:12:48 +00:00
|
|
|
|
2010-09-17 15:54:40 +00:00
|
|
|
const CXXBaseSpecifier * const *path_buffer() const {
|
|
|
|
return const_cast<CastExpr*>(this)->path_buffer();
|
|
|
|
}
|
|
|
|
CXXBaseSpecifier **path_buffer();
|
|
|
|
|
2011-05-02 19:39:53 +00:00
|
|
|
void setBasePathSize(unsigned basePathSize) {
|
|
|
|
CastExprBits.BasePathSize = basePathSize;
|
|
|
|
assert(CastExprBits.BasePathSize == basePathSize &&
|
|
|
|
"basePathSize doesn't fit in bits of CastExprBits.BasePathSize!");
|
|
|
|
}
|
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
protected:
|
2011-02-20 13:06:31 +00:00
|
|
|
CastExpr(StmtClass SC, QualType ty, ExprValueKind VK,
|
|
|
|
const CastKind kind, Expr *op, unsigned BasePathSize) :
|
|
|
|
Expr(SC, ty, VK, OK_Ordinary,
|
2009-06-02 17:58:47 +00:00
|
|
|
// 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.
|
2011-02-20 13:06:31 +00:00
|
|
|
ty->isDependentType() || (op && op->isValueDependent()),
|
2012-04-14 14:01:31 +00:00
|
|
|
(ty->isInstantiationDependentType() ||
|
2011-07-17 15:40:56 +00:00
|
|
|
(op && op->isInstantiationDependent())),
|
2011-02-20 13:06:31 +00:00
|
|
|
(ty->containsUnexpandedParameterPack() ||
|
|
|
|
op->containsUnexpandedParameterPack())),
|
|
|
|
Op(op) {
|
|
|
|
assert(kind != CK_Invalid && "creating cast with invalid cast kind");
|
|
|
|
CastExprBits.Kind = kind;
|
2011-05-02 19:39:53 +00:00
|
|
|
setBasePathSize(BasePathSize);
|
2011-10-20 21:14:49 +00:00
|
|
|
#ifndef NDEBUG
|
2011-02-20 13:06:31 +00:00
|
|
|
CheckCastConsistency();
|
2011-10-20 21:14:49 +00:00
|
|
|
#endif
|
2010-09-17 15:54:40 +00:00
|
|
|
}
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
/// \brief Construct an empty cast.
|
2010-09-17 15:54:40 +00:00
|
|
|
CastExpr(StmtClass SC, EmptyShell Empty, unsigned BasePathSize)
|
2011-02-20 13:06:31 +00:00
|
|
|
: Expr(SC, Empty) {
|
2011-05-02 19:39:53 +00:00
|
|
|
setBasePathSize(BasePathSize);
|
2011-02-20 13:06:31 +00:00
|
|
|
}
|
2010-05-04 16:12:48 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
public:
|
2011-02-20 13:06:31 +00:00
|
|
|
CastKind getCastKind() const { return (CastKind) CastExprBits.Kind; }
|
|
|
|
void setCastKind(CastKind K) { CastExprBits.Kind = K; }
|
2009-10-14 18:03:49 +00:00
|
|
|
const char *getCastKindName() const;
|
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
Expr *getSubExpr() { return cast<Expr>(Op); }
|
|
|
|
const Expr *getSubExpr() const { return cast<Expr>(Op); }
|
|
|
|
void setSubExpr(Expr *E) { Op = E; }
|
|
|
|
|
2009-12-15 18:49:47 +00:00
|
|
|
/// \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();
|
|
|
|
}
|
2010-05-04 16:12:48 +00:00
|
|
|
|
2010-09-17 15:54:40 +00:00
|
|
|
typedef CXXBaseSpecifier **path_iterator;
|
|
|
|
typedef const CXXBaseSpecifier * const *path_const_iterator;
|
2011-02-20 13:06:31 +00:00
|
|
|
bool path_empty() const { return CastExprBits.BasePathSize == 0; }
|
|
|
|
unsigned path_size() const { return CastExprBits.BasePathSize; }
|
2010-09-17 15:54:40 +00:00
|
|
|
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(); }
|
|
|
|
|
|
|
|
void setCastPath(const CXXCastPath &Path);
|
2010-05-04 16:12:48 +00:00
|
|
|
|
2009-10-14 18:03:49 +00:00
|
|
|
static bool classof(const Stmt *T) {
|
2010-05-27 15:17:06 +00:00
|
|
|
return T->getStmtClass() >= firstCastExprConstant &&
|
|
|
|
T->getStmtClass() <= lastCastExprConstant;
|
2009-06-02 17:58:47 +00:00
|
|
|
}
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
// Iterators
|
2011-02-20 13:06:31 +00:00
|
|
|
child_range children() { return child_range(&Op, &Op+1); }
|
2009-06-02 17:58:47 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/// 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
|
2010-09-17 15:54:40 +00:00
|
|
|
/// an lvalue or xvalue. For example:
|
2009-06-02 17:58:47 +00:00
|
|
|
///
|
|
|
|
/// @code
|
|
|
|
/// class Base { };
|
|
|
|
/// class Derived : public Base { };
|
2010-09-17 15:54:40 +00:00
|
|
|
/// Derived &&ref();
|
2009-10-14 18:03:49 +00:00
|
|
|
/// void f(Derived d) {
|
2010-09-17 15:54:40 +00:00
|
|
|
/// 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
|
2009-06-02 17:58:47 +00:00
|
|
|
/// }
|
|
|
|
/// @endcode
|
|
|
|
class ImplicitCastExpr : public CastExpr {
|
2010-09-17 15:54:40 +00:00
|
|
|
private:
|
|
|
|
ImplicitCastExpr(QualType ty, CastKind kind, Expr *op,
|
|
|
|
unsigned BasePathLength, ExprValueKind VK)
|
2011-02-20 13:06:31 +00:00
|
|
|
: CastExpr(ImplicitCastExprClass, ty, VK, kind, op, BasePathLength) {
|
2010-09-17 15:54:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// \brief Construct an empty implicit cast.
|
|
|
|
explicit ImplicitCastExpr(EmptyShell Shell, unsigned PathSize)
|
|
|
|
: CastExpr(ImplicitCastExprClass, Shell, PathSize) { }
|
2009-06-02 17:58:47 +00:00
|
|
|
|
|
|
|
public:
|
2010-09-17 15:54:40 +00:00
|
|
|
enum OnStack_t { OnStack };
|
|
|
|
ImplicitCastExpr(OnStack_t _, QualType ty, CastKind kind, Expr *op,
|
|
|
|
ExprValueKind VK)
|
2011-02-20 13:06:31 +00:00
|
|
|
: CastExpr(ImplicitCastExprClass, ty, VK, kind, op, 0) {
|
2010-09-17 15:54:40 +00:00
|
|
|
}
|
2009-06-02 17:58:47 +00:00
|
|
|
|
2010-09-17 15:54:40 +00:00
|
|
|
static ImplicitCastExpr *Create(ASTContext &Context, QualType T,
|
|
|
|
CastKind Kind, Expr *Operand,
|
|
|
|
const CXXCastPath *BasePath,
|
|
|
|
ExprValueKind Cat);
|
|
|
|
|
|
|
|
static ImplicitCastExpr *CreateEmpty(ASTContext &Context, unsigned PathSize);
|
2009-06-02 17:58:47 +00:00
|
|
|
|
2012-04-14 14:01:31 +00:00
|
|
|
SourceRange getSourceRange() const LLVM_READONLY {
|
2009-06-02 17:58:47 +00:00
|
|
|
return getSubExpr()->getSourceRange();
|
|
|
|
}
|
2012-04-14 14:01:31 +00:00
|
|
|
SourceLocation getLocStart() const LLVM_READONLY {
|
|
|
|
return getSubExpr()->getLocStart();
|
|
|
|
}
|
|
|
|
SourceLocation getLocEnd() const LLVM_READONLY {
|
|
|
|
return getSubExpr()->getLocEnd();
|
|
|
|
}
|
2009-06-02 17:58:47 +00:00
|
|
|
|
2009-10-14 18:03:49 +00:00
|
|
|
static bool classof(const Stmt *T) {
|
|
|
|
return T->getStmtClass() == ImplicitCastExprClass;
|
2009-06-02 17:58:47 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2011-07-17 15:40:56 +00:00
|
|
|
inline Expr *Expr::IgnoreImpCasts() {
|
|
|
|
Expr *e = this;
|
|
|
|
while (ImplicitCastExpr *ice = dyn_cast<ImplicitCastExpr>(e))
|
|
|
|
e = ice->getSubExpr();
|
|
|
|
return e;
|
|
|
|
}
|
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
/// ExplicitCastExpr - An explicit cast written in the source
|
2009-10-14 18:03:49 +00:00
|
|
|
/// code.
|
2009-06-02 17:58:47 +00:00
|
|
|
///
|
|
|
|
/// 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
|
2010-09-17 15:54:40 +00:00
|
|
|
/// expression will be an lvalue or xvalue. The reference type, however,
|
|
|
|
/// will not be used as the type of the expression.
|
2009-06-02 17:58:47 +00:00
|
|
|
class ExplicitCastExpr : public CastExpr {
|
2010-01-23 11:10:26 +00:00
|
|
|
/// TInfo - Source type info for the (written) type
|
|
|
|
/// this expression is casting to.
|
|
|
|
TypeSourceInfo *TInfo;
|
2009-06-02 17:58:47 +00:00
|
|
|
|
|
|
|
protected:
|
2011-02-20 13:06:31 +00:00
|
|
|
ExplicitCastExpr(StmtClass SC, QualType exprTy, ExprValueKind VK,
|
|
|
|
CastKind kind, Expr *op, unsigned PathSize,
|
|
|
|
TypeSourceInfo *writtenTy)
|
|
|
|
: CastExpr(SC, exprTy, VK, kind, op, PathSize), TInfo(writtenTy) {}
|
2009-06-02 17:58:47 +00:00
|
|
|
|
|
|
|
/// \brief Construct an empty explicit cast.
|
2010-09-17 15:54:40 +00:00
|
|
|
ExplicitCastExpr(StmtClass SC, EmptyShell Shell, unsigned PathSize)
|
|
|
|
: CastExpr(SC, Shell, PathSize) { }
|
2009-06-02 17:58:47 +00:00
|
|
|
|
|
|
|
public:
|
2010-01-23 11:10:26 +00:00
|
|
|
/// 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; }
|
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
/// getTypeAsWritten - Returns the type that this expression is
|
|
|
|
/// casting to, as written in the source code.
|
2010-01-23 11:10:26 +00:00
|
|
|
QualType getTypeAsWritten() const { return TInfo->getType(); }
|
2009-06-02 17:58:47 +00:00
|
|
|
|
2009-10-14 18:03:49 +00:00
|
|
|
static bool classof(const Stmt *T) {
|
2010-05-27 15:17:06 +00:00
|
|
|
return T->getStmtClass() >= firstExplicitCastExprConstant &&
|
|
|
|
T->getStmtClass() <= lastExplicitCastExprConstant;
|
2009-06-02 17:58:47 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
/// 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 : public ExplicitCastExpr {
|
|
|
|
SourceLocation LPLoc; // the location of the left paren
|
|
|
|
SourceLocation RPLoc; // the location of the right paren
|
2010-09-17 15:54:40 +00:00
|
|
|
|
2011-02-20 13:06:31 +00:00
|
|
|
CStyleCastExpr(QualType exprTy, ExprValueKind vk, CastKind kind, Expr *op,
|
2010-09-17 15:54:40 +00:00
|
|
|
unsigned PathSize, TypeSourceInfo *writtenTy,
|
2010-05-04 16:12:48 +00:00
|
|
|
SourceLocation l, SourceLocation r)
|
2011-02-20 13:06:31 +00:00
|
|
|
: ExplicitCastExpr(CStyleCastExprClass, exprTy, vk, kind, op, PathSize,
|
2010-05-04 16:12:48 +00:00
|
|
|
writtenTy), LPLoc(l), RPLoc(r) {}
|
2009-06-02 17:58:47 +00:00
|
|
|
|
|
|
|
/// \brief Construct an empty C-style explicit cast.
|
2010-09-17 15:54:40 +00:00
|
|
|
explicit CStyleCastExpr(EmptyShell Shell, unsigned PathSize)
|
|
|
|
: ExplicitCastExpr(CStyleCastExprClass, Shell, PathSize) { }
|
|
|
|
|
|
|
|
public:
|
2011-02-20 13:06:31 +00:00
|
|
|
static CStyleCastExpr *Create(ASTContext &Context, QualType T,
|
|
|
|
ExprValueKind VK, CastKind K,
|
2010-09-17 15:54:40 +00:00
|
|
|
Expr *Op, const CXXCastPath *BasePath,
|
|
|
|
TypeSourceInfo *WrittenTy, SourceLocation L,
|
|
|
|
SourceLocation R);
|
|
|
|
|
|
|
|
static CStyleCastExpr *CreateEmpty(ASTContext &Context, unsigned PathSize);
|
2009-06-02 17:58:47 +00:00
|
|
|
|
|
|
|
SourceLocation getLParenLoc() const { return LPLoc; }
|
|
|
|
void setLParenLoc(SourceLocation L) { LPLoc = L; }
|
|
|
|
|
|
|
|
SourceLocation getRParenLoc() const { return RPLoc; }
|
|
|
|
void setRParenLoc(SourceLocation L) { RPLoc = L; }
|
|
|
|
|
2012-04-14 14:01:31 +00:00
|
|
|
SourceRange getSourceRange() const LLVM_READONLY {
|
2009-06-02 17:58:47 +00:00
|
|
|
return SourceRange(LPLoc, getSubExpr()->getSourceRange().getEnd());
|
|
|
|
}
|
2009-10-14 18:03:49 +00:00
|
|
|
static bool classof(const Stmt *T) {
|
|
|
|
return T->getStmtClass() == CStyleCastExprClass;
|
2009-06-02 17:58:47 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
/// \brief A builtin binary operation expression such as "x + y" or "x <= y".
|
|
|
|
///
|
|
|
|
/// This expression node kind describes a builtin binary operation,
|
|
|
|
/// such as "x + y" for integer values "x" and "y". The operands will
|
|
|
|
/// already have been converted to appropriate types (e.g., by
|
|
|
|
/// performing promotions or conversions).
|
|
|
|
///
|
|
|
|
/// In C++, where operators may be overloaded, a different kind of
|
|
|
|
/// expression node (CXXOperatorCallExpr) is used to express the
|
|
|
|
/// invocation of an overloaded operator with operator syntax. Within
|
|
|
|
/// a C++ template, whether BinaryOperator or CXXOperatorCallExpr is
|
|
|
|
/// used to store an expression "x + y" depends on the subexpressions
|
|
|
|
/// for x and y. If neither x or y is type-dependent, and the "+"
|
|
|
|
/// operator resolves to a built-in operation, BinaryOperator will be
|
|
|
|
/// used to express the computation (x and y may still be
|
|
|
|
/// value-dependent). If either x or y is type-dependent, or if the
|
|
|
|
/// "+" resolves to an overloaded operator, CXXOperatorCallExpr will
|
|
|
|
/// be used to express the computation.
|
|
|
|
class BinaryOperator : public Expr {
|
|
|
|
public:
|
2010-09-17 15:54:40 +00:00
|
|
|
typedef BinaryOperatorKind Opcode;
|
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
private:
|
2010-09-17 15:54:40 +00:00
|
|
|
unsigned Opc : 6;
|
2012-12-02 13:20:44 +00:00
|
|
|
|
|
|
|
// Records the FP_CONTRACT pragma status at the point that this binary
|
|
|
|
// operator was parsed. This bit is only meaningful for operations on
|
|
|
|
// floating point types. For all other types it should default to
|
|
|
|
// false.
|
|
|
|
unsigned FPContractable : 1;
|
2010-09-17 15:54:40 +00:00
|
|
|
SourceLocation OpLoc;
|
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
enum { LHS, RHS, END_EXPR };
|
|
|
|
Stmt* SubExprs[END_EXPR];
|
2009-10-14 18:03:49 +00:00
|
|
|
public:
|
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
BinaryOperator(Expr *lhs, Expr *rhs, Opcode opc, QualType ResTy,
|
2011-02-20 13:06:31 +00:00
|
|
|
ExprValueKind VK, ExprObjectKind OK,
|
2012-12-02 13:20:44 +00:00
|
|
|
SourceLocation opLoc, bool fpContractable)
|
2011-02-20 13:06:31 +00:00
|
|
|
: Expr(BinaryOperatorClass, ResTy, VK, OK,
|
2009-06-02 17:58:47 +00:00
|
|
|
lhs->isTypeDependent() || rhs->isTypeDependent(),
|
2011-02-20 13:06:31 +00:00
|
|
|
lhs->isValueDependent() || rhs->isValueDependent(),
|
2011-07-17 15:40:56 +00:00
|
|
|
(lhs->isInstantiationDependent() ||
|
|
|
|
rhs->isInstantiationDependent()),
|
2011-02-20 13:06:31 +00:00
|
|
|
(lhs->containsUnexpandedParameterPack() ||
|
|
|
|
rhs->containsUnexpandedParameterPack())),
|
2012-12-02 13:20:44 +00:00
|
|
|
Opc(opc), FPContractable(fpContractable), OpLoc(opLoc) {
|
2009-06-02 17:58:47 +00:00
|
|
|
SubExprs[LHS] = lhs;
|
|
|
|
SubExprs[RHS] = rhs;
|
2009-10-14 18:03:49 +00:00
|
|
|
assert(!isCompoundAssignmentOp() &&
|
2009-06-02 17:58:47 +00:00
|
|
|
"Use ArithAssignBinaryOperator for compound assignments");
|
|
|
|
}
|
|
|
|
|
|
|
|
/// \brief Construct an empty binary operator.
|
2009-10-14 18:03:49 +00:00
|
|
|
explicit BinaryOperator(EmptyShell Empty)
|
2010-09-17 15:54:40 +00:00
|
|
|
: Expr(BinaryOperatorClass, Empty), Opc(BO_Comma) { }
|
2009-06-02 17:58:47 +00:00
|
|
|
|
2012-04-14 14:01:31 +00:00
|
|
|
SourceLocation getExprLoc() const LLVM_READONLY { return OpLoc; }
|
2009-06-02 17:58:47 +00:00
|
|
|
SourceLocation getOperatorLoc() const { return OpLoc; }
|
|
|
|
void setOperatorLoc(SourceLocation L) { OpLoc = L; }
|
|
|
|
|
2010-09-17 15:54:40 +00:00
|
|
|
Opcode getOpcode() const { return static_cast<Opcode>(Opc); }
|
2009-06-02 17:58:47 +00:00
|
|
|
void setOpcode(Opcode O) { Opc = O; }
|
|
|
|
|
|
|
|
Expr *getLHS() const { return cast<Expr>(SubExprs[LHS]); }
|
|
|
|
void setLHS(Expr *E) { SubExprs[LHS] = E; }
|
|
|
|
Expr *getRHS() const { return cast<Expr>(SubExprs[RHS]); }
|
|
|
|
void setRHS(Expr *E) { SubExprs[RHS] = E; }
|
|
|
|
|
2012-04-14 14:01:31 +00:00
|
|
|
SourceRange getSourceRange() const LLVM_READONLY {
|
2009-06-02 17:58:47 +00:00
|
|
|
return SourceRange(getLHS()->getLocStart(), getRHS()->getLocEnd());
|
|
|
|
}
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
/// getOpcodeStr - Turn an Opcode enum value into the punctuation char it
|
|
|
|
/// corresponds to, e.g. "<<=".
|
2012-12-02 13:20:44 +00:00
|
|
|
static StringRef getOpcodeStr(Opcode Op);
|
2009-06-02 17:58:47 +00:00
|
|
|
|
2012-12-02 13:20:44 +00:00
|
|
|
StringRef getOpcodeStr() const { return getOpcodeStr(getOpcode()); }
|
2010-09-17 15:54:40 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
/// \brief Retrieve the binary opcode that corresponds to the given
|
|
|
|
/// overloaded operator.
|
|
|
|
static Opcode getOverloadedOpcode(OverloadedOperatorKind OO);
|
|
|
|
|
|
|
|
/// \brief Retrieve the overloaded operator kind that corresponds to
|
|
|
|
/// the given binary opcode.
|
|
|
|
static OverloadedOperatorKind getOverloadedOperator(Opcode Opc);
|
|
|
|
|
|
|
|
/// predicates to categorize the respective opcodes.
|
2011-02-20 13:06:31 +00:00
|
|
|
bool isPtrMemOp() const { return Opc == BO_PtrMemD || Opc == BO_PtrMemI; }
|
2010-09-17 15:54:40 +00:00
|
|
|
bool isMultiplicativeOp() const { return Opc >= BO_Mul && Opc <= BO_Rem; }
|
|
|
|
static bool isAdditiveOp(Opcode Opc) { return Opc == BO_Add || Opc==BO_Sub; }
|
|
|
|
bool isAdditiveOp() const { return isAdditiveOp(getOpcode()); }
|
|
|
|
static bool isShiftOp(Opcode Opc) { return Opc == BO_Shl || Opc == BO_Shr; }
|
|
|
|
bool isShiftOp() const { return isShiftOp(getOpcode()); }
|
2009-11-04 15:04:32 +00:00
|
|
|
|
2010-09-17 15:54:40 +00:00
|
|
|
static bool isBitwiseOp(Opcode Opc) { return Opc >= BO_And && Opc <= BO_Or; }
|
|
|
|
bool isBitwiseOp() const { return isBitwiseOp(getOpcode()); }
|
2009-06-02 17:58:47 +00:00
|
|
|
|
2010-09-17 15:54:40 +00:00
|
|
|
static bool isRelationalOp(Opcode Opc) { return Opc >= BO_LT && Opc<=BO_GE; }
|
|
|
|
bool isRelationalOp() const { return isRelationalOp(getOpcode()); }
|
2009-06-02 17:58:47 +00:00
|
|
|
|
2010-09-17 15:54:40 +00:00
|
|
|
static bool isEqualityOp(Opcode Opc) { return Opc == BO_EQ || Opc == BO_NE; }
|
|
|
|
bool isEqualityOp() const { return isEqualityOp(getOpcode()); }
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2010-09-17 15:54:40 +00:00
|
|
|
static bool isComparisonOp(Opcode Opc) { return Opc >= BO_LT && Opc<=BO_NE; }
|
|
|
|
bool isComparisonOp() const { return isComparisonOp(getOpcode()); }
|
2009-11-04 15:04:32 +00:00
|
|
|
|
2010-09-17 15:54:40 +00:00
|
|
|
static bool isLogicalOp(Opcode Opc) { return Opc == BO_LAnd || Opc==BO_LOr; }
|
|
|
|
bool isLogicalOp() const { return isLogicalOp(getOpcode()); }
|
2009-06-02 17:58:47 +00:00
|
|
|
|
2011-02-20 13:06:31 +00:00
|
|
|
static bool isAssignmentOp(Opcode Opc) {
|
|
|
|
return Opc >= BO_Assign && Opc <= BO_OrAssign;
|
|
|
|
}
|
|
|
|
bool isAssignmentOp() const { return isAssignmentOp(getOpcode()); }
|
|
|
|
|
|
|
|
static bool isCompoundAssignmentOp(Opcode Opc) {
|
2010-09-17 15:54:40 +00:00
|
|
|
return Opc > BO_Assign && Opc <= BO_OrAssign;
|
|
|
|
}
|
2011-02-20 13:06:31 +00:00
|
|
|
bool isCompoundAssignmentOp() const {
|
|
|
|
return isCompoundAssignmentOp(getOpcode());
|
|
|
|
}
|
2012-04-14 14:01:31 +00:00
|
|
|
static Opcode getOpForCompoundAssignment(Opcode Opc) {
|
|
|
|
assert(isCompoundAssignmentOp(Opc));
|
|
|
|
if (Opc >= BO_AndAssign)
|
|
|
|
return Opcode(unsigned(Opc) - BO_AndAssign + BO_And);
|
|
|
|
else
|
|
|
|
return Opcode(unsigned(Opc) - BO_MulAssign + BO_Mul);
|
|
|
|
}
|
2011-02-20 13:06:31 +00:00
|
|
|
|
|
|
|
static bool isShiftAssignOp(Opcode Opc) {
|
2010-09-17 15:54:40 +00:00
|
|
|
return Opc == BO_ShlAssign || Opc == BO_ShrAssign;
|
|
|
|
}
|
2011-02-20 13:06:31 +00:00
|
|
|
bool isShiftAssignOp() const {
|
|
|
|
return isShiftAssignOp(getOpcode());
|
|
|
|
}
|
2009-10-14 18:03:49 +00:00
|
|
|
|
|
|
|
static bool classof(const Stmt *S) {
|
2010-05-27 15:17:06 +00:00
|
|
|
return S->getStmtClass() >= firstBinaryOperatorConstant &&
|
|
|
|
S->getStmtClass() <= lastBinaryOperatorConstant;
|
2009-06-02 17:58:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Iterators
|
2011-02-20 13:06:31 +00:00
|
|
|
child_range children() {
|
|
|
|
return child_range(&SubExprs[0], &SubExprs[0]+END_EXPR);
|
|
|
|
}
|
2009-06-02 17:58:47 +00:00
|
|
|
|
2012-12-02 13:20:44 +00:00
|
|
|
// Set the FP contractability status of this operator. Only meaningful for
|
|
|
|
// operations on floating point types.
|
|
|
|
void setFPContractable(bool FPC) { FPContractable = FPC; }
|
|
|
|
|
|
|
|
// Get the FP contractability status of this operator. Only meaningful for
|
|
|
|
// operations on floating point types.
|
|
|
|
bool isFPContractable() const { return FPContractable; }
|
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
protected:
|
|
|
|
BinaryOperator(Expr *lhs, Expr *rhs, Opcode opc, QualType ResTy,
|
2011-02-20 13:06:31 +00:00
|
|
|
ExprValueKind VK, ExprObjectKind OK,
|
2012-12-02 13:20:44 +00:00
|
|
|
SourceLocation opLoc, bool fpContractable, bool dead2)
|
2011-02-20 13:06:31 +00:00
|
|
|
: Expr(CompoundAssignOperatorClass, ResTy, VK, OK,
|
2010-01-01 10:34:51 +00:00
|
|
|
lhs->isTypeDependent() || rhs->isTypeDependent(),
|
2011-02-20 13:06:31 +00:00
|
|
|
lhs->isValueDependent() || rhs->isValueDependent(),
|
2011-07-17 15:40:56 +00:00
|
|
|
(lhs->isInstantiationDependent() ||
|
|
|
|
rhs->isInstantiationDependent()),
|
2011-02-20 13:06:31 +00:00
|
|
|
(lhs->containsUnexpandedParameterPack() ||
|
|
|
|
rhs->containsUnexpandedParameterPack())),
|
2012-12-02 13:20:44 +00:00
|
|
|
Opc(opc), FPContractable(fpContractable), OpLoc(opLoc) {
|
2009-06-02 17:58:47 +00:00
|
|
|
SubExprs[LHS] = lhs;
|
|
|
|
SubExprs[RHS] = rhs;
|
|
|
|
}
|
|
|
|
|
2009-10-14 18:03:49 +00:00
|
|
|
BinaryOperator(StmtClass SC, EmptyShell Empty)
|
2010-09-17 15:54:40 +00:00
|
|
|
: Expr(SC, Empty), Opc(BO_MulAssign) { }
|
2009-06-02 17:58:47 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/// CompoundAssignOperator - For compound assignments (e.g. +=), we keep
|
|
|
|
/// track of the type the operation is performed in. Due to the semantics of
|
2011-10-20 21:14:49 +00:00
|
|
|
/// these operators, the operands are promoted, the arithmetic performed, an
|
2009-06-02 17:58:47 +00:00
|
|
|
/// implicit conversion back to the result type done, then the assignment takes
|
|
|
|
/// place. This captures the intermediate type which the computation is done
|
|
|
|
/// in.
|
|
|
|
class CompoundAssignOperator : public BinaryOperator {
|
|
|
|
QualType ComputationLHSType;
|
|
|
|
QualType ComputationResultType;
|
|
|
|
public:
|
2011-02-20 13:06:31 +00:00
|
|
|
CompoundAssignOperator(Expr *lhs, Expr *rhs, Opcode opc, QualType ResType,
|
|
|
|
ExprValueKind VK, ExprObjectKind OK,
|
|
|
|
QualType CompLHSType, QualType CompResultType,
|
2012-12-02 13:20:44 +00:00
|
|
|
SourceLocation OpLoc, bool fpContractable)
|
|
|
|
: BinaryOperator(lhs, rhs, opc, ResType, VK, OK, OpLoc, fpContractable,
|
|
|
|
true),
|
2009-06-02 17:58:47 +00:00
|
|
|
ComputationLHSType(CompLHSType),
|
|
|
|
ComputationResultType(CompResultType) {
|
2009-10-14 18:03:49 +00:00
|
|
|
assert(isCompoundAssignmentOp() &&
|
2009-06-02 17:58:47 +00:00
|
|
|
"Only should be used for compound assignments");
|
|
|
|
}
|
|
|
|
|
|
|
|
/// \brief Build an empty compound assignment operator expression.
|
|
|
|
explicit CompoundAssignOperator(EmptyShell Empty)
|
|
|
|
: BinaryOperator(CompoundAssignOperatorClass, Empty) { }
|
|
|
|
|
|
|
|
// The two computation types are the type the LHS is converted
|
|
|
|
// to for the computation and the type of the result; the two are
|
|
|
|
// distinct in a few cases (specifically, int+=ptr and ptr-=ptr).
|
|
|
|
QualType getComputationLHSType() const { return ComputationLHSType; }
|
|
|
|
void setComputationLHSType(QualType T) { ComputationLHSType = T; }
|
|
|
|
|
|
|
|
QualType getComputationResultType() const { return ComputationResultType; }
|
|
|
|
void setComputationResultType(QualType T) { ComputationResultType = T; }
|
|
|
|
|
2009-10-14 18:03:49 +00:00
|
|
|
static bool classof(const Stmt *S) {
|
|
|
|
return S->getStmtClass() == CompoundAssignOperatorClass;
|
2009-06-02 17:58:47 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2011-02-20 13:06:31 +00:00
|
|
|
/// AbstractConditionalOperator - An abstract base class for
|
|
|
|
/// ConditionalOperator and BinaryConditionalOperator.
|
|
|
|
class AbstractConditionalOperator : public Expr {
|
|
|
|
SourceLocation QuestionLoc, ColonLoc;
|
|
|
|
friend class ASTStmtReader;
|
|
|
|
|
|
|
|
protected:
|
|
|
|
AbstractConditionalOperator(StmtClass SC, QualType T,
|
|
|
|
ExprValueKind VK, ExprObjectKind OK,
|
2011-07-17 15:40:56 +00:00
|
|
|
bool TD, bool VD, bool ID,
|
2011-02-20 13:06:31 +00:00
|
|
|
bool ContainsUnexpandedParameterPack,
|
|
|
|
SourceLocation qloc,
|
|
|
|
SourceLocation cloc)
|
2011-07-17 15:40:56 +00:00
|
|
|
: Expr(SC, T, VK, OK, TD, VD, ID, ContainsUnexpandedParameterPack),
|
2011-02-20 13:06:31 +00:00
|
|
|
QuestionLoc(qloc), ColonLoc(cloc) {}
|
|
|
|
|
|
|
|
AbstractConditionalOperator(StmtClass SC, EmptyShell Empty)
|
|
|
|
: Expr(SC, Empty) { }
|
|
|
|
|
|
|
|
public:
|
|
|
|
// getCond - Return the expression representing the condition for
|
|
|
|
// the ?: operator.
|
|
|
|
Expr *getCond() const;
|
|
|
|
|
|
|
|
// getTrueExpr - Return the subexpression representing the value of
|
|
|
|
// the expression if the condition evaluates to true.
|
|
|
|
Expr *getTrueExpr() const;
|
|
|
|
|
|
|
|
// getFalseExpr - Return the subexpression representing the value of
|
|
|
|
// the expression if the condition evaluates to false. This is
|
|
|
|
// the same as getRHS.
|
|
|
|
Expr *getFalseExpr() const;
|
|
|
|
|
|
|
|
SourceLocation getQuestionLoc() const { return QuestionLoc; }
|
|
|
|
SourceLocation getColonLoc() const { return ColonLoc; }
|
|
|
|
|
|
|
|
static bool classof(const Stmt *T) {
|
|
|
|
return T->getStmtClass() == ConditionalOperatorClass ||
|
|
|
|
T->getStmtClass() == BinaryConditionalOperatorClass;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
/// ConditionalOperator - The ?: ternary operator. The GNU "missing
|
|
|
|
/// middle" extension is a BinaryConditionalOperator.
|
|
|
|
class ConditionalOperator : public AbstractConditionalOperator {
|
2009-06-02 17:58:47 +00:00
|
|
|
enum { COND, LHS, RHS, END_EXPR };
|
|
|
|
Stmt* SubExprs[END_EXPR]; // Left/Middle/Right hand sides.
|
2011-02-20 13:06:31 +00:00
|
|
|
|
|
|
|
friend class ASTStmtReader;
|
2009-06-02 17:58:47 +00:00
|
|
|
public:
|
2009-10-14 18:03:49 +00:00
|
|
|
ConditionalOperator(Expr *cond, SourceLocation QLoc, Expr *lhs,
|
2011-02-20 13:06:31 +00:00
|
|
|
SourceLocation CLoc, Expr *rhs,
|
|
|
|
QualType t, ExprValueKind VK, ExprObjectKind OK)
|
|
|
|
: AbstractConditionalOperator(ConditionalOperatorClass, t, VK, OK,
|
2009-06-02 17:58:47 +00:00
|
|
|
// FIXME: the type of the conditional operator doesn't
|
|
|
|
// depend on the type of the conditional, but the standard
|
|
|
|
// seems to imply that it could. File a bug!
|
2011-02-20 13:06:31 +00:00
|
|
|
(lhs->isTypeDependent() || rhs->isTypeDependent()),
|
|
|
|
(cond->isValueDependent() || lhs->isValueDependent() ||
|
|
|
|
rhs->isValueDependent()),
|
2011-07-17 15:40:56 +00:00
|
|
|
(cond->isInstantiationDependent() ||
|
|
|
|
lhs->isInstantiationDependent() ||
|
|
|
|
rhs->isInstantiationDependent()),
|
2011-02-20 13:06:31 +00:00
|
|
|
(cond->containsUnexpandedParameterPack() ||
|
|
|
|
lhs->containsUnexpandedParameterPack() ||
|
|
|
|
rhs->containsUnexpandedParameterPack()),
|
|
|
|
QLoc, CLoc) {
|
2009-06-02 17:58:47 +00:00
|
|
|
SubExprs[COND] = cond;
|
|
|
|
SubExprs[LHS] = lhs;
|
|
|
|
SubExprs[RHS] = rhs;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// \brief Build an empty conditional operator.
|
|
|
|
explicit ConditionalOperator(EmptyShell Empty)
|
2011-02-20 13:06:31 +00:00
|
|
|
: AbstractConditionalOperator(ConditionalOperatorClass, Empty) { }
|
2009-06-02 17:58:47 +00:00
|
|
|
|
|
|
|
// getCond - Return the expression representing the condition for
|
2011-02-20 13:06:31 +00:00
|
|
|
// the ?: operator.
|
2009-06-02 17:58:47 +00:00
|
|
|
Expr *getCond() const { return cast<Expr>(SubExprs[COND]); }
|
|
|
|
|
2011-02-20 13:06:31 +00:00
|
|
|
// getTrueExpr - Return the subexpression representing the value of
|
|
|
|
// the expression if the condition evaluates to true.
|
|
|
|
Expr *getTrueExpr() const { return cast<Expr>(SubExprs[LHS]); }
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2011-02-20 13:06:31 +00:00
|
|
|
// getFalseExpr - Return the subexpression representing the value of
|
|
|
|
// the expression if the condition evaluates to false. This is
|
|
|
|
// the same as getRHS.
|
2009-06-02 17:58:47 +00:00
|
|
|
Expr *getFalseExpr() const { return cast<Expr>(SubExprs[RHS]); }
|
2012-04-14 14:01:31 +00:00
|
|
|
|
2011-02-20 13:06:31 +00:00
|
|
|
Expr *getLHS() const { return cast<Expr>(SubExprs[LHS]); }
|
2009-06-02 17:58:47 +00:00
|
|
|
Expr *getRHS() const { return cast<Expr>(SubExprs[RHS]); }
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2012-04-14 14:01:31 +00:00
|
|
|
SourceRange getSourceRange() const LLVM_READONLY {
|
2009-06-02 17:58:47 +00:00
|
|
|
return SourceRange(getCond()->getLocStart(), getRHS()->getLocEnd());
|
|
|
|
}
|
2009-10-14 18:03:49 +00:00
|
|
|
static bool classof(const Stmt *T) {
|
|
|
|
return T->getStmtClass() == ConditionalOperatorClass;
|
2009-06-02 17:58:47 +00:00
|
|
|
}
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
// Iterators
|
2011-02-20 13:06:31 +00:00
|
|
|
child_range children() {
|
|
|
|
return child_range(&SubExprs[0], &SubExprs[0]+END_EXPR);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
/// BinaryConditionalOperator - The GNU extension to the conditional
|
|
|
|
/// operator which allows the middle operand to be omitted.
|
|
|
|
///
|
|
|
|
/// This is a different expression kind on the assumption that almost
|
|
|
|
/// every client ends up needing to know that these are different.
|
|
|
|
class BinaryConditionalOperator : public AbstractConditionalOperator {
|
|
|
|
enum { COMMON, COND, LHS, RHS, NUM_SUBEXPRS };
|
|
|
|
|
|
|
|
/// - the common condition/left-hand-side expression, which will be
|
|
|
|
/// evaluated as the opaque value
|
|
|
|
/// - the condition, expressed in terms of the opaque value
|
|
|
|
/// - the left-hand-side, expressed in terms of the opaque value
|
|
|
|
/// - the right-hand-side
|
|
|
|
Stmt *SubExprs[NUM_SUBEXPRS];
|
|
|
|
OpaqueValueExpr *OpaqueValue;
|
|
|
|
|
|
|
|
friend class ASTStmtReader;
|
|
|
|
public:
|
|
|
|
BinaryConditionalOperator(Expr *common, OpaqueValueExpr *opaqueValue,
|
|
|
|
Expr *cond, Expr *lhs, Expr *rhs,
|
|
|
|
SourceLocation qloc, SourceLocation cloc,
|
|
|
|
QualType t, ExprValueKind VK, ExprObjectKind OK)
|
|
|
|
: AbstractConditionalOperator(BinaryConditionalOperatorClass, t, VK, OK,
|
|
|
|
(common->isTypeDependent() || rhs->isTypeDependent()),
|
|
|
|
(common->isValueDependent() || rhs->isValueDependent()),
|
2011-07-17 15:40:56 +00:00
|
|
|
(common->isInstantiationDependent() ||
|
|
|
|
rhs->isInstantiationDependent()),
|
2011-02-20 13:06:31 +00:00
|
|
|
(common->containsUnexpandedParameterPack() ||
|
|
|
|
rhs->containsUnexpandedParameterPack()),
|
|
|
|
qloc, cloc),
|
|
|
|
OpaqueValue(opaqueValue) {
|
|
|
|
SubExprs[COMMON] = common;
|
|
|
|
SubExprs[COND] = cond;
|
|
|
|
SubExprs[LHS] = lhs;
|
|
|
|
SubExprs[RHS] = rhs;
|
2012-04-14 14:01:31 +00:00
|
|
|
assert(OpaqueValue->getSourceExpr() == common && "Wrong opaque value");
|
2011-02-20 13:06:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// \brief Build an empty conditional operator.
|
|
|
|
explicit BinaryConditionalOperator(EmptyShell Empty)
|
|
|
|
: AbstractConditionalOperator(BinaryConditionalOperatorClass, Empty) { }
|
|
|
|
|
|
|
|
/// \brief getCommon - Return the common expression, written to the
|
|
|
|
/// left of the condition. The opaque value will be bound to the
|
|
|
|
/// result of this expression.
|
|
|
|
Expr *getCommon() const { return cast<Expr>(SubExprs[COMMON]); }
|
|
|
|
|
|
|
|
/// \brief getOpaqueValue - Return the opaque value placeholder.
|
|
|
|
OpaqueValueExpr *getOpaqueValue() const { return OpaqueValue; }
|
|
|
|
|
|
|
|
/// \brief getCond - Return the condition expression; this is defined
|
|
|
|
/// in terms of the opaque value.
|
|
|
|
Expr *getCond() const { return cast<Expr>(SubExprs[COND]); }
|
|
|
|
|
|
|
|
/// \brief getTrueExpr - Return the subexpression which will be
|
|
|
|
/// evaluated if the condition evaluates to true; this is defined
|
|
|
|
/// in terms of the opaque value.
|
|
|
|
Expr *getTrueExpr() const {
|
|
|
|
return cast<Expr>(SubExprs[LHS]);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// \brief getFalseExpr - Return the subexpression which will be
|
|
|
|
/// evaluated if the condnition evaluates to false; this is
|
|
|
|
/// defined in terms of the opaque value.
|
|
|
|
Expr *getFalseExpr() const {
|
|
|
|
return cast<Expr>(SubExprs[RHS]);
|
|
|
|
}
|
2012-04-14 14:01:31 +00:00
|
|
|
|
|
|
|
SourceRange getSourceRange() const LLVM_READONLY {
|
2011-02-20 13:06:31 +00:00
|
|
|
return SourceRange(getCommon()->getLocStart(), getFalseExpr()->getLocEnd());
|
|
|
|
}
|
|
|
|
static bool classof(const Stmt *T) {
|
|
|
|
return T->getStmtClass() == BinaryConditionalOperatorClass;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Iterators
|
|
|
|
child_range children() {
|
|
|
|
return child_range(SubExprs, SubExprs + NUM_SUBEXPRS);
|
|
|
|
}
|
2009-06-02 17:58:47 +00:00
|
|
|
};
|
|
|
|
|
2011-02-20 13:06:31 +00:00
|
|
|
inline Expr *AbstractConditionalOperator::getCond() const {
|
|
|
|
if (const ConditionalOperator *co = dyn_cast<ConditionalOperator>(this))
|
|
|
|
return co->getCond();
|
|
|
|
return cast<BinaryConditionalOperator>(this)->getCond();
|
|
|
|
}
|
|
|
|
|
|
|
|
inline Expr *AbstractConditionalOperator::getTrueExpr() const {
|
|
|
|
if (const ConditionalOperator *co = dyn_cast<ConditionalOperator>(this))
|
|
|
|
return co->getTrueExpr();
|
|
|
|
return cast<BinaryConditionalOperator>(this)->getTrueExpr();
|
|
|
|
}
|
|
|
|
|
|
|
|
inline Expr *AbstractConditionalOperator::getFalseExpr() const {
|
|
|
|
if (const ConditionalOperator *co = dyn_cast<ConditionalOperator>(this))
|
|
|
|
return co->getFalseExpr();
|
|
|
|
return cast<BinaryConditionalOperator>(this)->getFalseExpr();
|
|
|
|
}
|
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
/// AddrLabelExpr - The GNU address of label extension, representing &&label.
|
|
|
|
class AddrLabelExpr : public Expr {
|
|
|
|
SourceLocation AmpAmpLoc, LabelLoc;
|
2011-02-20 13:06:31 +00:00
|
|
|
LabelDecl *Label;
|
2009-06-02 17:58:47 +00:00
|
|
|
public:
|
2011-02-20 13:06:31 +00:00
|
|
|
AddrLabelExpr(SourceLocation AALoc, SourceLocation LLoc, LabelDecl *L,
|
2009-06-02 17:58:47 +00:00
|
|
|
QualType t)
|
2011-07-17 15:40:56 +00:00
|
|
|
: Expr(AddrLabelExprClass, t, VK_RValue, OK_Ordinary, false, false, false,
|
|
|
|
false),
|
2010-01-01 10:34:51 +00:00
|
|
|
AmpAmpLoc(AALoc), LabelLoc(LLoc), Label(L) {}
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
/// \brief Build an empty address of a label expression.
|
2009-10-14 18:03:49 +00:00
|
|
|
explicit AddrLabelExpr(EmptyShell Empty)
|
2009-06-02 17:58:47 +00:00
|
|
|
: Expr(AddrLabelExprClass, Empty) { }
|
|
|
|
|
|
|
|
SourceLocation getAmpAmpLoc() const { return AmpAmpLoc; }
|
|
|
|
void setAmpAmpLoc(SourceLocation L) { AmpAmpLoc = L; }
|
|
|
|
SourceLocation getLabelLoc() const { return LabelLoc; }
|
|
|
|
void setLabelLoc(SourceLocation L) { LabelLoc = L; }
|
|
|
|
|
2012-04-14 14:01:31 +00:00
|
|
|
SourceRange getSourceRange() const LLVM_READONLY {
|
2009-06-02 17:58:47 +00:00
|
|
|
return SourceRange(AmpAmpLoc, LabelLoc);
|
|
|
|
}
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2011-02-20 13:06:31 +00:00
|
|
|
LabelDecl *getLabel() const { return Label; }
|
|
|
|
void setLabel(LabelDecl *L) { Label = L; }
|
2009-06-02 17:58:47 +00:00
|
|
|
|
|
|
|
static bool classof(const Stmt *T) {
|
2009-10-14 18:03:49 +00:00
|
|
|
return T->getStmtClass() == AddrLabelExprClass;
|
2009-06-02 17:58:47 +00:00
|
|
|
}
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
// Iterators
|
2011-02-20 13:06:31 +00:00
|
|
|
child_range children() { return child_range(); }
|
2009-06-02 17:58:47 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/// StmtExpr - This is the GNU Statement Expression extension: ({int X=4; X;}).
|
|
|
|
/// The StmtExpr contains a single CompoundStmt node, which it evaluates and
|
|
|
|
/// takes the value of the last subexpression.
|
2011-02-20 13:06:31 +00:00
|
|
|
///
|
|
|
|
/// A StmtExpr is always an r-value; values "returned" out of a
|
|
|
|
/// StmtExpr will be copied.
|
2009-06-02 17:58:47 +00:00
|
|
|
class StmtExpr : public Expr {
|
|
|
|
Stmt *SubStmt;
|
|
|
|
SourceLocation LParenLoc, RParenLoc;
|
|
|
|
public:
|
2010-01-01 10:34:51 +00:00
|
|
|
// FIXME: Does type-dependence need to be computed differently?
|
2011-07-17 15:40:56 +00:00
|
|
|
// FIXME: Do we need to compute instantiation instantiation-dependence for
|
|
|
|
// statements? (ugh!)
|
2009-06-02 17:58:47 +00:00
|
|
|
StmtExpr(CompoundStmt *substmt, QualType T,
|
|
|
|
SourceLocation lp, SourceLocation rp) :
|
2011-02-20 13:06:31 +00:00
|
|
|
Expr(StmtExprClass, T, VK_RValue, OK_Ordinary,
|
2011-07-17 15:40:56 +00:00
|
|
|
T->isDependentType(), false, false, false),
|
2010-01-01 10:34:51 +00:00
|
|
|
SubStmt(substmt), LParenLoc(lp), RParenLoc(rp) { }
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
/// \brief Build an empty statement expression.
|
|
|
|
explicit StmtExpr(EmptyShell Empty) : Expr(StmtExprClass, Empty) { }
|
|
|
|
|
|
|
|
CompoundStmt *getSubStmt() { return cast<CompoundStmt>(SubStmt); }
|
|
|
|
const CompoundStmt *getSubStmt() const { return cast<CompoundStmt>(SubStmt); }
|
|
|
|
void setSubStmt(CompoundStmt *S) { SubStmt = S; }
|
|
|
|
|
2012-04-14 14:01:31 +00:00
|
|
|
SourceRange getSourceRange() const LLVM_READONLY {
|
2009-06-02 17:58:47 +00:00
|
|
|
return SourceRange(LParenLoc, RParenLoc);
|
|
|
|
}
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
SourceLocation getLParenLoc() const { return LParenLoc; }
|
|
|
|
void setLParenLoc(SourceLocation L) { LParenLoc = L; }
|
|
|
|
SourceLocation getRParenLoc() const { return RParenLoc; }
|
|
|
|
void setRParenLoc(SourceLocation L) { RParenLoc = L; }
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
static bool classof(const Stmt *T) {
|
2009-10-14 18:03:49 +00:00
|
|
|
return T->getStmtClass() == StmtExprClass;
|
2009-06-02 17:58:47 +00:00
|
|
|
}
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
// Iterators
|
2011-02-20 13:06:31 +00:00
|
|
|
child_range children() { return child_range(&SubStmt, &SubStmt+1); }
|
2009-06-02 17:58:47 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/// ShuffleVectorExpr - clang-specific builtin-in function
|
|
|
|
/// __builtin_shufflevector.
|
|
|
|
/// This AST node represents a operator that does a constant
|
|
|
|
/// shuffle, similar to LLVM's shufflevector instruction. It takes
|
|
|
|
/// two vectors and a variable number of constant indices,
|
|
|
|
/// and returns the appropriately shuffled vector.
|
|
|
|
class ShuffleVectorExpr : public Expr {
|
|
|
|
SourceLocation BuiltinLoc, RParenLoc;
|
|
|
|
|
|
|
|
// SubExprs - the list of values passed to the __builtin_shufflevector
|
|
|
|
// function. The first two are vectors, and the rest are constant
|
|
|
|
// indices. The number of values in this list is always
|
|
|
|
// 2+the number of indices in the vector type.
|
|
|
|
Stmt **SubExprs;
|
|
|
|
unsigned NumExprs;
|
|
|
|
|
|
|
|
public:
|
2012-12-02 13:20:44 +00:00
|
|
|
ShuffleVectorExpr(ASTContext &C, ArrayRef<Expr*> args, QualType Type,
|
|
|
|
SourceLocation BLoc, SourceLocation RP);
|
2009-06-02 17:58:47 +00:00
|
|
|
|
|
|
|
/// \brief Build an empty vector-shuffle expression.
|
2009-10-14 18:03:49 +00:00
|
|
|
explicit ShuffleVectorExpr(EmptyShell Empty)
|
2009-06-02 17:58:47 +00:00
|
|
|
: Expr(ShuffleVectorExprClass, Empty), SubExprs(0) { }
|
|
|
|
|
|
|
|
SourceLocation getBuiltinLoc() const { return BuiltinLoc; }
|
|
|
|
void setBuiltinLoc(SourceLocation L) { BuiltinLoc = L; }
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
SourceLocation getRParenLoc() const { return RParenLoc; }
|
|
|
|
void setRParenLoc(SourceLocation L) { RParenLoc = L; }
|
|
|
|
|
2012-04-14 14:01:31 +00:00
|
|
|
SourceRange getSourceRange() const LLVM_READONLY {
|
2009-06-02 17:58:47 +00:00
|
|
|
return SourceRange(BuiltinLoc, RParenLoc);
|
|
|
|
}
|
|
|
|
static bool classof(const Stmt *T) {
|
2009-10-14 18:03:49 +00:00
|
|
|
return T->getStmtClass() == ShuffleVectorExprClass;
|
2009-06-02 17:58:47 +00:00
|
|
|
}
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
/// getNumSubExprs - Return the size of the SubExprs array. This includes the
|
|
|
|
/// constant expression, the actual arguments passed in, and the function
|
|
|
|
/// pointers.
|
|
|
|
unsigned getNumSubExprs() const { return NumExprs; }
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2011-02-20 13:06:31 +00:00
|
|
|
/// \brief Retrieve the array of expressions.
|
|
|
|
Expr **getSubExprs() { return reinterpret_cast<Expr **>(SubExprs); }
|
2012-04-14 14:01:31 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
/// getExpr - Return the Expr at the specified index.
|
|
|
|
Expr *getExpr(unsigned Index) {
|
|
|
|
assert((Index < NumExprs) && "Arg access out of range!");
|
|
|
|
return cast<Expr>(SubExprs[Index]);
|
|
|
|
}
|
|
|
|
const Expr *getExpr(unsigned Index) const {
|
|
|
|
assert((Index < NumExprs) && "Arg access out of range!");
|
|
|
|
return cast<Expr>(SubExprs[Index]);
|
|
|
|
}
|
|
|
|
|
2009-10-14 18:03:49 +00:00
|
|
|
void setExprs(ASTContext &C, Expr ** Exprs, unsigned NumExprs);
|
2009-06-02 17:58:47 +00:00
|
|
|
|
2012-12-02 13:20:44 +00:00
|
|
|
unsigned getShuffleMaskIdx(ASTContext &Ctx, unsigned N) const {
|
2009-06-02 17:58:47 +00:00
|
|
|
assert((N < NumExprs - 2) && "Shuffle idx out of range!");
|
2011-10-20 21:14:49 +00:00
|
|
|
return getExpr(N+2)->EvaluateKnownConstInt(Ctx).getZExtValue();
|
2009-06-02 17:58:47 +00:00
|
|
|
}
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
// Iterators
|
2011-02-20 13:06:31 +00:00
|
|
|
child_range children() {
|
|
|
|
return child_range(&SubExprs[0], &SubExprs[0]+NumExprs);
|
|
|
|
}
|
2009-06-02 17:58:47 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/// ChooseExpr - GNU builtin-in function __builtin_choose_expr.
|
2009-10-14 18:03:49 +00:00
|
|
|
/// This AST node is similar to the conditional operator (?:) in C, with
|
2009-06-02 17:58:47 +00:00
|
|
|
/// the following exceptions:
|
|
|
|
/// - the test expression must be a integer constant expression.
|
|
|
|
/// - the expression returned acts like the chosen subexpression in every
|
|
|
|
/// visible way: the type is the same as that of the chosen subexpression,
|
|
|
|
/// and all predicates (whether it's an l-value, whether it's an integer
|
|
|
|
/// constant expression, etc.) return the same result as for the chosen
|
|
|
|
/// sub-expression.
|
|
|
|
class ChooseExpr : public Expr {
|
|
|
|
enum { COND, LHS, RHS, END_EXPR };
|
|
|
|
Stmt* SubExprs[END_EXPR]; // Left/Middle/Right hand sides.
|
|
|
|
SourceLocation BuiltinLoc, RParenLoc;
|
|
|
|
public:
|
2011-02-20 13:06:31 +00:00
|
|
|
ChooseExpr(SourceLocation BLoc, Expr *cond, Expr *lhs, Expr *rhs,
|
|
|
|
QualType t, ExprValueKind VK, ExprObjectKind OK,
|
2009-10-14 18:03:49 +00:00
|
|
|
SourceLocation RP, bool TypeDependent, bool ValueDependent)
|
2011-02-20 13:06:31 +00:00
|
|
|
: Expr(ChooseExprClass, t, VK, OK, TypeDependent, ValueDependent,
|
2011-07-17 15:40:56 +00:00
|
|
|
(cond->isInstantiationDependent() ||
|
|
|
|
lhs->isInstantiationDependent() ||
|
|
|
|
rhs->isInstantiationDependent()),
|
2011-02-20 13:06:31 +00:00
|
|
|
(cond->containsUnexpandedParameterPack() ||
|
|
|
|
lhs->containsUnexpandedParameterPack() ||
|
|
|
|
rhs->containsUnexpandedParameterPack())),
|
2009-06-02 17:58:47 +00:00
|
|
|
BuiltinLoc(BLoc), RParenLoc(RP) {
|
|
|
|
SubExprs[COND] = cond;
|
|
|
|
SubExprs[LHS] = lhs;
|
|
|
|
SubExprs[RHS] = rhs;
|
2009-10-14 18:03:49 +00:00
|
|
|
}
|
2009-06-02 17:58:47 +00:00
|
|
|
|
|
|
|
/// \brief Build an empty __builtin_choose_expr.
|
|
|
|
explicit ChooseExpr(EmptyShell Empty) : Expr(ChooseExprClass, Empty) { }
|
|
|
|
|
|
|
|
/// isConditionTrue - Return whether the condition is true (i.e. not
|
|
|
|
/// equal to zero).
|
2011-02-20 13:06:31 +00:00
|
|
|
bool isConditionTrue(const ASTContext &C) const;
|
2009-06-02 17:58:47 +00:00
|
|
|
|
|
|
|
/// getChosenSubExpr - Return the subexpression chosen according to the
|
|
|
|
/// condition.
|
2011-02-20 13:06:31 +00:00
|
|
|
Expr *getChosenSubExpr(const ASTContext &C) const {
|
2009-06-02 17:58:47 +00:00
|
|
|
return isConditionTrue(C) ? getLHS() : getRHS();
|
|
|
|
}
|
|
|
|
|
|
|
|
Expr *getCond() const { return cast<Expr>(SubExprs[COND]); }
|
|
|
|
void setCond(Expr *E) { SubExprs[COND] = E; }
|
|
|
|
Expr *getLHS() const { return cast<Expr>(SubExprs[LHS]); }
|
|
|
|
void setLHS(Expr *E) { SubExprs[LHS] = E; }
|
|
|
|
Expr *getRHS() const { return cast<Expr>(SubExprs[RHS]); }
|
|
|
|
void setRHS(Expr *E) { SubExprs[RHS] = E; }
|
|
|
|
|
|
|
|
SourceLocation getBuiltinLoc() const { return BuiltinLoc; }
|
|
|
|
void setBuiltinLoc(SourceLocation L) { BuiltinLoc = L; }
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
SourceLocation getRParenLoc() const { return RParenLoc; }
|
|
|
|
void setRParenLoc(SourceLocation L) { RParenLoc = L; }
|
|
|
|
|
2012-04-14 14:01:31 +00:00
|
|
|
SourceRange getSourceRange() const LLVM_READONLY {
|
2009-06-02 17:58:47 +00:00
|
|
|
return SourceRange(BuiltinLoc, RParenLoc);
|
|
|
|
}
|
|
|
|
static bool classof(const Stmt *T) {
|
2009-10-14 18:03:49 +00:00
|
|
|
return T->getStmtClass() == ChooseExprClass;
|
2009-06-02 17:58:47 +00:00
|
|
|
}
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
// Iterators
|
2011-02-20 13:06:31 +00:00
|
|
|
child_range children() {
|
|
|
|
return child_range(&SubExprs[0], &SubExprs[0]+END_EXPR);
|
|
|
|
}
|
2009-06-02 17:58:47 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/// GNUNullExpr - Implements the GNU __null extension, which is a name
|
|
|
|
/// for a null pointer constant that has integral type (e.g., int or
|
|
|
|
/// long) and is the same size and alignment as a pointer. The __null
|
|
|
|
/// extension is typically only used by system headers, which define
|
|
|
|
/// NULL as __null in C++ rather than using 0 (which is an integer
|
|
|
|
/// that may not match the size of a pointer).
|
|
|
|
class GNUNullExpr : public Expr {
|
|
|
|
/// TokenLoc - The location of the __null keyword.
|
|
|
|
SourceLocation TokenLoc;
|
|
|
|
|
|
|
|
public:
|
2009-10-14 18:03:49 +00:00
|
|
|
GNUNullExpr(QualType Ty, SourceLocation Loc)
|
2011-07-17 15:40:56 +00:00
|
|
|
: Expr(GNUNullExprClass, Ty, VK_RValue, OK_Ordinary, false, false, false,
|
|
|
|
false),
|
2011-02-20 13:06:31 +00:00
|
|
|
TokenLoc(Loc) { }
|
2009-06-02 17:58:47 +00:00
|
|
|
|
|
|
|
/// \brief Build an empty GNU __null expression.
|
|
|
|
explicit GNUNullExpr(EmptyShell Empty) : Expr(GNUNullExprClass, Empty) { }
|
|
|
|
|
|
|
|
/// getTokenLocation - The location of the __null token.
|
|
|
|
SourceLocation getTokenLocation() const { return TokenLoc; }
|
|
|
|
void setTokenLocation(SourceLocation L) { TokenLoc = L; }
|
|
|
|
|
2012-04-14 14:01:31 +00:00
|
|
|
SourceRange getSourceRange() const LLVM_READONLY {
|
2009-06-02 17:58:47 +00:00
|
|
|
return SourceRange(TokenLoc);
|
|
|
|
}
|
|
|
|
static bool classof(const Stmt *T) {
|
2009-10-14 18:03:49 +00:00
|
|
|
return T->getStmtClass() == GNUNullExprClass;
|
2009-06-02 17:58:47 +00:00
|
|
|
}
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
// Iterators
|
2011-02-20 13:06:31 +00:00
|
|
|
child_range children() { return child_range(); }
|
2009-06-02 17:58:47 +00:00
|
|
|
};
|
|
|
|
|
2010-05-04 16:12:48 +00:00
|
|
|
/// VAArgExpr, used for the builtin function __builtin_va_arg.
|
2009-06-02 17:58:47 +00:00
|
|
|
class VAArgExpr : public Expr {
|
|
|
|
Stmt *Val;
|
2010-09-17 15:54:40 +00:00
|
|
|
TypeSourceInfo *TInfo;
|
2009-06-02 17:58:47 +00:00
|
|
|
SourceLocation BuiltinLoc, RParenLoc;
|
|
|
|
public:
|
2010-09-17 15:54:40 +00:00
|
|
|
VAArgExpr(SourceLocation BLoc, Expr* e, TypeSourceInfo *TInfo,
|
|
|
|
SourceLocation RPLoc, QualType t)
|
2011-02-20 13:06:31 +00:00
|
|
|
: Expr(VAArgExprClass, t, VK_RValue, OK_Ordinary,
|
|
|
|
t->isDependentType(), false,
|
2011-07-17 15:40:56 +00:00
|
|
|
(TInfo->getType()->isInstantiationDependentType() ||
|
|
|
|
e->isInstantiationDependent()),
|
2011-02-20 13:06:31 +00:00
|
|
|
(TInfo->getType()->containsUnexpandedParameterPack() ||
|
|
|
|
e->containsUnexpandedParameterPack())),
|
2010-09-17 15:54:40 +00:00
|
|
|
Val(e), TInfo(TInfo),
|
2009-06-02 17:58:47 +00:00
|
|
|
BuiltinLoc(BLoc),
|
|
|
|
RParenLoc(RPLoc) { }
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2010-05-04 16:12:48 +00:00
|
|
|
/// \brief Create an empty __builtin_va_arg expression.
|
2009-06-02 17:58:47 +00:00
|
|
|
explicit VAArgExpr(EmptyShell Empty) : Expr(VAArgExprClass, Empty) { }
|
|
|
|
|
|
|
|
const Expr *getSubExpr() const { return cast<Expr>(Val); }
|
|
|
|
Expr *getSubExpr() { return cast<Expr>(Val); }
|
|
|
|
void setSubExpr(Expr *E) { Val = E; }
|
|
|
|
|
2010-09-17 15:54:40 +00:00
|
|
|
TypeSourceInfo *getWrittenTypeInfo() const { return TInfo; }
|
|
|
|
void setWrittenTypeInfo(TypeSourceInfo *TI) { TInfo = TI; }
|
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
SourceLocation getBuiltinLoc() const { return BuiltinLoc; }
|
|
|
|
void setBuiltinLoc(SourceLocation L) { BuiltinLoc = L; }
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
SourceLocation getRParenLoc() const { return RParenLoc; }
|
|
|
|
void setRParenLoc(SourceLocation L) { RParenLoc = L; }
|
|
|
|
|
2012-04-14 14:01:31 +00:00
|
|
|
SourceRange getSourceRange() const LLVM_READONLY {
|
2009-06-02 17:58:47 +00:00
|
|
|
return SourceRange(BuiltinLoc, RParenLoc);
|
2009-10-14 18:03:49 +00:00
|
|
|
}
|
2009-06-02 17:58:47 +00:00
|
|
|
static bool classof(const Stmt *T) {
|
|
|
|
return T->getStmtClass() == VAArgExprClass;
|
|
|
|
}
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
// Iterators
|
2011-02-20 13:06:31 +00:00
|
|
|
child_range children() { return child_range(&Val, &Val+1); }
|
2009-06-02 17:58:47 +00:00
|
|
|
};
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
/// @brief Describes an C or C++ initializer list.
|
|
|
|
///
|
|
|
|
/// InitListExpr describes an initializer list, which can be used to
|
|
|
|
/// initialize objects of different types, including
|
|
|
|
/// struct/class/union types, arrays, and vectors. For example:
|
|
|
|
///
|
|
|
|
/// @code
|
|
|
|
/// struct foo x = { 1, { 2, 3 } };
|
|
|
|
/// @endcode
|
|
|
|
///
|
|
|
|
/// Prior to semantic analysis, an initializer list will represent the
|
|
|
|
/// initializer list as written by the user, but will have the
|
|
|
|
/// placeholder type "void". This initializer list is called the
|
|
|
|
/// syntactic form of the initializer, and may contain C99 designated
|
|
|
|
/// initializers (represented as DesignatedInitExprs), initializations
|
|
|
|
/// of subobject members without explicit braces, and so on. Clients
|
|
|
|
/// interested in the original syntax of the initializer list should
|
|
|
|
/// use the syntactic form of the initializer list.
|
|
|
|
///
|
|
|
|
/// After semantic analysis, the initializer list will represent the
|
|
|
|
/// semantic form of the initializer, where the initializations of all
|
|
|
|
/// subobjects are made explicit with nested InitListExpr nodes and
|
|
|
|
/// C99 designators have been eliminated by placing the designated
|
|
|
|
/// initializations into the subobject they initialize. Additionally,
|
|
|
|
/// any "holes" in the initialization, where no initializer has been
|
|
|
|
/// specified for a particular subobject, will be replaced with
|
|
|
|
/// implicitly-generated ImplicitValueInitExpr expressions that
|
|
|
|
/// value-initialize the subobjects. Note, however, that the
|
|
|
|
/// initializer lists may still have fewer initializers than there are
|
|
|
|
/// elements to initialize within the object.
|
|
|
|
///
|
2012-12-02 13:20:44 +00:00
|
|
|
/// After semantic analysis has completed, given an initializer list,
|
|
|
|
/// method isSemanticForm() returns true if and only if this is the
|
|
|
|
/// semantic form of the initializer list (note: the same AST node
|
|
|
|
/// may at the same time be the syntactic form).
|
2009-06-02 17:58:47 +00:00
|
|
|
/// Given the semantic form of the initializer list, one can retrieve
|
2012-12-02 13:20:44 +00:00
|
|
|
/// the syntactic form of that initializer list (when different)
|
|
|
|
/// using method getSyntacticForm(); the method returns null if applied
|
|
|
|
/// to a initializer list which is already in syntactic form.
|
|
|
|
/// Similarly, given the syntactic form (i.e., an initializer list such
|
|
|
|
/// that isSemanticForm() returns false), one can retrieve the semantic
|
|
|
|
/// form using method getSemanticForm().
|
|
|
|
/// Since many initializer lists have the same syntactic and semantic forms,
|
|
|
|
/// getSyntacticForm() may return NULL, indicating that the current
|
|
|
|
/// semantic initializer list also serves as its syntactic form.
|
2009-06-02 17:58:47 +00:00
|
|
|
class InitListExpr : public Expr {
|
2009-10-14 18:03:49 +00:00
|
|
|
// FIXME: Eliminate this vector in favor of ASTContext allocation
|
2010-05-04 16:12:48 +00:00
|
|
|
typedef ASTVector<Stmt *> InitExprsTy;
|
|
|
|
InitExprsTy InitExprs;
|
2009-06-02 17:58:47 +00:00
|
|
|
SourceLocation LBraceLoc, RBraceLoc;
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2012-12-02 13:20:44 +00:00
|
|
|
/// The alternative form of the initializer list (if it exists).
|
|
|
|
/// The int part of the pair stores whether this initalizer list is
|
|
|
|
/// in semantic form. If not null, the pointer points to:
|
|
|
|
/// - the syntactic form, if this is in semantic form;
|
|
|
|
/// - the semantic form, if this is in syntactic form.
|
|
|
|
llvm::PointerIntPair<InitListExpr *, 1, bool> AltForm;
|
2009-06-02 17:58:47 +00:00
|
|
|
|
2011-05-02 19:39:53 +00:00
|
|
|
/// \brief Either:
|
|
|
|
/// If this initializer list initializes an array with more elements than
|
|
|
|
/// there are initializers in the list, specifies an expression to be used
|
|
|
|
/// for value initialization of the rest of the elements.
|
|
|
|
/// Or
|
|
|
|
/// If this initializer list initializes a union, specifies which
|
|
|
|
/// field within the union will be initialized.
|
|
|
|
llvm::PointerUnion<Expr *, FieldDecl *> ArrayFillerOrUnionFieldInit;
|
2009-06-02 17:58:47 +00:00
|
|
|
|
|
|
|
public:
|
2010-05-04 16:12:48 +00:00
|
|
|
InitListExpr(ASTContext &C, SourceLocation lbraceloc,
|
2012-12-02 13:20:44 +00:00
|
|
|
ArrayRef<Expr*> initExprs, SourceLocation rbraceloc);
|
2009-06-02 17:58:47 +00:00
|
|
|
|
|
|
|
/// \brief Build an empty initializer list.
|
2010-05-04 16:12:48 +00:00
|
|
|
explicit InitListExpr(ASTContext &C, EmptyShell Empty)
|
|
|
|
: Expr(InitListExprClass, Empty), InitExprs(C) { }
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
unsigned getNumInits() const { return InitExprs.size(); }
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2011-02-20 13:06:31 +00:00
|
|
|
/// \brief Retrieve the set of initializers.
|
|
|
|
Expr **getInits() { return reinterpret_cast<Expr **>(InitExprs.data()); }
|
2012-04-14 14:01:31 +00:00
|
|
|
|
2011-02-20 13:06:31 +00:00
|
|
|
const Expr *getInit(unsigned Init) const {
|
2009-06-02 17:58:47 +00:00
|
|
|
assert(Init < getNumInits() && "Initializer access out of range!");
|
|
|
|
return cast_or_null<Expr>(InitExprs[Init]);
|
|
|
|
}
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2011-02-20 13:06:31 +00:00
|
|
|
Expr *getInit(unsigned Init) {
|
2009-06-02 17:58:47 +00:00
|
|
|
assert(Init < getNumInits() && "Initializer access out of range!");
|
|
|
|
return cast_or_null<Expr>(InitExprs[Init]);
|
|
|
|
}
|
2009-10-14 18:03:49 +00:00
|
|
|
|
|
|
|
void setInit(unsigned Init, Expr *expr) {
|
2009-06-02 17:58:47 +00:00
|
|
|
assert(Init < getNumInits() && "Initializer access out of range!");
|
|
|
|
InitExprs[Init] = expr;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// \brief Reserve space for some number of initializers.
|
2010-05-04 16:12:48 +00:00
|
|
|
void reserveInits(ASTContext &C, unsigned NumInits);
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
/// @brief Specify the number of initializers
|
|
|
|
///
|
|
|
|
/// If there are more than @p NumInits initializers, the remaining
|
|
|
|
/// initializers will be destroyed. If there are fewer than @p
|
|
|
|
/// NumInits initializers, NULL expressions will be added for the
|
|
|
|
/// unknown initializers.
|
|
|
|
void resizeInits(ASTContext &Context, unsigned NumInits);
|
|
|
|
|
|
|
|
/// @brief Updates the initializer at index @p Init with the new
|
|
|
|
/// expression @p expr, and returns the old expression at that
|
|
|
|
/// location.
|
|
|
|
///
|
|
|
|
/// When @p Init is out of range for this initializer list, the
|
|
|
|
/// initializer list will be extended with NULL expressions to
|
2011-05-02 19:39:53 +00:00
|
|
|
/// accommodate the new entry.
|
2010-05-04 16:12:48 +00:00
|
|
|
Expr *updateInit(ASTContext &C, unsigned Init, Expr *expr);
|
2009-06-02 17:58:47 +00:00
|
|
|
|
2011-05-02 19:39:53 +00:00
|
|
|
/// \brief If this initializer list initializes an array with more elements
|
|
|
|
/// than there are initializers in the list, specifies an expression to be
|
|
|
|
/// used for value initialization of the rest of the elements.
|
|
|
|
Expr *getArrayFiller() {
|
|
|
|
return ArrayFillerOrUnionFieldInit.dyn_cast<Expr *>();
|
|
|
|
}
|
2011-06-12 15:46:16 +00:00
|
|
|
const Expr *getArrayFiller() const {
|
|
|
|
return const_cast<InitListExpr *>(this)->getArrayFiller();
|
|
|
|
}
|
2011-05-02 19:39:53 +00:00
|
|
|
void setArrayFiller(Expr *filler);
|
|
|
|
|
2012-04-14 14:01:31 +00:00
|
|
|
/// \brief Return true if this is an array initializer and its array "filler"
|
|
|
|
/// has been set.
|
|
|
|
bool hasArrayFiller() const { return getArrayFiller(); }
|
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
/// \brief If this initializes a union, specifies which field in the
|
|
|
|
/// union to initialize.
|
|
|
|
///
|
|
|
|
/// Typically, this field is the first named field within the
|
|
|
|
/// union. However, a designated initializer can specify the
|
|
|
|
/// initialization of a different field within the union.
|
2011-05-02 19:39:53 +00:00
|
|
|
FieldDecl *getInitializedFieldInUnion() {
|
|
|
|
return ArrayFillerOrUnionFieldInit.dyn_cast<FieldDecl *>();
|
|
|
|
}
|
2011-06-12 15:46:16 +00:00
|
|
|
const FieldDecl *getInitializedFieldInUnion() const {
|
|
|
|
return const_cast<InitListExpr *>(this)->getInitializedFieldInUnion();
|
|
|
|
}
|
2011-05-02 19:39:53 +00:00
|
|
|
void setInitializedFieldInUnion(FieldDecl *FD) {
|
|
|
|
ArrayFillerOrUnionFieldInit = FD;
|
|
|
|
}
|
2009-06-02 17:58:47 +00:00
|
|
|
|
|
|
|
// Explicit InitListExpr's originate from source code (and have valid source
|
|
|
|
// locations). Implicit InitListExpr's are created by the semantic analyzer.
|
|
|
|
bool isExplicit() {
|
|
|
|
return LBraceLoc.isValid() && RBraceLoc.isValid();
|
|
|
|
}
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2012-05-03 16:53:59 +00:00
|
|
|
// Is this an initializer for an array of characters, initialized by a string
|
|
|
|
// literal or an @encode?
|
|
|
|
bool isStringLiteralInit() const;
|
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
SourceLocation getLBraceLoc() const { return LBraceLoc; }
|
|
|
|
void setLBraceLoc(SourceLocation Loc) { LBraceLoc = Loc; }
|
|
|
|
SourceLocation getRBraceLoc() const { return RBraceLoc; }
|
|
|
|
void setRBraceLoc(SourceLocation Loc) { RBraceLoc = Loc; }
|
|
|
|
|
2012-12-02 13:20:44 +00:00
|
|
|
bool isSemanticForm() const { return AltForm.getInt(); }
|
|
|
|
InitListExpr *getSemanticForm() const {
|
|
|
|
return isSemanticForm() ? 0 : AltForm.getPointer();
|
|
|
|
}
|
|
|
|
InitListExpr *getSyntacticForm() const {
|
|
|
|
return isSemanticForm() ? AltForm.getPointer() : 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void setSyntacticForm(InitListExpr *Init) {
|
|
|
|
AltForm.setPointer(Init);
|
|
|
|
AltForm.setInt(true);
|
|
|
|
Init->AltForm.setPointer(this);
|
|
|
|
Init->AltForm.setInt(false);
|
|
|
|
}
|
2009-06-02 17:58:47 +00:00
|
|
|
|
2012-04-14 14:01:31 +00:00
|
|
|
bool hadArrayRangeDesignator() const {
|
|
|
|
return InitListExprBits.HadArrayRangeDesignator != 0;
|
|
|
|
}
|
2009-10-14 18:03:49 +00:00
|
|
|
void sawArrayRangeDesignator(bool ARD = true) {
|
2012-04-14 14:01:31 +00:00
|
|
|
InitListExprBits.HadArrayRangeDesignator = ARD;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool initializesStdInitializerList() const {
|
|
|
|
return InitListExprBits.InitializesStdInitializerList != 0;
|
|
|
|
}
|
|
|
|
void setInitializesStdInitializerList(bool ISIL = true) {
|
|
|
|
InitListExprBits.InitializesStdInitializerList = ISIL;
|
2009-06-02 17:58:47 +00:00
|
|
|
}
|
|
|
|
|
2012-04-14 14:01:31 +00:00
|
|
|
SourceRange getSourceRange() const LLVM_READONLY;
|
2011-02-20 13:06:31 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
static bool classof(const Stmt *T) {
|
2009-10-14 18:03:49 +00:00
|
|
|
return T->getStmtClass() == InitListExprClass;
|
2009-06-02 17:58:47 +00:00
|
|
|
}
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
// Iterators
|
2011-02-20 13:06:31 +00:00
|
|
|
child_range children() {
|
|
|
|
if (InitExprs.empty()) return child_range();
|
|
|
|
return child_range(&InitExprs[0], &InitExprs[0] + InitExprs.size());
|
|
|
|
}
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2010-05-04 16:12:48 +00:00
|
|
|
typedef InitExprsTy::iterator iterator;
|
2010-09-17 15:54:40 +00:00
|
|
|
typedef InitExprsTy::const_iterator const_iterator;
|
2010-05-04 16:12:48 +00:00
|
|
|
typedef InitExprsTy::reverse_iterator reverse_iterator;
|
2010-09-17 15:54:40 +00:00
|
|
|
typedef InitExprsTy::const_reverse_iterator const_reverse_iterator;
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
iterator begin() { return InitExprs.begin(); }
|
2010-09-17 15:54:40 +00:00
|
|
|
const_iterator begin() const { return InitExprs.begin(); }
|
2009-06-02 17:58:47 +00:00
|
|
|
iterator end() { return InitExprs.end(); }
|
2010-09-17 15:54:40 +00:00
|
|
|
const_iterator end() const { return InitExprs.end(); }
|
2009-06-02 17:58:47 +00:00
|
|
|
reverse_iterator rbegin() { return InitExprs.rbegin(); }
|
2010-09-17 15:54:40 +00:00
|
|
|
const_reverse_iterator rbegin() const { return InitExprs.rbegin(); }
|
2009-06-02 17:58:47 +00:00
|
|
|
reverse_iterator rend() { return InitExprs.rend(); }
|
2010-09-17 15:54:40 +00:00
|
|
|
const_reverse_iterator rend() const { return InitExprs.rend(); }
|
2011-05-02 19:39:53 +00:00
|
|
|
|
|
|
|
friend class ASTStmtReader;
|
|
|
|
friend class ASTStmtWriter;
|
2009-06-02 17:58:47 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/// @brief Represents a C99 designated initializer expression.
|
|
|
|
///
|
|
|
|
/// A designated initializer expression (C99 6.7.8) contains one or
|
|
|
|
/// more designators (which can be field designators, array
|
|
|
|
/// designators, or GNU array-range designators) followed by an
|
|
|
|
/// expression that initializes the field or element(s) that the
|
|
|
|
/// designators refer to. For example, given:
|
2009-10-14 18:03:49 +00:00
|
|
|
///
|
2009-06-02 17:58:47 +00:00
|
|
|
/// @code
|
|
|
|
/// struct point {
|
|
|
|
/// double x;
|
|
|
|
/// double y;
|
|
|
|
/// };
|
|
|
|
/// struct point ptarray[10] = { [2].y = 1.0, [2].x = 2.0, [0].x = 1.0 };
|
|
|
|
/// @endcode
|
|
|
|
///
|
|
|
|
/// The InitListExpr contains three DesignatedInitExprs, the first of
|
|
|
|
/// which covers @c [2].y=1.0. This DesignatedInitExpr will have two
|
|
|
|
/// designators, one array designator for @c [2] followed by one field
|
|
|
|
/// designator for @c .y. The initalization expression will be 1.0.
|
|
|
|
class DesignatedInitExpr : public Expr {
|
|
|
|
public:
|
|
|
|
/// \brief Forward declaration of the Designator class.
|
|
|
|
class Designator;
|
|
|
|
|
|
|
|
private:
|
|
|
|
/// The location of the '=' or ':' prior to the actual initializer
|
|
|
|
/// expression.
|
|
|
|
SourceLocation EqualOrColonLoc;
|
|
|
|
|
|
|
|
/// Whether this designated initializer used the GNU deprecated
|
|
|
|
/// syntax rather than the C99 '=' syntax.
|
|
|
|
bool GNUSyntax : 1;
|
|
|
|
|
|
|
|
/// The number of designators in this initializer expression.
|
|
|
|
unsigned NumDesignators : 15;
|
|
|
|
|
|
|
|
/// The number of subexpressions of this initializer expression,
|
|
|
|
/// which contains both the initializer and any additional
|
|
|
|
/// expressions used by array and array-range designators.
|
|
|
|
unsigned NumSubExprs : 16;
|
|
|
|
|
2012-04-14 14:01:31 +00:00
|
|
|
/// \brief The designators in this designated initialization
|
|
|
|
/// expression.
|
|
|
|
Designator *Designators;
|
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
|
2010-01-15 15:39:40 +00:00
|
|
|
DesignatedInitExpr(ASTContext &C, QualType Ty, unsigned NumDesignators,
|
2009-06-02 17:58:47 +00:00
|
|
|
const Designator *Designators,
|
|
|
|
SourceLocation EqualOrColonLoc, bool GNUSyntax,
|
2012-12-02 13:20:44 +00:00
|
|
|
ArrayRef<Expr*> IndexExprs, Expr *Init);
|
2009-06-02 17:58:47 +00:00
|
|
|
|
|
|
|
explicit DesignatedInitExpr(unsigned NumSubExprs)
|
|
|
|
: Expr(DesignatedInitExprClass, EmptyShell()),
|
2012-04-14 14:01:31 +00:00
|
|
|
NumDesignators(0), NumSubExprs(NumSubExprs), Designators(0) { }
|
2009-06-02 17:58:47 +00:00
|
|
|
|
|
|
|
public:
|
|
|
|
/// A field designator, e.g., ".x".
|
|
|
|
struct FieldDesignator {
|
|
|
|
/// Refers to the field that is being initialized. The low bit
|
|
|
|
/// of this field determines whether this is actually a pointer
|
|
|
|
/// to an IdentifierInfo (if 1) or a FieldDecl (if 0). When
|
|
|
|
/// initially constructed, a field designator will store an
|
|
|
|
/// IdentifierInfo*. After semantic analysis has resolved that
|
|
|
|
/// name, the field designator will instead store a FieldDecl*.
|
|
|
|
uintptr_t NameOrField;
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
/// The location of the '.' in the designated initializer.
|
|
|
|
unsigned DotLoc;
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
/// The location of the field name in the designated initializer.
|
|
|
|
unsigned FieldLoc;
|
|
|
|
};
|
|
|
|
|
|
|
|
/// An array or GNU array-range designator, e.g., "[9]" or "[10..15]".
|
|
|
|
struct ArrayOrRangeDesignator {
|
|
|
|
/// Location of the first index expression within the designated
|
|
|
|
/// initializer expression's list of subexpressions.
|
|
|
|
unsigned Index;
|
|
|
|
/// The location of the '[' starting the array range designator.
|
|
|
|
unsigned LBracketLoc;
|
|
|
|
/// The location of the ellipsis separating the start and end
|
|
|
|
/// indices. Only valid for GNU array-range designators.
|
|
|
|
unsigned EllipsisLoc;
|
|
|
|
/// The location of the ']' terminating the array range designator.
|
2009-10-14 18:03:49 +00:00
|
|
|
unsigned RBracketLoc;
|
2009-06-02 17:58:47 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/// @brief Represents a single C99 designator.
|
|
|
|
///
|
|
|
|
/// @todo This class is infuriatingly similar to clang::Designator,
|
|
|
|
/// but minor differences (storing indices vs. storing pointers)
|
|
|
|
/// keep us from reusing it. Try harder, later, to rectify these
|
|
|
|
/// differences.
|
|
|
|
class Designator {
|
|
|
|
/// @brief The kind of designator this describes.
|
|
|
|
enum {
|
|
|
|
FieldDesignator,
|
|
|
|
ArrayDesignator,
|
|
|
|
ArrayRangeDesignator
|
|
|
|
} Kind;
|
|
|
|
|
|
|
|
union {
|
|
|
|
/// A field designator, e.g., ".x".
|
|
|
|
struct FieldDesignator Field;
|
|
|
|
/// An array or GNU array-range designator, e.g., "[9]" or "[10..15]".
|
|
|
|
struct ArrayOrRangeDesignator ArrayOrRange;
|
|
|
|
};
|
|
|
|
friend class DesignatedInitExpr;
|
|
|
|
|
|
|
|
public:
|
|
|
|
Designator() {}
|
|
|
|
|
|
|
|
/// @brief Initializes a field designator.
|
2009-10-14 18:03:49 +00:00
|
|
|
Designator(const IdentifierInfo *FieldName, SourceLocation DotLoc,
|
|
|
|
SourceLocation FieldLoc)
|
2009-06-02 17:58:47 +00:00
|
|
|
: Kind(FieldDesignator) {
|
|
|
|
Field.NameOrField = reinterpret_cast<uintptr_t>(FieldName) | 0x01;
|
|
|
|
Field.DotLoc = DotLoc.getRawEncoding();
|
|
|
|
Field.FieldLoc = FieldLoc.getRawEncoding();
|
|
|
|
}
|
|
|
|
|
|
|
|
/// @brief Initializes an array designator.
|
2009-10-14 18:03:49 +00:00
|
|
|
Designator(unsigned Index, SourceLocation LBracketLoc,
|
2009-06-02 17:58:47 +00:00
|
|
|
SourceLocation RBracketLoc)
|
|
|
|
: Kind(ArrayDesignator) {
|
|
|
|
ArrayOrRange.Index = Index;
|
|
|
|
ArrayOrRange.LBracketLoc = LBracketLoc.getRawEncoding();
|
|
|
|
ArrayOrRange.EllipsisLoc = SourceLocation().getRawEncoding();
|
|
|
|
ArrayOrRange.RBracketLoc = RBracketLoc.getRawEncoding();
|
|
|
|
}
|
|
|
|
|
|
|
|
/// @brief Initializes a GNU array-range designator.
|
2009-10-14 18:03:49 +00:00
|
|
|
Designator(unsigned Index, SourceLocation LBracketLoc,
|
2009-06-02 17:58:47 +00:00
|
|
|
SourceLocation EllipsisLoc, SourceLocation RBracketLoc)
|
|
|
|
: Kind(ArrayRangeDesignator) {
|
|
|
|
ArrayOrRange.Index = Index;
|
|
|
|
ArrayOrRange.LBracketLoc = LBracketLoc.getRawEncoding();
|
|
|
|
ArrayOrRange.EllipsisLoc = EllipsisLoc.getRawEncoding();
|
|
|
|
ArrayOrRange.RBracketLoc = RBracketLoc.getRawEncoding();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool isFieldDesignator() const { return Kind == FieldDesignator; }
|
|
|
|
bool isArrayDesignator() const { return Kind == ArrayDesignator; }
|
|
|
|
bool isArrayRangeDesignator() const { return Kind == ArrayRangeDesignator; }
|
|
|
|
|
2011-07-17 15:40:56 +00:00
|
|
|
IdentifierInfo *getFieldName() const;
|
2009-06-02 17:58:47 +00:00
|
|
|
|
2011-07-17 15:40:56 +00:00
|
|
|
FieldDecl *getField() const {
|
2009-06-02 17:58:47 +00:00
|
|
|
assert(Kind == FieldDesignator && "Only valid on a field designator");
|
|
|
|
if (Field.NameOrField & 0x01)
|
|
|
|
return 0;
|
|
|
|
else
|
|
|
|
return reinterpret_cast<FieldDecl *>(Field.NameOrField);
|
|
|
|
}
|
|
|
|
|
|
|
|
void setField(FieldDecl *FD) {
|
|
|
|
assert(Kind == FieldDesignator && "Only valid on a field designator");
|
|
|
|
Field.NameOrField = reinterpret_cast<uintptr_t>(FD);
|
|
|
|
}
|
|
|
|
|
|
|
|
SourceLocation getDotLoc() const {
|
|
|
|
assert(Kind == FieldDesignator && "Only valid on a field designator");
|
|
|
|
return SourceLocation::getFromRawEncoding(Field.DotLoc);
|
|
|
|
}
|
|
|
|
|
|
|
|
SourceLocation getFieldLoc() const {
|
|
|
|
assert(Kind == FieldDesignator && "Only valid on a field designator");
|
|
|
|
return SourceLocation::getFromRawEncoding(Field.FieldLoc);
|
|
|
|
}
|
|
|
|
|
|
|
|
SourceLocation getLBracketLoc() const {
|
|
|
|
assert((Kind == ArrayDesignator || Kind == ArrayRangeDesignator) &&
|
|
|
|
"Only valid on an array or array-range designator");
|
|
|
|
return SourceLocation::getFromRawEncoding(ArrayOrRange.LBracketLoc);
|
|
|
|
}
|
|
|
|
|
|
|
|
SourceLocation getRBracketLoc() const {
|
|
|
|
assert((Kind == ArrayDesignator || Kind == ArrayRangeDesignator) &&
|
|
|
|
"Only valid on an array or array-range designator");
|
|
|
|
return SourceLocation::getFromRawEncoding(ArrayOrRange.RBracketLoc);
|
|
|
|
}
|
|
|
|
|
|
|
|
SourceLocation getEllipsisLoc() const {
|
|
|
|
assert(Kind == ArrayRangeDesignator &&
|
|
|
|
"Only valid on an array-range designator");
|
|
|
|
return SourceLocation::getFromRawEncoding(ArrayOrRange.EllipsisLoc);
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned getFirstExprIndex() const {
|
|
|
|
assert((Kind == ArrayDesignator || Kind == ArrayRangeDesignator) &&
|
|
|
|
"Only valid on an array or array-range designator");
|
|
|
|
return ArrayOrRange.Index;
|
|
|
|
}
|
|
|
|
|
|
|
|
SourceLocation getStartLocation() const {
|
|
|
|
if (Kind == FieldDesignator)
|
|
|
|
return getDotLoc().isInvalid()? getFieldLoc() : getDotLoc();
|
|
|
|
else
|
|
|
|
return getLBracketLoc();
|
|
|
|
}
|
2011-05-02 19:39:53 +00:00
|
|
|
SourceLocation getEndLocation() const {
|
|
|
|
return Kind == FieldDesignator ? getFieldLoc() : getRBracketLoc();
|
|
|
|
}
|
2012-04-14 14:01:31 +00:00
|
|
|
SourceRange getSourceRange() const LLVM_READONLY {
|
2011-05-02 19:39:53 +00:00
|
|
|
return SourceRange(getStartLocation(), getEndLocation());
|
|
|
|
}
|
2009-06-02 17:58:47 +00:00
|
|
|
};
|
|
|
|
|
2009-10-14 18:03:49 +00:00
|
|
|
static DesignatedInitExpr *Create(ASTContext &C, Designator *Designators,
|
2009-06-02 17:58:47 +00:00
|
|
|
unsigned NumDesignators,
|
2012-12-02 13:20:44 +00:00
|
|
|
ArrayRef<Expr*> IndexExprs,
|
2009-06-02 17:58:47 +00:00
|
|
|
SourceLocation EqualOrColonLoc,
|
|
|
|
bool GNUSyntax, Expr *Init);
|
|
|
|
|
|
|
|
static DesignatedInitExpr *CreateEmpty(ASTContext &C, unsigned NumIndexExprs);
|
|
|
|
|
|
|
|
/// @brief Returns the number of designators in this initializer.
|
|
|
|
unsigned size() const { return NumDesignators; }
|
|
|
|
|
|
|
|
// Iterator access to the designators.
|
2011-07-17 15:40:56 +00:00
|
|
|
typedef Designator *designators_iterator;
|
2009-06-02 17:58:47 +00:00
|
|
|
designators_iterator designators_begin() { return Designators; }
|
2009-10-14 18:03:49 +00:00
|
|
|
designators_iterator designators_end() {
|
|
|
|
return Designators + NumDesignators;
|
2009-06-02 17:58:47 +00:00
|
|
|
}
|
|
|
|
|
2011-07-17 15:40:56 +00:00
|
|
|
typedef const Designator *const_designators_iterator;
|
|
|
|
const_designators_iterator designators_begin() const { return Designators; }
|
|
|
|
const_designators_iterator designators_end() const {
|
|
|
|
return Designators + NumDesignators;
|
|
|
|
}
|
|
|
|
|
2011-02-20 13:06:31 +00:00
|
|
|
typedef std::reverse_iterator<designators_iterator>
|
|
|
|
reverse_designators_iterator;
|
|
|
|
reverse_designators_iterator designators_rbegin() {
|
|
|
|
return reverse_designators_iterator(designators_end());
|
|
|
|
}
|
|
|
|
reverse_designators_iterator designators_rend() {
|
|
|
|
return reverse_designators_iterator(designators_begin());
|
|
|
|
}
|
|
|
|
|
2011-07-17 15:40:56 +00:00
|
|
|
typedef std::reverse_iterator<const_designators_iterator>
|
|
|
|
const_reverse_designators_iterator;
|
|
|
|
const_reverse_designators_iterator designators_rbegin() const {
|
|
|
|
return const_reverse_designators_iterator(designators_end());
|
|
|
|
}
|
|
|
|
const_reverse_designators_iterator designators_rend() const {
|
|
|
|
return const_reverse_designators_iterator(designators_begin());
|
|
|
|
}
|
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
Designator *getDesignator(unsigned Idx) { return &designators_begin()[Idx]; }
|
|
|
|
|
2012-04-14 14:01:31 +00:00
|
|
|
void setDesignators(ASTContext &C, const Designator *Desigs,
|
2010-01-15 15:39:40 +00:00
|
|
|
unsigned NumDesigs);
|
2009-06-02 17:58:47 +00:00
|
|
|
|
|
|
|
Expr *getArrayIndex(const Designator& D);
|
|
|
|
Expr *getArrayRangeStart(const Designator& D);
|
|
|
|
Expr *getArrayRangeEnd(const Designator& D);
|
|
|
|
|
|
|
|
/// @brief Retrieve the location of the '=' that precedes the
|
|
|
|
/// initializer value itself, if present.
|
|
|
|
SourceLocation getEqualOrColonLoc() const { return EqualOrColonLoc; }
|
|
|
|
void setEqualOrColonLoc(SourceLocation L) { EqualOrColonLoc = L; }
|
|
|
|
|
|
|
|
/// @brief Determines whether this designated initializer used the
|
|
|
|
/// deprecated GNU syntax for designated initializers.
|
|
|
|
bool usesGNUSyntax() const { return GNUSyntax; }
|
|
|
|
void setGNUSyntax(bool GNU) { GNUSyntax = GNU; }
|
|
|
|
|
|
|
|
/// @brief Retrieve the initializer value.
|
2009-10-14 18:03:49 +00:00
|
|
|
Expr *getInit() const {
|
2009-06-02 17:58:47 +00:00
|
|
|
return cast<Expr>(*const_cast<DesignatedInitExpr*>(this)->child_begin());
|
|
|
|
}
|
|
|
|
|
|
|
|
void setInit(Expr *init) {
|
|
|
|
*child_begin() = init;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// \brief Retrieve the total number of subexpressions in this
|
|
|
|
/// designated initializer expression, including the actual
|
|
|
|
/// initialized value and any expressions that occur within array
|
|
|
|
/// and array-range designators.
|
|
|
|
unsigned getNumSubExprs() const { return NumSubExprs; }
|
|
|
|
|
|
|
|
Expr *getSubExpr(unsigned Idx) {
|
|
|
|
assert(Idx < NumSubExprs && "Subscript out of range");
|
|
|
|
char* Ptr = static_cast<char*>(static_cast<void *>(this));
|
|
|
|
Ptr += sizeof(DesignatedInitExpr);
|
|
|
|
return reinterpret_cast<Expr**>(reinterpret_cast<void**>(Ptr))[Idx];
|
|
|
|
}
|
|
|
|
|
|
|
|
void setSubExpr(unsigned Idx, Expr *E) {
|
|
|
|
assert(Idx < NumSubExprs && "Subscript out of range");
|
|
|
|
char* Ptr = static_cast<char*>(static_cast<void *>(this));
|
|
|
|
Ptr += sizeof(DesignatedInitExpr);
|
|
|
|
reinterpret_cast<Expr**>(reinterpret_cast<void**>(Ptr))[Idx] = E;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// \brief Replaces the designator at index @p Idx with the series
|
|
|
|
/// of designators in [First, Last).
|
2010-01-15 15:39:40 +00:00
|
|
|
void ExpandDesignator(ASTContext &C, unsigned Idx, const Designator *First,
|
2009-06-02 17:58:47 +00:00
|
|
|
const Designator *Last);
|
|
|
|
|
2011-05-02 19:39:53 +00:00
|
|
|
SourceRange getDesignatorsSourceRange() const;
|
|
|
|
|
2012-04-14 14:01:31 +00:00
|
|
|
SourceRange getSourceRange() const LLVM_READONLY;
|
2009-06-02 17:58:47 +00:00
|
|
|
|
|
|
|
static bool classof(const Stmt *T) {
|
2009-10-14 18:03:49 +00:00
|
|
|
return T->getStmtClass() == DesignatedInitExprClass;
|
2009-06-02 17:58:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Iterators
|
2011-02-20 13:06:31 +00:00
|
|
|
child_range children() {
|
|
|
|
Stmt **begin = reinterpret_cast<Stmt**>(this + 1);
|
|
|
|
return child_range(begin, begin + NumSubExprs);
|
|
|
|
}
|
2009-06-02 17:58:47 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/// \brief Represents an implicitly-generated value initialization of
|
|
|
|
/// an object of a given type.
|
|
|
|
///
|
|
|
|
/// Implicit value initializations occur within semantic initializer
|
|
|
|
/// list expressions (InitListExpr) as placeholders for subobject
|
|
|
|
/// initializations not explicitly specified by the user.
|
|
|
|
///
|
|
|
|
/// \see InitListExpr
|
2009-10-14 18:03:49 +00:00
|
|
|
class ImplicitValueInitExpr : public Expr {
|
2009-06-02 17:58:47 +00:00
|
|
|
public:
|
2009-10-14 18:03:49 +00:00
|
|
|
explicit ImplicitValueInitExpr(QualType ty)
|
2011-02-20 13:06:31 +00:00
|
|
|
: Expr(ImplicitValueInitExprClass, ty, VK_RValue, OK_Ordinary,
|
2011-07-17 15:40:56 +00:00
|
|
|
false, false, ty->isInstantiationDependentType(), false) { }
|
2009-06-02 17:58:47 +00:00
|
|
|
|
|
|
|
/// \brief Construct an empty implicit value initialization.
|
|
|
|
explicit ImplicitValueInitExpr(EmptyShell Empty)
|
|
|
|
: Expr(ImplicitValueInitExprClass, Empty) { }
|
|
|
|
|
2009-10-14 18:03:49 +00:00
|
|
|
static bool classof(const Stmt *T) {
|
2009-06-02 17:58:47 +00:00
|
|
|
return T->getStmtClass() == ImplicitValueInitExprClass;
|
|
|
|
}
|
|
|
|
|
2012-04-14 14:01:31 +00:00
|
|
|
SourceRange getSourceRange() const LLVM_READONLY {
|
2009-06-02 17:58:47 +00:00
|
|
|
return SourceRange();
|
|
|
|
}
|
|
|
|
|
2009-10-14 18:03:49 +00:00
|
|
|
// Iterators
|
2011-02-20 13:06:31 +00:00
|
|
|
child_range children() { return child_range(); }
|
2009-10-14 18:03:49 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
class ParenListExpr : public Expr {
|
|
|
|
Stmt **Exprs;
|
|
|
|
unsigned NumExprs;
|
|
|
|
SourceLocation LParenLoc, RParenLoc;
|
|
|
|
|
|
|
|
public:
|
2012-12-02 13:20:44 +00:00
|
|
|
ParenListExpr(ASTContext& C, SourceLocation lparenloc, ArrayRef<Expr*> exprs,
|
|
|
|
SourceLocation rparenloc);
|
2009-10-14 18:03:49 +00:00
|
|
|
|
|
|
|
/// \brief Build an empty paren list.
|
2010-07-13 17:21:42 +00:00
|
|
|
explicit ParenListExpr(EmptyShell Empty) : Expr(ParenListExprClass, Empty) { }
|
2009-10-14 18:03:49 +00:00
|
|
|
|
|
|
|
unsigned getNumExprs() const { return NumExprs; }
|
|
|
|
|
|
|
|
const Expr* getExpr(unsigned Init) const {
|
|
|
|
assert(Init < getNumExprs() && "Initializer access out of range!");
|
|
|
|
return cast_or_null<Expr>(Exprs[Init]);
|
|
|
|
}
|
|
|
|
|
|
|
|
Expr* getExpr(unsigned Init) {
|
|
|
|
assert(Init < getNumExprs() && "Initializer access out of range!");
|
|
|
|
return cast_or_null<Expr>(Exprs[Init]);
|
|
|
|
}
|
|
|
|
|
|
|
|
Expr **getExprs() { return reinterpret_cast<Expr **>(Exprs); }
|
|
|
|
|
|
|
|
SourceLocation getLParenLoc() const { return LParenLoc; }
|
|
|
|
SourceLocation getRParenLoc() const { return RParenLoc; }
|
|
|
|
|
2012-04-14 14:01:31 +00:00
|
|
|
SourceRange getSourceRange() const LLVM_READONLY {
|
2009-10-14 18:03:49 +00:00
|
|
|
return SourceRange(LParenLoc, RParenLoc);
|
|
|
|
}
|
|
|
|
static bool classof(const Stmt *T) {
|
|
|
|
return T->getStmtClass() == ParenListExprClass;
|
|
|
|
}
|
2009-06-02 17:58:47 +00:00
|
|
|
|
|
|
|
// Iterators
|
2011-02-20 13:06:31 +00:00
|
|
|
child_range children() {
|
|
|
|
return child_range(&Exprs[0], &Exprs[0]+NumExprs);
|
|
|
|
}
|
2010-07-13 17:21:42 +00:00
|
|
|
|
2010-09-17 15:54:40 +00:00
|
|
|
friend class ASTStmtReader;
|
|
|
|
friend class ASTStmtWriter;
|
2009-06-02 17:58:47 +00:00
|
|
|
};
|
|
|
|
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2012-04-14 14:01:31 +00:00
|
|
|
/// \brief Represents a C11 generic selection.
|
2011-05-02 19:39:53 +00:00
|
|
|
///
|
2012-04-14 14:01:31 +00:00
|
|
|
/// A generic selection (C11 6.5.1.1) contains an unevaluated controlling
|
2011-05-02 19:39:53 +00:00
|
|
|
/// expression, followed by one or more generic associations. Each generic
|
|
|
|
/// association specifies a type name and an expression, or "default" and an
|
|
|
|
/// expression (in which case it is known as a default generic association).
|
|
|
|
/// The type and value of the generic selection are identical to those of its
|
|
|
|
/// result expression, which is defined as the expression in the generic
|
|
|
|
/// association with a type name that is compatible with the type of the
|
|
|
|
/// controlling expression, or the expression in the default generic association
|
|
|
|
/// if no types are compatible. For example:
|
|
|
|
///
|
|
|
|
/// @code
|
|
|
|
/// _Generic(X, double: 1, float: 2, default: 3)
|
|
|
|
/// @endcode
|
|
|
|
///
|
|
|
|
/// The above expression evaluates to 1 if 1.0 is substituted for X, 2 if 1.0f
|
|
|
|
/// or 3 if "hello".
|
|
|
|
///
|
|
|
|
/// As an extension, generic selections are allowed in C++, where the following
|
|
|
|
/// additional semantics apply:
|
|
|
|
///
|
|
|
|
/// Any generic selection whose controlling expression is type-dependent or
|
|
|
|
/// which names a dependent type in its association list is result-dependent,
|
|
|
|
/// which means that the choice of result expression is dependent.
|
|
|
|
/// Result-dependent generic associations are both type- and value-dependent.
|
|
|
|
class GenericSelectionExpr : public Expr {
|
|
|
|
enum { CONTROLLING, END_EXPR };
|
|
|
|
TypeSourceInfo **AssocTypes;
|
|
|
|
Stmt **SubExprs;
|
|
|
|
unsigned NumAssocs, ResultIndex;
|
|
|
|
SourceLocation GenericLoc, DefaultLoc, RParenLoc;
|
|
|
|
|
|
|
|
public:
|
|
|
|
GenericSelectionExpr(ASTContext &Context,
|
|
|
|
SourceLocation GenericLoc, Expr *ControllingExpr,
|
2012-12-02 13:20:44 +00:00
|
|
|
ArrayRef<TypeSourceInfo*> AssocTypes,
|
|
|
|
ArrayRef<Expr*> AssocExprs,
|
|
|
|
SourceLocation DefaultLoc, SourceLocation RParenLoc,
|
2011-05-02 19:39:53 +00:00
|
|
|
bool ContainsUnexpandedParameterPack,
|
|
|
|
unsigned ResultIndex);
|
|
|
|
|
|
|
|
/// This constructor is used in the result-dependent case.
|
|
|
|
GenericSelectionExpr(ASTContext &Context,
|
|
|
|
SourceLocation GenericLoc, Expr *ControllingExpr,
|
2012-12-02 13:20:44 +00:00
|
|
|
ArrayRef<TypeSourceInfo*> AssocTypes,
|
|
|
|
ArrayRef<Expr*> AssocExprs,
|
|
|
|
SourceLocation DefaultLoc, SourceLocation RParenLoc,
|
2011-05-02 19:39:53 +00:00
|
|
|
bool ContainsUnexpandedParameterPack);
|
|
|
|
|
|
|
|
explicit GenericSelectionExpr(EmptyShell Empty)
|
|
|
|
: Expr(GenericSelectionExprClass, Empty) { }
|
|
|
|
|
|
|
|
unsigned getNumAssocs() const { return NumAssocs; }
|
|
|
|
|
|
|
|
SourceLocation getGenericLoc() const { return GenericLoc; }
|
|
|
|
SourceLocation getDefaultLoc() const { return DefaultLoc; }
|
|
|
|
SourceLocation getRParenLoc() const { return RParenLoc; }
|
|
|
|
|
|
|
|
const Expr *getAssocExpr(unsigned i) const {
|
|
|
|
return cast<Expr>(SubExprs[END_EXPR+i]);
|
|
|
|
}
|
|
|
|
Expr *getAssocExpr(unsigned i) { return cast<Expr>(SubExprs[END_EXPR+i]); }
|
|
|
|
|
|
|
|
const TypeSourceInfo *getAssocTypeSourceInfo(unsigned i) const {
|
|
|
|
return AssocTypes[i];
|
|
|
|
}
|
|
|
|
TypeSourceInfo *getAssocTypeSourceInfo(unsigned i) { return AssocTypes[i]; }
|
|
|
|
|
|
|
|
QualType getAssocType(unsigned i) const {
|
|
|
|
if (const TypeSourceInfo *TS = getAssocTypeSourceInfo(i))
|
|
|
|
return TS->getType();
|
|
|
|
else
|
|
|
|
return QualType();
|
|
|
|
}
|
|
|
|
|
|
|
|
const Expr *getControllingExpr() const {
|
|
|
|
return cast<Expr>(SubExprs[CONTROLLING]);
|
|
|
|
}
|
|
|
|
Expr *getControllingExpr() { return cast<Expr>(SubExprs[CONTROLLING]); }
|
|
|
|
|
|
|
|
/// Whether this generic selection is result-dependent.
|
|
|
|
bool isResultDependent() const { return ResultIndex == -1U; }
|
|
|
|
|
|
|
|
/// The zero-based index of the result expression's generic association in
|
|
|
|
/// the generic selection's association list. Defined only if the
|
|
|
|
/// generic selection is not result-dependent.
|
|
|
|
unsigned getResultIndex() const {
|
|
|
|
assert(!isResultDependent() && "Generic selection is result-dependent");
|
|
|
|
return ResultIndex;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// The generic selection's result expression. Defined only if the
|
|
|
|
/// generic selection is not result-dependent.
|
|
|
|
const Expr *getResultExpr() const { return getAssocExpr(getResultIndex()); }
|
|
|
|
Expr *getResultExpr() { return getAssocExpr(getResultIndex()); }
|
|
|
|
|
2012-04-14 14:01:31 +00:00
|
|
|
SourceRange getSourceRange() const LLVM_READONLY {
|
2011-05-02 19:39:53 +00:00
|
|
|
return SourceRange(GenericLoc, RParenLoc);
|
|
|
|
}
|
|
|
|
static bool classof(const Stmt *T) {
|
|
|
|
return T->getStmtClass() == GenericSelectionExprClass;
|
|
|
|
}
|
|
|
|
|
|
|
|
child_range children() {
|
|
|
|
return child_range(SubExprs, SubExprs+END_EXPR+NumAssocs);
|
|
|
|
}
|
|
|
|
|
|
|
|
friend class ASTStmtReader;
|
|
|
|
};
|
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Clang Extensions
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
|
|
|
|
/// ExtVectorElementExpr - This represents access to specific elements of a
|
|
|
|
/// vector, and may occur on the left hand side or right hand side. For example
|
|
|
|
/// the following is legal: "V.xy = V.zw" if V is a 4 element extended vector.
|
|
|
|
///
|
|
|
|
/// Note that the base may have either vector or pointer to vector type, just
|
|
|
|
/// like a struct field reference.
|
|
|
|
///
|
|
|
|
class ExtVectorElementExpr : public Expr {
|
|
|
|
Stmt *Base;
|
|
|
|
IdentifierInfo *Accessor;
|
|
|
|
SourceLocation AccessorLoc;
|
|
|
|
public:
|
2011-02-20 13:06:31 +00:00
|
|
|
ExtVectorElementExpr(QualType ty, ExprValueKind VK, Expr *base,
|
|
|
|
IdentifierInfo &accessor, SourceLocation loc)
|
|
|
|
: Expr(ExtVectorElementExprClass, ty, VK,
|
|
|
|
(VK == VK_RValue ? OK_Ordinary : OK_VectorComponent),
|
|
|
|
base->isTypeDependent(), base->isValueDependent(),
|
2011-07-17 15:40:56 +00:00
|
|
|
base->isInstantiationDependent(),
|
2011-02-20 13:06:31 +00:00
|
|
|
base->containsUnexpandedParameterPack()),
|
2009-06-02 17:58:47 +00:00
|
|
|
Base(base), Accessor(&accessor), AccessorLoc(loc) {}
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
/// \brief Build an empty vector element expression.
|
|
|
|
explicit ExtVectorElementExpr(EmptyShell Empty)
|
|
|
|
: Expr(ExtVectorElementExprClass, Empty) { }
|
|
|
|
|
|
|
|
const Expr *getBase() const { return cast<Expr>(Base); }
|
|
|
|
Expr *getBase() { return cast<Expr>(Base); }
|
|
|
|
void setBase(Expr *E) { Base = E; }
|
|
|
|
|
|
|
|
IdentifierInfo &getAccessor() const { return *Accessor; }
|
|
|
|
void setAccessor(IdentifierInfo *II) { Accessor = II; }
|
|
|
|
|
|
|
|
SourceLocation getAccessorLoc() const { return AccessorLoc; }
|
|
|
|
void setAccessorLoc(SourceLocation L) { AccessorLoc = L; }
|
|
|
|
|
|
|
|
/// getNumElements - Get the number of components being selected.
|
|
|
|
unsigned getNumElements() const;
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
/// containsDuplicateElements - Return true if any element access is
|
|
|
|
/// repeated.
|
|
|
|
bool containsDuplicateElements() const;
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
/// getEncodedElementAccess - Encode the elements accessed into an llvm
|
|
|
|
/// aggregate Constant of ConstantInt(s).
|
2011-10-20 21:14:49 +00:00
|
|
|
void getEncodedElementAccess(SmallVectorImpl<unsigned> &Elts) const;
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2012-04-14 14:01:31 +00:00
|
|
|
SourceRange getSourceRange() const LLVM_READONLY {
|
2009-06-02 17:58:47 +00:00
|
|
|
return SourceRange(getBase()->getLocStart(), AccessorLoc);
|
|
|
|
}
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
/// isArrow - Return true if the base expression is a pointer to vector,
|
|
|
|
/// return false if the base expression is a vector.
|
|
|
|
bool isArrow() const;
|
2009-10-14 18:03:49 +00:00
|
|
|
|
|
|
|
static bool classof(const Stmt *T) {
|
|
|
|
return T->getStmtClass() == ExtVectorElementExprClass;
|
2009-06-02 17:58:47 +00:00
|
|
|
}
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
// Iterators
|
2011-02-20 13:06:31 +00:00
|
|
|
child_range children() { return child_range(&Base, &Base+1); }
|
2009-06-02 17:58:47 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/// BlockExpr - Adaptor class for mixing a BlockDecl with expressions.
|
|
|
|
/// ^{ statement-body } or ^(int arg1, float arg2){ statement-body }
|
|
|
|
class BlockExpr : public Expr {
|
|
|
|
protected:
|
|
|
|
BlockDecl *TheBlock;
|
|
|
|
public:
|
2011-02-20 13:06:31 +00:00
|
|
|
BlockExpr(BlockDecl *BD, QualType ty)
|
|
|
|
: Expr(BlockExprClass, ty, VK_RValue, OK_Ordinary,
|
2012-04-14 14:01:31 +00:00
|
|
|
ty->isDependentType(), ty->isDependentType(),
|
|
|
|
ty->isInstantiationDependentType() || BD->isDependentContext(),
|
2011-07-17 15:40:56 +00:00
|
|
|
false),
|
2011-02-20 13:06:31 +00:00
|
|
|
TheBlock(BD) {}
|
2009-06-02 17:58:47 +00:00
|
|
|
|
|
|
|
/// \brief Build an empty block expression.
|
|
|
|
explicit BlockExpr(EmptyShell Empty) : Expr(BlockExprClass, Empty) { }
|
|
|
|
|
|
|
|
const BlockDecl *getBlockDecl() const { return TheBlock; }
|
|
|
|
BlockDecl *getBlockDecl() { return TheBlock; }
|
|
|
|
void setBlockDecl(BlockDecl *BD) { TheBlock = BD; }
|
|
|
|
|
|
|
|
// Convenience functions for probing the underlying BlockDecl.
|
|
|
|
SourceLocation getCaretLocation() const;
|
|
|
|
const Stmt *getBody() const;
|
|
|
|
Stmt *getBody();
|
|
|
|
|
2012-04-14 14:01:31 +00:00
|
|
|
SourceRange getSourceRange() const LLVM_READONLY {
|
2009-06-02 17:58:47 +00:00
|
|
|
return SourceRange(getCaretLocation(), getBody()->getLocEnd());
|
|
|
|
}
|
|
|
|
|
|
|
|
/// getFunctionType - Return the underlying function type for this block.
|
2012-04-14 14:01:31 +00:00
|
|
|
const FunctionProtoType *getFunctionType() const;
|
2009-06-02 17:58:47 +00:00
|
|
|
|
2009-10-14 18:03:49 +00:00
|
|
|
static bool classof(const Stmt *T) {
|
2009-06-02 17:58:47 +00:00
|
|
|
return T->getStmtClass() == BlockExprClass;
|
|
|
|
}
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2009-06-02 17:58:47 +00:00
|
|
|
// Iterators
|
2011-02-20 13:06:31 +00:00
|
|
|
child_range children() { return child_range(); }
|
2009-06-02 17:58:47 +00:00
|
|
|
};
|
2009-10-14 18:03:49 +00:00
|
|
|
|
2011-06-12 15:46:16 +00:00
|
|
|
/// AsTypeExpr - Clang builtin function __builtin_astype [OpenCL 6.2.4.2]
|
|
|
|
/// This AST node provides support for reinterpreting a type to another
|
|
|
|
/// type of the same size.
|
2011-07-17 15:40:56 +00:00
|
|
|
class AsTypeExpr : public Expr { // Should this be an ExplicitCastExpr?
|
2011-06-12 15:46:16 +00:00
|
|
|
private:
|
2011-07-17 15:40:56 +00:00
|
|
|
Stmt *SrcExpr;
|
2011-06-12 15:46:16 +00:00
|
|
|
SourceLocation BuiltinLoc, RParenLoc;
|
2011-07-17 15:40:56 +00:00
|
|
|
|
|
|
|
friend class ASTReader;
|
|
|
|
friend class ASTStmtReader;
|
|
|
|
explicit AsTypeExpr(EmptyShell Empty) : Expr(AsTypeExprClass, Empty) {}
|
2012-04-14 14:01:31 +00:00
|
|
|
|
2011-06-12 15:46:16 +00:00
|
|
|
public:
|
|
|
|
AsTypeExpr(Expr* SrcExpr, QualType DstType,
|
|
|
|
ExprValueKind VK, ExprObjectKind OK,
|
|
|
|
SourceLocation BuiltinLoc, SourceLocation RParenLoc)
|
2012-04-14 14:01:31 +00:00
|
|
|
: Expr(AsTypeExprClass, DstType, VK, OK,
|
2011-07-17 15:40:56 +00:00
|
|
|
DstType->isDependentType(),
|
|
|
|
DstType->isDependentType() || SrcExpr->isValueDependent(),
|
|
|
|
(DstType->isInstantiationDependentType() ||
|
|
|
|
SrcExpr->isInstantiationDependent()),
|
|
|
|
(DstType->containsUnexpandedParameterPack() ||
|
|
|
|
SrcExpr->containsUnexpandedParameterPack())),
|
|
|
|
SrcExpr(SrcExpr), BuiltinLoc(BuiltinLoc), RParenLoc(RParenLoc) {}
|
2012-04-14 14:01:31 +00:00
|
|
|
|
2011-06-12 15:46:16 +00:00
|
|
|
/// getSrcExpr - Return the Expr to be converted.
|
2011-07-17 15:40:56 +00:00
|
|
|
Expr *getSrcExpr() const { return cast<Expr>(SrcExpr); }
|
|
|
|
|
|
|
|
/// getBuiltinLoc - Return the location of the __builtin_astype token.
|
|
|
|
SourceLocation getBuiltinLoc() const { return BuiltinLoc; }
|
|
|
|
|
|
|
|
/// getRParenLoc - Return the location of final right parenthesis.
|
|
|
|
SourceLocation getRParenLoc() const { return RParenLoc; }
|
2012-04-14 14:01:31 +00:00
|
|
|
|
|
|
|
SourceRange getSourceRange() const LLVM_READONLY {
|
2011-06-12 15:46:16 +00:00
|
|
|
return SourceRange(BuiltinLoc, RParenLoc);
|
|
|
|
}
|
2012-04-14 14:01:31 +00:00
|
|
|
|
2011-06-12 15:46:16 +00:00
|
|
|
static bool classof(const Stmt *T) {
|
2012-04-14 14:01:31 +00:00
|
|
|
return T->getStmtClass() == AsTypeExprClass;
|
2011-06-12 15:46:16 +00:00
|
|
|
}
|
2012-04-14 14:01:31 +00:00
|
|
|
|
2011-06-12 15:46:16 +00:00
|
|
|
// Iterators
|
2011-07-17 15:40:56 +00:00
|
|
|
child_range children() { return child_range(&SrcExpr, &SrcExpr+1); }
|
2011-06-12 15:46:16 +00:00
|
|
|
};
|
2011-10-20 21:14:49 +00:00
|
|
|
|
2012-04-14 14:01:31 +00:00
|
|
|
/// PseudoObjectExpr - An expression which accesses a pseudo-object
|
|
|
|
/// l-value. A pseudo-object is an abstract object, accesses to which
|
|
|
|
/// are translated to calls. The pseudo-object expression has a
|
|
|
|
/// syntactic form, which shows how the expression was actually
|
|
|
|
/// written in the source code, and a semantic form, which is a series
|
|
|
|
/// of expressions to be executed in order which detail how the
|
|
|
|
/// operation is actually evaluated. Optionally, one of the semantic
|
|
|
|
/// forms may also provide a result value for the expression.
|
|
|
|
///
|
|
|
|
/// If any of the semantic-form expressions is an OpaqueValueExpr,
|
|
|
|
/// that OVE is required to have a source expression, and it is bound
|
|
|
|
/// to the result of that source expression. Such OVEs may appear
|
|
|
|
/// only in subsequent semantic-form expressions and as
|
|
|
|
/// sub-expressions of the syntactic form.
|
|
|
|
///
|
|
|
|
/// PseudoObjectExpr should be used only when an operation can be
|
|
|
|
/// usefully described in terms of fairly simple rewrite rules on
|
|
|
|
/// objects and functions that are meant to be used by end-developers.
|
|
|
|
/// For example, under the Itanium ABI, dynamic casts are implemented
|
|
|
|
/// as a call to a runtime function called __dynamic_cast; using this
|
|
|
|
/// class to describe that would be inappropriate because that call is
|
|
|
|
/// not really part of the user-visible semantics, and instead the
|
|
|
|
/// cast is properly reflected in the AST and IR-generation has been
|
|
|
|
/// taught to generate the call as necessary. In contrast, an
|
|
|
|
/// Objective-C property access is semantically defined to be
|
|
|
|
/// equivalent to a particular message send, and this is very much
|
|
|
|
/// part of the user model. The name of this class encourages this
|
|
|
|
/// modelling design.
|
|
|
|
class PseudoObjectExpr : public Expr {
|
|
|
|
// PseudoObjectExprBits.NumSubExprs - The number of sub-expressions.
|
|
|
|
// Always at least two, because the first sub-expression is the
|
|
|
|
// syntactic form.
|
|
|
|
|
|
|
|
// PseudoObjectExprBits.ResultIndex - The index of the
|
|
|
|
// sub-expression holding the result. 0 means the result is void,
|
|
|
|
// which is unambiguous because it's the index of the syntactic
|
|
|
|
// form. Note that this is therefore 1 higher than the value passed
|
|
|
|
// in to Create, which is an index within the semantic forms.
|
|
|
|
// Note also that ASTStmtWriter assumes this encoding.
|
|
|
|
|
|
|
|
Expr **getSubExprsBuffer() { return reinterpret_cast<Expr**>(this + 1); }
|
|
|
|
const Expr * const *getSubExprsBuffer() const {
|
|
|
|
return reinterpret_cast<const Expr * const *>(this + 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
friend class ASTStmtReader;
|
|
|
|
|
|
|
|
PseudoObjectExpr(QualType type, ExprValueKind VK,
|
|
|
|
Expr *syntactic, ArrayRef<Expr*> semantic,
|
|
|
|
unsigned resultIndex);
|
|
|
|
|
|
|
|
PseudoObjectExpr(EmptyShell shell, unsigned numSemanticExprs);
|
|
|
|
|
|
|
|
unsigned getNumSubExprs() const {
|
|
|
|
return PseudoObjectExprBits.NumSubExprs;
|
|
|
|
}
|
|
|
|
|
|
|
|
public:
|
|
|
|
/// NoResult - A value for the result index indicating that there is
|
|
|
|
/// no semantic result.
|
|
|
|
enum { NoResult = ~0U };
|
|
|
|
|
|
|
|
static PseudoObjectExpr *Create(ASTContext &Context, Expr *syntactic,
|
|
|
|
ArrayRef<Expr*> semantic,
|
|
|
|
unsigned resultIndex);
|
|
|
|
|
|
|
|
static PseudoObjectExpr *Create(ASTContext &Context, EmptyShell shell,
|
|
|
|
unsigned numSemanticExprs);
|
|
|
|
|
|
|
|
/// Return the syntactic form of this expression, i.e. the
|
|
|
|
/// expression it actually looks like. Likely to be expressed in
|
|
|
|
/// terms of OpaqueValueExprs bound in the semantic form.
|
|
|
|
Expr *getSyntacticForm() { return getSubExprsBuffer()[0]; }
|
|
|
|
const Expr *getSyntacticForm() const { return getSubExprsBuffer()[0]; }
|
|
|
|
|
|
|
|
/// Return the index of the result-bearing expression into the semantics
|
|
|
|
/// expressions, or PseudoObjectExpr::NoResult if there is none.
|
|
|
|
unsigned getResultExprIndex() const {
|
|
|
|
if (PseudoObjectExprBits.ResultIndex == 0) return NoResult;
|
|
|
|
return PseudoObjectExprBits.ResultIndex - 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Return the result-bearing expression, or null if there is none.
|
|
|
|
Expr *getResultExpr() {
|
|
|
|
if (PseudoObjectExprBits.ResultIndex == 0)
|
|
|
|
return 0;
|
|
|
|
return getSubExprsBuffer()[PseudoObjectExprBits.ResultIndex];
|
|
|
|
}
|
|
|
|
const Expr *getResultExpr() const {
|
|
|
|
return const_cast<PseudoObjectExpr*>(this)->getResultExpr();
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned getNumSemanticExprs() const { return getNumSubExprs() - 1; }
|
|
|
|
|
|
|
|
typedef Expr * const *semantics_iterator;
|
|
|
|
typedef const Expr * const *const_semantics_iterator;
|
|
|
|
semantics_iterator semantics_begin() {
|
|
|
|
return getSubExprsBuffer() + 1;
|
|
|
|
}
|
|
|
|
const_semantics_iterator semantics_begin() const {
|
|
|
|
return getSubExprsBuffer() + 1;
|
|
|
|
}
|
|
|
|
semantics_iterator semantics_end() {
|
|
|
|
return getSubExprsBuffer() + getNumSubExprs();
|
|
|
|
}
|
|
|
|
const_semantics_iterator semantics_end() const {
|
|
|
|
return getSubExprsBuffer() + getNumSubExprs();
|
|
|
|
}
|
|
|
|
Expr *getSemanticExpr(unsigned index) {
|
|
|
|
assert(index + 1 < getNumSubExprs());
|
|
|
|
return getSubExprsBuffer()[index + 1];
|
|
|
|
}
|
|
|
|
const Expr *getSemanticExpr(unsigned index) const {
|
|
|
|
return const_cast<PseudoObjectExpr*>(this)->getSemanticExpr(index);
|
|
|
|
}
|
|
|
|
|
|
|
|
SourceLocation getExprLoc() const LLVM_READONLY {
|
|
|
|
return getSyntacticForm()->getExprLoc();
|
|
|
|
}
|
|
|
|
SourceRange getSourceRange() const LLVM_READONLY {
|
|
|
|
return getSyntacticForm()->getSourceRange();
|
|
|
|
}
|
|
|
|
|
|
|
|
child_range children() {
|
|
|
|
Stmt **cs = reinterpret_cast<Stmt**>(getSubExprsBuffer());
|
|
|
|
return child_range(cs, cs + getNumSubExprs());
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool classof(const Stmt *T) {
|
|
|
|
return T->getStmtClass() == PseudoObjectExprClass;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2011-10-20 21:14:49 +00:00
|
|
|
/// AtomicExpr - Variadic atomic builtins: __atomic_exchange, __atomic_fetch_*,
|
|
|
|
/// __atomic_load, __atomic_store, and __atomic_compare_exchange_*, for the
|
2012-04-14 14:01:31 +00:00
|
|
|
/// similarly-named C++11 instructions, and __c11 variants for <stdatomic.h>.
|
|
|
|
/// All of these instructions take one primary pointer and at least one memory
|
|
|
|
/// order.
|
2011-10-20 21:14:49 +00:00
|
|
|
class AtomicExpr : public Expr {
|
|
|
|
public:
|
2012-04-14 14:01:31 +00:00
|
|
|
enum AtomicOp {
|
|
|
|
#define BUILTIN(ID, TYPE, ATTRS)
|
|
|
|
#define ATOMIC_BUILTIN(ID, TYPE, ATTRS) AO ## ID,
|
|
|
|
#include "clang/Basic/Builtins.def"
|
|
|
|
// Avoid trailing comma
|
|
|
|
BI_First = 0
|
|
|
|
};
|
|
|
|
|
2011-10-20 21:14:49 +00:00
|
|
|
private:
|
2012-04-14 14:01:31 +00:00
|
|
|
enum { PTR, ORDER, VAL1, ORDER_FAIL, VAL2, WEAK, END_EXPR };
|
2011-10-20 21:14:49 +00:00
|
|
|
Stmt* SubExprs[END_EXPR];
|
|
|
|
unsigned NumSubExprs;
|
|
|
|
SourceLocation BuiltinLoc, RParenLoc;
|
|
|
|
AtomicOp Op;
|
|
|
|
|
2012-04-14 14:01:31 +00:00
|
|
|
friend class ASTStmtReader;
|
|
|
|
|
2011-10-20 21:14:49 +00:00
|
|
|
public:
|
2012-12-02 13:20:44 +00:00
|
|
|
AtomicExpr(SourceLocation BLoc, ArrayRef<Expr*> args, QualType t,
|
2011-10-20 21:14:49 +00:00
|
|
|
AtomicOp op, SourceLocation RP);
|
|
|
|
|
2012-04-14 14:01:31 +00:00
|
|
|
/// \brief Determine the number of arguments the specified atomic builtin
|
|
|
|
/// should have.
|
|
|
|
static unsigned getNumSubExprs(AtomicOp Op);
|
|
|
|
|
2011-10-20 21:14:49 +00:00
|
|
|
/// \brief Build an empty AtomicExpr.
|
|
|
|
explicit AtomicExpr(EmptyShell Empty) : Expr(AtomicExprClass, Empty) { }
|
|
|
|
|
|
|
|
Expr *getPtr() const {
|
|
|
|
return cast<Expr>(SubExprs[PTR]);
|
|
|
|
}
|
|
|
|
Expr *getOrder() const {
|
|
|
|
return cast<Expr>(SubExprs[ORDER]);
|
|
|
|
}
|
|
|
|
Expr *getVal1() const {
|
2012-04-14 14:01:31 +00:00
|
|
|
if (Op == AO__c11_atomic_init)
|
|
|
|
return cast<Expr>(SubExprs[ORDER]);
|
|
|
|
assert(NumSubExprs > VAL1);
|
2011-10-20 21:14:49 +00:00
|
|
|
return cast<Expr>(SubExprs[VAL1]);
|
|
|
|
}
|
|
|
|
Expr *getOrderFail() const {
|
2012-04-14 14:01:31 +00:00
|
|
|
assert(NumSubExprs > ORDER_FAIL);
|
2011-10-20 21:14:49 +00:00
|
|
|
return cast<Expr>(SubExprs[ORDER_FAIL]);
|
|
|
|
}
|
|
|
|
Expr *getVal2() const {
|
2012-04-14 14:01:31 +00:00
|
|
|
if (Op == AO__atomic_exchange)
|
|
|
|
return cast<Expr>(SubExprs[ORDER_FAIL]);
|
|
|
|
assert(NumSubExprs > VAL2);
|
2011-10-20 21:14:49 +00:00
|
|
|
return cast<Expr>(SubExprs[VAL2]);
|
|
|
|
}
|
2012-04-14 14:01:31 +00:00
|
|
|
Expr *getWeak() const {
|
|
|
|
assert(NumSubExprs > WEAK);
|
|
|
|
return cast<Expr>(SubExprs[WEAK]);
|
2011-10-20 21:14:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
AtomicOp getOp() const { return Op; }
|
|
|
|
unsigned getNumSubExprs() { return NumSubExprs; }
|
|
|
|
|
|
|
|
Expr **getSubExprs() { return reinterpret_cast<Expr **>(SubExprs); }
|
|
|
|
|
|
|
|
bool isVolatile() const {
|
|
|
|
return getPtr()->getType()->getPointeeType().isVolatileQualified();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool isCmpXChg() const {
|
2012-04-14 14:01:31 +00:00
|
|
|
return getOp() == AO__c11_atomic_compare_exchange_strong ||
|
|
|
|
getOp() == AO__c11_atomic_compare_exchange_weak ||
|
|
|
|
getOp() == AO__atomic_compare_exchange ||
|
|
|
|
getOp() == AO__atomic_compare_exchange_n;
|
2011-10-20 21:14:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
SourceLocation getBuiltinLoc() const { return BuiltinLoc; }
|
|
|
|
SourceLocation getRParenLoc() const { return RParenLoc; }
|
|
|
|
|
2012-04-14 14:01:31 +00:00
|
|
|
SourceRange getSourceRange() const LLVM_READONLY {
|
2011-10-20 21:14:49 +00:00
|
|
|
return SourceRange(BuiltinLoc, RParenLoc);
|
|
|
|
}
|
|
|
|
static bool classof(const Stmt *T) {
|
|
|
|
return T->getStmtClass() == AtomicExprClass;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Iterators
|
|
|
|
child_range children() {
|
|
|
|
return child_range(SubExprs, SubExprs+NumSubExprs);
|
|
|
|
}
|
|
|
|
};
|
2009-06-02 17:58:47 +00:00
|
|
|
} // end namespace clang
|
|
|
|
|
|
|
|
#endif
|