269 changes: 269 additions & 0 deletions clang/include/clang/AST/Expr.h
Original file line number Diff line number Diff line change
Expand Up @@ -6610,6 +6610,275 @@ class TypoExpr : public Expr {

};

/// This class represents BOTH the OpenMP Array Section and OpenACC 'subarray',
/// with a boolean differentiator.
/// OpenMP 5.0 [2.1.5, Array Sections].
/// To specify an array section in an OpenMP construct, array subscript
/// expressions are extended with the following syntax:
/// \code
/// [ lower-bound : length : stride ]
/// [ lower-bound : length : ]
/// [ lower-bound : length ]
/// [ lower-bound : : stride ]
/// [ lower-bound : : ]
/// [ lower-bound : ]
/// [ : length : stride ]
/// [ : length : ]
/// [ : length ]
/// [ : : stride ]
/// [ : : ]
/// [ : ]
/// \endcode
/// The array section must be a subset of the original array.
/// Array sections are allowed on multidimensional arrays. Base language array
/// subscript expressions can be used to specify length-one dimensions of
/// multidimensional array sections.
/// Each of the lower-bound, length, and stride expressions if specified must be
/// an integral type expressions of the base language. When evaluated
/// they represent a set of integer values as follows:
/// \code
/// { lower-bound, lower-bound + stride, lower-bound + 2 * stride,... ,
/// lower-bound + ((length - 1) * stride) }
/// \endcode
/// The lower-bound and length must evaluate to non-negative integers.
/// The stride must evaluate to a positive integer.
/// When the size of the array dimension is not known, the length must be
/// specified explicitly.
/// When the stride is absent it defaults to 1.
/// When the length is absent it defaults to ⌈(size − lower-bound)/stride⌉,
/// where size is the size of the array dimension. When the lower-bound is
/// absent it defaults to 0.
///
///
/// OpenACC 3.3 [2.7.1 Data Specification in Data Clauses]
/// In C and C++, a subarray is an array name followed by an extended array
/// range specification in brackets, with start and length, such as
///
/// AA[2:n]
///
/// If the lower bound is missing, zero is used. If the length is missing and
/// the array has known size, the size of the array is used; otherwise the
/// length is required. The subarray AA[2:n] means elements AA[2], AA[3], . . .
/// , AA[2+n-1]. In C and C++, a two dimensional array may be declared in at
/// least four ways:
///
/// -Statically-sized array: float AA[100][200];
/// -Pointer to statically sized rows: typedef float row[200]; row* BB;
/// -Statically-sized array of pointers: float* CC[200];
/// -Pointer to pointers: float** DD;
///
/// Each dimension may be statically sized, or a pointer to dynamically
/// allocated memory. Each of these may be included in a data clause using
/// subarray notation to specify a rectangular array:
///
/// -AA[2:n][0:200]
/// -BB[2:n][0:m]
/// -CC[2:n][0:m]
/// -DD[2:n][0:m]
///
/// Multidimensional rectangular subarrays in C and C++ may be specified for any
/// array with any combination of statically-sized or dynamically-allocated
/// dimensions. For statically sized dimensions, all dimensions except the first
/// must specify the whole extent to preserve the contiguous data restriction,
/// discussed below. For dynamically allocated dimensions, the implementation
/// will allocate pointers in device memory corresponding to the pointers in
/// local memory and will fill in those pointers as appropriate.
///
/// In Fortran, a subarray is an array name followed by a comma-separated list
/// of range specifications in parentheses, with lower and upper bound
/// subscripts, such as
///
/// arr(1:high,low:100)
///
/// If either the lower or upper bounds are missing, the declared or allocated
/// bounds of the array, if known, are used. All dimensions except the last must
/// specify the whole extent, to preserve the contiguous data restriction,
/// discussed below.
///
/// Restrictions
///
/// -In Fortran, the upper bound for the last dimension of an assumed-size dummy
/// array must be specified.
///
/// -In C and C++, the length for dynamically allocated dimensions of an array
/// must be explicitly specified.
///
/// -In C and C++, modifying pointers in pointer arrays during the data
/// lifetime, either on the host or on the device, may result in undefined
/// behavior.
///
/// -If a subarray appears in a data clause, the implementation may choose to
/// allocate memory for only that subarray on the accelerator.
///
/// -In Fortran, array pointers may appear, but pointer association is not
/// preserved in device memory.
///
/// -Any array or subarray in a data clause, including Fortran array pointers,
/// must be a contiguous section of memory, except for dynamic multidimensional
/// C arrays.
///
/// -In C and C++, if a variable or array of composite type appears, all the
/// data members of the struct or class are allocated and copied, as
/// appropriate. If a composite member is a pointer type, the data addressed by
/// that pointer are not implicitly copied.
///
/// -In Fortran, if a variable or array of composite type appears, all the
/// members of that derived type are allocated and copied, as appropriate. If
/// any member has the allocatable or pointer attribute, the data accessed
/// through that member are not copied.
///
/// -If an expression is used in a subscript or subarray expression in a clause
/// on a data construct, the same value is used when copying data at the end of
/// the data region, even if the values of variables in the expression change
/// during the data region.
class ArraySectionExpr : public Expr {
friend class ASTStmtReader;
friend class ASTStmtWriter;

public:
enum ArraySectionType { OMPArraySection, OpenACCArraySection };

private:
enum {
BASE,
LOWER_BOUND,
LENGTH,
STRIDE,
END_EXPR,
OPENACC_END_EXPR = STRIDE
};

ArraySectionType ASType = OMPArraySection;
Stmt *SubExprs[END_EXPR] = {nullptr};
SourceLocation ColonLocFirst;
SourceLocation ColonLocSecond;
SourceLocation RBracketLoc;

public:
// Constructor for OMP array sections, which include a 'stride'.
ArraySectionExpr(Expr *Base, Expr *LowerBound, Expr *Length, Expr *Stride,
QualType Type, ExprValueKind VK, ExprObjectKind OK,
SourceLocation ColonLocFirst, SourceLocation ColonLocSecond,
SourceLocation RBracketLoc)
: Expr(ArraySectionExprClass, Type, VK, OK), ASType(OMPArraySection),
ColonLocFirst(ColonLocFirst), ColonLocSecond(ColonLocSecond),
RBracketLoc(RBracketLoc) {
setBase(Base);
setLowerBound(LowerBound);
setLength(Length);
setStride(Stride);
setDependence(computeDependence(this));
}

// Constructor for OpenACC sub-arrays, which do not permit a 'stride'.
ArraySectionExpr(Expr *Base, Expr *LowerBound, Expr *Length, QualType Type,
ExprValueKind VK, ExprObjectKind OK, SourceLocation ColonLoc,
SourceLocation RBracketLoc)
: Expr(ArraySectionExprClass, Type, VK, OK), ASType(OpenACCArraySection),
ColonLocFirst(ColonLoc), RBracketLoc(RBracketLoc) {
setBase(Base);
setLowerBound(LowerBound);
setLength(Length);
setDependence(computeDependence(this));
}

/// Create an empty array section expression.
explicit ArraySectionExpr(EmptyShell Shell)
: Expr(ArraySectionExprClass, Shell) {}

/// Return original type of the base expression for array section.
static QualType getBaseOriginalType(const Expr *Base);

static bool classof(const Stmt *T) {
return T->getStmtClass() == ArraySectionExprClass;
}

bool isOMPArraySection() const { return ASType == OMPArraySection; }
bool isOpenACCArraySection() const { return ASType == OpenACCArraySection; }

/// Get base of the array section.
Expr *getBase() { return cast<Expr>(SubExprs[BASE]); }
const Expr *getBase() const { return cast<Expr>(SubExprs[BASE]); }

/// Get lower bound of array section.
Expr *getLowerBound() { return cast_or_null<Expr>(SubExprs[LOWER_BOUND]); }
const Expr *getLowerBound() const {
return cast_or_null<Expr>(SubExprs[LOWER_BOUND]);
}

/// Get length of array section.
Expr *getLength() { return cast_or_null<Expr>(SubExprs[LENGTH]); }
const Expr *getLength() const { return cast_or_null<Expr>(SubExprs[LENGTH]); }

/// Get stride of array section.
Expr *getStride() {
assert(ASType != OpenACCArraySection &&
"Stride not valid in OpenACC subarrays");
return cast_or_null<Expr>(SubExprs[STRIDE]);
}

const Expr *getStride() const {
assert(ASType != OpenACCArraySection &&
"Stride not valid in OpenACC subarrays");
return cast_or_null<Expr>(SubExprs[STRIDE]);
}

SourceLocation getBeginLoc() const LLVM_READONLY {
return getBase()->getBeginLoc();
}
SourceLocation getEndLoc() const LLVM_READONLY { return RBracketLoc; }

SourceLocation getColonLocFirst() const { return ColonLocFirst; }
SourceLocation getColonLocSecond() const {
assert(ASType != OpenACCArraySection &&
"second colon for stride not valid in OpenACC subarrays");
return ColonLocSecond;
}
SourceLocation getRBracketLoc() const { return RBracketLoc; }

SourceLocation getExprLoc() const LLVM_READONLY {
return getBase()->getExprLoc();
}

child_range children() {
return child_range(
&SubExprs[BASE],
&SubExprs[ASType == OMPArraySection ? END_EXPR : OPENACC_END_EXPR]);
}

const_child_range children() const {
return const_child_range(
&SubExprs[BASE],
&SubExprs[ASType == OMPArraySection ? END_EXPR : OPENACC_END_EXPR]);
}

private:
/// Set base of the array section.
void setBase(Expr *E) { SubExprs[BASE] = E; }

/// Set lower bound of the array section.
void setLowerBound(Expr *E) { SubExprs[LOWER_BOUND] = E; }

/// Set length of the array section.
void setLength(Expr *E) { SubExprs[LENGTH] = E; }

/// Set length of the array section.
void setStride(Expr *E) {
assert(ASType != OpenACCArraySection &&
"Stride not valid in OpenACC subarrays");
SubExprs[STRIDE] = E;
}

void setColonLocFirst(SourceLocation L) { ColonLocFirst = L; }

void setColonLocSecond(SourceLocation L) {
assert(ASType != OpenACCArraySection &&
"second colon for stride not valid in OpenACC subarrays");
ColonLocSecond = L;
}
void setRBracketLoc(SourceLocation L) { RBracketLoc = L; }
};

/// Frontend produces RecoveryExprs on semantic errors that prevent creating
/// other well-formed expressions. E.g. when type-checking of a binary operator
/// fails, we cannot produce a BinaryOperator expression. Instead, we can choose
Expand Down
124 changes: 0 additions & 124 deletions clang/include/clang/AST/ExprOpenMP.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,130 +17,6 @@
#include "clang/AST/Expr.h"

namespace clang {
/// OpenMP 5.0 [2.1.5, Array Sections].
/// To specify an array section in an OpenMP construct, array subscript
/// expressions are extended with the following syntax:
/// \code
/// [ lower-bound : length : stride ]
/// [ lower-bound : length : ]
/// [ lower-bound : length ]
/// [ lower-bound : : stride ]
/// [ lower-bound : : ]
/// [ lower-bound : ]
/// [ : length : stride ]
/// [ : length : ]
/// [ : length ]
/// [ : : stride ]
/// [ : : ]
/// [ : ]
/// \endcode
/// The array section must be a subset of the original array.
/// Array sections are allowed on multidimensional arrays. Base language array
/// subscript expressions can be used to specify length-one dimensions of
/// multidimensional array sections.
/// Each of the lower-bound, length, and stride expressions if specified must be
/// an integral type expressions of the base language. When evaluated
/// they represent a set of integer values as follows:
/// \code
/// { lower-bound, lower-bound + stride, lower-bound + 2 * stride,... ,
/// lower-bound + ((length - 1) * stride) }
/// \endcode
/// The lower-bound and length must evaluate to non-negative integers.
/// The stride must evaluate to a positive integer.
/// When the size of the array dimension is not known, the length must be
/// specified explicitly.
/// When the stride is absent it defaults to 1.
/// When the length is absent it defaults to ⌈(size − lower-bound)/stride⌉,
/// where size is the size of the array dimension. When the lower-bound is
/// absent it defaults to 0.
class OMPArraySectionExpr : public Expr {
enum { BASE, LOWER_BOUND, LENGTH, STRIDE, END_EXPR };
Stmt *SubExprs[END_EXPR];
SourceLocation ColonLocFirst;
SourceLocation ColonLocSecond;
SourceLocation RBracketLoc;

public:
OMPArraySectionExpr(Expr *Base, Expr *LowerBound, Expr *Length, Expr *Stride,
QualType Type, ExprValueKind VK, ExprObjectKind OK,
SourceLocation ColonLocFirst,
SourceLocation ColonLocSecond, SourceLocation RBracketLoc)
: Expr(OMPArraySectionExprClass, Type, VK, OK),
ColonLocFirst(ColonLocFirst), ColonLocSecond(ColonLocSecond),
RBracketLoc(RBracketLoc) {
SubExprs[BASE] = Base;
SubExprs[LOWER_BOUND] = LowerBound;
SubExprs[LENGTH] = Length;
SubExprs[STRIDE] = Stride;
setDependence(computeDependence(this));
}

/// Create an empty array section expression.
explicit OMPArraySectionExpr(EmptyShell Shell)
: Expr(OMPArraySectionExprClass, Shell) {}

/// An array section can be written only as Base[LowerBound:Length].

/// Get base of the array section.
Expr *getBase() { return cast<Expr>(SubExprs[BASE]); }
const Expr *getBase() const { return cast<Expr>(SubExprs[BASE]); }
/// Set base of the array section.
void setBase(Expr *E) { SubExprs[BASE] = E; }

/// Return original type of the base expression for array section.
static QualType getBaseOriginalType(const Expr *Base);

/// Get lower bound of array section.
Expr *getLowerBound() { return cast_or_null<Expr>(SubExprs[LOWER_BOUND]); }
const Expr *getLowerBound() const {
return cast_or_null<Expr>(SubExprs[LOWER_BOUND]);
}
/// Set lower bound of the array section.
void setLowerBound(Expr *E) { SubExprs[LOWER_BOUND] = E; }

/// Get length of array section.
Expr *getLength() { return cast_or_null<Expr>(SubExprs[LENGTH]); }
const Expr *getLength() const { return cast_or_null<Expr>(SubExprs[LENGTH]); }
/// Set length of the array section.
void setLength(Expr *E) { SubExprs[LENGTH] = E; }

/// Get stride of array section.
Expr *getStride() { return cast_or_null<Expr>(SubExprs[STRIDE]); }
const Expr *getStride() const { return cast_or_null<Expr>(SubExprs[STRIDE]); }
/// Set length of the array section.
void setStride(Expr *E) { SubExprs[STRIDE] = E; }

SourceLocation getBeginLoc() const LLVM_READONLY {
return getBase()->getBeginLoc();
}
SourceLocation getEndLoc() const LLVM_READONLY { return RBracketLoc; }

SourceLocation getColonLocFirst() const { return ColonLocFirst; }
void setColonLocFirst(SourceLocation L) { ColonLocFirst = L; }

SourceLocation getColonLocSecond() const { return ColonLocSecond; }
void setColonLocSecond(SourceLocation L) { ColonLocSecond = L; }

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() == OMPArraySectionExprClass;
}

child_range children() {
return child_range(&SubExprs[BASE], &SubExprs[END_EXPR]);
}

const_child_range children() const {
return const_child_range(&SubExprs[BASE], &SubExprs[END_EXPR]);
}
};

/// An explicit cast in C or a C-style cast in C++, which uses the syntax
/// ([s1][s2]...[sn])expr. For example: @c ([3][3])f.
class OMPArrayShapingExpr final
Expand Down
2 changes: 1 addition & 1 deletion clang/include/clang/AST/NestedNameSpecifier.h
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,7 @@ class NestedNameSpecifierLoc {
explicit operator bool() const { return Qualifier; }

/// Evaluates true when this nested-name-specifier location is
/// empty.
/// non-empty.
bool hasQualifier() const { return Qualifier; }

/// Retrieve the nested-name-specifier to which this instance
Expand Down
2 changes: 1 addition & 1 deletion clang/include/clang/AST/RecursiveASTVisitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -2740,7 +2740,7 @@ DEF_TRAVERSE_STMT(CXXMemberCallExpr, {})
DEF_TRAVERSE_STMT(AddrLabelExpr, {})
DEF_TRAVERSE_STMT(ArraySubscriptExpr, {})
DEF_TRAVERSE_STMT(MatrixSubscriptExpr, {})
DEF_TRAVERSE_STMT(OMPArraySectionExpr, {})
DEF_TRAVERSE_STMT(ArraySectionExpr, {})
DEF_TRAVERSE_STMT(OMPArrayShapingExpr, {})
DEF_TRAVERSE_STMT(OMPIteratorExpr, {})

Expand Down
262 changes: 236 additions & 26 deletions clang/include/clang/AST/Type.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,10 @@
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/ExceptionSpecificationType.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/Linkage.h"
#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Basic/PointerAuthOptions.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/Specifiers.h"
#include "clang/Basic/Visibility.h"
Expand Down Expand Up @@ -139,6 +141,174 @@ using CanQualType = CanQual<Type>;
#define TYPE(Class, Base) class Class##Type;
#include "clang/AST/TypeNodes.inc"

/// Pointer-authentication qualifiers.
class PointerAuthQualifier {
enum : uint32_t {
EnabledShift = 0,
EnabledBits = 1,
EnabledMask = 1 << EnabledShift,
AddressDiscriminatedShift = EnabledShift + EnabledBits,
AddressDiscriminatedBits = 1,
AddressDiscriminatedMask = 1 << AddressDiscriminatedShift,
AuthenticationModeShift =
AddressDiscriminatedShift + AddressDiscriminatedBits,
AuthenticationModeBits = 2,
AuthenticationModeMask = ((1 << AuthenticationModeBits) - 1)
<< AuthenticationModeShift,
IsaPointerShift = AuthenticationModeShift + AuthenticationModeBits,
IsaPointerBits = 1,
IsaPointerMask = ((1 << IsaPointerBits) - 1) << IsaPointerShift,
AuthenticatesNullValuesShift = IsaPointerShift + IsaPointerBits,
AuthenticatesNullValuesBits = 1,
AuthenticatesNullValuesMask = ((1 << AuthenticatesNullValuesBits) - 1)
<< AuthenticatesNullValuesShift,
KeyShift = AuthenticatesNullValuesShift + AuthenticatesNullValuesBits,
KeyBits = 10,
KeyMask = ((1 << KeyBits) - 1) << KeyShift,
DiscriminatorShift = KeyShift + KeyBits,
DiscriminatorBits = 16,
DiscriminatorMask = ((1u << DiscriminatorBits) - 1) << DiscriminatorShift,
};

// bits: |0 |1 |2..3 |4 |
// |Enabled|Address|AuthenticationMode|ISA pointer|
// bits: |5 |6..15| 16...31 |
// |AuthenticatesNull|Key |Discriminator|
uint32_t Data = 0;

// The following static assertions check that each of the 32 bits is present
// exactly in one of the constants.
static_assert((EnabledBits + AddressDiscriminatedBits +
AuthenticationModeBits + IsaPointerBits +
AuthenticatesNullValuesBits + KeyBits + DiscriminatorBits) ==
32,
"PointerAuthQualifier should be exactly 32 bits");
static_assert((EnabledMask + AddressDiscriminatedMask +
AuthenticationModeMask + IsaPointerMask +
AuthenticatesNullValuesMask + KeyMask + DiscriminatorMask) ==
0xFFFFFFFF,
"All masks should cover the entire bits");
static_assert((EnabledMask ^ AddressDiscriminatedMask ^
AuthenticationModeMask ^ IsaPointerMask ^
AuthenticatesNullValuesMask ^ KeyMask ^ DiscriminatorMask) ==
0xFFFFFFFF,
"All masks should cover the entire bits");

PointerAuthQualifier(unsigned Key, bool IsAddressDiscriminated,
unsigned ExtraDiscriminator,
PointerAuthenticationMode AuthenticationMode,
bool IsIsaPointer, bool AuthenticatesNullValues)
: Data(EnabledMask |
(IsAddressDiscriminated
? llvm::to_underlying(AddressDiscriminatedMask)
: 0) |
(Key << KeyShift) |
(llvm::to_underlying(AuthenticationMode)
<< AuthenticationModeShift) |
(ExtraDiscriminator << DiscriminatorShift) |
(IsIsaPointer << IsaPointerShift) |
(AuthenticatesNullValues << AuthenticatesNullValuesShift)) {
assert(Key <= KeyNoneInternal);
assert(ExtraDiscriminator <= MaxDiscriminator);
assert((Data == 0) ==
(getAuthenticationMode() == PointerAuthenticationMode::None));
}

public:
enum {
KeyNoneInternal = (1u << KeyBits) - 1,

/// The maximum supported pointer-authentication key.
MaxKey = KeyNoneInternal - 1,

/// The maximum supported pointer-authentication discriminator.
MaxDiscriminator = (1u << DiscriminatorBits) - 1
};

public:
PointerAuthQualifier() = default;

static PointerAuthQualifier
Create(unsigned Key, bool IsAddressDiscriminated, unsigned ExtraDiscriminator,
PointerAuthenticationMode AuthenticationMode, bool IsIsaPointer,
bool AuthenticatesNullValues) {
if (Key == PointerAuthKeyNone)
Key = KeyNoneInternal;
assert(Key <= KeyNoneInternal && "out-of-range key value");
return PointerAuthQualifier(Key, IsAddressDiscriminated, ExtraDiscriminator,
AuthenticationMode, IsIsaPointer,
AuthenticatesNullValues);
}

bool isPresent() const {
assert((Data == 0) ==
(getAuthenticationMode() == PointerAuthenticationMode::None));
return Data != 0;
}

explicit operator bool() const { return isPresent(); }

unsigned getKey() const {
assert(isPresent());
return (Data & KeyMask) >> KeyShift;
}

bool hasKeyNone() const { return isPresent() && getKey() == KeyNoneInternal; }

bool isAddressDiscriminated() const {
assert(isPresent());
return (Data & AddressDiscriminatedMask) >> AddressDiscriminatedShift;
}

unsigned getExtraDiscriminator() const {
assert(isPresent());
return (Data >> DiscriminatorShift);
}

PointerAuthenticationMode getAuthenticationMode() const {
return PointerAuthenticationMode((Data & AuthenticationModeMask) >>
AuthenticationModeShift);
}

bool isIsaPointer() const {
assert(isPresent());
return (Data & IsaPointerMask) >> IsaPointerShift;
}

bool authenticatesNullValues() const {
assert(isPresent());
return (Data & AuthenticatesNullValuesMask) >> AuthenticatesNullValuesShift;
}

PointerAuthQualifier withoutKeyNone() const {
return hasKeyNone() ? PointerAuthQualifier() : *this;
}

friend bool operator==(PointerAuthQualifier Lhs, PointerAuthQualifier Rhs) {
return Lhs.Data == Rhs.Data;
}
friend bool operator!=(PointerAuthQualifier Lhs, PointerAuthQualifier Rhs) {
return Lhs.Data != Rhs.Data;
}

bool isEquivalent(PointerAuthQualifier Other) const {
return withoutKeyNone() == Other.withoutKeyNone();
}

uint32_t getAsOpaqueValue() const { return Data; }

// Deserialize pointer-auth qualifiers from an opaque representation.
static PointerAuthQualifier fromOpaqueValue(uint32_t Opaque) {
PointerAuthQualifier Result;
Result.Data = Opaque;
assert((Result.Data == 0) ==
(Result.getAuthenticationMode() == PointerAuthenticationMode::None));
return Result;
}

void Profile(llvm::FoldingSetNodeID &ID) const { ID.AddInteger(Data); }
};

/// The collection of all-type qualifiers we support.
/// Clang supports five independent qualifiers:
/// * C99: const, volatile, and restrict
Expand All @@ -147,8 +317,9 @@ using CanQualType = CanQual<Type>;
/// * Objective C: the GC attributes (none, weak, or strong)
class Qualifiers {
public:
enum TQ { // NOTE: These flags must be kept in sync with DeclSpec::TQ.
Const = 0x1,
enum TQ : uint64_t {
// NOTE: These flags must be kept in sync with DeclSpec::TQ.
Const = 0x1,
Restrict = 0x2,
Volatile = 0x4,
CVRMask = Const | Volatile | Restrict
Expand Down Expand Up @@ -182,7 +353,7 @@ class Qualifiers {
OCL_Autoreleasing
};

enum {
enum : uint64_t {
/// The maximum supported address space number.
/// 23 bits should be enough for anyone.
MaxAddressSpace = 0x7fffffu,
Expand All @@ -197,16 +368,25 @@ class Qualifiers {
/// Returns the common set of qualifiers while removing them from
/// the given sets.
static Qualifiers removeCommonQualifiers(Qualifiers &L, Qualifiers &R) {
Qualifiers Q;
PointerAuthQualifier LPtrAuth = L.getPointerAuth();
if (LPtrAuth.isPresent() &&
LPtrAuth.getKey() != PointerAuthQualifier::KeyNoneInternal &&
LPtrAuth == R.getPointerAuth()) {
Q.setPointerAuth(LPtrAuth);
PointerAuthQualifier Empty;
L.setPointerAuth(Empty);
R.setPointerAuth(Empty);
}

// If both are only CVR-qualified, bit operations are sufficient.
if (!(L.Mask & ~CVRMask) && !(R.Mask & ~CVRMask)) {
Qualifiers Q;
Q.Mask = L.Mask & R.Mask;
L.Mask &= ~Q.Mask;
R.Mask &= ~Q.Mask;
return Q;
}

Qualifiers Q;
unsigned CommonCRV = L.getCVRQualifiers() & R.getCVRQualifiers();
Q.addCVRQualifiers(CommonCRV);
L.removeCVRQualifiers(CommonCRV);
Expand Down Expand Up @@ -251,16 +431,14 @@ class Qualifiers {
}

// Deserialize qualifiers from an opaque representation.
static Qualifiers fromOpaqueValue(unsigned opaque) {
static Qualifiers fromOpaqueValue(uint64_t opaque) {
Qualifiers Qs;
Qs.Mask = opaque;
return Qs;
}

// Serialize these qualifiers into an opaque representation.
unsigned getAsOpaqueValue() const {
return Mask;
}
uint64_t getAsOpaqueValue() const { return Mask; }

bool hasConst() const { return Mask & Const; }
bool hasOnlyConst() const { return Mask == Const; }
Expand Down Expand Up @@ -302,7 +480,7 @@ class Qualifiers {
}
void removeCVRQualifiers(unsigned mask) {
assert(!(mask & ~CVRMask) && "bitmask contains non-CVR bits");
Mask &= ~mask;
Mask &= ~static_cast<uint64_t>(mask);
}
void removeCVRQualifiers() {
removeCVRQualifiers(CVRMask);
Expand Down Expand Up @@ -407,6 +585,20 @@ class Qualifiers {
setAddressSpace(space);
}

bool hasPointerAuth() const { return Mask & PtrAuthMask; }
PointerAuthQualifier getPointerAuth() const {
return PointerAuthQualifier::fromOpaqueValue(Mask >> PtrAuthShift);
}
void setPointerAuth(PointerAuthQualifier Q) {
Mask = (Mask & ~PtrAuthMask) |
(uint64_t(Q.getAsOpaqueValue()) << PtrAuthShift);
}
void removePointerAuth() { Mask &= ~PtrAuthMask; }
void addPointerAuth(PointerAuthQualifier Q) {
assert(Q.isPresent());
setPointerAuth(Q);
}

// Fast qualifiers are those that can be allocated directly
// on a QualType object.
bool hasFastQualifiers() const { return getFastQualifiers(); }
Expand All @@ -417,7 +609,7 @@ class Qualifiers {
}
void removeFastQualifiers(unsigned mask) {
assert(!(mask & ~FastMask) && "bitmask contains non-fast qualifier bits");
Mask &= ~mask;
Mask &= ~static_cast<uint64_t>(mask);
}
void removeFastQualifiers() {
removeFastQualifiers(FastMask);
Expand Down Expand Up @@ -454,6 +646,8 @@ class Qualifiers {
addObjCGCAttr(Q.getObjCGCAttr());
if (Q.hasObjCLifetime())
addObjCLifetime(Q.getObjCLifetime());
if (Q.hasPointerAuth())
addPointerAuth(Q.getPointerAuth());
}
}

Expand All @@ -471,6 +665,8 @@ class Qualifiers {
removeObjCLifetime();
if (getAddressSpace() == Q.getAddressSpace())
removeAddressSpace();
if (getPointerAuth() == Q.getPointerAuth())
removePointerAuth();
}
}

Expand All @@ -483,6 +679,8 @@ class Qualifiers {
!hasObjCGCAttr() || !qs.hasObjCGCAttr());
assert(getObjCLifetime() == qs.getObjCLifetime() ||
!hasObjCLifetime() || !qs.hasObjCLifetime());
assert(!hasPointerAuth() || !qs.hasPointerAuth() ||
getPointerAuth() == qs.getPointerAuth());
Mask |= qs.Mask;
}

Expand Down Expand Up @@ -536,6 +734,8 @@ class Qualifiers {
// be changed.
(getObjCGCAttr() == other.getObjCGCAttr() || !hasObjCGCAttr() ||
!other.hasObjCGCAttr()) &&
// Pointer-auth qualifiers must match exactly.
getPointerAuth() == other.getPointerAuth() &&
// ObjC lifetime qualifiers must match exactly.
getObjCLifetime() == other.getObjCLifetime() &&
// CVR qualifiers may subset.
Expand Down Expand Up @@ -605,24 +805,26 @@ class Qualifiers {
void print(raw_ostream &OS, const PrintingPolicy &Policy,
bool appendSpaceIfNonEmpty = false) const;

void Profile(llvm::FoldingSetNodeID &ID) const {
ID.AddInteger(Mask);
}
void Profile(llvm::FoldingSetNodeID &ID) const { ID.AddInteger(Mask); }

private:
// bits: |0 1 2|3|4 .. 5|6 .. 8|9 ... 31|
// |C R V|U|GCAttr|Lifetime|AddressSpace|
uint32_t Mask = 0;

static const uint32_t UMask = 0x8;
static const uint32_t UShift = 3;
static const uint32_t GCAttrMask = 0x30;
static const uint32_t GCAttrShift = 4;
static const uint32_t LifetimeMask = 0x1C0;
static const uint32_t LifetimeShift = 6;
static const uint32_t AddressSpaceMask =
// bits: |0 1 2|3|4 .. 5|6 .. 8|9 ... 31|32 ... 63|
// |C R V|U|GCAttr|Lifetime|AddressSpace| PtrAuth |
uint64_t Mask = 0;
static_assert(sizeof(PointerAuthQualifier) == sizeof(uint32_t),
"PointerAuthQualifier must be 32 bits");

static constexpr uint64_t UMask = 0x8;
static constexpr uint64_t UShift = 3;
static constexpr uint64_t GCAttrMask = 0x30;
static constexpr uint64_t GCAttrShift = 4;
static constexpr uint64_t LifetimeMask = 0x1C0;
static constexpr uint64_t LifetimeShift = 6;
static constexpr uint64_t AddressSpaceMask =
~(CVRMask | UMask | GCAttrMask | LifetimeMask);
static const uint32_t AddressSpaceShift = 9;
static constexpr uint64_t AddressSpaceShift = 9;
static constexpr uint64_t PtrAuthShift = 32;
static constexpr uint64_t PtrAuthMask = uint64_t(0xffffffff) << PtrAuthShift;
};

class QualifiersAndAtomic {
Expand Down Expand Up @@ -1242,6 +1444,10 @@ class QualType {
// true when Type is objc's weak and weak is enabled but ARC isn't.
bool isNonWeakInMRRWithObjCWeak(const ASTContext &Context) const;

PointerAuthQualifier getPointerAuth() const {
return getQualifiers().getPointerAuth();
}

enum PrimitiveDefaultInitializeKind {
/// The type does not fall into any of the following categories. Note that
/// this case is zero-valued so that values of this enum can be used as a
Expand Down Expand Up @@ -2172,6 +2378,10 @@ class alignas(TypeAlignment) Type : public ExtQualsTypeCommonBase {
/// 'riscv_rvv_vector_bits' type attribute as VectorType.
QualType getRVVEltType(const ASTContext &Ctx) const;

/// Returns the representative type for the element of a sizeless vector
/// builtin type.
QualType getSizelessVectorEltType(const ASTContext &Ctx) const;

/// Types are partitioned into 3 broad categories (C99 6.2.5p1):
/// object types, function types, and incomplete types.

Expand Down
81 changes: 62 additions & 19 deletions clang/include/clang/Basic/Attr.td
Original file line number Diff line number Diff line change
Expand Up @@ -592,6 +592,49 @@ class AttrSubjectMatcherAggregateRule<AttrSubject subject> {

def SubjectMatcherForNamed : AttrSubjectMatcherAggregateRule<Named>;

// Enumeration specifying what kind of behavior should be used for late
// parsing of attributes.
class LateAttrParseKind <int val> {
int Kind = val;
}

// Never late parsed
def LateAttrParseNever : LateAttrParseKind<0>;

// Standard late attribute parsing
//
// This is language dependent. For example:
//
// * For C++ enables late parsing of a declaration attributes
// * For C does not enable late parsing of attributes
//
def LateAttrParseStandard : LateAttrParseKind<1>;

// Experimental extension to standard late attribute parsing
//
// This extension behaves like `LateAttrParseStandard` but allows
// late parsing attributes in more contexts.
//
// In contexts where `LateAttrParseStandard` attributes are late
// parsed, `LateAttrParseExperimentalExt` attributes will also
// be late parsed.
//
// In contexts that only late parse `LateAttrParseExperimentalExt` attributes
// (see `LateParsedAttrList::lateAttrParseExperimentalExtOnly()`)
//
// * If `-fexperimental-late-parse-attributes`
// (`LangOpts.ExperimentalLateParseAttributes`) is enabled the attribute
// will be late parsed.
// * If `-fexperimental-late-parse-attributes`
// (`LangOpts.ExperimentalLateParseAttributes`) is disabled the attribute
// will **not** be late parsed (i.e parsed immediately).
//
// The following contexts are supported:
//
// * TODO: Add contexts here when they are implemented.
//
def LateAttrParseExperimentalExt : LateAttrParseKind<2>;

class Attr {
// The various ways in which an attribute can be spelled in source
list<Spelling> Spellings;
Expand All @@ -603,8 +646,8 @@ class Attr {
list<Accessor> Accessors = [];
// Specify targets for spellings.
list<TargetSpecificSpelling> TargetSpecificSpellings = [];
// Set to true for attributes with arguments which require delayed parsing.
bit LateParsed = 0;
// Specifies the late parsing kind.
LateAttrParseKind LateParsed = LateAttrParseNever;
// Set to false to prevent an attribute from being propagated from a template
// to the instantiation.
bit Clone = 1;
Expand Down Expand Up @@ -3173,7 +3216,7 @@ def DiagnoseIf : InheritableAttr {
BoolArgument<"ArgDependent", 0, /*fake*/ 1>,
DeclArgument<Named, "Parent", 0, /*fake*/ 1>];
let InheritEvenIfAlreadyPresent = 1;
let LateParsed = 1;
let LateParsed = LateAttrParseStandard;
let AdditionalMembers = [{
bool isError() const { return diagnosticType == DT_Error; }
bool isWarning() const { return diagnosticType == DT_Warning; }
Expand Down Expand Up @@ -3211,7 +3254,7 @@ def ObjCRequiresPropertyDefs : InheritableAttr {
def Unused : InheritableAttr {
let Spellings = [CXX11<"", "maybe_unused", 201603>, GCC<"unused">,
C23<"", "maybe_unused", 202106>];
let Subjects = SubjectList<[Var, ObjCIvar, Type, Enum, EnumConstant, Label,
let Subjects = SubjectList<[Var, Binding, ObjCIvar, Type, Enum, EnumConstant, Label,
Field, ObjCMethod, FunctionLike]>;
let Documentation = [WarnMaybeUnusedDocs];
}
Expand Down Expand Up @@ -3472,7 +3515,7 @@ def AssertCapability : InheritableAttr {
let Spellings = [Clang<"assert_capability", 0>,
Clang<"assert_shared_capability", 0>];
let Subjects = SubjectList<[Function]>;
let LateParsed = 1;
let LateParsed = LateAttrParseStandard;
let TemplateDependent = 1;
let ParseArgumentsAsUnevaluated = 1;
let InheritEvenIfAlreadyPresent = 1;
Expand All @@ -3488,7 +3531,7 @@ def AcquireCapability : InheritableAttr {
GNU<"exclusive_lock_function">,
GNU<"shared_lock_function">];
let Subjects = SubjectList<[Function]>;
let LateParsed = 1;
let LateParsed = LateAttrParseStandard;
let TemplateDependent = 1;
let ParseArgumentsAsUnevaluated = 1;
let InheritEvenIfAlreadyPresent = 1;
Expand All @@ -3504,7 +3547,7 @@ def TryAcquireCapability : InheritableAttr {
Clang<"try_acquire_shared_capability", 0>];
let Subjects = SubjectList<[Function],
ErrorDiag>;
let LateParsed = 1;
let LateParsed = LateAttrParseStandard;
let TemplateDependent = 1;
let ParseArgumentsAsUnevaluated = 1;
let InheritEvenIfAlreadyPresent = 1;
Expand All @@ -3520,7 +3563,7 @@ def ReleaseCapability : InheritableAttr {
Clang<"release_generic_capability", 0>,
Clang<"unlock_function", 0>];
let Subjects = SubjectList<[Function]>;
let LateParsed = 1;
let LateParsed = LateAttrParseStandard;
let TemplateDependent = 1;
let ParseArgumentsAsUnevaluated = 1;
let InheritEvenIfAlreadyPresent = 1;
Expand All @@ -3539,7 +3582,7 @@ def RequiresCapability : InheritableAttr {
Clang<"requires_shared_capability", 0>,
Clang<"shared_locks_required", 0>];
let Args = [VariadicExprArgument<"Args">];
let LateParsed = 1;
let LateParsed = LateAttrParseStandard;
let TemplateDependent = 1;
let ParseArgumentsAsUnevaluated = 1;
let InheritEvenIfAlreadyPresent = 1;
Expand All @@ -3559,7 +3602,7 @@ def NoThreadSafetyAnalysis : InheritableAttr {
def GuardedBy : InheritableAttr {
let Spellings = [GNU<"guarded_by">];
let Args = [ExprArgument<"Arg">];
let LateParsed = 1;
let LateParsed = LateAttrParseStandard;
let TemplateDependent = 1;
let ParseArgumentsAsUnevaluated = 1;
let InheritEvenIfAlreadyPresent = 1;
Expand All @@ -3570,7 +3613,7 @@ def GuardedBy : InheritableAttr {
def PtGuardedBy : InheritableAttr {
let Spellings = [GNU<"pt_guarded_by">];
let Args = [ExprArgument<"Arg">];
let LateParsed = 1;
let LateParsed = LateAttrParseStandard;
let TemplateDependent = 1;
let ParseArgumentsAsUnevaluated = 1;
let InheritEvenIfAlreadyPresent = 1;
Expand All @@ -3581,7 +3624,7 @@ def PtGuardedBy : InheritableAttr {
def AcquiredAfter : InheritableAttr {
let Spellings = [GNU<"acquired_after">];
let Args = [VariadicExprArgument<"Args">];
let LateParsed = 1;
let LateParsed = LateAttrParseStandard;
let TemplateDependent = 1;
let ParseArgumentsAsUnevaluated = 1;
let InheritEvenIfAlreadyPresent = 1;
Expand All @@ -3592,7 +3635,7 @@ def AcquiredAfter : InheritableAttr {
def AcquiredBefore : InheritableAttr {
let Spellings = [GNU<"acquired_before">];
let Args = [VariadicExprArgument<"Args">];
let LateParsed = 1;
let LateParsed = LateAttrParseStandard;
let TemplateDependent = 1;
let ParseArgumentsAsUnevaluated = 1;
let InheritEvenIfAlreadyPresent = 1;
Expand All @@ -3603,7 +3646,7 @@ def AcquiredBefore : InheritableAttr {
def AssertExclusiveLock : InheritableAttr {
let Spellings = [GNU<"assert_exclusive_lock">];
let Args = [VariadicExprArgument<"Args">];
let LateParsed = 1;
let LateParsed = LateAttrParseStandard;
let TemplateDependent = 1;
let ParseArgumentsAsUnevaluated = 1;
let InheritEvenIfAlreadyPresent = 1;
Expand All @@ -3614,7 +3657,7 @@ def AssertExclusiveLock : InheritableAttr {
def AssertSharedLock : InheritableAttr {
let Spellings = [GNU<"assert_shared_lock">];
let Args = [VariadicExprArgument<"Args">];
let LateParsed = 1;
let LateParsed = LateAttrParseStandard;
let TemplateDependent = 1;
let ParseArgumentsAsUnevaluated = 1;
let InheritEvenIfAlreadyPresent = 1;
Expand All @@ -3627,7 +3670,7 @@ def AssertSharedLock : InheritableAttr {
def ExclusiveTrylockFunction : InheritableAttr {
let Spellings = [GNU<"exclusive_trylock_function">];
let Args = [ExprArgument<"SuccessValue">, VariadicExprArgument<"Args">];
let LateParsed = 1;
let LateParsed = LateAttrParseStandard;
let TemplateDependent = 1;
let ParseArgumentsAsUnevaluated = 1;
let InheritEvenIfAlreadyPresent = 1;
Expand All @@ -3640,7 +3683,7 @@ def ExclusiveTrylockFunction : InheritableAttr {
def SharedTrylockFunction : InheritableAttr {
let Spellings = [GNU<"shared_trylock_function">];
let Args = [ExprArgument<"SuccessValue">, VariadicExprArgument<"Args">];
let LateParsed = 1;
let LateParsed = LateAttrParseStandard;
let TemplateDependent = 1;
let ParseArgumentsAsUnevaluated = 1;
let InheritEvenIfAlreadyPresent = 1;
Expand All @@ -3651,7 +3694,7 @@ def SharedTrylockFunction : InheritableAttr {
def LockReturned : InheritableAttr {
let Spellings = [GNU<"lock_returned">];
let Args = [ExprArgument<"Arg">];
let LateParsed = 1;
let LateParsed = LateAttrParseStandard;
let TemplateDependent = 1;
let ParseArgumentsAsUnevaluated = 1;
let Subjects = SubjectList<[Function]>;
Expand All @@ -3661,7 +3704,7 @@ def LockReturned : InheritableAttr {
def LocksExcluded : InheritableAttr {
let Spellings = [GNU<"locks_excluded">];
let Args = [VariadicExprArgument<"Args">];
let LateParsed = 1;
let LateParsed = LateAttrParseStandard;
let TemplateDependent = 1;
let ParseArgumentsAsUnevaluated = 1;
let InheritEvenIfAlreadyPresent = 1;
Expand Down
3 changes: 3 additions & 0 deletions clang/include/clang/Basic/DiagnosticFrontendKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -370,4 +370,7 @@ def warn_missing_symbol_graph_dir : Warning<
"Missing symbol graph output directory, defaulting to working directory">,
InGroup<ExtractAPIMisuse>;

def err_ast_action_on_llvm_ir : Error<
"cannot apply AST actions to LLVM IR file '%0'">,
DefaultFatal;
}
9 changes: 9 additions & 0 deletions clang/include/clang/Basic/DiagnosticParseKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -478,6 +478,15 @@ def ext_decomp_decl_empty : ExtWarn<
"ISO C++17 does not allow a decomposition group to be empty">,
InGroup<DiagGroup<"empty-decomposition">>;

// C++26 structured bindings
def ext_decl_attrs_on_binding : ExtWarn<
"an attribute specifier sequence attached to a structured binding declaration "
"is a C++2c extension">, InGroup<CXX26>;
def warn_cxx23_compat_decl_attrs_on_binding : Warning<
"an attribute specifier sequence attached to a structured binding declaration "
"is incompatible with C++ standards before C++2c">,
InGroup<CXXPre26Compat>, DefaultIgnore;

/// Objective-C parser diagnostics
def err_expected_minus_or_plus : Error<
"method type specifier must start with '-' or '+'">;
Expand Down
11 changes: 10 additions & 1 deletion clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -9901,6 +9901,9 @@ def warn_format_invalid_annotation : Warning<
def warn_format_P_no_precision : Warning<
"using '%%P' format specifier without precision">,
InGroup<Format>;
def warn_format_P_with_objc_pointer : Warning<
"using '%%P' format specifier with an Objective-C pointer results in dumping runtime object structure, not object value">,
InGroup<Format>;
def warn_printf_ignored_flag: Warning<
"flag '%0' is ignored when flag '%1' is present">,
InGroup<Format>;
Expand Down Expand Up @@ -9950,6 +9953,8 @@ def warn_ret_stack_addr_ref : Warning<
def warn_ret_local_temp_addr_ref : Warning<
"returning %select{address of|reference to}0 local temporary object">,
InGroup<ReturnStackAddress>;
def err_ret_local_temp_ref : Error<
"returning reference to local temporary object">;
def warn_ret_addr_label : Warning<
"returning address of label, which is local">,
InGroup<ReturnStackAddress>;
Expand Down Expand Up @@ -10328,9 +10333,13 @@ def err_shufflevector_nonconstant_argument : Error<
def err_shufflevector_argument_too_large : Error<
"index for __builtin_shufflevector must be less than the total number "
"of vector elements">;
def err_shufflevector_minus_one_is_undefined_behavior_constexpr : Error<
"index for __builtin_shufflevector not within the bounds of the input vectors; index of -1 found at position %0 not permitted in a constexpr context.">;

def err_convertvector_non_vector : Error<
"first argument to __builtin_convertvector must be a vector">;
def err_convertvector_constexpr_unsupported_vector_cast : Error<
"unsupported vector cast from %0 to %1 in a constant expression.">;
def err_builtin_non_vector_type : Error<
"%0 argument to %1 must be of vector type">;
def err_convertvector_incompatible_vector : Error<
Expand Down Expand Up @@ -11161,7 +11170,7 @@ def err_omp_declare_mapper_redefinition : Error<
"redefinition of user-defined mapper for type %0 with name %1">;
def err_omp_invalid_mapper: Error<
"cannot find a valid user-defined mapper for type %0 with name %1">;
def err_omp_array_section_use : Error<"OpenMP array section is not allowed here">;
def err_array_section_use : Error<"%select{OpenACC sub-array|OpenMP array section}0 is not allowed here">;
def err_omp_array_shaping_use : Error<"OpenMP array shaping operation is not allowed here">;
def err_omp_iterator_use : Error<"OpenMP iterator is not allowed here">;
def err_omp_typecheck_section_value : Error<
Expand Down
10 changes: 10 additions & 0 deletions clang/include/clang/Basic/FileManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,12 @@ class FileManager : public RefCountedBase<FileManager> {
///
unsigned NextFileUID;

/// Statistics gathered during the lifetime of the FileManager.
unsigned NumDirLookups = 0;
unsigned NumFileLookups = 0;
unsigned NumDirCacheMisses = 0;
unsigned NumFileCacheMisses = 0;

// Caching.
std::unique_ptr<FileSystemStatCache> StatCache;

Expand Down Expand Up @@ -341,6 +347,10 @@ class FileManager : public RefCountedBase<FileManager> {

public:
void PrintStats() const;

/// Import statistics from a child FileManager and add them to this current
/// FileManager.
void AddStats(const FileManager &Other);
};

} // end namespace clang
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/Basic/LangOptions.def
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ LANGOPT(ExperimentalLibrary, 1, 0, "enable unstable and experimental library fea
LANGOPT(PointerAuthIntrinsics, 1, 0, "pointer authentication intrinsics")

LANGOPT(DoubleSquareBracketAttributes, 1, 0, "'[[]]' attributes extension for all language standard modes")
LANGOPT(ExperimentalLateParseAttributes, 1, 0, "experimental late parsing of attributes")

COMPATIBLE_LANGOPT(RecoveryAST, 1, 1, "Preserve expressions in AST when encountering errors")
COMPATIBLE_LANGOPT(RecoveryASTType, 1, 1, "Preserve the type in recovery expressions")
Expand Down
7 changes: 7 additions & 0 deletions clang/include/clang/Basic/LangOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,13 @@ enum class ShaderStage {
Invalid,
};

enum class PointerAuthenticationMode : unsigned {
None,
Strip,
SignAndStrip,
SignAndAuth
};

/// Bitfields of LangOptions, split out from LangOptions in order to ensure that
/// this large collection of bitfields is a trivial class type.
class LangOptionsBase {
Expand Down
23 changes: 23 additions & 0 deletions clang/include/clang/Basic/PointerAuthOptions.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
//===--- PointerAuthOptions.h -----------------------------------*- C++ -*-===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// This file defines options for configuring pointer-auth technologies
// like ARMv8.3.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_BASIC_POINTERAUTHOPTIONS_H
#define LLVM_CLANG_BASIC_POINTERAUTHOPTIONS_H

namespace clang {

constexpr unsigned PointerAuthKeyNone = -1;

} // end namespace clang

#endif
2 changes: 1 addition & 1 deletion clang/include/clang/Basic/StmtNodes.td
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ def OffsetOfExpr : StmtNode<Expr>;
def UnaryExprOrTypeTraitExpr : StmtNode<Expr>;
def ArraySubscriptExpr : StmtNode<Expr>;
def MatrixSubscriptExpr : StmtNode<Expr>;
def OMPArraySectionExpr : StmtNode<Expr>;
def ArraySectionExpr : StmtNode<Expr>;
def OMPIteratorExpr : StmtNode<Expr>;
def CallExpr : StmtNode<Expr>;
def MemberExpr : StmtNode<Expr>;
Expand Down
10 changes: 10 additions & 0 deletions clang/include/clang/Basic/TargetInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
#include <cassert>
#include <optional>
#include <string>
#include <utility>
#include <vector>

namespace llvm {
Expand Down Expand Up @@ -1792,6 +1793,15 @@ class TargetInfo : public TransferrableTargetInfo,
/// Whether to support HIP image/texture API's.
virtual bool hasHIPImageSupport() const { return true; }

/// The first value in the pair is the minimum offset between two objects to
/// avoid false sharing (destructive interference). The second value in the
/// pair is maximum size of contiguous memory to promote true sharing
/// (constructive interference). Neither of these values are considered part
/// of the ABI and can be changed by targets at any time.
virtual std::pair<unsigned, unsigned> hardwareInterferenceSizes() const {
return std::make_pair(64, 64);
}

protected:
/// Copy type and layout related info.
void copyAuxTarget(const TargetInfo *Aux);
Expand Down
2 changes: 1 addition & 1 deletion clang/include/clang/Basic/arm_neon.td
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,7 @@ def OP_VCVT_BF16_F32_HI_A32
(call "vget_low", $p0))>;

def OP_CVT_F32_BF16
: Op<(bitcast "R", (op "<<", (bitcast "int32_t", $p0),
: Op<(bitcast "R", (op "<<", (cast "int32_t", (bitcast "int16_t", $p0)),
(literal "int32_t", "16")))>;

//===----------------------------------------------------------------------===//
Expand Down
27 changes: 14 additions & 13 deletions clang/include/clang/Basic/arm_sve.td
Original file line number Diff line number Diff line change
Expand Up @@ -1961,19 +1961,20 @@ def SVPSEL_D : SInst<"svpsel_lane_b64", "PPPm", "Pl", MergeNone, "", [IsStreamin

// Standalone sve2.1 builtins
let TargetGuard = "sve2p1" in {
def SVORQV : SInst<"svorqv[_{d}]", "{Pd", "csilUcUsUiUl", MergeNone, "aarch64_sve_orqv", [IsReductionQV]>;
def SVEORQV : SInst<"sveorqv[_{d}]", "{Pd", "csilUcUsUiUl", MergeNone, "aarch64_sve_eorqv", [IsReductionQV]>;
def SVADDQV : SInst<"svaddqv[_{d}]", "{Pd", "hfdcsilUcUsUiUl", MergeNone, "aarch64_sve_addqv", [IsReductionQV]>;
def SVANDQV : SInst<"svandqv[_{d}]", "{Pd", "csilUcUsUiUl", MergeNone, "aarch64_sve_andqv", [IsReductionQV]>;
def SVSMAXQV : SInst<"svmaxqv[_{d}]", "{Pd", "csil", MergeNone, "aarch64_sve_smaxqv", [IsReductionQV]>;
def SVUMAXQV : SInst<"svmaxqv[_{d}]", "{Pd", "UcUsUiUl", MergeNone, "aarch64_sve_umaxqv", [IsReductionQV]>;
def SVSMINQV : SInst<"svminqv[_{d}]", "{Pd", "csil", MergeNone, "aarch64_sve_sminqv", [IsReductionQV]>;
def SVUMINQV : SInst<"svminqv[_{d}]", "{Pd", "UcUsUiUl", MergeNone, "aarch64_sve_uminqv", [IsReductionQV]>;

def SVFMAXNMQV: SInst<"svmaxnmqv[_{d}]", "{Pd", "hfd", MergeNone, "aarch64_sve_fmaxnmqv", [IsReductionQV]>;
def SVFMINNMQV: SInst<"svminnmqv[_{d}]", "{Pd", "hfd", MergeNone, "aarch64_sve_fminnmqv", [IsReductionQV]>;
def SVFMAXQV: SInst<"svmaxqv[_{d}]", "{Pd", "hfd", MergeNone, "aarch64_sve_fmaxqv", [IsReductionQV]>;
def SVFMINQV: SInst<"svminqv[_{d}]", "{Pd", "hfd", MergeNone, "aarch64_sve_fminqv", [IsReductionQV]>;
def SVORQV : SInst<"svorqv[_{d}]", "{Pd", "csilUcUsUiUl", MergeNone, "aarch64_sve_orqv", [IsReductionQV]>;
def SVEORQV : SInst<"sveorqv[_{d}]", "{Pd", "csilUcUsUiUl", MergeNone, "aarch64_sve_eorqv", [IsReductionQV]>;
def SVADDQV : SInst<"svaddqv[_{d}]", "{Pd", "csilUcUsUiUl", MergeNone, "aarch64_sve_addqv", [IsReductionQV]>;
def SVANDQV : SInst<"svandqv[_{d}]", "{Pd", "csilUcUsUiUl", MergeNone, "aarch64_sve_andqv", [IsReductionQV]>;
def SVSMAXQV : SInst<"svmaxqv[_{d}]", "{Pd", "csil", MergeNone, "aarch64_sve_smaxqv", [IsReductionQV]>;
def SVUMAXQV : SInst<"svmaxqv[_{d}]", "{Pd", "UcUsUiUl", MergeNone, "aarch64_sve_umaxqv", [IsReductionQV]>;
def SVSMINQV : SInst<"svminqv[_{d}]", "{Pd", "csil", MergeNone, "aarch64_sve_sminqv", [IsReductionQV]>;
def SVUMINQV : SInst<"svminqv[_{d}]", "{Pd", "UcUsUiUl", MergeNone, "aarch64_sve_uminqv", [IsReductionQV]>;

def SVFADDQV : SInst<"svaddqv[_{d}]", "{Pd", "hfd", MergeNone, "aarch64_sve_faddqv", [IsReductionQV]>;
def SVFMAXNMQV : SInst<"svmaxnmqv[_{d}]", "{Pd", "hfd", MergeNone, "aarch64_sve_fmaxnmqv", [IsReductionQV]>;
def SVFMINNMQV : SInst<"svminnmqv[_{d}]", "{Pd", "hfd", MergeNone, "aarch64_sve_fminnmqv", [IsReductionQV]>;
def SVFMAXQV : SInst<"svmaxqv[_{d}]", "{Pd", "hfd", MergeNone, "aarch64_sve_fmaxqv", [IsReductionQV]>;
def SVFMINQV : SInst<"svminqv[_{d}]", "{Pd", "hfd", MergeNone, "aarch64_sve_fminqv", [IsReductionQV]>;
}

let TargetGuard = "sve2p1|sme2" in {
Expand Down
31 changes: 25 additions & 6 deletions clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -1608,6 +1608,13 @@ defm double_square_bracket_attributes : BoolFOption<"double-square-bracket-attri
LangOpts<"DoubleSquareBracketAttributes">, DefaultTrue, PosFlag<SetTrue>,
NegFlag<SetFalse>>;

defm experimental_late_parse_attributes : BoolFOption<"experimental-late-parse-attributes",
LangOpts<"ExperimentalLateParseAttributes">, DefaultFalse,
PosFlag<SetTrue, [], [ClangOption], "Enable">,
NegFlag<SetFalse, [], [ClangOption], "Disable">,
BothFlags<[], [ClangOption, CC1Option],
" experimental late parsing of attributes">>;

defm autolink : BoolFOption<"autolink",
CodeGenOpts<"Autolink">, DefaultTrue,
NegFlag<SetFalse, [], [ClangOption, CC1Option],
Expand Down Expand Up @@ -2615,6 +2622,11 @@ defm protect_parens : BoolFOption<"protect-parens",
"floating-point expressions are evaluated">,
NegFlag<SetFalse>>;

defm daz_ftz : SimpleMFlag<"daz-ftz",
"Globally set", "Do not globally set",
" the denormals-are-zero (DAZ) and flush-to-zero (FTZ) bits in the "
"floating-point control register on program startup">;

def ffor_scope : Flag<["-"], "ffor-scope">, Group<f_Group>;
def fno_for_scope : Flag<["-"], "fno-for-scope">, Group<f_Group>;

Expand Down Expand Up @@ -2881,6 +2893,17 @@ def flax_vector_conversions : Flag<["-"], "flax-vector-conversions">, Group<f_Gr
def flimited_precision_EQ : Joined<["-"], "flimited-precision=">, Group<f_Group>;
def fapple_link_rtlib : Flag<["-"], "fapple-link-rtlib">, Group<f_Group>,
HelpText<"Force linking the clang builtins runtime library">;

/// ClangIR-specific options - BEGIN
defm clangir : BoolFOption<"clangir",
FrontendOpts<"UseClangIRPipeline">, DefaultFalse,
PosFlag<SetTrue, [], [ClangOption, CC1Option], "Use the ClangIR pipeline to compile">,
NegFlag<SetFalse, [], [ClangOption, CC1Option], "Use the AST -> LLVM pipeline to compile">,
BothFlags<[], [ClangOption, CC1Option], "">>;
def emit_cir : Flag<["-"], "emit-cir">, Visibility<[CC1Option]>,
Group<Action_Group>, HelpText<"Build ASTs and then lower to ClangIR">;
/// ClangIR-specific options - END

def flto_EQ : Joined<["-"], "flto=">,
Visibility<[ClangOption, CLOption, CC1Option, FC1Option, FlangOption]>,
Group<f_Group>,
Expand Down Expand Up @@ -4876,6 +4899,8 @@ def msimd128 : Flag<["-"], "msimd128">, Group<m_wasm_Features_Group>;
def mno_simd128 : Flag<["-"], "mno-simd128">, Group<m_wasm_Features_Group>;
def mrelaxed_simd : Flag<["-"], "mrelaxed-simd">, Group<m_wasm_Features_Group>;
def mno_relaxed_simd : Flag<["-"], "mno-relaxed-simd">, Group<m_wasm_Features_Group>;
def mhalf_precision : Flag<["-"], "mhalf-precision">, Group<m_wasm_Features_Group>;
def mno_half_precision : Flag<["-"], "mno-half-precision">, Group<m_wasm_Features_Group>;
def mnontrapping_fptoint : Flag<["-"], "mnontrapping-fptoint">, Group<m_wasm_Features_Group>;
def mno_nontrapping_fptoint : Flag<["-"], "mno-nontrapping-fptoint">, Group<m_wasm_Features_Group>;
def msign_ext : Flag<["-"], "msign-ext">, Group<m_wasm_Features_Group>;
Expand Down Expand Up @@ -6582,12 +6607,6 @@ def J : JoinedOrSeparate<["-"], "J">,
Group<gfortran_Group>,
Alias<module_dir>;

let Visibility = [FlangOption] in {
def no_fortran_main : Flag<["-"], "fno-fortran-main">,
Visibility<[FlangOption]>, Group<f_Group>,
HelpText<"Do not include Fortran_main.a (provided by Flang) when linking">;
} // let Visibility = [ FlangOption ]

//===----------------------------------------------------------------------===//
// FC1 Options
//===----------------------------------------------------------------------===//
Expand Down
9 changes: 8 additions & 1 deletion clang/include/clang/Frontend/FrontendOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@ enum ActionKind {
/// Translate input source into HTML.
EmitHTML,

/// Emit a .cir file
EmitCIR,

/// Emit a .ll file.
EmitLLVM,

Expand Down Expand Up @@ -408,6 +411,10 @@ class FrontendOptions {
LLVM_PREFERRED_TYPE(bool)
unsigned GenReducedBMI : 1;

/// Use Clang IR pipeline to emit code
LLVM_PREFERRED_TYPE(bool)
unsigned UseClangIRPipeline : 1;

CodeCompleteOptions CodeCompleteOpts;

/// Specifies the output format of the AST.
Expand Down Expand Up @@ -590,7 +597,7 @@ class FrontendOptions {
EmitSymbolGraph(false), EmitExtensionSymbolGraphs(false),
EmitSymbolGraphSymbolLabelsForTesting(false),
EmitPrettySymbolGraphs(false), GenReducedBMI(false),
TimeTraceGranularity(500) {}
UseClangIRPipeline(false), TimeTraceGranularity(500) {}

/// getInputKindForExtension - Return the appropriate input kind for a file
/// extension. For example, "c" would return Language::C.
Expand Down
13 changes: 11 additions & 2 deletions clang/include/clang/Parse/Parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -1398,12 +1398,21 @@ class Parser : public CodeCompletionHandler {
// A list of late-parsed attributes. Used by ParseGNUAttributes.
class LateParsedAttrList: public SmallVector<LateParsedAttribute *, 2> {
public:
LateParsedAttrList(bool PSoon = false) : ParseSoon(PSoon) { }
LateParsedAttrList(bool PSoon = false,
bool LateAttrParseExperimentalExtOnly = false)
: ParseSoon(PSoon),
LateAttrParseExperimentalExtOnly(LateAttrParseExperimentalExtOnly) {}

bool parseSoon() { return ParseSoon; }
/// returns true iff the attribute to be parsed should only be late parsed
/// if it is annotated with `LateAttrParseExperimentalExt`
bool lateAttrParseExperimentalExtOnly() {
return LateAttrParseExperimentalExtOnly;
}

private:
bool ParseSoon; // Are we planning to parse these shortly after creation?
bool ParseSoon; // Are we planning to parse these shortly after creation?
bool LateAttrParseExperimentalExtOnly;
};

/// Contains the lexed tokens of a member function definition
Expand Down
18 changes: 10 additions & 8 deletions clang/include/clang/Sema/DeclSpec.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/ErrorHandling.h"
#include <optional>

namespace clang {
class ASTContext;
Expand Down Expand Up @@ -1790,6 +1791,7 @@ class DecompositionDeclarator {
struct Binding {
IdentifierInfo *Name;
SourceLocation NameLoc;
std::optional<ParsedAttributes> Attrs;
};

private:
Expand All @@ -1809,15 +1811,15 @@ class DecompositionDeclarator {
: Bindings(nullptr), NumBindings(0), DeleteBindings(false) {}
DecompositionDeclarator(const DecompositionDeclarator &G) = delete;
DecompositionDeclarator &operator=(const DecompositionDeclarator &G) = delete;
~DecompositionDeclarator() {
if (DeleteBindings)
delete[] Bindings;
}
~DecompositionDeclarator() { clear(); }

void clear() {
LSquareLoc = RSquareLoc = SourceLocation();
if (DeleteBindings)
delete[] Bindings;
else
llvm::for_each(llvm::MutableArrayRef(Bindings, NumBindings),
[](Binding &B) { B.Attrs.reset(); });
Bindings = nullptr;
NumBindings = 0;
DeleteBindings = false;
Expand Down Expand Up @@ -2339,10 +2341,10 @@ class Declarator {
}

/// Set the decomposition bindings for this declarator.
void
setDecompositionBindings(SourceLocation LSquareLoc,
ArrayRef<DecompositionDeclarator::Binding> Bindings,
SourceLocation RSquareLoc);
void setDecompositionBindings(
SourceLocation LSquareLoc,
MutableArrayRef<DecompositionDeclarator::Binding> Bindings,
SourceLocation RSquareLoc);

/// AddTypeInfo - Add a chunk to this declarator. Also extend the range to
/// EndLoc, which should be the last token of the chunk.
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/Sema/ParsedAttr.h
Original file line number Diff line number Diff line change
Expand Up @@ -948,6 +948,7 @@ class ParsedAttributes : public ParsedAttributesView {
ParsedAttributes(AttributeFactory &factory) : pool(factory) {}
ParsedAttributes(const ParsedAttributes &) = delete;
ParsedAttributes &operator=(const ParsedAttributes &) = delete;
ParsedAttributes(ParsedAttributes &&G) = default;

AttributePool &getPool() const { return pool; }

Expand Down
6 changes: 6 additions & 0 deletions clang/include/clang/Sema/SemaOpenACC.h
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,12 @@ class SemaOpenACC : public SemaBase {
/// conversions and diagnostics to 'int'.
ExprResult ActOnIntExpr(OpenACCDirectiveKind DK, OpenACCClauseKind CK,
SourceLocation Loc, Expr *IntExpr);

/// Checks and creates an Array Section used in an OpenACC construct/clause.
ExprResult ActOnArraySectionExpr(Expr *Base, SourceLocation LBLoc,
Expr *LowerBound,
SourceLocation ColonLocFirst, Expr *Length,
SourceLocation RBLoc);
};

} // namespace clang
Expand Down
6 changes: 3 additions & 3 deletions clang/include/clang/Serialization/ASTBitCodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -973,8 +973,8 @@ enum PredefinedTypeIDs {
/// OpenCL reserve_id type.
PREDEF_TYPE_RESERVE_ID_ID = 41,

/// The placeholder type for OpenMP array section.
PREDEF_TYPE_OMP_ARRAY_SECTION = 42,
/// The placeholder type for an array section.
PREDEF_TYPE_ARRAY_SECTION = 42,

/// The '__float128' type
PREDEF_TYPE_FLOAT128_ID = 43,
Expand Down Expand Up @@ -1926,7 +1926,7 @@ enum StmtCode {
STMT_OMP_TARGET_TEAMS_GENERIC_LOOP_DIRECTIVE,
STMT_OMP_PARALLEL_GENERIC_LOOP_DIRECTIVE,
STMT_OMP_TARGET_PARALLEL_GENERIC_LOOP_DIRECTIVE,
EXPR_OMP_ARRAY_SECTION,
EXPR_ARRAY_SECTION,
EXPR_OMP_ARRAY_SHAPING,
EXPR_OMP_ITERATOR,

Expand Down
14 changes: 5 additions & 9 deletions clang/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h
Original file line number Diff line number Diff line change
Expand Up @@ -225,15 +225,11 @@ class StoreManager {
/// invalidated. This should include any regions explicitly invalidated
/// even if they do not currently have bindings. Pass \c NULL if this
/// information will not be used.
virtual StoreRef invalidateRegions(Store store,
ArrayRef<SVal> Values,
const Expr *E, unsigned Count,
const LocationContext *LCtx,
const CallEvent *Call,
InvalidatedSymbols &IS,
RegionAndSymbolInvalidationTraits &ITraits,
InvalidatedRegions *InvalidatedTopLevel,
InvalidatedRegions *Invalidated) = 0;
virtual StoreRef invalidateRegions(
Store store, ArrayRef<SVal> Values, const Expr *Ex, unsigned Count,
const LocationContext *LCtx, const CallEvent *Call,
InvalidatedSymbols &IS, RegionAndSymbolInvalidationTraits &ITraits,
InvalidatedRegions *TopLevelRegions, InvalidatedRegions *Invalidated) = 0;

/// enterStackFrame - Let the StoreManager to do something when execution
/// engine is about to execute into a callee.
Expand Down
5 changes: 4 additions & 1 deletion clang/lib/APINotes/APINotesFormat.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,10 @@ const uint16_t VERSION_MAJOR = 0;
/// API notes file minor version number.
///
/// When the format changes IN ANY WAY, this number should be incremented.
const uint16_t VERSION_MINOR = 25; // SwiftImportAs
const uint16_t VERSION_MINOR = 26; // SwiftCopyable

const uint8_t kSwiftCopyable = 1;
const uint8_t kSwiftNonCopyable = 2;

using IdentifierID = llvm::PointerEmbeddedInt<unsigned, 31>;
using IdentifierIDField = llvm::BCVBR<16>;
Expand Down
7 changes: 7 additions & 0 deletions clang/lib/APINotes/APINotesReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -527,6 +527,13 @@ class TagTableInfo
Info.EnumExtensibility =
static_cast<EnumExtensibilityKind>((Payload & 0x3) - 1);

uint8_t Copyable =
endian::readNext<uint8_t, llvm::endianness::little>(Data);
if (Copyable == kSwiftNonCopyable)
Info.setSwiftCopyable(std::optional(false));
else if (Copyable == kSwiftCopyable)
Info.setSwiftCopyable(std::optional(true));

unsigned ImportAsLength =
endian::readNext<uint16_t, llvm::endianness::little>(Data);
if (ImportAsLength > 0) {
Expand Down
7 changes: 6 additions & 1 deletion clang/lib/APINotes/APINotesWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1128,7 +1128,7 @@ class TagTableInfo : public CommonTypeTableInfo<TagTableInfo, TagInfo> {
return 2 + (TI.SwiftImportAs ? TI.SwiftImportAs->size() : 0) +
2 + (TI.SwiftRetainOp ? TI.SwiftRetainOp->size() : 0) +
2 + (TI.SwiftReleaseOp ? TI.SwiftReleaseOp->size() : 0) +
1 + getCommonTypeInfoSize(TI);
2 + getCommonTypeInfoSize(TI);
}

void emitUnversionedInfo(raw_ostream &OS, const TagInfo &TI) {
Expand All @@ -1146,6 +1146,11 @@ class TagTableInfo : public CommonTypeTableInfo<TagTableInfo, TagInfo> {

writer.write<uint8_t>(Flags);

if (auto Copyable = TI.isSwiftCopyable())
writer.write<uint8_t>(*Copyable ? kSwiftCopyable : kSwiftNonCopyable);
else
writer.write<uint8_t>(0);

if (auto ImportAs = TI.SwiftImportAs) {
writer.write<uint16_t>(ImportAs->size() + 1);
OS.write(ImportAs->c_str(), ImportAs->size());
Expand Down
5 changes: 5 additions & 0 deletions clang/lib/APINotes/APINotesYAMLCompiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -419,6 +419,7 @@ struct Tag {
std::optional<EnumExtensibilityKind> EnumExtensibility;
std::optional<bool> FlagEnum;
std::optional<EnumConvenienceAliasKind> EnumConvenienceKind;
std::optional<bool> SwiftCopyable;
};

typedef std::vector<Tag> TagsSeq;
Expand Down Expand Up @@ -452,6 +453,7 @@ template <> struct MappingTraits<Tag> {
IO.mapOptional("EnumExtensibility", T.EnumExtensibility);
IO.mapOptional("FlagEnum", T.FlagEnum);
IO.mapOptional("EnumKind", T.EnumConvenienceKind);
IO.mapOptional("SwiftCopyable", T.SwiftCopyable);
}
};
} // namespace yaml
Expand Down Expand Up @@ -1009,6 +1011,9 @@ class YAMLConverter {
if (Tag.SwiftReleaseOp)
TI.SwiftReleaseOp = Tag.SwiftReleaseOp;

if (Tag.SwiftCopyable)
TI.setSwiftCopyable(Tag.SwiftCopyable);

if (Tag.EnumConvenienceKind) {
if (Tag.EnumExtensibility) {
emitError(
Expand Down
12 changes: 5 additions & 7 deletions clang/lib/AST/ASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1321,16 +1321,14 @@ void ASTContext::InitBuiltinTypes(const TargetInfo &Target,

// Placeholder type for OMP array sections.
if (LangOpts.OpenMP) {
InitBuiltinType(OMPArraySectionTy, BuiltinType::OMPArraySection);
InitBuiltinType(ArraySectionTy, BuiltinType::ArraySection);
InitBuiltinType(OMPArrayShapingTy, BuiltinType::OMPArrayShaping);
InitBuiltinType(OMPIteratorTy, BuiltinType::OMPIterator);
}
// Placeholder type for OpenACC array sections.
if (LangOpts.OpenACC) {
// FIXME: Once we implement OpenACC array sections in Sema, this will either
// be combined with the OpenMP type, or given its own type. In the meantime,
// just use the OpenMP type so that parsing can work.
InitBuiltinType(OMPArraySectionTy, BuiltinType::OMPArraySection);
// Placeholder type for OpenACC array sections, if we are ALSO in OMP mode,
// don't bother, as we're just using the same type as OMP.
if (LangOpts.OpenACC && !LangOpts.OpenMP) {
InitBuiltinType(ArraySectionTy, BuiltinType::ArraySection);
}
if (LangOpts.MatrixTypes)
InitBuiltinType(IncompleteMatrixIdxTy, BuiltinType::IncompleteMatrixIdx);
Expand Down
7 changes: 6 additions & 1 deletion clang/lib/AST/ComputeDependence.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -443,12 +443,17 @@ ExprDependence clang::computeDependence(ObjCIndirectCopyRestoreExpr *E) {
return E->getSubExpr()->getDependence();
}

ExprDependence clang::computeDependence(OMPArraySectionExpr *E) {
ExprDependence clang::computeDependence(ArraySectionExpr *E) {
auto D = E->getBase()->getDependence();
if (auto *LB = E->getLowerBound())
D |= LB->getDependence();
if (auto *Len = E->getLength())
D |= Len->getDependence();

if (E->isOMPArraySection()) {
if (auto *Stride = E->getStride())
D |= Stride->getDependence();
}
return D;
}

Expand Down
4 changes: 3 additions & 1 deletion clang/lib/AST/DeclBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1115,7 +1115,9 @@ int64_t Decl::getID() const {

const FunctionType *Decl::getFunctionType(bool BlocksToo) const {
QualType Ty;
if (const auto *D = dyn_cast<ValueDecl>(this))
if (isa<BindingDecl>(this))
return nullptr;
else if (const auto *D = dyn_cast<ValueDecl>(this))
Ty = D->getType();
else if (const auto *D = dyn_cast<TypedefNameDecl>(this))
Ty = D->getUnderlyingType();
Expand Down
6 changes: 3 additions & 3 deletions clang/lib/AST/Expr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3680,7 +3680,7 @@ bool Expr::HasSideEffects(const ASTContext &Ctx,
case ParenExprClass:
case ArraySubscriptExprClass:
case MatrixSubscriptExprClass:
case OMPArraySectionExprClass:
case ArraySectionExprClass:
case OMPArrayShapingExprClass:
case OMPIteratorExprClass:
case MemberExprClass:
Expand Down Expand Up @@ -5060,9 +5060,9 @@ QualType AtomicExpr::getValueType() const {
return T;
}

QualType OMPArraySectionExpr::getBaseOriginalType(const Expr *Base) {
QualType ArraySectionExpr::getBaseOriginalType(const Expr *Base) {
unsigned ArraySectionCount = 0;
while (auto *OASE = dyn_cast<OMPArraySectionExpr>(Base->IgnoreParens())) {
while (auto *OASE = dyn_cast<ArraySectionExpr>(Base->IgnoreParens())) {
Base = OASE->getBase();
++ArraySectionCount;
}
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/AST/ExprClassification.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
case Expr::FunctionParmPackExprClass:
case Expr::MSPropertyRefExprClass:
case Expr::MSPropertySubscriptExprClass:
case Expr::OMPArraySectionExprClass:
case Expr::ArraySectionExprClass:
case Expr::OMPArrayShapingExprClass:
case Expr::OMPIteratorExprClass:
return Cl::CL_LValue;
Expand Down
136 changes: 130 additions & 6 deletions clang/lib/AST/ExprConstant.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2706,7 +2706,11 @@ static bool checkFloatingPointResult(EvalInfo &Info, const Expr *E,
static bool HandleFloatToFloatCast(EvalInfo &Info, const Expr *E,
QualType SrcType, QualType DestType,
APFloat &Result) {
assert(isa<CastExpr>(E) || isa<CompoundAssignOperator>(E));
assert((isa<CastExpr>(E) || isa<CompoundAssignOperator>(E) ||
isa<ConvertVectorExpr>(E)) &&
"HandleFloatToFloatCast has been checked with only CastExpr, "
"CompoundAssignOperator and ConvertVectorExpr. Please either validate "
"the new expression or address the root cause of this usage.");
llvm::RoundingMode RM = getActiveRoundingMode(Info, E);
APFloat::opStatus St;
APFloat Value = Result;
Expand Down Expand Up @@ -9237,9 +9241,10 @@ bool PointerExprEvaluator::VisitCastExpr(const CastExpr *E) {
bool HasValidResult = !Result.InvalidBase && !Result.Designator.Invalid &&
!Result.IsNullPtr;
bool VoidPtrCastMaybeOK =
HasValidResult &&
Info.Ctx.hasSameUnqualifiedType(Result.Designator.getType(Info.Ctx),
E->getType()->getPointeeType());
Result.IsNullPtr ||
(HasValidResult &&
Info.Ctx.hasSimilarType(Result.Designator.getType(Info.Ctx),
E->getType()->getPointeeType()));
// 1. We'll allow it in std::allocator::allocate, and anything which that
// calls.
// 2. HACK 2022-03-28: Work around an issue with libstdc++'s
Expand Down Expand Up @@ -10709,8 +10714,11 @@ namespace {
bool VisitUnaryImag(const UnaryOperator *E);
bool VisitBinaryOperator(const BinaryOperator *E);
bool VisitUnaryOperator(const UnaryOperator *E);
bool VisitConvertVectorExpr(const ConvertVectorExpr *E);
bool VisitShuffleVectorExpr(const ShuffleVectorExpr *E);

// FIXME: Missing: conditional operator (for GNU
// conditional select), shufflevector, ExtVectorElementExpr
// conditional select), ExtVectorElementExpr
};
} // end anonymous namespace

Expand Down Expand Up @@ -10961,6 +10969,122 @@ bool VectorExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) {
return Success(APValue(ResultElements.data(), ResultElements.size()), E);
}

static bool handleVectorElementCast(EvalInfo &Info, const FPOptions FPO,
const Expr *E, QualType SourceTy,
QualType DestTy, APValue const &Original,
APValue &Result) {
if (SourceTy->isIntegerType()) {
if (DestTy->isRealFloatingType()) {
Result = APValue(APFloat(0.0));
return HandleIntToFloatCast(Info, E, FPO, SourceTy, Original.getInt(),
DestTy, Result.getFloat());
}
if (DestTy->isIntegerType()) {
Result = APValue(
HandleIntToIntCast(Info, E, DestTy, SourceTy, Original.getInt()));
return true;
}
} else if (SourceTy->isRealFloatingType()) {
if (DestTy->isRealFloatingType()) {
Result = Original;
return HandleFloatToFloatCast(Info, E, SourceTy, DestTy,
Result.getFloat());
}
if (DestTy->isIntegerType()) {
Result = APValue(APSInt());
return HandleFloatToIntCast(Info, E, SourceTy, Original.getFloat(),
DestTy, Result.getInt());
}
}

Info.FFDiag(E, diag::err_convertvector_constexpr_unsupported_vector_cast)
<< SourceTy << DestTy;
return false;
}

bool VectorExprEvaluator::VisitConvertVectorExpr(const ConvertVectorExpr *E) {
APValue Source;
QualType SourceVecType = E->getSrcExpr()->getType();
if (!EvaluateAsRValue(Info, E->getSrcExpr(), Source))
return false;

QualType DestTy = E->getType()->castAs<VectorType>()->getElementType();
QualType SourceTy = SourceVecType->castAs<VectorType>()->getElementType();

const FPOptions FPO = E->getFPFeaturesInEffect(Info.Ctx.getLangOpts());

auto SourceLen = Source.getVectorLength();
SmallVector<APValue, 4> ResultElements;
ResultElements.reserve(SourceLen);
for (unsigned EltNum = 0; EltNum < SourceLen; ++EltNum) {
APValue Elt;
if (!handleVectorElementCast(Info, FPO, E, SourceTy, DestTy,
Source.getVectorElt(EltNum), Elt))
return false;
ResultElements.push_back(std::move(Elt));
}

return Success(APValue(ResultElements.data(), ResultElements.size()), E);
}

static bool handleVectorShuffle(EvalInfo &Info, const ShuffleVectorExpr *E,
QualType ElemType, APValue const &VecVal1,
APValue const &VecVal2, unsigned EltNum,
APValue &Result) {
unsigned const TotalElementsInInputVector1 = VecVal1.getVectorLength();
unsigned const TotalElementsInInputVector2 = VecVal2.getVectorLength();

APSInt IndexVal = E->getShuffleMaskIdx(Info.Ctx, EltNum);
int64_t index = IndexVal.getExtValue();
// The spec says that -1 should be treated as undef for optimizations,
// but in constexpr we'd have to produce an APValue::Indeterminate,
// which is prohibited from being a top-level constant value. Emit a
// diagnostic instead.
if (index == -1) {
Info.FFDiag(
E, diag::err_shufflevector_minus_one_is_undefined_behavior_constexpr)
<< EltNum;
return false;
}

if (index < 0 ||
index >= TotalElementsInInputVector1 + TotalElementsInInputVector2)
llvm_unreachable("Out of bounds shuffle index");

if (index >= TotalElementsInInputVector1)
Result = VecVal2.getVectorElt(index - TotalElementsInInputVector1);
else
Result = VecVal1.getVectorElt(index);
return true;
}

bool VectorExprEvaluator::VisitShuffleVectorExpr(const ShuffleVectorExpr *E) {
APValue VecVal1;
const Expr *Vec1 = E->getExpr(0);
if (!EvaluateAsRValue(Info, Vec1, VecVal1))
return false;
APValue VecVal2;
const Expr *Vec2 = E->getExpr(1);
if (!EvaluateAsRValue(Info, Vec2, VecVal2))
return false;

VectorType const *DestVecTy = E->getType()->castAs<VectorType>();
QualType DestElTy = DestVecTy->getElementType();

auto TotalElementsInOutputVector = DestVecTy->getNumElements();

SmallVector<APValue, 4> ResultElements;
ResultElements.reserve(TotalElementsInOutputVector);
for (unsigned EltNum = 0; EltNum < TotalElementsInOutputVector; ++EltNum) {
APValue Elt;
if (!handleVectorShuffle(Info, E, DestElTy, VecVal1, VecVal2, EltNum, Elt))
return false;
ResultElements.push_back(std::move(Elt));
}

return Success(APValue(ResultElements.data(), ResultElements.size()), E);
}

//===----------------------------------------------------------------------===//
// Array Evaluation
//===----------------------------------------------------------------------===//
Expand Down Expand Up @@ -16130,7 +16254,7 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) {
case Expr::StringLiteralClass:
case Expr::ArraySubscriptExprClass:
case Expr::MatrixSubscriptExprClass:
case Expr::OMPArraySectionExprClass:
case Expr::ArraySectionExprClass:
case Expr::OMPArrayShapingExprClass:
case Expr::OMPIteratorExprClass:
case Expr::MemberExprClass:
Expand Down
426 changes: 244 additions & 182 deletions clang/lib/AST/Interp/ByteCodeExprGen.cpp

Large diffs are not rendered by default.

8 changes: 5 additions & 3 deletions clang/lib/AST/Interp/ByteCodeExprGen.h
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@ class ByteCodeExprGen : public ConstStmtVisitor<ByteCodeExprGen<Emitter>, bool>,
bool visitVarDecl(const VarDecl *VD);
/// Visit an APValue.
bool visitAPValue(const APValue &Val, PrimType ValType, const Expr *E);
bool visitAPValueInitializer(const APValue &Val, const Expr *E);

/// Visits an expression and converts it to a boolean.
bool visitBool(const Expr *E);
Expand Down Expand Up @@ -224,7 +225,8 @@ class ByteCodeExprGen : public ConstStmtVisitor<ByteCodeExprGen<Emitter>, bool>,
return this->emitFinishInitPop(I);
}

bool visitInitList(ArrayRef<const Expr *> Inits, const Expr *E);
bool visitInitList(ArrayRef<const Expr *> Inits, const Expr *ArrayFiller,
const Expr *E);
bool visitArrayElemInit(unsigned ElemIndex, const Expr *Init);

/// Creates a local primitive value.
Expand Down Expand Up @@ -283,8 +285,8 @@ class ByteCodeExprGen : public ConstStmtVisitor<ByteCodeExprGen<Emitter>, bool>,

bool emitRecordDestruction(const Record *R);
bool emitDestruction(const Descriptor *Desc);
unsigned collectBaseOffset(const RecordType *BaseType,
const RecordType *DerivedType);
unsigned collectBaseOffset(const QualType BaseType,
const QualType DerivedType);

protected:
/// Variable to storage mapping.
Expand Down
24 changes: 17 additions & 7 deletions clang/lib/AST/Interp/ByteCodeStmtGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -189,14 +189,23 @@ bool ByteCodeStmtGen<Emitter>::visitFunc(const FunctionDecl *F) {
if (!emitFieldInitializer(F, F->Offset, InitExpr))
return false;
} else if (const Type *Base = Init->getBaseClass()) {
// Base class initializer.
// Get This Base and call initializer on it.
const auto *BaseDecl = Base->getAsCXXRecordDecl();
assert(BaseDecl);
const Record::Base *B = R->getBase(BaseDecl);
assert(B);
if (!this->emitGetPtrThisBase(B->Offset, InitExpr))
return false;

if (Init->isBaseVirtual()) {
assert(R->getVirtualBase(BaseDecl));
if (!this->emitGetPtrThisVirtBase(BaseDecl, InitExpr))
return false;

} else {
// Base class initializer.
// Get This Base and call initializer on it.
const Record::Base *B = R->getBase(BaseDecl);
assert(B);
if (!this->emitGetPtrThisBase(B->Offset, InitExpr))
return false;
}

if (!this->visitInitializer(InitExpr))
return false;
if (!this->emitFinishInitPop(InitExpr))
Expand Down Expand Up @@ -323,7 +332,8 @@ bool ByteCodeStmtGen<Emitter>::visitCompoundStmt(
template <class Emitter>
bool ByteCodeStmtGen<Emitter>::visitDeclStmt(const DeclStmt *DS) {
for (auto *D : DS->decls()) {
if (isa<StaticAssertDecl, TagDecl, TypedefNameDecl, UsingEnumDecl>(D))
if (isa<StaticAssertDecl, TagDecl, TypedefNameDecl, UsingEnumDecl,
FunctionDecl>(D))
continue;

const auto *VD = dyn_cast<VarDecl>(D);
Expand Down
33 changes: 33 additions & 0 deletions clang/lib/AST/Interp/Context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -262,3 +262,36 @@ const Function *Context::getOrCreateFunction(const FunctionDecl *FD) {

return Func;
}

unsigned Context::collectBaseOffset(const RecordDecl *BaseDecl,
const RecordDecl *DerivedDecl) const {
assert(BaseDecl);
assert(DerivedDecl);
const auto *FinalDecl = cast<CXXRecordDecl>(BaseDecl);
const RecordDecl *CurDecl = DerivedDecl;
const Record *CurRecord = P->getOrCreateRecord(CurDecl);
assert(CurDecl && FinalDecl);

unsigned OffsetSum = 0;
for (;;) {
assert(CurRecord->getNumBases() > 0);
// One level up
for (const Record::Base &B : CurRecord->bases()) {
const auto *BaseDecl = cast<CXXRecordDecl>(B.Decl);

if (BaseDecl == FinalDecl || BaseDecl->isDerivedFrom(FinalDecl)) {
OffsetSum += B.Offset;
CurRecord = B.R;
CurDecl = BaseDecl;
break;
}
}
if (CurDecl == FinalDecl)
break;

// break;
}

assert(OffsetSum > 0);
return OffsetSum;
}
3 changes: 3 additions & 0 deletions clang/lib/AST/Interp/Context.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,9 @@ class Context final {
/// Returns the program. This is only needed for unittests.
Program &getProgram() const { return *P.get(); }

unsigned collectBaseOffset(const RecordDecl *BaseDecl,
const RecordDecl *DerivedDecl) const;

private:
/// Runs a function.
bool Run(State &Parent, const Function *Func, APValue &Result);
Expand Down
74 changes: 56 additions & 18 deletions clang/lib/AST/Interp/Descriptor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -136,28 +136,66 @@ static void moveArrayDesc(Block *B, const std::byte *Src, std::byte *Dst,
}
}

static void initField(Block *B, std::byte *Ptr, bool IsConst, bool IsMutable,
bool IsActive, const Descriptor *D,
unsigned FieldOffset) {
bool IsUnion = false; // FIXME
auto *Desc = reinterpret_cast<InlineDescriptor *>(Ptr + FieldOffset) - 1;
Desc->Offset = FieldOffset;
Desc->Desc = D;
Desc->IsInitialized = D->IsArray;
Desc->IsBase = false;
Desc->IsActive = IsActive && !IsUnion;
Desc->IsConst = IsConst || D->IsConst;
Desc->IsFieldMutable = IsMutable || D->IsMutable;

if (auto Fn = D->CtorFn)
Fn(B, Ptr + FieldOffset, Desc->IsConst, Desc->IsFieldMutable,
Desc->IsActive, D);
}

static void initBase(Block *B, std::byte *Ptr, bool IsConst, bool IsMutable,
bool IsActive, const Descriptor *D, unsigned FieldOffset,
bool IsVirtualBase) {
assert(D);
assert(D->ElemRecord);

bool IsUnion = D->ElemRecord->isUnion();
auto *Desc = reinterpret_cast<InlineDescriptor *>(Ptr + FieldOffset) - 1;
Desc->Offset = FieldOffset;
Desc->Desc = D;
Desc->IsInitialized = D->IsArray;
Desc->IsBase = true;
Desc->IsActive = IsActive && !IsUnion;
Desc->IsConst = IsConst || D->IsConst;
Desc->IsFieldMutable = IsMutable || D->IsMutable;

for (const auto &V : D->ElemRecord->bases())
initBase(B, Ptr + FieldOffset, IsConst, IsMutable, IsActive, V.Desc,
V.Offset, false);
for (const auto &F : D->ElemRecord->fields())
initField(B, Ptr + FieldOffset, IsConst, IsMutable, IsActive, F.Desc,
F.Offset);

// If this is initializing a virtual base, we do NOT want to consider its
// virtual bases, those are already flattened into the parent record when
// creating it.
if (IsVirtualBase)
return;

for (const auto &V : D->ElemRecord->virtual_bases())
initBase(B, Ptr + FieldOffset, IsConst, IsMutable, IsActive, V.Desc,
V.Offset, true);
}

static void ctorRecord(Block *B, std::byte *Ptr, bool IsConst, bool IsMutable,
bool IsActive, const Descriptor *D) {
const bool IsUnion = D->ElemRecord->isUnion();
auto CtorSub = [=](unsigned SubOff, const Descriptor *F, bool IsBase) {
auto *Desc = reinterpret_cast<InlineDescriptor *>(Ptr + SubOff) - 1;
Desc->Offset = SubOff;
Desc->Desc = F;
Desc->IsInitialized = F->IsArray && !IsBase;
Desc->IsBase = IsBase;
Desc->IsActive = IsActive && !IsUnion;
Desc->IsConst = IsConst || F->IsConst;
Desc->IsFieldMutable = IsMutable || F->IsMutable;
if (auto Fn = F->CtorFn)
Fn(B, Ptr + SubOff, Desc->IsConst, Desc->IsFieldMutable, Desc->IsActive,
F);
};
for (const auto &B : D->ElemRecord->bases())
CtorSub(B.Offset, B.Desc, /*isBase=*/true);
for (const auto &V : D->ElemRecord->bases())
initBase(B, Ptr, IsConst, IsMutable, IsActive, V.Desc, V.Offset, false);
for (const auto &F : D->ElemRecord->fields())
CtorSub(F.Offset, F.Desc, /*isBase=*/false);
initField(B, Ptr, IsConst, IsMutable, IsActive, F.Desc, F.Offset);
for (const auto &V : D->ElemRecord->virtual_bases())
CtorSub(V.Offset, V.Desc, /*isBase=*/true);
initBase(B, Ptr, IsConst, IsMutable, IsActive, V.Desc, V.Offset, true);
}

static void dtorRecord(Block *B, std::byte *Ptr, const Descriptor *D) {
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/AST/Interp/Descriptor.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,9 @@ struct InlineDescriptor {
InlineDescriptor(const Descriptor *D)
: Offset(sizeof(InlineDescriptor)), IsConst(false), IsInitialized(false),
IsBase(false), IsActive(false), IsFieldMutable(false), Desc(D) {}

void dump() const { dump(llvm::errs()); }
void dump(llvm::raw_ostream &OS) const;
};

/// Describes a memory block created by an allocation site.
Expand Down
31 changes: 28 additions & 3 deletions clang/lib/AST/Interp/Disasm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -200,14 +200,33 @@ LLVM_DUMP_METHOD void Descriptor::dump(llvm::raw_ostream &OS) const {
OS << " primitive";

if (isZeroSizeArray())
OS << " zero-size-arrary";
OS << " zero-size-array";
else if (isUnknownSizeArray())
OS << " unknown-size-array";

if (isDummy())
OS << " dummy";
}

LLVM_DUMP_METHOD void InlineDescriptor::dump(llvm::raw_ostream &OS) const {
{
ColorScope SC(OS, true, {llvm::raw_ostream::BLUE, true});
OS << "InlineDescriptor " << (const void *)this << "\n";
}
OS << "Offset: " << Offset << "\n";
OS << "IsConst: " << IsConst << "\n";
OS << "IsInitialized: " << IsInitialized << "\n";
OS << "IsBase: " << IsBase << "\n";
OS << "IsActive: " << IsActive << "\n";
OS << "IsFieldMutable: " << IsFieldMutable << "\n";
OS << "Desc: ";
if (Desc)
Desc->dump(OS);
else
OS << "nullptr";
OS << "\n";
}

LLVM_DUMP_METHOD void InterpFrame::dump(llvm::raw_ostream &OS,
unsigned Indent) const {
unsigned Spaces = Indent * 2;
Expand Down Expand Up @@ -251,8 +270,6 @@ LLVM_DUMP_METHOD void Record::dump(llvm::raw_ostream &OS, unsigned Indentation,
++I;
}

// FIXME: Virtual bases.

I = 0;
for (const Record::Field &F : fields()) {
OS.indent(Indent) << "- Field " << I << ": ";
Expand All @@ -263,6 +280,14 @@ LLVM_DUMP_METHOD void Record::dump(llvm::raw_ostream &OS, unsigned Indentation,
OS << ". Offset " << (Offset + F.Offset) << "\n";
++I;
}

I = 0;
for (const Record::Base &B : virtual_bases()) {
OS.indent(Indent) << "- Virtual Base " << I << ". Offset "
<< (Offset + B.Offset) << "\n";
B.R->dump(OS, Indentation + 1, Offset + B.Offset);
++I;
}
}

LLVM_DUMP_METHOD void Block::dump(llvm::raw_ostream &OS) const {
Expand Down
12 changes: 9 additions & 3 deletions clang/lib/AST/Interp/Interp.h
Original file line number Diff line number Diff line change
Expand Up @@ -1355,20 +1355,26 @@ inline bool VirtBaseHelper(InterpState &S, CodePtr OpPC, const RecordDecl *Decl,
while (Base.isBaseClass())
Base = Base.getBase();

auto *Field = Base.getRecord()->getVirtualBase(Decl);
S.Stk.push<Pointer>(Base.atField(Field->Offset));
const Record::Base *VirtBase = Base.getRecord()->getVirtualBase(Decl);
S.Stk.push<Pointer>(Base.atField(VirtBase->Offset));
return true;
}

inline bool GetPtrVirtBase(InterpState &S, CodePtr OpPC, const RecordDecl *D) {
inline bool GetPtrVirtBasePop(InterpState &S, CodePtr OpPC,
const RecordDecl *D) {
assert(D);
const Pointer &Ptr = S.Stk.pop<Pointer>();
if (!CheckNull(S, OpPC, Ptr, CSK_Base))
return false;
if (Ptr.isDummy()) // FIXME: Once we have type info for dummy pointers, this
// needs to go.
return false;
return VirtBaseHelper(S, OpPC, D, Ptr);
}

inline bool GetPtrThisVirtBase(InterpState &S, CodePtr OpPC,
const RecordDecl *D) {
assert(D);
if (S.checkingPotentialConstantExpression())
return false;
const Pointer &This = S.Current->getThis();
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/AST/Interp/Opcodes.td
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,7 @@ def GetPtrDerivedPop : Opcode {
}

// [Pointer] -> [Pointer]
def GetPtrVirtBase : Opcode {
def GetPtrVirtBasePop : Opcode {
// RecordDecl of base class.
let Args = [ArgRecordDecl];
}
Expand Down
3 changes: 2 additions & 1 deletion clang/lib/AST/Interp/Program.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,8 @@ std::optional<unsigned> Program::createGlobal(const ValueDecl *VD,
if (const auto *Var = dyn_cast<VarDecl>(VD)) {
IsStatic = Context::shouldBeGloballyIndexed(VD);
IsExtern = Var->hasExternalStorage();
} else if (isa<UnnamedGlobalConstantDecl, MSGuidDecl>(VD)) {
} else if (isa<UnnamedGlobalConstantDecl, MSGuidDecl,
TemplateParamObjectDecl>(VD)) {
IsStatic = true;
IsExtern = false;
} else {
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/AST/ItaniumMangle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4715,7 +4715,7 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity,
case Expr::MSPropertySubscriptExprClass:
case Expr::TypoExprClass: // This should no longer exist in the AST by now.
case Expr::RecoveryExprClass:
case Expr::OMPArraySectionExprClass:
case Expr::ArraySectionExprClass:
case Expr::OMPArrayShapingExprClass:
case Expr::OMPIteratorExprClass:
case Expr::CXXInheritedCtorInitExprClass:
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/AST/NSAPI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -462,7 +462,7 @@ NSAPI::getNSNumberFactoryMethodKind(QualType T) const {
case BuiltinType::PseudoObject:
case BuiltinType::BuiltinFn:
case BuiltinType::IncompleteMatrixIdx:
case BuiltinType::OMPArraySection:
case BuiltinType::ArraySection:
case BuiltinType::OMPArrayShaping:
case BuiltinType::OMPIterator:
case BuiltinType::BFloat16:
Expand Down
4 changes: 2 additions & 2 deletions clang/lib/AST/StmtPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1521,7 +1521,7 @@ void StmtPrinter::VisitMatrixSubscriptExpr(MatrixSubscriptExpr *Node) {
OS << "]";
}

void StmtPrinter::VisitOMPArraySectionExpr(OMPArraySectionExpr *Node) {
void StmtPrinter::VisitArraySectionExpr(ArraySectionExpr *Node) {
PrintExpr(Node->getBase());
OS << "[";
if (Node->getLowerBound())
Expand All @@ -1531,7 +1531,7 @@ void StmtPrinter::VisitOMPArraySectionExpr(OMPArraySectionExpr *Node) {
if (Node->getLength())
PrintExpr(Node->getLength());
}
if (Node->getColonLocSecond().isValid()) {
if (Node->isOMPArraySection() && Node->getColonLocSecond().isValid()) {
OS << ":";
if (Node->getStride())
PrintExpr(Node->getStride());
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/AST/StmtProfile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1435,7 +1435,7 @@ void StmtProfiler::VisitMatrixSubscriptExpr(const MatrixSubscriptExpr *S) {
VisitExpr(S);
}

void StmtProfiler::VisitOMPArraySectionExpr(const OMPArraySectionExpr *S) {
void StmtProfiler::VisitArraySectionExpr(const ArraySectionExpr *S) {
VisitExpr(S);
}

Expand Down
18 changes: 15 additions & 3 deletions clang/lib/AST/Type.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2510,6 +2510,18 @@ bool Type::isSveVLSBuiltinType() const {
return false;
}

QualType Type::getSizelessVectorEltType(const ASTContext &Ctx) const {
assert(isSizelessVectorType() && "Must be sizeless vector type");
// Currently supports SVE and RVV
if (isSVESizelessBuiltinType())
return getSveEltType(Ctx);

if (isRVVSizelessBuiltinType())
return getRVVEltType(Ctx);

llvm_unreachable("Unhandled type");
}

QualType Type::getSveEltType(const ASTContext &Ctx) const {
assert(isSveVLSBuiltinType() && "unsupported type!");

Expand Down Expand Up @@ -3413,8 +3425,8 @@ StringRef BuiltinType::getName(const PrintingPolicy &Policy) const {
return "reserve_id_t";
case IncompleteMatrixIdx:
return "<incomplete matrix index type>";
case OMPArraySection:
return "<OpenMP array section type>";
case ArraySection:
return "<array section type>";
case OMPArrayShaping:
return "<OpenMP array shaping type>";
case OMPIterator:
Expand Down Expand Up @@ -4710,7 +4722,7 @@ bool Type::canHaveNullability(bool ResultIfUnknown) const {
case BuiltinType::BuiltinFn:
case BuiltinType::NullPtr:
case BuiltinType::IncompleteMatrixIdx:
case BuiltinType::OMPArraySection:
case BuiltinType::ArraySection:
case BuiltinType::OMPArrayShaping:
case BuiltinType::OMPIterator:
return false;
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/AST/TypeLoc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -429,7 +429,7 @@ TypeSpecifierType BuiltinTypeLoc::getWrittenTypeSpec() const {
#include "clang/Basic/WebAssemblyReferenceTypes.def"
case BuiltinType::BuiltinFn:
case BuiltinType::IncompleteMatrixIdx:
case BuiltinType::OMPArraySection:
case BuiltinType::ArraySection:
case BuiltinType::OMPArrayShaping:
case BuiltinType::OMPIterator:
return TST_unspecified;
Expand Down
16 changes: 12 additions & 4 deletions clang/lib/Analysis/FlowSensitive/ASTOps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,20 @@ namespace clang::dataflow {

const Expr &ignoreCFGOmittedNodes(const Expr &E) {
const Expr *Current = &E;
if (auto *EWC = dyn_cast<ExprWithCleanups>(Current)) {
Current = EWC->getSubExpr();
const Expr *Last = nullptr;
while (Current != Last) {
Last = Current;
if (auto *EWC = dyn_cast<ExprWithCleanups>(Current)) {
Current = EWC->getSubExpr();
assert(Current != nullptr);
}
if (auto *CE = dyn_cast<ConstantExpr>(Current)) {
Current = CE->getSubExpr();
assert(Current != nullptr);
}
Current = Current->IgnoreParens();
assert(Current != nullptr);
}
Current = Current->IgnoreParens();
assert(Current != nullptr);
return *Current;
}

Expand Down
6 changes: 5 additions & 1 deletion clang/lib/Analysis/FlowSensitive/Transfer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,11 @@ namespace dataflow {

const Environment *StmtToEnvMap::getEnvironment(const Stmt &S) const {
auto BlockIt = ACFG.getStmtToBlock().find(&ignoreCFGOmittedNodes(S));
assert(BlockIt != ACFG.getStmtToBlock().end());
if (BlockIt == ACFG.getStmtToBlock().end()) {
assert(false);
// Return null to avoid dereferencing the end iterator in non-assert builds.
return nullptr;
}
if (!ACFG.isBlockReachable(*BlockIt->getSecond()))
return nullptr;
if (BlockIt->getSecond()->getBlockID() == CurBlockID)
Expand Down
14 changes: 8 additions & 6 deletions clang/lib/Basic/FileManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,6 @@ using namespace clang;

#define DEBUG_TYPE "file-search"

ALWAYS_ENABLED_STATISTIC(NumDirLookups, "Number of directory lookups.");
ALWAYS_ENABLED_STATISTIC(NumFileLookups, "Number of file lookups.");
ALWAYS_ENABLED_STATISTIC(NumDirCacheMisses,
"Number of directory cache misses.");
ALWAYS_ENABLED_STATISTIC(NumFileCacheMisses, "Number of file cache misses.");

//===----------------------------------------------------------------------===//
// Common logic.
//===----------------------------------------------------------------------===//
Expand Down Expand Up @@ -656,6 +650,14 @@ StringRef FileManager::getCanonicalName(const void *Entry, StringRef Name) {
return CanonicalName;
}

void FileManager::AddStats(const FileManager &Other) {
assert(&Other != this && "Collecting stats into the same FileManager");
NumDirLookups += Other.NumDirLookups;
NumFileLookups += Other.NumFileLookups;
NumDirCacheMisses += Other.NumDirCacheMisses;
NumFileCacheMisses += Other.NumFileCacheMisses;
}

void FileManager::PrintStats() const {
llvm::errs() << "\n*** File Manager Stats:\n";
llvm::errs() << UniqueRealFiles.size() << " real files found, "
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/Basic/Targets/ARM.h
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,10 @@ class LLVM_LIBRARY_VISIBILITY ARMTargetInfo : public TargetInfo {
bool hasBitIntType() const override { return true; }

const char *getBFloat16Mangling() const override { return "u6__bf16"; };

std::pair<unsigned, unsigned> hardwareInterferenceSizes() const override {
return std::make_pair(getTriple().isArch64Bit() ? 256 : 64, 64);
}
};

class LLVM_LIBRARY_VISIBILITY ARMleTargetInfo : public ARMTargetInfo {
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/Basic/Targets/AVR.h
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,10 @@ class LLVM_LIBRARY_VISIBILITY AVRTargetInfo : public TargetInfo {
std::optional<std::string> handleAsmEscapedChar(char EscChar) const override;
StringRef getABI() const override { return ABI; }

std::pair<unsigned, unsigned> hardwareInterferenceSizes() const override {
return std::make_pair(32, 32);
}

protected:
std::string CPU;
StringRef ABI;
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/Basic/Targets/BPF.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,10 @@ class LLVM_LIBRARY_VISIBILITY BPFTargetInfo : public TargetInfo {
StringRef CPUName(Name);
return isValidCPUName(CPUName);
}

std::pair<unsigned, unsigned> hardwareInterferenceSizes() const override {
return std::make_pair(32, 32);
}
};
} // namespace targets
} // namespace clang
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/Basic/Targets/M68k.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ class LLVM_LIBRARY_VISIBILITY M68kTargetInfo : public TargetInfo {
BuiltinVaListKind getBuiltinVaListKind() const override;
bool setCPU(const std::string &Name) override;
CallingConvCheckResult checkCallingConvention(CallingConv CC) const override;

std::pair<unsigned, unsigned> hardwareInterferenceSizes() const override {
return std::make_pair(32, 32);
}
};

} // namespace targets
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/Basic/Targets/Mips.h
Original file line number Diff line number Diff line change
Expand Up @@ -431,6 +431,10 @@ class LLVM_LIBRARY_VISIBILITY MipsTargetInfo : public TargetInfo {

bool validateTarget(DiagnosticsEngine &Diags) const override;
bool hasBitIntType() const override { return true; }

std::pair<unsigned, unsigned> hardwareInterferenceSizes() const override {
return std::make_pair(32, 32);
}
};
} // namespace targets
} // namespace clang
Expand Down
8 changes: 8 additions & 0 deletions clang/lib/Basic/Targets/PPC.h
Original file line number Diff line number Diff line change
Expand Up @@ -423,6 +423,10 @@ class LLVM_LIBRARY_VISIBILITY PPC32TargetInfo : public PPCTargetInfo {
// This is the ELF definition
return TargetInfo::PowerABIBuiltinVaList;
}

std::pair<unsigned, unsigned> hardwareInterferenceSizes() const override {
return std::make_pair(32, 32);
}
};

// Note: ABI differences may eventually require us to have a separate
Expand Down Expand Up @@ -503,6 +507,10 @@ class LLVM_LIBRARY_VISIBILITY PPC64TargetInfo : public PPCTargetInfo {
return CCCR_Warning;
}
}

std::pair<unsigned, unsigned> hardwareInterferenceSizes() const override {
return std::make_pair(128, 128);
}
};

class LLVM_LIBRARY_VISIBILITY AIXPPC32TargetInfo :
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/Basic/Targets/RISCV.h
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,10 @@ class RISCVTargetInfo : public TargetInfo {
void fillValidTuneCPUList(SmallVectorImpl<StringRef> &Values) const override;
bool supportsTargetAttributeTune() const override { return true; }
ParsedTargetAttr parseTargetAttr(StringRef Str) const override;

std::pair<unsigned, unsigned> hardwareInterferenceSizes() const override {
return std::make_pair(32, 32);
}
};
class LLVM_LIBRARY_VISIBILITY RISCV32TargetInfo : public RISCVTargetInfo {
public:
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/Basic/Targets/Sparc.h
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,10 @@ class LLVM_LIBRARY_VISIBILITY SparcTargetInfo : public TargetInfo {
CPU = getCPUKind(Name);
return CPU != CK_GENERIC;
}

std::pair<unsigned, unsigned> hardwareInterferenceSizes() const override {
return std::make_pair(32, 32);
}
};

// SPARC v8 is the 32-bit mode selected by Triple::sparc.
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/Basic/Targets/SystemZ.h
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,10 @@ class LLVM_LIBRARY_VISIBILITY SystemZTargetInfo : public TargetInfo {
int getEHDataRegisterNumber(unsigned RegNo) const override {
return RegNo < 4 ? 6 + RegNo : -1;
}

std::pair<unsigned, unsigned> hardwareInterferenceSizes() const override {
return std::make_pair(256, 256);
}
};
} // namespace targets
} // namespace clang
Expand Down
31 changes: 24 additions & 7 deletions clang/lib/Basic/Targets/WebAssembly.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ bool WebAssemblyTargetInfo::hasFeature(StringRef Feature) const {
return llvm::StringSwitch<bool>(Feature)
.Case("simd128", SIMDLevel >= SIMD128)
.Case("relaxed-simd", SIMDLevel >= RelaxedSIMD)
.Case("half-precision", HasHalfPrecision)
.Case("nontrapping-fptoint", HasNontrappingFPToInt)
.Case("sign-ext", HasSignExt)
.Case("exception-handling", HasExceptionHandling)
Expand Down Expand Up @@ -147,19 +148,26 @@ void WebAssemblyTargetInfo::setFeatureEnabled(llvm::StringMap<bool> &Features,
bool WebAssemblyTargetInfo::initFeatureMap(
llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU,
const std::vector<std::string> &FeaturesVec) const {
if (CPU == "bleeding-edge") {
auto addGenericFeatures = [&]() {
Features["multivalue"] = true;
Features["mutable-globals"] = true;
Features["reference-types"] = true;
Features["sign-ext"] = true;
};
auto addBleedingEdgeFeatures = [&]() {
addGenericFeatures();
Features["atomics"] = true;
Features["bulk-memory"] = true;
Features["multimemory"] = true;
Features["mutable-globals"] = true;
Features["nontrapping-fptoint"] = true;
Features["reference-types"] = true;
Features["sign-ext"] = true;
Features["tail-call"] = true;
Features["half-precision"] = true;
setSIMDLevel(Features, SIMD128, true);
} else if (CPU == "generic") {
Features["mutable-globals"] = true;
Features["sign-ext"] = true;
};
if (CPU == "generic") {
addGenericFeatures();
} else if (CPU == "bleeding-edge") {
addBleedingEdgeFeatures();
}

return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec);
Expand Down Expand Up @@ -216,6 +224,15 @@ bool WebAssemblyTargetInfo::handleTargetFeatures(
HasBulkMemory = false;
continue;
}
if (Feature == "+half-precision") {
SIMDLevel = std::max(SIMDLevel, SIMD128);
HasHalfPrecision = true;
continue;
}
if (Feature == "-half-precision") {
HasHalfPrecision = false;
continue;
}
if (Feature == "+atomics") {
HasAtomics = true;
continue;
Expand Down
1 change: 1 addition & 0 deletions clang/lib/Basic/Targets/WebAssembly.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ class LLVM_LIBRARY_VISIBILITY WebAssemblyTargetInfo : public TargetInfo {
bool HasReferenceTypes = false;
bool HasExtendedConst = false;
bool HasMultiMemory = false;
bool HasHalfPrecision = false;

std::string ABI;

Expand Down
18 changes: 12 additions & 6 deletions clang/lib/CodeGen/CGBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3628,7 +3628,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
// frexpl instead of legalizing this type in the BE.
if (&getTarget().getLongDoubleFormat() == &llvm::APFloat::PPCDoubleDouble())
break;
LLVM_FALLTHROUGH;
[[fallthrough]];
}
case Builtin::BI__builtin_frexp:
case Builtin::BI__builtin_frexpf:
Expand Down Expand Up @@ -3885,9 +3885,12 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
}

case Builtin::BI__builtin_reduce_max: {
auto GetIntrinsicID = [](QualType QT) {
auto GetIntrinsicID = [this](QualType QT) {
if (auto *VecTy = QT->getAs<VectorType>())
QT = VecTy->getElementType();
else if (QT->isSizelessVectorType())
QT = QT->getSizelessVectorEltType(CGM.getContext());

if (QT->isSignedIntegerType())
return llvm::Intrinsic::vector_reduce_smax;
if (QT->isUnsignedIntegerType())
Expand All @@ -3900,9 +3903,12 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
}

case Builtin::BI__builtin_reduce_min: {
auto GetIntrinsicID = [](QualType QT) {
auto GetIntrinsicID = [this](QualType QT) {
if (auto *VecTy = QT->getAs<VectorType>())
QT = VecTy->getElementType();
else if (QT->isSizelessVectorType())
QT = QT->getSizelessVectorEltType(CGM.getContext());

if (QT->isSignedIntegerType())
return llvm::Intrinsic::vector_reduce_smin;
if (QT->isUnsignedIntegerType())
Expand Down Expand Up @@ -5366,7 +5372,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
case Builtin::BI__builtin_ptrauth_auth_and_resign:
if (Args[4]->getType()->isPointerTy())
Args[4] = Builder.CreatePtrToInt(Args[4], IntPtrTy);
LLVM_FALLTHROUGH;
[[fallthrough]];

case Builtin::BI__builtin_ptrauth_auth:
case Builtin::BI__builtin_ptrauth_sign_unauthenticated:
Expand Down Expand Up @@ -18850,7 +18856,7 @@ Value *CodeGenFunction::EmitAMDGPUBuiltinExpr(unsigned BuiltinID,
case AMDGPU::BI__builtin_amdgcn_wmma_f16_16x16x16_f16_w32_gfx12:
case AMDGPU::BI__builtin_amdgcn_wmma_f16_16x16x16_f16_w64_gfx12:
AppendFalseForOpselArg = true;
LLVM_FALLTHROUGH;
[[fallthrough]];
case AMDGPU::BI__builtin_amdgcn_wmma_f16_16x16x16_f16_w32:
case AMDGPU::BI__builtin_amdgcn_wmma_f16_16x16x16_f16_w64:
ArgsForMatchingMatrixTypes = {2, 0}; // CD, AB
Expand All @@ -18859,7 +18865,7 @@ Value *CodeGenFunction::EmitAMDGPUBuiltinExpr(unsigned BuiltinID,
case AMDGPU::BI__builtin_amdgcn_wmma_bf16_16x16x16_bf16_w32_gfx12:
case AMDGPU::BI__builtin_amdgcn_wmma_bf16_16x16x16_bf16_w64_gfx12:
AppendFalseForOpselArg = true;
LLVM_FALLTHROUGH;
[[fallthrough]];
case AMDGPU::BI__builtin_amdgcn_wmma_bf16_16x16x16_bf16_w32:
case AMDGPU::BI__builtin_amdgcn_wmma_bf16_16x16x16_bf16_w64:
ArgsForMatchingMatrixTypes = {2, 0}; // CD, AB
Expand Down
Loading