aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/clang/include/clang/AST/Expr.h
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/clang/include/clang/AST/Expr.h')
-rw-r--r--contrib/llvm-project/clang/include/clang/AST/Expr.h908
1 files changed, 555 insertions, 353 deletions
diff --git a/contrib/llvm-project/clang/include/clang/AST/Expr.h b/contrib/llvm-project/clang/include/clang/AST/Expr.h
index 8efa8fdbe2bb..9820bd11da86 100644
--- a/contrib/llvm-project/clang/include/clang/AST/Expr.h
+++ b/contrib/llvm-project/clang/include/clang/AST/Expr.h
@@ -13,6 +13,7 @@
#ifndef LLVM_CLANG_AST_EXPR_H
#define LLVM_CLANG_AST_EXPR_H
+#include "clang/AST/APNumericStorage.h"
#include "clang/AST/APValue.h"
#include "clang/AST/ASTVector.h"
#include "clang/AST/ComputeDependence.h"
@@ -36,6 +37,7 @@
#include "llvm/Support/AtomicOrdering.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/TrailingObjects.h"
+#include <optional>
namespace clang {
class APValue;
@@ -134,8 +136,8 @@ protected:
void setDependence(ExprDependence Deps) {
ExprBits.Dependent = static_cast<unsigned>(Deps);
}
- friend class ASTImporter; // Sets dependence dircetly.
- friend class ASTStmtReader; // Sets dependence dircetly.
+ friend class ASTImporter; // Sets dependence directly.
+ friend class ASTStmtReader; // Sets dependence directly.
public:
QualType getType() const { return TR; }
@@ -170,7 +172,7 @@ public:
}
/// Determines whether the type of this expression depends on
- /// - a template paramter (C++ [temp.dep.expr], which means that its type
+ /// - a template parameter (C++ [temp.dep.expr], which means that its type
/// could change from one template instantiation to the next)
/// - or an error
///
@@ -523,15 +525,25 @@ public:
/// semantically correspond to a bool.
bool isKnownToHaveBooleanValue(bool Semantic = true) const;
+ /// Check whether this array fits the idiom of a flexible array member,
+ /// depending on the value of -fstrict-flex-array.
+ /// When IgnoreTemplateOrMacroSubstitution is set, it doesn't consider sizes
+ /// resulting from the substitution of a macro or a template as special sizes.
+ bool isFlexibleArrayMemberLike(
+ ASTContext &Context,
+ LangOptions::StrictFlexArraysLevelKind StrictFlexArraysLevel,
+ bool IgnoreTemplateOrMacroSubstitution = false) const;
+
/// isIntegerConstantExpr - Return the value if this expression is a valid
- /// integer constant expression. If not a valid i-c-e, return None and fill
- /// in Loc (if specified) with the location of the invalid expression.
+ /// integer constant expression. If not a valid i-c-e, return std::nullopt
+ /// 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.
- Optional<llvm::APSInt> getIntegerConstantExpr(const ASTContext &Ctx,
- SourceLocation *Loc = nullptr,
- bool isEvaluated = true) const;
+ std::optional<llvm::APSInt>
+ getIntegerConstantExpr(const ASTContext &Ctx,
+ SourceLocation *Loc = nullptr) const;
bool isIntegerConstantExpr(const ASTContext &Ctx,
SourceLocation *Loc = nullptr) const;
@@ -555,7 +567,7 @@ public:
SmallVectorImpl<
PartialDiagnosticAt> &Diags);
- /// isPotentialConstantExprUnevaluted - Return true if this expression might
+ /// isPotentialConstantExprUnevaluated - 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
@@ -572,16 +584,22 @@ public:
bool isConstantInitializer(ASTContext &Ctx, bool ForRef,
const Expr **Culprit = nullptr) const;
+ /// If this expression is an unambiguous reference to a single declaration,
+ /// in the style of __builtin_function_start, return that declaration. Note
+ /// that this may return a non-static member function or field in C++ if this
+ /// expression is a member pointer constant.
+ const ValueDecl *getAsBuiltinConstantDeclRef(const ASTContext &Context) const;
+
/// EvalStatus is a struct with detailed info about an evaluation in progress.
struct EvalStatus {
/// Whether the evaluated expression has side effects.
/// For example, (f() && 0) can be folded, but it still has side effects.
- bool HasSideEffects;
+ bool HasSideEffects = false;
/// Whether the evaluation hit undefined behavior.
/// For example, 1.0 / 0.0 can be folded to Inf, but has undefined behavior.
/// Likewise, INT_MAX + 1 can be folded to INT_MIN, but has UB.
- bool HasUndefinedBehavior;
+ bool HasUndefinedBehavior = false;
/// 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
@@ -590,10 +608,16 @@ public:
/// 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;
+ ///
+ /// FIXME: this causes significant performance concerns and should be
+ /// refactored at some point. Not all evaluations of the constant
+ /// expression interpreter will display the given diagnostics, this means
+ /// those kinds of uses are paying the expense of generating a diagnostic
+ /// (which may include expensive operations like converting APValue objects
+ /// to a string representation).
+ SmallVectorImpl<PartialDiagnosticAt> *Diag = nullptr;
- EvalStatus()
- : HasSideEffects(false), HasUndefinedBehavior(false), Diag(nullptr) {}
+ EvalStatus() = default;
// hasSideEffects - Return true if the evaluated expression has
// side effects.
@@ -648,8 +672,8 @@ public:
SideEffectsKind AllowSideEffects = SE_NoSideEffects,
bool InConstantContext = false) const;
- /// EvaluateAsFloat - Return true if this is a constant which we can fold and
- /// convert to a fixed point value.
+ /// EvaluateAsFixedPoint - 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,
bool InConstantContext = false) const;
@@ -697,7 +721,8 @@ public:
/// 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;
+ SmallVectorImpl<PartialDiagnosticAt> &Notes,
+ bool IsConstantInitializer) const;
/// EvaluateWithSubstitution - Evaluate an expression as if from the context
/// of a call to the given function with the given arguments, inside an
@@ -739,6 +764,17 @@ public:
bool tryEvaluateObjectSize(uint64_t &Result, ASTContext &Ctx,
unsigned Type) const;
+ /// If the current Expr is a pointer, this will try to statically
+ /// determine the strlen of the string pointed to.
+ /// Returns true if all of the above holds and we were able to figure out the
+ /// strlen, false otherwise.
+ bool tryEvaluateStrLen(uint64_t &Result, ASTContext &Ctx) const;
+
+ bool EvaluateCharRangeAsString(std::string &Result,
+ const Expr *SizeExpression,
+ const Expr *PtrExpression, ASTContext &Ctx,
+ EvalResult &Status) const;
+
/// Enumeration used to describe the kind of Null pointer constant
/// returned from \c isNullPointerConstant().
enum NullPointerConstantKind {
@@ -796,7 +832,7 @@ public:
/// member expression.
static QualType findBoundMemberType(const Expr *expr);
- /// Skip past any invisble AST nodes which might surround this
+ /// Skip past any invisible AST nodes which might surround this
/// statement, such as ExprWithCleanups or ImplicitCastExpr nodes,
/// but also injected CXXMemberExpr and CXXConstructExpr which represent
/// implicit conversions.
@@ -900,7 +936,7 @@ public:
return const_cast<Expr *>(this)->IgnoreParenLValueCasts();
}
- /// Skip past any parenthese and casts which do not change the value
+ /// Skip past any parentheses 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
@@ -1014,6 +1050,9 @@ public:
}
};
+/// Describes the kind of result that can be tail-allocated.
+enum class ConstantResultStorageKind { None, Int64, APValue };
+
/// ConstantExpr - An expression that occurs in a constant context and
/// optionally the result of evaluating the expression.
class ConstantExpr final
@@ -1026,20 +1065,15 @@ class ConstantExpr final
friend class ASTStmtReader;
friend class ASTStmtWriter;
-public:
- /// Describes the kind of result that can be tail-allocated.
- enum ResultStorageKind { RSK_None, RSK_Int64, RSK_APValue };
-
-private:
size_t numTrailingObjects(OverloadToken<APValue>) const {
- return ConstantExprBits.ResultKind == ConstantExpr::RSK_APValue;
+ return getResultStorageKind() == ConstantResultStorageKind::APValue;
}
size_t numTrailingObjects(OverloadToken<uint64_t>) const {
- return ConstantExprBits.ResultKind == ConstantExpr::RSK_Int64;
+ return getResultStorageKind() == ConstantResultStorageKind::Int64;
}
uint64_t &Int64Result() {
- assert(ConstantExprBits.ResultKind == ConstantExpr::RSK_Int64 &&
+ assert(getResultStorageKind() == ConstantResultStorageKind::Int64 &&
"invalid accessor");
return *getTrailingObjects<uint64_t>();
}
@@ -1047,7 +1081,7 @@ private:
return const_cast<ConstantExpr *>(this)->Int64Result();
}
APValue &APValueResult() {
- assert(ConstantExprBits.ResultKind == ConstantExpr::RSK_APValue &&
+ assert(getResultStorageKind() == ConstantResultStorageKind::APValue &&
"invalid accessor");
return *getTrailingObjects<APValue>();
}
@@ -1055,22 +1089,23 @@ private:
return const_cast<ConstantExpr *>(this)->APValueResult();
}
- ConstantExpr(Expr *SubExpr, ResultStorageKind StorageKind,
+ ConstantExpr(Expr *SubExpr, ConstantResultStorageKind StorageKind,
bool IsImmediateInvocation);
- ConstantExpr(EmptyShell Empty, ResultStorageKind StorageKind);
+ ConstantExpr(EmptyShell Empty, ConstantResultStorageKind StorageKind);
public:
static ConstantExpr *Create(const ASTContext &Context, Expr *E,
const APValue &Result);
- static ConstantExpr *Create(const ASTContext &Context, Expr *E,
- ResultStorageKind Storage = RSK_None,
- bool IsImmediateInvocation = false);
+ static ConstantExpr *
+ Create(const ASTContext &Context, Expr *E,
+ ConstantResultStorageKind Storage = ConstantResultStorageKind::None,
+ bool IsImmediateInvocation = false);
static ConstantExpr *CreateEmpty(const ASTContext &Context,
- ResultStorageKind StorageKind);
+ ConstantResultStorageKind StorageKind);
- static ResultStorageKind getStorageKind(const APValue &Value);
- static ResultStorageKind getStorageKind(const Type *T,
- const ASTContext &Context);
+ static ConstantResultStorageKind getStorageKind(const APValue &Value);
+ static ConstantResultStorageKind getStorageKind(const Type *T,
+ const ASTContext &Context);
SourceLocation getBeginLoc() const LLVM_READONLY {
return SubExpr->getBeginLoc();
@@ -1091,8 +1126,8 @@ public:
APValue::ValueKind getResultAPValueKind() const {
return static_cast<APValue::ValueKind>(ConstantExprBits.APValueKind);
}
- ResultStorageKind getResultStorageKind() const {
- return static_cast<ResultStorageKind>(ConstantExprBits.ResultKind);
+ ConstantResultStorageKind getResultStorageKind() const {
+ return static_cast<ConstantResultStorageKind>(ConstantExprBits.ResultKind);
}
bool isImmediateInvocation() const {
return ConstantExprBits.IsImmediateInvocation;
@@ -1101,7 +1136,6 @@ public:
return ConstantExprBits.APValueKind != APValue::None;
}
APValue getAPValueResult() const;
- APValue &getResultAsAPValue() const { return APValueResult(); }
llvm::APSInt getResultAsAPSInt() const;
// Iterators
child_range children() { return child_range(&SubExpr, &SubExpr+1); }
@@ -1413,68 +1447,35 @@ public:
return DeclRefExprBits.RefersToEnclosingVariableOrCapture;
}
- static bool classof(const Stmt *T) {
- return T->getStmtClass() == DeclRefExprClass;
+ bool isImmediateEscalating() const {
+ return DeclRefExprBits.IsImmediateEscalating;
}
- // Iterators
- child_range children() {
- return child_range(child_iterator(), child_iterator());
+ void setIsImmediateEscalating(bool Set) {
+ DeclRefExprBits.IsImmediateEscalating = Set;
}
- const_child_range children() const {
- return const_child_range(const_child_iterator(), const_child_iterator());
+ bool isCapturedByCopyInLambdaWithExplicitObjectParameter() const {
+ return DeclRefExprBits.CapturedByCopyInLambdaWithExplicitObjectParameter;
}
-};
-/// 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 setCapturedByCopyInLambdaWithExplicitObjectParameter(
+ bool Set, const ASTContext &Context) {
+ DeclRefExprBits.CapturedByCopyInLambdaWithExplicitObjectParameter = Set;
+ setDependence(computeDependence(this, Context));
}
- 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);
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == DeclRefExprClass;
}
-};
-class APFloatStorage : private APNumericStorage {
-public:
- llvm::APFloat getValue(const llvm::fltSemantics &Semantics) const {
- return llvm::APFloat(Semantics, getIntValue());
+ // Iterators
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
}
- void setValue(const ASTContext &C, const llvm::APFloat &Val) {
- setIntValue(C, Val.bitcastToAPInt());
+
+ const_child_range children() const {
+ return const_child_range(const_child_iterator(), const_child_iterator());
}
};
@@ -1568,26 +1569,18 @@ class FixedPointLiteral : public Expr, public APIntStorage {
}
};
-class CharacterLiteral : public Expr {
-public:
- enum CharacterKind {
- Ascii,
- Wide,
- UTF8,
- UTF16,
- UTF32
- };
+enum class CharacterLiteralKind { Ascii, Wide, UTF8, UTF16, UTF32 };
-private:
+class CharacterLiteral : public Expr {
unsigned Value;
SourceLocation Loc;
public:
// type should be IntTy
- CharacterLiteral(unsigned value, CharacterKind kind, QualType type,
+ CharacterLiteral(unsigned value, CharacterLiteralKind kind, QualType type,
SourceLocation l)
: Expr(CharacterLiteralClass, type, VK_PRValue, OK_Ordinary),
Value(value), Loc(l) {
- CharacterLiteralBits.Kind = kind;
+ CharacterLiteralBits.Kind = llvm::to_underlying(kind);
setDependence(ExprDependence::None);
}
@@ -1595,8 +1588,8 @@ public:
CharacterLiteral(EmptyShell Empty) : Expr(CharacterLiteralClass, Empty) { }
SourceLocation getLocation() const { return Loc; }
- CharacterKind getKind() const {
- return static_cast<CharacterKind>(CharacterLiteralBits.Kind);
+ CharacterLiteralKind getKind() const {
+ return static_cast<CharacterLiteralKind>(CharacterLiteralBits.Kind);
}
SourceLocation getBeginLoc() const LLVM_READONLY { return Loc; }
@@ -1605,14 +1598,16 @@ public:
unsigned getValue() const { return Value; }
void setLocation(SourceLocation Location) { Loc = Location; }
- void setKind(CharacterKind kind) { CharacterLiteralBits.Kind = kind; }
+ void setKind(CharacterLiteralKind kind) {
+ CharacterLiteralBits.Kind = llvm::to_underlying(kind);
+ }
void setValue(unsigned Val) { Value = Val; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == CharacterLiteralClass;
}
- static void print(unsigned val, CharacterKind Kind, raw_ostream &OS);
+ static void print(unsigned val, CharacterLiteralKind Kind, raw_ostream &OS);
// Iterators
child_range children() {
@@ -1734,6 +1729,15 @@ public:
}
};
+enum class StringLiteralKind {
+ Ordinary,
+ Wide,
+ UTF8,
+ UTF16,
+ UTF32,
+ Unevaluated
+};
+
/// StringLiteral - This represents a string literal expression, e.g. "foo"
/// or L"bar" (wide strings). The actual string data can be obtained with
/// getBytes() and is NOT null-terminated. The length of the string data is
@@ -1772,10 +1776,6 @@ class StringLiteral final
///
/// * An array of getByteLength() char used to store the string data.
-public:
- enum StringKind { Ascii, Wide, UTF8, UTF16, UTF32 };
-
-private:
unsigned numTrailingObjects(OverloadToken<unsigned>) const { return 1; }
unsigned numTrailingObjects(OverloadToken<SourceLocation>) const {
return getNumConcatenated();
@@ -1797,7 +1797,7 @@ private:
}
/// Build a string literal.
- StringLiteral(const ASTContext &Ctx, StringRef Str, StringKind Kind,
+ StringLiteral(const ASTContext &Ctx, StringRef Str, StringLiteralKind Kind,
bool Pascal, QualType Ty, const SourceLocation *Loc,
unsigned NumConcatenated);
@@ -1806,7 +1806,8 @@ private:
unsigned CharByteWidth);
/// Map a target and string kind to the appropriate character width.
- static unsigned mapCharByteWidth(TargetInfo const &Target, StringKind SK);
+ static unsigned mapCharByteWidth(TargetInfo const &Target,
+ StringLiteralKind SK);
/// Set one of the string literal token.
void setStrTokenLoc(unsigned TokNum, SourceLocation L) {
@@ -1818,13 +1819,13 @@ public:
/// This is the "fully general" constructor that allows representation of
/// strings formed from multiple concatenated tokens.
static StringLiteral *Create(const ASTContext &Ctx, StringRef Str,
- StringKind Kind, bool Pascal, QualType Ty,
+ StringLiteralKind Kind, bool Pascal, QualType Ty,
const SourceLocation *Loc,
unsigned NumConcatenated);
/// Simple constructor for string literals made from one token.
static StringLiteral *Create(const ASTContext &Ctx, StringRef Str,
- StringKind Kind, bool Pascal, QualType Ty,
+ StringLiteralKind Kind, bool Pascal, QualType Ty,
SourceLocation Loc) {
return Create(Ctx, Str, Kind, Pascal, Ty, &Loc, 1);
}
@@ -1835,7 +1836,7 @@ public:
unsigned CharByteWidth);
StringRef getString() const {
- assert(getCharByteWidth() == 1 &&
+ assert((isUnevaluated() || getCharByteWidth() == 1) &&
"This function is used in places that assume strings use char");
return StringRef(getStrDataAsChar(), getByteLength());
}
@@ -1866,15 +1867,16 @@ public:
unsigned getLength() const { return *getTrailingObjects<unsigned>(); }
unsigned getCharByteWidth() const { return StringLiteralBits.CharByteWidth; }
- StringKind getKind() const {
- return static_cast<StringKind>(StringLiteralBits.Kind);
+ StringLiteralKind getKind() const {
+ return static_cast<StringLiteralKind>(StringLiteralBits.Kind);
}
- bool isAscii() const { return getKind() == Ascii; }
- bool isWide() const { return getKind() == Wide; }
- bool isUTF8() const { return getKind() == UTF8; }
- bool isUTF16() const { return getKind() == UTF16; }
- bool isUTF32() const { return getKind() == UTF32; }
+ bool isOrdinary() const { return getKind() == StringLiteralKind::Ordinary; }
+ bool isWide() const { return getKind() == StringLiteralKind::Wide; }
+ bool isUTF8() const { return getKind() == StringLiteralKind::UTF8; }
+ bool isUTF16() const { return getKind() == StringLiteralKind::UTF16; }
+ bool isUTF32() const { return getKind() == StringLiteralKind::UTF32; }
+ bool isUnevaluated() const { return getKind() == StringLiteralKind::Unevaluated; }
bool isPascal() const { return StringLiteralBits.IsPascal; }
bool containsNonAscii() const {
@@ -1942,6 +1944,19 @@ public:
}
};
+enum class PredefinedIdentKind {
+ Func,
+ Function,
+ LFunction, // Same as Function, but as wide string.
+ FuncDName,
+ FuncSig,
+ LFuncSig, // Same as FuncSig, but as wide string
+ PrettyFunction,
+ /// The same as PrettyFunction, except that the
+ /// 'virtual' keyword is omitted for virtual member functions.
+ PrettyFunctionNoVirtual
+};
+
/// [C99 6.4.2.2] - A predefined identifier such as __func__.
class PredefinedExpr final
: public Expr,
@@ -1953,23 +1968,8 @@ class PredefinedExpr final
// "Stmt *" for the predefined identifier. It is present if and only if
// hasFunctionName() is true and is always a "StringLiteral *".
-public:
- enum IdentKind {
- Func,
- Function,
- LFunction, // Same as Function, but as wide string.
- FuncDName,
- FuncSig,
- LFuncSig, // Same as FuncSig, but as as wide string
- PrettyFunction,
- /// The same as PrettyFunction, except that the
- /// 'virtual' keyword is omitted for virtual member functions.
- PrettyFunctionNoVirtual
- };
-
-private:
- PredefinedExpr(SourceLocation L, QualType FNTy, IdentKind IK,
- StringLiteral *SL);
+ PredefinedExpr(SourceLocation L, QualType FNTy, PredefinedIdentKind IK,
+ bool IsTransparent, StringLiteral *SL);
explicit PredefinedExpr(EmptyShell Empty, bool HasFunctionName);
@@ -1984,17 +1984,23 @@ private:
public:
/// Create a PredefinedExpr.
+ ///
+ /// If IsTransparent, the PredefinedExpr is transparently handled as a
+ /// StringLiteral.
static PredefinedExpr *Create(const ASTContext &Ctx, SourceLocation L,
- QualType FNTy, IdentKind IK, StringLiteral *SL);
+ QualType FNTy, PredefinedIdentKind IK,
+ bool IsTransparent, StringLiteral *SL);
/// Create an empty PredefinedExpr.
static PredefinedExpr *CreateEmpty(const ASTContext &Ctx,
bool HasFunctionName);
- IdentKind getIdentKind() const {
- return static_cast<IdentKind>(PredefinedExprBits.Kind);
+ PredefinedIdentKind getIdentKind() const {
+ return static_cast<PredefinedIdentKind>(PredefinedExprBits.Kind);
}
+ bool isTransparent() const { return PredefinedExprBits.IsTransparent; }
+
SourceLocation getLocation() const { return PredefinedExprBits.Loc; }
void setLocation(SourceLocation L) { PredefinedExprBits.Loc = L; }
@@ -2010,12 +2016,13 @@ public:
: nullptr;
}
- static StringRef getIdentKindName(IdentKind IK);
+ static StringRef getIdentKindName(PredefinedIdentKind IK);
StringRef getIdentKindName() const {
return getIdentKindName(getIdentKind());
}
- static std::string ComputeName(IdentKind IK, const Decl *CurrentDecl);
+ static std::string ComputeName(PredefinedIdentKind IK,
+ const Decl *CurrentDecl);
SourceLocation getBeginLoc() const { return getLocation(); }
SourceLocation getEndLoc() const { return getLocation(); }
@@ -2210,14 +2217,14 @@ public:
bool canOverflow() const { return UnaryOperatorBits.CanOverflow; }
void setCanOverflow(bool C) { UnaryOperatorBits.CanOverflow = C; }
- // Get the FP contractability status of this operator. Only meaningful for
- // operations on floating point types.
+ /// Get the FP contractability status of this operator. Only meaningful for
+ /// operations on floating point types.
bool isFPContractableWithinStatement(const LangOptions &LO) const {
return getFPFeaturesInEffect(LO).allowFPContractWithinStatement();
}
- // Get the FENV_ACCESS status of this operator. Only meaningful for
- // operations on floating point types.
+ /// Get the FENV_ACCESS status of this operator. Only meaningful for
+ /// operations on floating point types.
bool isFEnvAccessOn(const LangOptions &LO) const {
return getFPFeaturesInEffect(LO).getAllowFEnvAccess();
}
@@ -2298,12 +2305,12 @@ public:
}
protected:
- /// Set FPFeatures in trailing storage, used only by Serialization
+ /// Set FPFeatures in trailing storage, used by Serialization & ASTImporter.
void setStoredFPFeatures(FPOptionsOverride F) { getTrailingFPFeatures() = F; }
public:
- // Get the FP features status of this operator. Only meaningful for
- // operations on floating point types.
+ /// Get the FP features status of this operator. Only meaningful for
+ /// operations on floating point types.
FPOptions getFPFeaturesInEffect(const LangOptions &LO) const {
if (UnaryOperatorBits.HasFPFeatures)
return getStoredFPFeatures().applyOverrides(LO);
@@ -2316,6 +2323,7 @@ public:
}
friend TrailingObjects;
+ friend class ASTNodeImporter;
friend class ASTReader;
friend class ASTStmtReader;
friend class ASTStmtWriter;
@@ -2375,7 +2383,7 @@ public:
/// 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) {}
+ : Data(reinterpret_cast<uintptr_t>(Base) | OffsetOfNode::Base) {}
/// Determine what kind of offsetof node this is.
Kind getKind() const { return static_cast<Kind>(Data & Mask); }
@@ -2791,7 +2799,7 @@ class CallExpr : public Expr {
/// The number of arguments in the call expression.
unsigned NumArgs;
- /// The location of the right parenthese. This has a different meaning for
+ /// The location of the right parentheses. This has a different meaning for
/// the derived classes of CallExpr.
SourceLocation RParenLoc;
@@ -2997,7 +3005,7 @@ public:
/// Compute and set dependence bits.
void computeDependence() {
setDependence(clang::computeDependence(
- this, llvm::makeArrayRef(
+ this, llvm::ArrayRef(
reinterpret_cast<Expr **>(getTrailingStmts() + PREARGS_START),
getNumPreArgs())));
}
@@ -3044,14 +3052,10 @@ public:
/// interface. This provides efficient reverse iteration of the
/// subexpressions. This is currently used for CFG construction.
ArrayRef<Stmt *> getRawSubExprs() {
- return llvm::makeArrayRef(getTrailingStmts(),
- PREARGS_START + getNumPreArgs() + getNumArgs());
+ return llvm::ArrayRef(getTrailingStmts(),
+ PREARGS_START + getNumPreArgs() + getNumArgs());
}
- /// getNumCommas - Return the number of commas that must have been present in
- /// this function call.
- unsigned getNumCommas() const { return getNumArgs() ? getNumArgs() - 1 : 0; }
-
/// Get FPOptionsOverride from trailing storage.
FPOptionsOverride getStoredFPFeatures() const {
assert(hasStoredFPFeatures());
@@ -3063,8 +3067,8 @@ public:
*getTrailingFPFeatures() = F;
}
- // Get the FP features status of this operator. Only meaningful for
- // operations on floating point types.
+ /// Get the FP features status of this operator. Only meaningful for
+ /// operations on floating point types.
FPOptions getFPFeaturesInEffect(const LangOptions &LO) const {
if (hasStoredFPFeatures())
return getStoredFPFeatures().applyOverrides(LO);
@@ -3115,11 +3119,7 @@ public:
setDependence(getDependence() | ExprDependence::TypeValueInstantiation);
}
- bool isCallToStdMove() const {
- const FunctionDecl *FD = getDirectCallee();
- return getNumArgs() == 1 && FD && FD->isInStdNamespace() &&
- FD->getIdentifier() && FD->getIdentifier()->isStr("move");
- }
+ bool isCallToStdMove() const;
static bool classof(const Stmt *T) {
return T->getStmtClass() >= firstCallExprConstant &&
@@ -3484,7 +3484,6 @@ protected:
CastExprBits.BasePathSize = BasePathSize;
assert((CastExprBits.BasePathSize == BasePathSize) &&
"BasePathSize overflow!");
- setDependence(computeDependence(this));
assert(CastConsistency());
CastExprBits.HasFPFeatures = HasFPFeatures;
}
@@ -3559,8 +3558,8 @@ public:
return *getTrailingFPFeatures();
}
- // Get the FP features status of this operation. Only meaningful for
- // operations on floating point types.
+ /// Get the FP features status of this operation. Only meaningful for
+ /// operations on floating point types.
FPOptions getFPFeaturesInEffect(const LangOptions &LO) const {
if (hasStoredFPFeatures())
return getStoredFPFeatures().applyOverrides(LO);
@@ -3573,6 +3572,19 @@ public:
return FPOptionsOverride();
}
+ /// Return
+ // True : if this conversion changes the volatile-ness of a gl-value.
+ // Qualification conversions on gl-values currently use CK_NoOp, but
+ // it's important to recognize volatile-changing conversions in
+ // clients code generation that normally eagerly peephole loads. Note
+ // that the query is answering for this specific node; Sema may
+ // produce multiple cast nodes for any particular conversion sequence.
+ // False : Otherwise.
+ bool changesVolatileQualification() const {
+ return (isGLValue() && (getType().isVolatileQualified() !=
+ getSubExpr()->getType().isVolatileQualified()));
+ }
+
static const FieldDecl *getTargetFieldForToUnionCast(QualType unionType,
QualType opType);
static const FieldDecl *getTargetFieldForToUnionCast(const RecordDecl *RD,
@@ -3618,6 +3630,7 @@ class ImplicitCastExpr final
ExprValueKind VK)
: CastExpr(ImplicitCastExprClass, ty, VK, kind, op, BasePathLength,
FPO.requiresTrailingStorage()) {
+ setDependence(computeDependence(this));
if (hasStoredFPFeatures())
*getTrailingFPFeatures() = FPO;
}
@@ -3695,7 +3708,9 @@ protected:
CastKind kind, Expr *op, unsigned PathSize,
bool HasFPFeatures, TypeSourceInfo *writtenTy)
: CastExpr(SC, exprTy, VK, kind, op, PathSize, HasFPFeatures),
- TInfo(writtenTy) {}
+ TInfo(writtenTy) {
+ setDependence(computeDependence(this));
+ }
/// Construct an empty explicit cast.
ExplicitCastExpr(StmtClass SC, EmptyShell Shell, unsigned PathSize,
@@ -3954,11 +3969,12 @@ public:
return isShiftAssignOp(getOpcode());
}
- // Return true if a binary operator using the specified opcode and operands
- // would match the 'p = (i8*)nullptr + n' idiom for casting a pointer-sized
- // integer to a pointer.
+ /// Return true if a binary operator using the specified opcode and operands
+ /// would match the 'p = (i8*)nullptr + n' idiom for casting a pointer-sized
+ /// integer to a pointer.
static bool isNullPointerArithmeticExtension(ASTContext &Ctx, Opcode Opc,
- Expr *LHS, Expr *RHS);
+ const Expr *LHS,
+ const Expr *RHS);
static bool classof(const Stmt *S) {
return S->getStmtClass() >= firstBinaryOperatorConstant &&
@@ -3989,8 +4005,8 @@ public:
*getTrailingFPFeatures() = F;
}
- // Get the FP features status of this operator. Only meaningful for
- // operations on floating point types.
+ /// Get the FP features status of this operator. Only meaningful for
+ /// operations on floating point types.
FPOptions getFPFeaturesInEffect(const LangOptions &LO) const {
if (BinaryOperatorBits.HasFPFeatures)
return getStoredFPFeatures().applyOverrides(LO);
@@ -3998,20 +4014,20 @@ public:
}
// This is used in ASTImporter
- FPOptionsOverride getFPFeatures(const LangOptions &LO) const {
+ FPOptionsOverride getFPFeatures() const {
if (BinaryOperatorBits.HasFPFeatures)
return getStoredFPFeatures();
return FPOptionsOverride();
}
- // Get the FP contractability status of this operator. Only meaningful for
- // operations on floating point types.
+ /// Get the FP contractability status of this operator. Only meaningful for
+ /// operations on floating point types.
bool isFPContractableWithinStatement(const LangOptions &LO) const {
return getFPFeaturesInEffect(LO).allowFPContractWithinStatement();
}
- // Get the FENV_ACCESS status of this operator. Only meaningful for
- // operations on floating point types.
+ /// Get the FENV_ACCESS status of this operator. Only meaningful for
+ /// operations on floating point types.
bool isFEnvAccessOn(const LangOptions &LO) const {
return getFPFeaturesInEffect(LO).getAllowFEnvAccess();
}
@@ -4107,17 +4123,17 @@ protected:
: Expr(SC, Empty) { }
public:
- // getCond - Return the expression representing the condition for
- // the ?: operator.
+ /// 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.
+ /// 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.
+ /// 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; }
@@ -4152,17 +4168,17 @@ public:
explicit ConditionalOperator(EmptyShell Empty)
: AbstractConditionalOperator(ConditionalOperatorClass, Empty) { }
- // getCond - Return the expression representing the condition for
- // the ?: operator.
+ /// 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.
+ /// 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.
+ /// 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]); }
@@ -4666,16 +4682,26 @@ public:
}
};
+enum class SourceLocIdentKind {
+ Function,
+ FuncSig,
+ File,
+ FileName,
+ Line,
+ Column,
+ SourceLocStruct
+};
+
/// Represents a function call to one of __builtin_LINE(), __builtin_COLUMN(),
-/// __builtin_FUNCTION(), or __builtin_FILE().
+/// __builtin_FUNCTION(), __builtin_FUNCSIG(), __builtin_FILE(),
+/// __builtin_FILE_NAME() or __builtin_source_location().
class SourceLocExpr final : public Expr {
SourceLocation BuiltinLoc, RParenLoc;
DeclContext *ParentContext;
public:
- enum IdentKind { Function, File, Line, Column };
-
- SourceLocExpr(const ASTContext &Ctx, IdentKind Type, SourceLocation BLoc,
+ SourceLocExpr(const ASTContext &Ctx, SourceLocIdentKind Type,
+ QualType ResultTy, SourceLocation BLoc,
SourceLocation RParenLoc, DeclContext *Context);
/// Build an empty call expression.
@@ -4689,22 +4715,24 @@ public:
/// Return a string representing the name of the specific builtin function.
StringRef getBuiltinStr() const;
- IdentKind getIdentKind() const {
- return static_cast<IdentKind>(SourceLocExprBits.Kind);
+ SourceLocIdentKind getIdentKind() const {
+ return static_cast<SourceLocIdentKind>(SourceLocExprBits.Kind);
}
- bool isStringType() const {
+ bool isIntType() const {
switch (getIdentKind()) {
- case File:
- case Function:
- return true;
- case Line:
- case Column:
+ case SourceLocIdentKind::File:
+ case SourceLocIdentKind::FileName:
+ case SourceLocIdentKind::Function:
+ case SourceLocIdentKind::FuncSig:
+ case SourceLocIdentKind::SourceLocStruct:
return false;
+ case SourceLocIdentKind::Line:
+ case SourceLocIdentKind::Column:
+ return true;
}
llvm_unreachable("unknown source location expression kind");
}
- bool isIntType() const LLVM_READONLY { return !isStringType(); }
/// If the SourceLocExpr has been resolved return the subexpression
/// representing the resolved value. Otherwise return null.
@@ -4727,6 +4755,17 @@ public:
return T->getStmtClass() == SourceLocExprClass;
}
+ static bool MayBeDependent(SourceLocIdentKind Kind) {
+ switch (Kind) {
+ case SourceLocIdentKind::Function:
+ case SourceLocIdentKind::FuncSig:
+ case SourceLocIdentKind::SourceLocStruct:
+ return true;
+ default:
+ return false;
+ }
+ }
+
private:
friend class ASTStmtReader;
};
@@ -4816,12 +4855,10 @@ public:
return reinterpret_cast<Expr * const *>(InitExprs.data());
}
- ArrayRef<Expr *> inits() {
- return llvm::makeArrayRef(getInits(), getNumInits());
- }
+ ArrayRef<Expr *> inits() { return llvm::ArrayRef(getInits(), getNumInits()); }
ArrayRef<Expr *> inits() const {
- return llvm::makeArrayRef(getInits(), getNumInits());
+ return llvm::ArrayRef(getInits(), getNumInits());
}
const Expr *getInit(unsigned Init) const {
@@ -4884,6 +4921,13 @@ public:
/// has been set.
bool hasArrayFiller() const { return getArrayFiller(); }
+ /// Determine whether this initializer list contains a designated initializer.
+ bool hasDesignatedInit() const {
+ return std::any_of(begin(), end(), [](const Stmt *S) {
+ return isa<DesignatedInitExpr>(S);
+ });
+ }
+
/// If this initializes a union, specifies which field in the
/// union to initialize.
///
@@ -4912,8 +4956,8 @@ public:
return LBraceLoc.isValid() && RBraceLoc.isValid();
}
- // Is this an initializer for an array of characters, initialized by a string
- // literal or an @encode?
+ /// Is this an initializer for an array of characters, initialized by a string
+ /// literal or an @encode?
bool isStringLiteralInit() const;
/// Is this a transparent initializer list (that is, an InitListExpr that is
@@ -5028,6 +5072,7 @@ private:
/// Whether this designated initializer used the GNU deprecated
/// syntax rather than the C99 '=' syntax.
+ LLVM_PREFERRED_TYPE(bool)
unsigned GNUSyntax : 1;
/// The number of designators in this initializer expression.
@@ -5052,37 +5097,6 @@ private:
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.
- SourceLocation DotLoc;
-
- /// The location of the field name in the designated initializer.
- SourceLocation 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.
- SourceLocation LBracketLoc;
- /// The location of the ellipsis separating the start and end
- /// indices. Only valid for GNU array-range designators.
- SourceLocation EllipsisLoc;
- /// The location of the ']' terminating the array range designator.
- SourceLocation RBracketLoc;
- };
-
/// Represents a single C99 designator.
///
/// @todo This class is infuriatingly similar to clang::Designator,
@@ -5090,118 +5104,177 @@ public:
/// keep us from reusing it. Try harder, later, to rectify these
/// differences.
class Designator {
+ /// A field designator, e.g., ".x".
+ struct FieldDesignatorInfo {
+ /// 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.
+ SourceLocation DotLoc;
+
+ /// The location of the field name in the designated initializer.
+ SourceLocation FieldLoc;
+
+ FieldDesignatorInfo(const IdentifierInfo *II, SourceLocation DotLoc,
+ SourceLocation FieldLoc)
+ : NameOrField(reinterpret_cast<uintptr_t>(II) | 0x1), DotLoc(DotLoc),
+ FieldLoc(FieldLoc) {}
+ };
+
+ /// An array or GNU array-range designator, e.g., "[9]" or "[10...15]".
+ struct ArrayOrRangeDesignatorInfo {
+ /// 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.
+ SourceLocation LBracketLoc;
+
+ /// The location of the ellipsis separating the start and end
+ /// indices. Only valid for GNU array-range designators.
+ SourceLocation EllipsisLoc;
+
+ /// The location of the ']' terminating the array range designator.
+ SourceLocation RBracketLoc;
+
+ ArrayOrRangeDesignatorInfo(unsigned Index, SourceLocation LBracketLoc,
+ SourceLocation RBracketLoc)
+ : Index(Index), LBracketLoc(LBracketLoc), RBracketLoc(RBracketLoc) {}
+
+ ArrayOrRangeDesignatorInfo(unsigned Index,
+ SourceLocation LBracketLoc,
+ SourceLocation EllipsisLoc,
+ SourceLocation RBracketLoc)
+ : Index(Index), LBracketLoc(LBracketLoc), EllipsisLoc(EllipsisLoc),
+ RBracketLoc(RBracketLoc) {}
+ };
+
/// The kind of designator this describes.
- enum {
+ enum DesignatorKind {
FieldDesignator,
ArrayDesignator,
ArrayRangeDesignator
- } Kind;
+ };
+
+ DesignatorKind Kind;
union {
/// A field designator, e.g., ".x".
- struct FieldDesignator Field;
+ struct FieldDesignatorInfo FieldInfo;
+
/// An array or GNU array-range designator, e.g., "[9]" or "[10..15]".
- struct ArrayOrRangeDesignator ArrayOrRange;
+ struct ArrayOrRangeDesignatorInfo ArrayOrRangeInfo;
};
- friend class DesignatedInitExpr;
+
+ Designator(DesignatorKind Kind) : Kind(Kind) {}
public:
Designator() {}
- /// Initializes a field designator.
- Designator(const IdentifierInfo *FieldName, SourceLocation DotLoc,
- SourceLocation FieldLoc)
- : Kind(FieldDesignator) {
- new (&Field) DesignatedInitExpr::FieldDesignator;
- Field.NameOrField = reinterpret_cast<uintptr_t>(FieldName) | 0x01;
- Field.DotLoc = DotLoc;
- Field.FieldLoc = FieldLoc;
- }
-
- /// Initializes an array designator.
- Designator(unsigned Index, SourceLocation LBracketLoc,
- SourceLocation RBracketLoc)
- : Kind(ArrayDesignator) {
- new (&ArrayOrRange) DesignatedInitExpr::ArrayOrRangeDesignator;
- ArrayOrRange.Index = Index;
- ArrayOrRange.LBracketLoc = LBracketLoc;
- ArrayOrRange.EllipsisLoc = SourceLocation();
- ArrayOrRange.RBracketLoc = RBracketLoc;
- }
-
- /// Initializes a GNU array-range designator.
- Designator(unsigned Index, SourceLocation LBracketLoc,
- SourceLocation EllipsisLoc, SourceLocation RBracketLoc)
- : Kind(ArrayRangeDesignator) {
- new (&ArrayOrRange) DesignatedInitExpr::ArrayOrRangeDesignator;
- ArrayOrRange.Index = Index;
- ArrayOrRange.LBracketLoc = LBracketLoc;
- ArrayOrRange.EllipsisLoc = EllipsisLoc;
- ArrayOrRange.RBracketLoc = RBracketLoc;
- }
-
bool isFieldDesignator() const { return Kind == FieldDesignator; }
bool isArrayDesignator() const { return Kind == ArrayDesignator; }
bool isArrayRangeDesignator() const { return Kind == ArrayRangeDesignator; }
- IdentifierInfo *getFieldName() const;
+ //===------------------------------------------------------------------===//
+ // FieldDesignatorInfo
+
+ /// Creates a field designator.
+ static Designator CreateFieldDesignator(const IdentifierInfo *FieldName,
+ SourceLocation DotLoc,
+ SourceLocation FieldLoc) {
+ Designator D(FieldDesignator);
+ new (&D.FieldInfo) FieldDesignatorInfo(FieldName, DotLoc, FieldLoc);
+ return D;
+ }
- FieldDecl *getField() const {
- assert(Kind == FieldDesignator && "Only valid on a field designator");
- if (Field.NameOrField & 0x01)
+ const IdentifierInfo *getFieldName() const;
+
+ FieldDecl *getFieldDecl() const {
+ assert(isFieldDesignator() && "Only valid on a field designator");
+ if (FieldInfo.NameOrField & 0x01)
return nullptr;
- else
- return reinterpret_cast<FieldDecl *>(Field.NameOrField);
+ return reinterpret_cast<FieldDecl *>(FieldInfo.NameOrField);
}
- void setField(FieldDecl *FD) {
- assert(Kind == FieldDesignator && "Only valid on a field designator");
- Field.NameOrField = reinterpret_cast<uintptr_t>(FD);
+ void setFieldDecl(FieldDecl *FD) {
+ assert(isFieldDesignator() && "Only valid on a field designator");
+ FieldInfo.NameOrField = reinterpret_cast<uintptr_t>(FD);
}
SourceLocation getDotLoc() const {
- assert(Kind == FieldDesignator && "Only valid on a field designator");
- return Field.DotLoc;
+ assert(isFieldDesignator() && "Only valid on a field designator");
+ return FieldInfo.DotLoc;
}
SourceLocation getFieldLoc() const {
- assert(Kind == FieldDesignator && "Only valid on a field designator");
- return Field.FieldLoc;
+ assert(isFieldDesignator() && "Only valid on a field designator");
+ return FieldInfo.FieldLoc;
}
- SourceLocation getLBracketLoc() const {
- assert((Kind == ArrayDesignator || Kind == ArrayRangeDesignator) &&
+ //===------------------------------------------------------------------===//
+ // ArrayOrRangeDesignator
+
+ /// Creates an array designator.
+ static Designator CreateArrayDesignator(unsigned Index,
+ SourceLocation LBracketLoc,
+ SourceLocation RBracketLoc) {
+ Designator D(ArrayDesignator);
+ new (&D.ArrayOrRangeInfo) ArrayOrRangeDesignatorInfo(Index, LBracketLoc,
+ RBracketLoc);
+ return D;
+ }
+
+ /// Creates a GNU array-range designator.
+ static Designator CreateArrayRangeDesignator(unsigned Index,
+ SourceLocation LBracketLoc,
+ SourceLocation EllipsisLoc,
+ SourceLocation RBracketLoc) {
+ Designator D(ArrayRangeDesignator);
+ new (&D.ArrayOrRangeInfo) ArrayOrRangeDesignatorInfo(Index, LBracketLoc,
+ EllipsisLoc,
+ RBracketLoc);
+ return D;
+ }
+
+ unsigned getArrayIndex() const {
+ assert((isArrayDesignator() || isArrayRangeDesignator()) &&
"Only valid on an array or array-range designator");
- return ArrayOrRange.LBracketLoc;
+ return ArrayOrRangeInfo.Index;
}
- SourceLocation getRBracketLoc() const {
- assert((Kind == ArrayDesignator || Kind == ArrayRangeDesignator) &&
+ SourceLocation getLBracketLoc() const {
+ assert((isArrayDesignator() || isArrayRangeDesignator()) &&
"Only valid on an array or array-range designator");
- return ArrayOrRange.RBracketLoc;
+ return ArrayOrRangeInfo.LBracketLoc;
}
SourceLocation getEllipsisLoc() const {
- assert(Kind == ArrayRangeDesignator &&
+ assert(isArrayRangeDesignator() &&
"Only valid on an array-range designator");
- return ArrayOrRange.EllipsisLoc;
+ return ArrayOrRangeInfo.EllipsisLoc;
}
- unsigned getFirstExprIndex() const {
- assert((Kind == ArrayDesignator || Kind == ArrayRangeDesignator) &&
+ SourceLocation getRBracketLoc() const {
+ assert((isArrayDesignator() || isArrayRangeDesignator()) &&
"Only valid on an array or array-range designator");
- return ArrayOrRange.Index;
+ return ArrayOrRangeInfo.RBracketLoc;
}
SourceLocation getBeginLoc() const LLVM_READONLY {
- if (Kind == FieldDesignator)
- return getDotLoc().isInvalid()? getFieldLoc() : getDotLoc();
- else
- return getLBracketLoc();
+ if (isFieldDesignator())
+ return getDotLoc().isInvalid() ? getFieldLoc() : getDotLoc();
+ return getLBracketLoc();
}
+
SourceLocation getEndLoc() const LLVM_READONLY {
- return Kind == FieldDesignator ? getFieldLoc() : getRBracketLoc();
+ return isFieldDesignator() ? getFieldLoc() : getRBracketLoc();
}
+
SourceRange getSourceRange() const LLVM_READONLY {
return SourceRange(getBeginLoc(), getEndLoc());
}
@@ -5563,9 +5636,7 @@ public:
return reinterpret_cast<Expr **>(getTrailingObjects<Stmt *>());
}
- ArrayRef<Expr *> exprs() {
- return llvm::makeArrayRef(getExprs(), getNumExprs());
- }
+ ArrayRef<Expr *> exprs() { return llvm::ArrayRef(getExprs(), getNumExprs()); }
SourceLocation getLParenLoc() const { return LParenLoc; }
SourceLocation getRParenLoc() const { return RParenLoc; }
@@ -5613,6 +5684,12 @@ 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.
+///
+/// We also allow an extended form in both C and C++ where the controlling
+/// predicate for the selection expression is a type rather than an expression.
+/// This type argument form does not perform any conversions for the
+/// controlling type, which makes it suitable for use with qualified type
+/// associations, which is not possible with the expression form.
class GenericSelectionExpr final
: public Expr,
private llvm::TrailingObjects<GenericSelectionExpr, Stmt *,
@@ -5625,31 +5702,68 @@ class GenericSelectionExpr final
/// 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;
+ unsigned NumAssocs : 15;
+ unsigned ResultIndex : 15; // NB: ResultDependentIndex is tied to this width.
+ LLVM_PREFERRED_TYPE(bool)
+ unsigned IsExprPredicate : 1;
enum : unsigned {
- ResultDependentIndex = std::numeric_limits<unsigned>::max(),
- ControllingIndex = 0,
- AssocExprStartIndex = 1
+ ResultDependentIndex = 0x7FFF
};
+ unsigned getIndexOfControllingExpression() const {
+ // If controlled by an expression, the first offset into the Stmt *
+ // trailing array is the controlling expression, the associated expressions
+ // follow this.
+ assert(isExprPredicate() && "Asking for the controlling expression of a "
+ "selection expr predicated by a type");
+ return 0;
+ }
+
+ unsigned getIndexOfControllingType() const {
+ // If controlled by a type, the first offset into the TypeSourceInfo *
+ // trailing array is the controlling type, the associated types follow this.
+ assert(isTypePredicate() && "Asking for the controlling type of a "
+ "selection expr predicated by an expression");
+ return 0;
+ }
+
+ unsigned getIndexOfStartOfAssociatedExprs() const {
+ // If the predicate is a type, then the associated expressions are the only
+ // Stmt * in the trailing array, otherwise we need to offset past the
+ // predicate expression.
+ return (int)isExprPredicate();
+ }
+
+ unsigned getIndexOfStartOfAssociatedTypes() const {
+ // If the predicate is a type, then the associated types follow it in the
+ // trailing array. Otherwise, the associated types are the only
+ // TypeSourceInfo * in the trailing array.
+ return (int)isTypePredicate();
+ }
+
+
/// 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.
+ // * A single Stmt * for the controlling expression or a TypeSourceInfo * for
+ // the controlling type, depending on the result of isTypePredicate() or
+ // isExprPredicate().
// * 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();
+ return getNumAssocs() + (int)isExprPredicate();
}
unsigned numTrailingObjects(OverloadToken<TypeSourceInfo *>) const {
- return getNumAssocs();
+ // Add one to account for the controlling type predicate, the remainder
+ // are the associated types.
+ return getNumAssocs() + (int)isTypePredicate();
}
template <bool Const> class AssociationIteratorTy;
@@ -5730,7 +5844,8 @@ class GenericSelectionExpr final
bool operator==(AssociationIteratorTy Other) const { return E == Other.E; }
}; // class AssociationIterator
- /// Build a non-result-dependent generic selection expression.
+ /// Build a non-result-dependent generic selection expression accepting an
+ /// expression predicate.
GenericSelectionExpr(const ASTContext &Context, SourceLocation GenericLoc,
Expr *ControllingExpr,
ArrayRef<TypeSourceInfo *> AssocTypes,
@@ -5739,7 +5854,8 @@ class GenericSelectionExpr final
bool ContainsUnexpandedParameterPack,
unsigned ResultIndex);
- /// Build a result-dependent generic selection expression.
+ /// Build a result-dependent generic selection expression accepting an
+ /// expression predicate.
GenericSelectionExpr(const ASTContext &Context, SourceLocation GenericLoc,
Expr *ControllingExpr,
ArrayRef<TypeSourceInfo *> AssocTypes,
@@ -5747,11 +5863,31 @@ class GenericSelectionExpr final
SourceLocation RParenLoc,
bool ContainsUnexpandedParameterPack);
+ /// Build a non-result-dependent generic selection expression accepting a
+ /// type predicate.
+ GenericSelectionExpr(const ASTContext &Context, SourceLocation GenericLoc,
+ TypeSourceInfo *ControllingType,
+ ArrayRef<TypeSourceInfo *> AssocTypes,
+ ArrayRef<Expr *> AssocExprs, SourceLocation DefaultLoc,
+ SourceLocation RParenLoc,
+ bool ContainsUnexpandedParameterPack,
+ unsigned ResultIndex);
+
+ /// Build a result-dependent generic selection expression accepting a type
+ /// predicate.
+ GenericSelectionExpr(const ASTContext &Context, SourceLocation GenericLoc,
+ TypeSourceInfo *ControllingType,
+ ArrayRef<TypeSourceInfo *> AssocTypes,
+ ArrayRef<Expr *> AssocExprs, SourceLocation DefaultLoc,
+ SourceLocation RParenLoc,
+ bool ContainsUnexpandedParameterPack);
+
/// Build an empty generic selection expression for deserialization.
explicit GenericSelectionExpr(EmptyShell Empty, unsigned NumAssocs);
public:
- /// Create a non-result-dependent generic selection expression.
+ /// Create a non-result-dependent generic selection expression accepting an
+ /// expression predicate.
static GenericSelectionExpr *
Create(const ASTContext &Context, SourceLocation GenericLoc,
Expr *ControllingExpr, ArrayRef<TypeSourceInfo *> AssocTypes,
@@ -5759,13 +5895,31 @@ public:
SourceLocation RParenLoc, bool ContainsUnexpandedParameterPack,
unsigned ResultIndex);
- /// Create a result-dependent generic selection expression.
+ /// Create a result-dependent generic selection expression accepting an
+ /// expression predicate.
static GenericSelectionExpr *
Create(const ASTContext &Context, SourceLocation GenericLoc,
Expr *ControllingExpr, ArrayRef<TypeSourceInfo *> AssocTypes,
ArrayRef<Expr *> AssocExprs, SourceLocation DefaultLoc,
SourceLocation RParenLoc, bool ContainsUnexpandedParameterPack);
+ /// Create a non-result-dependent generic selection expression accepting a
+ /// type predicate.
+ static GenericSelectionExpr *
+ Create(const ASTContext &Context, SourceLocation GenericLoc,
+ TypeSourceInfo *ControllingType, ArrayRef<TypeSourceInfo *> AssocTypes,
+ ArrayRef<Expr *> AssocExprs, SourceLocation DefaultLoc,
+ SourceLocation RParenLoc, bool ContainsUnexpandedParameterPack,
+ unsigned ResultIndex);
+
+ /// Create a result-dependent generic selection expression accepting a type
+ /// predicate
+ static GenericSelectionExpr *
+ Create(const ASTContext &Context, SourceLocation GenericLoc,
+ TypeSourceInfo *ControllingType, 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);
@@ -5793,32 +5947,56 @@ public:
/// Whether this generic selection is result-dependent.
bool isResultDependent() const { return ResultIndex == ResultDependentIndex; }
+ /// Whether this generic selection uses an expression as its controlling
+ /// argument.
+ bool isExprPredicate() const { return IsExprPredicate; }
+ /// Whether this generic selection uses a type as its controlling argument.
+ bool isTypePredicate() const { return !IsExprPredicate; }
+
/// Return the controlling expression of this generic selection expression.
+ /// Only valid to call if the selection expression used an expression as its
+ /// controlling argument.
Expr *getControllingExpr() {
- return cast<Expr>(getTrailingObjects<Stmt *>()[ControllingIndex]);
+ return cast<Expr>(
+ getTrailingObjects<Stmt *>()[getIndexOfControllingExpression()]);
}
const Expr *getControllingExpr() const {
- return cast<Expr>(getTrailingObjects<Stmt *>()[ControllingIndex]);
+ return cast<Expr>(
+ getTrailingObjects<Stmt *>()[getIndexOfControllingExpression()]);
+ }
+
+ /// Return the controlling type of this generic selection expression. Only
+ /// valid to call if the selection expression used a type as its controlling
+ /// argument.
+ TypeSourceInfo *getControllingType() {
+ return getTrailingObjects<TypeSourceInfo *>()[getIndexOfControllingType()];
+ }
+ const TypeSourceInfo* getControllingType() const {
+ return getTrailingObjects<TypeSourceInfo *>()[getIndexOfControllingType()];
}
/// 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()]);
+ getTrailingObjects<Stmt *>()[getIndexOfStartOfAssociatedExprs() +
+ getResultIndex()]);
}
const Expr *getResultExpr() const {
return cast<Expr>(
- getTrailingObjects<Stmt *>()[AssocExprStartIndex + getResultIndex()]);
+ getTrailingObjects<Stmt *>()[getIndexOfStartOfAssociatedExprs() +
+ getResultIndex()]);
}
ArrayRef<Expr *> getAssocExprs() const {
return {reinterpret_cast<Expr *const *>(getTrailingObjects<Stmt *>() +
- AssocExprStartIndex),
+ getIndexOfStartOfAssociatedExprs()),
NumAssocs};
}
ArrayRef<TypeSourceInfo *> getAssocTypeSourceInfos() const {
- return {getTrailingObjects<TypeSourceInfo *>(), NumAssocs};
+ return {getTrailingObjects<TypeSourceInfo *>() +
+ getIndexOfStartOfAssociatedTypes(),
+ NumAssocs};
}
/// Return the Ith association expression with its TypeSourceInfo,
@@ -5827,23 +6005,30 @@ public:
assert(I < getNumAssocs() &&
"Out-of-range index in GenericSelectionExpr::getAssociation!");
return Association(
- cast<Expr>(getTrailingObjects<Stmt *>()[AssocExprStartIndex + I]),
- getTrailingObjects<TypeSourceInfo *>()[I],
+ cast<Expr>(
+ getTrailingObjects<Stmt *>()[getIndexOfStartOfAssociatedExprs() +
+ I]),
+ getTrailingObjects<
+ TypeSourceInfo *>()[getIndexOfStartOfAssociatedTypes() + 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],
+ cast<Expr>(
+ getTrailingObjects<Stmt *>()[getIndexOfStartOfAssociatedExprs() +
+ I]),
+ getTrailingObjects<
+ TypeSourceInfo *>()[getIndexOfStartOfAssociatedTypes() + I],
!isResultDependent() && (getResultIndex() == I));
}
association_range associations() {
AssociationIterator Begin(getTrailingObjects<Stmt *>() +
- AssocExprStartIndex,
- getTrailingObjects<TypeSourceInfo *>(),
+ getIndexOfStartOfAssociatedExprs(),
+ getTrailingObjects<TypeSourceInfo *>() +
+ getIndexOfStartOfAssociatedTypes(),
/*Offset=*/0, ResultIndex);
AssociationIterator End(Begin.E + NumAssocs, Begin.TSI + NumAssocs,
/*Offset=*/NumAssocs, ResultIndex);
@@ -5852,8 +6037,9 @@ public:
const_association_range associations() const {
ConstAssociationIterator Begin(getTrailingObjects<Stmt *>() +
- AssocExprStartIndex,
- getTrailingObjects<TypeSourceInfo *>(),
+ getIndexOfStartOfAssociatedExprs(),
+ getTrailingObjects<TypeSourceInfo *>() +
+ getIndexOfStartOfAssociatedTypes(),
/*Offset=*/0, ResultIndex);
ConstAssociationIterator End(Begin.E + NumAssocs, Begin.TSI + NumAssocs,
/*Offset=*/NumAssocs, ResultIndex);
@@ -6166,11 +6352,11 @@ public:
return getSubExprsBuffer() + getNumSubExprs();
}
- llvm::iterator_range<semantics_iterator> semantics() {
- return llvm::make_range(semantics_begin(), semantics_end());
+ ArrayRef<Expr*> semantics() {
+ return ArrayRef(semantics_begin(), semantics_end());
}
- llvm::iterator_range<const_semantics_iterator> semantics() const {
- return llvm::make_range(semantics_begin(), semantics_end());
+ ArrayRef<const Expr*> semantics() const {
+ return ArrayRef(semantics_begin(), semantics_end());
}
Expr *getSemanticExpr(unsigned index) {
@@ -6272,7 +6458,7 @@ public:
return cast<Expr>(SubExprs[ORDER_FAIL]);
}
Expr *getVal2() const {
- if (Op == AO__atomic_exchange)
+ if (Op == AO__atomic_exchange || Op == AO__scoped_atomic_exchange)
return cast<Expr>(SubExprs[ORDER_FAIL]);
assert(NumSubExprs > VAL2);
return cast<Expr>(SubExprs[VAL2]);
@@ -6284,6 +6470,16 @@ public:
QualType getValueType() const;
AtomicOp getOp() const { return Op; }
+ StringRef getOpAsString() const {
+ switch (Op) {
+#define BUILTIN(ID, TYPE, ATTRS)
+#define ATOMIC_BUILTIN(ID, TYPE, ATTRS) \
+ case AO##ID: \
+ return #ID;
+#include "clang/Basic/Builtins.def"
+ }
+ llvm_unreachable("not an atomic operator?");
+ }
unsigned getNumSubExprs() const { return NumSubExprs; }
Expr **getSubExprs() { return reinterpret_cast<Expr **>(SubExprs); }
@@ -6298,10 +6494,14 @@ public:
bool isCmpXChg() const {
return getOp() == AO__c11_atomic_compare_exchange_strong ||
getOp() == AO__c11_atomic_compare_exchange_weak ||
+ getOp() == AO__hip_atomic_compare_exchange_strong ||
getOp() == AO__opencl_atomic_compare_exchange_strong ||
getOp() == AO__opencl_atomic_compare_exchange_weak ||
+ getOp() == AO__hip_atomic_compare_exchange_weak ||
getOp() == AO__atomic_compare_exchange ||
- getOp() == AO__atomic_compare_exchange_n;
+ getOp() == AO__atomic_compare_exchange_n ||
+ getOp() == AO__scoped_atomic_compare_exchange ||
+ getOp() == AO__scoped_atomic_compare_exchange_n;
}
bool isOpenCL() const {
@@ -6331,11 +6531,13 @@ public:
/// \return empty atomic scope model if the atomic op code does not have
/// scope operand.
static std::unique_ptr<AtomicScopeModel> getScopeModel(AtomicOp Op) {
- auto Kind =
- (Op >= AO__opencl_atomic_load && Op <= AO__opencl_atomic_fetch_max)
- ? AtomicScopeModelKind::OpenCL
- : AtomicScopeModelKind::None;
- return AtomicScopeModel::create(Kind);
+ if (Op >= AO__opencl_atomic_load && Op <= AO__opencl_atomic_fetch_max)
+ return AtomicScopeModel::create(AtomicScopeModelKind::OpenCL);
+ else if (Op >= AO__hip_atomic_load && Op <= AO__hip_atomic_fetch_max)
+ return AtomicScopeModel::create(AtomicScopeModelKind::HIP);
+ else if (Op >= AO__scoped_atomic_load && Op <= AO__scoped_atomic_fetch_max)
+ return AtomicScopeModel::create(AtomicScopeModelKind::Generic);
+ return AtomicScopeModel::create(AtomicScopeModelKind::None);
}
/// Get atomic scope model.
@@ -6412,7 +6614,7 @@ public:
ArrayRef<Expr *> subExpressions() {
auto *B = getTrailingObjects<Expr *>();
- return llvm::makeArrayRef(B, B + NumExprs);
+ return llvm::ArrayRef(B, B + NumExprs);
}
ArrayRef<const Expr *> subExpressions() const {