summaryrefslogtreecommitdiffstats
path: root/include/clang/AST/Expr.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/clang/AST/Expr.h')
-rw-r--r--include/clang/AST/Expr.h518
1 files changed, 365 insertions, 153 deletions
diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h
index 3de7342882..ce9c5266f0 100644
--- a/include/clang/AST/Expr.h
+++ b/include/clang/AST/Expr.h
@@ -1,9 +1,8 @@
//===--- 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.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -23,11 +22,14 @@
#include "clang/AST/TemplateBase.h"
#include "clang/AST/Type.h"
#include "clang/Basic/CharInfo.h"
+#include "clang/Basic/FixedPoint.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/SyncScope.h"
#include "clang/Basic/TypeTraits.h"
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/APSInt.h"
+#include "llvm/ADT/iterator.h"
+#include "llvm/ADT/iterator_range.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/AtomicOrdering.h"
@@ -103,13 +105,13 @@ struct SubobjectAdjustment {
/// 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 {
+class Expr : public ValueStmt {
QualType TR;
protected:
Expr(StmtClass SC, QualType T, ExprValueKind VK, ExprObjectKind OK,
bool TD, bool VD, bool ID, bool ContainsUnexpandedParameterPack)
- : Stmt(SC)
+ : ValueStmt(SC)
{
ExprBits.TypeDependent = TD;
ExprBits.ValueDependent = VD;
@@ -122,7 +124,7 @@ protected:
}
/// Construct an empty expression.
- explicit Expr(StmtClass SC, EmptyShell) : Stmt(SC) { }
+ explicit Expr(StmtClass SC, EmptyShell) : ValueStmt(SC) { }
public:
QualType getType() const { return TR; }
@@ -611,6 +613,12 @@ public:
EvaluateAsFloat(llvm::APFloat &Result, const ASTContext &Ctx,
SideEffectsKind AllowSideEffects = SE_NoSideEffects) const;
+ /// EvaluateAsFloat - Return true if this is a constant which we can fold and
+ /// convert to a fixed point value.
+ bool EvaluateAsFixedPoint(
+ EvalResult &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,
@@ -738,67 +746,110 @@ public:
/// member expression.
static QualType findBoundMemberType(const Expr *expr);
- /// IgnoreImpCasts - Skip past any implicit casts which might
- /// surround this expression. Only skips ImplicitCastExprs.
+ /// Skip past any implicit casts which might surround this expression until
+ /// reaching a fixed point. Skips:
+ /// * ImplicitCastExpr
+ /// * FullExpr
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();
+ const Expr *IgnoreImpCasts() const {
+ return const_cast<Expr *>(this)->IgnoreImpCasts();
}
- /// 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.
+ /// Skip past any casts which might surround this expression until reaching
+ /// a fixed point. Skips:
+ /// * CastExpr
+ /// * FullExpr
+ /// * MaterializeTemporaryExpr
+ /// * SubstNonTypeTemplateParmExpr
Expr *IgnoreCasts() LLVM_READONLY;
-
- /// IgnoreParenImpCasts - Ignore parentheses and implicit casts. Strip off
- /// any ParenExpr or ImplicitCastExprs, returning their operand.
+ const Expr *IgnoreCasts() const {
+ return const_cast<Expr *>(this)->IgnoreCasts();
+ }
+
+ /// Skip past any implicit AST nodes which might surround this expression
+ /// until reaching a fixed point. Skips:
+ /// * What IgnoreImpCasts() skips
+ /// * MaterializeTemporaryExpr
+ /// * CXXBindTemporaryExpr
+ Expr *IgnoreImplicit() LLVM_READONLY;
+ const Expr *IgnoreImplicit() const {
+ return const_cast<Expr *>(this)->IgnoreImplicit();
+ }
+
+ /// Skip past any parentheses which might surround this expression until
+ /// reaching a fixed point. Skips:
+ /// * ParenExpr
+ /// * UnaryOperator if `UO_Extension`
+ /// * GenericSelectionExpr if `!isResultDependent()`
+ /// * ChooseExpr if `!isConditionDependent()`
+ /// * ConstantExpr
+ Expr *IgnoreParens() LLVM_READONLY;
+ const Expr *IgnoreParens() const {
+ return const_cast<Expr *>(this)->IgnoreParens();
+ }
+
+ /// Skip past any parentheses and implicit casts which might surround this
+ /// expression until reaching a fixed point.
+ /// FIXME: IgnoreParenImpCasts really ought to be equivalent to
+ /// IgnoreParens() + IgnoreImpCasts() until reaching a fixed point. However
+ /// this is currently not the case. Instead IgnoreParenImpCasts() skips:
+ /// * What IgnoreParens() skips
+ /// * What IgnoreImpCasts() skips
+ /// * MaterializeTemporaryExpr
+ /// * SubstNonTypeTemplateParmExpr
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 {
+ return const_cast<Expr *>(this)->IgnoreParenImpCasts();
}
- const Expr *IgnoreParenImpCasts() const LLVM_READONLY {
- return const_cast<Expr*>(this)->IgnoreParenImpCasts();
+ /// Skip past any parentheses and casts which might surround this expression
+ /// until reaching a fixed point. Skips:
+ /// * What IgnoreParens() skips
+ /// * What IgnoreCasts() skips
+ Expr *IgnoreParenCasts() LLVM_READONLY;
+ const Expr *IgnoreParenCasts() const {
+ return const_cast<Expr *>(this)->IgnoreParenCasts();
}
- /// Ignore parentheses and lvalue casts. Strip off any ParenExpr and
- /// CastExprs that represent lvalue casts, returning their operand.
+ /// Skip conversion operators. If this Expr is a call to a conversion
+ /// operator, return the argument.
+ Expr *IgnoreConversionOperator() LLVM_READONLY;
+ const Expr *IgnoreConversionOperator() const {
+ return const_cast<Expr *>(this)->IgnoreConversionOperator();
+ }
+
+ /// Skip past any parentheses and lvalue casts which might surround this
+ /// expression until reaching a fixed point. Skips:
+ /// * What IgnoreParens() skips
+ /// * What IgnoreCasts() skips, except that only lvalue-to-rvalue
+ /// casts are skipped
+ /// FIXME: 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 *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.
+ const Expr *IgnoreParenLValueCasts() const {
+ return const_cast<Expr *>(this)->IgnoreParenLValueCasts();
+ }
+
+ /// Skip past any parenthese and casts which do not change the value
+ /// (including ptr->int casts of the same size) until reaching a fixed point.
+ /// Skips:
+ /// * What IgnoreParens() skips
+ /// * CastExpr which do not change the value
+ /// * SubstNonTypeTemplateParmExpr
+ Expr *IgnoreParenNoopCasts(const ASTContext &Ctx) LLVM_READONLY;
+ const Expr *IgnoreParenNoopCasts(const ASTContext &Ctx) const {
+ return const_cast<Expr *>(this)->IgnoreParenNoopCasts(Ctx);
+ }
+
+ /// Skip past any parentheses and derived-to-base casts until reaching a
+ /// fixed point. Skips:
+ /// * What IgnoreParens() skips
+ /// * CastExpr which represent a derived-to-base cast (CK_DerivedToBase,
+ /// CK_UncheckedDerivedToBase and CK_NoOp)
Expr *ignoreParenBaseCasts() LLVM_READONLY;
-
- const Expr *ignoreParenBaseCasts() const LLVM_READONLY {
- return const_cast<Expr*>(this)->ignoreParenBaseCasts();
+ const Expr *ignoreParenBaseCasts() const {
+ return const_cast<Expr *>(this)->ignoreParenBaseCasts();
}
/// Determine whether this expression is a default function argument.
@@ -817,24 +868,6 @@ public:
/// 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);
/// For an expression of class type or pointer to class type,
@@ -1837,6 +1870,11 @@ public:
return child_range(getTrailingObjects<Stmt *>(),
getTrailingObjects<Stmt *>() + hasFunctionName());
}
+
+ const_child_range children() const {
+ return const_child_range(getTrailingObjects<Stmt *>(),
+ getTrailingObjects<Stmt *>() + hasFunctionName());
+ }
};
/// ParenExpr - This represents a parethesized expression, e.g. "(1)". This
@@ -2577,6 +2615,11 @@ public:
NumArgs = NewNumArgs;
}
+ /// Bluntly set a new number of arguments without doing any checks whatsoever.
+ /// Only used during construction of a CallExpr in a few places in Sema.
+ /// FIXME: Find a way to remove it.
+ void setNumArgsUnsafe(unsigned NewNumArgs) { NumArgs = NewNumArgs; }
+
typedef ExprIterator arg_iterator;
typedef ConstExprIterator const_arg_iterator;
typedef llvm::iterator_range<arg_iterator> arg_range;
@@ -3159,18 +3202,6 @@ public:
friend class CastExpr;
};
-inline Expr *Expr::IgnoreImpCasts() {
- Expr *e = this;
- while (true)
- if (ImplicitCastExpr *ice = dyn_cast<ImplicitCastExpr>(e))
- e = ice->getSubExpr();
- else if (FullExpr *fe = dyn_cast<FullExpr>(e))
- e = fe->getSubExpr();
- else
- break;
- return e;
-}
-
/// ExplicitCastExpr - An explicit cast written in the source
/// code.
///
@@ -3377,6 +3408,9 @@ public:
static bool isComparisonOp(Opcode Opc) { return Opc >= BO_Cmp && Opc<=BO_NE; }
bool isComparisonOp() const { return isComparisonOp(getOpcode()); }
+ static bool isCommaOp(Opcode Opc) { return Opc == BO_Comma; }
+ bool isCommaOp() const { return isCommaOp(getOpcode()); }
+
static Opcode negateComparisonOp(Opcode Opc) {
switch (Opc) {
default:
@@ -5007,99 +5041,277 @@ public:
/// 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;
+class GenericSelectionExpr final
+ : public Expr,
+ private llvm::TrailingObjects<GenericSelectionExpr, Stmt *,
+ TypeSourceInfo *> {
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
+ friend TrailingObjects;
+
+ /// The number of association expressions and the index of the result
+ /// expression in the case where the generic selection expression is not
+ /// result-dependent. The result index is equal to ResultDependentIndex
+ /// if and only if the generic selection expression is result-dependent.
unsigned NumAssocs, ResultIndex;
- SourceLocation GenericLoc, DefaultLoc, RParenLoc;
+ enum : unsigned {
+ ResultDependentIndex = std::numeric_limits<unsigned>::max(),
+ ControllingIndex = 0,
+ AssocExprStartIndex = 1
+ };
-public:
- GenericSelectionExpr(const ASTContext &Context,
- SourceLocation GenericLoc, Expr *ControllingExpr,
- ArrayRef<TypeSourceInfo*> AssocTypes,
- ArrayRef<Expr*> AssocExprs,
- SourceLocation DefaultLoc, SourceLocation RParenLoc,
+ /// The location of the "default" and of the right parenthesis.
+ SourceLocation DefaultLoc, RParenLoc;
+
+ // GenericSelectionExpr is followed by several trailing objects.
+ // They are (in order):
+ //
+ // * A single Stmt * for the controlling expression.
+ // * An array of getNumAssocs() Stmt * for the association expressions.
+ // * An array of getNumAssocs() TypeSourceInfo *, one for each of the
+ // association expressions.
+ unsigned numTrailingObjects(OverloadToken<Stmt *>) const {
+ // Add one to account for the controlling expression; the remainder
+ // are the associated expressions.
+ return 1 + getNumAssocs();
+ }
+
+ unsigned numTrailingObjects(OverloadToken<TypeSourceInfo *>) const {
+ return getNumAssocs();
+ }
+
+ template <bool Const> class AssociationIteratorTy;
+ /// Bundle together an association expression and its TypeSourceInfo.
+ /// The Const template parameter is for the const and non-const versions
+ /// of AssociationTy.
+ template <bool Const> class AssociationTy {
+ friend class GenericSelectionExpr;
+ template <bool OtherConst> friend class AssociationIteratorTy;
+ using ExprPtrTy =
+ typename std::conditional<Const, const Expr *, Expr *>::type;
+ using TSIPtrTy = typename std::conditional<Const, const TypeSourceInfo *,
+ TypeSourceInfo *>::type;
+ ExprPtrTy E;
+ TSIPtrTy TSI;
+ bool Selected;
+ AssociationTy(ExprPtrTy E, TSIPtrTy TSI, bool Selected)
+ : E(E), TSI(TSI), Selected(Selected) {}
+
+ public:
+ ExprPtrTy getAssociationExpr() const { return E; }
+ TSIPtrTy getTypeSourceInfo() const { return TSI; }
+ QualType getType() const { return TSI ? TSI->getType() : QualType(); }
+ bool isSelected() const { return Selected; }
+ AssociationTy *operator->() { return this; }
+ const AssociationTy *operator->() const { return this; }
+ }; // class AssociationTy
+
+ /// Iterator over const and non-const Association objects. The Association
+ /// objects are created on the fly when the iterator is dereferenced.
+ /// This abstract over how exactly the association expressions and the
+ /// corresponding TypeSourceInfo * are stored.
+ template <bool Const>
+ class AssociationIteratorTy
+ : public llvm::iterator_facade_base<
+ AssociationIteratorTy<Const>, std::input_iterator_tag,
+ AssociationTy<Const>, std::ptrdiff_t, AssociationTy<Const>,
+ AssociationTy<Const>> {
+ friend class GenericSelectionExpr;
+ // FIXME: This iterator could conceptually be a random access iterator, and
+ // it would be nice if we could strengthen the iterator category someday.
+ // However this iterator does not satisfy two requirements of forward
+ // iterators:
+ // a) reference = T& or reference = const T&
+ // b) If It1 and It2 are both dereferenceable, then It1 == It2 if and only
+ // if *It1 and *It2 are bound to the same objects.
+ // An alternative design approach was discussed during review;
+ // store an Association object inside the iterator, and return a reference
+ // to it when dereferenced. This idea was discarded beacuse of nasty
+ // lifetime issues:
+ // AssociationIterator It = ...;
+ // const Association &Assoc = *It++; // Oops, Assoc is dangling.
+ using BaseTy = typename AssociationIteratorTy::iterator_facade_base;
+ using StmtPtrPtrTy =
+ typename std::conditional<Const, const Stmt *const *, Stmt **>::type;
+ using TSIPtrPtrTy =
+ typename std::conditional<Const, const TypeSourceInfo *const *,
+ TypeSourceInfo **>::type;
+ StmtPtrPtrTy E; // = nullptr; FIXME: Once support for gcc 4.8 is dropped.
+ TSIPtrPtrTy TSI; // Kept in sync with E.
+ unsigned Offset = 0, SelectedOffset = 0;
+ AssociationIteratorTy(StmtPtrPtrTy E, TSIPtrPtrTy TSI, unsigned Offset,
+ unsigned SelectedOffset)
+ : E(E), TSI(TSI), Offset(Offset), SelectedOffset(SelectedOffset) {}
+
+ public:
+ AssociationIteratorTy() : E(nullptr), TSI(nullptr) {}
+ typename BaseTy::reference operator*() const {
+ return AssociationTy<Const>(cast<Expr>(*E), *TSI,
+ Offset == SelectedOffset);
+ }
+ typename BaseTy::pointer operator->() const { return **this; }
+ using BaseTy::operator++;
+ AssociationIteratorTy &operator++() {
+ ++E;
+ ++TSI;
+ ++Offset;
+ return *this;
+ }
+ bool operator==(AssociationIteratorTy Other) const { return E == Other.E; }
+ }; // class AssociationIterator
+
+ /// Build a non-result-dependent generic selection expression.
+ 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,
+ /// Build a result-dependent generic selection expression.
+ 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) { }
+ /// Build an empty generic selection expression for deserialization.
+ explicit GenericSelectionExpr(EmptyShell Empty, unsigned NumAssocs);
+public:
+ /// Create a non-result-dependent generic selection expression.
+ static GenericSelectionExpr *
+ Create(const ASTContext &Context, SourceLocation GenericLoc,
+ Expr *ControllingExpr, ArrayRef<TypeSourceInfo *> AssocTypes,
+ ArrayRef<Expr *> AssocExprs, SourceLocation DefaultLoc,
+ SourceLocation RParenLoc, bool ContainsUnexpandedParameterPack,
+ unsigned ResultIndex);
+
+ /// Create a result-dependent generic selection expression.
+ static GenericSelectionExpr *
+ Create(const ASTContext &Context, SourceLocation GenericLoc,
+ Expr *ControllingExpr, ArrayRef<TypeSourceInfo *> AssocTypes,
+ ArrayRef<Expr *> AssocExprs, SourceLocation DefaultLoc,
+ SourceLocation RParenLoc, bool ContainsUnexpandedParameterPack);
+
+ /// Create an empty generic selection expression for deserialization.
+ static GenericSelectionExpr *CreateEmpty(const ASTContext &Context,
+ unsigned NumAssocs);
+
+ using Association = AssociationTy<false>;
+ using ConstAssociation = AssociationTy<true>;
+ using AssociationIterator = AssociationIteratorTy<false>;
+ using ConstAssociationIterator = AssociationIteratorTy<true>;
+ using association_range = llvm::iterator_range<AssociationIterator>;
+ using const_association_range =
+ llvm::iterator_range<ConstAssociationIterator>;
+
+ /// The number of association expressions.
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]); }
- ArrayRef<Expr *> getAssocExprs() const {
- return NumAssocs
- ? llvm::makeArrayRef(
- &reinterpret_cast<Expr **>(SubExprs)[END_EXPR], NumAssocs)
- : None;
- }
- const TypeSourceInfo *getAssocTypeSourceInfo(unsigned i) const {
- return AssocTypes[i];
- }
- TypeSourceInfo *getAssocTypeSourceInfo(unsigned i) { return AssocTypes[i]; }
- ArrayRef<TypeSourceInfo *> getAssocTypeSourceInfos() const {
- return NumAssocs ? llvm::makeArrayRef(&AssocTypes[0], NumAssocs) : None;
- }
-
- 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");
+ assert(!isResultDependent() &&
+ "Generic selection is result-dependent but getResultIndex called!");
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()); }
+ /// Whether this generic selection is result-dependent.
+ bool isResultDependent() const { return ResultIndex == ResultDependentIndex; }
- SourceLocation getBeginLoc() const LLVM_READONLY { return GenericLoc; }
- SourceLocation getEndLoc() const LLVM_READONLY { return RParenLoc; }
+ /// Return the controlling expression of this generic selection expression.
+ Expr *getControllingExpr() {
+ return cast<Expr>(getTrailingObjects<Stmt *>()[ControllingIndex]);
+ }
+ const Expr *getControllingExpr() const {
+ return cast<Expr>(getTrailingObjects<Stmt *>()[ControllingIndex]);
+ }
+
+ /// Return the result expression of this controlling expression. Defined if
+ /// and only if the generic selection expression is not result-dependent.
+ Expr *getResultExpr() {
+ return cast<Expr>(
+ getTrailingObjects<Stmt *>()[AssocExprStartIndex + getResultIndex()]);
+ }
+ const Expr *getResultExpr() const {
+ return cast<Expr>(
+ getTrailingObjects<Stmt *>()[AssocExprStartIndex + getResultIndex()]);
+ }
+
+ ArrayRef<Expr *> getAssocExprs() const {
+ return {reinterpret_cast<Expr *const *>(getTrailingObjects<Stmt *>() +
+ AssocExprStartIndex),
+ NumAssocs};
+ }
+ ArrayRef<TypeSourceInfo *> getAssocTypeSourceInfos() const {
+ return {getTrailingObjects<TypeSourceInfo *>(), NumAssocs};
+ }
+
+ /// Return the Ith association expression with its TypeSourceInfo,
+ /// bundled together in GenericSelectionExpr::(Const)Association.
+ Association getAssociation(unsigned I) {
+ assert(I < getNumAssocs() &&
+ "Out-of-range index in GenericSelectionExpr::getAssociation!");
+ return Association(
+ cast<Expr>(getTrailingObjects<Stmt *>()[AssocExprStartIndex + I]),
+ getTrailingObjects<TypeSourceInfo *>()[I],
+ !isResultDependent() && (getResultIndex() == I));
+ }
+ ConstAssociation getAssociation(unsigned I) const {
+ assert(I < getNumAssocs() &&
+ "Out-of-range index in GenericSelectionExpr::getAssociation!");
+ return ConstAssociation(
+ cast<Expr>(getTrailingObjects<Stmt *>()[AssocExprStartIndex + I]),
+ getTrailingObjects<TypeSourceInfo *>()[I],
+ !isResultDependent() && (getResultIndex() == I));
+ }
+
+ association_range associations() {
+ AssociationIterator Begin(getTrailingObjects<Stmt *>() +
+ AssocExprStartIndex,
+ getTrailingObjects<TypeSourceInfo *>(),
+ /*Offset=*/0, ResultIndex);
+ AssociationIterator End(Begin.E + NumAssocs, Begin.TSI + NumAssocs,
+ /*Offset=*/NumAssocs, ResultIndex);
+ return llvm::make_range(Begin, End);
+ }
+
+ const_association_range associations() const {
+ ConstAssociationIterator Begin(getTrailingObjects<Stmt *>() +
+ AssocExprStartIndex,
+ getTrailingObjects<TypeSourceInfo *>(),
+ /*Offset=*/0, ResultIndex);
+ ConstAssociationIterator End(Begin.E + NumAssocs, Begin.TSI + NumAssocs,
+ /*Offset=*/NumAssocs, ResultIndex);
+ return llvm::make_range(Begin, End);
+ }
+
+ SourceLocation getGenericLoc() const {
+ return GenericSelectionExprBits.GenericLoc;
+ }
+ SourceLocation getDefaultLoc() const { return DefaultLoc; }
+ SourceLocation getRParenLoc() const { return RParenLoc; }
+ SourceLocation getBeginLoc() const { return getGenericLoc(); }
+ SourceLocation getEndLoc() const { return getRParenLoc(); }
static bool classof(const Stmt *T) {
return T->getStmtClass() == GenericSelectionExprClass;
}
child_range children() {
- return child_range(SubExprs, SubExprs+END_EXPR+NumAssocs);
+ return child_range(getTrailingObjects<Stmt *>(),
+ getTrailingObjects<Stmt *>() +
+ numTrailingObjects(OverloadToken<Stmt *>()));
}
const_child_range children() const {
- return const_child_range(SubExprs, SubExprs + END_EXPR + NumAssocs);
+ return const_child_range(getTrailingObjects<Stmt *>(),
+ getTrailingObjects<Stmt *>() +
+ numTrailingObjects(OverloadToken<Stmt *>()));
}
- friend class ASTStmtReader;
};
//===----------------------------------------------------------------------===//