[PATCH] D14480: Improve running time of getAsmSrcLocInfo
Rafael EspĂndola via llvm-commits
llvm-commits at lists.llvm.org
Mon Nov 16 18:45:39 PST 2015
There is something strange with your git-clang-format setup. This is
what I get locally.
Cheers,
Rafael
On 17 November 2015 at 09:34, Yunlian Jiang <yunlian at google.com> wrote:
> yunlian added inline comments.
>
> ================
> Comment at: lib/AST/Expr.cpp:1030
> @@ +1029,3 @@
> + unsigned StringOffset = 0;
> + if (StartToken) TokNo = *StartToken;
> + if (StartTokenByteOffset) {
> ----------------
> yunlian wrote:
>> rafael wrote:
>> > This part also needs git-clang-format..
>> Which part? Could you please give me some advice on how to modify it?
>> Thanks
>> I run git clang-format and it says clang-format did not modify any files.
>>
> For this line:
> if (StartToken) TokNo = *StartToken;
>
> I try to make it like
> if (StartToken)
> TokNo = *StartToken;
>
> Bug git clang-format changes it back.
>
>
> http://reviews.llvm.org/D14480
>
>
>
-------------- next part --------------
diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h
index e3c17e0..9f066fe 100644
--- a/include/clang/AST/Expr.h
+++ b/include/clang/AST/Expr.h
@@ -1,4988 +1,4990 @@
//===--- Expr.h - Classes for representing expressions ----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the Expr interface and subclasses.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_EXPR_H
#define LLVM_CLANG_AST_EXPR_H
#include "clang/AST/APValue.h"
#include "clang/AST/ASTVector.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclAccessPair.h"
#include "clang/AST/OperationKinds.h"
#include "clang/AST/Stmt.h"
#include "clang/AST/TemplateBase.h"
#include "clang/AST/Type.h"
#include "clang/Basic/CharInfo.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/TypeTraits.h"
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Compiler.h"
namespace clang {
class APValue;
class ASTContext;
class BlockDecl;
class CXXBaseSpecifier;
class CXXMemberCallExpr;
class CXXOperatorCallExpr;
class CastExpr;
class Decl;
class IdentifierInfo;
class MaterializeTemporaryExpr;
class NamedDecl;
class ObjCPropertyRefExpr;
class OpaqueValueExpr;
class ParmVarDecl;
class StringLiteral;
class TargetInfo;
class ValueDecl;
/// \brief A simple array of base specifiers.
typedef SmallVector<CXXBaseSpecifier*, 4> CXXCastPath;
/// \brief An adjustment to be made to the temporary created when emitting a
/// reference binding, which accesses a particular subobject of that temporary.
struct SubobjectAdjustment {
enum {
DerivedToBaseAdjustment,
FieldAdjustment,
MemberPointerAdjustment
} Kind;
struct DTB {
const CastExpr *BasePath;
const CXXRecordDecl *DerivedClass;
};
struct P {
const MemberPointerType *MPT;
Expr *RHS;
};
union {
struct DTB DerivedToBase;
FieldDecl *Field;
struct P Ptr;
};
SubobjectAdjustment(const CastExpr *BasePath,
const CXXRecordDecl *DerivedClass)
: Kind(DerivedToBaseAdjustment) {
DerivedToBase.BasePath = BasePath;
DerivedToBase.DerivedClass = DerivedClass;
}
SubobjectAdjustment(FieldDecl *Field)
: Kind(FieldAdjustment) {
this->Field = Field;
}
SubobjectAdjustment(const MemberPointerType *MPT, Expr *RHS)
: Kind(MemberPointerAdjustment) {
this->Ptr.MPT = MPT;
this->Ptr.RHS = RHS;
}
};
/// Expr - This represents one expression. Note that Expr's are subclasses of
/// Stmt. This allows an expression to be transparently used any place a Stmt
/// is required.
///
class Expr : public Stmt {
QualType TR;
protected:
Expr(StmtClass SC, QualType T, ExprValueKind VK, ExprObjectKind OK,
bool TD, bool VD, bool ID, bool ContainsUnexpandedParameterPack)
: Stmt(SC)
{
ExprBits.TypeDependent = TD;
ExprBits.ValueDependent = VD;
ExprBits.InstantiationDependent = ID;
ExprBits.ValueKind = VK;
ExprBits.ObjectKind = OK;
ExprBits.ContainsUnexpandedParameterPack = ContainsUnexpandedParameterPack;
setType(T);
}
/// \brief Construct an empty expression.
explicit Expr(StmtClass SC, EmptyShell) : Stmt(SC) { }
public:
QualType getType() const { return TR; }
void setType(QualType t) {
// In C++, the type of an expression is always adjusted so that it
// will not have reference type (C++ [expr]p6). Use
// QualType::getNonReferenceType() to retrieve the non-reference
// type. Additionally, inspect Expr::isLvalue to determine whether
// an expression that is adjusted in this manner should be
// considered an lvalue.
assert((t.isNull() || !t->isReferenceType()) &&
"Expressions can't have reference type");
TR = t;
}
/// isValueDependent - Determines whether this expression is
/// value-dependent (C++ [temp.dep.constexpr]). For example, the
/// array bound of "Chars" in the following example is
/// value-dependent.
/// @code
/// template<int Size, char (&Chars)[Size]> struct meta_string;
/// @endcode
bool isValueDependent() const { return ExprBits.ValueDependent; }
/// \brief Set whether this expression is value-dependent or not.
void setValueDependent(bool VD) {
ExprBits.ValueDependent = VD;
}
/// isTypeDependent - Determines whether this expression is
/// type-dependent (C++ [temp.dep.expr]), which means that its type
/// could change from one template instantiation to the next. For
/// example, the expressions "x" and "x + y" are type-dependent in
/// the following code, but "y" is not type-dependent:
/// @code
/// template<typename T>
/// void add(T x, int y) {
/// x + y;
/// }
/// @endcode
bool isTypeDependent() const { return ExprBits.TypeDependent; }
/// \brief Set whether this expression is type-dependent or not.
void setTypeDependent(bool TD) {
ExprBits.TypeDependent = TD;
}
/// \brief Whether this expression is instantiation-dependent, meaning that
/// it depends in some way on a template parameter, even if neither its type
/// nor (constant) value can change due to the template instantiation.
///
/// In the following example, the expression \c sizeof(sizeof(T() + T())) is
/// instantiation-dependent (since it involves a template parameter \c T), but
/// is neither type- nor value-dependent, since the type of the inner
/// \c sizeof is known (\c std::size_t) and therefore the size of the outer
/// \c sizeof is known.
///
/// \code
/// template<typename T>
/// void f(T x, T y) {
/// sizeof(sizeof(T() + T());
/// }
/// \endcode
///
bool isInstantiationDependent() const {
return ExprBits.InstantiationDependent;
}
/// \brief Set whether this expression is instantiation-dependent or not.
void setInstantiationDependent(bool ID) {
ExprBits.InstantiationDependent = ID;
}
/// \brief Whether this expression contains an unexpanded parameter
/// pack (for C++11 variadic templates).
///
/// Given the following function template:
///
/// \code
/// template<typename F, typename ...Types>
/// void forward(const F &f, Types &&...args) {
/// f(static_cast<Types&&>(args)...);
/// }
/// \endcode
///
/// The expressions \c args and \c static_cast<Types&&>(args) both
/// contain parameter packs.
bool containsUnexpandedParameterPack() const {
return ExprBits.ContainsUnexpandedParameterPack;
}
/// \brief Set the bit that describes whether this expression
/// contains an unexpanded parameter pack.
void setContainsUnexpandedParameterPack(bool PP = true) {
ExprBits.ContainsUnexpandedParameterPack = PP;
}
/// getExprLoc - Return the preferred location for the arrow when diagnosing
/// a problem with a generic expression.
SourceLocation getExprLoc() const LLVM_READONLY;
/// isUnusedResultAWarning - Return true if this immediate expression should
/// be warned about if the result is unused. If so, fill in expr, location,
/// and ranges with expr to warn on and source locations/ranges appropriate
/// for a warning.
bool isUnusedResultAWarning(const Expr *&WarnExpr, SourceLocation &Loc,
SourceRange &R1, SourceRange &R2,
ASTContext &Ctx) const;
/// isLValue - True if this expression is an "l-value" according to
/// the rules of the current language. C and C++ give somewhat
/// different rules for this concept, but in general, the result of
/// an l-value expression identifies a specific object whereas the
/// result of an r-value expression is a value detached from any
/// specific storage.
///
/// C++11 divides the concept of "r-value" into pure r-values
/// ("pr-values") and so-called expiring values ("x-values"), which
/// identify specific objects that can be safely cannibalized for
/// their resources. This is an unfortunate abuse of terminology on
/// the part of the C++ committee. In Clang, when we say "r-value",
/// we generally mean a pr-value.
bool isLValue() const { return getValueKind() == VK_LValue; }
bool isRValue() const { return getValueKind() == VK_RValue; }
bool isXValue() const { return getValueKind() == VK_XValue; }
bool isGLValue() const { return getValueKind() != VK_RValue; }
enum LValueClassification {
LV_Valid,
LV_NotObjectType,
LV_IncompleteVoidType,
LV_DuplicateVectorComponents,
LV_InvalidExpression,
LV_InvalidMessageExpression,
LV_MemberFunction,
LV_SubObjCPropertySetting,
LV_ClassTemporary,
LV_ArrayTemporary
};
/// Reasons why an expression might not be an l-value.
LValueClassification ClassifyLValue(ASTContext &Ctx) const;
enum isModifiableLvalueResult {
MLV_Valid,
MLV_NotObjectType,
MLV_IncompleteVoidType,
MLV_DuplicateVectorComponents,
MLV_InvalidExpression,
MLV_LValueCast, // Specialized form of MLV_InvalidExpression.
MLV_IncompleteType,
MLV_ConstQualified,
MLV_ConstAddrSpace,
MLV_ArrayType,
MLV_NoSetterProperty,
MLV_MemberFunction,
MLV_SubObjCPropertySetting,
MLV_InvalidMessageExpression,
MLV_ClassTemporary,
MLV_ArrayTemporary
};
/// isModifiableLvalue - C99 6.3.2.1: an lvalue that does not have array type,
/// does not have an incomplete type, does not have a const-qualified type,
/// and if it is a structure or union, does not have any member (including,
/// recursively, any member or element of all contained aggregates or unions)
/// with a const-qualified type.
///
/// \param Loc [in,out] - A source location which *may* be filled
/// in with the location of the expression making this a
/// non-modifiable lvalue, if specified.
isModifiableLvalueResult
isModifiableLvalue(ASTContext &Ctx, SourceLocation *Loc = nullptr) const;
/// \brief The return type of classify(). Represents the C++11 expression
/// taxonomy.
class Classification {
public:
/// \brief The various classification results. Most of these mean prvalue.
enum Kinds {
CL_LValue,
CL_XValue,
CL_Function, // Functions cannot be lvalues in C.
CL_Void, // Void cannot be an lvalue in C.
CL_AddressableVoid, // Void expression whose address can be taken in C.
CL_DuplicateVectorComponents, // A vector shuffle with dupes.
CL_MemberFunction, // An expression referring to a member function
CL_SubObjCPropertySetting,
CL_ClassTemporary, // A temporary of class type, or subobject thereof.
CL_ArrayTemporary, // A temporary of array type.
CL_ObjCMessageRValue, // ObjC message is an rvalue
CL_PRValue // A prvalue for any other reason, of any other type
};
/// \brief The results of modification testing.
enum ModifiableType {
CM_Untested, // testModifiable was false.
CM_Modifiable,
CM_RValue, // Not modifiable because it's an rvalue
CM_Function, // Not modifiable because it's a function; C++ only
CM_LValueCast, // Same as CM_RValue, but indicates GCC cast-as-lvalue ext
CM_NoSetterProperty,// Implicit assignment to ObjC property without setter
CM_ConstQualified,
CM_ConstAddrSpace,
CM_ArrayType,
CM_IncompleteType
};
private:
friend class Expr;
unsigned short Kind;
unsigned short Modifiable;
explicit Classification(Kinds k, ModifiableType m)
: Kind(k), Modifiable(m)
{}
public:
Classification() {}
Kinds getKind() const { return static_cast<Kinds>(Kind); }
ModifiableType getModifiable() const {
assert(Modifiable != CM_Untested && "Did not test for modifiability.");
return static_cast<ModifiableType>(Modifiable);
}
bool isLValue() const { return Kind == CL_LValue; }
bool isXValue() const { return Kind == CL_XValue; }
bool isGLValue() const { return Kind <= CL_XValue; }
bool isPRValue() const { return Kind >= CL_Function; }
bool isRValue() const { return Kind >= CL_XValue; }
bool isModifiable() const { return getModifiable() == CM_Modifiable; }
/// \brief Create a simple, modifiably lvalue
static Classification makeSimpleLValue() {
return Classification(CL_LValue, CM_Modifiable);
}
};
/// \brief Classify - Classify this expression according to the C++11
/// expression taxonomy.
///
/// C++11 defines ([basic.lval]) a new taxonomy of expressions to replace the
/// old lvalue vs rvalue. This function determines the type of expression this
/// is. There are three expression types:
/// - lvalues are classical lvalues as in C++03.
/// - prvalues are equivalent to rvalues in C++03.
/// - xvalues are expressions yielding unnamed rvalue references, e.g. a
/// function returning an rvalue reference.
/// lvalues and xvalues are collectively referred to as glvalues, while
/// prvalues and xvalues together form rvalues.
Classification Classify(ASTContext &Ctx) const {
return ClassifyImpl(Ctx, nullptr);
}
/// \brief ClassifyModifiable - Classify this expression according to the
/// C++11 expression taxonomy, and see if it is valid on the left side
/// of an assignment.
///
/// This function extends classify in that it also tests whether the
/// expression is modifiable (C99 6.3.2.1p1).
/// \param Loc A source location that might be filled with a relevant location
/// if the expression is not modifiable.
Classification ClassifyModifiable(ASTContext &Ctx, SourceLocation &Loc) const{
return ClassifyImpl(Ctx, &Loc);
}
/// getValueKindForType - Given a formal return or parameter type,
/// give its value kind.
static ExprValueKind getValueKindForType(QualType T) {
if (const ReferenceType *RT = T->getAs<ReferenceType>())
return (isa<LValueReferenceType>(RT)
? VK_LValue
: (RT->getPointeeType()->isFunctionType()
? VK_LValue : VK_XValue));
return VK_RValue;
}
/// getValueKind - The value kind that this expression produces.
ExprValueKind getValueKind() const {
return static_cast<ExprValueKind>(ExprBits.ValueKind);
}
/// getObjectKind - The object kind that this expression produces.
/// Object kinds are meaningful only for expressions that yield an
/// l-value or x-value.
ExprObjectKind getObjectKind() const {
return static_cast<ExprObjectKind>(ExprBits.ObjectKind);
}
bool isOrdinaryOrBitFieldObject() const {
ExprObjectKind OK = getObjectKind();
return (OK == OK_Ordinary || OK == OK_BitField);
}
/// setValueKind - Set the value kind produced by this expression.
void setValueKind(ExprValueKind Cat) { ExprBits.ValueKind = Cat; }
/// setObjectKind - Set the object kind produced by this expression.
void setObjectKind(ExprObjectKind Cat) { ExprBits.ObjectKind = Cat; }
private:
Classification ClassifyImpl(ASTContext &Ctx, SourceLocation *Loc) const;
public:
/// \brief Returns true if this expression is a gl-value that
/// potentially refers to a bit-field.
///
/// In C++, whether a gl-value refers to a bitfield is essentially
/// an aspect of the value-kind type system.
bool refersToBitField() const { return getObjectKind() == OK_BitField; }
/// \brief If this expression refers to a bit-field, retrieve the
/// declaration of that bit-field.
///
/// Note that this returns a non-null pointer in subtly different
/// places than refersToBitField returns true. In particular, this can
/// return a non-null pointer even for r-values loaded from
/// bit-fields, but it will return null for a conditional bit-field.
FieldDecl *getSourceBitField();
const FieldDecl *getSourceBitField() const {
return const_cast<Expr*>(this)->getSourceBitField();
}
/// \brief If this expression is an l-value for an Objective C
/// property, find the underlying property reference expression.
const ObjCPropertyRefExpr *getObjCProperty() const;
/// \brief Check if this expression is the ObjC 'self' implicit parameter.
bool isObjCSelfExpr() const;
/// \brief Returns whether this expression refers to a vector element.
bool refersToVectorElement() const;
/// \brief Returns whether this expression refers to a global register
/// variable.
bool refersToGlobalRegisterVar() const;
/// \brief Returns whether this expression has a placeholder type.
bool hasPlaceholderType() const {
return getType()->isPlaceholderType();
}
/// \brief Returns whether this expression has a specific placeholder type.
bool hasPlaceholderType(BuiltinType::Kind K) const {
assert(BuiltinType::isPlaceholderTypeKind(K));
if (const BuiltinType *BT = dyn_cast<BuiltinType>(getType()))
return BT->getKind() == K;
return false;
}
/// isKnownToHaveBooleanValue - Return true if this is an integer expression
/// that is known to return 0 or 1. This happens for _Bool/bool expressions
/// but also int expressions which are produced by things like comparisons in
/// C.
bool isKnownToHaveBooleanValue() const;
/// isIntegerConstantExpr - Return true if this expression is a valid integer
/// constant expression, and, if so, return its value in Result. If not a
/// valid i-c-e, return false and fill in Loc (if specified) with the location
/// of the invalid expression.
///
/// Note: This does not perform the implicit conversions required by C++11
/// [expr.const]p5.
bool isIntegerConstantExpr(llvm::APSInt &Result, const ASTContext &Ctx,
SourceLocation *Loc = nullptr,
bool isEvaluated = true) const;
bool isIntegerConstantExpr(const ASTContext &Ctx,
SourceLocation *Loc = nullptr) const;
/// isCXX98IntegralConstantExpr - Return true if this expression is an
/// integral constant expression in C++98. Can only be used in C++.
bool isCXX98IntegralConstantExpr(const ASTContext &Ctx) const;
/// isCXX11ConstantExpr - Return true if this expression is a constant
/// expression in C++11. Can only be used in C++.
///
/// Note: This does not perform the implicit conversions required by C++11
/// [expr.const]p5.
bool isCXX11ConstantExpr(const ASTContext &Ctx, APValue *Result = nullptr,
SourceLocation *Loc = nullptr) const;
/// isPotentialConstantExpr - Return true if this function's definition
/// might be usable in a constant expression in C++11, if it were marked
/// constexpr. Return false if the function can never produce a constant
/// expression, along with diagnostics describing why not.
static bool isPotentialConstantExpr(const FunctionDecl *FD,
SmallVectorImpl<
PartialDiagnosticAt> &Diags);
/// isPotentialConstantExprUnevaluted - Return true if this expression might
/// be usable in a constant expression in C++11 in an unevaluated context, if
/// it were in function FD marked constexpr. Return false if the function can
/// never produce a constant expression, along with diagnostics describing
/// why not.
static bool isPotentialConstantExprUnevaluated(Expr *E,
const FunctionDecl *FD,
SmallVectorImpl<
PartialDiagnosticAt> &Diags);
/// isConstantInitializer - Returns true if this expression can be emitted to
/// IR as a constant, and thus can be used as a constant initializer in C.
/// If this expression is not constant and Culprit is non-null,
/// it is used to store the address of first non constant expr.
bool isConstantInitializer(ASTContext &Ctx, bool ForRef,
const Expr **Culprit = nullptr) const;
/// EvalStatus is a struct with detailed info about an evaluation in progress.
struct EvalStatus {
/// HasSideEffects - Whether the evaluated expression has side effects.
/// For example, (f() && 0) can be folded, but it still has side effects.
bool HasSideEffects;
/// Diag - If this is non-null, it will be filled in with a stack of notes
/// indicating why evaluation failed (or why it failed to produce a constant
/// expression).
/// If the expression is unfoldable, the notes will indicate why it's not
/// foldable. If the expression is foldable, but not a constant expression,
/// the notes will describes why it isn't a constant expression. If the
/// expression *is* a constant expression, no notes will be produced.
SmallVectorImpl<PartialDiagnosticAt> *Diag;
EvalStatus() : HasSideEffects(false), Diag(nullptr) {}
// hasSideEffects - Return true if the evaluated expression has
// side effects.
bool hasSideEffects() const {
return HasSideEffects;
}
};
/// EvalResult is a struct with detailed info about an evaluated expression.
struct EvalResult : EvalStatus {
/// Val - This is the value the expression can be folded to.
APValue Val;
// isGlobalLValue - Return true if the evaluated lvalue expression
// is global.
bool isGlobalLValue() const;
};
/// EvaluateAsRValue - Return true if this is a constant which we can fold to
/// an rvalue using any crazy technique (that has nothing to do with language
/// standards) that we want to, even if the expression has side-effects. If
/// this function returns true, it returns the folded constant in Result. If
/// the expression is a glvalue, an lvalue-to-rvalue conversion will be
/// applied.
bool EvaluateAsRValue(EvalResult &Result, const ASTContext &Ctx) const;
/// EvaluateAsBooleanCondition - Return true if this is a constant
/// which we we can fold and convert to a boolean condition using
/// any crazy technique that we want to, even if the expression has
/// side-effects.
bool EvaluateAsBooleanCondition(bool &Result, const ASTContext &Ctx) const;
enum SideEffectsKind { SE_NoSideEffects, SE_AllowSideEffects };
/// EvaluateAsInt - Return true if this is a constant which we can fold and
/// convert to an integer, using any crazy technique that we want to.
bool EvaluateAsInt(llvm::APSInt &Result, const ASTContext &Ctx,
SideEffectsKind AllowSideEffects = SE_NoSideEffects) const;
/// isEvaluatable - Call EvaluateAsRValue to see if this expression can be
/// constant folded without side-effects, but discard the result.
bool isEvaluatable(const ASTContext &Ctx) const;
/// HasSideEffects - This routine returns true for all those expressions
/// which have any effect other than producing a value. Example is a function
/// call, volatile variable read, or throwing an exception. If
/// IncludePossibleEffects is false, this call treats certain expressions with
/// potential side effects (such as function call-like expressions,
/// instantiation-dependent expressions, or invocations from a macro) as not
/// having side effects.
bool HasSideEffects(const ASTContext &Ctx,
bool IncludePossibleEffects = true) const;
/// \brief Determine whether this expression involves a call to any function
/// that is not trivial.
bool hasNonTrivialCall(const ASTContext &Ctx) const;
/// EvaluateKnownConstInt - Call EvaluateAsRValue and return the folded
/// integer. This must be called on an expression that constant folds to an
/// integer.
llvm::APSInt EvaluateKnownConstInt(const ASTContext &Ctx,
SmallVectorImpl<PartialDiagnosticAt> *Diag = nullptr) const;
void EvaluateForOverflow(const ASTContext &Ctx) const;
/// EvaluateAsLValue - Evaluate an expression to see if we can fold it to an
/// lvalue with link time known address, with no side-effects.
bool EvaluateAsLValue(EvalResult &Result, const ASTContext &Ctx) const;
/// EvaluateAsInitializer - Evaluate an expression as if it were the
/// initializer of the given declaration. Returns true if the initializer
/// can be folded to a constant, and produces any relevant notes. In C++11,
/// notes will be produced if the expression is not a constant expression.
bool EvaluateAsInitializer(APValue &Result, const ASTContext &Ctx,
const VarDecl *VD,
SmallVectorImpl<PartialDiagnosticAt> &Notes) const;
/// EvaluateWithSubstitution - Evaluate an expression as if from the context
/// of a call to the given function with the given arguments, inside an
/// unevaluated context. Returns true if the expression could be folded to a
/// constant.
bool EvaluateWithSubstitution(APValue &Value, ASTContext &Ctx,
const FunctionDecl *Callee,
ArrayRef<const Expr*> Args) const;
/// \brief Enumeration used to describe the kind of Null pointer constant
/// returned from \c isNullPointerConstant().
enum NullPointerConstantKind {
/// \brief Expression is not a Null pointer constant.
NPCK_NotNull = 0,
/// \brief Expression is a Null pointer constant built from a zero integer
/// expression that is not a simple, possibly parenthesized, zero literal.
/// C++ Core Issue 903 will classify these expressions as "not pointers"
/// once it is adopted.
/// http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#903
NPCK_ZeroExpression,
/// \brief Expression is a Null pointer constant built from a literal zero.
NPCK_ZeroLiteral,
/// \brief Expression is a C++11 nullptr.
NPCK_CXX11_nullptr,
/// \brief Expression is a GNU-style __null constant.
NPCK_GNUNull
};
/// \brief Enumeration used to describe how \c isNullPointerConstant()
/// should cope with value-dependent expressions.
enum NullPointerConstantValueDependence {
/// \brief Specifies that the expression should never be value-dependent.
NPC_NeverValueDependent = 0,
/// \brief Specifies that a value-dependent expression of integral or
/// dependent type should be considered a null pointer constant.
NPC_ValueDependentIsNull,
/// \brief Specifies that a value-dependent expression should be considered
/// to never be a null pointer constant.
NPC_ValueDependentIsNotNull
};
/// isNullPointerConstant - C99 6.3.2.3p3 - Test if this reduces down to
/// a Null pointer constant. The return value can further distinguish the
/// kind of NULL pointer constant that was detected.
NullPointerConstantKind isNullPointerConstant(
ASTContext &Ctx,
NullPointerConstantValueDependence NPC) const;
/// isOBJCGCCandidate - Return true if this expression may be used in a read/
/// write barrier.
bool isOBJCGCCandidate(ASTContext &Ctx) const;
/// \brief Returns true if this expression is a bound member function.
bool isBoundMemberFunction(ASTContext &Ctx) const;
/// \brief Given an expression of bound-member type, find the type
/// of the member. Returns null if this is an *overloaded* bound
/// member expression.
static QualType findBoundMemberType(const Expr *expr);
/// IgnoreImpCasts - Skip past any implicit casts which might
/// surround this expression. Only skips ImplicitCastExprs.
Expr *IgnoreImpCasts() LLVM_READONLY;
/// IgnoreImplicit - Skip past any implicit AST nodes which might
/// surround this expression.
Expr *IgnoreImplicit() LLVM_READONLY {
return cast<Expr>(Stmt::IgnoreImplicit());
}
const Expr *IgnoreImplicit() const LLVM_READONLY {
return const_cast<Expr*>(this)->IgnoreImplicit();
}
/// IgnoreParens - Ignore parentheses. If this Expr is a ParenExpr, return
/// its subexpression. If that subexpression is also a ParenExpr,
/// then this method recursively returns its subexpression, and so forth.
/// Otherwise, the method returns the current Expr.
Expr *IgnoreParens() LLVM_READONLY;
/// IgnoreParenCasts - Ignore parentheses and casts. Strip off any ParenExpr
/// or CastExprs, returning their operand.
Expr *IgnoreParenCasts() LLVM_READONLY;
/// Ignore casts. Strip off any CastExprs, returning their operand.
Expr *IgnoreCasts() LLVM_READONLY;
/// IgnoreParenImpCasts - Ignore parentheses and implicit casts. Strip off
/// any ParenExpr or ImplicitCastExprs, returning their operand.
Expr *IgnoreParenImpCasts() LLVM_READONLY;
/// IgnoreConversionOperator - Ignore conversion operator. If this Expr is a
/// call to a conversion operator, return the argument.
Expr *IgnoreConversionOperator() LLVM_READONLY;
const Expr *IgnoreConversionOperator() const LLVM_READONLY {
return const_cast<Expr*>(this)->IgnoreConversionOperator();
}
const Expr *IgnoreParenImpCasts() const LLVM_READONLY {
return const_cast<Expr*>(this)->IgnoreParenImpCasts();
}
/// Ignore parentheses and lvalue casts. Strip off any ParenExpr and
/// CastExprs that represent lvalue casts, returning their operand.
Expr *IgnoreParenLValueCasts() LLVM_READONLY;
const Expr *IgnoreParenLValueCasts() const LLVM_READONLY {
return const_cast<Expr*>(this)->IgnoreParenLValueCasts();
}
/// IgnoreParenNoopCasts - Ignore parentheses and casts that do not change the
/// value (including ptr->int casts of the same size). Strip off any
/// ParenExpr or CastExprs, returning their operand.
Expr *IgnoreParenNoopCasts(ASTContext &Ctx) LLVM_READONLY;
/// Ignore parentheses and derived-to-base casts.
Expr *ignoreParenBaseCasts() LLVM_READONLY;
const Expr *ignoreParenBaseCasts() const LLVM_READONLY {
return const_cast<Expr*>(this)->ignoreParenBaseCasts();
}
/// \brief Determine whether this expression is a default function argument.
///
/// Default arguments are implicitly generated in the abstract syntax tree
/// by semantic analysis for function calls, object constructions, etc. in
/// C++. Default arguments are represented by \c CXXDefaultArgExpr nodes;
/// this routine also looks through any implicit casts to determine whether
/// the expression is a default argument.
bool isDefaultArgument() const;
/// \brief Determine whether the result of this expression is a
/// temporary object of the given class type.
bool isTemporaryObject(ASTContext &Ctx, const CXXRecordDecl *TempTy) const;
/// \brief Whether this expression is an implicit reference to 'this' in C++.
bool isImplicitCXXThis() const;
const Expr *IgnoreImpCasts() const LLVM_READONLY {
return const_cast<Expr*>(this)->IgnoreImpCasts();
}
const Expr *IgnoreParens() const LLVM_READONLY {
return const_cast<Expr*>(this)->IgnoreParens();
}
const Expr *IgnoreParenCasts() const LLVM_READONLY {
return const_cast<Expr*>(this)->IgnoreParenCasts();
}
/// Strip off casts, but keep parentheses.
const Expr *IgnoreCasts() const LLVM_READONLY {
return const_cast<Expr*>(this)->IgnoreCasts();
}
const Expr *IgnoreParenNoopCasts(ASTContext &Ctx) const LLVM_READONLY {
return const_cast<Expr*>(this)->IgnoreParenNoopCasts(Ctx);
}
static bool hasAnyTypeDependentArguments(ArrayRef<Expr *> Exprs);
/// \brief For an expression of class type or pointer to class type,
/// return the most derived class decl the expression is known to refer to.
///
/// If this expression is a cast, this method looks through it to find the
/// most derived decl that can be inferred from the expression.
/// This is valid because derived-to-base conversions have undefined
/// behavior if the object isn't dynamically of the derived type.
const CXXRecordDecl *getBestDynamicClassType() const;
/// Walk outwards from an expression we want to bind a reference to and
/// find the expression whose lifetime needs to be extended. Record
/// the LHSs of comma expressions and adjustments needed along the path.
const Expr *skipRValueSubobjectAdjustments(
SmallVectorImpl<const Expr *> &CommaLHS,
SmallVectorImpl<SubobjectAdjustment> &Adjustments) const;
static bool classof(const Stmt *T) {
return T->getStmtClass() >= firstExprConstant &&
T->getStmtClass() <= lastExprConstant;
}
};
//===----------------------------------------------------------------------===//
// Primary Expressions.
//===----------------------------------------------------------------------===//
/// OpaqueValueExpr - An expression referring to an opaque object of a
/// fixed type and value class. These don't correspond to concrete
/// syntax; instead they're used to express operations (usually copy
/// operations) on values whose source is generally obvious from
/// context.
class OpaqueValueExpr : public Expr {
friend class ASTStmtReader;
Expr *SourceExpr;
SourceLocation Loc;
public:
OpaqueValueExpr(SourceLocation Loc, QualType T, ExprValueKind VK,
ExprObjectKind OK = OK_Ordinary,
Expr *SourceExpr = nullptr)
: Expr(OpaqueValueExprClass, T, VK, OK,
T->isDependentType(),
T->isDependentType() ||
(SourceExpr && SourceExpr->isValueDependent()),
T->isInstantiationDependentType(),
false),
SourceExpr(SourceExpr), Loc(Loc) {
}
/// Given an expression which invokes a copy constructor --- i.e. a
/// CXXConstructExpr, possibly wrapped in an ExprWithCleanups ---
/// find the OpaqueValueExpr that's the source of the construction.
static const OpaqueValueExpr *findInCopyConstruct(const Expr *expr);
explicit OpaqueValueExpr(EmptyShell Empty)
: Expr(OpaqueValueExprClass, Empty) { }
/// \brief Retrieve the location of this expression.
SourceLocation getLocation() const { return Loc; }
SourceLocation getLocStart() const LLVM_READONLY {
return SourceExpr ? SourceExpr->getLocStart() : Loc;
}
SourceLocation getLocEnd() const LLVM_READONLY {
return SourceExpr ? SourceExpr->getLocEnd() : Loc;
}
SourceLocation getExprLoc() const LLVM_READONLY {
if (SourceExpr) return SourceExpr->getExprLoc();
return Loc;
}
child_range children() {
return child_range(child_iterator(), child_iterator());
}
/// The source expression of an opaque value expression is the
/// expression which originally generated the value. This is
/// provided as a convenience for analyses that don't wish to
/// precisely model the execution behavior of the program.
///
/// The source expression is typically set when building the
/// expression which binds the opaque value expression in the first
/// place.
Expr *getSourceExpr() const { return SourceExpr; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == OpaqueValueExprClass;
}
};
/// \brief A reference to a declared variable, function, enum, etc.
/// [C99 6.5.1p2]
///
/// This encodes all the information about how a declaration is referenced
/// within an expression.
///
/// There are several optional constructs attached to DeclRefExprs only when
/// they apply in order to conserve memory. These are laid out past the end of
/// the object, and flags in the DeclRefExprBitfield track whether they exist:
///
/// DeclRefExprBits.HasQualifier:
/// Specifies when this declaration reference expression has a C++
/// nested-name-specifier.
/// DeclRefExprBits.HasFoundDecl:
/// Specifies when this declaration reference expression has a record of
/// a NamedDecl (different from the referenced ValueDecl) which was found
/// during name lookup and/or overload resolution.
/// DeclRefExprBits.HasTemplateKWAndArgsInfo:
/// Specifies when this declaration reference expression has an explicit
/// C++ template keyword and/or template argument list.
/// DeclRefExprBits.RefersToEnclosingVariableOrCapture
/// Specifies when this declaration reference expression (validly)
/// refers to an enclosed local or a captured variable.
class LLVM_ALIGNAS(/*alignof(uint64_t)*/ 8) DeclRefExpr : public Expr {
/// \brief The declaration that we are referencing.
ValueDecl *D;
/// \brief The location of the declaration name itself.
SourceLocation Loc;
/// \brief Provides source/type location info for the declaration name
/// embedded in D.
DeclarationNameLoc DNLoc;
/// \brief Helper to retrieve the optional NestedNameSpecifierLoc.
NestedNameSpecifierLoc &getInternalQualifierLoc() {
assert(hasQualifier());
return *reinterpret_cast<NestedNameSpecifierLoc *>(this + 1);
}
/// \brief Helper to retrieve the optional NestedNameSpecifierLoc.
const NestedNameSpecifierLoc &getInternalQualifierLoc() const {
return const_cast<DeclRefExpr *>(this)->getInternalQualifierLoc();
}
/// \brief Test whether there is a distinct FoundDecl attached to the end of
/// this DRE.
bool hasFoundDecl() const { return DeclRefExprBits.HasFoundDecl; }
/// \brief Helper to retrieve the optional NamedDecl through which this
/// reference occurred.
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 occurred.
NamedDecl *getInternalFoundDecl() const {
return const_cast<DeclRefExpr *>(this)->getInternalFoundDecl();
}
DeclRefExpr(const ASTContext &Ctx,
NestedNameSpecifierLoc QualifierLoc,
SourceLocation TemplateKWLoc,
ValueDecl *D, bool RefersToEnlosingVariableOrCapture,
const DeclarationNameInfo &NameInfo,
NamedDecl *FoundD,
const TemplateArgumentListInfo *TemplateArgs,
QualType T, ExprValueKind VK);
/// \brief Construct an empty declaration reference expression.
explicit DeclRefExpr(EmptyShell Empty)
: Expr(DeclRefExprClass, Empty) { }
/// \brief Computes the type- and value-dependence flags for this
/// declaration reference expression.
void computeDependence(const ASTContext &C);
public:
DeclRefExpr(ValueDecl *D, bool RefersToEnclosingVariableOrCapture, QualType T,
ExprValueKind VK, SourceLocation L,
const DeclarationNameLoc &LocInfo = DeclarationNameLoc())
: Expr(DeclRefExprClass, T, VK, OK_Ordinary, false, false, false, false),
D(D), Loc(L), DNLoc(LocInfo) {
DeclRefExprBits.HasQualifier = 0;
DeclRefExprBits.HasTemplateKWAndArgsInfo = 0;
DeclRefExprBits.HasFoundDecl = 0;
DeclRefExprBits.HadMultipleCandidates = 0;
DeclRefExprBits.RefersToEnclosingVariableOrCapture =
RefersToEnclosingVariableOrCapture;
computeDependence(D->getASTContext());
}
static DeclRefExpr *
Create(const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc,
SourceLocation TemplateKWLoc, ValueDecl *D,
bool RefersToEnclosingVariableOrCapture, SourceLocation NameLoc,
QualType T, ExprValueKind VK, NamedDecl *FoundD = nullptr,
const TemplateArgumentListInfo *TemplateArgs = nullptr);
static DeclRefExpr *
Create(const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc,
SourceLocation TemplateKWLoc, ValueDecl *D,
bool RefersToEnclosingVariableOrCapture,
const DeclarationNameInfo &NameInfo, QualType T, ExprValueKind VK,
NamedDecl *FoundD = nullptr,
const TemplateArgumentListInfo *TemplateArgs = nullptr);
/// \brief Construct an empty declaration reference expression.
static DeclRefExpr *CreateEmpty(const ASTContext &Context,
bool HasQualifier,
bool HasFoundDecl,
bool HasTemplateKWAndArgsInfo,
unsigned NumTemplateArgs);
ValueDecl *getDecl() { return D; }
const ValueDecl *getDecl() const { return D; }
void setDecl(ValueDecl *NewD) { D = NewD; }
DeclarationNameInfo getNameInfo() const {
return DeclarationNameInfo(getDecl()->getDeclName(), Loc, DNLoc);
}
SourceLocation getLocation() const { return Loc; }
void setLocation(SourceLocation L) { Loc = L; }
SourceLocation getLocStart() const LLVM_READONLY;
SourceLocation getLocEnd() const LLVM_READONLY;
/// \brief Determine whether this declaration reference was preceded by a
/// C++ nested-name-specifier, e.g., \c N::foo.
bool hasQualifier() const { return DeclRefExprBits.HasQualifier; }
/// \brief If the name was qualified, retrieves the nested-name-specifier
/// that precedes the name. Otherwise, returns NULL.
NestedNameSpecifier *getQualifier() const {
if (!hasQualifier())
return nullptr;
return getInternalQualifierLoc().getNestedNameSpecifier();
}
/// \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 occurred.
///
/// This Decl may be different from the ValueDecl actually referred to in the
/// presence of using declarations, etc. It always returns non-NULL, and may
/// simple return the ValueDecl when appropriate.
NamedDecl *getFoundDecl() {
return hasFoundDecl() ? getInternalFoundDecl() : D;
}
/// \brief Get the NamedDecl through which this reference occurred.
/// See non-const variant.
const NamedDecl *getFoundDecl() const {
return hasFoundDecl() ? getInternalFoundDecl() : D;
}
bool hasTemplateKWAndArgsInfo() const {
return DeclRefExprBits.HasTemplateKWAndArgsInfo;
}
/// \brief Return the optional template keyword and arguments info.
ASTTemplateKWAndArgsInfo *getTemplateKWAndArgsInfo() {
if (!hasTemplateKWAndArgsInfo())
return nullptr;
if (hasFoundDecl()) {
return reinterpret_cast<ASTTemplateKWAndArgsInfo *>(
llvm::alignAddr(&getInternalFoundDecl() + 1,
llvm::alignOf<ASTTemplateKWAndArgsInfo>()));
}
if (hasQualifier()) {
return reinterpret_cast<ASTTemplateKWAndArgsInfo *>(
llvm::alignAddr(&getInternalQualifierLoc() + 1,
llvm::alignOf<ASTTemplateKWAndArgsInfo>()));
}
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();
}
/// \brief Retrieve the explicit template argument list that followed the
/// member template name.
const ASTTemplateArgumentListInfo &getExplicitTemplateArgs() const {
return const_cast<DeclRefExpr *>(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.
const ASTTemplateArgumentListInfo *getOptionalExplicitTemplateArgs() const {
if (!hasExplicitTemplateArgs()) return nullptr;
return &getExplicitTemplateArgs();
}
/// \brief Copies the template arguments (if present) into the given
/// structure.
void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const {
if (hasExplicitTemplateArgs())
getExplicitTemplateArgs().copyInto(List);
}
/// \brief Retrieve the template arguments provided as part of this
/// template-id.
const TemplateArgumentLoc *getTemplateArgs() const {
if (!hasExplicitTemplateArgs())
return nullptr;
return getExplicitTemplateArgs().getTemplateArgs();
}
/// \brief Retrieve the number of template arguments provided as part of this
/// template-id.
unsigned getNumTemplateArgs() const {
if (!hasExplicitTemplateArgs())
return 0;
return getExplicitTemplateArgs().NumTemplateArgs;
}
/// \brief Returns true if this expression refers to a function that
/// was resolved from an overloaded set having size greater than 1.
bool hadMultipleCandidates() const {
return DeclRefExprBits.HadMultipleCandidates;
}
/// \brief Sets the flag telling whether this expression refers to
/// a function that was resolved from an overloaded set having size
/// greater than 1.
void setHadMultipleCandidates(bool V = true) {
DeclRefExprBits.HadMultipleCandidates = V;
}
/// \brief Does this DeclRefExpr refer to an enclosing local or a captured
/// variable?
bool refersToEnclosingVariableOrCapture() const {
return DeclRefExprBits.RefersToEnclosingVariableOrCapture;
}
static bool classof(const Stmt *T) {
return T->getStmtClass() == DeclRefExprClass;
}
// Iterators
child_range children() {
return child_range(child_iterator(), child_iterator());
}
friend class ASTStmtReader;
friend class ASTStmtWriter;
};
/// \brief [C99 6.4.2.2] - A predefined identifier such as __func__.
class PredefinedExpr : public Expr {
public:
enum IdentType {
Func,
Function,
LFunction, // Same as Function, but as wide string.
FuncDName,
FuncSig,
PrettyFunction,
/// \brief The same as PrettyFunction, except that the
/// 'virtual' keyword is omitted for virtual member functions.
PrettyFunctionNoVirtual
};
private:
SourceLocation Loc;
IdentType Type;
Stmt *FnName;
public:
PredefinedExpr(SourceLocation L, QualType FNTy, IdentType IT,
StringLiteral *SL);
/// \brief Construct an empty predefined expression.
explicit PredefinedExpr(EmptyShell Empty)
: Expr(PredefinedExprClass, Empty), Loc(), Type(Func), FnName(nullptr) {}
IdentType getIdentType() const { return Type; }
SourceLocation getLocation() const { return Loc; }
void setLocation(SourceLocation L) { Loc = L; }
StringLiteral *getFunctionName();
const StringLiteral *getFunctionName() const {
return const_cast<PredefinedExpr *>(this)->getFunctionName();
}
static StringRef getIdentTypeName(IdentType IT);
static std::string ComputeName(IdentType IT, const Decl *CurrentDecl);
SourceLocation getLocStart() const LLVM_READONLY { return Loc; }
SourceLocation getLocEnd() const LLVM_READONLY { return Loc; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == PredefinedExprClass;
}
// Iterators
child_range children() { return child_range(&FnName, &FnName + 1); }
friend class ASTStmtReader;
};
/// \brief Used by IntegerLiteral/FloatingLiteral to store the numeric without
/// leaking memory.
///
/// For large floats/integers, APFloat/APInt will allocate memory from the heap
/// to represent these numbers. Unfortunately, when we use a BumpPtrAllocator
/// to allocate IntegerLiteral/FloatingLiteral nodes the memory associated with
/// the APFloat/APInt values will never get freed. APNumericStorage uses
/// ASTContext's allocator for memory allocation.
class APNumericStorage {
union {
uint64_t VAL; ///< Used to store the <= 64 bits integer value.
uint64_t *pVal; ///< Used to store the >64 bits integer value.
};
unsigned BitWidth;
bool hasAllocation() const { return llvm::APInt::getNumWords(BitWidth) > 1; }
APNumericStorage(const APNumericStorage &) = delete;
void operator=(const APNumericStorage &) = delete;
protected:
APNumericStorage() : VAL(0), BitWidth(0) { }
llvm::APInt getIntValue() const {
unsigned NumWords = llvm::APInt::getNumWords(BitWidth);
if (NumWords > 1)
return llvm::APInt(BitWidth, NumWords, pVal);
else
return llvm::APInt(BitWidth, VAL);
}
void setIntValue(const ASTContext &C, const llvm::APInt &Val);
};
class APIntStorage : private APNumericStorage {
public:
llvm::APInt getValue() const { return getIntValue(); }
void setValue(const ASTContext &C, const llvm::APInt &Val) {
setIntValue(C, Val);
}
};
class APFloatStorage : private APNumericStorage {
public:
llvm::APFloat getValue(const llvm::fltSemantics &Semantics) const {
return llvm::APFloat(Semantics, getIntValue());
}
void setValue(const ASTContext &C, const llvm::APFloat &Val) {
setIntValue(C, Val.bitcastToAPInt());
}
};
class IntegerLiteral : public Expr, public APIntStorage {
SourceLocation Loc;
/// \brief Construct an empty integer literal.
explicit IntegerLiteral(EmptyShell Empty)
: Expr(IntegerLiteralClass, Empty) { }
public:
// type should be IntTy, LongTy, LongLongTy, UnsignedIntTy, UnsignedLongTy,
// or UnsignedLongLongTy
IntegerLiteral(const ASTContext &C, const llvm::APInt &V, QualType type,
SourceLocation l);
/// \brief Returns a new integer literal with value 'V' and type 'type'.
/// \param type - either IntTy, LongTy, LongLongTy, UnsignedIntTy,
/// UnsignedLongTy, or UnsignedLongLongTy which should match the size of V
/// \param V - the value that the returned integer literal contains.
static IntegerLiteral *Create(const ASTContext &C, const llvm::APInt &V,
QualType type, SourceLocation l);
/// \brief Returns a new empty integer literal.
static IntegerLiteral *Create(const ASTContext &C, EmptyShell Empty);
SourceLocation getLocStart() const LLVM_READONLY { return Loc; }
SourceLocation getLocEnd() const LLVM_READONLY { return Loc; }
/// \brief Retrieve the location of the literal.
SourceLocation getLocation() const { return Loc; }
void setLocation(SourceLocation Location) { Loc = Location; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == IntegerLiteralClass;
}
// Iterators
child_range children() {
return child_range(child_iterator(), child_iterator());
}
};
class CharacterLiteral : public Expr {
public:
enum CharacterKind {
Ascii,
Wide,
UTF16,
UTF32
};
private:
unsigned Value;
SourceLocation Loc;
public:
// type should be IntTy
CharacterLiteral(unsigned value, CharacterKind kind, QualType type,
SourceLocation l)
: Expr(CharacterLiteralClass, type, VK_RValue, OK_Ordinary, false, false,
false, false),
Value(value), Loc(l) {
CharacterLiteralBits.Kind = kind;
}
/// \brief Construct an empty character literal.
CharacterLiteral(EmptyShell Empty) : Expr(CharacterLiteralClass, Empty) { }
SourceLocation getLocation() const { return Loc; }
CharacterKind getKind() const {
return static_cast<CharacterKind>(CharacterLiteralBits.Kind);
}
SourceLocation getLocStart() const LLVM_READONLY { return Loc; }
SourceLocation getLocEnd() const LLVM_READONLY { return Loc; }
unsigned getValue() const { return Value; }
void setLocation(SourceLocation Location) { Loc = Location; }
void setKind(CharacterKind kind) { CharacterLiteralBits.Kind = kind; }
void setValue(unsigned Val) { Value = Val; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == CharacterLiteralClass;
}
// Iterators
child_range children() {
return child_range(child_iterator(), child_iterator());
}
};
class FloatingLiteral : public Expr, private APFloatStorage {
SourceLocation Loc;
FloatingLiteral(const ASTContext &C, const llvm::APFloat &V, bool isexact,
QualType Type, SourceLocation L);
/// \brief Construct an empty floating-point literal.
explicit FloatingLiteral(const ASTContext &C, EmptyShell Empty);
public:
static FloatingLiteral *Create(const ASTContext &C, const llvm::APFloat &V,
bool isexact, QualType Type, SourceLocation L);
static FloatingLiteral *Create(const ASTContext &C, EmptyShell Empty);
llvm::APFloat getValue() const {
return APFloatStorage::getValue(getSemantics());
}
void setValue(const ASTContext &C, const llvm::APFloat &Val) {
assert(&getSemantics() == &Val.getSemantics() && "Inconsistent semantics");
APFloatStorage::setValue(C, Val);
}
/// Get a raw enumeration value representing the floating-point semantics of
/// this literal (32-bit IEEE, x87, ...), suitable for serialisation.
APFloatSemantics getRawSemantics() const {
return static_cast<APFloatSemantics>(FloatingLiteralBits.Semantics);
}
/// Set the raw enumeration value representing the floating-point semantics of
/// this literal (32-bit IEEE, x87, ...), suitable for serialisation.
void setRawSemantics(APFloatSemantics Sem) {
FloatingLiteralBits.Semantics = Sem;
}
/// Return the APFloat semantics this literal uses.
const llvm::fltSemantics &getSemantics() const;
/// Set the APFloat semantics this literal uses.
void setSemantics(const llvm::fltSemantics &Sem);
bool isExact() const { return FloatingLiteralBits.IsExact; }
void setExact(bool E) { FloatingLiteralBits.IsExact = E; }
/// getValueAsApproximateDouble - This returns the value as an inaccurate
/// double. Note that this may cause loss of precision, but is useful for
/// debugging dumps, etc.
double getValueAsApproximateDouble() const;
SourceLocation getLocation() const { return Loc; }
void setLocation(SourceLocation L) { Loc = L; }
SourceLocation getLocStart() const LLVM_READONLY { return Loc; }
SourceLocation getLocEnd() const LLVM_READONLY { return Loc; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == FloatingLiteralClass;
}
// Iterators
child_range children() {
return child_range(child_iterator(), child_iterator());
}
};
/// ImaginaryLiteral - We support imaginary integer and floating point literals,
/// like "1.0i". We represent these as a wrapper around FloatingLiteral and
/// IntegerLiteral classes. Instances of this class always have a Complex type
/// whose element type matches the subexpression.
///
class ImaginaryLiteral : public Expr {
Stmt *Val;
public:
ImaginaryLiteral(Expr *val, QualType Ty)
: Expr(ImaginaryLiteralClass, Ty, VK_RValue, OK_Ordinary, false, false,
false, false),
Val(val) {}
/// \brief Build an empty imaginary literal.
explicit ImaginaryLiteral(EmptyShell Empty)
: Expr(ImaginaryLiteralClass, Empty) { }
const Expr *getSubExpr() const { return cast<Expr>(Val); }
Expr *getSubExpr() { return cast<Expr>(Val); }
void setSubExpr(Expr *E) { Val = E; }
SourceLocation getLocStart() const LLVM_READONLY { return Val->getLocStart(); }
SourceLocation getLocEnd() const LLVM_READONLY { return Val->getLocEnd(); }
static bool classof(const Stmt *T) {
return T->getStmtClass() == ImaginaryLiteralClass;
}
// Iterators
child_range children() { return child_range(&Val, &Val+1); }
};
/// StringLiteral - This represents a string literal expression, e.g. "foo"
/// or L"bar" (wide strings). The actual string is returned by getBytes()
/// is NOT null-terminated, and the length of the string is determined by
/// calling getByteLength(). The C type for a string is always a
/// ConstantArrayType. In C++, the char type is const qualified, in C it is
/// not.
///
/// Note that strings in C can be formed by concatenation of multiple string
/// literal pptokens in translation phase #6. This keeps track of the locations
/// of each of these pieces.
///
/// Strings in C can also be truncated and extended by assigning into arrays,
/// e.g. with constructs like:
/// char X[2] = "foobar";
/// In this case, getByteLength() will return 6, but the string literal will
/// have type "char[2]".
class StringLiteral : public Expr {
public:
enum StringKind {
Ascii,
Wide,
UTF8,
UTF16,
UTF32
};
private:
friend class ASTStmtReader;
union {
const char *asChar;
const uint16_t *asUInt16;
const uint32_t *asUInt32;
} StrData;
unsigned Length;
unsigned CharByteWidth : 4;
unsigned Kind : 3;
unsigned IsPascal : 1;
unsigned NumConcatenated;
SourceLocation TokLocs[1];
StringLiteral(QualType Ty) :
Expr(StringLiteralClass, Ty, VK_LValue, OK_Ordinary, false, false, false,
false) {}
static int mapCharByteWidth(TargetInfo const &target,StringKind k);
public:
/// This is the "fully general" constructor that allows representation of
/// strings formed from multiple concatenated tokens.
static StringLiteral *Create(const ASTContext &C, StringRef Str,
StringKind Kind, bool Pascal, QualType Ty,
const SourceLocation *Loc, unsigned NumStrs);
/// Simple constructor for string literals made from one token.
static StringLiteral *Create(const ASTContext &C, StringRef Str,
StringKind Kind, bool Pascal, QualType Ty,
SourceLocation Loc) {
return Create(C, Str, Kind, Pascal, Ty, &Loc, 1);
}
/// \brief Construct an empty string literal.
static StringLiteral *CreateEmpty(const ASTContext &C, unsigned NumStrs);
StringRef getString() const {
assert(CharByteWidth==1
&& "This function is used in places that assume strings use char");
return StringRef(StrData.asChar, getByteLength());
}
/// Allow access to clients that need the byte representation, such as
/// ASTWriterStmt::VisitStringLiteral().
StringRef getBytes() const {
// FIXME: StringRef may not be the right type to use as a result for this.
if (CharByteWidth == 1)
return StringRef(StrData.asChar, getByteLength());
if (CharByteWidth == 4)
return StringRef(reinterpret_cast<const char*>(StrData.asUInt32),
getByteLength());
assert(CharByteWidth == 2 && "unsupported CharByteWidth");
return StringRef(reinterpret_cast<const char*>(StrData.asUInt16),
getByteLength());
}
void outputString(raw_ostream &OS) const;
uint32_t getCodeUnit(size_t i) const {
assert(i < Length && "out of bounds access");
if (CharByteWidth == 1)
return static_cast<unsigned char>(StrData.asChar[i]);
if (CharByteWidth == 4)
return StrData.asUInt32[i];
assert(CharByteWidth == 2 && "unsupported CharByteWidth");
return StrData.asUInt16[i];
}
unsigned getByteLength() const { return CharByteWidth*Length; }
unsigned getLength() const { return Length; }
unsigned getCharByteWidth() const { return CharByteWidth; }
/// \brief Sets the string data to the given string data.
void setString(const ASTContext &C, StringRef Str,
StringKind Kind, bool IsPascal);
StringKind getKind() const { return static_cast<StringKind>(Kind); }
bool isAscii() const { return Kind == Ascii; }
bool isWide() const { return Kind == Wide; }
bool isUTF8() const { return Kind == UTF8; }
bool isUTF16() const { return Kind == UTF16; }
bool isUTF32() const { return Kind == UTF32; }
bool isPascal() const { return IsPascal; }
bool containsNonAsciiOrNull() const {
StringRef Str = getString();
for (unsigned i = 0, e = Str.size(); i != e; ++i)
if (!isASCII(Str[i]) || !Str[i])
return true;
return false;
}
/// getNumConcatenated - Get the number of string literal tokens that were
/// concatenated in translation phase #6 to form this string literal.
unsigned getNumConcatenated() const { return NumConcatenated; }
SourceLocation getStrTokenLoc(unsigned TokNum) const {
assert(TokNum < NumConcatenated && "Invalid tok number");
return TokLocs[TokNum];
}
void setStrTokenLoc(unsigned TokNum, SourceLocation L) {
assert(TokNum < NumConcatenated && "Invalid tok number");
TokLocs[TokNum] = L;
}
/// getLocationOfByte - Return a source location that points to the specified
/// byte of this string literal.
///
/// Strings are amazingly complex. They can be formed from multiple tokens
/// and can have escape sequences in them in addition to the usual trigraph
/// and escaped newline business. This routine handles this complexity.
///
- SourceLocation getLocationOfByte(unsigned ByteNo, const SourceManager &SM,
- const LangOptions &Features,
- const TargetInfo &Target) const;
+ SourceLocation
+ getLocationOfByte(unsigned ByteNo, const SourceManager &SM,
+ const LangOptions &Features, const TargetInfo &Target,
+ unsigned *StartToken = nullptr,
+ unsigned *StartTokenByteOffset = nullptr) const;
typedef const SourceLocation *tokloc_iterator;
tokloc_iterator tokloc_begin() const { return TokLocs; }
- tokloc_iterator tokloc_end() const { return TokLocs+NumConcatenated; }
+ tokloc_iterator tokloc_end() const { return TokLocs + NumConcatenated; }
SourceLocation getLocStart() const LLVM_READONLY { return TokLocs[0]; }
SourceLocation getLocEnd() const LLVM_READONLY {
return TokLocs[NumConcatenated - 1];
}
static bool classof(const Stmt *T) {
return T->getStmtClass() == StringLiteralClass;
}
// Iterators
child_range children() {
return child_range(child_iterator(), child_iterator());
}
};
/// ParenExpr - This represents a parethesized expression, e.g. "(1)". This
/// AST node is only formed if full location information is requested.
class ParenExpr : public Expr {
SourceLocation L, R;
Stmt *Val;
public:
ParenExpr(SourceLocation l, SourceLocation r, Expr *val)
: Expr(ParenExprClass, val->getType(),
val->getValueKind(), val->getObjectKind(),
val->isTypeDependent(), val->isValueDependent(),
val->isInstantiationDependent(),
val->containsUnexpandedParameterPack()),
L(l), R(r), Val(val) {}
/// \brief Construct an empty parenthesized expression.
explicit ParenExpr(EmptyShell Empty)
: Expr(ParenExprClass, Empty) { }
const Expr *getSubExpr() const { return cast<Expr>(Val); }
Expr *getSubExpr() { return cast<Expr>(Val); }
void setSubExpr(Expr *E) { Val = E; }
SourceLocation getLocStart() const LLVM_READONLY { return L; }
SourceLocation getLocEnd() const LLVM_READONLY { return R; }
/// \brief Get the location of the left parentheses '('.
SourceLocation getLParen() const { return L; }
void setLParen(SourceLocation Loc) { L = Loc; }
/// \brief Get the location of the right parentheses ')'.
SourceLocation getRParen() const { return R; }
void setRParen(SourceLocation Loc) { R = Loc; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == ParenExprClass;
}
// Iterators
child_range children() { return child_range(&Val, &Val+1); }
};
/// UnaryOperator - This represents the unary-expression's (except sizeof and
/// alignof), the postinc/postdec operators from postfix-expression, and various
/// extensions.
///
/// Notes on various nodes:
///
/// Real/Imag - These return the real/imag part of a complex operand. If
/// applied to a non-complex value, the former returns its operand and the
/// later returns zero in the type of the operand.
///
class UnaryOperator : public Expr {
public:
typedef UnaryOperatorKind Opcode;
private:
unsigned Opc : 5;
SourceLocation Loc;
Stmt *Val;
public:
UnaryOperator(Expr *input, Opcode opc, QualType type,
ExprValueKind VK, ExprObjectKind OK, SourceLocation l)
: Expr(UnaryOperatorClass, type, VK, OK,
input->isTypeDependent() || type->isDependentType(),
input->isValueDependent(),
(input->isInstantiationDependent() ||
type->isInstantiationDependentType()),
input->containsUnexpandedParameterPack()),
Opc(opc), Loc(l), Val(input) {}
/// \brief Build an empty unary operator.
explicit UnaryOperator(EmptyShell Empty)
: Expr(UnaryOperatorClass, Empty), Opc(UO_AddrOf) { }
Opcode getOpcode() const { return static_cast<Opcode>(Opc); }
void setOpcode(Opcode O) { Opc = O; }
Expr *getSubExpr() const { return cast<Expr>(Val); }
void setSubExpr(Expr *E) { Val = E; }
/// getOperatorLoc - Return the location of the operator.
SourceLocation getOperatorLoc() const { return Loc; }
void setOperatorLoc(SourceLocation L) { Loc = L; }
/// isPostfix - Return true if this is a postfix operation, like x++.
static bool isPostfix(Opcode Op) {
return Op == UO_PostInc || Op == UO_PostDec;
}
/// isPrefix - Return true if this is a prefix operation, like --x.
static bool isPrefix(Opcode Op) {
return Op == UO_PreInc || Op == UO_PreDec;
}
bool isPrefix() const { return isPrefix(getOpcode()); }
bool isPostfix() const { return isPostfix(getOpcode()); }
static bool isIncrementOp(Opcode Op) {
return Op == UO_PreInc || Op == UO_PostInc;
}
bool isIncrementOp() const {
return isIncrementOp(getOpcode());
}
static bool isDecrementOp(Opcode Op) {
return Op == UO_PreDec || Op == UO_PostDec;
}
bool isDecrementOp() const {
return isDecrementOp(getOpcode());
}
static bool isIncrementDecrementOp(Opcode Op) { return Op <= UO_PreDec; }
bool isIncrementDecrementOp() const {
return isIncrementDecrementOp(getOpcode());
}
static bool isArithmeticOp(Opcode Op) {
return Op >= UO_Plus && Op <= UO_LNot;
}
bool isArithmeticOp() const { return isArithmeticOp(getOpcode()); }
/// getOpcodeStr - Turn an Opcode enum value into the punctuation char it
/// corresponds to, e.g. "sizeof" or "[pre]++"
static StringRef getOpcodeStr(Opcode Op);
/// \brief Retrieve the unary opcode that corresponds to the given
/// overloaded operator.
static Opcode getOverloadedOpcode(OverloadedOperatorKind OO, bool Postfix);
/// \brief Retrieve the overloaded operator kind that corresponds to
/// the given unary opcode.
static OverloadedOperatorKind getOverloadedOperator(Opcode Opc);
SourceLocation getLocStart() const LLVM_READONLY {
return isPostfix() ? Val->getLocStart() : Loc;
}
SourceLocation getLocEnd() const LLVM_READONLY {
return isPostfix() ? Loc : Val->getLocEnd();
}
SourceLocation getExprLoc() const LLVM_READONLY { return Loc; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == UnaryOperatorClass;
}
// Iterators
child_range children() { return child_range(&Val, &Val+1); }
};
/// OffsetOfExpr - [C99 7.17] - This represents an expression of the form
/// offsetof(record-type, member-designator). For example, given:
/// @code
/// struct S {
/// float f;
/// double d;
/// };
/// struct T {
/// int i;
/// struct S s[10];
/// };
/// @endcode
/// we can represent and evaluate the expression @c offsetof(struct T, s[2].d).
class OffsetOfExpr : 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 };
/// \brief The source range that covers this part of the designator.
SourceRange Range;
/// \brief The data describing the designator, which comes in three
/// different forms, depending on the lower two bits.
/// - An unsigned index into the array of Expr*'s stored after this node
/// in memory, for [constant-expression] designators.
/// - A FieldDecl*, for references to a known field.
/// - An IdentifierInfo*, for references to a field with a given name
/// when the class type is dependent.
/// - A CXXBaseSpecifier*, for references that look at a field in a
/// base class.
uintptr_t Data;
public:
/// \brief Create an offsetof node that refers to an array element.
OffsetOfNode(SourceLocation LBracketLoc, unsigned Index,
SourceLocation RBracketLoc)
: Range(LBracketLoc, RBracketLoc), Data((Index << 2) | Array) { }
/// \brief Create an offsetof node that refers to a field.
OffsetOfNode(SourceLocation DotLoc, FieldDecl *Field,
SourceLocation NameLoc)
: Range(DotLoc.isValid()? DotLoc : NameLoc, NameLoc),
Data(reinterpret_cast<uintptr_t>(Field) | OffsetOfNode::Field) { }
/// \brief Create an offsetof node that refers to an identifier.
OffsetOfNode(SourceLocation DotLoc, IdentifierInfo *Name,
SourceLocation NameLoc)
: Range(DotLoc.isValid()? DotLoc : NameLoc, NameLoc),
Data(reinterpret_cast<uintptr_t>(Name) | Identifier) { }
/// \brief Create an offsetof node that refers into a C++ base class.
explicit OffsetOfNode(const CXXBaseSpecifier *Base)
: Range(), Data(reinterpret_cast<uintptr_t>(Base) | OffsetOfNode::Base) {}
/// \brief Determine what kind of offsetof node this is.
Kind getKind() const {
return static_cast<Kind>(Data & Mask);
}
/// \brief For an array element node, returns the index into the array
/// of expressions.
unsigned getArrayExprIndex() const {
assert(getKind() == Array);
return Data >> 2;
}
/// \brief For a field offsetof node, returns the field.
FieldDecl *getField() const {
assert(getKind() == Field);
return reinterpret_cast<FieldDecl *>(Data & ~(uintptr_t)Mask);
}
/// \brief For a field or identifier offsetof node, returns the name of
/// the field.
IdentifierInfo *getFieldName() const;
/// \brief For a base class node, returns the base specifier.
CXXBaseSpecifier *getBase() const {
assert(getKind() == Base);
return reinterpret_cast<CXXBaseSpecifier *>(Data & ~(uintptr_t)Mask);
}
/// \brief Retrieve the source range that covers this offsetof node.
///
/// For an array element node, the source range contains the locations of
/// the square brackets. For a field or identifier node, the source range
/// contains the location of the period (if there is one) and the
/// identifier.
SourceRange getSourceRange() const LLVM_READONLY { return Range; }
SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); }
SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); }
};
private:
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;
OffsetOfExpr(const ASTContext &C, QualType type,
SourceLocation OperatorLoc, TypeSourceInfo *tsi,
ArrayRef<OffsetOfNode> comps, ArrayRef<Expr*> exprs,
SourceLocation RParenLoc);
explicit OffsetOfExpr(unsigned numComps, unsigned numExprs)
: Expr(OffsetOfExprClass, EmptyShell()),
TSInfo(nullptr), NumComps(numComps), NumExprs(numExprs) {}
public:
static OffsetOfExpr *Create(const ASTContext &C, QualType type,
SourceLocation OperatorLoc, TypeSourceInfo *tsi,
ArrayRef<OffsetOfNode> comps,
ArrayRef<Expr*> exprs, SourceLocation RParenLoc);
static OffsetOfExpr *CreateEmpty(const ASTContext &C,
unsigned NumComps, unsigned NumExprs);
/// getOperatorLoc - Return the location of the operator.
SourceLocation getOperatorLoc() const { return OperatorLoc; }
void setOperatorLoc(SourceLocation L) { OperatorLoc = L; }
/// \brief Return the location of the right parentheses.
SourceLocation getRParenLoc() const { return RParenLoc; }
void setRParenLoc(SourceLocation R) { RParenLoc = R; }
TypeSourceInfo *getTypeSourceInfo() const {
return TSInfo;
}
void setTypeSourceInfo(TypeSourceInfo *tsi) {
TSInfo = tsi;
}
const OffsetOfNode &getComponent(unsigned Idx) const {
assert(Idx < NumComps && "Subscript out of range");
return reinterpret_cast<const OffsetOfNode *> (this + 1)[Idx];
}
void setComponent(unsigned Idx, OffsetOfNode ON) {
assert(Idx < NumComps && "Subscript out of range");
reinterpret_cast<OffsetOfNode *> (this + 1)[Idx] = ON;
}
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];
}
const Expr *getIndexExpr(unsigned Idx) const {
return const_cast<OffsetOfExpr*>(this)->getIndexExpr(Idx);
}
void setIndexExpr(unsigned Idx, Expr* E) {
assert(Idx < NumComps && "Subscript out of range");
reinterpret_cast<Expr **>(
reinterpret_cast<OffsetOfNode *>(this+1) + NumComps)[Idx] = E;
}
unsigned getNumExpressions() const {
return NumExprs;
}
SourceLocation getLocStart() const LLVM_READONLY { return OperatorLoc; }
SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == OffsetOfExprClass;
}
// Iterators
child_range children() {
Stmt **begin =
reinterpret_cast<Stmt**>(reinterpret_cast<OffsetOfNode*>(this + 1)
+ NumComps);
return child_range(begin, begin + NumExprs);
}
};
/// UnaryExprOrTypeTraitExpr - expression with either a type or (unevaluated)
/// expression operand. Used for sizeof/alignof (C99 6.5.3.4) and
/// vec_step (OpenCL 1.1 6.11.12).
class UnaryExprOrTypeTraitExpr : public Expr {
union {
TypeSourceInfo *Ty;
Stmt *Ex;
} Argument;
SourceLocation OpLoc, RParenLoc;
public:
UnaryExprOrTypeTraitExpr(UnaryExprOrTypeTrait ExprKind, TypeSourceInfo *TInfo,
QualType resultType, SourceLocation op,
SourceLocation rp) :
Expr(UnaryExprOrTypeTraitExprClass, resultType, VK_RValue, OK_Ordinary,
false, // Never type-dependent (C++ [temp.dep.expr]p3).
// Value-dependent if the argument is type-dependent.
TInfo->getType()->isDependentType(),
TInfo->getType()->isInstantiationDependentType(),
TInfo->getType()->containsUnexpandedParameterPack()),
OpLoc(op), RParenLoc(rp) {
UnaryExprOrTypeTraitExprBits.Kind = ExprKind;
UnaryExprOrTypeTraitExprBits.IsType = true;
Argument.Ty = TInfo;
}
UnaryExprOrTypeTraitExpr(UnaryExprOrTypeTrait ExprKind, Expr *E,
QualType resultType, SourceLocation op,
SourceLocation rp);
/// \brief Construct an empty sizeof/alignof expression.
explicit UnaryExprOrTypeTraitExpr(EmptyShell Empty)
: Expr(UnaryExprOrTypeTraitExprClass, Empty) { }
UnaryExprOrTypeTrait getKind() const {
return static_cast<UnaryExprOrTypeTrait>(UnaryExprOrTypeTraitExprBits.Kind);
}
void setKind(UnaryExprOrTypeTrait K) { UnaryExprOrTypeTraitExprBits.Kind = K;}
bool isArgumentType() const { return UnaryExprOrTypeTraitExprBits.IsType; }
QualType getArgumentType() const {
return getArgumentTypeInfo()->getType();
}
TypeSourceInfo *getArgumentTypeInfo() const {
assert(isArgumentType() && "calling getArgumentType() when arg is expr");
return Argument.Ty;
}
Expr *getArgumentExpr() {
assert(!isArgumentType() && "calling getArgumentExpr() when arg is type");
return static_cast<Expr*>(Argument.Ex);
}
const Expr *getArgumentExpr() const {
return const_cast<UnaryExprOrTypeTraitExpr*>(this)->getArgumentExpr();
}
void setArgument(Expr *E) {
Argument.Ex = E;
UnaryExprOrTypeTraitExprBits.IsType = false;
}
void setArgument(TypeSourceInfo *TInfo) {
Argument.Ty = TInfo;
UnaryExprOrTypeTraitExprBits.IsType = true;
}
/// Gets the argument type, or the type of the argument expression, whichever
/// is appropriate.
QualType getTypeOfArgument() const {
return isArgumentType() ? getArgumentType() : getArgumentExpr()->getType();
}
SourceLocation getOperatorLoc() const { return OpLoc; }
void setOperatorLoc(SourceLocation L) { OpLoc = L; }
SourceLocation getRParenLoc() const { return RParenLoc; }
void setRParenLoc(SourceLocation L) { RParenLoc = L; }
SourceLocation getLocStart() const LLVM_READONLY { return OpLoc; }
SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == UnaryExprOrTypeTraitExprClass;
}
// Iterators
child_range children();
};
//===----------------------------------------------------------------------===//
// Postfix Operators.
//===----------------------------------------------------------------------===//
/// ArraySubscriptExpr - [C99 6.5.2.1] Array Subscripting.
class ArraySubscriptExpr : public Expr {
enum { LHS, RHS, END_EXPR=2 };
Stmt* SubExprs[END_EXPR];
SourceLocation RBracketLoc;
public:
ArraySubscriptExpr(Expr *lhs, Expr *rhs, QualType t,
ExprValueKind VK, ExprObjectKind OK,
SourceLocation rbracketloc)
: Expr(ArraySubscriptExprClass, t, VK, OK,
lhs->isTypeDependent() || rhs->isTypeDependent(),
lhs->isValueDependent() || rhs->isValueDependent(),
(lhs->isInstantiationDependent() ||
rhs->isInstantiationDependent()),
(lhs->containsUnexpandedParameterPack() ||
rhs->containsUnexpandedParameterPack())),
RBracketLoc(rbracketloc) {
SubExprs[LHS] = lhs;
SubExprs[RHS] = rhs;
}
/// \brief Create an empty array subscript expression.
explicit ArraySubscriptExpr(EmptyShell Shell)
: Expr(ArraySubscriptExprClass, Shell) { }
/// An array access can be written A[4] or 4[A] (both are equivalent).
/// - getBase() and getIdx() always present the normalized view: A[4].
/// In this case getBase() returns "A" and getIdx() returns "4".
/// - getLHS() and getRHS() present the syntactic view. e.g. for
/// 4[A] getLHS() returns "4".
/// Note: Because vector element access is also written A[4] we must
/// predicate the format conversion in getBase and getIdx only on the
/// the type of the RHS, as it is possible for the LHS to be a vector of
/// integer type
Expr *getLHS() { return cast<Expr>(SubExprs[LHS]); }
const Expr *getLHS() const { return cast<Expr>(SubExprs[LHS]); }
void setLHS(Expr *E) { SubExprs[LHS] = E; }
Expr *getRHS() { return cast<Expr>(SubExprs[RHS]); }
const Expr *getRHS() const { return cast<Expr>(SubExprs[RHS]); }
void setRHS(Expr *E) { SubExprs[RHS] = E; }
Expr *getBase() {
return cast<Expr>(getRHS()->getType()->isIntegerType() ? getLHS():getRHS());
}
const Expr *getBase() const {
return cast<Expr>(getRHS()->getType()->isIntegerType() ? getLHS():getRHS());
}
Expr *getIdx() {
return cast<Expr>(getRHS()->getType()->isIntegerType() ? getRHS():getLHS());
}
const Expr *getIdx() const {
return cast<Expr>(getRHS()->getType()->isIntegerType() ? getRHS():getLHS());
}
SourceLocation getLocStart() const LLVM_READONLY {
return getLHS()->getLocStart();
}
SourceLocation getLocEnd() const LLVM_READONLY { return RBracketLoc; }
SourceLocation getRBracketLoc() const { return RBracketLoc; }
void setRBracketLoc(SourceLocation L) { RBracketLoc = L; }
SourceLocation getExprLoc() const LLVM_READONLY {
return getBase()->getExprLoc();
}
static bool classof(const Stmt *T) {
return T->getStmtClass() == ArraySubscriptExprClass;
}
// Iterators
child_range children() {
return child_range(&SubExprs[0], &SubExprs[0]+END_EXPR);
}
};
/// CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
/// CallExpr itself represents a normal function call, e.g., "f(x, 2)",
/// while its subclasses may represent alternative syntax that (semantically)
/// results in a function call. For example, CXXOperatorCallExpr is
/// a subclass for overloaded operator calls that use operator syntax, e.g.,
/// "str1 + str2" to resolve to a function call.
class CallExpr : public Expr {
enum { FN=0, PREARGS_START=1 };
Stmt **SubExprs;
unsigned NumArgs;
SourceLocation RParenLoc;
protected:
// These versions of the constructor are for derived classes.
CallExpr(const ASTContext& C, StmtClass SC, Expr *fn, unsigned NumPreArgs,
ArrayRef<Expr*> args, QualType t, ExprValueKind VK,
SourceLocation rparenloc);
CallExpr(const ASTContext &C, StmtClass SC, unsigned NumPreArgs,
EmptyShell Empty);
Stmt *getPreArg(unsigned i) {
assert(i < getNumPreArgs() && "Prearg access out of range!");
return SubExprs[PREARGS_START+i];
}
const Stmt *getPreArg(unsigned i) const {
assert(i < getNumPreArgs() && "Prearg access out of range!");
return SubExprs[PREARGS_START+i];
}
void setPreArg(unsigned i, Stmt *PreArg) {
assert(i < getNumPreArgs() && "Prearg access out of range!");
SubExprs[PREARGS_START+i] = PreArg;
}
unsigned getNumPreArgs() const { return CallExprBits.NumPreArgs; }
public:
CallExpr(const ASTContext& C, Expr *fn, ArrayRef<Expr*> args, QualType t,
ExprValueKind VK, SourceLocation rparenloc);
/// \brief Build an empty call expression.
CallExpr(const ASTContext &C, StmtClass SC, EmptyShell Empty);
const Expr *getCallee() const { return cast<Expr>(SubExprs[FN]); }
Expr *getCallee() { return cast<Expr>(SubExprs[FN]); }
void setCallee(Expr *F) { SubExprs[FN] = F; }
Decl *getCalleeDecl();
const Decl *getCalleeDecl() const {
return const_cast<CallExpr*>(this)->getCalleeDecl();
}
/// \brief If the callee is a FunctionDecl, return it. Otherwise return 0.
FunctionDecl *getDirectCallee();
const FunctionDecl *getDirectCallee() const {
return const_cast<CallExpr*>(this)->getDirectCallee();
}
/// getNumArgs - Return the number of actual arguments to this call.
///
unsigned getNumArgs() const { return NumArgs; }
/// \brief Retrieve the call arguments.
Expr **getArgs() {
return reinterpret_cast<Expr **>(SubExprs+getNumPreArgs()+PREARGS_START);
}
const Expr *const *getArgs() const {
return const_cast<CallExpr*>(this)->getArgs();
}
/// getArg - Return the specified argument.
Expr *getArg(unsigned Arg) {
assert(Arg < NumArgs && "Arg access out of range!");
return cast_or_null<Expr>(SubExprs[Arg + getNumPreArgs() + PREARGS_START]);
}
const Expr *getArg(unsigned Arg) const {
assert(Arg < NumArgs && "Arg access out of range!");
return cast_or_null<Expr>(SubExprs[Arg + getNumPreArgs() + PREARGS_START]);
}
/// setArg - Set the specified argument.
void setArg(unsigned Arg, Expr *ArgExpr) {
assert(Arg < NumArgs && "Arg access out of range!");
SubExprs[Arg+getNumPreArgs()+PREARGS_START] = ArgExpr;
}
/// setNumArgs - This changes the number of arguments present in this call.
/// Any orphaned expressions are deleted by this, and any new operands are set
/// to null.
void setNumArgs(const ASTContext& C, unsigned NumArgs);
typedef ExprIterator arg_iterator;
typedef ConstExprIterator const_arg_iterator;
typedef llvm::iterator_range<arg_iterator> arg_range;
typedef llvm::iterator_range<const_arg_iterator> arg_const_range;
arg_range arguments() { return arg_range(arg_begin(), arg_end()); }
arg_const_range arguments() const {
return arg_const_range(arg_begin(), arg_end());
}
arg_iterator arg_begin() { return SubExprs+PREARGS_START+getNumPreArgs(); }
arg_iterator arg_end() {
return SubExprs+PREARGS_START+getNumPreArgs()+getNumArgs();
}
const_arg_iterator arg_begin() const {
return SubExprs+PREARGS_START+getNumPreArgs();
}
const_arg_iterator arg_end() const {
return SubExprs+PREARGS_START+getNumPreArgs()+getNumArgs();
}
/// This method provides fast access to all the subexpressions of
/// a CallExpr without going through the slower virtual child_iterator
/// interface. This provides efficient reverse iteration of the
/// subexpressions. This is currently used for CFG construction.
ArrayRef<Stmt*> getRawSubExprs() {
return llvm::makeArrayRef(SubExprs,
getNumPreArgs() + PREARGS_START + getNumArgs());
}
/// getNumCommas - Return the number of commas that must have been present in
/// this function call.
unsigned getNumCommas() const { return NumArgs ? NumArgs - 1 : 0; }
/// getBuiltinCallee - If this is a call to a builtin, return the builtin ID
/// of the callee. If not, return 0.
unsigned getBuiltinCallee() const;
/// \brief Returns \c true if this is a call to a builtin which does not
/// evaluate side-effects within its arguments.
bool isUnevaluatedBuiltinCall(const ASTContext &Ctx) const;
/// getCallReturnType - Get the return type of the call expr. This is not
/// always the type of the expr itself, if the return type is a reference
/// type.
QualType getCallReturnType(const ASTContext &Ctx) const;
SourceLocation getRParenLoc() const { return RParenLoc; }
void setRParenLoc(SourceLocation L) { RParenLoc = L; }
SourceLocation getLocStart() const LLVM_READONLY;
SourceLocation getLocEnd() const LLVM_READONLY;
static bool classof(const Stmt *T) {
return T->getStmtClass() >= firstCallExprConstant &&
T->getStmtClass() <= lastCallExprConstant;
}
// Iterators
child_range children() {
return child_range(&SubExprs[0],
&SubExprs[0]+NumArgs+getNumPreArgs()+PREARGS_START);
}
};
/// MemberExpr - [C99 6.5.2.3] Structure and Union Members. X->F and X.F.
///
class LLVM_ALIGNAS(/*alignof(uint64_t)*/ 8) MemberExpr : public Expr {
/// Extra data stored in some member expressions.
struct LLVM_ALIGNAS(/*alignof(uint64_t)*/ 8) 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.
DeclAccessPair FoundDecl;
};
/// Base - the expression for the base pointer or structure references. In
/// X.F, this is "X".
Stmt *Base;
/// MemberDecl - This is the decl being referenced by the field/member name.
/// In X.F, this is the decl referenced by F.
ValueDecl *MemberDecl;
/// MemberDNLoc - Provides source/type location info for the
/// declaration name embedded in MemberDecl.
DeclarationNameLoc MemberDNLoc;
/// MemberLoc - This is the location of the member name.
SourceLocation MemberLoc;
/// This is the location of the -> or . in the expression.
SourceLocation OperatorLoc;
/// IsArrow - True if this is "X->F", false if this is "X.F".
bool IsArrow : 1;
/// \brief True if this member expression used a nested-name-specifier to
/// refer to the member, e.g., "x->Base::f", or found its member via a using
/// declaration. When true, a MemberNameQualifier
/// structure is allocated immediately after the MemberExpr.
bool HasQualifierOrFoundDecl : 1;
/// \brief True if this member expression specified a template keyword
/// and/or a template argument list explicitly, e.g., x->f<int>,
/// x->template f, x->template f<int>.
/// When true, an ASTTemplateKWAndArgsInfo structure and its
/// TemplateArguments (if any) are allocated immediately after
/// the MemberExpr or, if the member expression also has a qualifier,
/// after the MemberNameQualifier structure.
bool HasTemplateKWAndArgsInfo : 1;
/// \brief True if this member expression refers to a method that
/// was resolved from an overloaded set having size greater than 1.
bool HadMultipleCandidates : 1;
/// \brief Retrieve the qualifier that preceded the member name, if any.
MemberNameQualifier *getMemberQualifier() {
assert(HasQualifierOrFoundDecl);
return reinterpret_cast<MemberNameQualifier *> (this + 1);
}
/// \brief Retrieve the qualifier that preceded the member name, if any.
const MemberNameQualifier *getMemberQualifier() const {
return const_cast<MemberExpr *>(this)->getMemberQualifier();
}
public:
MemberExpr(Expr *base, bool isarrow, SourceLocation operatorloc,
ValueDecl *memberdecl, const DeclarationNameInfo &NameInfo,
QualType ty, ExprValueKind VK, ExprObjectKind OK)
: Expr(MemberExprClass, ty, VK, OK, base->isTypeDependent(),
base->isValueDependent(), base->isInstantiationDependent(),
base->containsUnexpandedParameterPack()),
Base(base), MemberDecl(memberdecl), MemberDNLoc(NameInfo.getInfo()),
MemberLoc(NameInfo.getLoc()), OperatorLoc(operatorloc),
IsArrow(isarrow), HasQualifierOrFoundDecl(false),
HasTemplateKWAndArgsInfo(false), HadMultipleCandidates(false) {
assert(memberdecl->getDeclName() == NameInfo.getName());
}
// NOTE: this constructor should be used only when it is known that
// the member name can not provide additional syntactic info
// (i.e., source locations for C++ operator names or type source info
// for constructors, destructors and conversion operators).
MemberExpr(Expr *base, bool isarrow, SourceLocation operatorloc,
ValueDecl *memberdecl, SourceLocation l, QualType ty,
ExprValueKind VK, ExprObjectKind OK)
: Expr(MemberExprClass, ty, VK, OK, base->isTypeDependent(),
base->isValueDependent(), base->isInstantiationDependent(),
base->containsUnexpandedParameterPack()),
Base(base), MemberDecl(memberdecl), MemberDNLoc(), MemberLoc(l),
OperatorLoc(operatorloc), IsArrow(isarrow),
HasQualifierOrFoundDecl(false), HasTemplateKWAndArgsInfo(false),
HadMultipleCandidates(false) {}
static MemberExpr *Create(const ASTContext &C, Expr *base, bool isarrow,
SourceLocation OperatorLoc,
NestedNameSpecifierLoc QualifierLoc,
SourceLocation TemplateKWLoc, ValueDecl *memberdecl,
DeclAccessPair founddecl,
DeclarationNameInfo MemberNameInfo,
const TemplateArgumentListInfo *targs, QualType ty,
ExprValueKind VK, ExprObjectKind OK);
void setBase(Expr *E) { Base = E; }
Expr *getBase() const { return cast<Expr>(Base); }
/// \brief Retrieve the member declaration to which this expression refers.
///
/// The returned declaration will either be a FieldDecl or (in C++)
/// a CXXMethodDecl.
ValueDecl *getMemberDecl() const { return MemberDecl; }
void setMemberDecl(ValueDecl *D) { MemberDecl = D; }
/// \brief Retrieves the declaration found by lookup.
DeclAccessPair getFoundDecl() const {
if (!HasQualifierOrFoundDecl)
return DeclAccessPair::make(getMemberDecl(),
getMemberDecl()->getAccess());
return getMemberQualifier()->FoundDecl;
}
/// \brief Determines whether this member expression actually had
/// a C++ nested-name-specifier prior to the name of the member, e.g.,
/// x->Base::foo.
bool hasQualifier() const { return getQualifier() != nullptr; }
/// \brief If the member name was qualified, retrieves the
/// nested-name-specifier that precedes the member name. Otherwise, returns
/// NULL.
NestedNameSpecifier *getQualifier() const {
if (!HasQualifierOrFoundDecl)
return nullptr;
return getMemberQualifier()->QualifierLoc.getNestedNameSpecifier();
}
/// \brief If the member name was qualified, retrieves the
/// nested-name-specifier that precedes the member name, with source-location
/// information.
NestedNameSpecifierLoc getQualifierLoc() const {
if (!hasQualifier())
return NestedNameSpecifierLoc();
return getMemberQualifier()->QualifierLoc;
}
/// \brief Return the optional template keyword and arguments info.
ASTTemplateKWAndArgsInfo *getTemplateKWAndArgsInfo() {
if (!HasTemplateKWAndArgsInfo)
return nullptr;
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;
}
/// Determines whether the member name was preceded by the template keyword.
bool hasTemplateKeyword() const { return getTemplateKeywordLoc().isValid(); }
/// \brief Determines whether the member name was followed by an
/// explicit template argument list.
bool hasExplicitTemplateArgs() const { return getLAngleLoc().isValid(); }
/// \brief Copies the template arguments (if present) into the given
/// structure.
void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const {
if (hasExplicitTemplateArgs())
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.
ASTTemplateArgumentListInfo &getExplicitTemplateArgs() {
assert(hasExplicitTemplateArgs());
return *getTemplateKWAndArgsInfo();
}
/// \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.
const ASTTemplateArgumentListInfo &getExplicitTemplateArgs() const {
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.
const ASTTemplateArgumentListInfo *getOptionalExplicitTemplateArgs() const {
if (!hasExplicitTemplateArgs()) return nullptr;
return &getExplicitTemplateArgs();
}
/// \brief Retrieve the template arguments provided as part of this
/// template-id.
const TemplateArgumentLoc *getTemplateArgs() const {
if (!hasExplicitTemplateArgs())
return nullptr;
return getExplicitTemplateArgs().getTemplateArgs();
}
/// \brief Retrieve the number of template arguments provided as part of this
/// template-id.
unsigned getNumTemplateArgs() const {
if (!hasExplicitTemplateArgs())
return 0;
return getExplicitTemplateArgs().NumTemplateArgs;
}
/// \brief Retrieve the member declaration name info.
DeclarationNameInfo getMemberNameInfo() const {
return DeclarationNameInfo(MemberDecl->getDeclName(),
MemberLoc, MemberDNLoc);
}
SourceLocation getOperatorLoc() const LLVM_READONLY { return OperatorLoc; }
bool isArrow() const { return IsArrow; }
void setArrow(bool A) { IsArrow = A; }
/// getMemberLoc - Return the location of the "member", in X->F, it is the
/// location of 'F'.
SourceLocation getMemberLoc() const { return MemberLoc; }
void setMemberLoc(SourceLocation L) { MemberLoc = L; }
SourceLocation getLocStart() const LLVM_READONLY;
SourceLocation getLocEnd() const LLVM_READONLY;
SourceLocation getExprLoc() const LLVM_READONLY { return MemberLoc; }
/// \brief Determine whether the base of this explicit is implicit.
bool isImplicitAccess() const {
return getBase() && getBase()->isImplicitCXXThis();
}
/// \brief Returns true if this member expression refers to a method that
/// was resolved from an overloaded set having size greater than 1.
bool hadMultipleCandidates() const {
return HadMultipleCandidates;
}
/// \brief Sets the flag telling whether this expression refers to
/// a method that was resolved from an overloaded set having size
/// greater than 1.
void setHadMultipleCandidates(bool V = true) {
HadMultipleCandidates = V;
}
/// \brief Returns true if virtual dispatch is performed.
/// If the member access is fully qualified, (i.e. X::f()), virtual
/// dispatching is not performed. In -fapple-kext mode qualified
/// calls to virtual method will still go through the vtable.
bool performsVirtualDispatch(const LangOptions &LO) const {
return LO.AppleKext || !hasQualifier();
}
static bool classof(const Stmt *T) {
return T->getStmtClass() == MemberExprClass;
}
// Iterators
child_range children() { return child_range(&Base, &Base+1); }
friend class ASTReader;
friend class ASTStmtWriter;
};
/// CompoundLiteralExpr - [C99 6.5.2.5]
///
class CompoundLiteralExpr : public Expr {
/// LParenLoc - If non-null, this is the location of the left paren in a
/// compound literal like "(int){4}". This can be null if this is a
/// synthesized compound expression.
SourceLocation LParenLoc;
/// The type as written. This can be an incomplete array type, in
/// which case the actual expression type will be different.
/// The int part of the pair stores whether this expr is file scope.
llvm::PointerIntPair<TypeSourceInfo *, 1, bool> TInfoAndScope;
Stmt *Init;
public:
CompoundLiteralExpr(SourceLocation lparenloc, TypeSourceInfo *tinfo,
QualType T, ExprValueKind VK, Expr *init, bool fileScope)
: Expr(CompoundLiteralExprClass, T, VK, OK_Ordinary,
tinfo->getType()->isDependentType(),
init->isValueDependent(),
(init->isInstantiationDependent() ||
tinfo->getType()->isInstantiationDependentType()),
init->containsUnexpandedParameterPack()),
LParenLoc(lparenloc), TInfoAndScope(tinfo, fileScope), Init(init) {}
/// \brief Construct an empty compound literal.
explicit CompoundLiteralExpr(EmptyShell Empty)
: Expr(CompoundLiteralExprClass, Empty) { }
const Expr *getInitializer() const { return cast<Expr>(Init); }
Expr *getInitializer() { return cast<Expr>(Init); }
void setInitializer(Expr *E) { Init = E; }
bool isFileScope() const { return TInfoAndScope.getInt(); }
void setFileScope(bool FS) { TInfoAndScope.setInt(FS); }
SourceLocation getLParenLoc() const { return LParenLoc; }
void setLParenLoc(SourceLocation L) { LParenLoc = L; }
TypeSourceInfo *getTypeSourceInfo() const {
return TInfoAndScope.getPointer();
}
void setTypeSourceInfo(TypeSourceInfo *tinfo) {
TInfoAndScope.setPointer(tinfo);
}
SourceLocation getLocStart() const LLVM_READONLY {
// FIXME: Init should never be null.
if (!Init)
return SourceLocation();
if (LParenLoc.isInvalid())
return Init->getLocStart();
return LParenLoc;
}
SourceLocation getLocEnd() const LLVM_READONLY {
// FIXME: Init should never be null.
if (!Init)
return SourceLocation();
return Init->getLocEnd();
}
static bool classof(const Stmt *T) {
return T->getStmtClass() == CompoundLiteralExprClass;
}
// Iterators
child_range children() { return child_range(&Init, &Init+1); }
};
/// CastExpr - Base class for type casts, including both implicit
/// casts (ImplicitCastExpr) and explicit casts that have some
/// representation in the source code (ExplicitCastExpr's derived
/// classes).
class CastExpr : public Expr {
private:
Stmt *Op;
bool CastConsistency() const;
const CXXBaseSpecifier * const *path_buffer() const {
return const_cast<CastExpr*>(this)->path_buffer();
}
CXXBaseSpecifier **path_buffer();
void setBasePathSize(unsigned basePathSize) {
CastExprBits.BasePathSize = basePathSize;
assert(CastExprBits.BasePathSize == basePathSize &&
"basePathSize doesn't fit in bits of CastExprBits.BasePathSize!");
}
protected:
CastExpr(StmtClass SC, QualType ty, ExprValueKind VK, const CastKind kind,
Expr *op, unsigned BasePathSize)
: Expr(SC, ty, VK, OK_Ordinary,
// Cast expressions are type-dependent if the type is
// dependent (C++ [temp.dep.expr]p3).
ty->isDependentType(),
// Cast expressions are value-dependent if the type is
// dependent or if the subexpression is value-dependent.
ty->isDependentType() || (op && op->isValueDependent()),
(ty->isInstantiationDependentType() ||
(op && op->isInstantiationDependent())),
// An implicit cast expression doesn't (lexically) contain an
// unexpanded pack, even if its target type does.
((SC != ImplicitCastExprClass &&
ty->containsUnexpandedParameterPack()) ||
(op && op->containsUnexpandedParameterPack()))),
Op(op) {
assert(kind != CK_Invalid && "creating cast with invalid cast kind");
CastExprBits.Kind = kind;
setBasePathSize(BasePathSize);
assert(CastConsistency());
}
/// \brief Construct an empty cast.
CastExpr(StmtClass SC, EmptyShell Empty, unsigned BasePathSize)
: Expr(SC, Empty) {
setBasePathSize(BasePathSize);
}
public:
CastKind getCastKind() const { return (CastKind) CastExprBits.Kind; }
void setCastKind(CastKind K) { CastExprBits.Kind = K; }
const char *getCastKindName() const;
Expr *getSubExpr() { return cast<Expr>(Op); }
const Expr *getSubExpr() const { return cast<Expr>(Op); }
void setSubExpr(Expr *E) { Op = E; }
/// \brief Retrieve the cast subexpression as it was written in the source
/// code, looking through any implicit casts or other intermediate nodes
/// introduced by semantic analysis.
Expr *getSubExprAsWritten();
const Expr *getSubExprAsWritten() const {
return const_cast<CastExpr *>(this)->getSubExprAsWritten();
}
typedef CXXBaseSpecifier **path_iterator;
typedef const CXXBaseSpecifier * const *path_const_iterator;
bool path_empty() const { return CastExprBits.BasePathSize == 0; }
unsigned path_size() const { return CastExprBits.BasePathSize; }
path_iterator path_begin() { return path_buffer(); }
path_iterator path_end() { return path_buffer() + path_size(); }
path_const_iterator path_begin() const { return path_buffer(); }
path_const_iterator path_end() const { return path_buffer() + path_size(); }
void setCastPath(const CXXCastPath &Path);
static bool classof(const Stmt *T) {
return T->getStmtClass() >= firstCastExprConstant &&
T->getStmtClass() <= lastCastExprConstant;
}
// Iterators
child_range children() { return child_range(&Op, &Op+1); }
};
/// ImplicitCastExpr - Allows us to explicitly represent implicit type
/// conversions, which have no direct representation in the original
/// source code. For example: converting T[]->T*, void f()->void
/// (*f)(), float->double, short->int, etc.
///
/// In C, implicit casts always produce rvalues. However, in C++, an
/// implicit cast whose result is being bound to a reference will be
/// an lvalue or xvalue. For example:
///
/// @code
/// class Base { };
/// class Derived : public Base { };
/// Derived &&ref();
/// void f(Derived d) {
/// Base& b = d; // initializer is an ImplicitCastExpr
/// // to an lvalue of type Base
/// Base&& r = ref(); // initializer is an ImplicitCastExpr
/// // to an xvalue of type Base
/// }
/// @endcode
class ImplicitCastExpr : public CastExpr {
private:
ImplicitCastExpr(QualType ty, CastKind kind, Expr *op,
unsigned BasePathLength, ExprValueKind VK)
: CastExpr(ImplicitCastExprClass, ty, VK, kind, op, BasePathLength) {
}
/// \brief Construct an empty implicit cast.
explicit ImplicitCastExpr(EmptyShell Shell, unsigned PathSize)
: CastExpr(ImplicitCastExprClass, Shell, PathSize) { }
public:
enum OnStack_t { OnStack };
ImplicitCastExpr(OnStack_t _, QualType ty, CastKind kind, Expr *op,
ExprValueKind VK)
: CastExpr(ImplicitCastExprClass, ty, VK, kind, op, 0) {
}
static ImplicitCastExpr *Create(const ASTContext &Context, QualType T,
CastKind Kind, Expr *Operand,
const CXXCastPath *BasePath,
ExprValueKind Cat);
static ImplicitCastExpr *CreateEmpty(const ASTContext &Context,
unsigned PathSize);
SourceLocation getLocStart() const LLVM_READONLY {
return getSubExpr()->getLocStart();
}
SourceLocation getLocEnd() const LLVM_READONLY {
return getSubExpr()->getLocEnd();
}
static bool classof(const Stmt *T) {
return T->getStmtClass() == ImplicitCastExprClass;
}
};
inline Expr *Expr::IgnoreImpCasts() {
Expr *e = this;
while (ImplicitCastExpr *ice = dyn_cast<ImplicitCastExpr>(e))
e = ice->getSubExpr();
return e;
}
/// ExplicitCastExpr - An explicit cast written in the source
/// code.
///
/// This class is effectively an abstract class, because it provides
/// the basic representation of an explicitly-written cast without
/// specifying which kind of cast (C cast, functional cast, static
/// cast, etc.) was written; specific derived classes represent the
/// particular style of cast and its location information.
///
/// Unlike implicit casts, explicit cast nodes have two different
/// types: the type that was written into the source code, and the
/// actual type of the expression as determined by semantic
/// analysis. These types may differ slightly. For example, in C++ one
/// can cast to a reference type, which indicates that the resulting
/// expression will be an lvalue or xvalue. The reference type, however,
/// will not be used as the type of the expression.
class ExplicitCastExpr : public CastExpr {
/// TInfo - Source type info for the (written) type
/// this expression is casting to.
TypeSourceInfo *TInfo;
protected:
ExplicitCastExpr(StmtClass SC, QualType exprTy, ExprValueKind VK,
CastKind kind, Expr *op, unsigned PathSize,
TypeSourceInfo *writtenTy)
: CastExpr(SC, exprTy, VK, kind, op, PathSize), TInfo(writtenTy) {}
/// \brief Construct an empty explicit cast.
ExplicitCastExpr(StmtClass SC, EmptyShell Shell, unsigned PathSize)
: CastExpr(SC, Shell, PathSize) { }
public:
/// getTypeInfoAsWritten - Returns the type source info for the type
/// that this expression is casting to.
TypeSourceInfo *getTypeInfoAsWritten() const { return TInfo; }
void setTypeInfoAsWritten(TypeSourceInfo *writtenTy) { TInfo = writtenTy; }
/// getTypeAsWritten - Returns the type that this expression is
/// casting to, as written in the source code.
QualType getTypeAsWritten() const { return TInfo->getType(); }
static bool classof(const Stmt *T) {
return T->getStmtClass() >= firstExplicitCastExprConstant &&
T->getStmtClass() <= lastExplicitCastExprConstant;
}
};
/// CStyleCastExpr - An explicit cast in C (C99 6.5.4) or a C-style
/// cast in C++ (C++ [expr.cast]), which uses the syntax
/// (Type)expr. For example: @c (int)f.
class CStyleCastExpr : public ExplicitCastExpr {
SourceLocation LPLoc; // the location of the left paren
SourceLocation RPLoc; // the location of the right paren
CStyleCastExpr(QualType exprTy, ExprValueKind vk, CastKind kind, Expr *op,
unsigned PathSize, TypeSourceInfo *writtenTy,
SourceLocation l, SourceLocation r)
: ExplicitCastExpr(CStyleCastExprClass, exprTy, vk, kind, op, PathSize,
writtenTy), LPLoc(l), RPLoc(r) {}
/// \brief Construct an empty C-style explicit cast.
explicit CStyleCastExpr(EmptyShell Shell, unsigned PathSize)
: ExplicitCastExpr(CStyleCastExprClass, Shell, PathSize) { }
public:
static CStyleCastExpr *Create(const ASTContext &Context, QualType T,
ExprValueKind VK, CastKind K,
Expr *Op, const CXXCastPath *BasePath,
TypeSourceInfo *WrittenTy, SourceLocation L,
SourceLocation R);
static CStyleCastExpr *CreateEmpty(const ASTContext &Context,
unsigned PathSize);
SourceLocation getLParenLoc() const { return LPLoc; }
void setLParenLoc(SourceLocation L) { LPLoc = L; }
SourceLocation getRParenLoc() const { return RPLoc; }
void setRParenLoc(SourceLocation L) { RPLoc = L; }
SourceLocation getLocStart() const LLVM_READONLY { return LPLoc; }
SourceLocation getLocEnd() const LLVM_READONLY {
return getSubExpr()->getLocEnd();
}
static bool classof(const Stmt *T) {
return T->getStmtClass() == CStyleCastExprClass;
}
};
/// \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:
typedef BinaryOperatorKind Opcode;
private:
unsigned Opc : 6;
// 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;
SourceLocation OpLoc;
enum { LHS, RHS, END_EXPR };
Stmt* SubExprs[END_EXPR];
public:
BinaryOperator(Expr *lhs, Expr *rhs, Opcode opc, QualType ResTy,
ExprValueKind VK, ExprObjectKind OK,
SourceLocation opLoc, bool fpContractable)
: Expr(BinaryOperatorClass, ResTy, VK, OK,
lhs->isTypeDependent() || rhs->isTypeDependent(),
lhs->isValueDependent() || rhs->isValueDependent(),
(lhs->isInstantiationDependent() ||
rhs->isInstantiationDependent()),
(lhs->containsUnexpandedParameterPack() ||
rhs->containsUnexpandedParameterPack())),
Opc(opc), FPContractable(fpContractable), OpLoc(opLoc) {
SubExprs[LHS] = lhs;
SubExprs[RHS] = rhs;
assert(!isCompoundAssignmentOp() &&
"Use CompoundAssignOperator for compound assignments");
}
/// \brief Construct an empty binary operator.
explicit BinaryOperator(EmptyShell Empty)
: Expr(BinaryOperatorClass, Empty), Opc(BO_Comma) { }
SourceLocation getExprLoc() const LLVM_READONLY { return OpLoc; }
SourceLocation getOperatorLoc() const { return OpLoc; }
void setOperatorLoc(SourceLocation L) { OpLoc = L; }
Opcode getOpcode() const { return static_cast<Opcode>(Opc); }
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; }
SourceLocation getLocStart() const LLVM_READONLY {
return getLHS()->getLocStart();
}
SourceLocation getLocEnd() const LLVM_READONLY {
return getRHS()->getLocEnd();
}
/// getOpcodeStr - Turn an Opcode enum value into the punctuation char it
/// corresponds to, e.g. "<<=".
static StringRef getOpcodeStr(Opcode Op);
StringRef getOpcodeStr() const { return getOpcodeStr(getOpcode()); }
/// \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.
bool isPtrMemOp() const { return Opc == BO_PtrMemD || Opc == BO_PtrMemI; }
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()); }
static bool isBitwiseOp(Opcode Opc) { return Opc >= BO_And && Opc <= BO_Or; }
bool isBitwiseOp() const { return isBitwiseOp(getOpcode()); }
static bool isRelationalOp(Opcode Opc) { return Opc >= BO_LT && Opc<=BO_GE; }
bool isRelationalOp() const { return isRelationalOp(getOpcode()); }
static bool isEqualityOp(Opcode Opc) { return Opc == BO_EQ || Opc == BO_NE; }
bool isEqualityOp() const { return isEqualityOp(getOpcode()); }
static bool isComparisonOp(Opcode Opc) { return Opc >= BO_LT && Opc<=BO_NE; }
bool isComparisonOp() const { return isComparisonOp(getOpcode()); }
static Opcode negateComparisonOp(Opcode Opc) {
switch (Opc) {
default:
llvm_unreachable("Not a comparsion operator.");
case BO_LT: return BO_GE;
case BO_GT: return BO_LE;
case BO_LE: return BO_GT;
case BO_GE: return BO_LT;
case BO_EQ: return BO_NE;
case BO_NE: return BO_EQ;
}
}
static Opcode reverseComparisonOp(Opcode Opc) {
switch (Opc) {
default:
llvm_unreachable("Not a comparsion operator.");
case BO_LT: return BO_GT;
case BO_GT: return BO_LT;
case BO_LE: return BO_GE;
case BO_GE: return BO_LE;
case BO_EQ:
case BO_NE:
return Opc;
}
}
static bool isLogicalOp(Opcode Opc) { return Opc == BO_LAnd || Opc==BO_LOr; }
bool isLogicalOp() const { return isLogicalOp(getOpcode()); }
static bool isAssignmentOp(Opcode Opc) {
return Opc >= BO_Assign && Opc <= BO_OrAssign;
}
bool isAssignmentOp() const { return isAssignmentOp(getOpcode()); }
static bool isCompoundAssignmentOp(Opcode Opc) {
return Opc > BO_Assign && Opc <= BO_OrAssign;
}
bool isCompoundAssignmentOp() const {
return isCompoundAssignmentOp(getOpcode());
}
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);
}
static bool isShiftAssignOp(Opcode Opc) {
return Opc == BO_ShlAssign || Opc == BO_ShrAssign;
}
bool isShiftAssignOp() const {
return isShiftAssignOp(getOpcode());
}
static bool classof(const Stmt *S) {
return S->getStmtClass() >= firstBinaryOperatorConstant &&
S->getStmtClass() <= lastBinaryOperatorConstant;
}
// Iterators
child_range children() {
return child_range(&SubExprs[0], &SubExprs[0]+END_EXPR);
}
// 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; }
protected:
BinaryOperator(Expr *lhs, Expr *rhs, Opcode opc, QualType ResTy,
ExprValueKind VK, ExprObjectKind OK,
SourceLocation opLoc, bool fpContractable, bool dead2)
: Expr(CompoundAssignOperatorClass, ResTy, VK, OK,
lhs->isTypeDependent() || rhs->isTypeDependent(),
lhs->isValueDependent() || rhs->isValueDependent(),
(lhs->isInstantiationDependent() ||
rhs->isInstantiationDependent()),
(lhs->containsUnexpandedParameterPack() ||
rhs->containsUnexpandedParameterPack())),
Opc(opc), FPContractable(fpContractable), OpLoc(opLoc) {
SubExprs[LHS] = lhs;
SubExprs[RHS] = rhs;
}
BinaryOperator(StmtClass SC, EmptyShell Empty)
: Expr(SC, Empty), Opc(BO_MulAssign) { }
};
/// CompoundAssignOperator - For compound assignments (e.g. +=), we keep
/// track of the type the operation is performed in. Due to the semantics of
/// these operators, the operands are promoted, the arithmetic performed, an
/// 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:
CompoundAssignOperator(Expr *lhs, Expr *rhs, Opcode opc, QualType ResType,
ExprValueKind VK, ExprObjectKind OK,
QualType CompLHSType, QualType CompResultType,
SourceLocation OpLoc, bool fpContractable)
: BinaryOperator(lhs, rhs, opc, ResType, VK, OK, OpLoc, fpContractable,
true),
ComputationLHSType(CompLHSType),
ComputationResultType(CompResultType) {
assert(isCompoundAssignmentOp() &&
"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; }
static bool classof(const Stmt *S) {
return S->getStmtClass() == CompoundAssignOperatorClass;
}
};
/// 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,
bool TD, bool VD, bool ID,
bool ContainsUnexpandedParameterPack,
SourceLocation qloc,
SourceLocation cloc)
: Expr(SC, T, VK, OK, TD, VD, ID, ContainsUnexpandedParameterPack),
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 {
enum { COND, LHS, RHS, END_EXPR };
Stmt* SubExprs[END_EXPR]; // Left/Middle/Right hand sides.
friend class ASTStmtReader;
public:
ConditionalOperator(Expr *cond, SourceLocation QLoc, Expr *lhs,
SourceLocation CLoc, Expr *rhs,
QualType t, ExprValueKind VK, ExprObjectKind OK)
: AbstractConditionalOperator(ConditionalOperatorClass, t, VK, OK,
// 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!
(lhs->isTypeDependent() || rhs->isTypeDependent()),
(cond->isValueDependent() || lhs->isValueDependent() ||
rhs->isValueDependent()),
(cond->isInstantiationDependent() ||
lhs->isInstantiationDependent() ||
rhs->isInstantiationDependent()),
(cond->containsUnexpandedParameterPack() ||
lhs->containsUnexpandedParameterPack() ||
rhs->containsUnexpandedParameterPack()),
QLoc, CLoc) {
SubExprs[COND] = cond;
SubExprs[LHS] = lhs;
SubExprs[RHS] = rhs;
}
/// \brief Build an empty conditional operator.
explicit ConditionalOperator(EmptyShell Empty)
: AbstractConditionalOperator(ConditionalOperatorClass, Empty) { }
// getCond - Return the expression representing the condition for
// the ?: operator.
Expr *getCond() const { return cast<Expr>(SubExprs[COND]); }
// getTrueExpr - Return the subexpression representing the value of
// the expression if the condition evaluates to true.
Expr *getTrueExpr() const { return cast<Expr>(SubExprs[LHS]); }
// 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 { return cast<Expr>(SubExprs[RHS]); }
Expr *getLHS() const { return cast<Expr>(SubExprs[LHS]); }
Expr *getRHS() const { return cast<Expr>(SubExprs[RHS]); }
SourceLocation getLocStart() const LLVM_READONLY {
return getCond()->getLocStart();
}
SourceLocation getLocEnd() const LLVM_READONLY {
return getRHS()->getLocEnd();
}
static bool classof(const Stmt *T) {
return T->getStmtClass() == ConditionalOperatorClass;
}
// Iterators
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()),
(common->isInstantiationDependent() ||
rhs->isInstantiationDependent()),
(common->containsUnexpandedParameterPack() ||
rhs->containsUnexpandedParameterPack()),
qloc, cloc),
OpaqueValue(opaqueValue) {
SubExprs[COMMON] = common;
SubExprs[COND] = cond;
SubExprs[LHS] = lhs;
SubExprs[RHS] = rhs;
assert(OpaqueValue->getSourceExpr() == common && "Wrong opaque value");
}
/// \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]);
}
SourceLocation getLocStart() const LLVM_READONLY {
return getCommon()->getLocStart();
}
SourceLocation getLocEnd() const LLVM_READONLY {
return getFalseExpr()->getLocEnd();
}
static bool classof(const Stmt *T) {
return T->getStmtClass() == BinaryConditionalOperatorClass;
}
// Iterators
child_range children() {
return child_range(SubExprs, SubExprs + NUM_SUBEXPRS);
}
};
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();
}
/// AddrLabelExpr - The GNU address of label extension, representing &&label.
class AddrLabelExpr : public Expr {
SourceLocation AmpAmpLoc, LabelLoc;
LabelDecl *Label;
public:
AddrLabelExpr(SourceLocation AALoc, SourceLocation LLoc, LabelDecl *L,
QualType t)
: Expr(AddrLabelExprClass, t, VK_RValue, OK_Ordinary, false, false, false,
false),
AmpAmpLoc(AALoc), LabelLoc(LLoc), Label(L) {}
/// \brief Build an empty address of a label expression.
explicit AddrLabelExpr(EmptyShell Empty)
: 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; }
SourceLocation getLocStart() const LLVM_READONLY { return AmpAmpLoc; }
SourceLocation getLocEnd() const LLVM_READONLY { return LabelLoc; }
LabelDecl *getLabel() const { return Label; }
void setLabel(LabelDecl *L) { Label = L; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == AddrLabelExprClass;
}
// Iterators
child_range children() {
return child_range(child_iterator(), child_iterator());
}
};
/// 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.
///
/// A StmtExpr is always an r-value; values "returned" out of a
/// StmtExpr will be copied.
class StmtExpr : public Expr {
Stmt *SubStmt;
SourceLocation LParenLoc, RParenLoc;
public:
// FIXME: Does type-dependence need to be computed differently?
// FIXME: Do we need to compute instantiation instantiation-dependence for
// statements? (ugh!)
StmtExpr(CompoundStmt *substmt, QualType T,
SourceLocation lp, SourceLocation rp) :
Expr(StmtExprClass, T, VK_RValue, OK_Ordinary,
T->isDependentType(), false, false, false),
SubStmt(substmt), LParenLoc(lp), RParenLoc(rp) { }
/// \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; }
SourceLocation getLocStart() const LLVM_READONLY { return LParenLoc; }
SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; }
SourceLocation getLParenLoc() const { return LParenLoc; }
void setLParenLoc(SourceLocation L) { LParenLoc = L; }
SourceLocation getRParenLoc() const { return RParenLoc; }
void setRParenLoc(SourceLocation L) { RParenLoc = L; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == StmtExprClass;
}
// Iterators
child_range children() { return child_range(&SubStmt, &SubStmt+1); }
};
/// 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:
ShuffleVectorExpr(const ASTContext &C, ArrayRef<Expr*> args, QualType Type,
SourceLocation BLoc, SourceLocation RP);
/// \brief Build an empty vector-shuffle expression.
explicit ShuffleVectorExpr(EmptyShell Empty)
: Expr(ShuffleVectorExprClass, Empty), SubExprs(nullptr) { }
SourceLocation getBuiltinLoc() const { return BuiltinLoc; }
void setBuiltinLoc(SourceLocation L) { BuiltinLoc = L; }
SourceLocation getRParenLoc() const { return RParenLoc; }
void setRParenLoc(SourceLocation L) { RParenLoc = L; }
SourceLocation getLocStart() const LLVM_READONLY { return BuiltinLoc; }
SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == ShuffleVectorExprClass;
}
/// 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; }
/// \brief Retrieve the array of expressions.
Expr **getSubExprs() { return reinterpret_cast<Expr **>(SubExprs); }
/// 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]);
}
void setExprs(const ASTContext &C, ArrayRef<Expr *> Exprs);
llvm::APSInt getShuffleMaskIdx(const ASTContext &Ctx, unsigned N) const {
assert((N < NumExprs - 2) && "Shuffle idx out of range!");
return getExpr(N+2)->EvaluateKnownConstInt(Ctx);
}
// Iterators
child_range children() {
return child_range(&SubExprs[0], &SubExprs[0]+NumExprs);
}
};
/// ConvertVectorExpr - Clang builtin function __builtin_convertvector
/// This AST node provides support for converting a vector type to another
/// vector type of the same arity.
class ConvertVectorExpr : public Expr {
private:
Stmt *SrcExpr;
TypeSourceInfo *TInfo;
SourceLocation BuiltinLoc, RParenLoc;
friend class ASTReader;
friend class ASTStmtReader;
explicit ConvertVectorExpr(EmptyShell Empty) : Expr(ConvertVectorExprClass, Empty) {}
public:
ConvertVectorExpr(Expr* SrcExpr, TypeSourceInfo *TI, QualType DstType,
ExprValueKind VK, ExprObjectKind OK,
SourceLocation BuiltinLoc, SourceLocation RParenLoc)
: Expr(ConvertVectorExprClass, DstType, VK, OK,
DstType->isDependentType(),
DstType->isDependentType() || SrcExpr->isValueDependent(),
(DstType->isInstantiationDependentType() ||
SrcExpr->isInstantiationDependent()),
(DstType->containsUnexpandedParameterPack() ||
SrcExpr->containsUnexpandedParameterPack())),
SrcExpr(SrcExpr), TInfo(TI), BuiltinLoc(BuiltinLoc), RParenLoc(RParenLoc) {}
/// getSrcExpr - Return the Expr to be converted.
Expr *getSrcExpr() const { return cast<Expr>(SrcExpr); }
/// getTypeSourceInfo - Return the destination type.
TypeSourceInfo *getTypeSourceInfo() const {
return TInfo;
}
void setTypeSourceInfo(TypeSourceInfo *ti) {
TInfo = ti;
}
/// getBuiltinLoc - Return the location of the __builtin_convertvector token.
SourceLocation getBuiltinLoc() const { return BuiltinLoc; }
/// getRParenLoc - Return the location of final right parenthesis.
SourceLocation getRParenLoc() const { return RParenLoc; }
SourceLocation getLocStart() const LLVM_READONLY { return BuiltinLoc; }
SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == ConvertVectorExprClass;
}
// Iterators
child_range children() { return child_range(&SrcExpr, &SrcExpr+1); }
};
/// ChooseExpr - GNU builtin-in function __builtin_choose_expr.
/// This AST node is similar to the conditional operator (?:) in C, with
/// 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;
bool CondIsTrue;
public:
ChooseExpr(SourceLocation BLoc, Expr *cond, Expr *lhs, Expr *rhs,
QualType t, ExprValueKind VK, ExprObjectKind OK,
SourceLocation RP, bool condIsTrue,
bool TypeDependent, bool ValueDependent)
: Expr(ChooseExprClass, t, VK, OK, TypeDependent, ValueDependent,
(cond->isInstantiationDependent() ||
lhs->isInstantiationDependent() ||
rhs->isInstantiationDependent()),
(cond->containsUnexpandedParameterPack() ||
lhs->containsUnexpandedParameterPack() ||
rhs->containsUnexpandedParameterPack())),
BuiltinLoc(BLoc), RParenLoc(RP), CondIsTrue(condIsTrue) {
SubExprs[COND] = cond;
SubExprs[LHS] = lhs;
SubExprs[RHS] = rhs;
}
/// \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).
bool isConditionTrue() const {
assert(!isConditionDependent() &&
"Dependent condition isn't true or false");
return CondIsTrue;
}
void setIsConditionTrue(bool isTrue) { CondIsTrue = isTrue; }
bool isConditionDependent() const {
return getCond()->isTypeDependent() || getCond()->isValueDependent();
}
/// getChosenSubExpr - Return the subexpression chosen according to the
/// condition.
Expr *getChosenSubExpr() const {
return isConditionTrue() ? 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; }
SourceLocation getRParenLoc() const { return RParenLoc; }
void setRParenLoc(SourceLocation L) { RParenLoc = L; }
SourceLocation getLocStart() const LLVM_READONLY { return BuiltinLoc; }
SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == ChooseExprClass;
}
// Iterators
child_range children() {
return child_range(&SubExprs[0], &SubExprs[0]+END_EXPR);
}
};
/// 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:
GNUNullExpr(QualType Ty, SourceLocation Loc)
: Expr(GNUNullExprClass, Ty, VK_RValue, OK_Ordinary, false, false, false,
false),
TokenLoc(Loc) { }
/// \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; }
SourceLocation getLocStart() const LLVM_READONLY { return TokenLoc; }
SourceLocation getLocEnd() const LLVM_READONLY { return TokenLoc; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == GNUNullExprClass;
}
// Iterators
child_range children() {
return child_range(child_iterator(), child_iterator());
}
};
/// Represents a call to the builtin function \c __builtin_va_arg.
class VAArgExpr : public Expr {
Stmt *Val;
llvm::PointerIntPair<TypeSourceInfo *, 1, bool> TInfo;
SourceLocation BuiltinLoc, RParenLoc;
public:
VAArgExpr(SourceLocation BLoc, Expr *e, TypeSourceInfo *TInfo,
SourceLocation RPLoc, QualType t, bool IsMS)
: Expr(VAArgExprClass, t, VK_RValue, OK_Ordinary, t->isDependentType(),
false, (TInfo->getType()->isInstantiationDependentType() ||
e->isInstantiationDependent()),
(TInfo->getType()->containsUnexpandedParameterPack() ||
e->containsUnexpandedParameterPack())),
Val(e), TInfo(TInfo, IsMS), BuiltinLoc(BLoc), RParenLoc(RPLoc) {}
/// Create an empty __builtin_va_arg expression.
explicit VAArgExpr(EmptyShell Empty)
: Expr(VAArgExprClass, Empty), Val(nullptr), TInfo(nullptr, false) {}
const Expr *getSubExpr() const { return cast<Expr>(Val); }
Expr *getSubExpr() { return cast<Expr>(Val); }
void setSubExpr(Expr *E) { Val = E; }
/// Returns whether this is really a Win64 ABI va_arg expression.
bool isMicrosoftABI() const { return TInfo.getInt(); }
void setIsMicrosoftABI(bool IsMS) { TInfo.setInt(IsMS); }
TypeSourceInfo *getWrittenTypeInfo() const { return TInfo.getPointer(); }
void setWrittenTypeInfo(TypeSourceInfo *TI) { TInfo.setPointer(TI); }
SourceLocation getBuiltinLoc() const { return BuiltinLoc; }
void setBuiltinLoc(SourceLocation L) { BuiltinLoc = L; }
SourceLocation getRParenLoc() const { return RParenLoc; }
void setRParenLoc(SourceLocation L) { RParenLoc = L; }
SourceLocation getLocStart() const LLVM_READONLY { return BuiltinLoc; }
SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == VAArgExprClass;
}
// Iterators
child_range children() { return child_range(&Val, &Val+1); }
};
/// @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.
///
/// 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).
/// Given the semantic form of the initializer list, one can retrieve
/// 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.
class InitListExpr : public Expr {
// FIXME: Eliminate this vector in favor of ASTContext allocation
typedef ASTVector<Stmt *> InitExprsTy;
InitExprsTy InitExprs;
SourceLocation LBraceLoc, RBraceLoc;
/// The alternative form of the initializer list (if it exists).
/// The int part of the pair stores whether this initializer 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;
/// \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;
public:
InitListExpr(const ASTContext &C, SourceLocation lbraceloc,
ArrayRef<Expr*> initExprs, SourceLocation rbraceloc);
/// \brief Build an empty initializer list.
explicit InitListExpr(EmptyShell Empty)
: Expr(InitListExprClass, Empty) { }
unsigned getNumInits() const { return InitExprs.size(); }
/// \brief Retrieve the set of initializers.
Expr **getInits() { return reinterpret_cast<Expr **>(InitExprs.data()); }
ArrayRef<Expr *> inits() {
return llvm::makeArrayRef(getInits(), getNumInits());
}
const Expr *getInit(unsigned Init) const {
assert(Init < getNumInits() && "Initializer access out of range!");
return cast_or_null<Expr>(InitExprs[Init]);
}
Expr *getInit(unsigned Init) {
assert(Init < getNumInits() && "Initializer access out of range!");
return cast_or_null<Expr>(InitExprs[Init]);
}
void setInit(unsigned Init, Expr *expr) {
assert(Init < getNumInits() && "Initializer access out of range!");
InitExprs[Init] = expr;
if (expr) {
ExprBits.TypeDependent |= expr->isTypeDependent();
ExprBits.ValueDependent |= expr->isValueDependent();
ExprBits.InstantiationDependent |= expr->isInstantiationDependent();
ExprBits.ContainsUnexpandedParameterPack |=
expr->containsUnexpandedParameterPack();
}
}
/// \brief Reserve space for some number of initializers.
void reserveInits(const ASTContext &C, unsigned NumInits);
/// @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(const 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
/// accommodate the new entry.
Expr *updateInit(const ASTContext &C, unsigned Init, Expr *expr);
/// \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 *>();
}
const Expr *getArrayFiller() const {
return const_cast<InitListExpr *>(this)->getArrayFiller();
}
void setArrayFiller(Expr *filler);
/// \brief Return true if this is an array initializer and its array "filler"
/// has been set.
bool hasArrayFiller() const { return getArrayFiller(); }
/// \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.
FieldDecl *getInitializedFieldInUnion() {
return ArrayFillerOrUnionFieldInit.dyn_cast<FieldDecl *>();
}
const FieldDecl *getInitializedFieldInUnion() const {
return const_cast<InitListExpr *>(this)->getInitializedFieldInUnion();
}
void setInitializedFieldInUnion(FieldDecl *FD) {
assert((FD == nullptr
|| getInitializedFieldInUnion() == nullptr
|| getInitializedFieldInUnion() == FD)
&& "Only one field of a union may be initialized at a time!");
ArrayFillerOrUnionFieldInit = FD;
}
// 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();
}
// Is this an initializer for an array of characters, initialized by a string
// literal or an @encode?
bool isStringLiteralInit() const;
SourceLocation getLBraceLoc() const { return LBraceLoc; }
void setLBraceLoc(SourceLocation Loc) { LBraceLoc = Loc; }
SourceLocation getRBraceLoc() const { return RBraceLoc; }
void setRBraceLoc(SourceLocation Loc) { RBraceLoc = Loc; }
bool isSemanticForm() const { return AltForm.getInt(); }
InitListExpr *getSemanticForm() const {
return isSemanticForm() ? nullptr : AltForm.getPointer();
}
InitListExpr *getSyntacticForm() const {
return isSemanticForm() ? AltForm.getPointer() : nullptr;
}
void setSyntacticForm(InitListExpr *Init) {
AltForm.setPointer(Init);
AltForm.setInt(true);
Init->AltForm.setPointer(this);
Init->AltForm.setInt(false);
}
bool hadArrayRangeDesignator() const {
return InitListExprBits.HadArrayRangeDesignator != 0;
}
void sawArrayRangeDesignator(bool ARD = true) {
InitListExprBits.HadArrayRangeDesignator = ARD;
}
SourceLocation getLocStart() const LLVM_READONLY;
SourceLocation getLocEnd() const LLVM_READONLY;
static bool classof(const Stmt *T) {
return T->getStmtClass() == InitListExprClass;
}
// Iterators
child_range children() {
// FIXME: This does not include the array filler expression.
if (InitExprs.empty())
return child_range(child_iterator(), child_iterator());
return child_range(&InitExprs[0], &InitExprs[0] + InitExprs.size());
}
typedef InitExprsTy::iterator iterator;
typedef InitExprsTy::const_iterator const_iterator;
typedef InitExprsTy::reverse_iterator reverse_iterator;
typedef InitExprsTy::const_reverse_iterator const_reverse_iterator;
iterator begin() { return InitExprs.begin(); }
const_iterator begin() const { return InitExprs.begin(); }
iterator end() { return InitExprs.end(); }
const_iterator end() const { return InitExprs.end(); }
reverse_iterator rbegin() { return InitExprs.rbegin(); }
const_reverse_iterator rbegin() const { return InitExprs.rbegin(); }
reverse_iterator rend() { return InitExprs.rend(); }
const_reverse_iterator rend() const { return InitExprs.rend(); }
friend class ASTStmtReader;
friend class ASTStmtWriter;
};
/// @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:
///
/// @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 initialization 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;
/// \brief The designators in this designated initialization
/// expression.
Designator *Designators;
DesignatedInitExpr(const ASTContext &C, QualType Ty, unsigned NumDesignators,
const Designator *Designators,
SourceLocation EqualOrColonLoc, bool GNUSyntax,
ArrayRef<Expr*> IndexExprs, Expr *Init);
explicit DesignatedInitExpr(unsigned NumSubExprs)
: Expr(DesignatedInitExprClass, EmptyShell()),
NumDesignators(0), NumSubExprs(NumSubExprs), Designators(nullptr) { }
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;
/// The location of the '.' in the designated initializer.
unsigned DotLoc;
/// 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.
unsigned RBracketLoc;
};
/// @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.
Designator(const IdentifierInfo *FieldName, SourceLocation DotLoc,
SourceLocation FieldLoc)
: Kind(FieldDesignator) {
Field.NameOrField = reinterpret_cast<uintptr_t>(FieldName) | 0x01;
Field.DotLoc = DotLoc.getRawEncoding();
Field.FieldLoc = FieldLoc.getRawEncoding();
}
/// @brief Initializes an array designator.
Designator(unsigned Index, SourceLocation LBracketLoc,
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.
Designator(unsigned Index, SourceLocation LBracketLoc,
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; }
IdentifierInfo *getFieldName() const;
FieldDecl *getField() const {
assert(Kind == FieldDesignator && "Only valid on a field designator");
if (Field.NameOrField & 0x01)
return nullptr;
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 getLocStart() const LLVM_READONLY {
if (Kind == FieldDesignator)
return getDotLoc().isInvalid()? getFieldLoc() : getDotLoc();
else
return getLBracketLoc();
}
SourceLocation getLocEnd() const LLVM_READONLY {
return Kind == FieldDesignator ? getFieldLoc() : getRBracketLoc();
}
SourceRange getSourceRange() const LLVM_READONLY {
return SourceRange(getLocStart(), getLocEnd());
}
};
static DesignatedInitExpr *Create(const ASTContext &C,
Designator *Designators,
unsigned NumDesignators,
ArrayRef<Expr*> IndexExprs,
SourceLocation EqualOrColonLoc,
bool GNUSyntax, Expr *Init);
static DesignatedInitExpr *CreateEmpty(const ASTContext &C,
unsigned NumIndexExprs);
/// @brief Returns the number of designators in this initializer.
unsigned size() const { return NumDesignators; }
// Iterator access to the designators.
typedef Designator *designators_iterator;
designators_iterator designators_begin() { return Designators; }
designators_iterator designators_end() {
return Designators + NumDesignators;
}
typedef const Designator *const_designators_iterator;
const_designators_iterator designators_begin() const { return Designators; }
const_designators_iterator designators_end() const {
return Designators + NumDesignators;
}
typedef llvm::iterator_range<designators_iterator> designators_range;
designators_range designators() {
return designators_range(designators_begin(), designators_end());
}
typedef llvm::iterator_range<const_designators_iterator>
designators_const_range;
designators_const_range designators() const {
return designators_const_range(designators_begin(), designators_end());
}
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());
}
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());
}
Designator *getDesignator(unsigned Idx) { return &designators_begin()[Idx]; }
void setDesignators(const ASTContext &C, const Designator *Desigs,
unsigned NumDesigs);
Expr *getArrayIndex(const Designator &D) const;
Expr *getArrayRangeStart(const Designator &D) const;
Expr *getArrayRangeEnd(const Designator &D) const;
/// @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.
Expr *getInit() const {
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) const {
assert(Idx < NumSubExprs && "Subscript out of range");
return cast<Expr>(reinterpret_cast<Stmt *const *>(this + 1)[Idx]);
}
void setSubExpr(unsigned Idx, Expr *E) {
assert(Idx < NumSubExprs && "Subscript out of range");
reinterpret_cast<Stmt **>(this + 1)[Idx] = E;
}
/// \brief Replaces the designator at index @p Idx with the series
/// of designators in [First, Last).
void ExpandDesignator(const ASTContext &C, unsigned Idx,
const Designator *First, const Designator *Last);
SourceRange getDesignatorsSourceRange() const;
SourceLocation getLocStart() const LLVM_READONLY;
SourceLocation getLocEnd() const LLVM_READONLY;
static bool classof(const Stmt *T) {
return T->getStmtClass() == DesignatedInitExprClass;
}
// Iterators
child_range children() {
Stmt **begin = reinterpret_cast<Stmt**>(this + 1);
return child_range(begin, begin + NumSubExprs);
}
};
/// \brief Represents a place-holder for an object not to be initialized by
/// anything.
///
/// This only makes sense when it appears as part of an updater of a
/// DesignatedInitUpdateExpr (see below). The base expression of a DIUE
/// initializes a big object, and the NoInitExpr's mark the spots within the
/// big object not to be overwritten by the updater.
///
/// \see DesignatedInitUpdateExpr
class NoInitExpr : public Expr {
public:
explicit NoInitExpr(QualType ty)
: Expr(NoInitExprClass, ty, VK_RValue, OK_Ordinary,
false, false, ty->isInstantiationDependentType(), false) { }
explicit NoInitExpr(EmptyShell Empty)
: Expr(NoInitExprClass, Empty) { }
static bool classof(const Stmt *T) {
return T->getStmtClass() == NoInitExprClass;
}
SourceLocation getLocStart() const LLVM_READONLY { return SourceLocation(); }
SourceLocation getLocEnd() const LLVM_READONLY { return SourceLocation(); }
// Iterators
child_range children() {
return child_range(child_iterator(), child_iterator());
}
};
// In cases like:
// struct Q { int a, b, c; };
// Q *getQ();
// void foo() {
// struct A { Q q; } a = { *getQ(), .q.b = 3 };
// }
//
// We will have an InitListExpr for a, with type A, and then a
// DesignatedInitUpdateExpr for "a.q" with type Q. The "base" for this DIUE
// is the call expression *getQ(); the "updater" for the DIUE is ".q.b = 3"
//
class DesignatedInitUpdateExpr : public Expr {
// BaseAndUpdaterExprs[0] is the base expression;
// BaseAndUpdaterExprs[1] is an InitListExpr overwriting part of the base.
Stmt *BaseAndUpdaterExprs[2];
public:
DesignatedInitUpdateExpr(const ASTContext &C, SourceLocation lBraceLoc,
Expr *baseExprs, SourceLocation rBraceLoc);
explicit DesignatedInitUpdateExpr(EmptyShell Empty)
: Expr(DesignatedInitUpdateExprClass, Empty) { }
SourceLocation getLocStart() const LLVM_READONLY;
SourceLocation getLocEnd() const LLVM_READONLY;
static bool classof(const Stmt *T) {
return T->getStmtClass() == DesignatedInitUpdateExprClass;
}
Expr *getBase() const { return cast<Expr>(BaseAndUpdaterExprs[0]); }
void setBase(Expr *Base) { BaseAndUpdaterExprs[0] = Base; }
InitListExpr *getUpdater() const {
return cast<InitListExpr>(BaseAndUpdaterExprs[1]);
}
void setUpdater(Expr *Updater) { BaseAndUpdaterExprs[1] = Updater; }
// Iterators
// children = the base and the updater
child_range children() {
return child_range(&BaseAndUpdaterExprs[0], &BaseAndUpdaterExprs[0] + 2);
}
};
/// \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
class ImplicitValueInitExpr : public Expr {
public:
explicit ImplicitValueInitExpr(QualType ty)
: Expr(ImplicitValueInitExprClass, ty, VK_RValue, OK_Ordinary,
false, false, ty->isInstantiationDependentType(), false) { }
/// \brief Construct an empty implicit value initialization.
explicit ImplicitValueInitExpr(EmptyShell Empty)
: Expr(ImplicitValueInitExprClass, Empty) { }
static bool classof(const Stmt *T) {
return T->getStmtClass() == ImplicitValueInitExprClass;
}
SourceLocation getLocStart() const LLVM_READONLY { return SourceLocation(); }
SourceLocation getLocEnd() const LLVM_READONLY { return SourceLocation(); }
// Iterators
child_range children() {
return child_range(child_iterator(), child_iterator());
}
};
class ParenListExpr : public Expr {
Stmt **Exprs;
unsigned NumExprs;
SourceLocation LParenLoc, RParenLoc;
public:
ParenListExpr(const ASTContext& C, SourceLocation lparenloc,
ArrayRef<Expr*> exprs, SourceLocation rparenloc);
/// \brief Build an empty paren list.
explicit ParenListExpr(EmptyShell Empty) : Expr(ParenListExprClass, Empty) { }
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); }
ArrayRef<Expr *> exprs() {
return llvm::makeArrayRef(getExprs(), getNumExprs());
}
SourceLocation getLParenLoc() const { return LParenLoc; }
SourceLocation getRParenLoc() const { return RParenLoc; }
SourceLocation getLocStart() const LLVM_READONLY { return LParenLoc; }
SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == ParenListExprClass;
}
// Iterators
child_range children() {
return child_range(&Exprs[0], &Exprs[0]+NumExprs);
}
friend class ASTStmtReader;
friend class ASTStmtWriter;
};
/// \brief Represents a C11 generic selection.
///
/// A generic selection (C11 6.5.1.1) contains an unevaluated controlling
/// 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(const ASTContext &Context,
SourceLocation GenericLoc, Expr *ControllingExpr,
ArrayRef<TypeSourceInfo*> AssocTypes,
ArrayRef<Expr*> AssocExprs,
SourceLocation DefaultLoc, SourceLocation RParenLoc,
bool ContainsUnexpandedParameterPack,
unsigned ResultIndex);
/// This constructor is used in the result-dependent case.
GenericSelectionExpr(const ASTContext &Context,
SourceLocation GenericLoc, Expr *ControllingExpr,
ArrayRef<TypeSourceInfo*> AssocTypes,
ArrayRef<Expr*> AssocExprs,
SourceLocation DefaultLoc, SourceLocation RParenLoc,
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()); }
SourceLocation getLocStart() const LLVM_READONLY { return GenericLoc; }
SourceLocation getLocEnd() const LLVM_READONLY { return 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;
};
//===----------------------------------------------------------------------===//
// 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:
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(),
base->isInstantiationDependent(),
base->containsUnexpandedParameterPack()),
Base(base), Accessor(&accessor), AccessorLoc(loc) {}
/// \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;
/// containsDuplicateElements - Return true if any element access is
/// repeated.
bool containsDuplicateElements() const;
/// getEncodedElementAccess - Encode the elements accessed into an llvm
/// aggregate Constant of ConstantInt(s).
void getEncodedElementAccess(SmallVectorImpl<uint32_t> &Elts) const;
SourceLocation getLocStart() const LLVM_READONLY {
return getBase()->getLocStart();
}
SourceLocation getLocEnd() const LLVM_READONLY { return AccessorLoc; }
/// isArrow - Return true if the base expression is a pointer to vector,
/// return false if the base expression is a vector.
bool isArrow() const;
static bool classof(const Stmt *T) {
return T->getStmtClass() == ExtVectorElementExprClass;
}
// Iterators
child_range children() { return child_range(&Base, &Base+1); }
};
/// 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:
BlockExpr(BlockDecl *BD, QualType ty)
: Expr(BlockExprClass, ty, VK_RValue, OK_Ordinary,
ty->isDependentType(), ty->isDependentType(),
ty->isInstantiationDependentType() || BD->isDependentContext(),
false),
TheBlock(BD) {}
/// \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();
SourceLocation getLocStart() const LLVM_READONLY { return getCaretLocation(); }
SourceLocation getLocEnd() const LLVM_READONLY { return getBody()->getLocEnd(); }
/// getFunctionType - Return the underlying function type for this block.
const FunctionProtoType *getFunctionType() const;
static bool classof(const Stmt *T) {
return T->getStmtClass() == BlockExprClass;
}
// Iterators
child_range children() {
return child_range(child_iterator(), child_iterator());
}
};
/// 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.
class AsTypeExpr : public Expr {
private:
Stmt *SrcExpr;
SourceLocation BuiltinLoc, RParenLoc;
friend class ASTReader;
friend class ASTStmtReader;
explicit AsTypeExpr(EmptyShell Empty) : Expr(AsTypeExprClass, Empty) {}
public:
AsTypeExpr(Expr* SrcExpr, QualType DstType,
ExprValueKind VK, ExprObjectKind OK,
SourceLocation BuiltinLoc, SourceLocation RParenLoc)
: Expr(AsTypeExprClass, DstType, VK, OK,
DstType->isDependentType(),
DstType->isDependentType() || SrcExpr->isValueDependent(),
(DstType->isInstantiationDependentType() ||
SrcExpr->isInstantiationDependent()),
(DstType->containsUnexpandedParameterPack() ||
SrcExpr->containsUnexpandedParameterPack())),
SrcExpr(SrcExpr), BuiltinLoc(BuiltinLoc), RParenLoc(RParenLoc) {}
/// getSrcExpr - Return the Expr to be converted.
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; }
SourceLocation getLocStart() const LLVM_READONLY { return BuiltinLoc; }
SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == AsTypeExprClass;
}
// Iterators
child_range children() { return child_range(&SrcExpr, &SrcExpr+1); }
};
/// 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 : unsigned { NoResult = ~0U };
static PseudoObjectExpr *Create(const ASTContext &Context, Expr *syntactic,
ArrayRef<Expr*> semantic,
unsigned resultIndex);
static PseudoObjectExpr *Create(const 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 nullptr;
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();
}
SourceLocation getLocStart() const LLVM_READONLY {
return getSyntacticForm()->getLocStart();
}
SourceLocation getLocEnd() const LLVM_READONLY {
return getSyntacticForm()->getLocEnd();
}
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;
}
};
/// AtomicExpr - Variadic atomic builtins: __atomic_exchange, __atomic_fetch_*,
/// __atomic_load, __atomic_store, and __atomic_compare_exchange_*, for the
/// 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.
class AtomicExpr : public Expr {
public:
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
};
// The ABI values for various atomic memory orderings.
enum AtomicOrderingKind {
AO_ABI_memory_order_relaxed = 0,
AO_ABI_memory_order_consume = 1,
AO_ABI_memory_order_acquire = 2,
AO_ABI_memory_order_release = 3,
AO_ABI_memory_order_acq_rel = 4,
AO_ABI_memory_order_seq_cst = 5
};
private:
enum { PTR, ORDER, VAL1, ORDER_FAIL, VAL2, WEAK, END_EXPR };
Stmt* SubExprs[END_EXPR];
unsigned NumSubExprs;
SourceLocation BuiltinLoc, RParenLoc;
AtomicOp Op;
friend class ASTStmtReader;
public:
AtomicExpr(SourceLocation BLoc, ArrayRef<Expr*> args, QualType t,
AtomicOp op, SourceLocation RP);
/// \brief Determine the number of arguments the specified atomic builtin
/// should have.
static unsigned getNumSubExprs(AtomicOp Op);
/// \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 {
if (Op == AO__c11_atomic_init)
return cast<Expr>(SubExprs[ORDER]);
assert(NumSubExprs > VAL1);
return cast<Expr>(SubExprs[VAL1]);
}
Expr *getOrderFail() const {
assert(NumSubExprs > ORDER_FAIL);
return cast<Expr>(SubExprs[ORDER_FAIL]);
}
Expr *getVal2() const {
if (Op == AO__atomic_exchange)
return cast<Expr>(SubExprs[ORDER_FAIL]);
assert(NumSubExprs > VAL2);
return cast<Expr>(SubExprs[VAL2]);
}
Expr *getWeak() const {
assert(NumSubExprs > WEAK);
return cast<Expr>(SubExprs[WEAK]);
}
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 {
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;
}
SourceLocation getBuiltinLoc() const { return BuiltinLoc; }
SourceLocation getRParenLoc() const { return RParenLoc; }
SourceLocation getLocStart() const LLVM_READONLY { return BuiltinLoc; }
SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == AtomicExprClass;
}
// Iterators
child_range children() {
return child_range(SubExprs, SubExprs+NumSubExprs);
}
};
/// TypoExpr - Internal placeholder for expressions where typo correction
/// still needs to be performed and/or an error diagnostic emitted.
class TypoExpr : public Expr {
public:
TypoExpr(QualType T)
: Expr(TypoExprClass, T, VK_LValue, OK_Ordinary,
/*isTypeDependent*/ true,
/*isValueDependent*/ true,
/*isInstantiationDependent*/ true,
/*containsUnexpandedParameterPack*/ false) {
assert(T->isDependentType() && "TypoExpr given a non-dependent type");
}
child_range children() {
return child_range(child_iterator(), child_iterator());
}
SourceLocation getLocStart() const LLVM_READONLY { return SourceLocation(); }
SourceLocation getLocEnd() const LLVM_READONLY { return SourceLocation(); }
static bool classof(const Stmt *T) {
return T->getStmtClass() == TypoExprClass;
}
};
} // end namespace clang
#endif // LLVM_CLANG_AST_EXPR_H
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index dbc890d..a4da453 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -1,4014 +1,4043 @@
//===--- Expr.cpp - Expression AST Node Implementation --------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the Expr class and subclasses.
//
//===----------------------------------------------------------------------===//
#include "clang/AST/APValue.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Attr.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/EvaluatedExprVisitor.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/Mangle.h"
#include "clang/AST/RecordLayout.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/Basic/Builtins.h"
#include "clang/Basic/CharInfo.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Lex/Lexer.h"
#include "clang/Lex/LiteralSupport.h"
#include "clang/Sema/SemaDiagnostic.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cstring>
using namespace clang;
const CXXRecordDecl *Expr::getBestDynamicClassType() const {
const Expr *E = ignoreParenBaseCasts();
QualType DerivedType = E->getType();
if (const PointerType *PTy = DerivedType->getAs<PointerType>())
DerivedType = PTy->getPointeeType();
if (DerivedType->isDependentType())
return nullptr;
const RecordType *Ty = DerivedType->castAs<RecordType>();
Decl *D = Ty->getDecl();
return cast<CXXRecordDecl>(D);
}
const Expr *Expr::skipRValueSubobjectAdjustments(
SmallVectorImpl<const Expr *> &CommaLHSs,
SmallVectorImpl<SubobjectAdjustment> &Adjustments) const {
const Expr *E = this;
while (true) {
E = E->IgnoreParens();
if (const CastExpr *CE = dyn_cast<CastExpr>(E)) {
if ((CE->getCastKind() == CK_DerivedToBase ||
CE->getCastKind() == CK_UncheckedDerivedToBase) &&
E->getType()->isRecordType()) {
E = CE->getSubExpr();
CXXRecordDecl *Derived
= cast<CXXRecordDecl>(E->getType()->getAs<RecordType>()->getDecl());
Adjustments.push_back(SubobjectAdjustment(CE, Derived));
continue;
}
if (CE->getCastKind() == CK_NoOp) {
E = CE->getSubExpr();
continue;
}
} else if (const MemberExpr *ME = dyn_cast<MemberExpr>(E)) {
if (!ME->isArrow()) {
assert(ME->getBase()->getType()->isRecordType());
if (FieldDecl *Field = dyn_cast<FieldDecl>(ME->getMemberDecl())) {
if (!Field->isBitField() && !Field->getType()->isReferenceType()) {
E = ME->getBase();
Adjustments.push_back(SubobjectAdjustment(Field));
continue;
}
}
}
} else if (const BinaryOperator *BO = dyn_cast<BinaryOperator>(E)) {
if (BO->isPtrMemOp()) {
assert(BO->getRHS()->isRValue());
E = BO->getLHS();
const MemberPointerType *MPT =
BO->getRHS()->getType()->getAs<MemberPointerType>();
Adjustments.push_back(SubobjectAdjustment(MPT, BO->getRHS()));
continue;
} else if (BO->getOpcode() == BO_Comma) {
CommaLHSs.push_back(BO->getLHS());
E = BO->getRHS();
continue;
}
}
// Nothing changed.
break;
}
return E;
}
/// 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 Expr::isKnownToHaveBooleanValue() const {
const Expr *E = IgnoreParens();
// If this value has _Bool type, it is obvious 0/1.
if (E->getType()->isBooleanType()) return true;
// If this is a non-scalar-integer type, we don't care enough to try.
if (!E->getType()->isIntegralOrEnumerationType()) return false;
if (const UnaryOperator *UO = dyn_cast<UnaryOperator>(E)) {
switch (UO->getOpcode()) {
case UO_Plus:
return UO->getSubExpr()->isKnownToHaveBooleanValue();
case UO_LNot:
return true;
default:
return false;
}
}
// Only look through implicit casts. If the user writes
// '(int) (a && b)' treat it as an arbitrary int.
if (const ImplicitCastExpr *CE = dyn_cast<ImplicitCastExpr>(E))
return CE->getSubExpr()->isKnownToHaveBooleanValue();
if (const BinaryOperator *BO = dyn_cast<BinaryOperator>(E)) {
switch (BO->getOpcode()) {
default: return false;
case BO_LT: // Relational operators.
case BO_GT:
case BO_LE:
case BO_GE:
case BO_EQ: // Equality operators.
case BO_NE:
case BO_LAnd: // AND operator.
case BO_LOr: // Logical OR operator.
return true;
case BO_And: // Bitwise AND operator.
case BO_Xor: // Bitwise XOR operator.
case BO_Or: // Bitwise OR operator.
// Handle things like (x==2)|(y==12).
return BO->getLHS()->isKnownToHaveBooleanValue() &&
BO->getRHS()->isKnownToHaveBooleanValue();
case BO_Comma:
case BO_Assign:
return BO->getRHS()->isKnownToHaveBooleanValue();
}
}
if (const ConditionalOperator *CO = dyn_cast<ConditionalOperator>(E))
return CO->getTrueExpr()->isKnownToHaveBooleanValue() &&
CO->getFalseExpr()->isKnownToHaveBooleanValue();
return false;
}
// Amusing macro metaprogramming hack: check whether a class provides
// a more specific implementation of getExprLoc().
//
// See also Stmt.cpp:{getLocStart(),getLocEnd()}.
namespace {
/// This implementation is used when a class provides a custom
/// implementation of getExprLoc.
template <class E, class T>
SourceLocation getExprLocImpl(const Expr *expr,
SourceLocation (T::*v)() const) {
return static_cast<const E*>(expr)->getExprLoc();
}
/// This implementation is used when a class doesn't provide
/// a custom implementation of getExprLoc. Overload resolution
/// should pick it over the implementation above because it's
/// more specialized according to function template partial ordering.
template <class E>
SourceLocation getExprLocImpl(const Expr *expr,
SourceLocation (Expr::*v)() const) {
return static_cast<const E*>(expr)->getLocStart();
}
}
SourceLocation Expr::getExprLoc() const {
switch (getStmtClass()) {
case Stmt::NoStmtClass: llvm_unreachable("statement without class");
#define ABSTRACT_STMT(type)
#define STMT(type, base) \
case Stmt::type##Class: break;
#define EXPR(type, base) \
case Stmt::type##Class: return getExprLocImpl<type>(this, &type::getExprLoc);
#include "clang/AST/StmtNodes.inc"
}
llvm_unreachable("unknown expression kind");
}
//===----------------------------------------------------------------------===//
// Primary Expressions.
//===----------------------------------------------------------------------===//
/// \brief Compute the type-, value-, and instantiation-dependence of a
/// declaration reference
/// based on the declaration being referenced.
static void computeDeclRefDependence(const ASTContext &Ctx, NamedDecl *D,
QualType T, bool &TypeDependent,
bool &ValueDependent,
bool &InstantiationDependent) {
TypeDependent = false;
ValueDependent = false;
InstantiationDependent = false;
// (TD) C++ [temp.dep.expr]p3:
// An id-expression is type-dependent if it contains:
//
// and
//
// (VD) C++ [temp.dep.constexpr]p2:
// An identifier is value-dependent if it is:
// (TD) - an identifier that was declared with dependent type
// (VD) - a name declared with a dependent type,
if (T->isDependentType()) {
TypeDependent = true;
ValueDependent = true;
InstantiationDependent = true;
return;
} else if (T->isInstantiationDependentType()) {
InstantiationDependent = true;
}
// (TD) - a conversion-function-id that specifies a dependent type
if (D->getDeclName().getNameKind()
== DeclarationName::CXXConversionFunctionName) {
QualType T = D->getDeclName().getCXXNameType();
if (T->isDependentType()) {
TypeDependent = true;
ValueDependent = true;
InstantiationDependent = true;
return;
}
if (T->isInstantiationDependentType())
InstantiationDependent = true;
}
// (VD) - the name of a non-type template parameter,
if (isa<NonTypeTemplateParmDecl>(D)) {
ValueDependent = true;
InstantiationDependent = true;
return;
}
// (VD) - a constant with integral or enumeration type and is
// initialized with an expression that is value-dependent.
// (VD) - a constant with literal type and is initialized with an
// expression that is value-dependent [C++11].
// (VD) - FIXME: Missing from the standard:
// - an entity with reference type and is initialized with an
// expression that is value-dependent [C++11]
if (VarDecl *Var = dyn_cast<VarDecl>(D)) {
if ((Ctx.getLangOpts().CPlusPlus11 ?
Var->getType()->isLiteralType(Ctx) :
Var->getType()->isIntegralOrEnumerationType()) &&
(Var->getType().isConstQualified() ||
Var->getType()->isReferenceType())) {
if (const Expr *Init = Var->getAnyInitializer())
if (Init->isValueDependent()) {
ValueDependent = true;
InstantiationDependent = true;
}
}
// (VD) - FIXME: Missing from the standard:
// - a member function or a static data member of the current
// instantiation
if (Var->isStaticDataMember() &&
Var->getDeclContext()->isDependentContext()) {
ValueDependent = true;
InstantiationDependent = true;
TypeSourceInfo *TInfo = Var->getFirstDecl()->getTypeSourceInfo();
if (TInfo->getType()->isIncompleteArrayType())
TypeDependent = true;
}
return;
}
// (VD) - FIXME: Missing from the standard:
// - a member function or a static data member of the current
// instantiation
if (isa<CXXMethodDecl>(D) && D->getDeclContext()->isDependentContext()) {
ValueDependent = true;
InstantiationDependent = true;
}
}
void DeclRefExpr::computeDependence(const ASTContext &Ctx) {
bool TypeDependent = false;
bool ValueDependent = false;
bool InstantiationDependent = false;
computeDeclRefDependence(Ctx, getDecl(), getType(), TypeDependent,
ValueDependent, InstantiationDependent);
ExprBits.TypeDependent |= TypeDependent;
ExprBits.ValueDependent |= ValueDependent;
ExprBits.InstantiationDependent |= InstantiationDependent;
// Is the declaration a parameter pack?
if (getDecl()->isParameterPack())
ExprBits.ContainsUnexpandedParameterPack = true;
}
DeclRefExpr::DeclRefExpr(const ASTContext &Ctx,
NestedNameSpecifierLoc QualifierLoc,
SourceLocation TemplateKWLoc,
ValueDecl *D, bool RefersToEnclosingVariableOrCapture,
const DeclarationNameInfo &NameInfo,
NamedDecl *FoundD,
const TemplateArgumentListInfo *TemplateArgs,
QualType T, ExprValueKind VK)
: Expr(DeclRefExprClass, T, VK, OK_Ordinary, false, false, false, false),
D(D), Loc(NameInfo.getLoc()), DNLoc(NameInfo.getInfo()) {
DeclRefExprBits.HasQualifier = QualifierLoc ? 1 : 0;
if (QualifierLoc) {
getInternalQualifierLoc() = QualifierLoc;
auto *NNS = QualifierLoc.getNestedNameSpecifier();
if (NNS->isInstantiationDependent())
ExprBits.InstantiationDependent = true;
if (NNS->containsUnexpandedParameterPack())
ExprBits.ContainsUnexpandedParameterPack = true;
}
DeclRefExprBits.HasFoundDecl = FoundD ? 1 : 0;
if (FoundD)
getInternalFoundDecl() = FoundD;
DeclRefExprBits.HasTemplateKWAndArgsInfo
= (TemplateArgs || TemplateKWLoc.isValid()) ? 1 : 0;
DeclRefExprBits.RefersToEnclosingVariableOrCapture =
RefersToEnclosingVariableOrCapture;
if (TemplateArgs) {
bool Dependent = false;
bool InstantiationDependent = false;
bool ContainsUnexpandedParameterPack = false;
getTemplateKWAndArgsInfo()->initializeFrom(TemplateKWLoc, *TemplateArgs,
Dependent,
InstantiationDependent,
ContainsUnexpandedParameterPack);
assert(!Dependent && "built a DeclRefExpr with dependent template args");
ExprBits.InstantiationDependent |= InstantiationDependent;
ExprBits.ContainsUnexpandedParameterPack |= ContainsUnexpandedParameterPack;
} else if (TemplateKWLoc.isValid()) {
getTemplateKWAndArgsInfo()->initializeFrom(TemplateKWLoc);
}
DeclRefExprBits.HadMultipleCandidates = 0;
computeDependence(Ctx);
}
DeclRefExpr *DeclRefExpr::Create(const ASTContext &Context,
NestedNameSpecifierLoc QualifierLoc,
SourceLocation TemplateKWLoc,
ValueDecl *D,
bool RefersToEnclosingVariableOrCapture,
SourceLocation NameLoc,
QualType T,
ExprValueKind VK,
NamedDecl *FoundD,
const TemplateArgumentListInfo *TemplateArgs) {
return Create(Context, QualifierLoc, TemplateKWLoc, D,
RefersToEnclosingVariableOrCapture,
DeclarationNameInfo(D->getDeclName(), NameLoc),
T, VK, FoundD, TemplateArgs);
}
DeclRefExpr *DeclRefExpr::Create(const ASTContext &Context,
NestedNameSpecifierLoc QualifierLoc,
SourceLocation TemplateKWLoc,
ValueDecl *D,
bool RefersToEnclosingVariableOrCapture,
const DeclarationNameInfo &NameInfo,
QualType T,
ExprValueKind VK,
NamedDecl *FoundD,
const TemplateArgumentListInfo *TemplateArgs) {
// Filter out cases where the found Decl is the same as the value refenenced.
if (D == FoundD)
FoundD = nullptr;
std::size_t Size = sizeof(DeclRefExpr);
if (QualifierLoc)
Size += sizeof(NestedNameSpecifierLoc);
if (FoundD)
Size += sizeof(NamedDecl *);
if (TemplateArgs) {
Size = llvm::RoundUpToAlignment(Size,
llvm::alignOf<ASTTemplateKWAndArgsInfo>());
Size += ASTTemplateKWAndArgsInfo::sizeFor(TemplateArgs->size());
} else if (TemplateKWLoc.isValid()) {
Size = llvm::RoundUpToAlignment(Size,
llvm::alignOf<ASTTemplateKWAndArgsInfo>());
Size += ASTTemplateKWAndArgsInfo::sizeFor(0);
}
void *Mem = Context.Allocate(Size, llvm::alignOf<DeclRefExpr>());
return new (Mem) DeclRefExpr(Context, QualifierLoc, TemplateKWLoc, D,
RefersToEnclosingVariableOrCapture,
NameInfo, FoundD, TemplateArgs, T, VK);
}
DeclRefExpr *DeclRefExpr::CreateEmpty(const ASTContext &Context,
bool HasQualifier,
bool HasFoundDecl,
bool HasTemplateKWAndArgsInfo,
unsigned NumTemplateArgs) {
std::size_t Size = sizeof(DeclRefExpr);
if (HasQualifier)
Size += sizeof(NestedNameSpecifierLoc);
if (HasFoundDecl)
Size += sizeof(NamedDecl *);
if (HasTemplateKWAndArgsInfo) {
Size = llvm::RoundUpToAlignment(Size,
llvm::alignOf<ASTTemplateKWAndArgsInfo>());
Size += ASTTemplateKWAndArgsInfo::sizeFor(NumTemplateArgs);
}
void *Mem = Context.Allocate(Size, llvm::alignOf<DeclRefExpr>());
return new (Mem) DeclRefExpr(EmptyShell());
}
SourceLocation DeclRefExpr::getLocStart() const {
if (hasQualifier())
return getQualifierLoc().getBeginLoc();
return getNameInfo().getLocStart();
}
SourceLocation DeclRefExpr::getLocEnd() const {
if (hasExplicitTemplateArgs())
return getRAngleLoc();
return getNameInfo().getLocEnd();
}
PredefinedExpr::PredefinedExpr(SourceLocation L, QualType FNTy, IdentType IT,
StringLiteral *SL)
: Expr(PredefinedExprClass, FNTy, VK_LValue, OK_Ordinary,
FNTy->isDependentType(), FNTy->isDependentType(),
FNTy->isInstantiationDependentType(),
/*ContainsUnexpandedParameterPack=*/false),
Loc(L), Type(IT), FnName(SL) {}
StringLiteral *PredefinedExpr::getFunctionName() {
return cast_or_null<StringLiteral>(FnName);
}
StringRef PredefinedExpr::getIdentTypeName(PredefinedExpr::IdentType IT) {
switch (IT) {
case Func:
return "__func__";
case Function:
return "__FUNCTION__";
case FuncDName:
return "__FUNCDNAME__";
case LFunction:
return "L__FUNCTION__";
case PrettyFunction:
return "__PRETTY_FUNCTION__";
case FuncSig:
return "__FUNCSIG__";
case PrettyFunctionNoVirtual:
break;
}
llvm_unreachable("Unknown ident type for PredefinedExpr");
}
// FIXME: Maybe this should use DeclPrinter with a special "print predefined
// expr" policy instead.
std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) {
ASTContext &Context = CurrentDecl->getASTContext();
if (IT == PredefinedExpr::FuncDName) {
if (const NamedDecl *ND = dyn_cast<NamedDecl>(CurrentDecl)) {
std::unique_ptr<MangleContext> MC;
MC.reset(Context.createMangleContext());
if (MC->shouldMangleDeclName(ND)) {
SmallString<256> Buffer;
llvm::raw_svector_ostream Out(Buffer);
if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(ND))
MC->mangleCXXCtor(CD, Ctor_Base, Out);
else if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(ND))
MC->mangleCXXDtor(DD, Dtor_Base, Out);
else
MC->mangleName(ND, Out);
if (!Buffer.empty() && Buffer.front() == '\01')
return Buffer.substr(1);
return Buffer.str();
} else
return ND->getIdentifier()->getName();
}
return "";
}
if (auto *BD = dyn_cast<BlockDecl>(CurrentDecl)) {
std::unique_ptr<MangleContext> MC;
MC.reset(Context.createMangleContext());
SmallString<256> Buffer;
llvm::raw_svector_ostream Out(Buffer);
auto DC = CurrentDecl->getDeclContext();
if (DC->isFileContext())
MC->mangleGlobalBlock(BD, /*ID*/ nullptr, Out);
else if (const auto *CD = dyn_cast<CXXConstructorDecl>(DC))
MC->mangleCtorBlock(CD, /*CT*/ Ctor_Complete, BD, Out);
else if (const auto *DD = dyn_cast<CXXDestructorDecl>(DC))
MC->mangleDtorBlock(DD, /*DT*/ Dtor_Complete, BD, Out);
else
MC->mangleBlock(DC, BD, Out);
return Out.str();
}
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CurrentDecl)) {
if (IT != PrettyFunction && IT != PrettyFunctionNoVirtual && IT != FuncSig)
return FD->getNameAsString();
SmallString<256> Name;
llvm::raw_svector_ostream Out(Name);
if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) {
if (MD->isVirtual() && IT != PrettyFunctionNoVirtual)
Out << "virtual ";
if (MD->isStatic())
Out << "static ";
}
PrintingPolicy Policy(Context.getLangOpts());
std::string Proto;
llvm::raw_string_ostream POut(Proto);
const FunctionDecl *Decl = FD;
if (const FunctionDecl* Pattern = FD->getTemplateInstantiationPattern())
Decl = Pattern;
const FunctionType *AFT = Decl->getType()->getAs<FunctionType>();
const FunctionProtoType *FT = nullptr;
if (FD->hasWrittenPrototype())
FT = dyn_cast<FunctionProtoType>(AFT);
if (IT == FuncSig) {
switch (FT->getCallConv()) {
case CC_C: POut << "__cdecl "; break;
case CC_X86StdCall: POut << "__stdcall "; break;
case CC_X86FastCall: POut << "__fastcall "; break;
case CC_X86ThisCall: POut << "__thiscall "; break;
case CC_X86VectorCall: POut << "__vectorcall "; break;
// Only bother printing the conventions that MSVC knows about.
default: break;
}
}
FD->printQualifiedName(POut, Policy);
POut << "(";
if (FT) {
for (unsigned i = 0, e = Decl->getNumParams(); i != e; ++i) {
if (i) POut << ", ";
POut << Decl->getParamDecl(i)->getType().stream(Policy);
}
if (FT->isVariadic()) {
if (FD->getNumParams()) POut << ", ";
POut << "...";
}
}
POut << ")";
if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) {
const FunctionType *FT = MD->getType()->castAs<FunctionType>();
if (FT->isConst())
POut << " const";
if (FT->isVolatile())
POut << " volatile";
RefQualifierKind Ref = MD->getRefQualifier();
if (Ref == RQ_LValue)
POut << " &";
else if (Ref == RQ_RValue)
POut << " &&";
}
typedef SmallVector<const ClassTemplateSpecializationDecl *, 8> SpecsTy;
SpecsTy Specs;
const DeclContext *Ctx = FD->getDeclContext();
while (Ctx && isa<NamedDecl>(Ctx)) {
const ClassTemplateSpecializationDecl *Spec
= dyn_cast<ClassTemplateSpecializationDecl>(Ctx);
if (Spec && !Spec->isExplicitSpecialization())
Specs.push_back(Spec);
Ctx = Ctx->getParent();
}
std::string TemplateParams;
llvm::raw_string_ostream TOut(TemplateParams);
for (SpecsTy::reverse_iterator I = Specs.rbegin(), E = Specs.rend();
I != E; ++I) {
const TemplateParameterList *Params
= (*I)->getSpecializedTemplate()->getTemplateParameters();
const TemplateArgumentList &Args = (*I)->getTemplateArgs();
assert(Params->size() == Args.size());
for (unsigned i = 0, numParams = Params->size(); i != numParams; ++i) {
StringRef Param = Params->getParam(i)->getName();
if (Param.empty()) continue;
TOut << Param << " = ";
Args.get(i).print(Policy, TOut);
TOut << ", ";
}
}
FunctionTemplateSpecializationInfo *FSI
= FD->getTemplateSpecializationInfo();
if (FSI && !FSI->isExplicitSpecialization()) {
const TemplateParameterList* Params
= FSI->getTemplate()->getTemplateParameters();
const TemplateArgumentList* Args = FSI->TemplateArguments;
assert(Params->size() == Args->size());
for (unsigned i = 0, e = Params->size(); i != e; ++i) {
StringRef Param = Params->getParam(i)->getName();
if (Param.empty()) continue;
TOut << Param << " = ";
Args->get(i).print(Policy, TOut);
TOut << ", ";
}
}
TOut.flush();
if (!TemplateParams.empty()) {
// remove the trailing comma and space
TemplateParams.resize(TemplateParams.size() - 2);
POut << " [" << TemplateParams << "]";
}
POut.flush();
// Print "auto" for all deduced return types. This includes C++1y return
// type deduction and lambdas. For trailing return types resolve the
// decltype expression. Otherwise print the real type when this is
// not a constructor or destructor.
if (isa<CXXMethodDecl>(FD) &&
cast<CXXMethodDecl>(FD)->getParent()->isLambda())
Proto = "auto " + Proto;
else if (FT && FT->getReturnType()->getAs<DecltypeType>())
FT->getReturnType()
->getAs<DecltypeType>()
->getUnderlyingType()
.getAsStringInternal(Proto, Policy);
else if (!isa<CXXConstructorDecl>(FD) && !isa<CXXDestructorDecl>(FD))
AFT->getReturnType().getAsStringInternal(Proto, Policy);
Out << Proto;
return Name.str().str();
}
if (const CapturedDecl *CD = dyn_cast<CapturedDecl>(CurrentDecl)) {
for (const DeclContext *DC = CD->getParent(); DC; DC = DC->getParent())
// Skip to its enclosing function or method, but not its enclosing
// CapturedDecl.
if (DC->isFunctionOrMethod() && (DC->getDeclKind() != Decl::Captured)) {
const Decl *D = Decl::castFromDeclContext(DC);
return ComputeName(IT, D);
}
llvm_unreachable("CapturedDecl not inside a function or method");
}
if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(CurrentDecl)) {
SmallString<256> Name;
llvm::raw_svector_ostream Out(Name);
Out << (MD->isInstanceMethod() ? '-' : '+');
Out << '[';
// For incorrect code, there might not be an ObjCInterfaceDecl. Do
// a null check to avoid a crash.
if (const ObjCInterfaceDecl *ID = MD->getClassInterface())
Out << *ID;
if (const ObjCCategoryImplDecl *CID =
dyn_cast<ObjCCategoryImplDecl>(MD->getDeclContext()))
Out << '(' << *CID << ')';
Out << ' ';
MD->getSelector().print(Out);
Out << ']';
return Name.str().str();
}
if (isa<TranslationUnitDecl>(CurrentDecl) && IT == PrettyFunction) {
// __PRETTY_FUNCTION__ -> "top level", the others produce an empty string.
return "top level";
}
return "";
}
void APNumericStorage::setIntValue(const ASTContext &C,
const llvm::APInt &Val) {
if (hasAllocation())
C.Deallocate(pVal);
BitWidth = Val.getBitWidth();
unsigned NumWords = Val.getNumWords();
const uint64_t* Words = Val.getRawData();
if (NumWords > 1) {
pVal = new (C) uint64_t[NumWords];
std::copy(Words, Words + NumWords, pVal);
} else if (NumWords == 1)
VAL = Words[0];
else
VAL = 0;
}
IntegerLiteral::IntegerLiteral(const ASTContext &C, const llvm::APInt &V,
QualType type, SourceLocation l)
: Expr(IntegerLiteralClass, type, VK_RValue, OK_Ordinary, false, false,
false, false),
Loc(l) {
assert(type->isIntegerType() && "Illegal type in IntegerLiteral");
assert(V.getBitWidth() == C.getIntWidth(type) &&
"Integer type is not the correct size for constant.");
setValue(C, V);
}
IntegerLiteral *
IntegerLiteral::Create(const ASTContext &C, const llvm::APInt &V,
QualType type, SourceLocation l) {
return new (C) IntegerLiteral(C, V, type, l);
}
IntegerLiteral *
IntegerLiteral::Create(const ASTContext &C, EmptyShell Empty) {
return new (C) IntegerLiteral(Empty);
}
FloatingLiteral::FloatingLiteral(const ASTContext &C, const llvm::APFloat &V,
bool isexact, QualType Type, SourceLocation L)
: Expr(FloatingLiteralClass, Type, VK_RValue, OK_Ordinary, false, false,
false, false), Loc(L) {
setSemantics(V.getSemantics());
FloatingLiteralBits.IsExact = isexact;
setValue(C, V);
}
FloatingLiteral::FloatingLiteral(const ASTContext &C, EmptyShell Empty)
: Expr(FloatingLiteralClass, Empty) {
setRawSemantics(IEEEhalf);
FloatingLiteralBits.IsExact = false;
}
FloatingLiteral *
FloatingLiteral::Create(const ASTContext &C, const llvm::APFloat &V,
bool isexact, QualType Type, SourceLocation L) {
return new (C) FloatingLiteral(C, V, isexact, Type, L);
}
FloatingLiteral *
FloatingLiteral::Create(const ASTContext &C, EmptyShell Empty) {
return new (C) FloatingLiteral(C, Empty);
}
const llvm::fltSemantics &FloatingLiteral::getSemantics() const {
switch(FloatingLiteralBits.Semantics) {
case IEEEhalf:
return llvm::APFloat::IEEEhalf;
case IEEEsingle:
return llvm::APFloat::IEEEsingle;
case IEEEdouble:
return llvm::APFloat::IEEEdouble;
case x87DoubleExtended:
return llvm::APFloat::x87DoubleExtended;
case IEEEquad:
return llvm::APFloat::IEEEquad;
case PPCDoubleDouble:
return llvm::APFloat::PPCDoubleDouble;
}
llvm_unreachable("Unrecognised floating semantics");
}
void FloatingLiteral::setSemantics(const llvm::fltSemantics &Sem) {
if (&Sem == &llvm::APFloat::IEEEhalf)
FloatingLiteralBits.Semantics = IEEEhalf;
else if (&Sem == &llvm::APFloat::IEEEsingle)
FloatingLiteralBits.Semantics = IEEEsingle;
else if (&Sem == &llvm::APFloat::IEEEdouble)
FloatingLiteralBits.Semantics = IEEEdouble;
else if (&Sem == &llvm::APFloat::x87DoubleExtended)
FloatingLiteralBits.Semantics = x87DoubleExtended;
else if (&Sem == &llvm::APFloat::IEEEquad)
FloatingLiteralBits.Semantics = IEEEquad;
else if (&Sem == &llvm::APFloat::PPCDoubleDouble)
FloatingLiteralBits.Semantics = PPCDoubleDouble;
else
llvm_unreachable("Unknown floating semantics");
}
/// 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 FloatingLiteral::getValueAsApproximateDouble() const {
llvm::APFloat V = getValue();
bool ignored;
V.convert(llvm::APFloat::IEEEdouble, llvm::APFloat::rmNearestTiesToEven,
&ignored);
return V.convertToDouble();
}
int StringLiteral::mapCharByteWidth(TargetInfo const &target,StringKind k) {
int CharByteWidth = 0;
switch(k) {
case Ascii:
case UTF8:
CharByteWidth = target.getCharWidth();
break;
case Wide:
CharByteWidth = target.getWCharWidth();
break;
case UTF16:
CharByteWidth = target.getChar16Width();
break;
case UTF32:
CharByteWidth = target.getChar32Width();
break;
}
assert((CharByteWidth & 7) == 0 && "Assumes character size is byte multiple");
CharByteWidth /= 8;
assert((CharByteWidth==1 || CharByteWidth==2 || CharByteWidth==4)
&& "character byte widths supported are 1, 2, and 4 only");
return CharByteWidth;
}
StringLiteral *StringLiteral::Create(const ASTContext &C, StringRef Str,
StringKind Kind, bool Pascal, QualType Ty,
const SourceLocation *Loc,
unsigned NumStrs) {
assert(C.getAsConstantArrayType(Ty) &&
"StringLiteral must be of constant array type!");
// Allocate enough space for the StringLiteral plus an array of locations for
// any concatenated string tokens.
void *Mem = C.Allocate(sizeof(StringLiteral)+
sizeof(SourceLocation)*(NumStrs-1),
llvm::alignOf<StringLiteral>());
StringLiteral *SL = new (Mem) StringLiteral(Ty);
// OPTIMIZE: could allocate this appended to the StringLiteral.
SL->setString(C,Str,Kind,Pascal);
SL->TokLocs[0] = Loc[0];
SL->NumConcatenated = NumStrs;
if (NumStrs != 1)
memcpy(&SL->TokLocs[1], Loc+1, sizeof(SourceLocation)*(NumStrs-1));
return SL;
}
StringLiteral *StringLiteral::CreateEmpty(const ASTContext &C,
unsigned NumStrs) {
void *Mem = C.Allocate(sizeof(StringLiteral)+
sizeof(SourceLocation)*(NumStrs-1),
llvm::alignOf<StringLiteral>());
StringLiteral *SL = new (Mem) StringLiteral(QualType());
SL->CharByteWidth = 0;
SL->Length = 0;
SL->NumConcatenated = NumStrs;
return SL;
}
void StringLiteral::outputString(raw_ostream &OS) const {
switch (getKind()) {
case Ascii: break; // no prefix.
case Wide: OS << 'L'; break;
case UTF8: OS << "u8"; break;
case UTF16: OS << 'u'; break;
case UTF32: OS << 'U'; break;
}
OS << '"';
static const char Hex[] = "0123456789ABCDEF";
unsigned LastSlashX = getLength();
for (unsigned I = 0, N = getLength(); I != N; ++I) {
switch (uint32_t Char = getCodeUnit(I)) {
default:
// FIXME: Convert UTF-8 back to codepoints before rendering.
// Convert UTF-16 surrogate pairs back to codepoints before rendering.
// Leave invalid surrogates alone; we'll use \x for those.
if (getKind() == UTF16 && I != N - 1 && Char >= 0xd800 &&
Char <= 0xdbff) {
uint32_t Trail = getCodeUnit(I + 1);
if (Trail >= 0xdc00 && Trail <= 0xdfff) {
Char = 0x10000 + ((Char - 0xd800) << 10) + (Trail - 0xdc00);
++I;
}
}
if (Char > 0xff) {
// If this is a wide string, output characters over 0xff using \x
// escapes. Otherwise, this is a UTF-16 or UTF-32 string, and Char is a
// codepoint: use \x escapes for invalid codepoints.
if (getKind() == Wide ||
(Char >= 0xd800 && Char <= 0xdfff) || Char >= 0x110000) {
// FIXME: Is this the best way to print wchar_t?
OS << "\\x";
int Shift = 28;
while ((Char >> Shift) == 0)
Shift -= 4;
for (/**/; Shift >= 0; Shift -= 4)
OS << Hex[(Char >> Shift) & 15];
LastSlashX = I;
break;
}
if (Char > 0xffff)
OS << "\\U00"
<< Hex[(Char >> 20) & 15]
<< Hex[(Char >> 16) & 15];
else
OS << "\\u";
OS << Hex[(Char >> 12) & 15]
<< Hex[(Char >> 8) & 15]
<< Hex[(Char >> 4) & 15]
<< Hex[(Char >> 0) & 15];
break;
}
// If we used \x... for the previous character, and this character is a
// hexadecimal digit, prevent it being slurped as part of the \x.
if (LastSlashX + 1 == I) {
switch (Char) {
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
OS << "\"\"";
}
}
assert(Char <= 0xff &&
"Characters above 0xff should already have been handled.");
if (isPrintable(Char))
OS << (char)Char;
else // Output anything hard as an octal escape.
OS << '\\'
<< (char)('0' + ((Char >> 6) & 7))
<< (char)('0' + ((Char >> 3) & 7))
<< (char)('0' + ((Char >> 0) & 7));
break;
// Handle some common non-printable cases to make dumps prettier.
case '\\': OS << "\\\\"; break;
case '"': OS << "\\\""; break;
case '\n': OS << "\\n"; break;
case '\t': OS << "\\t"; break;
case '\a': OS << "\\a"; break;
case '\b': OS << "\\b"; break;
}
}
OS << '"';
}
void StringLiteral::setString(const ASTContext &C, StringRef Str,
StringKind Kind, bool IsPascal) {
//FIXME: we assume that the string data comes from a target that uses the same
// code unit size and endianess for the type of string.
this->Kind = Kind;
this->IsPascal = IsPascal;
CharByteWidth = mapCharByteWidth(C.getTargetInfo(),Kind);
assert((Str.size()%CharByteWidth == 0)
&& "size of data must be multiple of CharByteWidth");
Length = Str.size()/CharByteWidth;
switch(CharByteWidth) {
case 1: {
char *AStrData = new (C) char[Length];
std::memcpy(AStrData,Str.data(),Length*sizeof(*AStrData));
StrData.asChar = AStrData;
break;
}
case 2: {
uint16_t *AStrData = new (C) uint16_t[Length];
std::memcpy(AStrData,Str.data(),Length*sizeof(*AStrData));
StrData.asUInt16 = AStrData;
break;
}
case 4: {
uint32_t *AStrData = new (C) uint32_t[Length];
std::memcpy(AStrData,Str.data(),Length*sizeof(*AStrData));
StrData.asUInt32 = AStrData;
break;
}
default:
assert(false && "unsupported CharByteWidth");
}
}
/// 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 StringLiteral::
-getLocationOfByte(unsigned ByteNo, const SourceManager &SM,
- const LangOptions &Features, const TargetInfo &Target) const {
+/// The *StartToken sets the first token to be searched in this function and
+/// the *StartTokenByteOffset is the byte offset of the first token. Before
+/// returning, it updates the *StartToken to the TokNo of the token being found
+/// and sets *StartTokenByteOffset to the byte offset of the token in the
+/// string.
+/// Using these two parameters can reduce the time complexity from O(n^2) to
+/// O(n) if one wants to get the location of byte for all the tokens in a
+/// string.
+///
+SourceLocation
+StringLiteral::getLocationOfByte(unsigned ByteNo, const SourceManager &SM,
+ const LangOptions &Features,
+ const TargetInfo &Target, unsigned *StartToken,
+ unsigned *StartTokenByteOffset) const {
assert((Kind == StringLiteral::Ascii || Kind == StringLiteral::UTF8) &&
"Only narrow string literals are currently supported");
// Loop over all of the tokens in this string until we find the one that
// contains the byte we're looking for.
unsigned TokNo = 0;
+ unsigned StringOffset = 0;
+ if (StartToken)
+ TokNo = *StartToken;
+ if (StartTokenByteOffset) {
+ StringOffset = *StartTokenByteOffset;
+ ByteNo -= StringOffset;
+ }
while (1) {
assert(TokNo < getNumConcatenated() && "Invalid byte number!");
SourceLocation StrTokLoc = getStrTokenLoc(TokNo);
// Get the spelling of the string so that we can get the data that makes up
// the string literal, not the identifier for the macro it is potentially
// expanded through.
SourceLocation StrTokSpellingLoc = SM.getSpellingLoc(StrTokLoc);
-
+
// Re-lex the token to get its length and original spelling.
- std::pair<FileID, unsigned> LocInfo =SM.getDecomposedLoc(StrTokSpellingLoc);
+ std::pair<FileID, unsigned> LocInfo =
+ SM.getDecomposedLoc(StrTokSpellingLoc);
bool Invalid = false;
StringRef Buffer = SM.getBufferData(LocInfo.first, &Invalid);
- if (Invalid)
+ if (Invalid) {
+ if (StartTokenByteOffset != nullptr)
+ *StartTokenByteOffset = StringOffset;
+ if (StartToken != nullptr)
+ *StartToken = TokNo;
return StrTokSpellingLoc;
-
+ }
+
const char *StrData = Buffer.data()+LocInfo.second;
// Create a lexer starting at the beginning of this token.
Lexer TheLexer(SM.getLocForStartOfFile(LocInfo.first), Features,
Buffer.begin(), StrData, Buffer.end());
Token TheTok;
TheLexer.LexFromRawLexer(TheTok);
// Use the StringLiteralParser to compute the length of the string in bytes.
StringLiteralParser SLP(TheTok, SM, Features, Target);
unsigned TokNumBytes = SLP.GetStringLength();
// If the byte is in this token, return the location of the byte.
if (ByteNo < TokNumBytes ||
(ByteNo == TokNumBytes && TokNo == getNumConcatenated() - 1)) {
- unsigned Offset = SLP.getOffsetOfStringByte(TheTok, ByteNo);
-
+ unsigned Offset = SLP.getOffsetOfStringByte(TheTok, ByteNo);
+
// Now that we know the offset of the token in the spelling, use the
// preprocessor to get the offset in the original source.
+ if (StartTokenByteOffset != nullptr)
+ *StartTokenByteOffset = StringOffset;
+ if (StartToken != nullptr)
+ *StartToken = TokNo;
return Lexer::AdvanceToTokenCharacter(StrTokLoc, Offset, SM, Features);
}
-
+
// Move to the next string token.
+ StringOffset += TokNumBytes;
++TokNo;
ByteNo -= TokNumBytes;
}
}
/// getOpcodeStr - Turn an Opcode enum value into the punctuation char it
/// corresponds to, e.g. "sizeof" or "[pre]++".
StringRef UnaryOperator::getOpcodeStr(Opcode Op) {
switch (Op) {
case UO_PostInc: return "++";
case UO_PostDec: return "--";
case UO_PreInc: return "++";
case UO_PreDec: return "--";
case UO_AddrOf: return "&";
case UO_Deref: return "*";
case UO_Plus: return "+";
case UO_Minus: return "-";
case UO_Not: return "~";
case UO_LNot: return "!";
case UO_Real: return "__real";
case UO_Imag: return "__imag";
case UO_Extension: return "__extension__";
case UO_Coawait: return "co_await";
}
llvm_unreachable("Unknown unary operator");
}
UnaryOperatorKind
UnaryOperator::getOverloadedOpcode(OverloadedOperatorKind OO, bool Postfix) {
switch (OO) {
default: llvm_unreachable("No unary operator for overloaded function");
case OO_PlusPlus: return Postfix ? UO_PostInc : UO_PreInc;
case OO_MinusMinus: return Postfix ? UO_PostDec : UO_PreDec;
case OO_Amp: return UO_AddrOf;
case OO_Star: return UO_Deref;
case OO_Plus: return UO_Plus;
case OO_Minus: return UO_Minus;
case OO_Tilde: return UO_Not;
case OO_Exclaim: return UO_LNot;
case OO_Coawait: return UO_Coawait;
}
}
OverloadedOperatorKind UnaryOperator::getOverloadedOperator(Opcode Opc) {
switch (Opc) {
case UO_PostInc: case UO_PreInc: return OO_PlusPlus;
case UO_PostDec: case UO_PreDec: return OO_MinusMinus;
case UO_AddrOf: return OO_Amp;
case UO_Deref: return OO_Star;
case UO_Plus: return OO_Plus;
case UO_Minus: return OO_Minus;
case UO_Not: return OO_Tilde;
case UO_LNot: return OO_Exclaim;
case UO_Coawait: return OO_Coawait;
default: return OO_None;
}
}
//===----------------------------------------------------------------------===//
// Postfix Operators.
//===----------------------------------------------------------------------===//
CallExpr::CallExpr(const ASTContext& C, StmtClass SC, Expr *fn,
unsigned NumPreArgs, ArrayRef<Expr*> args, QualType t,
ExprValueKind VK, SourceLocation rparenloc)
: Expr(SC, t, VK, OK_Ordinary,
fn->isTypeDependent(),
fn->isValueDependent(),
fn->isInstantiationDependent(),
fn->containsUnexpandedParameterPack()),
NumArgs(args.size()) {
SubExprs = new (C) Stmt*[args.size()+PREARGS_START+NumPreArgs];
SubExprs[FN] = fn;
for (unsigned i = 0; i != args.size(); ++i) {
if (args[i]->isTypeDependent())
ExprBits.TypeDependent = true;
if (args[i]->isValueDependent())
ExprBits.ValueDependent = true;
if (args[i]->isInstantiationDependent())
ExprBits.InstantiationDependent = true;
if (args[i]->containsUnexpandedParameterPack())
ExprBits.ContainsUnexpandedParameterPack = true;
SubExprs[i+PREARGS_START+NumPreArgs] = args[i];
}
CallExprBits.NumPreArgs = NumPreArgs;
RParenLoc = rparenloc;
}
CallExpr::CallExpr(const ASTContext &C, Expr *fn, ArrayRef<Expr *> args,
QualType t, ExprValueKind VK, SourceLocation rparenloc)
: CallExpr(C, CallExprClass, fn, /*NumPreArgs=*/0, args, t, VK, rparenloc) {
}
CallExpr::CallExpr(const ASTContext &C, StmtClass SC, EmptyShell Empty)
: CallExpr(C, SC, /*NumPreArgs=*/0, Empty) {}
CallExpr::CallExpr(const ASTContext &C, StmtClass SC, unsigned NumPreArgs,
EmptyShell Empty)
: Expr(SC, Empty), SubExprs(nullptr), NumArgs(0) {
// FIXME: Why do we allocate this?
SubExprs = new (C) Stmt*[PREARGS_START+NumPreArgs];
CallExprBits.NumPreArgs = NumPreArgs;
}
Decl *CallExpr::getCalleeDecl() {
Expr *CEE = getCallee()->IgnoreParenImpCasts();
while (SubstNonTypeTemplateParmExpr *NTTP
= dyn_cast<SubstNonTypeTemplateParmExpr>(CEE)) {
CEE = NTTP->getReplacement()->IgnoreParenCasts();
}
// If we're calling a dereference, look at the pointer instead.
if (BinaryOperator *BO = dyn_cast<BinaryOperator>(CEE)) {
if (BO->isPtrMemOp())
CEE = BO->getRHS()->IgnoreParenCasts();
} else if (UnaryOperator *UO = dyn_cast<UnaryOperator>(CEE)) {
if (UO->getOpcode() == UO_Deref)
CEE = UO->getSubExpr()->IgnoreParenCasts();
}
if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CEE))
return DRE->getDecl();
if (MemberExpr *ME = dyn_cast<MemberExpr>(CEE))
return ME->getMemberDecl();
return nullptr;
}
FunctionDecl *CallExpr::getDirectCallee() {
return dyn_cast_or_null<FunctionDecl>(getCalleeDecl());
}
/// 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 CallExpr::setNumArgs(const ASTContext& C, unsigned NumArgs) {
// No change, just return.
if (NumArgs == getNumArgs()) return;
// If shrinking # arguments, just delete the extras and forgot them.
if (NumArgs < getNumArgs()) {
this->NumArgs = NumArgs;
return;
}
// Otherwise, we are growing the # arguments. New an bigger argument array.
unsigned NumPreArgs = getNumPreArgs();
Stmt **NewSubExprs = new (C) Stmt*[NumArgs+PREARGS_START+NumPreArgs];
// Copy over args.
for (unsigned i = 0; i != getNumArgs()+PREARGS_START+NumPreArgs; ++i)
NewSubExprs[i] = SubExprs[i];
// Null out new args.
for (unsigned i = getNumArgs()+PREARGS_START+NumPreArgs;
i != NumArgs+PREARGS_START+NumPreArgs; ++i)
NewSubExprs[i] = nullptr;
if (SubExprs) C.Deallocate(SubExprs);
SubExprs = NewSubExprs;
this->NumArgs = NumArgs;
}
/// getBuiltinCallee - If this is a call to a builtin, return the builtin ID. If
/// not, return 0.
unsigned CallExpr::getBuiltinCallee() const {
// All simple function calls (e.g. func()) are implicitly cast to pointer to
// function. As a result, we try and obtain the DeclRefExpr from the
// ImplicitCastExpr.
const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(getCallee());
if (!ICE) // FIXME: deal with more complex calls (e.g. (func)(), (*func)()).
return 0;
const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(ICE->getSubExpr());
if (!DRE)
return 0;
const FunctionDecl *FDecl = dyn_cast<FunctionDecl>(DRE->getDecl());
if (!FDecl)
return 0;
if (!FDecl->getIdentifier())
return 0;
return FDecl->getBuiltinID();
}
bool CallExpr::isUnevaluatedBuiltinCall(const ASTContext &Ctx) const {
if (unsigned BI = getBuiltinCallee())
return Ctx.BuiltinInfo.isUnevaluated(BI);
return false;
}
QualType CallExpr::getCallReturnType(const ASTContext &Ctx) const {
const Expr *Callee = getCallee();
QualType CalleeType = Callee->getType();
if (const auto *FnTypePtr = CalleeType->getAs<PointerType>()) {
CalleeType = FnTypePtr->getPointeeType();
} else if (const auto *BPT = CalleeType->getAs<BlockPointerType>()) {
CalleeType = BPT->getPointeeType();
} else if (CalleeType->isSpecificPlaceholderType(BuiltinType::BoundMember)) {
if (isa<CXXPseudoDestructorExpr>(Callee->IgnoreParens()))
return Ctx.VoidTy;
// This should never be overloaded and so should never return null.
CalleeType = Expr::findBoundMemberType(Callee);
}
const FunctionType *FnType = CalleeType->castAs<FunctionType>();
return FnType->getReturnType();
}
SourceLocation CallExpr::getLocStart() const {
if (isa<CXXOperatorCallExpr>(this))
return cast<CXXOperatorCallExpr>(this)->getLocStart();
SourceLocation begin = getCallee()->getLocStart();
if (begin.isInvalid() && getNumArgs() > 0 && getArg(0))
begin = getArg(0)->getLocStart();
return begin;
}
SourceLocation CallExpr::getLocEnd() const {
if (isa<CXXOperatorCallExpr>(this))
return cast<CXXOperatorCallExpr>(this)->getLocEnd();
SourceLocation end = getRParenLoc();
if (end.isInvalid() && getNumArgs() > 0 && getArg(getNumArgs() - 1))
end = getArg(getNumArgs() - 1)->getLocEnd();
return end;
}
OffsetOfExpr *OffsetOfExpr::Create(const ASTContext &C, QualType type,
SourceLocation OperatorLoc,
TypeSourceInfo *tsi,
ArrayRef<OffsetOfNode> comps,
ArrayRef<Expr*> exprs,
SourceLocation RParenLoc) {
void *Mem = C.Allocate(sizeof(OffsetOfExpr) +
sizeof(OffsetOfNode) * comps.size() +
sizeof(Expr*) * exprs.size());
return new (Mem) OffsetOfExpr(C, type, OperatorLoc, tsi, comps, exprs,
RParenLoc);
}
OffsetOfExpr *OffsetOfExpr::CreateEmpty(const ASTContext &C,
unsigned numComps, unsigned numExprs) {
void *Mem = C.Allocate(sizeof(OffsetOfExpr) +
sizeof(OffsetOfNode) * numComps +
sizeof(Expr*) * numExprs);
return new (Mem) OffsetOfExpr(numComps, numExprs);
}
OffsetOfExpr::OffsetOfExpr(const ASTContext &C, QualType type,
SourceLocation OperatorLoc, TypeSourceInfo *tsi,
ArrayRef<OffsetOfNode> comps, ArrayRef<Expr*> exprs,
SourceLocation RParenLoc)
: Expr(OffsetOfExprClass, type, VK_RValue, OK_Ordinary,
/*TypeDependent=*/false,
/*ValueDependent=*/tsi->getType()->isDependentType(),
tsi->getType()->isInstantiationDependentType(),
tsi->getType()->containsUnexpandedParameterPack()),
OperatorLoc(OperatorLoc), RParenLoc(RParenLoc), TSInfo(tsi),
NumComps(comps.size()), NumExprs(exprs.size())
{
for (unsigned i = 0; i != comps.size(); ++i) {
setComponent(i, comps[i]);
}
for (unsigned i = 0; i != exprs.size(); ++i) {
if (exprs[i]->isTypeDependent() || exprs[i]->isValueDependent())
ExprBits.ValueDependent = true;
if (exprs[i]->containsUnexpandedParameterPack())
ExprBits.ContainsUnexpandedParameterPack = true;
setIndexExpr(i, exprs[i]);
}
}
IdentifierInfo *OffsetOfExpr::OffsetOfNode::getFieldName() const {
assert(getKind() == Field || getKind() == Identifier);
if (getKind() == Field)
return getField()->getIdentifier();
return reinterpret_cast<IdentifierInfo *> (Data & ~(uintptr_t)Mask);
}
UnaryExprOrTypeTraitExpr::UnaryExprOrTypeTraitExpr(
UnaryExprOrTypeTrait ExprKind, Expr *E, QualType resultType,
SourceLocation op, SourceLocation rp)
: Expr(UnaryExprOrTypeTraitExprClass, resultType, VK_RValue, OK_Ordinary,
false, // Never type-dependent (C++ [temp.dep.expr]p3).
// Value-dependent if the argument is type-dependent.
E->isTypeDependent(), E->isInstantiationDependent(),
E->containsUnexpandedParameterPack()),
OpLoc(op), RParenLoc(rp) {
UnaryExprOrTypeTraitExprBits.Kind = ExprKind;
UnaryExprOrTypeTraitExprBits.IsType = false;
Argument.Ex = E;
// Check to see if we are in the situation where alignof(decl) should be
// dependent because decl's alignment is dependent.
if (ExprKind == UETT_AlignOf) {
if (!isValueDependent() || !isInstantiationDependent()) {
E = E->IgnoreParens();
const ValueDecl *D = nullptr;
if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
D = DRE->getDecl();
else if (const auto *ME = dyn_cast<MemberExpr>(E))
D = ME->getMemberDecl();
if (D) {
for (const auto *I : D->specific_attrs<AlignedAttr>()) {
if (I->isAlignmentDependent()) {
setValueDependent(true);
setInstantiationDependent(true);
break;
}
}
}
}
}
}
MemberExpr *MemberExpr::Create(
const ASTContext &C, Expr *base, bool isarrow, SourceLocation OperatorLoc,
NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc,
ValueDecl *memberdecl, DeclAccessPair founddecl,
DeclarationNameInfo nameinfo, const TemplateArgumentListInfo *targs,
QualType ty, ExprValueKind vk, ExprObjectKind ok) {
std::size_t Size = sizeof(MemberExpr);
bool hasQualOrFound = (QualifierLoc ||
founddecl.getDecl() != memberdecl ||
founddecl.getAccess() != memberdecl->getAccess());
if (hasQualOrFound)
Size += sizeof(MemberNameQualifier);
if (targs)
Size += ASTTemplateKWAndArgsInfo::sizeFor(targs->size());
else if (TemplateKWLoc.isValid())
Size += ASTTemplateKWAndArgsInfo::sizeFor(0);
void *Mem = C.Allocate(Size, llvm::alignOf<MemberExpr>());
MemberExpr *E = new (Mem)
MemberExpr(base, isarrow, OperatorLoc, memberdecl, nameinfo, ty, vk, ok);
if (hasQualOrFound) {
// FIXME: Wrong. We should be looking at the member declaration we found.
if (QualifierLoc && QualifierLoc.getNestedNameSpecifier()->isDependent()) {
E->setValueDependent(true);
E->setTypeDependent(true);
E->setInstantiationDependent(true);
}
else if (QualifierLoc &&
QualifierLoc.getNestedNameSpecifier()->isInstantiationDependent())
E->setInstantiationDependent(true);
E->HasQualifierOrFoundDecl = true;
MemberNameQualifier *NQ = E->getMemberQualifier();
NQ->QualifierLoc = QualifierLoc;
NQ->FoundDecl = founddecl;
}
E->HasTemplateKWAndArgsInfo = (targs || TemplateKWLoc.isValid());
if (targs) {
bool Dependent = false;
bool InstantiationDependent = false;
bool ContainsUnexpandedParameterPack = false;
E->getTemplateKWAndArgsInfo()->initializeFrom(TemplateKWLoc, *targs,
Dependent,
InstantiationDependent,
ContainsUnexpandedParameterPack);
if (InstantiationDependent)
E->setInstantiationDependent(true);
} else if (TemplateKWLoc.isValid()) {
E->getTemplateKWAndArgsInfo()->initializeFrom(TemplateKWLoc);
}
return E;
}
SourceLocation MemberExpr::getLocStart() const {
if (isImplicitAccess()) {
if (hasQualifier())
return getQualifierLoc().getBeginLoc();
return MemberLoc;
}
// FIXME: We don't want this to happen. Rather, we should be able to
// detect all kinds of implicit accesses more cleanly.
SourceLocation BaseStartLoc = getBase()->getLocStart();
if (BaseStartLoc.isValid())
return BaseStartLoc;
return MemberLoc;
}
SourceLocation MemberExpr::getLocEnd() const {
SourceLocation EndLoc = getMemberNameInfo().getEndLoc();
if (hasExplicitTemplateArgs())
EndLoc = getRAngleLoc();
else if (EndLoc.isInvalid())
EndLoc = getBase()->getLocEnd();
return EndLoc;
}
bool CastExpr::CastConsistency() const {
switch (getCastKind()) {
case CK_DerivedToBase:
case CK_UncheckedDerivedToBase:
case CK_DerivedToBaseMemberPointer:
case CK_BaseToDerived:
case CK_BaseToDerivedMemberPointer:
assert(!path_empty() && "Cast kind should have a base path!");
break;
case CK_CPointerToObjCPointerCast:
assert(getType()->isObjCObjectPointerType());
assert(getSubExpr()->getType()->isPointerType());
goto CheckNoBasePath;
case CK_BlockPointerToObjCPointerCast:
assert(getType()->isObjCObjectPointerType());
assert(getSubExpr()->getType()->isBlockPointerType());
goto CheckNoBasePath;
case CK_ReinterpretMemberPointer:
assert(getType()->isMemberPointerType());
assert(getSubExpr()->getType()->isMemberPointerType());
goto CheckNoBasePath;
case CK_BitCast:
// Arbitrary casts to C pointer types count as bitcasts.
// Otherwise, we should only have block and ObjC pointer casts
// here if they stay within the type kind.
if (!getType()->isPointerType()) {
assert(getType()->isObjCObjectPointerType() ==
getSubExpr()->getType()->isObjCObjectPointerType());
assert(getType()->isBlockPointerType() ==
getSubExpr()->getType()->isBlockPointerType());
}
goto CheckNoBasePath;
case CK_AnyPointerToBlockPointerCast:
assert(getType()->isBlockPointerType());
assert(getSubExpr()->getType()->isAnyPointerType() &&
!getSubExpr()->getType()->isBlockPointerType());
goto CheckNoBasePath;
case CK_CopyAndAutoreleaseBlockObject:
assert(getType()->isBlockPointerType());
assert(getSubExpr()->getType()->isBlockPointerType());
goto CheckNoBasePath;
case CK_FunctionToPointerDecay:
assert(getType()->isPointerType());
assert(getSubExpr()->getType()->isFunctionType());
goto CheckNoBasePath;
case CK_AddressSpaceConversion:
assert(getType()->isPointerType());
assert(getSubExpr()->getType()->isPointerType());
assert(getType()->getPointeeType().getAddressSpace() !=
getSubExpr()->getType()->getPointeeType().getAddressSpace());
// These should not have an inheritance path.
case CK_Dynamic:
case CK_ToUnion:
case CK_ArrayToPointerDecay:
case CK_NullToMemberPointer:
case CK_NullToPointer:
case CK_ConstructorConversion:
case CK_IntegralToPointer:
case CK_PointerToIntegral:
case CK_ToVoid:
case CK_VectorSplat:
case CK_IntegralCast:
case CK_IntegralToFloating:
case CK_FloatingToIntegral:
case CK_FloatingCast:
case CK_ObjCObjectLValueCast:
case CK_FloatingRealToComplex:
case CK_FloatingComplexToReal:
case CK_FloatingComplexCast:
case CK_FloatingComplexToIntegralComplex:
case CK_IntegralRealToComplex:
case CK_IntegralComplexToReal:
case CK_IntegralComplexCast:
case CK_IntegralComplexToFloatingComplex:
case CK_ARCProduceObject:
case CK_ARCConsumeObject:
case CK_ARCReclaimReturnedObject:
case CK_ARCExtendBlockObject:
case CK_ZeroToOCLEvent:
assert(!getType()->isBooleanType() && "unheralded conversion to bool");
goto CheckNoBasePath;
case CK_Dependent:
case CK_LValueToRValue:
case CK_NoOp:
case CK_AtomicToNonAtomic:
case CK_NonAtomicToAtomic:
case CK_PointerToBoolean:
case CK_IntegralToBoolean:
case CK_FloatingToBoolean:
case CK_MemberPointerToBoolean:
case CK_FloatingComplexToBoolean:
case CK_IntegralComplexToBoolean:
case CK_LValueBitCast: // -> bool&
case CK_UserDefinedConversion: // operator bool()
case CK_BuiltinFnToFnPtr:
CheckNoBasePath:
assert(path_empty() && "Cast kind should not have a base path!");
break;
}
return true;
}
const char *CastExpr::getCastKindName() const {
switch (getCastKind()) {
case CK_Dependent:
return "Dependent";
case CK_BitCast:
return "BitCast";
case CK_LValueBitCast:
return "LValueBitCast";
case CK_LValueToRValue:
return "LValueToRValue";
case CK_NoOp:
return "NoOp";
case CK_BaseToDerived:
return "BaseToDerived";
case CK_DerivedToBase:
return "DerivedToBase";
case CK_UncheckedDerivedToBase:
return "UncheckedDerivedToBase";
case CK_Dynamic:
return "Dynamic";
case CK_ToUnion:
return "ToUnion";
case CK_ArrayToPointerDecay:
return "ArrayToPointerDecay";
case CK_FunctionToPointerDecay:
return "FunctionToPointerDecay";
case CK_NullToMemberPointer:
return "NullToMemberPointer";
case CK_NullToPointer:
return "NullToPointer";
case CK_BaseToDerivedMemberPointer:
return "BaseToDerivedMemberPointer";
case CK_DerivedToBaseMemberPointer:
return "DerivedToBaseMemberPointer";
case CK_ReinterpretMemberPointer:
return "ReinterpretMemberPointer";
case CK_UserDefinedConversion:
return "UserDefinedConversion";
case CK_ConstructorConversion:
return "ConstructorConversion";
case CK_IntegralToPointer:
return "IntegralToPointer";
case CK_PointerToIntegral:
return "PointerToIntegral";
case CK_PointerToBoolean:
return "PointerToBoolean";
case CK_ToVoid:
return "ToVoid";
case CK_VectorSplat:
return "VectorSplat";
case CK_IntegralCast:
return "IntegralCast";
case CK_IntegralToBoolean:
return "IntegralToBoolean";
case CK_IntegralToFloating:
return "IntegralToFloating";
case CK_FloatingToIntegral:
return "FloatingToIntegral";
case CK_FloatingCast:
return "FloatingCast";
case CK_FloatingToBoolean:
return "FloatingToBoolean";
case CK_MemberPointerToBoolean:
return "MemberPointerToBoolean";
case CK_CPointerToObjCPointerCast:
return "CPointerToObjCPointerCast";
case CK_BlockPointerToObjCPointerCast:
return "BlockPointerToObjCPointerCast";
case CK_AnyPointerToBlockPointerCast:
return "AnyPointerToBlockPointerCast";
case CK_ObjCObjectLValueCast:
return "ObjCObjectLValueCast";
case CK_FloatingRealToComplex:
return "FloatingRealToComplex";
case CK_FloatingComplexToReal:
return "FloatingComplexToReal";
case CK_FloatingComplexToBoolean:
return "FloatingComplexToBoolean";
case CK_FloatingComplexCast:
return "FloatingComplexCast";
case CK_FloatingComplexToIntegralComplex:
return "FloatingComplexToIntegralComplex";
case CK_IntegralRealToComplex:
return "IntegralRealToComplex";
case CK_IntegralComplexToReal:
return "IntegralComplexToReal";
case CK_IntegralComplexToBoolean:
return "IntegralComplexToBoolean";
case CK_IntegralComplexCast:
return "IntegralComplexCast";
case CK_IntegralComplexToFloatingComplex:
return "IntegralComplexToFloatingComplex";
case CK_ARCConsumeObject:
return "ARCConsumeObject";
case CK_ARCProduceObject:
return "ARCProduceObject";
case CK_ARCReclaimReturnedObject:
return "ARCReclaimReturnedObject";
case CK_ARCExtendBlockObject:
return "ARCExtendBlockObject";
case CK_AtomicToNonAtomic:
return "AtomicToNonAtomic";
case CK_NonAtomicToAtomic:
return "NonAtomicToAtomic";
case CK_CopyAndAutoreleaseBlockObject:
return "CopyAndAutoreleaseBlockObject";
case CK_BuiltinFnToFnPtr:
return "BuiltinFnToFnPtr";
case CK_ZeroToOCLEvent:
return "ZeroToOCLEvent";
case CK_AddressSpaceConversion:
return "AddressSpaceConversion";
}
llvm_unreachable("Unhandled cast kind!");
}
Expr *CastExpr::getSubExprAsWritten() {
Expr *SubExpr = nullptr;
CastExpr *E = this;
do {
SubExpr = E->getSubExpr();
// Skip through reference binding to temporary.
if (MaterializeTemporaryExpr *Materialize
= dyn_cast<MaterializeTemporaryExpr>(SubExpr))
SubExpr = Materialize->GetTemporaryExpr();
// Skip any temporary bindings; they're implicit.
if (CXXBindTemporaryExpr *Binder = dyn_cast<CXXBindTemporaryExpr>(SubExpr))
SubExpr = Binder->getSubExpr();
// Conversions by constructor and conversion functions have a
// subexpression describing the call; strip it off.
if (E->getCastKind() == CK_ConstructorConversion)
SubExpr = cast<CXXConstructExpr>(SubExpr)->getArg(0);
else if (E->getCastKind() == CK_UserDefinedConversion)
SubExpr = cast<CXXMemberCallExpr>(SubExpr)->getImplicitObjectArgument();
// If the subexpression we're left with is an implicit cast, look
// through that, too.
} while ((E = dyn_cast<ImplicitCastExpr>(SubExpr)));
return SubExpr;
}
CXXBaseSpecifier **CastExpr::path_buffer() {
switch (getStmtClass()) {
#define ABSTRACT_STMT(x)
#define CASTEXPR(Type, Base) \
case Stmt::Type##Class: \
return reinterpret_cast<CXXBaseSpecifier**>(static_cast<Type*>(this)+1);
#define STMT(Type, Base)
#include "clang/AST/StmtNodes.inc"
default:
llvm_unreachable("non-cast expressions not possible here");
}
}
void CastExpr::setCastPath(const CXXCastPath &Path) {
assert(Path.size() == path_size());
memcpy(path_buffer(), Path.data(), Path.size() * sizeof(CXXBaseSpecifier*));
}
ImplicitCastExpr *ImplicitCastExpr::Create(const ASTContext &C, QualType T,
CastKind Kind, Expr *Operand,
const CXXCastPath *BasePath,
ExprValueKind VK) {
unsigned PathSize = (BasePath ? BasePath->size() : 0);
void *Buffer =
C.Allocate(sizeof(ImplicitCastExpr) + PathSize * sizeof(CXXBaseSpecifier*));
ImplicitCastExpr *E =
new (Buffer) ImplicitCastExpr(T, Kind, Operand, PathSize, VK);
if (PathSize) E->setCastPath(*BasePath);
return E;
}
ImplicitCastExpr *ImplicitCastExpr::CreateEmpty(const ASTContext &C,
unsigned PathSize) {
void *Buffer =
C.Allocate(sizeof(ImplicitCastExpr) + PathSize * sizeof(CXXBaseSpecifier*));
return new (Buffer) ImplicitCastExpr(EmptyShell(), PathSize);
}
CStyleCastExpr *CStyleCastExpr::Create(const ASTContext &C, QualType T,
ExprValueKind VK, CastKind K, Expr *Op,
const CXXCastPath *BasePath,
TypeSourceInfo *WrittenTy,
SourceLocation L, SourceLocation R) {
unsigned PathSize = (BasePath ? BasePath->size() : 0);
void *Buffer =
C.Allocate(sizeof(CStyleCastExpr) + PathSize * sizeof(CXXBaseSpecifier*));
CStyleCastExpr *E =
new (Buffer) CStyleCastExpr(T, VK, K, Op, PathSize, WrittenTy, L, R);
if (PathSize) E->setCastPath(*BasePath);
return E;
}
CStyleCastExpr *CStyleCastExpr::CreateEmpty(const ASTContext &C,
unsigned PathSize) {
void *Buffer =
C.Allocate(sizeof(CStyleCastExpr) + PathSize * sizeof(CXXBaseSpecifier*));
return new (Buffer) CStyleCastExpr(EmptyShell(), PathSize);
}
/// getOpcodeStr - Turn an Opcode enum value into the punctuation char it
/// corresponds to, e.g. "<<=".
StringRef BinaryOperator::getOpcodeStr(Opcode Op) {
switch (Op) {
case BO_PtrMemD: return ".*";
case BO_PtrMemI: return "->*";
case BO_Mul: return "*";
case BO_Div: return "/";
case BO_Rem: return "%";
case BO_Add: return "+";
case BO_Sub: return "-";
case BO_Shl: return "<<";
case BO_Shr: return ">>";
case BO_LT: return "<";
case BO_GT: return ">";
case BO_LE: return "<=";
case BO_GE: return ">=";
case BO_EQ: return "==";
case BO_NE: return "!=";
case BO_And: return "&";
case BO_Xor: return "^";
case BO_Or: return "|";
case BO_LAnd: return "&&";
case BO_LOr: return "||";
case BO_Assign: return "=";
case BO_MulAssign: return "*=";
case BO_DivAssign: return "/=";
case BO_RemAssign: return "%=";
case BO_AddAssign: return "+=";
case BO_SubAssign: return "-=";
case BO_ShlAssign: return "<<=";
case BO_ShrAssign: return ">>=";
case BO_AndAssign: return "&=";
case BO_XorAssign: return "^=";
case BO_OrAssign: return "|=";
case BO_Comma: return ",";
}
llvm_unreachable("Invalid OpCode!");
}
BinaryOperatorKind
BinaryOperator::getOverloadedOpcode(OverloadedOperatorKind OO) {
switch (OO) {
default: llvm_unreachable("Not an overloadable binary operator");
case OO_Plus: return BO_Add;
case OO_Minus: return BO_Sub;
case OO_Star: return BO_Mul;
case OO_Slash: return BO_Div;
case OO_Percent: return BO_Rem;
case OO_Caret: return BO_Xor;
case OO_Amp: return BO_And;
case OO_Pipe: return BO_Or;
case OO_Equal: return BO_Assign;
case OO_Less: return BO_LT;
case OO_Greater: return BO_GT;
case OO_PlusEqual: return BO_AddAssign;
case OO_MinusEqual: return BO_SubAssign;
case OO_StarEqual: return BO_MulAssign;
case OO_SlashEqual: return BO_DivAssign;
case OO_PercentEqual: return BO_RemAssign;
case OO_CaretEqual: return BO_XorAssign;
case OO_AmpEqual: return BO_AndAssign;
case OO_PipeEqual: return BO_OrAssign;
case OO_LessLess: return BO_Shl;
case OO_GreaterGreater: return BO_Shr;
case OO_LessLessEqual: return BO_ShlAssign;
case OO_GreaterGreaterEqual: return BO_ShrAssign;
case OO_EqualEqual: return BO_EQ;
case OO_ExclaimEqual: return BO_NE;
case OO_LessEqual: return BO_LE;
case OO_GreaterEqual: return BO_GE;
case OO_AmpAmp: return BO_LAnd;
case OO_PipePipe: return BO_LOr;
case OO_Comma: return BO_Comma;
case OO_ArrowStar: return BO_PtrMemI;
}
}
OverloadedOperatorKind BinaryOperator::getOverloadedOperator(Opcode Opc) {
static const OverloadedOperatorKind OverOps[] = {
/* .* Cannot be overloaded */OO_None, OO_ArrowStar,
OO_Star, OO_Slash, OO_Percent,
OO_Plus, OO_Minus,
OO_LessLess, OO_GreaterGreater,
OO_Less, OO_Greater, OO_LessEqual, OO_GreaterEqual,
OO_EqualEqual, OO_ExclaimEqual,
OO_Amp,
OO_Caret,
OO_Pipe,
OO_AmpAmp,
OO_PipePipe,
OO_Equal, OO_StarEqual,
OO_SlashEqual, OO_PercentEqual,
OO_PlusEqual, OO_MinusEqual,
OO_LessLessEqual, OO_GreaterGreaterEqual,
OO_AmpEqual, OO_CaretEqual,
OO_PipeEqual,
OO_Comma
};
return OverOps[Opc];
}
InitListExpr::InitListExpr(const ASTContext &C, SourceLocation lbraceloc,
ArrayRef<Expr*> initExprs, SourceLocation rbraceloc)
: Expr(InitListExprClass, QualType(), VK_RValue, OK_Ordinary, false, false,
false, false),
InitExprs(C, initExprs.size()),
LBraceLoc(lbraceloc), RBraceLoc(rbraceloc), AltForm(nullptr, true)
{
sawArrayRangeDesignator(false);
for (unsigned I = 0; I != initExprs.size(); ++I) {
if (initExprs[I]->isTypeDependent())
ExprBits.TypeDependent = true;
if (initExprs[I]->isValueDependent())
ExprBits.ValueDependent = true;
if (initExprs[I]->isInstantiationDependent())
ExprBits.InstantiationDependent = true;
if (initExprs[I]->containsUnexpandedParameterPack())
ExprBits.ContainsUnexpandedParameterPack = true;
}
InitExprs.insert(C, InitExprs.end(), initExprs.begin(), initExprs.end());
}
void InitListExpr::reserveInits(const ASTContext &C, unsigned NumInits) {
if (NumInits > InitExprs.size())
InitExprs.reserve(C, NumInits);
}
void InitListExpr::resizeInits(const ASTContext &C, unsigned NumInits) {
InitExprs.resize(C, NumInits, nullptr);
}
Expr *InitListExpr::updateInit(const ASTContext &C, unsigned Init, Expr *expr) {
if (Init >= InitExprs.size()) {
InitExprs.insert(C, InitExprs.end(), Init - InitExprs.size() + 1, nullptr);
setInit(Init, expr);
return nullptr;
}
Expr *Result = cast_or_null<Expr>(InitExprs[Init]);
setInit(Init, expr);
return Result;
}
void InitListExpr::setArrayFiller(Expr *filler) {
assert(!hasArrayFiller() && "Filler already set!");
ArrayFillerOrUnionFieldInit = filler;
// Fill out any "holes" in the array due to designated initializers.
Expr **inits = getInits();
for (unsigned i = 0, e = getNumInits(); i != e; ++i)
if (inits[i] == nullptr)
inits[i] = filler;
}
bool InitListExpr::isStringLiteralInit() const {
if (getNumInits() != 1)
return false;
const ArrayType *AT = getType()->getAsArrayTypeUnsafe();
if (!AT || !AT->getElementType()->isIntegerType())
return false;
// It is possible for getInit() to return null.
const Expr *Init = getInit(0);
if (!Init)
return false;
Init = Init->IgnoreParens();
return isa<StringLiteral>(Init) || isa<ObjCEncodeExpr>(Init);
}
SourceLocation InitListExpr::getLocStart() const {
if (InitListExpr *SyntacticForm = getSyntacticForm())
return SyntacticForm->getLocStart();
SourceLocation Beg = LBraceLoc;
if (Beg.isInvalid()) {
// Find the first non-null initializer.
for (InitExprsTy::const_iterator I = InitExprs.begin(),
E = InitExprs.end();
I != E; ++I) {
if (Stmt *S = *I) {
Beg = S->getLocStart();
break;
}
}
}
return Beg;
}
SourceLocation InitListExpr::getLocEnd() const {
if (InitListExpr *SyntacticForm = getSyntacticForm())
return SyntacticForm->getLocEnd();
SourceLocation End = RBraceLoc;
if (End.isInvalid()) {
// Find the first non-null initializer from the end.
for (InitExprsTy::const_reverse_iterator I = InitExprs.rbegin(),
E = InitExprs.rend();
I != E; ++I) {
if (Stmt *S = *I) {
End = S->getLocEnd();
break;
}
}
}
return End;
}
/// getFunctionType - Return the underlying function type for this block.
///
const FunctionProtoType *BlockExpr::getFunctionType() const {
// The block pointer is never sugared, but the function type might be.
return cast<BlockPointerType>(getType())
->getPointeeType()->castAs<FunctionProtoType>();
}
SourceLocation BlockExpr::getCaretLocation() const {
return TheBlock->getCaretLocation();
}
const Stmt *BlockExpr::getBody() const {
return TheBlock->getBody();
}
Stmt *BlockExpr::getBody() {
return TheBlock->getBody();
}
//===----------------------------------------------------------------------===//
// Generic Expression Routines
//===----------------------------------------------------------------------===//
/// isUnusedResultAWarning - Return true if this immediate expression should
/// be warned about if the result is unused. If so, fill in Loc and Ranges
/// with location to warn on and the source range[s] to report with the
/// warning.
bool Expr::isUnusedResultAWarning(const Expr *&WarnE, SourceLocation &Loc,
SourceRange &R1, SourceRange &R2,
ASTContext &Ctx) const {
// Don't warn if the expr is type dependent. The type could end up
// instantiating to void.
if (isTypeDependent())
return false;
switch (getStmtClass()) {
default:
if (getType()->isVoidType())
return false;
WarnE = this;
Loc = getExprLoc();
R1 = getSourceRange();
return true;
case ParenExprClass:
return cast<ParenExpr>(this)->getSubExpr()->
isUnusedResultAWarning(WarnE, Loc, R1, R2, Ctx);
case GenericSelectionExprClass:
return cast<GenericSelectionExpr>(this)->getResultExpr()->
isUnusedResultAWarning(WarnE, Loc, R1, R2, Ctx);
case ChooseExprClass:
return cast<ChooseExpr>(this)->getChosenSubExpr()->
isUnusedResultAWarning(WarnE, Loc, R1, R2, Ctx);
case UnaryOperatorClass: {
const UnaryOperator *UO = cast<UnaryOperator>(this);
switch (UO->getOpcode()) {
case UO_Plus:
case UO_Minus:
case UO_AddrOf:
case UO_Not:
case UO_LNot:
case UO_Deref:
break;
case UO_Coawait:
// This is just the 'operator co_await' call inside the guts of a
// dependent co_await call.
case UO_PostInc:
case UO_PostDec:
case UO_PreInc:
case UO_PreDec: // ++/--
return false; // Not a warning.
case UO_Real:
case UO_Imag:
// accessing a piece of a volatile complex is a side-effect.
if (Ctx.getCanonicalType(UO->getSubExpr()->getType())
.isVolatileQualified())
return false;
break;
case UO_Extension:
return UO->getSubExpr()->isUnusedResultAWarning(WarnE, Loc, R1, R2, Ctx);
}
WarnE = this;
Loc = UO->getOperatorLoc();
R1 = UO->getSubExpr()->getSourceRange();
return true;
}
case BinaryOperatorClass: {
const BinaryOperator *BO = cast<BinaryOperator>(this);
switch (BO->getOpcode()) {
default:
break;
// Consider the RHS of comma for side effects. LHS was checked by
// Sema::CheckCommaOperands.
case BO_Comma:
// ((foo = <blah>), 0) is an idiom for hiding the result (and
// lvalue-ness) of an assignment written in a macro.
if (IntegerLiteral *IE =
dyn_cast<IntegerLiteral>(BO->getRHS()->IgnoreParens()))
if (IE->getValue() == 0)
return false;
return BO->getRHS()->isUnusedResultAWarning(WarnE, Loc, R1, R2, Ctx);
// Consider '||', '&&' to have side effects if the LHS or RHS does.
case BO_LAnd:
case BO_LOr:
if (!BO->getLHS()->isUnusedResultAWarning(WarnE, Loc, R1, R2, Ctx) ||
!BO->getRHS()->isUnusedResultAWarning(WarnE, Loc, R1, R2, Ctx))
return false;
break;
}
if (BO->isAssignmentOp())
return false;
WarnE = this;
Loc = BO->getOperatorLoc();
R1 = BO->getLHS()->getSourceRange();
R2 = BO->getRHS()->getSourceRange();
return true;
}
case CompoundAssignOperatorClass:
case VAArgExprClass:
case AtomicExprClass:
return false;
case ConditionalOperatorClass: {
// If only one of the LHS or RHS is a warning, the operator might
// be being used for control flow. Only warn if both the LHS and
// RHS are warnings.
const ConditionalOperator *Exp = cast<ConditionalOperator>(this);
if (!Exp->getRHS()->isUnusedResultAWarning(WarnE, Loc, R1, R2, Ctx))
return false;
if (!Exp->getLHS())
return true;
return Exp->getLHS()->isUnusedResultAWarning(WarnE, Loc, R1, R2, Ctx);
}
case MemberExprClass:
WarnE = this;
Loc = cast<MemberExpr>(this)->getMemberLoc();
R1 = SourceRange(Loc, Loc);
R2 = cast<MemberExpr>(this)->getBase()->getSourceRange();
return true;
case ArraySubscriptExprClass:
WarnE = this;
Loc = cast<ArraySubscriptExpr>(this)->getRBracketLoc();
R1 = cast<ArraySubscriptExpr>(this)->getLHS()->getSourceRange();
R2 = cast<ArraySubscriptExpr>(this)->getRHS()->getSourceRange();
return true;
case CXXOperatorCallExprClass: {
// Warn about operator ==,!=,<,>,<=, and >= even when user-defined operator
// overloads as there is no reasonable way to define these such that they
// have non-trivial, desirable side-effects. See the -Wunused-comparison
// warning: operators == and != are commonly typo'ed, and so warning on them
// provides additional value as well. If this list is updated,
// DiagnoseUnusedComparison should be as well.
const CXXOperatorCallExpr *Op = cast<CXXOperatorCallExpr>(this);
switch (Op->getOperator()) {
default:
break;
case OO_EqualEqual:
case OO_ExclaimEqual:
case OO_Less:
case OO_Greater:
case OO_GreaterEqual:
case OO_LessEqual:
if (Op->getCallReturnType(Ctx)->isReferenceType() ||
Op->getCallReturnType(Ctx)->isVoidType())
break;
WarnE = this;
Loc = Op->getOperatorLoc();
R1 = Op->getSourceRange();
return true;
}
// Fallthrough for generic call handling.
}
case CallExprClass:
case CXXMemberCallExprClass:
case UserDefinedLiteralClass: {
// If this is a direct call, get the callee.
const CallExpr *CE = cast<CallExpr>(this);
if (const Decl *FD = CE->getCalleeDecl()) {
const FunctionDecl *Func = dyn_cast<FunctionDecl>(FD);
bool HasWarnUnusedResultAttr = Func ? Func->hasUnusedResultAttr()
: FD->hasAttr<WarnUnusedResultAttr>();
// If the callee has attribute pure, const, or warn_unused_result, warn
// about it. void foo() { strlen("bar"); } should warn.
//
// Note: If new cases are added here, DiagnoseUnusedExprResult should be
// updated to match for QoI.
if (HasWarnUnusedResultAttr ||
FD->hasAttr<PureAttr>() || FD->hasAttr<ConstAttr>()) {
WarnE = this;
Loc = CE->getCallee()->getLocStart();
R1 = CE->getCallee()->getSourceRange();
if (unsigned NumArgs = CE->getNumArgs())
R2 = SourceRange(CE->getArg(0)->getLocStart(),
CE->getArg(NumArgs-1)->getLocEnd());
return true;
}
}
return false;
}
// If we don't know precisely what we're looking at, let's not warn.
case UnresolvedLookupExprClass:
case CXXUnresolvedConstructExprClass:
return false;
case CXXTemporaryObjectExprClass:
case CXXConstructExprClass: {
if (const CXXRecordDecl *Type = getType()->getAsCXXRecordDecl()) {
if (Type->hasAttr<WarnUnusedAttr>()) {
WarnE = this;
Loc = getLocStart();
R1 = getSourceRange();
return true;
}
}
return false;
}
case ObjCMessageExprClass: {
const ObjCMessageExpr *ME = cast<ObjCMessageExpr>(this);
if (Ctx.getLangOpts().ObjCAutoRefCount &&
ME->isInstanceMessage() &&
!ME->getType()->isVoidType() &&
ME->getMethodFamily() == OMF_init) {
WarnE = this;
Loc = getExprLoc();
R1 = ME->getSourceRange();
return true;
}
if (const ObjCMethodDecl *MD = ME->getMethodDecl())
if (MD->hasAttr<WarnUnusedResultAttr>()) {
WarnE = this;
Loc = getExprLoc();
return true;
}
return false;
}
case ObjCPropertyRefExprClass:
WarnE = this;
Loc = getExprLoc();
R1 = getSourceRange();
return true;
case PseudoObjectExprClass: {
const PseudoObjectExpr *PO = cast<PseudoObjectExpr>(this);
// Only complain about things that have the form of a getter.
if (isa<UnaryOperator>(PO->getSyntacticForm()) ||
isa<BinaryOperator>(PO->getSyntacticForm()))
return false;
WarnE = this;
Loc = getExprLoc();
R1 = getSourceRange();
return true;
}
case StmtExprClass: {
// Statement exprs don't logically have side effects themselves, but are
// sometimes used in macros in ways that give them a type that is unused.
// For example ({ blah; foo(); }) will end up with a type if foo has a type.
// however, if the result of the stmt expr is dead, we don't want to emit a
// warning.
const CompoundStmt *CS = cast<StmtExpr>(this)->getSubStmt();
if (!CS->body_empty()) {
if (const Expr *E = dyn_cast<Expr>(CS->body_back()))
return E->isUnusedResultAWarning(WarnE, Loc, R1, R2, Ctx);
if (const LabelStmt *Label = dyn_cast<LabelStmt>(CS->body_back()))
if (const Expr *E = dyn_cast<Expr>(Label->getSubStmt()))
return E->isUnusedResultAWarning(WarnE, Loc, R1, R2, Ctx);
}
if (getType()->isVoidType())
return false;
WarnE = this;
Loc = cast<StmtExpr>(this)->getLParenLoc();
R1 = getSourceRange();
return true;
}
case CXXFunctionalCastExprClass:
case CStyleCastExprClass: {
// Ignore an explicit cast to void unless the operand is a non-trivial
// volatile lvalue.
const CastExpr *CE = cast<CastExpr>(this);
if (CE->getCastKind() == CK_ToVoid) {
if (CE->getSubExpr()->isGLValue() &&
CE->getSubExpr()->getType().isVolatileQualified()) {
const DeclRefExpr *DRE =
dyn_cast<DeclRefExpr>(CE->getSubExpr()->IgnoreParens());
if (!(DRE && isa<VarDecl>(DRE->getDecl()) &&
cast<VarDecl>(DRE->getDecl())->hasLocalStorage())) {
return CE->getSubExpr()->isUnusedResultAWarning(WarnE, Loc,
R1, R2, Ctx);
}
}
return false;
}
// If this is a cast to a constructor conversion, check the operand.
// Otherwise, the result of the cast is unused.
if (CE->getCastKind() == CK_ConstructorConversion)
return CE->getSubExpr()->isUnusedResultAWarning(WarnE, Loc, R1, R2, Ctx);
WarnE = this;
if (const CXXFunctionalCastExpr *CXXCE =
dyn_cast<CXXFunctionalCastExpr>(this)) {
Loc = CXXCE->getLocStart();
R1 = CXXCE->getSubExpr()->getSourceRange();
} else {
const CStyleCastExpr *CStyleCE = cast<CStyleCastExpr>(this);
Loc = CStyleCE->getLParenLoc();
R1 = CStyleCE->getSubExpr()->getSourceRange();
}
return true;
}
case ImplicitCastExprClass: {
const CastExpr *ICE = cast<ImplicitCastExpr>(this);
// lvalue-to-rvalue conversion on a volatile lvalue is a side-effect.
if (ICE->getCastKind() == CK_LValueToRValue &&
ICE->getSubExpr()->getType().isVolatileQualified())
return false;
return ICE->getSubExpr()->isUnusedResultAWarning(WarnE, Loc, R1, R2, Ctx);
}
case CXXDefaultArgExprClass:
return (cast<CXXDefaultArgExpr>(this)
->getExpr()->isUnusedResultAWarning(WarnE, Loc, R1, R2, Ctx));
case CXXDefaultInitExprClass:
return (cast<CXXDefaultInitExpr>(this)
->getExpr()->isUnusedResultAWarning(WarnE, Loc, R1, R2, Ctx));
case CXXNewExprClass:
// FIXME: In theory, there might be new expressions that don't have side
// effects (e.g. a placement new with an uninitialized POD).
case CXXDeleteExprClass:
return false;
case CXXBindTemporaryExprClass:
return (cast<CXXBindTemporaryExpr>(this)
->getSubExpr()->isUnusedResultAWarning(WarnE, Loc, R1, R2, Ctx));
case ExprWithCleanupsClass:
return (cast<ExprWithCleanups>(this)
->getSubExpr()->isUnusedResultAWarning(WarnE, Loc, R1, R2, Ctx));
}
}
/// isOBJCGCCandidate - Check if an expression is objc gc'able.
/// returns true, if it is; false otherwise.
bool Expr::isOBJCGCCandidate(ASTContext &Ctx) const {
const Expr *E = IgnoreParens();
switch (E->getStmtClass()) {
default:
return false;
case ObjCIvarRefExprClass:
return true;
case Expr::UnaryOperatorClass:
return cast<UnaryOperator>(E)->getSubExpr()->isOBJCGCCandidate(Ctx);
case ImplicitCastExprClass:
return cast<ImplicitCastExpr>(E)->getSubExpr()->isOBJCGCCandidate(Ctx);
case MaterializeTemporaryExprClass:
return cast<MaterializeTemporaryExpr>(E)->GetTemporaryExpr()
->isOBJCGCCandidate(Ctx);
case CStyleCastExprClass:
return cast<CStyleCastExpr>(E)->getSubExpr()->isOBJCGCCandidate(Ctx);
case DeclRefExprClass: {
const Decl *D = cast<DeclRefExpr>(E)->getDecl();
if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
if (VD->hasGlobalStorage())
return true;
QualType T = VD->getType();
// dereferencing to a pointer is always a gc'able candidate,
// unless it is __weak.
return T->isPointerType() &&
(Ctx.getObjCGCAttrKind(T) != Qualifiers::Weak);
}
return false;
}
case MemberExprClass: {
const MemberExpr *M = cast<MemberExpr>(E);
return M->getBase()->isOBJCGCCandidate(Ctx);
}
case ArraySubscriptExprClass:
return cast<ArraySubscriptExpr>(E)->getBase()->isOBJCGCCandidate(Ctx);
}
}
bool Expr::isBoundMemberFunction(ASTContext &Ctx) const {
if (isTypeDependent())
return false;
return ClassifyLValue(Ctx) == Expr::LV_MemberFunction;
}
QualType Expr::findBoundMemberType(const Expr *expr) {
assert(expr->hasPlaceholderType(BuiltinType::BoundMember));
// Bound member expressions are always one of these possibilities:
// x->m x.m x->*y x.*y
// (possibly parenthesized)
expr = expr->IgnoreParens();
if (const MemberExpr *mem = dyn_cast<MemberExpr>(expr)) {
assert(isa<CXXMethodDecl>(mem->getMemberDecl()));
return mem->getMemberDecl()->getType();
}
if (const BinaryOperator *op = dyn_cast<BinaryOperator>(expr)) {
QualType type = op->getRHS()->getType()->castAs<MemberPointerType>()
->getPointeeType();
assert(type->isFunctionType());
return type;
}
assert(isa<UnresolvedMemberExpr>(expr) || isa<CXXPseudoDestructorExpr>(expr));
return QualType();
}
Expr* Expr::IgnoreParens() {
Expr* E = this;
while (true) {
if (ParenExpr* P = dyn_cast<ParenExpr>(E)) {
E = P->getSubExpr();
continue;
}
if (UnaryOperator* P = dyn_cast<UnaryOperator>(E)) {
if (P->getOpcode() == UO_Extension) {
E = P->getSubExpr();
continue;
}
}
if (GenericSelectionExpr* P = dyn_cast<GenericSelectionExpr>(E)) {
if (!P->isResultDependent()) {
E = P->getResultExpr();
continue;
}
}
if (ChooseExpr* P = dyn_cast<ChooseExpr>(E)) {
if (!P->isConditionDependent()) {
E = P->getChosenSubExpr();
continue;
}
}
return E;
}
}
/// IgnoreParenCasts - Ignore parentheses and casts. Strip off any ParenExpr
/// or CastExprs or ImplicitCastExprs, returning their operand.
Expr *Expr::IgnoreParenCasts() {
Expr *E = this;
while (true) {
E = E->IgnoreParens();
if (CastExpr *P = dyn_cast<CastExpr>(E)) {
E = P->getSubExpr();
continue;
}
if (MaterializeTemporaryExpr *Materialize
= dyn_cast<MaterializeTemporaryExpr>(E)) {
E = Materialize->GetTemporaryExpr();
continue;
}
if (SubstNonTypeTemplateParmExpr *NTTP
= dyn_cast<SubstNonTypeTemplateParmExpr>(E)) {
E = NTTP->getReplacement();
continue;
}
return E;
}
}
Expr *Expr::IgnoreCasts() {
Expr *E = this;
while (true) {
if (CastExpr *P = dyn_cast<CastExpr>(E)) {
E = P->getSubExpr();
continue;
}
if (MaterializeTemporaryExpr *Materialize
= dyn_cast<MaterializeTemporaryExpr>(E)) {
E = Materialize->GetTemporaryExpr();
continue;
}
if (SubstNonTypeTemplateParmExpr *NTTP
= dyn_cast<SubstNonTypeTemplateParmExpr>(E)) {
E = NTTP->getReplacement();
continue;
}
return E;
}
}
/// IgnoreParenLValueCasts - Ignore parentheses and lvalue-to-rvalue
/// casts. This is intended purely as a temporary workaround for code
/// that hasn't yet been rewritten to do the right thing about those
/// casts, and may disappear along with the last internal use.
Expr *Expr::IgnoreParenLValueCasts() {
Expr *E = this;
while (true) {
E = E->IgnoreParens();
if (CastExpr *P = dyn_cast<CastExpr>(E)) {
if (P->getCastKind() == CK_LValueToRValue) {
E = P->getSubExpr();
continue;
}
} else if (MaterializeTemporaryExpr *Materialize
= dyn_cast<MaterializeTemporaryExpr>(E)) {
E = Materialize->GetTemporaryExpr();
continue;
} else if (SubstNonTypeTemplateParmExpr *NTTP
= dyn_cast<SubstNonTypeTemplateParmExpr>(E)) {
E = NTTP->getReplacement();
continue;
}
break;
}
return E;
}
Expr *Expr::ignoreParenBaseCasts() {
Expr *E = this;
while (true) {
E = E->IgnoreParens();
if (CastExpr *CE = dyn_cast<CastExpr>(E)) {
if (CE->getCastKind() == CK_DerivedToBase ||
CE->getCastKind() == CK_UncheckedDerivedToBase ||
CE->getCastKind() == CK_NoOp) {
E = CE->getSubExpr();
continue;
}
}
return E;
}
}
Expr *Expr::IgnoreParenImpCasts() {
Expr *E = this;
while (true) {
E = E->IgnoreParens();
if (ImplicitCastExpr *P = dyn_cast<ImplicitCastExpr>(E)) {
E = P->getSubExpr();
continue;
}
if (MaterializeTemporaryExpr *Materialize
= dyn_cast<MaterializeTemporaryExpr>(E)) {
E = Materialize->GetTemporaryExpr();
continue;
}
if (SubstNonTypeTemplateParmExpr *NTTP
= dyn_cast<SubstNonTypeTemplateParmExpr>(E)) {
E = NTTP->getReplacement();
continue;
}
return E;
}
}
Expr *Expr::IgnoreConversionOperator() {
if (CXXMemberCallExpr *MCE = dyn_cast<CXXMemberCallExpr>(this)) {
if (MCE->getMethodDecl() && isa<CXXConversionDecl>(MCE->getMethodDecl()))
return MCE->getImplicitObjectArgument();
}
return this;
}
/// IgnoreParenNoopCasts - Ignore parentheses and casts that do not change the
/// value (including ptr->int casts of the same size). Strip off any
/// ParenExpr or CastExprs, returning their operand.
Expr *Expr::IgnoreParenNoopCasts(ASTContext &Ctx) {
Expr *E = this;
while (true) {
E = E->IgnoreParens();
if (CastExpr *P = dyn_cast<CastExpr>(E)) {
// We ignore integer <-> casts that are of the same width, ptr<->ptr and
// ptr<->int casts of the same width. We also ignore all identity casts.
Expr *SE = P->getSubExpr();
if (Ctx.hasSameUnqualifiedType(E->getType(), SE->getType())) {
E = SE;
continue;
}
if ((E->getType()->isPointerType() ||
E->getType()->isIntegralType(Ctx)) &&
(SE->getType()->isPointerType() ||
SE->getType()->isIntegralType(Ctx)) &&
Ctx.getTypeSize(E->getType()) == Ctx.getTypeSize(SE->getType())) {
E = SE;
continue;
}
}
if (SubstNonTypeTemplateParmExpr *NTTP
= dyn_cast<SubstNonTypeTemplateParmExpr>(E)) {
E = NTTP->getReplacement();
continue;
}
return E;
}
}
bool Expr::isDefaultArgument() const {
const Expr *E = this;
if (const MaterializeTemporaryExpr *M = dyn_cast<MaterializeTemporaryExpr>(E))
E = M->GetTemporaryExpr();
while (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E))
E = ICE->getSubExprAsWritten();
return isa<CXXDefaultArgExpr>(E);
}
/// \brief Skip over any no-op casts and any temporary-binding
/// expressions.
static const Expr *skipTemporaryBindingsNoOpCastsAndParens(const Expr *E) {
if (const MaterializeTemporaryExpr *M = dyn_cast<MaterializeTemporaryExpr>(E))
E = M->GetTemporaryExpr();
while (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) {
if (ICE->getCastKind() == CK_NoOp)
E = ICE->getSubExpr();
else
break;
}
while (const CXXBindTemporaryExpr *BE = dyn_cast<CXXBindTemporaryExpr>(E))
E = BE->getSubExpr();
while (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) {
if (ICE->getCastKind() == CK_NoOp)
E = ICE->getSubExpr();
else
break;
}
return E->IgnoreParens();
}
/// isTemporaryObject - Determines if this expression produces a
/// temporary of the given class type.
bool Expr::isTemporaryObject(ASTContext &C, const CXXRecordDecl *TempTy) const {
if (!C.hasSameUnqualifiedType(getType(), C.getTypeDeclType(TempTy)))
return false;
const Expr *E = skipTemporaryBindingsNoOpCastsAndParens(this);
// Temporaries are by definition pr-values of class type.
if (!E->Classify(C).isPRValue()) {
// In this context, property reference is a message call and is pr-value.
if (!isa<ObjCPropertyRefExpr>(E))
return false;
}
// Black-list a few cases which yield pr-values of class type that don't
// refer to temporaries of that type:
// - implicit derived-to-base conversions
if (isa<ImplicitCastExpr>(E)) {
switch (cast<ImplicitCastExpr>(E)->getCastKind()) {
case CK_DerivedToBase:
case CK_UncheckedDerivedToBase:
return false;
default:
break;
}
}
// - member expressions (all)
if (isa<MemberExpr>(E))
return false;
if (const BinaryOperator *BO = dyn_cast<BinaryOperator>(E))
if (BO->isPtrMemOp())
return false;
// - opaque values (all)
if (isa<OpaqueValueExpr>(E))
return false;
return true;
}
bool Expr::isImplicitCXXThis() const {
const Expr *E = this;
// Strip away parentheses and casts we don't care about.
while (true) {
if (const ParenExpr *Paren = dyn_cast<ParenExpr>(E)) {
E = Paren->getSubExpr();
continue;
}
if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) {
if (ICE->getCastKind() == CK_NoOp ||
ICE->getCastKind() == CK_LValueToRValue ||
ICE->getCastKind() == CK_DerivedToBase ||
ICE->getCastKind() == CK_UncheckedDerivedToBase) {
E = ICE->getSubExpr();
continue;
}
}
if (const UnaryOperator* UnOp = dyn_cast<UnaryOperator>(E)) {
if (UnOp->getOpcode() == UO_Extension) {
E = UnOp->getSubExpr();
continue;
}
}
if (const MaterializeTemporaryExpr *M
= dyn_cast<MaterializeTemporaryExpr>(E)) {
E = M->GetTemporaryExpr();
continue;
}
break;
}
if (const CXXThisExpr *This = dyn_cast<CXXThisExpr>(E))
return This->isImplicit();
return false;
}
/// hasAnyTypeDependentArguments - Determines if any of the expressions
/// in Exprs is type-dependent.
bool Expr::hasAnyTypeDependentArguments(ArrayRef<Expr *> Exprs) {
for (unsigned I = 0; I < Exprs.size(); ++I)
if (Exprs[I]->isTypeDependent())
return true;
return false;
}
bool Expr::isConstantInitializer(ASTContext &Ctx, bool IsForRef,
const Expr **Culprit) const {
// This function is attempting whether an expression is an initializer
// which can be evaluated at compile-time. It very closely parallels
// ConstExprEmitter in CGExprConstant.cpp; if they don't match, it
// will lead to unexpected results. Like ConstExprEmitter, it falls back
// to isEvaluatable most of the time.
//
// If we ever capture reference-binding directly in the AST, we can
// kill the second parameter.
if (IsForRef) {
EvalResult Result;
if (EvaluateAsLValue(Result, Ctx) && !Result.HasSideEffects)
return true;
if (Culprit)
*Culprit = this;
return false;
}
switch (getStmtClass()) {
default: break;
case StringLiteralClass:
case ObjCEncodeExprClass:
return true;
case CXXTemporaryObjectExprClass:
case CXXConstructExprClass: {
const CXXConstructExpr *CE = cast<CXXConstructExpr>(this);
if (CE->getConstructor()->isTrivial() &&
CE->getConstructor()->getParent()->hasTrivialDestructor()) {
// Trivial default constructor
if (!CE->getNumArgs()) return true;
// Trivial copy constructor
assert(CE->getNumArgs() == 1 && "trivial ctor with > 1 argument");
return CE->getArg(0)->isConstantInitializer(Ctx, false, Culprit);
}
break;
}
case CompoundLiteralExprClass: {
// This handles gcc's extension that allows global initializers like
// "struct x {int x;} x = (struct x) {};".
// FIXME: This accepts other cases it shouldn't!
const Expr *Exp = cast<CompoundLiteralExpr>(this)->getInitializer();
return Exp->isConstantInitializer(Ctx, false, Culprit);
}
case DesignatedInitUpdateExprClass: {
const DesignatedInitUpdateExpr *DIUE = cast<DesignatedInitUpdateExpr>(this);
return DIUE->getBase()->isConstantInitializer(Ctx, false, Culprit) &&
DIUE->getUpdater()->isConstantInitializer(Ctx, false, Culprit);
}
case InitListExprClass: {
const InitListExpr *ILE = cast<InitListExpr>(this);
if (ILE->getType()->isArrayType()) {
unsigned numInits = ILE->getNumInits();
for (unsigned i = 0; i < numInits; i++) {
if (!ILE->getInit(i)->isConstantInitializer(Ctx, false, Culprit))
return false;
}
return true;
}
if (ILE->getType()->isRecordType()) {
unsigned ElementNo = 0;
RecordDecl *RD = ILE->getType()->getAs<RecordType>()->getDecl();
for (const auto *Field : RD->fields()) {
// If this is a union, skip all the fields that aren't being initialized.
if (RD->isUnion() && ILE->getInitializedFieldInUnion() != Field)
continue;
// Don't emit anonymous bitfields, they just affect layout.
if (Field->isUnnamedBitfield())
continue;
if (ElementNo < ILE->getNumInits()) {
const Expr *Elt = ILE->getInit(ElementNo++);
if (Field->isBitField()) {
// Bitfields have to evaluate to an integer.
llvm::APSInt ResultTmp;
if (!Elt->EvaluateAsInt(ResultTmp, Ctx)) {
if (Culprit)
*Culprit = Elt;
return false;
}
} else {
bool RefType = Field->getType()->isReferenceType();
if (!Elt->isConstantInitializer(Ctx, RefType, Culprit))
return false;
}
}
}
return true;
}
break;
}
case ImplicitValueInitExprClass:
case NoInitExprClass:
return true;
case ParenExprClass:
return cast<ParenExpr>(this)->getSubExpr()
->isConstantInitializer(Ctx, IsForRef, Culprit);
case GenericSelectionExprClass:
return cast<GenericSelectionExpr>(this)->getResultExpr()
->isConstantInitializer(Ctx, IsForRef, Culprit);
case ChooseExprClass:
if (cast<ChooseExpr>(this)->isConditionDependent()) {
if (Culprit)
*Culprit = this;
return false;
}
return cast<ChooseExpr>(this)->getChosenSubExpr()
->isConstantInitializer(Ctx, IsForRef, Culprit);
case UnaryOperatorClass: {
const UnaryOperator* Exp = cast<UnaryOperator>(this);
if (Exp->getOpcode() == UO_Extension)
return Exp->getSubExpr()->isConstantInitializer(Ctx, false, Culprit);
break;
}
case CXXFunctionalCastExprClass:
case CXXStaticCastExprClass:
case ImplicitCastExprClass:
case CStyleCastExprClass:
case ObjCBridgedCastExprClass:
case CXXDynamicCastExprClass:
case CXXReinterpretCastExprClass:
case CXXConstCastExprClass: {
const CastExpr *CE = cast<CastExpr>(this);
// Handle misc casts we want to ignore.
if (CE->getCastKind() == CK_NoOp ||
CE->getCastKind() == CK_LValueToRValue ||
CE->getCastKind() == CK_ToUnion ||
CE->getCastKind() == CK_ConstructorConversion ||
CE->getCastKind() == CK_NonAtomicToAtomic ||
CE->getCastKind() == CK_AtomicToNonAtomic)
return CE->getSubExpr()->isConstantInitializer(Ctx, false, Culprit);
break;
}
case MaterializeTemporaryExprClass:
return cast<MaterializeTemporaryExpr>(this)->GetTemporaryExpr()
->isConstantInitializer(Ctx, false, Culprit);
case SubstNonTypeTemplateParmExprClass:
return cast<SubstNonTypeTemplateParmExpr>(this)->getReplacement()
->isConstantInitializer(Ctx, false, Culprit);
case CXXDefaultArgExprClass:
return cast<CXXDefaultArgExpr>(this)->getExpr()
->isConstantInitializer(Ctx, false, Culprit);
case CXXDefaultInitExprClass:
return cast<CXXDefaultInitExpr>(this)->getExpr()
->isConstantInitializer(Ctx, false, Culprit);
}
if (isEvaluatable(Ctx))
return true;
if (Culprit)
*Culprit = this;
return false;
}
namespace {
/// \brief Look for any side effects within a Stmt.
class SideEffectFinder : public ConstEvaluatedExprVisitor<SideEffectFinder> {
typedef ConstEvaluatedExprVisitor<SideEffectFinder> Inherited;
const bool IncludePossibleEffects;
bool HasSideEffects;
public:
explicit SideEffectFinder(const ASTContext &Context, bool IncludePossible)
: Inherited(Context),
IncludePossibleEffects(IncludePossible), HasSideEffects(false) { }
bool hasSideEffects() const { return HasSideEffects; }
void VisitExpr(const Expr *E) {
if (!HasSideEffects &&
E->HasSideEffects(Context, IncludePossibleEffects))
HasSideEffects = true;
}
};
}
bool Expr::HasSideEffects(const ASTContext &Ctx,
bool IncludePossibleEffects) const {
// In circumstances where we care about definite side effects instead of
// potential side effects, we want to ignore expressions that are part of a
// macro expansion as a potential side effect.
if (!IncludePossibleEffects && getExprLoc().isMacroID())
return false;
if (isInstantiationDependent())
return IncludePossibleEffects;
switch (getStmtClass()) {
case NoStmtClass:
#define ABSTRACT_STMT(Type)
#define STMT(Type, Base) case Type##Class:
#define EXPR(Type, Base)
#include "clang/AST/StmtNodes.inc"
llvm_unreachable("unexpected Expr kind");
case DependentScopeDeclRefExprClass:
case CXXUnresolvedConstructExprClass:
case CXXDependentScopeMemberExprClass:
case UnresolvedLookupExprClass:
case UnresolvedMemberExprClass:
case PackExpansionExprClass:
case SubstNonTypeTemplateParmPackExprClass:
case FunctionParmPackExprClass:
case TypoExprClass:
case CXXFoldExprClass:
llvm_unreachable("shouldn't see dependent / unresolved nodes here");
case DeclRefExprClass:
case ObjCIvarRefExprClass:
case PredefinedExprClass:
case IntegerLiteralClass:
case FloatingLiteralClass:
case ImaginaryLiteralClass:
case StringLiteralClass:
case CharacterLiteralClass:
case OffsetOfExprClass:
case ImplicitValueInitExprClass:
case UnaryExprOrTypeTraitExprClass:
case AddrLabelExprClass:
case GNUNullExprClass:
case NoInitExprClass:
case CXXBoolLiteralExprClass:
case CXXNullPtrLiteralExprClass:
case CXXThisExprClass:
case CXXScalarValueInitExprClass:
case TypeTraitExprClass:
case ArrayTypeTraitExprClass:
case ExpressionTraitExprClass:
case CXXNoexceptExprClass:
case SizeOfPackExprClass:
case ObjCStringLiteralClass:
case ObjCEncodeExprClass:
case ObjCBoolLiteralExprClass:
case CXXUuidofExprClass:
case OpaqueValueExprClass:
// These never have a side-effect.
return false;
case CallExprClass:
case CXXOperatorCallExprClass:
case CXXMemberCallExprClass:
case CUDAKernelCallExprClass:
case UserDefinedLiteralClass: {
// We don't know a call definitely has side effects, except for calls
// to pure/const functions that definitely don't.
// If the call itself is considered side-effect free, check the operands.
const Decl *FD = cast<CallExpr>(this)->getCalleeDecl();
bool IsPure = FD && (FD->hasAttr<ConstAttr>() || FD->hasAttr<PureAttr>());
if (IsPure || !IncludePossibleEffects)
break;
return true;
}
case BlockExprClass:
case CXXBindTemporaryExprClass:
if (!IncludePossibleEffects)
break;
return true;
case MSPropertyRefExprClass:
case CompoundAssignOperatorClass:
case VAArgExprClass:
case AtomicExprClass:
case CXXThrowExprClass:
case CXXNewExprClass:
case CXXDeleteExprClass:
case ExprWithCleanupsClass:
case CoawaitExprClass:
case CoyieldExprClass:
// These always have a side-effect.
return true;
case StmtExprClass: {
// StmtExprs have a side-effect if any substatement does.
SideEffectFinder Finder(Ctx, IncludePossibleEffects);
Finder.Visit(cast<StmtExpr>(this)->getSubStmt());
return Finder.hasSideEffects();
}
case ParenExprClass:
case ArraySubscriptExprClass:
case OMPArraySectionExprClass:
case MemberExprClass:
case ConditionalOperatorClass:
case BinaryConditionalOperatorClass:
case CompoundLiteralExprClass:
case ExtVectorElementExprClass:
case DesignatedInitExprClass:
case DesignatedInitUpdateExprClass:
case ParenListExprClass:
case CXXPseudoDestructorExprClass:
case CXXStdInitializerListExprClass:
case SubstNonTypeTemplateParmExprClass:
case MaterializeTemporaryExprClass:
case ShuffleVectorExprClass:
case ConvertVectorExprClass:
case AsTypeExprClass:
// These have a side-effect if any subexpression does.
break;
case UnaryOperatorClass:
if (cast<UnaryOperator>(this)->isIncrementDecrementOp())
return true;
break;
case BinaryOperatorClass:
if (cast<BinaryOperator>(this)->isAssignmentOp())
return true;
break;
case InitListExprClass:
// FIXME: The children for an InitListExpr doesn't include the array filler.
if (const Expr *E = cast<InitListExpr>(this)->getArrayFiller())
if (E->HasSideEffects(Ctx, IncludePossibleEffects))
return true;
break;
case GenericSelectionExprClass:
return cast<GenericSelectionExpr>(this)->getResultExpr()->
HasSideEffects(Ctx, IncludePossibleEffects);
case ChooseExprClass:
return cast<ChooseExpr>(this)->getChosenSubExpr()->HasSideEffects(
Ctx, IncludePossibleEffects);
case CXXDefaultArgExprClass:
return cast<CXXDefaultArgExpr>(this)->getExpr()->HasSideEffects(
Ctx, IncludePossibleEffects);
case CXXDefaultInitExprClass: {
const FieldDecl *FD = cast<CXXDefaultInitExpr>(this)->getField();
if (const Expr *E = FD->getInClassInitializer())
return E->HasSideEffects(Ctx, IncludePossibleEffects);
// If we've not yet parsed the initializer, assume it has side-effects.
return true;
}
case CXXDynamicCastExprClass: {
// A dynamic_cast expression has side-effects if it can throw.
const CXXDynamicCastExpr *DCE = cast<CXXDynamicCastExpr>(this);
if (DCE->getTypeAsWritten()->isReferenceType() &&
DCE->getCastKind() == CK_Dynamic)
return true;
} // Fall through.
case ImplicitCastExprClass:
case CStyleCastExprClass:
case CXXStaticCastExprClass:
case CXXReinterpretCastExprClass:
case CXXConstCastExprClass:
case CXXFunctionalCastExprClass: {
// While volatile reads are side-effecting in both C and C++, we treat them
// as having possible (not definite) side-effects. This allows idiomatic
// code to behave without warning, such as sizeof(*v) for a volatile-
// qualified pointer.
if (!IncludePossibleEffects)
break;
const CastExpr *CE = cast<CastExpr>(this);
if (CE->getCastKind() == CK_LValueToRValue &&
CE->getSubExpr()->getType().isVolatileQualified())
return true;
break;
}
case CXXTypeidExprClass:
// typeid might throw if its subexpression is potentially-evaluated, so has
// side-effects in that case whether or not its subexpression does.
return cast<CXXTypeidExpr>(this)->isPotentiallyEvaluated();
case CXXConstructExprClass:
case CXXTemporaryObjectExprClass: {
const CXXConstructExpr *CE = cast<CXXConstructExpr>(this);
if (!CE->getConstructor()->isTrivial() && IncludePossibleEffects)
return true;
// A trivial constructor does not add any side-effects of its own. Just look
// at its arguments.
break;
}
case LambdaExprClass: {
const LambdaExpr *LE = cast<LambdaExpr>(this);
for (LambdaExpr::capture_iterator I = LE->capture_begin(),
E = LE->capture_end(); I != E; ++I)
if (I->getCaptureKind() == LCK_ByCopy)
// FIXME: Only has a side-effect if the variable is volatile or if
// the copy would invoke a non-trivial copy constructor.
return true;
return false;
}
case PseudoObjectExprClass: {
// Only look for side-effects in the semantic form, and look past
// OpaqueValueExpr bindings in that form.
const PseudoObjectExpr *PO = cast<PseudoObjectExpr>(this);
for (PseudoObjectExpr::const_semantics_iterator I = PO->semantics_begin(),
E = PO->semantics_end();
I != E; ++I) {
const Expr *Subexpr = *I;
if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(Subexpr))
Subexpr = OVE->getSourceExpr();
if (Subexpr->HasSideEffects(Ctx, IncludePossibleEffects))
return true;
}
return false;
}
case ObjCBoxedExprClass:
case ObjCArrayLiteralClass:
case ObjCDictionaryLiteralClass:
case ObjCSelectorExprClass:
case ObjCProtocolExprClass:
case ObjCIsaExprClass:
case ObjCIndirectCopyRestoreExprClass:
case ObjCSubscriptRefExprClass:
case ObjCBridgedCastExprClass:
case ObjCMessageExprClass:
case ObjCPropertyRefExprClass:
// FIXME: Classify these cases better.
if (IncludePossibleEffects)
return true;
break;
}
// Recurse to children.
for (const Stmt *SubStmt : children())
if (SubStmt &&
cast<Expr>(SubStmt)->HasSideEffects(Ctx, IncludePossibleEffects))
return true;
return false;
}
namespace {
/// \brief Look for a call to a non-trivial function within an expression.
class NonTrivialCallFinder : public ConstEvaluatedExprVisitor<NonTrivialCallFinder>
{
typedef ConstEvaluatedExprVisitor<NonTrivialCallFinder> Inherited;
bool NonTrivial;
public:
explicit NonTrivialCallFinder(const ASTContext &Context)
: Inherited(Context), NonTrivial(false) { }
bool hasNonTrivialCall() const { return NonTrivial; }
void VisitCallExpr(const CallExpr *E) {
if (const CXXMethodDecl *Method
= dyn_cast_or_null<const CXXMethodDecl>(E->getCalleeDecl())) {
if (Method->isTrivial()) {
// Recurse to children of the call.
Inherited::VisitStmt(E);
return;
}
}
NonTrivial = true;
}
void VisitCXXConstructExpr(const CXXConstructExpr *E) {
if (E->getConstructor()->isTrivial()) {
// Recurse to children of the call.
Inherited::VisitStmt(E);
return;
}
NonTrivial = true;
}
void VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *E) {
if (E->getTemporary()->getDestructor()->isTrivial()) {
Inherited::VisitStmt(E);
return;
}
NonTrivial = true;
}
};
}
bool Expr::hasNonTrivialCall(const ASTContext &Ctx) const {
NonTrivialCallFinder Finder(Ctx);
Finder.Visit(this);
return Finder.hasNonTrivialCall();
}
/// isNullPointerConstant - C99 6.3.2.3p3 - Return whether this is a null
/// pointer constant or not, as well as the specific kind of constant detected.
/// Null pointer constants can be integer constant expressions with the
/// value zero, casts of zero to void*, nullptr (C++0X), or __null
/// (a GNU extension).
Expr::NullPointerConstantKind
Expr::isNullPointerConstant(ASTContext &Ctx,
NullPointerConstantValueDependence NPC) const {
if (isValueDependent() &&
(!Ctx.getLangOpts().CPlusPlus11 || Ctx.getLangOpts().MSVCCompat)) {
switch (NPC) {
case NPC_NeverValueDependent:
llvm_unreachable("Unexpected value dependent expression!");
case NPC_ValueDependentIsNull:
if (isTypeDependent() || getType()->isIntegralType(Ctx))
return NPCK_ZeroExpression;
else
return NPCK_NotNull;
case NPC_ValueDependentIsNotNull:
return NPCK_NotNull;
}
}
// Strip off a cast to void*, if it exists. Except in C++.
if (const ExplicitCastExpr *CE = dyn_cast<ExplicitCastExpr>(this)) {
if (!Ctx.getLangOpts().CPlusPlus) {
// Check that it is a cast to void*.
if (const PointerType *PT = CE->getType()->getAs<PointerType>()) {
QualType Pointee = PT->getPointeeType();
if (!Pointee.hasQualifiers() &&
Pointee->isVoidType() && // to void*
CE->getSubExpr()->getType()->isIntegerType()) // from int.
return CE->getSubExpr()->isNullPointerConstant(Ctx, NPC);
}
}
} else if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(this)) {
// Ignore the ImplicitCastExpr type entirely.
return ICE->getSubExpr()->isNullPointerConstant(Ctx, NPC);
} else if (const ParenExpr *PE = dyn_cast<ParenExpr>(this)) {
// Accept ((void*)0) as a null pointer constant, as many other
// implementations do.
return PE->getSubExpr()->isNullPointerConstant(Ctx, NPC);
} else if (const GenericSelectionExpr *GE =
dyn_cast<GenericSelectionExpr>(this)) {
if (GE->isResultDependent())
return NPCK_NotNull;
return GE->getResultExpr()->isNullPointerConstant(Ctx, NPC);
} else if (const ChooseExpr *CE = dyn_cast<ChooseExpr>(this)) {
if (CE->isConditionDependent())
return NPCK_NotNull;
return CE->getChosenSubExpr()->isNullPointerConstant(Ctx, NPC);
} else if (const CXXDefaultArgExpr *DefaultArg
= dyn_cast<CXXDefaultArgExpr>(this)) {
// See through default argument expressions.
return DefaultArg->getExpr()->isNullPointerConstant(Ctx, NPC);
} else if (const CXXDefaultInitExpr *DefaultInit
= dyn_cast<CXXDefaultInitExpr>(this)) {
// See through default initializer expressions.
return DefaultInit->getExpr()->isNullPointerConstant(Ctx, NPC);
} else if (isa<GNUNullExpr>(this)) {
// The GNU __null extension is always a null pointer constant.
return NPCK_GNUNull;
} else if (const MaterializeTemporaryExpr *M
= dyn_cast<MaterializeTemporaryExpr>(this)) {
return M->GetTemporaryExpr()->isNullPointerConstant(Ctx, NPC);
} else if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(this)) {
if (const Expr *Source = OVE->getSourceExpr())
return Source->isNullPointerConstant(Ctx, NPC);
}
// C++11 nullptr_t is always a null pointer constant.
if (getType()->isNullPtrType())
return NPCK_CXX11_nullptr;
if (const RecordType *UT = getType()->getAsUnionType())
if (!Ctx.getLangOpts().CPlusPlus11 &&
UT && UT->getDecl()->hasAttr<TransparentUnionAttr>())
if (const CompoundLiteralExpr *CLE = dyn_cast<CompoundLiteralExpr>(this)){
const Expr *InitExpr = CLE->getInitializer();
if (const InitListExpr *ILE = dyn_cast<InitListExpr>(InitExpr))
return ILE->getInit(0)->isNullPointerConstant(Ctx, NPC);
}
// This expression must be an integer type.
if (!getType()->isIntegerType() ||
(Ctx.getLangOpts().CPlusPlus && getType()->isEnumeralType()))
return NPCK_NotNull;
if (Ctx.getLangOpts().CPlusPlus11) {
// C++11 [conv.ptr]p1: A null pointer constant is an integer literal with
// value zero or a prvalue of type std::nullptr_t.
// Microsoft mode permits C++98 rules reflecting MSVC behavior.
const IntegerLiteral *Lit = dyn_cast<IntegerLiteral>(this);
if (Lit && !Lit->getValue())
return NPCK_ZeroLiteral;
else if (!Ctx.getLangOpts().MSVCCompat || !isCXX98IntegralConstantExpr(Ctx))
return NPCK_NotNull;
} else {
// If we have an integer constant expression, we need to *evaluate* it and
// test for the value 0.
if (!isIntegerConstantExpr(Ctx))
return NPCK_NotNull;
}
if (EvaluateKnownConstInt(Ctx) != 0)
return NPCK_NotNull;
if (isa<IntegerLiteral>(this))
return NPCK_ZeroLiteral;
return NPCK_ZeroExpression;
}
/// \brief If this expression is an l-value for an Objective C
/// property, find the underlying property reference expression.
const ObjCPropertyRefExpr *Expr::getObjCProperty() const {
const Expr *E = this;
while (true) {
assert((E->getValueKind() == VK_LValue &&
E->getObjectKind() == OK_ObjCProperty) &&
"expression is not a property reference");
E = E->IgnoreParenCasts();
if (const BinaryOperator *BO = dyn_cast<BinaryOperator>(E)) {
if (BO->getOpcode() == BO_Comma) {
E = BO->getRHS();
continue;
}
}
break;
}
return cast<ObjCPropertyRefExpr>(E);
}
bool Expr::isObjCSelfExpr() const {
const Expr *E = IgnoreParenImpCasts();
const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E);
if (!DRE)
return false;
const ImplicitParamDecl *Param = dyn_cast<ImplicitParamDecl>(DRE->getDecl());
if (!Param)
return false;
const ObjCMethodDecl *M = dyn_cast<ObjCMethodDecl>(Param->getDeclContext());
if (!M)
return false;
return M->getSelfDecl() == Param;
}
FieldDecl *Expr::getSourceBitField() {
Expr *E = this->IgnoreParens();
while (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) {
if (ICE->getCastKind() == CK_LValueToRValue ||
(ICE->getValueKind() != VK_RValue && ICE->getCastKind() == CK_NoOp))
E = ICE->getSubExpr()->IgnoreParens();
else
break;
}
if (MemberExpr *MemRef = dyn_cast<MemberExpr>(E))
if (FieldDecl *Field = dyn_cast<FieldDecl>(MemRef->getMemberDecl()))
if (Field->isBitField())
return Field;
if (ObjCIvarRefExpr *IvarRef = dyn_cast<ObjCIvarRefExpr>(E))
if (FieldDecl *Ivar = dyn_cast<FieldDecl>(IvarRef->getDecl()))
if (Ivar->isBitField())
return Ivar;
if (DeclRefExpr *DeclRef = dyn_cast<DeclRefExpr>(E))
if (FieldDecl *Field = dyn_cast<FieldDecl>(DeclRef->getDecl()))
if (Field->isBitField())
return Field;
if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(E)) {
if (BinOp->isAssignmentOp() && BinOp->getLHS())
return BinOp->getLHS()->getSourceBitField();
if (BinOp->getOpcode() == BO_Comma && BinOp->getRHS())
return BinOp->getRHS()->getSourceBitField();
}
if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(E))
if (UnOp->isPrefix() && UnOp->isIncrementDecrementOp())
return UnOp->getSubExpr()->getSourceBitField();
return nullptr;
}
bool Expr::refersToVectorElement() const {
const Expr *E = this->IgnoreParens();
while (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) {
if (ICE->getValueKind() != VK_RValue &&
ICE->getCastKind() == CK_NoOp)
E = ICE->getSubExpr()->IgnoreParens();
else
break;
}
if (const ArraySubscriptExpr *ASE = dyn_cast<ArraySubscriptExpr>(E))
return ASE->getBase()->getType()->isVectorType();
if (isa<ExtVectorElementExpr>(E))
return true;
return false;
}
bool Expr::refersToGlobalRegisterVar() const {
const Expr *E = this->IgnoreParenImpCasts();
if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
if (const auto *VD = dyn_cast<VarDecl>(DRE->getDecl()))
if (VD->getStorageClass() == SC_Register &&
VD->hasAttr<AsmLabelAttr>() && !VD->isLocalVarDecl())
return true;
return false;
}
/// isArrow - Return true if the base expression is a pointer to vector,
/// return false if the base expression is a vector.
bool ExtVectorElementExpr::isArrow() const {
return getBase()->getType()->isPointerType();
}
unsigned ExtVectorElementExpr::getNumElements() const {
if (const VectorType *VT = getType()->getAs<VectorType>())
return VT->getNumElements();
return 1;
}
/// containsDuplicateElements - Return true if any element access is repeated.
bool ExtVectorElementExpr::containsDuplicateElements() const {
// FIXME: Refactor this code to an accessor on the AST node which returns the
// "type" of component access, and share with code below and in Sema.
StringRef Comp = Accessor->getName();
// Halving swizzles do not contain duplicate elements.
if (Comp == "hi" || Comp == "lo" || Comp == "even" || Comp == "odd")
return false;
// Advance past s-char prefix on hex swizzles.
if (Comp[0] == 's' || Comp[0] == 'S')
Comp = Comp.substr(1);
for (unsigned i = 0, e = Comp.size(); i != e; ++i)
if (Comp.substr(i + 1).find(Comp[i]) != StringRef::npos)
return true;
return false;
}
/// getEncodedElementAccess - We encode the fields as a llvm ConstantArray.
void ExtVectorElementExpr::getEncodedElementAccess(
SmallVectorImpl<uint32_t> &Elts) const {
StringRef Comp = Accessor->getName();
if (Comp[0] == 's' || Comp[0] == 'S')
Comp = Comp.substr(1);
bool isHi = Comp == "hi";
bool isLo = Comp == "lo";
bool isEven = Comp == "even";
bool isOdd = Comp == "odd";
for (unsigned i = 0, e = getNumElements(); i != e; ++i) {
uint64_t Index;
if (isHi)
Index = e + i;
else if (isLo)
Index = i;
else if (isEven)
Index = 2 * i;
else if (isOdd)
Index = 2 * i + 1;
else
Index = ExtVectorType::getAccessorIdx(Comp[i]);
Elts.push_back(Index);
}
}
ShuffleVectorExpr::ShuffleVectorExpr(const ASTContext &C, ArrayRef<Expr*> args,
QualType Type, SourceLocation BLoc,
SourceLocation RP)
: Expr(ShuffleVectorExprClass, Type, VK_RValue, OK_Ordinary,
Type->isDependentType(), Type->isDependentType(),
Type->isInstantiationDependentType(),
Type->containsUnexpandedParameterPack()),
BuiltinLoc(BLoc), RParenLoc(RP), NumExprs(args.size())
{
SubExprs = new (C) Stmt*[args.size()];
for (unsigned i = 0; i != args.size(); i++) {
if (args[i]->isTypeDependent())
ExprBits.TypeDependent = true;
if (args[i]->isValueDependent())
ExprBits.ValueDependent = true;
if (args[i]->isInstantiationDependent())
ExprBits.InstantiationDependent = true;
if (args[i]->containsUnexpandedParameterPack())
ExprBits.ContainsUnexpandedParameterPack = true;
SubExprs[i] = args[i];
}
}
void ShuffleVectorExpr::setExprs(const ASTContext &C, ArrayRef<Expr *> Exprs) {
if (SubExprs) C.Deallocate(SubExprs);
this->NumExprs = Exprs.size();
SubExprs = new (C) Stmt*[NumExprs];
memcpy(SubExprs, Exprs.data(), sizeof(Expr *) * Exprs.size());
}
GenericSelectionExpr::GenericSelectionExpr(const ASTContext &Context,
SourceLocation GenericLoc, Expr *ControllingExpr,
ArrayRef<TypeSourceInfo*> AssocTypes,
ArrayRef<Expr*> AssocExprs,
SourceLocation DefaultLoc,
SourceLocation RParenLoc,
bool ContainsUnexpandedParameterPack,
unsigned ResultIndex)
: Expr(GenericSelectionExprClass,
AssocExprs[ResultIndex]->getType(),
AssocExprs[ResultIndex]->getValueKind(),
AssocExprs[ResultIndex]->getObjectKind(),
AssocExprs[ResultIndex]->isTypeDependent(),
AssocExprs[ResultIndex]->isValueDependent(),
AssocExprs[ResultIndex]->isInstantiationDependent(),
ContainsUnexpandedParameterPack),
AssocTypes(new (Context) TypeSourceInfo*[AssocTypes.size()]),
SubExprs(new (Context) Stmt*[END_EXPR+AssocExprs.size()]),
NumAssocs(AssocExprs.size()), ResultIndex(ResultIndex),
GenericLoc(GenericLoc), DefaultLoc(DefaultLoc), RParenLoc(RParenLoc) {
SubExprs[CONTROLLING] = ControllingExpr;
assert(AssocTypes.size() == AssocExprs.size());
std::copy(AssocTypes.begin(), AssocTypes.end(), this->AssocTypes);
std::copy(AssocExprs.begin(), AssocExprs.end(), SubExprs+END_EXPR);
}
GenericSelectionExpr::GenericSelectionExpr(const ASTContext &Context,
SourceLocation GenericLoc, Expr *ControllingExpr,
ArrayRef<TypeSourceInfo*> AssocTypes,
ArrayRef<Expr*> AssocExprs,
SourceLocation DefaultLoc,
SourceLocation RParenLoc,
bool ContainsUnexpandedParameterPack)
: Expr(GenericSelectionExprClass,
Context.DependentTy,
VK_RValue,
OK_Ordinary,
/*isTypeDependent=*/true,
/*isValueDependent=*/true,
/*isInstantiationDependent=*/true,
ContainsUnexpandedParameterPack),
AssocTypes(new (Context) TypeSourceInfo*[AssocTypes.size()]),
SubExprs(new (Context) Stmt*[END_EXPR+AssocExprs.size()]),
NumAssocs(AssocExprs.size()), ResultIndex(-1U), GenericLoc(GenericLoc),
DefaultLoc(DefaultLoc), RParenLoc(RParenLoc) {
SubExprs[CONTROLLING] = ControllingExpr;
assert(AssocTypes.size() == AssocExprs.size());
std::copy(AssocTypes.begin(), AssocTypes.end(), this->AssocTypes);
std::copy(AssocExprs.begin(), AssocExprs.end(), SubExprs+END_EXPR);
}
//===----------------------------------------------------------------------===//
// DesignatedInitExpr
//===----------------------------------------------------------------------===//
IdentifierInfo *DesignatedInitExpr::Designator::getFieldName() const {
assert(Kind == FieldDesignator && "Only valid on a field designator");
if (Field.NameOrField & 0x01)
return reinterpret_cast<IdentifierInfo *>(Field.NameOrField&~0x01);
else
return getField()->getIdentifier();
}
DesignatedInitExpr::DesignatedInitExpr(const ASTContext &C, QualType Ty,
unsigned NumDesignators,
const Designator *Designators,
SourceLocation EqualOrColonLoc,
bool GNUSyntax,
ArrayRef<Expr*> IndexExprs,
Expr *Init)
: Expr(DesignatedInitExprClass, Ty,
Init->getValueKind(), Init->getObjectKind(),
Init->isTypeDependent(), Init->isValueDependent(),
Init->isInstantiationDependent(),
Init->containsUnexpandedParameterPack()),
EqualOrColonLoc(EqualOrColonLoc), GNUSyntax(GNUSyntax),
NumDesignators(NumDesignators), NumSubExprs(IndexExprs.size() + 1) {
this->Designators = new (C) Designator[NumDesignators];
// Record the initializer itself.
child_iterator Child = child_begin();
*Child++ = Init;
// Copy the designators and their subexpressions, computing
// value-dependence along the way.
unsigned IndexIdx = 0;
for (unsigned I = 0; I != NumDesignators; ++I) {
this->Designators[I] = Designators[I];
if (this->Designators[I].isArrayDesignator()) {
// Compute type- and value-dependence.
Expr *Index = IndexExprs[IndexIdx];
if (Index->isTypeDependent() || Index->isValueDependent())
ExprBits.TypeDependent = ExprBits.ValueDependent = true;
if (Index->isInstantiationDependent())
ExprBits.InstantiationDependent = true;
// Propagate unexpanded parameter packs.
if (Index->containsUnexpandedParameterPack())
ExprBits.ContainsUnexpandedParameterPack = true;
// Copy the index expressions into permanent storage.
*Child++ = IndexExprs[IndexIdx++];
} else if (this->Designators[I].isArrayRangeDesignator()) {
// Compute type- and value-dependence.
Expr *Start = IndexExprs[IndexIdx];
Expr *End = IndexExprs[IndexIdx + 1];
if (Start->isTypeDependent() || Start->isValueDependent() ||
End->isTypeDependent() || End->isValueDependent()) {
ExprBits.TypeDependent = ExprBits.ValueDependent = true;
ExprBits.InstantiationDependent = true;
} else if (Start->isInstantiationDependent() ||
End->isInstantiationDependent()) {
ExprBits.InstantiationDependent = true;
}
// Propagate unexpanded parameter packs.
if (Start->containsUnexpandedParameterPack() ||
End->containsUnexpandedParameterPack())
ExprBits.ContainsUnexpandedParameterPack = true;
// Copy the start/end expressions into permanent storage.
*Child++ = IndexExprs[IndexIdx++];
*Child++ = IndexExprs[IndexIdx++];
}
}
assert(IndexIdx == IndexExprs.size() && "Wrong number of index expressions");
}
DesignatedInitExpr *
DesignatedInitExpr::Create(const ASTContext &C, Designator *Designators,
unsigned NumDesignators,
ArrayRef<Expr*> IndexExprs,
SourceLocation ColonOrEqualLoc,
bool UsesColonSyntax, Expr *Init) {
void *Mem = C.Allocate(sizeof(DesignatedInitExpr) +
sizeof(Stmt *) * (IndexExprs.size() + 1),
llvm::alignOf<DesignatedInitExpr>());
return new (Mem) DesignatedInitExpr(C, C.VoidTy, NumDesignators, Designators,
ColonOrEqualLoc, UsesColonSyntax,
IndexExprs, Init);
}
DesignatedInitExpr *DesignatedInitExpr::CreateEmpty(const ASTContext &C,
unsigned NumIndexExprs) {
void *Mem = C.Allocate(sizeof(DesignatedInitExpr) +
sizeof(Stmt *) * (NumIndexExprs + 1), 8);
return new (Mem) DesignatedInitExpr(NumIndexExprs + 1);
}
void DesignatedInitExpr::setDesignators(const ASTContext &C,
const Designator *Desigs,
unsigned NumDesigs) {
Designators = new (C) Designator[NumDesigs];
NumDesignators = NumDesigs;
for (unsigned I = 0; I != NumDesigs; ++I)
Designators[I] = Desigs[I];
}
SourceRange DesignatedInitExpr::getDesignatorsSourceRange() const {
DesignatedInitExpr *DIE = const_cast<DesignatedInitExpr*>(this);
if (size() == 1)
return DIE->getDesignator(0)->getSourceRange();
return SourceRange(DIE->getDesignator(0)->getLocStart(),
DIE->getDesignator(size()-1)->getLocEnd());
}
SourceLocation DesignatedInitExpr::getLocStart() const {
SourceLocation StartLoc;
Designator &First =
*const_cast<DesignatedInitExpr*>(this)->designators_begin();
if (First.isFieldDesignator()) {
if (GNUSyntax)
StartLoc = SourceLocation::getFromRawEncoding(First.Field.FieldLoc);
else
StartLoc = SourceLocation::getFromRawEncoding(First.Field.DotLoc);
} else
StartLoc =
SourceLocation::getFromRawEncoding(First.ArrayOrRange.LBracketLoc);
return StartLoc;
}
SourceLocation DesignatedInitExpr::getLocEnd() const {
return getInit()->getLocEnd();
}
Expr *DesignatedInitExpr::getArrayIndex(const Designator& D) const {
assert(D.Kind == Designator::ArrayDesignator && "Requires array designator");
Stmt *const *SubExprs = reinterpret_cast<Stmt *const *>(this + 1);
return cast<Expr>(*(SubExprs + D.ArrayOrRange.Index + 1));
}
Expr *DesignatedInitExpr::getArrayRangeStart(const Designator &D) const {
assert(D.Kind == Designator::ArrayRangeDesignator &&
"Requires array range designator");
Stmt *const *SubExprs = reinterpret_cast<Stmt *const *>(this + 1);
return cast<Expr>(*(SubExprs + D.ArrayOrRange.Index + 1));
}
Expr *DesignatedInitExpr::getArrayRangeEnd(const Designator &D) const {
assert(D.Kind == Designator::ArrayRangeDesignator &&
"Requires array range designator");
Stmt *const *SubExprs = reinterpret_cast<Stmt *const *>(this + 1);
return cast<Expr>(*(SubExprs + D.ArrayOrRange.Index + 2));
}
/// \brief Replaces the designator at index @p Idx with the series
/// of designators in [First, Last).
void DesignatedInitExpr::ExpandDesignator(const ASTContext &C, unsigned Idx,
const Designator *First,
const Designator *Last) {
unsigned NumNewDesignators = Last - First;
if (NumNewDesignators == 0) {
std::copy_backward(Designators + Idx + 1,
Designators + NumDesignators,
Designators + Idx);
--NumNewDesignators;
return;
} else if (NumNewDesignators == 1) {
Designators[Idx] = *First;
return;
}
Designator *NewDesignators
= new (C) Designator[NumDesignators - 1 + NumNewDesignators];
std::copy(Designators, Designators + Idx, NewDesignators);
std::copy(First, Last, NewDesignators + Idx);
std::copy(Designators + Idx + 1, Designators + NumDesignators,
NewDesignators + Idx + NumNewDesignators);
Designators = NewDesignators;
NumDesignators = NumDesignators - 1 + NumNewDesignators;
}
DesignatedInitUpdateExpr::DesignatedInitUpdateExpr(const ASTContext &C,
SourceLocation lBraceLoc, Expr *baseExpr, SourceLocation rBraceLoc)
: Expr(DesignatedInitUpdateExprClass, baseExpr->getType(), VK_RValue,
OK_Ordinary, false, false, false, false) {
BaseAndUpdaterExprs[0] = baseExpr;
InitListExpr *ILE = new (C) InitListExpr(C, lBraceLoc, None, rBraceLoc);
ILE->setType(baseExpr->getType());
BaseAndUpdaterExprs[1] = ILE;
}
SourceLocation DesignatedInitUpdateExpr::getLocStart() const {
return getBase()->getLocStart();
}
SourceLocation DesignatedInitUpdateExpr::getLocEnd() const {
return getBase()->getLocEnd();
}
ParenListExpr::ParenListExpr(const ASTContext& C, SourceLocation lparenloc,
ArrayRef<Expr*> exprs,
SourceLocation rparenloc)
: Expr(ParenListExprClass, QualType(), VK_RValue, OK_Ordinary,
false, false, false, false),
NumExprs(exprs.size()), LParenLoc(lparenloc), RParenLoc(rparenloc) {
Exprs = new (C) Stmt*[exprs.size()];
for (unsigned i = 0; i != exprs.size(); ++i) {
if (exprs[i]->isTypeDependent())
ExprBits.TypeDependent = true;
if (exprs[i]->isValueDependent())
ExprBits.ValueDependent = true;
if (exprs[i]->isInstantiationDependent())
ExprBits.InstantiationDependent = true;
if (exprs[i]->containsUnexpandedParameterPack())
ExprBits.ContainsUnexpandedParameterPack = true;
Exprs[i] = exprs[i];
}
}
const OpaqueValueExpr *OpaqueValueExpr::findInCopyConstruct(const Expr *e) {
if (const ExprWithCleanups *ewc = dyn_cast<ExprWithCleanups>(e))
e = ewc->getSubExpr();
if (const MaterializeTemporaryExpr *m = dyn_cast<MaterializeTemporaryExpr>(e))
e = m->GetTemporaryExpr();
e = cast<CXXConstructExpr>(e)->getArg(0);
while (const ImplicitCastExpr *ice = dyn_cast<ImplicitCastExpr>(e))
e = ice->getSubExpr();
return cast<OpaqueValueExpr>(e);
}
PseudoObjectExpr *PseudoObjectExpr::Create(const ASTContext &Context,
EmptyShell sh,
unsigned numSemanticExprs) {
void *buffer = Context.Allocate(sizeof(PseudoObjectExpr) +
(1 + numSemanticExprs) * sizeof(Expr*),
llvm::alignOf<PseudoObjectExpr>());
return new(buffer) PseudoObjectExpr(sh, numSemanticExprs);
}
PseudoObjectExpr::PseudoObjectExpr(EmptyShell shell, unsigned numSemanticExprs)
: Expr(PseudoObjectExprClass, shell) {
PseudoObjectExprBits.NumSubExprs = numSemanticExprs + 1;
}
PseudoObjectExpr *PseudoObjectExpr::Create(const ASTContext &C, Expr *syntax,
ArrayRef<Expr*> semantics,
unsigned resultIndex) {
assert(syntax && "no syntactic expression!");
assert(semantics.size() && "no semantic expressions!");
QualType type;
ExprValueKind VK;
if (resultIndex == NoResult) {
type = C.VoidTy;
VK = VK_RValue;
} else {
assert(resultIndex < semantics.size());
type = semantics[resultIndex]->getType();
VK = semantics[resultIndex]->getValueKind();
assert(semantics[resultIndex]->getObjectKind() == OK_Ordinary);
}
void *buffer = C.Allocate(sizeof(PseudoObjectExpr) +
(1 + semantics.size()) * sizeof(Expr*),
llvm::alignOf<PseudoObjectExpr>());
return new(buffer) PseudoObjectExpr(type, VK, syntax, semantics,
resultIndex);
}
PseudoObjectExpr::PseudoObjectExpr(QualType type, ExprValueKind VK,
Expr *syntax, ArrayRef<Expr*> semantics,
unsigned resultIndex)
: Expr(PseudoObjectExprClass, type, VK, OK_Ordinary,
/*filled in at end of ctor*/ false, false, false, false) {
PseudoObjectExprBits.NumSubExprs = semantics.size() + 1;
PseudoObjectExprBits.ResultIndex = resultIndex + 1;
for (unsigned i = 0, e = semantics.size() + 1; i != e; ++i) {
Expr *E = (i == 0 ? syntax : semantics[i-1]);
getSubExprsBuffer()[i] = E;
if (E->isTypeDependent())
ExprBits.TypeDependent = true;
if (E->isValueDependent())
ExprBits.ValueDependent = true;
if (E->isInstantiationDependent())
ExprBits.InstantiationDependent = true;
if (E->containsUnexpandedParameterPack())
ExprBits.ContainsUnexpandedParameterPack = true;
if (isa<OpaqueValueExpr>(E))
assert(cast<OpaqueValueExpr>(E)->getSourceExpr() != nullptr &&
"opaque-value semantic expressions for pseudo-object "
"operations must have sources");
}
}
//===----------------------------------------------------------------------===//
// Child Iterators for iterating over subexpressions/substatements
//===----------------------------------------------------------------------===//
// UnaryExprOrTypeTraitExpr
Stmt::child_range UnaryExprOrTypeTraitExpr::children() {
// If this is of a type and the type is a VLA type (and not a typedef), the
// size expression of the VLA needs to be treated as an executable expression.
// Why isn't this weirdness documented better in StmtIterator?
if (isArgumentType()) {
if (const VariableArrayType* T = dyn_cast<VariableArrayType>(
getArgumentType().getTypePtr()))
return child_range(child_iterator(T), child_iterator());
return child_range(child_iterator(), child_iterator());
}
return child_range(&Argument.Ex, &Argument.Ex + 1);
}
AtomicExpr::AtomicExpr(SourceLocation BLoc, ArrayRef<Expr*> args,
QualType t, AtomicOp op, SourceLocation RP)
: Expr(AtomicExprClass, t, VK_RValue, OK_Ordinary,
false, false, false, false),
NumSubExprs(args.size()), BuiltinLoc(BLoc), RParenLoc(RP), Op(op)
{
assert(args.size() == getNumSubExprs(op) && "wrong number of subexpressions");
for (unsigned i = 0; i != args.size(); i++) {
if (args[i]->isTypeDependent())
ExprBits.TypeDependent = true;
if (args[i]->isValueDependent())
ExprBits.ValueDependent = true;
if (args[i]->isInstantiationDependent())
ExprBits.InstantiationDependent = true;
if (args[i]->containsUnexpandedParameterPack())
ExprBits.ContainsUnexpandedParameterPack = true;
SubExprs[i] = args[i];
}
}
unsigned AtomicExpr::getNumSubExprs(AtomicOp Op) {
switch (Op) {
case AO__c11_atomic_init:
case AO__c11_atomic_load:
case AO__atomic_load_n:
return 2;
case AO__c11_atomic_store:
case AO__c11_atomic_exchange:
case AO__atomic_load:
case AO__atomic_store:
case AO__atomic_store_n:
case AO__atomic_exchange_n:
case AO__c11_atomic_fetch_add:
case AO__c11_atomic_fetch_sub:
case AO__c11_atomic_fetch_and:
case AO__c11_atomic_fetch_or:
case AO__c11_atomic_fetch_xor:
case AO__atomic_fetch_add:
case AO__atomic_fetch_sub:
case AO__atomic_fetch_and:
case AO__atomic_fetch_or:
case AO__atomic_fetch_xor:
case AO__atomic_fetch_nand:
case AO__atomic_add_fetch:
case AO__atomic_sub_fetch:
case AO__atomic_and_fetch:
case AO__atomic_or_fetch:
case AO__atomic_xor_fetch:
case AO__atomic_nand_fetch:
return 3;
case AO__atomic_exchange:
return 4;
case AO__c11_atomic_compare_exchange_strong:
case AO__c11_atomic_compare_exchange_weak:
return 5;
case AO__atomic_compare_exchange:
case AO__atomic_compare_exchange_n:
return 6;
}
llvm_unreachable("unknown atomic op");
}
QualType OMPArraySectionExpr::getBaseOriginalType(Expr *Base) {
unsigned ArraySectionCount = 0;
while (auto *OASE = dyn_cast<OMPArraySectionExpr>(Base->IgnoreParens())) {
Base = OASE->getBase();
++ArraySectionCount;
}
while (auto *ASE = dyn_cast<ArraySubscriptExpr>(Base->IgnoreParens())) {
Base = ASE->getBase();
++ArraySectionCount;
}
auto OriginalTy = Base->getType();
if (auto *DRE = dyn_cast<DeclRefExpr>(Base))
if (auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl()))
OriginalTy = PVD->getOriginalType().getNonReferenceType();
for (unsigned Cnt = 0; Cnt < ArraySectionCount; ++Cnt) {
if (OriginalTy->isAnyPointerType())
OriginalTy = OriginalTy->getPointeeType();
else {
assert (OriginalTy->isArrayType());
OriginalTy = OriginalTy->castAsArrayTypeUnsafe()->getElementType();
}
}
return OriginalTy;
}
diff --git a/lib/CodeGen/CGStmt.cpp b/lib/CodeGen/CGStmt.cpp
index 7c4fb41..657c23d 100644
--- a/lib/CodeGen/CGStmt.cpp
+++ b/lib/CodeGen/CGStmt.cpp
@@ -1,2172 +1,2174 @@
//===--- CGStmt.cpp - Emit LLVM Code from Statements ----------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This contains code to emit Stmt nodes as LLVM code.
//
//===----------------------------------------------------------------------===//
#include "CodeGenFunction.h"
#include "CGDebugInfo.h"
#include "CodeGenModule.h"
#include "TargetInfo.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/Basic/Builtins.h"
#include "clang/Basic/PrettyStackTrace.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Sema/LoopHint.h"
#include "clang/Sema/SemaDiagnostic.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/IR/CallSite.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/InlineAsm.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/MDBuilder.h"
using namespace clang;
using namespace CodeGen;
//===----------------------------------------------------------------------===//
// Statement Emission
//===----------------------------------------------------------------------===//
void CodeGenFunction::EmitStopPoint(const Stmt *S) {
if (CGDebugInfo *DI = getDebugInfo()) {
SourceLocation Loc;
Loc = S->getLocStart();
DI->EmitLocation(Builder, Loc);
LastStopPoint = Loc;
}
}
void CodeGenFunction::EmitStmt(const Stmt *S) {
assert(S && "Null statement?");
PGO.setCurrentStmt(S);
// These statements have their own debug info handling.
if (EmitSimpleStmt(S))
return;
// Check if we are generating unreachable code.
if (!HaveInsertPoint()) {
// If so, and the statement doesn't contain a label, then we do not need to
// generate actual code. This is safe because (1) the current point is
// unreachable, so we don't need to execute the code, and (2) we've already
// handled the statements which update internal data structures (like the
// local variable map) which could be used by subsequent statements.
if (!ContainsLabel(S)) {
// Verify that any decl statements were handled as simple, they may be in
// scope of subsequent reachable statements.
assert(!isa<DeclStmt>(*S) && "Unexpected DeclStmt!");
return;
}
// Otherwise, make a new block to hold the code.
EnsureInsertPoint();
}
// Generate a stoppoint if we are emitting debug info.
EmitStopPoint(S);
switch (S->getStmtClass()) {
case Stmt::NoStmtClass:
case Stmt::CXXCatchStmtClass:
case Stmt::SEHExceptStmtClass:
case Stmt::SEHFinallyStmtClass:
case Stmt::MSDependentExistsStmtClass:
llvm_unreachable("invalid statement class to emit generically");
case Stmt::NullStmtClass:
case Stmt::CompoundStmtClass:
case Stmt::DeclStmtClass:
case Stmt::LabelStmtClass:
case Stmt::AttributedStmtClass:
case Stmt::GotoStmtClass:
case Stmt::BreakStmtClass:
case Stmt::ContinueStmtClass:
case Stmt::DefaultStmtClass:
case Stmt::CaseStmtClass:
case Stmt::SEHLeaveStmtClass:
llvm_unreachable("should have emitted these statements as simple");
#define STMT(Type, Base)
#define ABSTRACT_STMT(Op)
#define EXPR(Type, Base) \
case Stmt::Type##Class:
#include "clang/AST/StmtNodes.inc"
{
// Remember the block we came in on.
llvm::BasicBlock *incoming = Builder.GetInsertBlock();
assert(incoming && "expression emission must have an insertion point");
EmitIgnoredExpr(cast<Expr>(S));
llvm::BasicBlock *outgoing = Builder.GetInsertBlock();
assert(outgoing && "expression emission cleared block!");
// The expression emitters assume (reasonably!) that the insertion
// point is always set. To maintain that, the call-emission code
// for noreturn functions has to enter a new block with no
// predecessors. We want to kill that block and mark the current
// insertion point unreachable in the common case of a call like
// "exit();". Since expression emission doesn't otherwise create
// blocks with no predecessors, we can just test for that.
// However, we must be careful not to do this to our incoming
// block, because *statement* emission does sometimes create
// reachable blocks which will have no predecessors until later in
// the function. This occurs with, e.g., labels that are not
// reachable by fallthrough.
if (incoming != outgoing && outgoing->use_empty()) {
outgoing->eraseFromParent();
Builder.ClearInsertionPoint();
}
break;
}
case Stmt::IndirectGotoStmtClass:
EmitIndirectGotoStmt(cast<IndirectGotoStmt>(*S)); break;
case Stmt::IfStmtClass: EmitIfStmt(cast<IfStmt>(*S)); break;
case Stmt::WhileStmtClass: EmitWhileStmt(cast<WhileStmt>(*S)); break;
case Stmt::DoStmtClass: EmitDoStmt(cast<DoStmt>(*S)); break;
case Stmt::ForStmtClass: EmitForStmt(cast<ForStmt>(*S)); break;
case Stmt::ReturnStmtClass: EmitReturnStmt(cast<ReturnStmt>(*S)); break;
case Stmt::SwitchStmtClass: EmitSwitchStmt(cast<SwitchStmt>(*S)); break;
case Stmt::GCCAsmStmtClass: // Intentional fall-through.
case Stmt::MSAsmStmtClass: EmitAsmStmt(cast<AsmStmt>(*S)); break;
case Stmt::CoroutineBodyStmtClass:
case Stmt::CoreturnStmtClass:
CGM.ErrorUnsupported(S, "coroutine");
break;
case Stmt::CapturedStmtClass: {
const CapturedStmt *CS = cast<CapturedStmt>(S);
EmitCapturedStmt(*CS, CS->getCapturedRegionKind());
}
break;
case Stmt::ObjCAtTryStmtClass:
EmitObjCAtTryStmt(cast<ObjCAtTryStmt>(*S));
break;
case Stmt::ObjCAtCatchStmtClass:
llvm_unreachable(
"@catch statements should be handled by EmitObjCAtTryStmt");
case Stmt::ObjCAtFinallyStmtClass:
llvm_unreachable(
"@finally statements should be handled by EmitObjCAtTryStmt");
case Stmt::ObjCAtThrowStmtClass:
EmitObjCAtThrowStmt(cast<ObjCAtThrowStmt>(*S));
break;
case Stmt::ObjCAtSynchronizedStmtClass:
EmitObjCAtSynchronizedStmt(cast<ObjCAtSynchronizedStmt>(*S));
break;
case Stmt::ObjCForCollectionStmtClass:
EmitObjCForCollectionStmt(cast<ObjCForCollectionStmt>(*S));
break;
case Stmt::ObjCAutoreleasePoolStmtClass:
EmitObjCAutoreleasePoolStmt(cast<ObjCAutoreleasePoolStmt>(*S));
break;
case Stmt::CXXTryStmtClass:
EmitCXXTryStmt(cast<CXXTryStmt>(*S));
break;
case Stmt::CXXForRangeStmtClass:
EmitCXXForRangeStmt(cast<CXXForRangeStmt>(*S));
break;
case Stmt::SEHTryStmtClass:
EmitSEHTryStmt(cast<SEHTryStmt>(*S));
break;
case Stmt::OMPParallelDirectiveClass:
EmitOMPParallelDirective(cast<OMPParallelDirective>(*S));
break;
case Stmt::OMPSimdDirectiveClass:
EmitOMPSimdDirective(cast<OMPSimdDirective>(*S));
break;
case Stmt::OMPForDirectiveClass:
EmitOMPForDirective(cast<OMPForDirective>(*S));
break;
case Stmt::OMPForSimdDirectiveClass:
EmitOMPForSimdDirective(cast<OMPForSimdDirective>(*S));
break;
case Stmt::OMPSectionsDirectiveClass:
EmitOMPSectionsDirective(cast<OMPSectionsDirective>(*S));
break;
case Stmt::OMPSectionDirectiveClass:
EmitOMPSectionDirective(cast<OMPSectionDirective>(*S));
break;
case Stmt::OMPSingleDirectiveClass:
EmitOMPSingleDirective(cast<OMPSingleDirective>(*S));
break;
case Stmt::OMPMasterDirectiveClass:
EmitOMPMasterDirective(cast<OMPMasterDirective>(*S));
break;
case Stmt::OMPCriticalDirectiveClass:
EmitOMPCriticalDirective(cast<OMPCriticalDirective>(*S));
break;
case Stmt::OMPParallelForDirectiveClass:
EmitOMPParallelForDirective(cast<OMPParallelForDirective>(*S));
break;
case Stmt::OMPParallelForSimdDirectiveClass:
EmitOMPParallelForSimdDirective(cast<OMPParallelForSimdDirective>(*S));
break;
case Stmt::OMPParallelSectionsDirectiveClass:
EmitOMPParallelSectionsDirective(cast<OMPParallelSectionsDirective>(*S));
break;
case Stmt::OMPTaskDirectiveClass:
EmitOMPTaskDirective(cast<OMPTaskDirective>(*S));
break;
case Stmt::OMPTaskyieldDirectiveClass:
EmitOMPTaskyieldDirective(cast<OMPTaskyieldDirective>(*S));
break;
case Stmt::OMPBarrierDirectiveClass:
EmitOMPBarrierDirective(cast<OMPBarrierDirective>(*S));
break;
case Stmt::OMPTaskwaitDirectiveClass:
EmitOMPTaskwaitDirective(cast<OMPTaskwaitDirective>(*S));
break;
case Stmt::OMPTaskgroupDirectiveClass:
EmitOMPTaskgroupDirective(cast<OMPTaskgroupDirective>(*S));
break;
case Stmt::OMPFlushDirectiveClass:
EmitOMPFlushDirective(cast<OMPFlushDirective>(*S));
break;
case Stmt::OMPOrderedDirectiveClass:
EmitOMPOrderedDirective(cast<OMPOrderedDirective>(*S));
break;
case Stmt::OMPAtomicDirectiveClass:
EmitOMPAtomicDirective(cast<OMPAtomicDirective>(*S));
break;
case Stmt::OMPTargetDirectiveClass:
EmitOMPTargetDirective(cast<OMPTargetDirective>(*S));
break;
case Stmt::OMPTeamsDirectiveClass:
EmitOMPTeamsDirective(cast<OMPTeamsDirective>(*S));
break;
case Stmt::OMPCancellationPointDirectiveClass:
EmitOMPCancellationPointDirective(cast<OMPCancellationPointDirective>(*S));
break;
case Stmt::OMPCancelDirectiveClass:
EmitOMPCancelDirective(cast<OMPCancelDirective>(*S));
break;
case Stmt::OMPTargetDataDirectiveClass:
EmitOMPTargetDataDirective(cast<OMPTargetDataDirective>(*S));
break;
}
}
bool CodeGenFunction::EmitSimpleStmt(const Stmt *S) {
switch (S->getStmtClass()) {
default: return false;
case Stmt::NullStmtClass: break;
case Stmt::CompoundStmtClass: EmitCompoundStmt(cast<CompoundStmt>(*S)); break;
case Stmt::DeclStmtClass: EmitDeclStmt(cast<DeclStmt>(*S)); break;
case Stmt::LabelStmtClass: EmitLabelStmt(cast<LabelStmt>(*S)); break;
case Stmt::AttributedStmtClass:
EmitAttributedStmt(cast<AttributedStmt>(*S)); break;
case Stmt::GotoStmtClass: EmitGotoStmt(cast<GotoStmt>(*S)); break;
case Stmt::BreakStmtClass: EmitBreakStmt(cast<BreakStmt>(*S)); break;
case Stmt::ContinueStmtClass: EmitContinueStmt(cast<ContinueStmt>(*S)); break;
case Stmt::DefaultStmtClass: EmitDefaultStmt(cast<DefaultStmt>(*S)); break;
case Stmt::CaseStmtClass: EmitCaseStmt(cast<CaseStmt>(*S)); break;
case Stmt::SEHLeaveStmtClass: EmitSEHLeaveStmt(cast<SEHLeaveStmt>(*S)); break;
}
return true;
}
/// EmitCompoundStmt - Emit a compound statement {..} node. If GetLast is true,
/// this captures the expression result of the last sub-statement and returns it
/// (for use by the statement expression extension).
Address CodeGenFunction::EmitCompoundStmt(const CompoundStmt &S, bool GetLast,
AggValueSlot AggSlot) {
PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),S.getLBracLoc(),
"LLVM IR generation of compound statement ('{}')");
// Keep track of the current cleanup stack depth, including debug scopes.
LexicalScope Scope(*this, S.getSourceRange());
return EmitCompoundStmtWithoutScope(S, GetLast, AggSlot);
}
Address
CodeGenFunction::EmitCompoundStmtWithoutScope(const CompoundStmt &S,
bool GetLast,
AggValueSlot AggSlot) {
for (CompoundStmt::const_body_iterator I = S.body_begin(),
E = S.body_end()-GetLast; I != E; ++I)
EmitStmt(*I);
Address RetAlloca = Address::invalid();
if (GetLast) {
// We have to special case labels here. They are statements, but when put
// at the end of a statement expression, they yield the value of their
// subexpression. Handle this by walking through all labels we encounter,
// emitting them before we evaluate the subexpr.
const Stmt *LastStmt = S.body_back();
while (const LabelStmt *LS = dyn_cast<LabelStmt>(LastStmt)) {
EmitLabel(LS->getDecl());
LastStmt = LS->getSubStmt();
}
EnsureInsertPoint();
QualType ExprTy = cast<Expr>(LastStmt)->getType();
if (hasAggregateEvaluationKind(ExprTy)) {
EmitAggExpr(cast<Expr>(LastStmt), AggSlot);
} else {
// We can't return an RValue here because there might be cleanups at
// the end of the StmtExpr. Because of that, we have to emit the result
// here into a temporary alloca.
RetAlloca = CreateMemTemp(ExprTy);
EmitAnyExprToMem(cast<Expr>(LastStmt), RetAlloca, Qualifiers(),
/*IsInit*/false);
}
}
return RetAlloca;
}
void CodeGenFunction::SimplifyForwardingBlocks(llvm::BasicBlock *BB) {
llvm::BranchInst *BI = dyn_cast<llvm::BranchInst>(BB->getTerminator());
// If there is a cleanup stack, then we it isn't worth trying to
// simplify this block (we would need to remove it from the scope map
// and cleanup entry).
if (!EHStack.empty())
return;
// Can only simplify direct branches.
if (!BI || !BI->isUnconditional())
return;
// Can only simplify empty blocks.
if (BI->getIterator() != BB->begin())
return;
BB->replaceAllUsesWith(BI->getSuccessor(0));
BI->eraseFromParent();
BB->eraseFromParent();
}
void CodeGenFunction::EmitBlock(llvm::BasicBlock *BB, bool IsFinished) {
llvm::BasicBlock *CurBB = Builder.GetInsertBlock();
// Fall out of the current block (if necessary).
EmitBranch(BB);
if (IsFinished && BB->use_empty()) {
delete BB;
return;
}
// Place the block after the current block, if possible, or else at
// the end of the function.
if (CurBB && CurBB->getParent())
CurFn->getBasicBlockList().insertAfter(CurBB->getIterator(), BB);
else
CurFn->getBasicBlockList().push_back(BB);
Builder.SetInsertPoint(BB);
}
void CodeGenFunction::EmitBranch(llvm::BasicBlock *Target) {
// Emit a branch from the current block to the target one if this
// was a real block. If this was just a fall-through block after a
// terminator, don't emit it.
llvm::BasicBlock *CurBB = Builder.GetInsertBlock();
if (!CurBB || CurBB->getTerminator()) {
// If there is no insert point or the previous block is already
// terminated, don't touch it.
} else {
// Otherwise, create a fall-through branch.
Builder.CreateBr(Target);
}
Builder.ClearInsertionPoint();
}
void CodeGenFunction::EmitBlockAfterUses(llvm::BasicBlock *block) {
bool inserted = false;
for (llvm::User *u : block->users()) {
if (llvm::Instruction *insn = dyn_cast<llvm::Instruction>(u)) {
CurFn->getBasicBlockList().insertAfter(insn->getParent()->getIterator(),
block);
inserted = true;
break;
}
}
if (!inserted)
CurFn->getBasicBlockList().push_back(block);
Builder.SetInsertPoint(block);
}
CodeGenFunction::JumpDest
CodeGenFunction::getJumpDestForLabel(const LabelDecl *D) {
JumpDest &Dest = LabelMap[D];
if (Dest.isValid()) return Dest;
// Create, but don't insert, the new block.
Dest = JumpDest(createBasicBlock(D->getName()),
EHScopeStack::stable_iterator::invalid(),
NextCleanupDestIndex++);
return Dest;
}
void CodeGenFunction::EmitLabel(const LabelDecl *D) {
// Add this label to the current lexical scope if we're within any
// normal cleanups. Jumps "in" to this label --- when permitted by
// the language --- may need to be routed around such cleanups.
if (EHStack.hasNormalCleanups() && CurLexicalScope)
CurLexicalScope->addLabel(D);
JumpDest &Dest = LabelMap[D];
// If we didn't need a forward reference to this label, just go
// ahead and create a destination at the current scope.
if (!Dest.isValid()) {
Dest = getJumpDestInCurrentScope(D->getName());
// Otherwise, we need to give this label a target depth and remove
// it from the branch-fixups list.
} else {
assert(!Dest.getScopeDepth().isValid() && "already emitted label!");
Dest.setScopeDepth(EHStack.stable_begin());
ResolveBranchFixups(Dest.getBlock());
}
EmitBlock(Dest.getBlock());
incrementProfileCounter(D->getStmt());
}
/// Change the cleanup scope of the labels in this lexical scope to
/// match the scope of the enclosing context.
void CodeGenFunction::LexicalScope::rescopeLabels() {
assert(!Labels.empty());
EHScopeStack::stable_iterator innermostScope
= CGF.EHStack.getInnermostNormalCleanup();
// Change the scope depth of all the labels.
for (SmallVectorImpl<const LabelDecl*>::const_iterator
i = Labels.begin(), e = Labels.end(); i != e; ++i) {
assert(CGF.LabelMap.count(*i));
JumpDest &dest = CGF.LabelMap.find(*i)->second;
assert(dest.getScopeDepth().isValid());
assert(innermostScope.encloses(dest.getScopeDepth()));
dest.setScopeDepth(innermostScope);
}
// Reparent the labels if the new scope also has cleanups.
if (innermostScope != EHScopeStack::stable_end() && ParentScope) {
ParentScope->Labels.append(Labels.begin(), Labels.end());
}
}
void CodeGenFunction::EmitLabelStmt(const LabelStmt &S) {
EmitLabel(S.getDecl());
EmitStmt(S.getSubStmt());
}
void CodeGenFunction::EmitAttributedStmt(const AttributedStmt &S) {
const Stmt *SubStmt = S.getSubStmt();
switch (SubStmt->getStmtClass()) {
case Stmt::DoStmtClass:
EmitDoStmt(cast<DoStmt>(*SubStmt), S.getAttrs());
break;
case Stmt::ForStmtClass:
EmitForStmt(cast<ForStmt>(*SubStmt), S.getAttrs());
break;
case Stmt::WhileStmtClass:
EmitWhileStmt(cast<WhileStmt>(*SubStmt), S.getAttrs());
break;
case Stmt::CXXForRangeStmtClass:
EmitCXXForRangeStmt(cast<CXXForRangeStmt>(*SubStmt), S.getAttrs());
break;
default:
EmitStmt(SubStmt);
}
}
void CodeGenFunction::EmitGotoStmt(const GotoStmt &S) {
// If this code is reachable then emit a stop point (if generating
// debug info). We have to do this ourselves because we are on the
// "simple" statement path.
if (HaveInsertPoint())
EmitStopPoint(&S);
EmitBranchThroughCleanup(getJumpDestForLabel(S.getLabel()));
}
void CodeGenFunction::EmitIndirectGotoStmt(const IndirectGotoStmt &S) {
if (const LabelDecl *Target = S.getConstantTarget()) {
EmitBranchThroughCleanup(getJumpDestForLabel(Target));
return;
}
// Ensure that we have an i8* for our PHI node.
llvm::Value *V = Builder.CreateBitCast(EmitScalarExpr(S.getTarget()),
Int8PtrTy, "addr");
llvm::BasicBlock *CurBB = Builder.GetInsertBlock();
// Get the basic block for the indirect goto.
llvm::BasicBlock *IndGotoBB = GetIndirectGotoBlock();
// The first instruction in the block has to be the PHI for the switch dest,
// add an entry for this branch.
cast<llvm::PHINode>(IndGotoBB->begin())->addIncoming(V, CurBB);
EmitBranch(IndGotoBB);
}
void CodeGenFunction::EmitIfStmt(const IfStmt &S) {
// C99 6.8.4.1: The first substatement is executed if the expression compares
// unequal to 0. The condition must be a scalar type.
LexicalScope ConditionScope(*this, S.getCond()->getSourceRange());
if (S.getConditionVariable())
EmitAutoVarDecl(*S.getConditionVariable());
// If the condition constant folds and can be elided, try to avoid emitting
// the condition and the dead arm of the if/else.
bool CondConstant;
if (ConstantFoldsToSimpleInteger(S.getCond(), CondConstant)) {
// Figure out which block (then or else) is executed.
const Stmt *Executed = S.getThen();
const Stmt *Skipped = S.getElse();
if (!CondConstant) // Condition false?
std::swap(Executed, Skipped);
// If the skipped block has no labels in it, just emit the executed block.
// This avoids emitting dead code and simplifies the CFG substantially.
if (!ContainsLabel(Skipped)) {
if (CondConstant)
incrementProfileCounter(&S);
if (Executed) {
RunCleanupsScope ExecutedScope(*this);
EmitStmt(Executed);
}
return;
}
}
// Otherwise, the condition did not fold, or we couldn't elide it. Just emit
// the conditional branch.
llvm::BasicBlock *ThenBlock = createBasicBlock("if.then");
llvm::BasicBlock *ContBlock = createBasicBlock("if.end");
llvm::BasicBlock *ElseBlock = ContBlock;
if (S.getElse())
ElseBlock = createBasicBlock("if.else");
EmitBranchOnBoolExpr(S.getCond(), ThenBlock, ElseBlock,
getProfileCount(S.getThen()));
// Emit the 'then' code.
EmitBlock(ThenBlock);
incrementProfileCounter(&S);
{
RunCleanupsScope ThenScope(*this);
EmitStmt(S.getThen());
}
EmitBranch(ContBlock);
// Emit the 'else' code if present.
if (const Stmt *Else = S.getElse()) {
{
// There is no need to emit line number for an unconditional branch.
auto NL = ApplyDebugLocation::CreateEmpty(*this);
EmitBlock(ElseBlock);
}
{
RunCleanupsScope ElseScope(*this);
EmitStmt(Else);
}
{
// There is no need to emit line number for an unconditional branch.
auto NL = ApplyDebugLocation::CreateEmpty(*this);
EmitBranch(ContBlock);
}
}
// Emit the continuation block for code after the if.
EmitBlock(ContBlock, true);
}
void CodeGenFunction::EmitWhileStmt(const WhileStmt &S,
ArrayRef<const Attr *> WhileAttrs) {
// Emit the header for the loop, which will also become
// the continue target.
JumpDest LoopHeader = getJumpDestInCurrentScope("while.cond");
EmitBlock(LoopHeader.getBlock());
LoopStack.push(LoopHeader.getBlock(), CGM.getContext(), WhileAttrs);
// Create an exit block for when the condition fails, which will
// also become the break target.
JumpDest LoopExit = getJumpDestInCurrentScope("while.end");
// Store the blocks to use for break and continue.
BreakContinueStack.push_back(BreakContinue(LoopExit, LoopHeader));
// C++ [stmt.while]p2:
// When the condition of a while statement is a declaration, the
// scope of the variable that is declared extends from its point
// of declaration (3.3.2) to the end of the while statement.
// [...]
// The object created in a condition is destroyed and created
// with each iteration of the loop.
RunCleanupsScope ConditionScope(*this);
if (S.getConditionVariable())
EmitAutoVarDecl(*S.getConditionVariable());
// Evaluate the conditional in the while header. C99 6.8.5.1: The
// evaluation of the controlling expression takes place before each
// execution of the loop body.
llvm::Value *BoolCondVal = EvaluateExprAsBool(S.getCond());
// while(1) is common, avoid extra exit blocks. Be sure
// to correctly handle break/continue though.
bool EmitBoolCondBranch = true;
if (llvm::ConstantInt *C = dyn_cast<llvm::ConstantInt>(BoolCondVal))
if (C->isOne())
EmitBoolCondBranch = false;
// As long as the condition is true, go to the loop body.
llvm::BasicBlock *LoopBody = createBasicBlock("while.body");
if (EmitBoolCondBranch) {
llvm::BasicBlock *ExitBlock = LoopExit.getBlock();
if (ConditionScope.requiresCleanups())
ExitBlock = createBasicBlock("while.exit");
Builder.CreateCondBr(
BoolCondVal, LoopBody, ExitBlock,
createProfileWeightsForLoop(S.getCond(), getProfileCount(S.getBody())));
if (ExitBlock != LoopExit.getBlock()) {
EmitBlock(ExitBlock);
EmitBranchThroughCleanup(LoopExit);
}
}
// Emit the loop body. We have to emit this in a cleanup scope
// because it might be a singleton DeclStmt.
{
RunCleanupsScope BodyScope(*this);
EmitBlock(LoopBody);
incrementProfileCounter(&S);
EmitStmt(S.getBody());
}
BreakContinueStack.pop_back();
// Immediately force cleanup.
ConditionScope.ForceCleanup();
EmitStopPoint(&S);
// Branch to the loop header again.
EmitBranch(LoopHeader.getBlock());
LoopStack.pop();
// Emit the exit block.
EmitBlock(LoopExit.getBlock(), true);
// The LoopHeader typically is just a branch if we skipped emitting
// a branch, try to erase it.
if (!EmitBoolCondBranch)
SimplifyForwardingBlocks(LoopHeader.getBlock());
}
void CodeGenFunction::EmitDoStmt(const DoStmt &S,
ArrayRef<const Attr *> DoAttrs) {
JumpDest LoopExit = getJumpDestInCurrentScope("do.end");
JumpDest LoopCond = getJumpDestInCurrentScope("do.cond");
uint64_t ParentCount = getCurrentProfileCount();
// Store the blocks to use for break and continue.
BreakContinueStack.push_back(BreakContinue(LoopExit, LoopCond));
// Emit the body of the loop.
llvm::BasicBlock *LoopBody = createBasicBlock("do.body");
LoopStack.push(LoopBody, CGM.getContext(), DoAttrs);
EmitBlockWithFallThrough(LoopBody, &S);
{
RunCleanupsScope BodyScope(*this);
EmitStmt(S.getBody());
}
EmitBlock(LoopCond.getBlock());
// C99 6.8.5.2: "The evaluation of the controlling expression takes place
// after each execution of the loop body."
// Evaluate the conditional in the while header.
// C99 6.8.5p2/p4: The first substatement is executed if the expression
// compares unequal to 0. The condition must be a scalar type.
llvm::Value *BoolCondVal = EvaluateExprAsBool(S.getCond());
BreakContinueStack.pop_back();
// "do {} while (0)" is common in macros, avoid extra blocks. Be sure
// to correctly handle break/continue though.
bool EmitBoolCondBranch = true;
if (llvm::ConstantInt *C = dyn_cast<llvm::ConstantInt>(BoolCondVal))
if (C->isZero())
EmitBoolCondBranch = false;
// As long as the condition is true, iterate the loop.
if (EmitBoolCondBranch) {
uint64_t BackedgeCount = getProfileCount(S.getBody()) - ParentCount;
Builder.CreateCondBr(
BoolCondVal, LoopBody, LoopExit.getBlock(),
createProfileWeightsForLoop(S.getCond(), BackedgeCount));
}
LoopStack.pop();
// Emit the exit block.
EmitBlock(LoopExit.getBlock());
// The DoCond block typically is just a branch if we skipped
// emitting a branch, try to erase it.
if (!EmitBoolCondBranch)
SimplifyForwardingBlocks(LoopCond.getBlock());
}
void CodeGenFunction::EmitForStmt(const ForStmt &S,
ArrayRef<const Attr *> ForAttrs) {
JumpDest LoopExit = getJumpDestInCurrentScope("for.end");
LexicalScope ForScope(*this, S.getSourceRange());
// Evaluate the first part before the loop.
if (S.getInit())
EmitStmt(S.getInit());
// Start the loop with a block that tests the condition.
// If there's an increment, the continue scope will be overwritten
// later.
JumpDest Continue = getJumpDestInCurrentScope("for.cond");
llvm::BasicBlock *CondBlock = Continue.getBlock();
EmitBlock(CondBlock);
LoopStack.push(CondBlock, CGM.getContext(), ForAttrs);
// If the for loop doesn't have an increment we can just use the
// condition as the continue block. Otherwise we'll need to create
// a block for it (in the current scope, i.e. in the scope of the
// condition), and that we will become our continue block.
if (S.getInc())
Continue = getJumpDestInCurrentScope("for.inc");
// Store the blocks to use for break and continue.
BreakContinueStack.push_back(BreakContinue(LoopExit, Continue));
// Create a cleanup scope for the condition variable cleanups.
LexicalScope ConditionScope(*this, S.getSourceRange());
if (S.getCond()) {
// If the for statement has a condition scope, emit the local variable
// declaration.
if (S.getConditionVariable()) {
EmitAutoVarDecl(*S.getConditionVariable());
}
llvm::BasicBlock *ExitBlock = LoopExit.getBlock();
// If there are any cleanups between here and the loop-exit scope,
// create a block to stage a loop exit along.
if (ForScope.requiresCleanups())
ExitBlock = createBasicBlock("for.cond.cleanup");
// As long as the condition is true, iterate the loop.
llvm::BasicBlock *ForBody = createBasicBlock("for.body");
// C99 6.8.5p2/p4: The first substatement is executed if the expression
// compares unequal to 0. The condition must be a scalar type.
llvm::Value *BoolCondVal = EvaluateExprAsBool(S.getCond());
Builder.CreateCondBr(
BoolCondVal, ForBody, ExitBlock,
createProfileWeightsForLoop(S.getCond(), getProfileCount(S.getBody())));
if (ExitBlock != LoopExit.getBlock()) {
EmitBlock(ExitBlock);
EmitBranchThroughCleanup(LoopExit);
}
EmitBlock(ForBody);
} else {
// Treat it as a non-zero constant. Don't even create a new block for the
// body, just fall into it.
}
incrementProfileCounter(&S);
{
// Create a separate cleanup scope for the body, in case it is not
// a compound statement.
RunCleanupsScope BodyScope(*this);
EmitStmt(S.getBody());
}
// If there is an increment, emit it next.
if (S.getInc()) {
EmitBlock(Continue.getBlock());
EmitStmt(S.getInc());
}
BreakContinueStack.pop_back();
ConditionScope.ForceCleanup();
EmitStopPoint(&S);
EmitBranch(CondBlock);
ForScope.ForceCleanup();
LoopStack.pop();
// Emit the fall-through block.
EmitBlock(LoopExit.getBlock(), true);
}
void
CodeGenFunction::EmitCXXForRangeStmt(const CXXForRangeStmt &S,
ArrayRef<const Attr *> ForAttrs) {
JumpDest LoopExit = getJumpDestInCurrentScope("for.end");
LexicalScope ForScope(*this, S.getSourceRange());
// Evaluate the first pieces before the loop.
EmitStmt(S.getRangeStmt());
EmitStmt(S.getBeginEndStmt());
// Start the loop with a block that tests the condition.
// If there's an increment, the continue scope will be overwritten
// later.
llvm::BasicBlock *CondBlock = createBasicBlock("for.cond");
EmitBlock(CondBlock);
LoopStack.push(CondBlock, CGM.getContext(), ForAttrs);
// If there are any cleanups between here and the loop-exit scope,
// create a block to stage a loop exit along.
llvm::BasicBlock *ExitBlock = LoopExit.getBlock();
if (ForScope.requiresCleanups())
ExitBlock = createBasicBlock("for.cond.cleanup");
// The loop body, consisting of the specified body and the loop variable.
llvm::BasicBlock *ForBody = createBasicBlock("for.body");
// The body is executed if the expression, contextually converted
// to bool, is true.
llvm::Value *BoolCondVal = EvaluateExprAsBool(S.getCond());
Builder.CreateCondBr(
BoolCondVal, ForBody, ExitBlock,
createProfileWeightsForLoop(S.getCond(), getProfileCount(S.getBody())));
if (ExitBlock != LoopExit.getBlock()) {
EmitBlock(ExitBlock);
EmitBranchThroughCleanup(LoopExit);
}
EmitBlock(ForBody);
incrementProfileCounter(&S);
// Create a block for the increment. In case of a 'continue', we jump there.
JumpDest Continue = getJumpDestInCurrentScope("for.inc");
// Store the blocks to use for break and continue.
BreakContinueStack.push_back(BreakContinue(LoopExit, Continue));
{
// Create a separate cleanup scope for the loop variable and body.
LexicalScope BodyScope(*this, S.getSourceRange());
EmitStmt(S.getLoopVarStmt());
EmitStmt(S.getBody());
}
EmitStopPoint(&S);
// If there is an increment, emit it next.
EmitBlock(Continue.getBlock());
EmitStmt(S.getInc());
BreakContinueStack.pop_back();
EmitBranch(CondBlock);
ForScope.ForceCleanup();
LoopStack.pop();
// Emit the fall-through block.
EmitBlock(LoopExit.getBlock(), true);
}
void CodeGenFunction::EmitReturnOfRValue(RValue RV, QualType Ty) {
if (RV.isScalar()) {
Builder.CreateStore(RV.getScalarVal(), ReturnValue);
} else if (RV.isAggregate()) {
EmitAggregateCopy(ReturnValue, RV.getAggregateAddress(), Ty);
} else {
EmitStoreOfComplex(RV.getComplexVal(), MakeAddrLValue(ReturnValue, Ty),
/*init*/ true);
}
EmitBranchThroughCleanup(ReturnBlock);
}
/// EmitReturnStmt - Note that due to GCC extensions, this can have an operand
/// if the function returns void, or may be missing one if the function returns
/// non-void. Fun stuff :).
void CodeGenFunction::EmitReturnStmt(const ReturnStmt &S) {
// Returning from an outlined SEH helper is UB, and we already warn on it.
if (IsOutlinedSEHHelper) {
Builder.CreateUnreachable();
Builder.ClearInsertionPoint();
}
// Emit the result value, even if unused, to evalute the side effects.
const Expr *RV = S.getRetValue();
// Treat block literals in a return expression as if they appeared
// in their own scope. This permits a small, easily-implemented
// exception to our over-conservative rules about not jumping to
// statements following block literals with non-trivial cleanups.
RunCleanupsScope cleanupScope(*this);
if (const ExprWithCleanups *cleanups =
dyn_cast_or_null<ExprWithCleanups>(RV)) {
enterFullExpression(cleanups);
RV = cleanups->getSubExpr();
}
// FIXME: Clean this up by using an LValue for ReturnTemp,
// EmitStoreThroughLValue, and EmitAnyExpr.
if (getLangOpts().ElideConstructors &&
S.getNRVOCandidate() && S.getNRVOCandidate()->isNRVOVariable()) {
// Apply the named return value optimization for this return statement,
// which means doing nothing: the appropriate result has already been
// constructed into the NRVO variable.
// If there is an NRVO flag for this variable, set it to 1 into indicate
// that the cleanup code should not destroy the variable.
if (llvm::Value *NRVOFlag = NRVOFlags[S.getNRVOCandidate()])
Builder.CreateFlagStore(Builder.getTrue(), NRVOFlag);
} else if (!ReturnValue.isValid() || (RV && RV->getType()->isVoidType())) {
// Make sure not to return anything, but evaluate the expression
// for side effects.
if (RV)
EmitAnyExpr(RV);
} else if (!RV) {
// Do nothing (return value is left uninitialized)
} else if (FnRetTy->isReferenceType()) {
// If this function returns a reference, take the address of the expression
// rather than the value.
RValue Result = EmitReferenceBindingToExpr(RV);
Builder.CreateStore(Result.getScalarVal(), ReturnValue);
} else {
switch (getEvaluationKind(RV->getType())) {
case TEK_Scalar:
Builder.CreateStore(EmitScalarExpr(RV), ReturnValue);
break;
case TEK_Complex:
EmitComplexExprIntoLValue(RV, MakeAddrLValue(ReturnValue, RV->getType()),
/*isInit*/ true);
break;
case TEK_Aggregate:
EmitAggExpr(RV, AggValueSlot::forAddr(ReturnValue,
Qualifiers(),
AggValueSlot::IsDestructed,
AggValueSlot::DoesNotNeedGCBarriers,
AggValueSlot::IsNotAliased));
break;
}
}
++NumReturnExprs;
if (!RV || RV->isEvaluatable(getContext()))
++NumSimpleReturnExprs;
cleanupScope.ForceCleanup();
EmitBranchThroughCleanup(ReturnBlock);
}
void CodeGenFunction::EmitDeclStmt(const DeclStmt &S) {
// As long as debug info is modeled with instructions, we have to ensure we
// have a place to insert here and write the stop point here.
if (HaveInsertPoint())
EmitStopPoint(&S);
for (const auto *I : S.decls())
EmitDecl(*I);
}
void CodeGenFunction::EmitBreakStmt(const BreakStmt &S) {
assert(!BreakContinueStack.empty() && "break stmt not in a loop or switch!");
// If this code is reachable then emit a stop point (if generating
// debug info). We have to do this ourselves because we are on the
// "simple" statement path.
if (HaveInsertPoint())
EmitStopPoint(&S);
EmitBranchThroughCleanup(BreakContinueStack.back().BreakBlock);
}
void CodeGenFunction::EmitContinueStmt(const ContinueStmt &S) {
assert(!BreakContinueStack.empty() && "continue stmt not in a loop!");
// If this code is reachable then emit a stop point (if generating
// debug info). We have to do this ourselves because we are on the
// "simple" statement path.
if (HaveInsertPoint())
EmitStopPoint(&S);
EmitBranchThroughCleanup(BreakContinueStack.back().ContinueBlock);
}
/// EmitCaseStmtRange - If case statement range is not too big then
/// add multiple cases to switch instruction, one for each value within
/// the range. If range is too big then emit "if" condition check.
void CodeGenFunction::EmitCaseStmtRange(const CaseStmt &S) {
assert(S.getRHS() && "Expected RHS value in CaseStmt");
llvm::APSInt LHS = S.getLHS()->EvaluateKnownConstInt(getContext());
llvm::APSInt RHS = S.getRHS()->EvaluateKnownConstInt(getContext());
// Emit the code for this case. We do this first to make sure it is
// properly chained from our predecessor before generating the
// switch machinery to enter this block.
llvm::BasicBlock *CaseDest = createBasicBlock("sw.bb");
EmitBlockWithFallThrough(CaseDest, &S);
EmitStmt(S.getSubStmt());
// If range is empty, do nothing.
if (LHS.isSigned() ? RHS.slt(LHS) : RHS.ult(LHS))
return;
llvm::APInt Range = RHS - LHS;
// FIXME: parameters such as this should not be hardcoded.
if (Range.ult(llvm::APInt(Range.getBitWidth(), 64))) {
// Range is small enough to add multiple switch instruction cases.
uint64_t Total = getProfileCount(&S);
unsigned NCases = Range.getZExtValue() + 1;
// We only have one region counter for the entire set of cases here, so we
// need to divide the weights evenly between the generated cases, ensuring
// that the total weight is preserved. E.g., a weight of 5 over three cases
// will be distributed as weights of 2, 2, and 1.
uint64_t Weight = Total / NCases, Rem = Total % NCases;
for (unsigned I = 0; I != NCases; ++I) {
if (SwitchWeights)
SwitchWeights->push_back(Weight + (Rem ? 1 : 0));
if (Rem)
Rem--;
SwitchInsn->addCase(Builder.getInt(LHS), CaseDest);
LHS++;
}
return;
}
// The range is too big. Emit "if" condition into a new block,
// making sure to save and restore the current insertion point.
llvm::BasicBlock *RestoreBB = Builder.GetInsertBlock();
// Push this test onto the chain of range checks (which terminates
// in the default basic block). The switch's default will be changed
// to the top of this chain after switch emission is complete.
llvm::BasicBlock *FalseDest = CaseRangeBlock;
CaseRangeBlock = createBasicBlock("sw.caserange");
CurFn->getBasicBlockList().push_back(CaseRangeBlock);
Builder.SetInsertPoint(CaseRangeBlock);
// Emit range check.
llvm::Value *Diff =
Builder.CreateSub(SwitchInsn->getCondition(), Builder.getInt(LHS));
llvm::Value *Cond =
Builder.CreateICmpULE(Diff, Builder.getInt(Range), "inbounds");
llvm::MDNode *Weights = nullptr;
if (SwitchWeights) {
uint64_t ThisCount = getProfileCount(&S);
uint64_t DefaultCount = (*SwitchWeights)[0];
Weights = createProfileWeights(ThisCount, DefaultCount);
// Since we're chaining the switch default through each large case range, we
// need to update the weight for the default, ie, the first case, to include
// this case.
(*SwitchWeights)[0] += ThisCount;
}
Builder.CreateCondBr(Cond, CaseDest, FalseDest, Weights);
// Restore the appropriate insertion point.
if (RestoreBB)
Builder.SetInsertPoint(RestoreBB);
else
Builder.ClearInsertionPoint();
}
void CodeGenFunction::EmitCaseStmt(const CaseStmt &S) {
// If there is no enclosing switch instance that we're aware of, then this
// case statement and its block can be elided. This situation only happens
// when we've constant-folded the switch, are emitting the constant case,
// and part of the constant case includes another case statement. For
// instance: switch (4) { case 4: do { case 5: } while (1); }
if (!SwitchInsn) {
EmitStmt(S.getSubStmt());
return;
}
// Handle case ranges.
if (S.getRHS()) {
EmitCaseStmtRange(S);
return;
}
llvm::ConstantInt *CaseVal =
Builder.getInt(S.getLHS()->EvaluateKnownConstInt(getContext()));
// If the body of the case is just a 'break', try to not emit an empty block.
// If we're profiling or we're not optimizing, leave the block in for better
// debug and coverage analysis.
if (!CGM.getCodeGenOpts().ProfileInstrGenerate &&
CGM.getCodeGenOpts().OptimizationLevel > 0 &&
isa<BreakStmt>(S.getSubStmt())) {
JumpDest Block = BreakContinueStack.back().BreakBlock;
// Only do this optimization if there are no cleanups that need emitting.
if (isObviouslyBranchWithoutCleanups(Block)) {
if (SwitchWeights)
SwitchWeights->push_back(getProfileCount(&S));
SwitchInsn->addCase(CaseVal, Block.getBlock());
// If there was a fallthrough into this case, make sure to redirect it to
// the end of the switch as well.
if (Builder.GetInsertBlock()) {
Builder.CreateBr(Block.getBlock());
Builder.ClearInsertionPoint();
}
return;
}
}
llvm::BasicBlock *CaseDest = createBasicBlock("sw.bb");
EmitBlockWithFallThrough(CaseDest, &S);
if (SwitchWeights)
SwitchWeights->push_back(getProfileCount(&S));
SwitchInsn->addCase(CaseVal, CaseDest);
// Recursively emitting the statement is acceptable, but is not wonderful for
// code where we have many case statements nested together, i.e.:
// case 1:
// case 2:
// case 3: etc.
// Handling this recursively will create a new block for each case statement
// that falls through to the next case which is IR intensive. It also causes
// deep recursion which can run into stack depth limitations. Handle
// sequential non-range case statements specially.
const CaseStmt *CurCase = &S;
const CaseStmt *NextCase = dyn_cast<CaseStmt>(S.getSubStmt());
// Otherwise, iteratively add consecutive cases to this switch stmt.
while (NextCase && NextCase->getRHS() == nullptr) {
CurCase = NextCase;
llvm::ConstantInt *CaseVal =
Builder.getInt(CurCase->getLHS()->EvaluateKnownConstInt(getContext()));
if (SwitchWeights)
SwitchWeights->push_back(getProfileCount(NextCase));
if (CGM.getCodeGenOpts().ProfileInstrGenerate) {
CaseDest = createBasicBlock("sw.bb");
EmitBlockWithFallThrough(CaseDest, &S);
}
SwitchInsn->addCase(CaseVal, CaseDest);
NextCase = dyn_cast<CaseStmt>(CurCase->getSubStmt());
}
// Normal default recursion for non-cases.
EmitStmt(CurCase->getSubStmt());
}
void CodeGenFunction::EmitDefaultStmt(const DefaultStmt &S) {
llvm::BasicBlock *DefaultBlock = SwitchInsn->getDefaultDest();
assert(DefaultBlock->empty() &&
"EmitDefaultStmt: Default block already defined?");
EmitBlockWithFallThrough(DefaultBlock, &S);
EmitStmt(S.getSubStmt());
}
/// CollectStatementsForCase - Given the body of a 'switch' statement and a
/// constant value that is being switched on, see if we can dead code eliminate
/// the body of the switch to a simple series of statements to emit. Basically,
/// on a switch (5) we want to find these statements:
/// case 5:
/// printf(...); <--
/// ++i; <--
/// break;
///
/// and add them to the ResultStmts vector. If it is unsafe to do this
/// transformation (for example, one of the elided statements contains a label
/// that might be jumped to), return CSFC_Failure. If we handled it and 'S'
/// should include statements after it (e.g. the printf() line is a substmt of
/// the case) then return CSFC_FallThrough. If we handled it and found a break
/// statement, then return CSFC_Success.
///
/// If Case is non-null, then we are looking for the specified case, checking
/// that nothing we jump over contains labels. If Case is null, then we found
/// the case and are looking for the break.
///
/// If the recursive walk actually finds our Case, then we set FoundCase to
/// true.
///
enum CSFC_Result { CSFC_Failure, CSFC_FallThrough, CSFC_Success };
static CSFC_Result CollectStatementsForCase(const Stmt *S,
const SwitchCase *Case,
bool &FoundCase,
SmallVectorImpl<const Stmt*> &ResultStmts) {
// If this is a null statement, just succeed.
if (!S)
return Case ? CSFC_Success : CSFC_FallThrough;
// If this is the switchcase (case 4: or default) that we're looking for, then
// we're in business. Just add the substatement.
if (const SwitchCase *SC = dyn_cast<SwitchCase>(S)) {
if (S == Case) {
FoundCase = true;
return CollectStatementsForCase(SC->getSubStmt(), nullptr, FoundCase,
ResultStmts);
}
// Otherwise, this is some other case or default statement, just ignore it.
return CollectStatementsForCase(SC->getSubStmt(), Case, FoundCase,
ResultStmts);
}
// If we are in the live part of the code and we found our break statement,
// return a success!
if (!Case && isa<BreakStmt>(S))
return CSFC_Success;
// If this is a switch statement, then it might contain the SwitchCase, the
// break, or neither.
if (const CompoundStmt *CS = dyn_cast<CompoundStmt>(S)) {
// Handle this as two cases: we might be looking for the SwitchCase (if so
// the skipped statements must be skippable) or we might already have it.
CompoundStmt::const_body_iterator I = CS->body_begin(), E = CS->body_end();
if (Case) {
// Keep track of whether we see a skipped declaration. The code could be
// using the declaration even if it is skipped, so we can't optimize out
// the decl if the kept statements might refer to it.
bool HadSkippedDecl = false;
// If we're looking for the case, just see if we can skip each of the
// substatements.
for (; Case && I != E; ++I) {
HadSkippedDecl |= isa<DeclStmt>(*I);
switch (CollectStatementsForCase(*I, Case, FoundCase, ResultStmts)) {
case CSFC_Failure: return CSFC_Failure;
case CSFC_Success:
// A successful result means that either 1) that the statement doesn't
// have the case and is skippable, or 2) does contain the case value
// and also contains the break to exit the switch. In the later case,
// we just verify the rest of the statements are elidable.
if (FoundCase) {
// If we found the case and skipped declarations, we can't do the
// optimization.
if (HadSkippedDecl)
return CSFC_Failure;
for (++I; I != E; ++I)
if (CodeGenFunction::ContainsLabel(*I, true))
return CSFC_Failure;
return CSFC_Success;
}
break;
case CSFC_FallThrough:
// If we have a fallthrough condition, then we must have found the
// case started to include statements. Consider the rest of the
// statements in the compound statement as candidates for inclusion.
assert(FoundCase && "Didn't find case but returned fallthrough?");
// We recursively found Case, so we're not looking for it anymore.
Case = nullptr;
// If we found the case and skipped declarations, we can't do the
// optimization.
if (HadSkippedDecl)
return CSFC_Failure;
break;
}
}
}
// If we have statements in our range, then we know that the statements are
// live and need to be added to the set of statements we're tracking.
for (; I != E; ++I) {
switch (CollectStatementsForCase(*I, nullptr, FoundCase, ResultStmts)) {
case CSFC_Failure: return CSFC_Failure;
case CSFC_FallThrough:
// A fallthrough result means that the statement was simple and just
// included in ResultStmt, keep adding them afterwards.
break;
case CSFC_Success:
// A successful result means that we found the break statement and
// stopped statement inclusion. We just ensure that any leftover stmts
// are skippable and return success ourselves.
for (++I; I != E; ++I)
if (CodeGenFunction::ContainsLabel(*I, true))
return CSFC_Failure;
return CSFC_Success;
}
}
return Case ? CSFC_Success : CSFC_FallThrough;
}
// Okay, this is some other statement that we don't handle explicitly, like a
// for statement or increment etc. If we are skipping over this statement,
// just verify it doesn't have labels, which would make it invalid to elide.
if (Case) {
if (CodeGenFunction::ContainsLabel(S, true))
return CSFC_Failure;
return CSFC_Success;
}
// Otherwise, we want to include this statement. Everything is cool with that
// so long as it doesn't contain a break out of the switch we're in.
if (CodeGenFunction::containsBreak(S)) return CSFC_Failure;
// Otherwise, everything is great. Include the statement and tell the caller
// that we fall through and include the next statement as well.
ResultStmts.push_back(S);
return CSFC_FallThrough;
}
/// FindCaseStatementsForValue - Find the case statement being jumped to and
/// then invoke CollectStatementsForCase to find the list of statements to emit
/// for a switch on constant. See the comment above CollectStatementsForCase
/// for more details.
static bool FindCaseStatementsForValue(const SwitchStmt &S,
const llvm::APSInt &ConstantCondValue,
SmallVectorImpl<const Stmt*> &ResultStmts,
ASTContext &C,
const SwitchCase *&ResultCase) {
// First step, find the switch case that is being branched to. We can do this
// efficiently by scanning the SwitchCase list.
const SwitchCase *Case = S.getSwitchCaseList();
const DefaultStmt *DefaultCase = nullptr;
for (; Case; Case = Case->getNextSwitchCase()) {
// It's either a default or case. Just remember the default statement in
// case we're not jumping to any numbered cases.
if (const DefaultStmt *DS = dyn_cast<DefaultStmt>(Case)) {
DefaultCase = DS;
continue;
}
// Check to see if this case is the one we're looking for.
const CaseStmt *CS = cast<CaseStmt>(Case);
// Don't handle case ranges yet.
if (CS->getRHS()) return false;
// If we found our case, remember it as 'case'.
if (CS->getLHS()->EvaluateKnownConstInt(C) == ConstantCondValue)
break;
}
// If we didn't find a matching case, we use a default if it exists, or we
// elide the whole switch body!
if (!Case) {
// It is safe to elide the body of the switch if it doesn't contain labels
// etc. If it is safe, return successfully with an empty ResultStmts list.
if (!DefaultCase)
return !CodeGenFunction::ContainsLabel(&S);
Case = DefaultCase;
}
// Ok, we know which case is being jumped to, try to collect all the
// statements that follow it. This can fail for a variety of reasons. Also,
// check to see that the recursive walk actually found our case statement.
// Insane cases like this can fail to find it in the recursive walk since we
// don't handle every stmt kind:
// switch (4) {
// while (1) {
// case 4: ...
bool FoundCase = false;
ResultCase = Case;
return CollectStatementsForCase(S.getBody(), Case, FoundCase,
ResultStmts) != CSFC_Failure &&
FoundCase;
}
void CodeGenFunction::EmitSwitchStmt(const SwitchStmt &S) {
// Handle nested switch statements.
llvm::SwitchInst *SavedSwitchInsn = SwitchInsn;
SmallVector<uint64_t, 16> *SavedSwitchWeights = SwitchWeights;
llvm::BasicBlock *SavedCRBlock = CaseRangeBlock;
// See if we can constant fold the condition of the switch and therefore only
// emit the live case statement (if any) of the switch.
llvm::APSInt ConstantCondValue;
if (ConstantFoldsToSimpleInteger(S.getCond(), ConstantCondValue)) {
SmallVector<const Stmt*, 4> CaseStmts;
const SwitchCase *Case = nullptr;
if (FindCaseStatementsForValue(S, ConstantCondValue, CaseStmts,
getContext(), Case)) {
if (Case)
incrementProfileCounter(Case);
RunCleanupsScope ExecutedScope(*this);
// Emit the condition variable if needed inside the entire cleanup scope
// used by this special case for constant folded switches.
if (S.getConditionVariable())
EmitAutoVarDecl(*S.getConditionVariable());
// At this point, we are no longer "within" a switch instance, so
// we can temporarily enforce this to ensure that any embedded case
// statements are not emitted.
SwitchInsn = nullptr;
// Okay, we can dead code eliminate everything except this case. Emit the
// specified series of statements and we're good.
for (unsigned i = 0, e = CaseStmts.size(); i != e; ++i)
EmitStmt(CaseStmts[i]);
incrementProfileCounter(&S);
// Now we want to restore the saved switch instance so that nested
// switches continue to function properly
SwitchInsn = SavedSwitchInsn;
return;
}
}
JumpDest SwitchExit = getJumpDestInCurrentScope("sw.epilog");
RunCleanupsScope ConditionScope(*this);
if (S.getConditionVariable())
EmitAutoVarDecl(*S.getConditionVariable());
llvm::Value *CondV = EmitScalarExpr(S.getCond());
// Create basic block to hold stuff that comes after switch
// statement. We also need to create a default block now so that
// explicit case ranges tests can have a place to jump to on
// failure.
llvm::BasicBlock *DefaultBlock = createBasicBlock("sw.default");
SwitchInsn = Builder.CreateSwitch(CondV, DefaultBlock);
if (PGO.haveRegionCounts()) {
// Walk the SwitchCase list to find how many there are.
uint64_t DefaultCount = 0;
unsigned NumCases = 0;
for (const SwitchCase *Case = S.getSwitchCaseList();
Case;
Case = Case->getNextSwitchCase()) {
if (isa<DefaultStmt>(Case))
DefaultCount = getProfileCount(Case);
NumCases += 1;
}
SwitchWeights = new SmallVector<uint64_t, 16>();
SwitchWeights->reserve(NumCases);
// The default needs to be first. We store the edge count, so we already
// know the right weight.
SwitchWeights->push_back(DefaultCount);
}
CaseRangeBlock = DefaultBlock;
// Clear the insertion point to indicate we are in unreachable code.
Builder.ClearInsertionPoint();
// All break statements jump to NextBlock. If BreakContinueStack is non-empty
// then reuse last ContinueBlock.
JumpDest OuterContinue;
if (!BreakContinueStack.empty())
OuterContinue = BreakContinueStack.back().ContinueBlock;
BreakContinueStack.push_back(BreakContinue(SwitchExit, OuterContinue));
// Emit switch body.
EmitStmt(S.getBody());
BreakContinueStack.pop_back();
// Update the default block in case explicit case range tests have
// been chained on top.
SwitchInsn->setDefaultDest(CaseRangeBlock);
// If a default was never emitted:
if (!DefaultBlock->getParent()) {
// If we have cleanups, emit the default block so that there's a
// place to jump through the cleanups from.
if (ConditionScope.requiresCleanups()) {
EmitBlock(DefaultBlock);
// Otherwise, just forward the default block to the switch end.
} else {
DefaultBlock->replaceAllUsesWith(SwitchExit.getBlock());
delete DefaultBlock;
}
}
ConditionScope.ForceCleanup();
// Emit continuation.
EmitBlock(SwitchExit.getBlock(), true);
incrementProfileCounter(&S);
// If the switch has a condition wrapped by __builtin_unpredictable,
// create metadata that specifies that the switch is unpredictable.
// Don't bother if not optimizing because that metadata would not be used.
if (CGM.getCodeGenOpts().OptimizationLevel != 0) {
if (const CallExpr *Call = dyn_cast<CallExpr>(S.getCond())) {
const Decl *TargetDecl = Call->getCalleeDecl();
if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(TargetDecl)) {
if (FD->getBuiltinID() == Builtin::BI__builtin_unpredictable) {
llvm::MDBuilder MDHelper(getLLVMContext());
SwitchInsn->setMetadata(llvm::LLVMContext::MD_unpredictable,
MDHelper.createUnpredictable());
}
}
}
}
if (SwitchWeights) {
assert(SwitchWeights->size() == 1 + SwitchInsn->getNumCases() &&
"switch weights do not match switch cases");
// If there's only one jump destination there's no sense weighting it.
if (SwitchWeights->size() > 1)
SwitchInsn->setMetadata(llvm::LLVMContext::MD_prof,
createProfileWeights(*SwitchWeights));
delete SwitchWeights;
}
SwitchInsn = SavedSwitchInsn;
SwitchWeights = SavedSwitchWeights;
CaseRangeBlock = SavedCRBlock;
}
static std::string
SimplifyConstraint(const char *Constraint, const TargetInfo &Target,
SmallVectorImpl<TargetInfo::ConstraintInfo> *OutCons=nullptr) {
std::string Result;
while (*Constraint) {
switch (*Constraint) {
default:
Result += Target.convertConstraint(Constraint);
break;
// Ignore these
case '*':
case '?':
case '!':
case '=': // Will see this and the following in mult-alt constraints.
case '+':
break;
case '#': // Ignore the rest of the constraint alternative.
while (Constraint[1] && Constraint[1] != ',')
Constraint++;
break;
case '&':
case '%':
Result += *Constraint;
while (Constraint[1] && Constraint[1] == *Constraint)
Constraint++;
break;
case ',':
Result += "|";
break;
case 'g':
Result += "imr";
break;
case '[': {
assert(OutCons &&
"Must pass output names to constraints with a symbolic name");
unsigned Index;
bool result = Target.resolveSymbolicName(Constraint, *OutCons, Index);
assert(result && "Could not resolve symbolic name"); (void)result;
Result += llvm::utostr(Index);
break;
}
}
Constraint++;
}
return Result;
}
/// AddVariableConstraints - Look at AsmExpr and if it is a variable declared
/// as using a particular register add that as a constraint that will be used
/// in this asm stmt.
static std::string
AddVariableConstraints(const std::string &Constraint, const Expr &AsmExpr,
const TargetInfo &Target, CodeGenModule &CGM,
const AsmStmt &Stmt, const bool EarlyClobber) {
const DeclRefExpr *AsmDeclRef = dyn_cast<DeclRefExpr>(&AsmExpr);
if (!AsmDeclRef)
return Constraint;
const ValueDecl &Value = *AsmDeclRef->getDecl();
const VarDecl *Variable = dyn_cast<VarDecl>(&Value);
if (!Variable)
return Constraint;
if (Variable->getStorageClass() != SC_Register)
return Constraint;
AsmLabelAttr *Attr = Variable->getAttr<AsmLabelAttr>();
if (!Attr)
return Constraint;
StringRef Register = Attr->getLabel();
assert(Target.isValidGCCRegisterName(Register));
// We're using validateOutputConstraint here because we only care if
// this is a register constraint.
TargetInfo::ConstraintInfo Info(Constraint, "");
if (Target.validateOutputConstraint(Info) &&
!Info.allowsRegister()) {
CGM.ErrorUnsupported(&Stmt, "__asm__");
return Constraint;
}
// Canonicalize the register here before returning it.
Register = Target.getNormalizedGCCRegisterName(Register);
return (EarlyClobber ? "&{" : "{") + Register.str() + "}";
}
llvm::Value*
CodeGenFunction::EmitAsmInputLValue(const TargetInfo::ConstraintInfo &Info,
LValue InputValue, QualType InputType,
std::string &ConstraintStr,
SourceLocation Loc) {
llvm::Value *Arg;
if (Info.allowsRegister() || !Info.allowsMemory()) {
if (CodeGenFunction::hasScalarEvaluationKind(InputType)) {
Arg = EmitLoadOfLValue(InputValue, Loc).getScalarVal();
} else {
llvm::Type *Ty = ConvertType(InputType);
uint64_t Size = CGM.getDataLayout().getTypeSizeInBits(Ty);
if (Size <= 64 && llvm::isPowerOf2_64(Size)) {
Ty = llvm::IntegerType::get(getLLVMContext(), Size);
Ty = llvm::PointerType::getUnqual(Ty);
Arg = Builder.CreateLoad(Builder.CreateBitCast(InputValue.getAddress(),
Ty));
} else {
Arg = InputValue.getPointer();
ConstraintStr += '*';
}
}
} else {
Arg = InputValue.getPointer();
ConstraintStr += '*';
}
return Arg;
}
llvm::Value* CodeGenFunction::EmitAsmInput(
const TargetInfo::ConstraintInfo &Info,
const Expr *InputExpr,
std::string &ConstraintStr) {
// If this can't be a register or memory, i.e., has to be a constant
// (immediate or symbolic), try to emit it as such.
if (!Info.allowsRegister() && !Info.allowsMemory()) {
llvm::APSInt Result;
if (InputExpr->EvaluateAsInt(Result, getContext()))
return llvm::ConstantInt::get(getLLVMContext(), Result);
assert(!Info.requiresImmediateConstant() &&
"Required-immediate inlineasm arg isn't constant?");
}
if (Info.allowsRegister() || !Info.allowsMemory())
if (CodeGenFunction::hasScalarEvaluationKind(InputExpr->getType()))
return EmitScalarExpr(InputExpr);
InputExpr = InputExpr->IgnoreParenNoopCasts(getContext());
LValue Dest = EmitLValue(InputExpr);
return EmitAsmInputLValue(Info, Dest, InputExpr->getType(), ConstraintStr,
InputExpr->getExprLoc());
}
/// getAsmSrcLocInfo - Return the !srcloc metadata node to attach to an inline
/// asm call instruction. The !srcloc MDNode contains a list of constant
/// integers which are the source locations of the start of each line in the
/// asm.
static llvm::MDNode *getAsmSrcLocInfo(const StringLiteral *Str,
CodeGenFunction &CGF) {
SmallVector<llvm::Metadata *, 8> Locs;
// Add the location of the first line to the MDNode.
Locs.push_back(llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
CGF.Int32Ty, Str->getLocStart().getRawEncoding())));
StringRef StrVal = Str->getString();
if (!StrVal.empty()) {
const SourceManager &SM = CGF.CGM.getContext().getSourceManager();
const LangOptions &LangOpts = CGF.CGM.getLangOpts();
+ unsigned StartToken = 0;
+ unsigned ByteOffset = 0;
// Add the location of the start of each subsequent line of the asm to the
// MDNode.
- for (unsigned i = 0, e = StrVal.size()-1; i != e; ++i) {
+ for (unsigned i = 0, e = StrVal.size() - 1; i != e; ++i) {
if (StrVal[i] != '\n') continue;
- SourceLocation LineLoc = Str->getLocationOfByte(i+1, SM, LangOpts,
- CGF.getTarget());
+ SourceLocation LineLoc = Str->getLocationOfByte(
+ i + 1, SM, LangOpts, CGF.getTarget(), &StartToken, &ByteOffset);
Locs.push_back(llvm::ConstantAsMetadata::get(
llvm::ConstantInt::get(CGF.Int32Ty, LineLoc.getRawEncoding())));
}
}
return llvm::MDNode::get(CGF.getLLVMContext(), Locs);
}
void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) {
// Assemble the final asm string.
std::string AsmString = S.generateAsmString(getContext());
// Get all the output and input constraints together.
SmallVector<TargetInfo::ConstraintInfo, 4> OutputConstraintInfos;
SmallVector<TargetInfo::ConstraintInfo, 4> InputConstraintInfos;
for (unsigned i = 0, e = S.getNumOutputs(); i != e; i++) {
StringRef Name;
if (const GCCAsmStmt *GAS = dyn_cast<GCCAsmStmt>(&S))
Name = GAS->getOutputName(i);
TargetInfo::ConstraintInfo Info(S.getOutputConstraint(i), Name);
bool IsValid = getTarget().validateOutputConstraint(Info); (void)IsValid;
assert(IsValid && "Failed to parse output constraint");
OutputConstraintInfos.push_back(Info);
}
for (unsigned i = 0, e = S.getNumInputs(); i != e; i++) {
StringRef Name;
if (const GCCAsmStmt *GAS = dyn_cast<GCCAsmStmt>(&S))
Name = GAS->getInputName(i);
TargetInfo::ConstraintInfo Info(S.getInputConstraint(i), Name);
bool IsValid =
getTarget().validateInputConstraint(OutputConstraintInfos, Info);
assert(IsValid && "Failed to parse input constraint"); (void)IsValid;
InputConstraintInfos.push_back(Info);
}
std::string Constraints;
std::vector<LValue> ResultRegDests;
std::vector<QualType> ResultRegQualTys;
std::vector<llvm::Type *> ResultRegTypes;
std::vector<llvm::Type *> ResultTruncRegTypes;
std::vector<llvm::Type *> ArgTypes;
std::vector<llvm::Value*> Args;
// Keep track of inout constraints.
std::string InOutConstraints;
std::vector<llvm::Value*> InOutArgs;
std::vector<llvm::Type*> InOutArgTypes;
// An inline asm can be marked readonly if it meets the following conditions:
// - it doesn't have any sideeffects
// - it doesn't clobber memory
// - it doesn't return a value by-reference
// It can be marked readnone if it doesn't have any input memory constraints
// in addition to meeting the conditions listed above.
bool ReadOnly = true, ReadNone = true;
for (unsigned i = 0, e = S.getNumOutputs(); i != e; i++) {
TargetInfo::ConstraintInfo &Info = OutputConstraintInfos[i];
// Simplify the output constraint.
std::string OutputConstraint(S.getOutputConstraint(i));
OutputConstraint = SimplifyConstraint(OutputConstraint.c_str() + 1,
getTarget());
const Expr *OutExpr = S.getOutputExpr(i);
OutExpr = OutExpr->IgnoreParenNoopCasts(getContext());
OutputConstraint = AddVariableConstraints(OutputConstraint, *OutExpr,
getTarget(), CGM, S,
Info.earlyClobber());
LValue Dest = EmitLValue(OutExpr);
if (!Constraints.empty())
Constraints += ',';
// If this is a register output, then make the inline asm return it
// by-value. If this is a memory result, return the value by-reference.
if (!Info.allowsMemory() && hasScalarEvaluationKind(OutExpr->getType())) {
Constraints += "=" + OutputConstraint;
ResultRegQualTys.push_back(OutExpr->getType());
ResultRegDests.push_back(Dest);
ResultRegTypes.push_back(ConvertTypeForMem(OutExpr->getType()));
ResultTruncRegTypes.push_back(ResultRegTypes.back());
// If this output is tied to an input, and if the input is larger, then
// we need to set the actual result type of the inline asm node to be the
// same as the input type.
if (Info.hasMatchingInput()) {
unsigned InputNo;
for (InputNo = 0; InputNo != S.getNumInputs(); ++InputNo) {
TargetInfo::ConstraintInfo &Input = InputConstraintInfos[InputNo];
if (Input.hasTiedOperand() && Input.getTiedOperand() == i)
break;
}
assert(InputNo != S.getNumInputs() && "Didn't find matching input!");
QualType InputTy = S.getInputExpr(InputNo)->getType();
QualType OutputType = OutExpr->getType();
uint64_t InputSize = getContext().getTypeSize(InputTy);
if (getContext().getTypeSize(OutputType) < InputSize) {
// Form the asm to return the value as a larger integer or fp type.
ResultRegTypes.back() = ConvertType(InputTy);
}
}
if (llvm::Type* AdjTy =
getTargetHooks().adjustInlineAsmType(*this, OutputConstraint,
ResultRegTypes.back()))
ResultRegTypes.back() = AdjTy;
else {
CGM.getDiags().Report(S.getAsmLoc(),
diag::err_asm_invalid_type_in_input)
<< OutExpr->getType() << OutputConstraint;
}
} else {
ArgTypes.push_back(Dest.getAddress().getType());
Args.push_back(Dest.getPointer());
Constraints += "=*";
Constraints += OutputConstraint;
ReadOnly = ReadNone = false;
}
if (Info.isReadWrite()) {
InOutConstraints += ',';
const Expr *InputExpr = S.getOutputExpr(i);
llvm::Value *Arg = EmitAsmInputLValue(Info, Dest, InputExpr->getType(),
InOutConstraints,
InputExpr->getExprLoc());
if (llvm::Type* AdjTy =
getTargetHooks().adjustInlineAsmType(*this, OutputConstraint,
Arg->getType()))
Arg = Builder.CreateBitCast(Arg, AdjTy);
if (Info.allowsRegister())
InOutConstraints += llvm::utostr(i);
else
InOutConstraints += OutputConstraint;
InOutArgTypes.push_back(Arg->getType());
InOutArgs.push_back(Arg);
}
}
// If this is a Microsoft-style asm blob, store the return registers (EAX:EDX)
// to the return value slot. Only do this when returning in registers.
if (isa<MSAsmStmt>(&S)) {
const ABIArgInfo &RetAI = CurFnInfo->getReturnInfo();
if (RetAI.isDirect() || RetAI.isExtend()) {
// Make a fake lvalue for the return value slot.
LValue ReturnSlot = MakeAddrLValue(ReturnValue, FnRetTy);
CGM.getTargetCodeGenInfo().addReturnRegisterOutputs(
*this, ReturnSlot, Constraints, ResultRegTypes, ResultTruncRegTypes,
ResultRegDests, AsmString, S.getNumOutputs());
SawAsmBlock = true;
}
}
for (unsigned i = 0, e = S.getNumInputs(); i != e; i++) {
const Expr *InputExpr = S.getInputExpr(i);
TargetInfo::ConstraintInfo &Info = InputConstraintInfos[i];
if (Info.allowsMemory())
ReadNone = false;
if (!Constraints.empty())
Constraints += ',';
// Simplify the input constraint.
std::string InputConstraint(S.getInputConstraint(i));
InputConstraint = SimplifyConstraint(InputConstraint.c_str(), getTarget(),
&OutputConstraintInfos);
InputConstraint = AddVariableConstraints(
InputConstraint, *InputExpr->IgnoreParenNoopCasts(getContext()),
getTarget(), CGM, S, false /* No EarlyClobber */);
llvm::Value *Arg = EmitAsmInput(Info, InputExpr, Constraints);
// If this input argument is tied to a larger output result, extend the
// input to be the same size as the output. The LLVM backend wants to see
// the input and output of a matching constraint be the same size. Note
// that GCC does not define what the top bits are here. We use zext because
// that is usually cheaper, but LLVM IR should really get an anyext someday.
if (Info.hasTiedOperand()) {
unsigned Output = Info.getTiedOperand();
QualType OutputType = S.getOutputExpr(Output)->getType();
QualType InputTy = InputExpr->getType();
if (getContext().getTypeSize(OutputType) >
getContext().getTypeSize(InputTy)) {
// Use ptrtoint as appropriate so that we can do our extension.
if (isa<llvm::PointerType>(Arg->getType()))
Arg = Builder.CreatePtrToInt(Arg, IntPtrTy);
llvm::Type *OutputTy = ConvertType(OutputType);
if (isa<llvm::IntegerType>(OutputTy))
Arg = Builder.CreateZExt(Arg, OutputTy);
else if (isa<llvm::PointerType>(OutputTy))
Arg = Builder.CreateZExt(Arg, IntPtrTy);
else {
assert(OutputTy->isFloatingPointTy() && "Unexpected output type");
Arg = Builder.CreateFPExt(Arg, OutputTy);
}
}
}
if (llvm::Type* AdjTy =
getTargetHooks().adjustInlineAsmType(*this, InputConstraint,
Arg->getType()))
Arg = Builder.CreateBitCast(Arg, AdjTy);
else
CGM.getDiags().Report(S.getAsmLoc(), diag::err_asm_invalid_type_in_input)
<< InputExpr->getType() << InputConstraint;
ArgTypes.push_back(Arg->getType());
Args.push_back(Arg);
Constraints += InputConstraint;
}
// Append the "input" part of inout constraints last.
for (unsigned i = 0, e = InOutArgs.size(); i != e; i++) {
ArgTypes.push_back(InOutArgTypes[i]);
Args.push_back(InOutArgs[i]);
}
Constraints += InOutConstraints;
// Clobbers
for (unsigned i = 0, e = S.getNumClobbers(); i != e; i++) {
StringRef Clobber = S.getClobber(i);
if (Clobber == "memory")
ReadOnly = ReadNone = false;
else if (Clobber != "cc")
Clobber = getTarget().getNormalizedGCCRegisterName(Clobber);
if (!Constraints.empty())
Constraints += ',';
Constraints += "~{";
Constraints += Clobber;
Constraints += '}';
}
// Add machine specific clobbers
std::string MachineClobbers = getTarget().getClobbers();
if (!MachineClobbers.empty()) {
if (!Constraints.empty())
Constraints += ',';
Constraints += MachineClobbers;
}
llvm::Type *ResultType;
if (ResultRegTypes.empty())
ResultType = VoidTy;
else if (ResultRegTypes.size() == 1)
ResultType = ResultRegTypes[0];
else
ResultType = llvm::StructType::get(getLLVMContext(), ResultRegTypes);
llvm::FunctionType *FTy =
llvm::FunctionType::get(ResultType, ArgTypes, false);
bool HasSideEffect = S.isVolatile() || S.getNumOutputs() == 0;
llvm::InlineAsm::AsmDialect AsmDialect = isa<MSAsmStmt>(&S) ?
llvm::InlineAsm::AD_Intel : llvm::InlineAsm::AD_ATT;
llvm::InlineAsm *IA =
llvm::InlineAsm::get(FTy, AsmString, Constraints, HasSideEffect,
/* IsAlignStack */ false, AsmDialect);
llvm::CallInst *Result = Builder.CreateCall(IA, Args);
Result->addAttribute(llvm::AttributeSet::FunctionIndex,
llvm::Attribute::NoUnwind);
// Attach readnone and readonly attributes.
if (!HasSideEffect) {
if (ReadNone)
Result->addAttribute(llvm::AttributeSet::FunctionIndex,
llvm::Attribute::ReadNone);
else if (ReadOnly)
Result->addAttribute(llvm::AttributeSet::FunctionIndex,
llvm::Attribute::ReadOnly);
}
// Slap the source location of the inline asm into a !srcloc metadata on the
// call.
if (const GCCAsmStmt *gccAsmStmt = dyn_cast<GCCAsmStmt>(&S)) {
Result->setMetadata("srcloc", getAsmSrcLocInfo(gccAsmStmt->getAsmString(),
*this));
} else {
// At least put the line number on MS inline asm blobs.
auto Loc = llvm::ConstantInt::get(Int32Ty, S.getAsmLoc().getRawEncoding());
Result->setMetadata("srcloc",
llvm::MDNode::get(getLLVMContext(),
llvm::ConstantAsMetadata::get(Loc)));
}
// Extract all of the register value results from the asm.
std::vector<llvm::Value*> RegResults;
if (ResultRegTypes.size() == 1) {
RegResults.push_back(Result);
} else {
for (unsigned i = 0, e = ResultRegTypes.size(); i != e; ++i) {
llvm::Value *Tmp = Builder.CreateExtractValue(Result, i, "asmresult");
RegResults.push_back(Tmp);
}
}
assert(RegResults.size() == ResultRegTypes.size());
assert(RegResults.size() == ResultTruncRegTypes.size());
assert(RegResults.size() == ResultRegDests.size());
for (unsigned i = 0, e = RegResults.size(); i != e; ++i) {
llvm::Value *Tmp = RegResults[i];
// If the result type of the LLVM IR asm doesn't match the result type of
// the expression, do the conversion.
if (ResultRegTypes[i] != ResultTruncRegTypes[i]) {
llvm::Type *TruncTy = ResultTruncRegTypes[i];
// Truncate the integer result to the right size, note that TruncTy can be
// a pointer.
if (TruncTy->isFloatingPointTy())
Tmp = Builder.CreateFPTrunc(Tmp, TruncTy);
else if (TruncTy->isPointerTy() && Tmp->getType()->isIntegerTy()) {
uint64_t ResSize = CGM.getDataLayout().getTypeSizeInBits(TruncTy);
Tmp = Builder.CreateTrunc(Tmp,
llvm::IntegerType::get(getLLVMContext(), (unsigned)ResSize));
Tmp = Builder.CreateIntToPtr(Tmp, TruncTy);
} else if (Tmp->getType()->isPointerTy() && TruncTy->isIntegerTy()) {
uint64_t TmpSize =CGM.getDataLayout().getTypeSizeInBits(Tmp->getType());
Tmp = Builder.CreatePtrToInt(Tmp,
llvm::IntegerType::get(getLLVMContext(), (unsigned)TmpSize));
Tmp = Builder.CreateTrunc(Tmp, TruncTy);
} else if (TruncTy->isIntegerTy()) {
Tmp = Builder.CreateTrunc(Tmp, TruncTy);
} else if (TruncTy->isVectorTy()) {
Tmp = Builder.CreateBitCast(Tmp, TruncTy);
}
}
EmitStoreThroughLValue(RValue::get(Tmp), ResultRegDests[i]);
}
}
LValue CodeGenFunction::InitCapturedStruct(const CapturedStmt &S) {
const RecordDecl *RD = S.getCapturedRecordDecl();
QualType RecordTy = getContext().getRecordType(RD);
// Initialize the captured struct.
LValue SlotLV =
MakeAddrLValue(CreateMemTemp(RecordTy, "agg.captured"), RecordTy);
RecordDecl::field_iterator CurField = RD->field_begin();
for (CapturedStmt::const_capture_init_iterator I = S.capture_init_begin(),
E = S.capture_init_end();
I != E; ++I, ++CurField) {
LValue LV = EmitLValueForFieldInitialization(SlotLV, *CurField);
if (CurField->hasCapturedVLAType()) {
auto VAT = CurField->getCapturedVLAType();
EmitStoreThroughLValue(RValue::get(VLASizeMap[VAT->getSizeExpr()]), LV);
} else {
EmitInitializerForField(*CurField, LV, *I, None);
}
}
return SlotLV;
}
/// Generate an outlined function for the body of a CapturedStmt, store any
/// captured variables into the captured struct, and call the outlined function.
llvm::Function *
CodeGenFunction::EmitCapturedStmt(const CapturedStmt &S, CapturedRegionKind K) {
LValue CapStruct = InitCapturedStruct(S);
// Emit the CapturedDecl
CodeGenFunction CGF(CGM, true);
CGCapturedStmtRAII CapInfoRAII(CGF, new CGCapturedStmtInfo(S, K));
llvm::Function *F = CGF.GenerateCapturedStmtFunction(S);
delete CGF.CapturedStmtInfo;
// Emit call to the helper function.
EmitCallOrInvoke(F, CapStruct.getPointer());
return F;
}
Address CodeGenFunction::GenerateCapturedStmtArgument(const CapturedStmt &S) {
LValue CapStruct = InitCapturedStruct(S);
return CapStruct.getAddress();
}
/// Creates the outlined function for a CapturedStmt.
llvm::Function *
CodeGenFunction::GenerateCapturedStmtFunction(const CapturedStmt &S) {
assert(CapturedStmtInfo &&
"CapturedStmtInfo should be set when generating the captured function");
const CapturedDecl *CD = S.getCapturedDecl();
const RecordDecl *RD = S.getCapturedRecordDecl();
SourceLocation Loc = S.getLocStart();
assert(CD->hasBody() && "missing CapturedDecl body");
// Build the argument list.
ASTContext &Ctx = CGM.getContext();
FunctionArgList Args;
Args.append(CD->param_begin(), CD->param_end());
// Create the function declaration.
FunctionType::ExtInfo ExtInfo;
const CGFunctionInfo &FuncInfo =
CGM.getTypes().arrangeFreeFunctionDeclaration(Ctx.VoidTy, Args, ExtInfo,
/*IsVariadic=*/false);
llvm::FunctionType *FuncLLVMTy = CGM.getTypes().GetFunctionType(FuncInfo);
llvm::Function *F =
llvm::Function::Create(FuncLLVMTy, llvm::GlobalValue::InternalLinkage,
CapturedStmtInfo->getHelperName(), &CGM.getModule());
CGM.SetInternalFunctionAttributes(CD, F, FuncInfo);
if (CD->isNothrow())
F->addFnAttr(llvm::Attribute::NoUnwind);
// Generate the function.
StartFunction(CD, Ctx.VoidTy, F, FuncInfo, Args,
CD->getLocation(),
CD->getBody()->getLocStart());
// Set the context parameter in CapturedStmtInfo.
Address DeclPtr = GetAddrOfLocalVar(CD->getContextParam());
CapturedStmtInfo->setContextValue(Builder.CreateLoad(DeclPtr));
// Initialize variable-length arrays.
LValue Base = MakeNaturalAlignAddrLValue(CapturedStmtInfo->getContextValue(),
Ctx.getTagDeclType(RD));
for (auto *FD : RD->fields()) {
if (FD->hasCapturedVLAType()) {
auto *ExprArg = EmitLoadOfLValue(EmitLValueForField(Base, FD),
S.getLocStart()).getScalarVal();
auto VAT = FD->getCapturedVLAType();
VLASizeMap[VAT->getSizeExpr()] = ExprArg;
}
}
// If 'this' is captured, load it into CXXThisValue.
if (CapturedStmtInfo->isCXXThisExprCaptured()) {
FieldDecl *FD = CapturedStmtInfo->getThisFieldDecl();
LValue ThisLValue = EmitLValueForField(Base, FD);
CXXThisValue = EmitLoadOfLValue(ThisLValue, Loc).getScalarVal();
}
PGO.assignRegionCounters(CD, F);
CapturedStmtInfo->EmitBody(*this, CD->getBody());
FinishFunction(CD->getBodyRBrace());
return F;
}
More information about the llvm-commits
mailing list