239 changes: 154 additions & 85 deletions clang/lib/Sema/SemaExprCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4294,6 +4294,20 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
return From;
}

// adjustVectorType - Compute the intermediate cast type casting elements of the
// from type to the elements of the to type without resizing the vector.
static QualType adjustVectorType(ASTContext &Context, QualType FromTy,
QualType ToType, QualType *ElTy = nullptr) {
auto *ToVec = ToType->castAs<VectorType>();
QualType ElType = ToVec->getElementType();
if (ElTy)
*ElTy = ElType;
if (!FromTy->isVectorType())
return ElType;
auto *FromVec = FromTy->castAs<VectorType>();
return Context.getExtVectorType(ElType, FromVec->getNumElements());
}

ExprResult
Sema::PerformImplicitConversion(Expr *From, QualType ToType,
const StandardConversionSequence& SCS,
Expand Down Expand Up @@ -4443,27 +4457,36 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
break;

case ICK_Integral_Promotion:
case ICK_Integral_Conversion:
if (ToType->isBooleanType()) {
case ICK_Integral_Conversion: {
QualType ElTy = ToType;
QualType StepTy = ToType;
if (ToType->isVectorType())
StepTy = adjustVectorType(Context, FromType, ToType, &ElTy);
if (ElTy->isBooleanType()) {
assert(FromType->castAs<EnumType>()->getDecl()->isFixed() &&
SCS.Second == ICK_Integral_Promotion &&
"only enums with fixed underlying type can promote to bool");
From = ImpCastExprToType(From, ToType, CK_IntegralToBoolean, VK_PRValue,
From = ImpCastExprToType(From, StepTy, CK_IntegralToBoolean, VK_PRValue,
/*BasePath=*/nullptr, CCK)
.get();
} else {
From = ImpCastExprToType(From, ToType, CK_IntegralCast, VK_PRValue,
From = ImpCastExprToType(From, StepTy, CK_IntegralCast, VK_PRValue,
/*BasePath=*/nullptr, CCK)
.get();
}
break;
}

case ICK_Floating_Promotion:
case ICK_Floating_Conversion:
From = ImpCastExprToType(From, ToType, CK_FloatingCast, VK_PRValue,
case ICK_Floating_Conversion: {
QualType StepTy = ToType;
if (ToType->isVectorType())
StepTy = adjustVectorType(Context, FromType, ToType);
From = ImpCastExprToType(From, StepTy, CK_FloatingCast, VK_PRValue,
/*BasePath=*/nullptr, CCK)
.get();
break;
}

case ICK_Complex_Promotion:
case ICK_Complex_Conversion: {
Expand All @@ -4486,16 +4509,21 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
break;
}

case ICK_Floating_Integral:
if (ToType->isRealFloatingType())
From = ImpCastExprToType(From, ToType, CK_IntegralToFloating, VK_PRValue,
case ICK_Floating_Integral: {
QualType ElTy = ToType;
QualType StepTy = ToType;
if (ToType->isVectorType())
StepTy = adjustVectorType(Context, FromType, ToType, &ElTy);
if (ElTy->isRealFloatingType())
From = ImpCastExprToType(From, StepTy, CK_IntegralToFloating, VK_PRValue,
/*BasePath=*/nullptr, CCK)
.get();
else
From = ImpCastExprToType(From, ToType, CK_FloatingToIntegral, VK_PRValue,
From = ImpCastExprToType(From, StepTy, CK_FloatingToIntegral, VK_PRValue,
/*BasePath=*/nullptr, CCK)
.get();
break;
}

case ICK_Fixed_Point_Conversion:
assert((FromType->isFixedPointType() || ToType->isFixedPointType()) &&
Expand Down Expand Up @@ -4617,18 +4645,26 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
break;
}

case ICK_Boolean_Conversion:
case ICK_Boolean_Conversion: {
// Perform half-to-boolean conversion via float.
if (From->getType()->isHalfType()) {
From = ImpCastExprToType(From, Context.FloatTy, CK_FloatingCast).get();
FromType = Context.FloatTy;
}
QualType ElTy = FromType;
QualType StepTy = ToType;
if (FromType->isVectorType()) {
if (getLangOpts().HLSL)
StepTy = adjustVectorType(Context, FromType, ToType);
ElTy = FromType->castAs<VectorType>()->getElementType();
}

From = ImpCastExprToType(From, Context.BoolTy,
ScalarTypeToBooleanCastKind(FromType), VK_PRValue,
From = ImpCastExprToType(From, StepTy, ScalarTypeToBooleanCastKind(ElTy),
VK_PRValue,
/*BasePath=*/nullptr, CCK)
.get();
break;
}

case ICK_Derived_To_Base: {
CXXCastPath BasePath;
Expand Down Expand Up @@ -4754,22 +4790,6 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
CK_ZeroToOCLOpaqueType,
From->getValueKind()).get();
break;
case ICK_HLSL_Vector_Truncation: {
// Note: HLSL built-in vectors are ExtVectors. Since this truncates a vector
// to a smaller vector, this can only operate on arguments where the source
// and destination types are ExtVectors.
assert(From->getType()->isExtVectorType() && ToType->isExtVectorType() &&
"HLSL vector truncation should only apply to ExtVectors");
auto *FromVec = From->getType()->castAs<VectorType>();
auto *ToVec = ToType->castAs<VectorType>();
QualType ElType = FromVec->getElementType();
QualType TruncTy =
Context.getExtVectorType(ElType, ToVec->getNumElements());
From = ImpCastExprToType(From, TruncTy, CK_HLSLVectorTruncation,
From->getValueKind())
.get();
break;
}

case ICK_Lvalue_To_Rvalue:
case ICK_Array_To_Pointer:
Expand All @@ -4780,73 +4800,45 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
case ICK_C_Only_Conversion:
case ICK_Incompatible_Pointer_Conversion:
case ICK_HLSL_Array_RValue:
case ICK_HLSL_Vector_Truncation:
case ICK_HLSL_Vector_Splat:
llvm_unreachable("Improper second standard conversion");
}

if (SCS.Element != ICK_Identity) {
if (SCS.Dimension != ICK_Identity) {
// If SCS.Element is not ICK_Identity the To and From types must be HLSL
// vectors or matrices.

// TODO: Support HLSL matrices.
assert((!From->getType()->isMatrixType() && !ToType->isMatrixType()) &&
"Element conversion for matrix types is not implemented yet.");
assert(From->getType()->isVectorType() && ToType->isVectorType() &&
"Element conversion is only supported for vector types.");
assert(From->getType()->getAs<VectorType>()->getNumElements() ==
ToType->getAs<VectorType>()->getNumElements() &&
"Element conversion is only supported for vectors with the same "
"element counts.");
QualType FromElTy = From->getType()->getAs<VectorType>()->getElementType();
unsigned NumElts = ToType->getAs<VectorType>()->getNumElements();
switch (SCS.Element) {
case ICK_Boolean_Conversion:
// Perform half-to-boolean conversion via float.
if (FromElTy->isHalfType()) {
QualType FPExtType = Context.getExtVectorType(FromElTy, NumElts);
From = ImpCastExprToType(From, FPExtType, CK_FloatingCast).get();
FromType = FPExtType;
}

From =
ImpCastExprToType(From, ToType, ScalarTypeToBooleanCastKind(FromElTy),
VK_PRValue,
/*BasePath=*/nullptr, CCK)
.get();
break;
case ICK_Integral_Promotion:
case ICK_Integral_Conversion:
if (ToType->isBooleanType()) {
assert(FromType->castAs<EnumType>()->getDecl()->isFixed() &&
SCS.Second == ICK_Integral_Promotion &&
"only enums with fixed underlying type can promote to bool");
From = ImpCastExprToType(From, ToType, CK_IntegralToBoolean, VK_PRValue,
/*BasePath=*/nullptr, CCK)
.get();
} else {
From = ImpCastExprToType(From, ToType, CK_IntegralCast, VK_PRValue,
/*BasePath=*/nullptr, CCK)
.get();
}
break;

case ICK_Floating_Promotion:
case ICK_Floating_Conversion:
From = ImpCastExprToType(From, ToType, CK_FloatingCast, VK_PRValue,
"Dimension conversion for matrix types is not implemented yet.");
assert(ToType->isVectorType() &&
"Dimension conversion is only supported for vector types.");
switch (SCS.Dimension) {
case ICK_HLSL_Vector_Splat: {
// Vector splat from any arithmetic type to a vector.
Expr *Elem = prepareVectorSplat(ToType, From).get();
From = ImpCastExprToType(Elem, ToType, CK_VectorSplat, VK_PRValue,
/*BasePath=*/nullptr, CCK)
.get();
break;
case ICK_Floating_Integral:
if (ToType->hasFloatingRepresentation())
From =
ImpCastExprToType(From, ToType, CK_IntegralToFloating, VK_PRValue,
/*BasePath=*/nullptr, CCK)
.get();
else
From =
ImpCastExprToType(From, ToType, CK_FloatingToIntegral, VK_PRValue,
/*BasePath=*/nullptr, CCK)
.get();
}
case ICK_HLSL_Vector_Truncation: {
// Note: HLSL built-in vectors are ExtVectors. Since this truncates a
// vector to a smaller vector, this can only operate on arguments where
// the source and destination types are ExtVectors.
assert(From->getType()->isExtVectorType() && ToType->isExtVectorType() &&
"HLSL vector truncation should only apply to ExtVectors");
auto *FromVec = From->getType()->castAs<VectorType>();
auto *ToVec = ToType->castAs<VectorType>();
QualType ElType = FromVec->getElementType();
QualType TruncTy =
Context.getExtVectorType(ElType, ToVec->getNumElements());
From = ImpCastExprToType(From, TruncTy, CK_HLSLVectorTruncation,
From->getValueKind())
.get();
break;
}
case ICK_Identity:
default:
llvm_unreachable("Improper element standard conversion");
Expand Down Expand Up @@ -5129,6 +5121,83 @@ static bool HasNoThrowOperator(const RecordType *RT, OverloadedOperatorKind Op,
return false;
}

static bool HasNonDeletedDefaultedEqualityComparison(Sema &S,
const CXXRecordDecl *Decl,
SourceLocation KeyLoc) {
if (Decl->isUnion())
return false;
if (Decl->isLambda())
return Decl->isCapturelessLambda();

{
EnterExpressionEvaluationContext UnevaluatedContext(
S, Sema::ExpressionEvaluationContext::Unevaluated);
Sema::SFINAETrap SFINAE(S, /*AccessCheckingSFINAE=*/true);
Sema::ContextRAII TUContext(S, S.Context.getTranslationUnitDecl());

// const ClassT& obj;
OpaqueValueExpr Operand(
{}, Decl->getTypeForDecl()->getCanonicalTypeUnqualified().withConst(),
ExprValueKind::VK_LValue);
UnresolvedSet<16> Functions;
// obj == obj;
S.LookupBinOp(S.TUScope, {}, BinaryOperatorKind::BO_EQ, Functions);

auto Result = S.CreateOverloadedBinOp(KeyLoc, BinaryOperatorKind::BO_EQ,
Functions, &Operand, &Operand);
if (Result.isInvalid() || SFINAE.hasErrorOccurred())
return false;

const auto *CallExpr = dyn_cast<CXXOperatorCallExpr>(Result.get());
if (!CallExpr)
return false;
const auto *Callee = CallExpr->getDirectCallee();
auto ParamT = Callee->getParamDecl(0)->getType();
if (!Callee->isDefaulted())
return false;
if (!ParamT->isReferenceType() && !Decl->isTriviallyCopyable())
return false;
if (ParamT.getNonReferenceType()->getUnqualifiedDesugaredType() !=
Decl->getTypeForDecl())
return false;
}

return llvm::all_of(Decl->bases(),
[&](const CXXBaseSpecifier &BS) {
if (const auto *RD = BS.getType()->getAsCXXRecordDecl())
return HasNonDeletedDefaultedEqualityComparison(
S, RD, KeyLoc);
return true;
}) &&
llvm::all_of(Decl->fields(), [&](const FieldDecl *FD) {
auto Type = FD->getType();
if (Type->isArrayType())
Type = Type->getBaseElementTypeUnsafe()
->getCanonicalTypeUnqualified();

if (Type->isReferenceType() || Type->isEnumeralType())
return false;
if (const auto *RD = Type->getAsCXXRecordDecl())
return HasNonDeletedDefaultedEqualityComparison(S, RD, KeyLoc);
return true;
});
}

static bool isTriviallyEqualityComparableType(Sema &S, QualType Type, SourceLocation KeyLoc) {
QualType CanonicalType = Type.getCanonicalType();
if (CanonicalType->isIncompleteType() || CanonicalType->isDependentType() ||
CanonicalType->isEnumeralType() || CanonicalType->isArrayType())
return false;

if (const auto *RD = CanonicalType->getAsCXXRecordDecl()) {
if (!HasNonDeletedDefaultedEqualityComparison(S, RD, KeyLoc))
return false;
}

return S.getASTContext().hasUniqueObjectRepresentations(
CanonicalType, /*CheckIfTriviallyCopyable=*/false);
}

static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT,
SourceLocation KeyLoc,
TypeSourceInfo *TInfo) {
Expand Down Expand Up @@ -5561,7 +5630,7 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT,
Self.Diag(KeyLoc, diag::err_builtin_pass_in_regs_non_class) << T;
return false;
case UTT_IsTriviallyEqualityComparable:
return T.isTriviallyEqualityComparableType(C);
return isTriviallyEqualityComparableType(Self, T, KeyLoc);
}
}

Expand Down
22 changes: 22 additions & 0 deletions clang/lib/Sema/SemaHLSL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -437,6 +437,28 @@ void SemaHLSL::handleShaderAttr(Decl *D, const ParsedAttr &AL) {
D->addAttr(NewAttr);
}

void SemaHLSL::handleResourceClassAttr(Decl *D, const ParsedAttr &AL) {
if (!AL.isArgIdent(0)) {
Diag(AL.getLoc(), diag::err_attribute_argument_type)
<< AL << AANT_ArgumentIdentifier;
return;
}

IdentifierLoc *Loc = AL.getArgAsIdent(0);
StringRef Identifier = Loc->Ident->getName();
SourceLocation ArgLoc = Loc->Loc;

// Validate.
llvm::dxil::ResourceClass RC;
if (!HLSLResourceClassAttr::ConvertStrToResourceClass(Identifier, RC)) {
Diag(ArgLoc, diag::warn_attribute_type_not_supported)
<< "ResourceClass" << Identifier;
return;
}

D->addAttr(HLSLResourceClassAttr::Create(getASTContext(), RC, ArgLoc));
}

void SemaHLSL::handleResourceBindingAttr(Decl *D, const ParsedAttr &AL) {
StringRef Space = "space0";
StringRef Slot = "";
Expand Down
145 changes: 71 additions & 74 deletions clang/lib/Sema/SemaOpenMP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9056,84 +9056,81 @@ void SemaOpenMP::ActOnOpenMPLoopInitialization(SourceLocation ForLoc,
assert(getLangOpts().OpenMP && "OpenMP is not active.");
assert(Init && "Expected loop in canonical form.");
unsigned AssociatedLoops = DSAStack->getAssociatedLoops();
if (AssociatedLoops > 0 &&
isOpenMPLoopDirective(DSAStack->getCurrentDirective())) {
DSAStack->loopStart();
OpenMPIterationSpaceChecker ISC(SemaRef, /*SupportsNonRectangular=*/true,
*DSAStack, ForLoc);
if (!ISC.checkAndSetInit(Init, /*EmitDiags=*/false)) {
if (ValueDecl *D = ISC.getLoopDecl()) {
auto *VD = dyn_cast<VarDecl>(D);
DeclRefExpr *PrivateRef = nullptr;
if (!VD) {
if (VarDecl *Private = isOpenMPCapturedDecl(D)) {
VD = Private;
} else {
PrivateRef = buildCapture(SemaRef, D, ISC.getLoopDeclRefExpr(),
/*WithInit=*/false);
VD = cast<VarDecl>(PrivateRef->getDecl());
}
}
DSAStack->addLoopControlVariable(D, VD);
const Decl *LD = DSAStack->getPossiblyLoopCounter();
if (LD != D->getCanonicalDecl()) {
DSAStack->resetPossibleLoopCounter();
if (auto *Var = dyn_cast_or_null<VarDecl>(LD))
SemaRef.MarkDeclarationsReferencedInExpr(buildDeclRefExpr(
SemaRef, const_cast<VarDecl *>(Var),
Var->getType().getNonLValueExprType(getASTContext()), ForLoc,
/*RefersToCapture=*/true));
}
OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
// OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables
// Referenced in a Construct, C/C++]. The loop iteration variable in the
// associated for-loop of a simd construct with just one associated
// for-loop may be listed in a linear clause with a constant-linear-step
// that is the increment of the associated for-loop. The loop iteration
// variable(s) in the associated for-loop(s) of a for or parallel for
// construct may be listed in a private or lastprivate clause.
DSAStackTy::DSAVarData DVar =
DSAStack->getTopDSA(D, /*FromParent=*/false);
// If LoopVarRefExpr is nullptr it means the corresponding loop variable
// is declared in the loop and it is predetermined as a private.
Expr *LoopDeclRefExpr = ISC.getLoopDeclRefExpr();
OpenMPClauseKind PredeterminedCKind =
isOpenMPSimdDirective(DKind)
? (DSAStack->hasMutipleLoops() ? OMPC_lastprivate : OMPC_linear)
: OMPC_private;
if (((isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown &&
DVar.CKind != PredeterminedCKind && DVar.RefExpr &&
(getLangOpts().OpenMP <= 45 || (DVar.CKind != OMPC_lastprivate &&
DVar.CKind != OMPC_private))) ||
((isOpenMPWorksharingDirective(DKind) || DKind == OMPD_taskloop ||
DKind == OMPD_master_taskloop || DKind == OMPD_masked_taskloop ||
DKind == OMPD_parallel_master_taskloop ||
DKind == OMPD_parallel_masked_taskloop ||
isOpenMPDistributeDirective(DKind)) &&
!isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown &&
DVar.CKind != OMPC_private && DVar.CKind != OMPC_lastprivate)) &&
(DVar.CKind != OMPC_private || DVar.RefExpr)) {
Diag(Init->getBeginLoc(), diag::err_omp_loop_var_dsa)
<< getOpenMPClauseName(DVar.CKind)
<< getOpenMPDirectiveName(DKind)
<< getOpenMPClauseName(PredeterminedCKind);
if (DVar.RefExpr == nullptr)
DVar.CKind = PredeterminedCKind;
reportOriginalDsa(SemaRef, DSAStack, D, DVar,
/*IsLoopIterVar=*/true);
} else if (LoopDeclRefExpr) {
// Make the loop iteration variable private (for worksharing
// constructs), linear (for simd directives with the only one
// associated loop) or lastprivate (for simd directives with several
// collapsed or ordered loops).
if (DVar.CKind == OMPC_unknown)
DSAStack->addDSA(D, LoopDeclRefExpr, PredeterminedCKind,
PrivateRef);
OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
if (AssociatedLoops == 0 || !isOpenMPLoopDirective(DKind))
return;

DSAStack->loopStart();
OpenMPIterationSpaceChecker ISC(SemaRef, /*SupportsNonRectangular=*/true,
*DSAStack, ForLoc);
if (!ISC.checkAndSetInit(Init, /*EmitDiags=*/false)) {
if (ValueDecl *D = ISC.getLoopDecl()) {
auto *VD = dyn_cast<VarDecl>(D);
DeclRefExpr *PrivateRef = nullptr;
if (!VD) {
if (VarDecl *Private = isOpenMPCapturedDecl(D)) {
VD = Private;
} else {
PrivateRef = buildCapture(SemaRef, D, ISC.getLoopDeclRefExpr(),
/*WithInit=*/false);
VD = cast<VarDecl>(PrivateRef->getDecl());
}
}
DSAStack->addLoopControlVariable(D, VD);
const Decl *LD = DSAStack->getPossiblyLoopCounter();
if (LD != D->getCanonicalDecl()) {
DSAStack->resetPossibleLoopCounter();
if (auto *Var = dyn_cast_or_null<VarDecl>(LD))
SemaRef.MarkDeclarationsReferencedInExpr(buildDeclRefExpr(
SemaRef, const_cast<VarDecl *>(Var),
Var->getType().getNonLValueExprType(getASTContext()), ForLoc,
/*RefersToCapture=*/true));
}
// OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables
// Referenced in a Construct, C/C++]. The loop iteration variable in the
// associated for-loop of a simd construct with just one associated
// for-loop may be listed in a linear clause with a constant-linear-step
// that is the increment of the associated for-loop. The loop iteration
// variable(s) in the associated for-loop(s) of a for or parallel for
// construct may be listed in a private or lastprivate clause.
DSAStackTy::DSAVarData DVar =
DSAStack->getTopDSA(D, /*FromParent=*/false);
// If LoopVarRefExpr is nullptr it means the corresponding loop variable
// is declared in the loop and it is predetermined as a private.
Expr *LoopDeclRefExpr = ISC.getLoopDeclRefExpr();
OpenMPClauseKind PredeterminedCKind =
isOpenMPSimdDirective(DKind)
? (DSAStack->hasMutipleLoops() ? OMPC_lastprivate : OMPC_linear)
: OMPC_private;
if (((isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown &&
DVar.CKind != PredeterminedCKind && DVar.RefExpr &&
(getLangOpts().OpenMP <= 45 ||
(DVar.CKind != OMPC_lastprivate && DVar.CKind != OMPC_private))) ||
((isOpenMPWorksharingDirective(DKind) || DKind == OMPD_taskloop ||
DKind == OMPD_master_taskloop || DKind == OMPD_masked_taskloop ||
DKind == OMPD_parallel_master_taskloop ||
DKind == OMPD_parallel_masked_taskloop ||
isOpenMPDistributeDirective(DKind)) &&
!isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown &&
DVar.CKind != OMPC_private && DVar.CKind != OMPC_lastprivate)) &&
(DVar.CKind != OMPC_private || DVar.RefExpr)) {
Diag(Init->getBeginLoc(), diag::err_omp_loop_var_dsa)
<< getOpenMPClauseName(DVar.CKind) << getOpenMPDirectiveName(DKind)
<< getOpenMPClauseName(PredeterminedCKind);
if (DVar.RefExpr == nullptr)
DVar.CKind = PredeterminedCKind;
reportOriginalDsa(SemaRef, DSAStack, D, DVar, /*IsLoopIterVar=*/true);
} else if (LoopDeclRefExpr) {
// Make the loop iteration variable private (for worksharing
// constructs), linear (for simd directives with the only one
// associated loop) or lastprivate (for simd directives with several
// collapsed or ordered loops).
if (DVar.CKind == OMPC_unknown)
DSAStack->addDSA(D, LoopDeclRefExpr, PredeterminedCKind, PrivateRef);
}
}
DSAStack->setAssociatedLoops(AssociatedLoops - 1);
}
DSAStack->setAssociatedLoops(AssociatedLoops - 1);
}

namespace {
Expand Down
85 changes: 39 additions & 46 deletions clang/lib/Sema/SemaOverload.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -164,13 +164,33 @@ ImplicitConversionRank clang::GetConversionRank(ImplicitConversionKind Kind) {
ICR_C_Conversion,
ICR_C_Conversion_Extension,
ICR_Conversion,
ICR_HLSL_Dimension_Reduction,
ICR_Conversion,
ICR_Conversion,
ICR_HLSL_Scalar_Widening,
};
static_assert(std::size(Rank) == (int)ICK_Num_Conversion_Kinds);
return Rank[(int)Kind];
}

ImplicitConversionRank
clang::GetDimensionConversionRank(ImplicitConversionRank Base,
ImplicitConversionKind Dimension) {
ImplicitConversionRank Rank = GetConversionRank(Dimension);
if (Rank == ICR_HLSL_Scalar_Widening) {
if (Base == ICR_Promotion)
return ICR_HLSL_Scalar_Widening_Promotion;
if (Base == ICR_Conversion)
return ICR_HLSL_Scalar_Widening_Conversion;
}
if (Rank == ICR_HLSL_Dimension_Reduction) {
if (Base == ICR_Promotion)
return ICR_HLSL_Dimension_Reduction_Promotion;
if (Base == ICR_Conversion)
return ICR_HLSL_Dimension_Reduction_Conversion;
}
return Rank;
}

/// GetImplicitConversionName - Return the name of this kind of
/// implicit conversion.
static const char *GetImplicitConversionName(ImplicitConversionKind Kind) {
Expand Down Expand Up @@ -208,6 +228,7 @@ static const char *GetImplicitConversionName(ImplicitConversionKind Kind) {
"Fixed point conversion",
"HLSL vector truncation",
"Non-decaying array conversion",
"HLSL vector splat",
};
static_assert(std::size(Name) == (int)ICK_Num_Conversion_Kinds);
return Name[Kind];
Expand All @@ -218,7 +239,7 @@ static const char *GetImplicitConversionName(ImplicitConversionKind Kind) {
void StandardConversionSequence::setAsIdentityConversion() {
First = ICK_Identity;
Second = ICK_Identity;
Element = ICK_Identity;
Dimension = ICK_Identity;
Third = ICK_Identity;
DeprecatedStringLiteralToCharPtr = false;
QualificationIncludesObjCLifetime = false;
Expand All @@ -241,8 +262,8 @@ ImplicitConversionRank StandardConversionSequence::getRank() const {
Rank = GetConversionRank(First);
if (GetConversionRank(Second) > Rank)
Rank = GetConversionRank(Second);
if (GetConversionRank(Element) > Rank)
Rank = GetConversionRank(Element);
if (GetDimensionConversionRank(Rank, Dimension) > Rank)
Rank = GetDimensionConversionRank(Rank, Dimension);
if (GetConversionRank(Third) > Rank)
Rank = GetConversionRank(Third);
return Rank;
Expand Down Expand Up @@ -1970,15 +1991,15 @@ static bool IsVectorConversion(Sema &S, QualType FromType, QualType ToType,
if (FromElts < ToElts)
return false;
if (FromElts == ToElts)
ICK = ICK_Identity;
ElConv = ICK_Identity;
else
ICK = ICK_HLSL_Vector_Truncation;
ElConv = ICK_HLSL_Vector_Truncation;

QualType FromElTy = FromExtType->getElementType();
QualType ToElTy = ToExtType->getElementType();
if (S.Context.hasSameUnqualifiedType(FromElTy, ToElTy))
return true;
return IsVectorElementConversion(S, FromElTy, ToElTy, ElConv, From);
return IsVectorElementConversion(S, FromElTy, ToElTy, ICK, From);
}
// There are no conversions between extended vector types other than the
// identity conversion.
Expand All @@ -1987,6 +2008,11 @@ static bool IsVectorConversion(Sema &S, QualType FromType, QualType ToType,

// Vector splat from any arithmetic type to a vector.
if (FromType->isArithmeticType()) {
if (S.getLangOpts().HLSL) {
ElConv = ICK_HLSL_Vector_Splat;
QualType ToElTy = ToExtType->getElementType();
return IsVectorElementConversion(S, FromType, ToElTy, ICK, From);
}
ICK = ICK_Vector_Splat;
return true;
}
Expand Down Expand Up @@ -2201,7 +2227,7 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType,
// conversion.
bool IncompatibleObjC = false;
ImplicitConversionKind SecondICK = ICK_Identity;
ImplicitConversionKind ElementICK = ICK_Identity;
ImplicitConversionKind DimensionICK = ICK_Identity;
if (S.Context.hasSameUnqualifiedType(FromType, ToType)) {
// The unqualified versions of the types are the same: there's no
// conversion to do.
Expand Down Expand Up @@ -2267,10 +2293,10 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType,
InOverloadResolution, FromType)) {
// Pointer to member conversions (4.11).
SCS.Second = ICK_Pointer_Member;
} else if (IsVectorConversion(S, FromType, ToType, SecondICK, ElementICK,
} else if (IsVectorConversion(S, FromType, ToType, SecondICK, DimensionICK,
From, InOverloadResolution, CStyle)) {
SCS.Second = SecondICK;
SCS.Element = ElementICK;
SCS.Dimension = DimensionICK;
FromType = ToType.getUnqualifiedType();
} else if (!S.getLangOpts().CPlusPlus &&
S.Context.typesAreCompatible(ToType, FromType)) {
Expand Down Expand Up @@ -4257,24 +4283,6 @@ getFixedEnumPromtion(Sema &S, const StandardConversionSequence &SCS) {
return FixedEnumPromotion::ToPromotedUnderlyingType;
}

static ImplicitConversionSequence::CompareKind
HLSLCompareFloatingRank(QualType LHS, QualType RHS) {
assert(LHS->isVectorType() == RHS->isVectorType() &&
"Either both elements should be vectors or neither should.");
if (const auto *VT = LHS->getAs<VectorType>())
LHS = VT->getElementType();

if (const auto *VT = RHS->getAs<VectorType>())
RHS = VT->getElementType();

const auto L = LHS->castAs<BuiltinType>()->getKind();
const auto R = RHS->castAs<BuiltinType>()->getKind();
if (L == R)
return ImplicitConversionSequence::Indistinguishable;
return L < R ? ImplicitConversionSequence::Better
: ImplicitConversionSequence::Worse;
}

/// CompareStandardConversionSequences - Compare two standard
/// conversion sequences to determine whether one is better than the
/// other or if they are indistinguishable (C++ 13.3.3.2p3).
Expand Down Expand Up @@ -4515,22 +4523,6 @@ CompareStandardConversionSequences(Sema &S, SourceLocation Loc,
? ImplicitConversionSequence::Better
: ImplicitConversionSequence::Worse;
}

if (S.getLangOpts().HLSL) {
// On a promotion we prefer the lower rank to disambiguate.
if ((SCS1.Second == ICK_Floating_Promotion &&
SCS2.Second == ICK_Floating_Promotion) ||
(SCS1.Element == ICK_Floating_Promotion &&
SCS2.Element == ICK_Floating_Promotion))
return HLSLCompareFloatingRank(SCS1.getToType(2), SCS2.getToType(2));
// On a conversion we prefer the higher rank to disambiguate.
if ((SCS1.Second == ICK_Floating_Conversion &&
SCS2.Second == ICK_Floating_Conversion) ||
(SCS1.Element == ICK_Floating_Conversion &&
SCS2.Element == ICK_Floating_Conversion))
return HLSLCompareFloatingRank(SCS2.getToType(2), SCS1.getToType(2));
}

return ImplicitConversionSequence::Indistinguishable;
}

Expand Down Expand Up @@ -5074,7 +5066,7 @@ TryReferenceInit(Sema &S, Expr *Init, QualType DeclType,
: (RefConv & Sema::ReferenceConversions::ObjC)
? ICK_Compatible_Conversion
: ICK_Identity;
ICS.Standard.Element = ICK_Identity;
ICS.Standard.Dimension = ICK_Identity;
// FIXME: As a speculative fix to a defect introduced by CWG2352, we rank
// a reference binding that performs a non-top-level qualification
// conversion as a qualification conversion, not as an identity conversion.
Expand Down Expand Up @@ -5990,6 +5982,7 @@ static bool CheckConvertedConstantConversions(Sema &S,
case ICK_Vector_Conversion:
case ICK_SVE_Vector_Conversion:
case ICK_RVV_Vector_Conversion:
case ICK_HLSL_Vector_Splat:
case ICK_Vector_Splat:
case ICK_Complex_Real:
case ICK_Block_Pointer_Conversion:
Expand Down Expand Up @@ -6276,7 +6269,7 @@ Sema::EvaluateConvertedConstantExpression(Expr *E, QualType T, APValue &Value,
static void dropPointerConversion(StandardConversionSequence &SCS) {
if (SCS.Second == ICK_Pointer_Conversion) {
SCS.Second = ICK_Identity;
SCS.Element = ICK_Identity;
SCS.Dimension = ICK_Identity;
SCS.Third = ICK_Identity;
SCS.ToTypePtrs[2] = SCS.ToTypePtrs[1] = SCS.ToTypePtrs[0];
}
Expand Down
11 changes: 9 additions & 2 deletions clang/lib/Sema/SemaTemplate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4250,10 +4250,10 @@ TemplateParameterList *Sema::MatchTemplateParametersToScopeSpecifier(

// C++ [temp.expl.spec]p16:
// In an explicit specialization declaration for a member of a class
// template or a member template that ap- pears in namespace scope, the
// template or a member template that appears in namespace scope, the
// member template and some of its enclosing class templates may remain
// unspecialized, except that the declaration shall not explicitly
// specialize a class member template if its en- closing class templates
// specialize a class member template if its enclosing class templates
// are not explicitly specialized as well.
if (ParamIdx < ParamLists.size()) {
if (ParamLists[ParamIdx]->size() == 0) {
Expand Down Expand Up @@ -11690,6 +11690,13 @@ Sema::ActOnTypenameType(Scope *S, SourceLocation TypenameLoc,
// Construct a dependent template specialization type.
assert(DTN && "dependent template has non-dependent name?");
assert(DTN->getQualifier() == SS.getScopeRep());

if (!DTN->isIdentifier()) {
Diag(TemplateIILoc, diag::err_template_id_not_a_type) << Template;
NoteAllFoundTemplates(Template);
return true;
}

QualType T = Context.getDependentTemplateSpecializationType(
ElaboratedTypeKeyword::Typename, DTN->getQualifier(),
DTN->getIdentifier(), TemplateArgs.arguments());
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Sema/SemaType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2373,7 +2373,7 @@ QualType Sema::BuildExtVectorType(QualType T, Expr *ArraySize,
// on bitvectors, and we have no well-defined ABI for bitvectors, so vectors
// of bool aren't allowed.
//
// We explictly allow bool elements in ext_vector_type for C/C++.
// We explicitly allow bool elements in ext_vector_type for C/C++.
bool IsNoBoolVecLang = getLangOpts().OpenCL || getLangOpts().OpenCLCPlusPlus;
if ((!T->isDependentType() && !T->isIntegerType() &&
!T->isRealFloatingType()) ||
Expand Down
9 changes: 4 additions & 5 deletions clang/lib/Serialization/ASTReaderStmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -793,16 +793,15 @@ readConstraintSatisfaction(ASTRecordReader &Record) {
if (!Satisfaction.IsSatisfied) {
unsigned NumDetailRecords = Record.readInt();
for (unsigned i = 0; i != NumDetailRecords; ++i) {
Expr *ConstraintExpr = Record.readExpr();
if (/* IsDiagnostic */Record.readInt()) {
SourceLocation DiagLocation = Record.readSourceLocation();
std::string DiagMessage = Record.readString();
Satisfaction.Details.emplace_back(
ConstraintExpr, new (Record.getContext())
ConstraintSatisfaction::SubstitutionDiagnostic{
DiagLocation, DiagMessage});
new (Record.getContext())
ConstraintSatisfaction::SubstitutionDiagnostic(DiagLocation,
DiagMessage));
} else
Satisfaction.Details.emplace_back(ConstraintExpr, Record.readExpr());
Satisfaction.Details.emplace_back(Record.readExpr());
}
}
return Satisfaction;
Expand Down
8 changes: 3 additions & 5 deletions clang/lib/Serialization/ASTWriterStmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -474,14 +474,12 @@ addConstraintSatisfaction(ASTRecordWriter &Record,
if (!Satisfaction.IsSatisfied) {
Record.push_back(Satisfaction.NumRecords);
for (const auto &DetailRecord : Satisfaction) {
Record.writeStmtRef(DetailRecord.first);
auto *E = DetailRecord.second.dyn_cast<Expr *>();
Record.push_back(E == nullptr);
auto *E = DetailRecord.dyn_cast<Expr *>();
Record.push_back(/* IsDiagnostic */ E == nullptr);
if (E)
Record.AddStmt(E);
else {
auto *Diag = DetailRecord.second.get<std::pair<SourceLocation,
StringRef> *>();
auto *Diag = DetailRecord.get<std::pair<SourceLocation, StringRef> *>();
Record.AddSourceLocation(Diag->first);
Record.AddString(Diag->second);
}
Expand Down
6 changes: 4 additions & 2 deletions clang/test/AST/HLSL/RWBuffer-AST.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ RWBuffer<float> Buffer;
// CHECK-NEXT: CXXRecordDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> implicit class RWBuffer definition

// CHECK: FinalAttr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> Implicit final
// CHECK-NEXT: HLSLResourceAttr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> Implicit UAV TypedBuffer
// CHECK-NEXT: HLSLResourceClassAttr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> Implicit UAV
// CHECK-NEXT: HLSLResourceAttr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> Implicit TypedBuffer
// CHECK-NEXT: FieldDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> implicit h 'element_type *'

// CHECK: CXXMethodDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> operator[] 'element_type &const (unsigned int) const'
Expand Down Expand Up @@ -62,5 +63,6 @@ RWBuffer<float> Buffer;
// CHECK: TemplateArgument type 'float'
// CHECK-NEXT: BuiltinType 0x{{[0-9A-Fa-f]+}} 'float'
// CHECK-NEXT: FinalAttr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> Implicit final
// CHECK-NEXT: HLSLResourceAttr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> Implicit UAV TypedBuffer
// CHECK-NEXT: HLSLResourceClassAttr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> Implicit UAV
// CHECK-NEXT: HLSLResourceAttr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> Implicit TypedBuffer
// CHECK-NEXT: FieldDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> implicit referenced h 'float *'
7 changes: 7 additions & 0 deletions clang/test/AST/Interp/arrays.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -625,3 +625,10 @@ constexpr int *get2() {
return same_entity_2;
}
static_assert(get2() == same_entity_2, "failed to find previous decl");

constexpr int zs[2][2][2][2] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
constexpr int fail(const int &p) {
return (&p)[64]; // both-note {{cannot refer to element 64 of array of 2 elements}}
}
static_assert(fail(*(&(&(*(*&(&zs[2] - 1)[0] + 2 - 2))[2])[-1][2] - 2)) == 11, ""); // both-error {{not an integral constant expression}} \
// both-note {{in call to}}
25 changes: 18 additions & 7 deletions clang/test/AST/Interp/functions.cpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -verify=expected,both %s
// RUN: %clang_cc1 -std=c++14 -fexperimental-new-constant-interpreter -verify=expected,both %s
// RUN: %clang_cc1 -std=c++20 -fexperimental-new-constant-interpreter -verify=expected,both %s
// RUN: %clang_cc1 -verify=ref,both %s
// RUN: %clang_cc1 -std=c++14 -verify=ref,both %s
// RUN: %clang_cc1 -std=c++20 -verify=ref,both %s
// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -pedantic -verify=expected,both %s
// RUN: %clang_cc1 -std=c++14 -fexperimental-new-constant-interpreter -pedantic -verify=expected,both %s
// RUN: %clang_cc1 -std=c++20 -fexperimental-new-constant-interpreter -pedantic -verify=expected,both %s
// RUN: %clang_cc1 -pedantic -verify=ref,both %s
// RUN: %clang_cc1 -pedantic -std=c++14 -verify=ref,both %s
// RUN: %clang_cc1 -pedantic -std=c++20 -verify=ref,both %s

constexpr void doNothing() {}
constexpr int gimme5() {
Expand Down Expand Up @@ -471,7 +471,7 @@ namespace AddressOf {
constexpr int foo() {return 1;}
static_assert(__builtin_addressof(foo) == foo, "");

constexpr _Complex float F = {3, 4};
constexpr _Complex float F = {3, 4}; // both-warning {{'_Complex' is a C99 extension}}
static_assert(__builtin_addressof(F) == &F, "");

void testAddressof(int x) {
Expand Down Expand Up @@ -633,3 +633,14 @@ namespace {
void (&r)() = f;
void (&cond3)() = r;
}

namespace FunctionCast {
// When folding, we allow functions to be cast to different types. Such
// cast functions cannot be called, even if they're constexpr.
constexpr int f() { return 1; }
typedef double (*DoubleFn)();
typedef int (*IntFn)();
int a[(int)DoubleFn(f)()]; // both-error {{variable length array}} \
// both-warning {{are a Clang extension}}
int b[(int)IntFn(f)()]; // ok
}
13 changes: 13 additions & 0 deletions clang/test/AST/Interp/lifetimes.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -verify=expected,both %s
// RUN: %clang_cc1 -verify=ref,both %s

/// FIXME: Slight difference in diagnostic output here.

struct Foo {
int a;
};
Expand All @@ -20,3 +22,14 @@ static_assert(dead1() == 1, ""); // both-error {{not an integral constant expres
// both-note {{in call to}}


struct S {
int &&r; // both-note {{reference member declared here}}
int t;
constexpr S() : r(0), t(r) {} // both-error {{reference member 'r' binds to a temporary object whose lifetime would be shorter than the lifetime of the constructed object}} \
// ref-note {{read of object outside its lifetime is not allowed in a constant expression}} \
// expected-note {{temporary created here}} \
// expected-note {{read of temporary whose lifetime has ended}}
};
constexpr int k1 = S().t; // both-error {{must be initialized by a constant expression}} \
// ref-note {{in call to}} \
// expected-note {{in call to}}
54 changes: 34 additions & 20 deletions clang/test/AST/Interp/literals.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -568,37 +568,27 @@ namespace IncDec {
return 1;
}
static_assert(uninit<int, true, true>(), ""); // both-error {{not an integral constant expression}} \
// ref-note {{in call to 'uninit<int, true, true>()'}} \
// expected-note {{in call to 'uninit()'}}
// both-note {{in call to 'uninit<int, true, true>()'}}
static_assert(uninit<int, false, true>(), ""); // both-error {{not an integral constant expression}} \
// ref-note {{in call to 'uninit<int, false, true>()'}} \
// expected-note {{in call to 'uninit()'}}
// both-note {{in call to 'uninit<int, false, true>()'}}

static_assert(uninit<float, true, true>(), ""); // both-error {{not an integral constant expression}} \
// ref-note {{in call to 'uninit<float, true, true>()'}} \
// expected-note {{in call to 'uninit()'}}
// both-note {{in call to 'uninit<float, true, true>()'}}
static_assert(uninit<float, false, true>(), ""); // both-error {{not an integral constant expression}} \
// ref-note {{in call to 'uninit<float, false, true>()'}} \
// expected-note {{in call to 'uninit()'}}
// both-note {{in call to 'uninit<float, false, true>()'}}
static_assert(uninit<float, true, false>(), ""); // both-error {{not an integral constant expression}} \
// ref-note {{in call to 'uninit<float, true, false>()'}} \
// expected-note {{in call to 'uninit()'}}
// both-note {{in call to 'uninit<float, true, false>()'}}
static_assert(uninit<float, false, false>(), ""); // both-error {{not an integral constant expression}} \
// ref-note {{in call to 'uninit<float, false, false>()'}} \
// expected-note {{in call to 'uninit()'}}
// both-note {{in call to 'uninit<float, false, false>()'}}

static_assert(uninit<int*, true, true>(), ""); // both-error {{not an integral constant expression}} \
// ref-note {{in call to 'uninit<int *, true, true>()'}} \
// expected-note {{in call to 'uninit()'}}
// both-note {{in call to 'uninit<int *, true, true>()'}}
static_assert(uninit<int*, false, true>(), ""); // both-error {{not an integral constant expression}} \
// ref-note {{in call to 'uninit<int *, false, true>()'}} \
// expected-note {{in call to 'uninit()'}}
// both-note {{in call to 'uninit<int *, false, true>()'}}
static_assert(uninit<int*, true, false>(), ""); // both-error {{not an integral constant expression}} \
// ref-note {{in call to 'uninit<int *, true, false>()'}} \
// expected-note {{in call to 'uninit()'}}
// both-note {{in call to 'uninit<int *, true, false>()'}}
static_assert(uninit<int*, false, false>(), ""); // both-error {{not an integral constant expression}} \
// ref-note {{in call to 'uninit<int *, false, false>()'}} \
// expected-note {{in call to 'uninit()'}}
// both-note {{in call to 'uninit<int *, false, false>()'}}

constexpr int OverFlow() { // both-error {{never produces a constant expression}}
int a = INT_MAX;
Expand Down Expand Up @@ -1276,3 +1266,27 @@ namespace ComparisonAgainstOnePastEnd {

static_assert(&a + 1 == &b + 1, ""); // both-error {{static assertion failed}}
};

namespace NTTP {
template <typename _Tp, unsigned _Nm>
constexpr unsigned
size(const _Tp (&)[_Nm]) noexcept
{ return _Nm; }

template <char C>
static int write_padding() {
static const char Chars[] = {C};

return size(Chars);
}
}

#if __cplusplus >= 201402L
namespace UnaryOpError {
constexpr int foo() {
int f = 0;
++g; // both-error {{use of undeclared identifier 'g'}}
return f;
}
}
#endif
14 changes: 14 additions & 0 deletions clang/test/AST/Interp/memberpointers.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -std=c++14 -fexperimental-new-constant-interpreter -verify=expected,both %s
// RUN: %clang_cc1 -std=c++23 -fexperimental-new-constant-interpreter -verify=expected,both %s
// RUN: %clang_cc1 -std=c++14 -verify=ref,both %s
// RUN: %clang_cc1 -std=c++23 -verify=ref,both %s

namespace MemberPointers {
struct A {
Expand Down Expand Up @@ -195,3 +197,15 @@ namespace {
use(psr->*&S::x);
}
}

namespace MemPtrTemporary {
struct A {
constexpr int f() const { return 5; }
};

constexpr int apply(const A &a, int (A::*ff)() const) {
return (a.*ff)();
}

static_assert(apply(A(), &A::f) == 5, "");
}
37 changes: 37 additions & 0 deletions clang/test/AST/Interp/records.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1500,3 +1500,40 @@ namespace LocalWithThisPtrInit {
}
static_assert(foo() == 2, "");
}

namespace OnePastEndAndBack {
struct Base {
constexpr Base() {}
int n = 0;
};

constexpr Base a;
constexpr const Base *c = &a + 1;
constexpr const Base *d = c - 1;
static_assert(d == &a, "");
}

namespace BitSet {
class Bitset {
unsigned Bit = 0;

public:
constexpr Bitset() {
int Init[2] = {1,2};
for (auto I : Init)
set(I);
}
constexpr void set(unsigned I) {
this->Bit++;
this->Bit = 1u << 1;
}
};

struct ArchInfo {
Bitset DefaultExts;
};

constexpr ArchInfo ARMV8A = {
Bitset()
};
}
21 changes: 17 additions & 4 deletions clang/test/AST/Interp/shifts.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -std=c++20 -verify %s
// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -std=c++17 -verify=cxx17 %s
// RUN: %clang_cc1 -std=c++20 -verify=ref %s
// RUN: %clang_cc1 -std=c++17 -verify=ref-cxx17 %s
// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -std=c++20 -verify=expected,all %s
// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -std=c++17 -verify=cxx17,all %s
// RUN: %clang_cc1 -std=c++20 -verify=ref,all %s
// RUN: %clang_cc1 -std=c++17 -verify=ref-cxx17,all %s

#define INT_MIN (~__INT_MAX__)

Expand Down Expand Up @@ -198,3 +198,16 @@ namespace LongInt {
}
static_assert(f() == 1, "");
};

enum shiftof {
X = (1<<-29), // all-error {{expression is not an integral constant expression}} \
// all-note {{negative shift count -29}}

X2 = (-1<<29), // cxx17-error {{expression is not an integral constant expression}} \
// cxx17-note {{left shift of negative value -1}} \
// ref-cxx17-error {{expression is not an integral constant expression}} \
// ref-cxx17-note {{left shift of negative value -1}}

X3 = (1<<32) // all-error {{expression is not an integral constant expression}} \
// all-note {{shift count 32 >= width of type 'int'}}
};
83 changes: 83 additions & 0 deletions clang/test/C/C2y/n3244.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
// RUN: %clang_cc1 -std=c2y %s -verify -Wno-gnu-alignof-expression

/* WG14 N3244: Partial
* Slay Some Earthly Demons I
*
* NB: the committee adopted:
* Annex J Item 21 (including additional change) -- no, we lack explicit documentation
* Annex J Item 56 -- yes
* Annex J Item 57 Option 1 -- yes
* Annex J Item 67 -- no
* Annex J Item 69 (alternative wording for semantics) -- no
*/

void reg_array(void) {
// Decay of an array with the register storage class specifier has gone from
// explicit undefined behavior to be implementation defined instead. Clang
// does not support this.
register int array[10];
(void)sizeof(array); // okay
int *vp = array; // expected-error {{address of register variable requested}}
int val = array[0]; // expected-error {{address of register variable requested}}
}

struct F; // expected-note {{forward declaration of 'struct F'}}
void incomplete_no_linkage(struct F); // okay
void incomplete_no_linkage(struct F f) { // expected-error {{variable has incomplete type 'struct F'}}
struct G g; // expected-error {{variable has incomplete type 'struct G'}} \
expected-note {{forward declaration of 'struct G'}}
int i[]; // expected-error {{definition of variable with array type needs an explicit size or an initializer}}
}

void block_scope_non_extern_func_decl(void) {
static void f(void); // expected-error {{function declared in block scope cannot have 'static' storage class}}
extern void g(void); // okay
__private_extern__ void h(void); // okay
}

// FIXME: this function should be diagnosed as it is never defined in the TU.
extern inline void never_defined_extern_inline(void);

// While this declaration is fine because the function is defined within the TU.
extern inline void is_defined_extern_inline(void);
extern inline void is_defined_extern_inline(void) {}

int NoAlignmentOnOriginalDecl;
// FIXME: the original declaration has no alignment specifier, so the
// declaration below should be diagnosed due to the incompatible alignment
// specifier.
_Alignas(8) int NoAlignmentOnOriginalDecl;
_Static_assert(_Alignof(NoAlignmentOnOriginalDecl) == 8, "");

_Alignas(8) int AlignmentOnOriginalDecl; // expected-note {{declared with '_Alignas' attribute here}}
// FIXME: this should be accepted because the redeclaration has no alignment
// specifier.
int AlignmentOnOriginalDecl; // expected-error {{'_Alignas' must be specified on definition if it is specified on any declaration}}
_Static_assert(_Alignof(AlignmentOnOriginalDecl) == 8, "");

long long CompatibleAlignment;
_Static_assert(_Alignof(CompatibleAlignment) == _Alignof(long long), "");
_Alignas(_Alignof(long long)) long long CompatibleAlignment; // Okay, alignment is the same as the implied alignment

_Alignas(_Alignof(long long)) long long CompatibleAlignment2; // expected-note {{declared with '_Alignas' attribute here}}
// FIXME: this should be accepted because the redeclaration has no alignment
// specifier.
long long CompatibleAlignment2; // expected-error {{'_Alignas' must be specified on definition if it is specified on any declaration}}

// FIXME: this should be accepted because the definition specifies the
// alignment and a subsequent declaration does not specify any alignment.
_Alignas(8) long long DefnWithInit = 12; // expected-note {{declared with '_Alignas' attribute here}}
long long DefnWithInit; // expected-error {{'_Alignas' must be specified on definition if it is specified on any declaration}}

// This is accepted because the definition has an alignment specifier and the
// subsequent redeclaration does not specify an alignment.
_Alignas(8) long long DefnWithInit2 = 12;
extern long long DefnWithInit2;

// FIXME: this should be accepted because the definition specifies the
// alignment and a subsequent declaration specifies a compatible alignment.
long long DefnWithInit3 = 12; // expected-error {{'_Alignas' must be specified on definition if it is specified on any declaration}}
_Alignas(_Alignof(long long)) long long DefnWithInit3; // expected-note {{declared with '_Alignas' attribute here}}

_Alignas(8) int Mismatch; // expected-note {{previous declaration is here}}
_Alignas(16) int Mismatch; // expected-error {{redeclaration has different alignment requirement (16 vs 8)}}
20 changes: 20 additions & 0 deletions clang/test/C/C2y/n3262.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// RUN: %clang_cc1 -verify -std=c2y -Wall -pedantic %s
// expected-no-diagnostics

/* WG14 N3262: Yes
* Usability of a byte-wise copy of va_list
*
* NB: Clang explicitly documents this as being undefined behavior. A
* diagnostic is produced for some targets but not for others for assignment or
* initialization, but no diagnostic is possible to produce for use with memcpy
* in the general case, nor with a manual bytewise copy via a for loop.
*
* Therefore, nothing is tested in this file; it serves as a reminder that we
* validated our documentation against the paper. See
* clang/docs/LanguageExtensions.rst for more details.
*
* FIXME: it would be nice to add ubsan support for recognizing when an invalid
* copy is made and diagnosing on copy (or on use of the copied va_list).
*/

int main() {}
18 changes: 18 additions & 0 deletions clang/test/CXX/class/class.compare/class.compare.default/p1.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -265,3 +265,21 @@ void f2() {
// access info for unnamed bit-field
}
}

namespace GH96043 {
template <typename> class a {};
template <typename b> b c(a<b>);
template <typename d> class e {
public:
typedef a<d *> f;
f begin();
};
template <typename d, typename g> constexpr bool operator==(d h, g i) {
return *c(h.begin()) == *c(i.begin());
}
struct j {
e<j> bar;
bool operator==(const j &) const;
};
bool j::operator==(const j &) const = default;
}
3 changes: 2 additions & 1 deletion clang/test/CXX/drs/cwg20xx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,8 @@ namespace cwg2083 { // cwg2083: partial
int &r = a.x; // #cwg2083-r
struct B {
void f() {
// FIXME: We emit more errors than we should be. They are explictly marked below.
// FIXME: We emit more errors than we should be. They are explicitly
// marked below.
a.x;
// expected-warning@-1 {{expression result unused}}
// expected-error@-2 {{reference to local variable 'a' declared in enclosing function 'cwg2083::discarded_lval'}} FIXME
Expand Down
4 changes: 2 additions & 2 deletions clang/test/CodeGen/asan-destructor-kind.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
// RUN: %clang_cc1 -fsanitize=address -emit-llvm -o - -triple x86_64-apple-macosx10.15 %s \
// RUN: | FileCheck %s --check-prefixes=CHECK-GLOBAL-DTOR

// Explictly ask for global dtor
// Explicitly ask for global dtor
// RUN: %clang_cc1 -fsanitize=address \
// RUN: -fsanitize-address-destructor=global -emit-llvm -o - \
// RUN: -triple x86_64-apple-macosx10.15 %s | \
Expand All @@ -18,7 +18,7 @@
// CHECK-GLOBAL-DTOR: llvm.global_dtor{{.+}}asan.module_dtor
// CHECK-GLOBAL-DTOR: define internal void @asan.module_dtor

// Explictly ask for no dtors
// Explicitly ask for no dtors
// RUN: %clang_cc1 -fsanitize=address \
// RUN: -fsanitize-address-destructor=none -emit-llvm -o - \
// RUN: -triple x86_64-apple-macosx10.15 %s | \
Expand Down
1 change: 0 additions & 1 deletion clang/test/CodeGen/bitfield-access-pad.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
// Configs that have expensive unaligned access
// Little Endian
// RUN: %clang_cc1 -triple=hexagon-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT-T %s
// RUN: %clang_cc1 -triple=le64-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT-T %s

// Big endian
// RUN: %clang_cc1 -triple=m68k-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT-T %s
Expand Down
4 changes: 2 additions & 2 deletions clang/test/CodeGen/bitfield-access-unit.c
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@
// RUN: %clang_cc1 -triple=sparc-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT-STRICT %s
// RUN: %clang_cc1 -triple=tce-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT-STRICT %s

// Both le64-elf and m68-elf are strict alignment ISAs with 4-byte aligned
// 64-bit or 2-byte aligned 32-bit integer types. This more compex to describe here.
// m68-elf is a strict alignment ISA with 4-byte aligned 64-bit or 2-byte
// aligned 32-bit integer types. This more compex to describe here.

// If unaligned access is expensive don't stick these together.
struct A {
Expand Down
25 changes: 15 additions & 10 deletions clang/test/CodeGen/ifunc.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@
// RUN: %clang_cc1 -triple x86_64-apple-macosx -emit-llvm -o - %s | FileCheck %s
// RUN: %clang_cc1 -triple arm64-apple-macosx -O2 -emit-llvm -o - %s | FileCheck %s
// RUN: %clang_cc1 -triple x86_64-apple-macosx -O2 -emit-llvm -o - %s | FileCheck %s
// RUN: %clang_cc1 -triple arm64-apple-macosx -fsanitize=thread -O2 -emit-llvm -o - %s | FileCheck %s --check-prefix=MACSAN
// RUN: %clang_cc1 -triple x86_64-apple-macosx -fsanitize=thread -O2 -emit-llvm -o - %s | FileCheck %s --check-prefix=MACSAN
// RUN: %clang_cc1 -triple arm64-apple-macosx -fsanitize=address -O2 -emit-llvm -o - %s | FileCheck %s --check-prefix=MACSAN
// RUN: %clang_cc1 -triple x86_64-apple-macosx -fsanitize=address -O2 -emit-llvm -o - %s | FileCheck %s --check-prefix=MACSAN
// RUN: %clang_cc1 -triple arm64-apple-macosx -fsanitize=thread -O2 -emit-llvm -o - %s | FileCheck %s --check-prefix=SAN
// RUN: %clang_cc1 -triple x86_64-apple-macosx -fsanitize=thread -O2 -emit-llvm -o - %s | FileCheck %s --check-prefix=SAN
// RUN: %clang_cc1 -triple arm64-apple-macosx -fsanitize=address -O2 -emit-llvm -o - %s | FileCheck %s --check-prefix=SAN
// RUN: %clang_cc1 -triple x86_64-apple-macosx -fsanitize=address -O2 -emit-llvm -o - %s | FileCheck %s --check-prefix=SAN

/// The ifunc is emitted before its resolver.
int foo(int) __attribute__ ((ifunc("foo_ifunc")));

static int f1(int i) {
Expand Down Expand Up @@ -45,20 +46,24 @@ extern void goo(void) __attribute__ ((ifunc("goo_ifunc")));
void* goo_ifunc(void) {
return 0;
}

/// The ifunc is emitted after its resolver.
void *hoo_ifunc(void) { return 0; }
extern void hoo(int) __attribute__ ((ifunc("hoo_ifunc")));

// CHECK: @foo = ifunc i32 (i32), ptr @foo_ifunc
// CHECK: @goo = ifunc void (), ptr @goo_ifunc
// CHECK: @hoo = ifunc void (i32), ptr @hoo_ifunc

// CHECK: call i32 @foo(i32
// CHECK: call void @goo()

// SAN: define internal nonnull {{(noundef )?}}ptr @foo_ifunc() #[[#FOO_IFUNC:]] {
// MACSAN: define internal nonnull {{(noundef )?}}ptr @foo_ifunc() #[[#FOO_IFUNC:]] {

// SAN: define dso_local noalias {{(noundef )?}}ptr @goo_ifunc() #[[#GOO_IFUNC:]] {
// MACSAN: define noalias {{(noundef )?}}ptr @goo_ifunc() #[[#GOO_IFUNC:]] {
// SAN: define {{(dso_local )?}}noalias {{(noundef )?}}ptr @goo_ifunc() #[[#GOO_IFUNC:]] {

// SAN-DAG: attributes #[[#FOO_IFUNC]] = {{{.*}} disable_sanitizer_instrumentation {{.*}}
// MACSAN-DAG: attributes #[[#FOO_IFUNC]] = {{{.*}} disable_sanitizer_instrumentation {{.*}}
// SAN: define {{(dso_local )?}}noalias {{(noundef )?}}ptr @hoo_ifunc() #[[#HOO_IFUNC:]] {

// SAN-DAG: attributes #[[#FOO_IFUNC]] = {{{.*}} disable_sanitizer_instrumentation {{.*}}
// SAN-DAG: attributes #[[#GOO_IFUNC]] = {{{.*}} disable_sanitizer_instrumentation {{.*}}
// MACSAN-DAG: attributes #[[#GOO_IFUNC]] = {{{.*}} disable_sanitizer_instrumentation {{.*}}
// SAN-DAG: attributes #[[#HOO_IFUNC]] = {{{.*}} disable_sanitizer_instrumentation {{.*}}
15 changes: 14 additions & 1 deletion clang/test/CodeGen/kcfi.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm -fsanitize=kcfi -o - %s | FileCheck %s
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm -fsanitize=kcfi -o - %s | FileCheck %s --check-prefixes=CHECK,C
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm -fsanitize=kcfi -x c++ -o - %s | FileCheck %s --check-prefixes=CHECK,MEMBER
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm -fsanitize=kcfi -fpatchable-function-entry-offset=3 -o - %s | FileCheck %s --check-prefixes=CHECK,OFFSET
#if !__has_feature(kcfi)
Expand All @@ -10,6 +10,9 @@
// CHECK: module asm ".set __kcfi_typeid_[[F4]], [[#%d,HASH:]]"
/// Must not __kcfi_typeid symbols for non-address-taken declarations
// CHECK-NOT: module asm ".weak __kcfi_typeid_{{f6|_Z2f6v}}"

// C: @ifunc1 = ifunc i32 (i32), ptr @resolver1
// C: @ifunc2 = ifunc i64 (i64), ptr @resolver2
typedef int (*fn_t)(void);

// CHECK: define dso_local{{.*}} i32 @{{f1|_Z2f1v}}(){{.*}} !kcfi_type ![[#TYPE:]]
Expand All @@ -30,6 +33,16 @@ int call(fn_t f) {
return f();
}

#ifndef __cplusplus
// C: define internal ptr @resolver1() #[[#]] {
int ifunc1(int) __attribute__((ifunc("resolver1")));
static void *resolver1(void) { return 0; }

// C: define internal ptr @resolver2() #[[#]] {
static void *resolver2(void) { return 0; }
long ifunc2(long) __attribute__((ifunc("resolver2")));
#endif

// CHECK-DAG: define internal{{.*}} i32 @{{f3|_ZL2f3v}}(){{.*}} !kcfi_type ![[#TYPE]]
static int f3(void) { return 1; }

Expand Down
94 changes: 94 additions & 0 deletions clang/test/CodeGen/variadic-nvptx.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5
// RUN: %clang_cc1 -triple nvptx64-nvidia-cuda -emit-llvm -o - %s | FileCheck %s

extern void varargs_simple(int, ...);

// CHECK-LABEL: define dso_local void @foo(
// CHECK-SAME: ) #[[ATTR0:[0-9]+]] {
// CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: [[C:%.*]] = alloca i8, align 1
// CHECK-NEXT: [[S:%.*]] = alloca i16, align 2
// CHECK-NEXT: [[I:%.*]] = alloca i32, align 4
// CHECK-NEXT: [[L:%.*]] = alloca i64, align 8
// CHECK-NEXT: [[F:%.*]] = alloca float, align 4
// CHECK-NEXT: [[D:%.*]] = alloca double, align 8
// CHECK-NEXT: [[A:%.*]] = alloca [[STRUCT_ANON:%.*]], align 4
// CHECK-NEXT: [[V:%.*]] = alloca <4 x i32>, align 16
// CHECK-NEXT: [[T:%.*]] = alloca [[STRUCT_ANON_0:%.*]], align 1
// CHECK-NEXT: store i8 1, ptr [[C]], align 1
// CHECK-NEXT: store i16 1, ptr [[S]], align 2
// CHECK-NEXT: store i32 1, ptr [[I]], align 4
// CHECK-NEXT: store i64 1, ptr [[L]], align 8
// CHECK-NEXT: store float 1.000000e+00, ptr [[F]], align 4
// CHECK-NEXT: store double 1.000000e+00, ptr [[D]], align 8
// CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[C]], align 1
// CHECK-NEXT: [[CONV:%.*]] = sext i8 [[TMP0]] to i32
// CHECK-NEXT: [[TMP1:%.*]] = load i16, ptr [[S]], align 2
// CHECK-NEXT: [[CONV1:%.*]] = sext i16 [[TMP1]] to i32
// CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[I]], align 4
// CHECK-NEXT: [[TMP3:%.*]] = load i64, ptr [[L]], align 8
// CHECK-NEXT: [[TMP4:%.*]] = load float, ptr [[F]], align 4
// CHECK-NEXT: [[CONV2:%.*]] = fpext float [[TMP4]] to double
// CHECK-NEXT: [[TMP5:%.*]] = load double, ptr [[D]], align 8
// CHECK-NEXT: call void (i32, ...) @varargs_simple(i32 noundef 0, i32 noundef [[CONV]], i32 noundef [[CONV1]], i32 noundef [[TMP2]], i64 noundef [[TMP3]], double noundef [[CONV2]], double noundef [[TMP5]])
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[A]], ptr align 4 @__const.foo.a, i64 12, i1 false)
// CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT_ANON]], ptr [[A]], i32 0, i32 0
// CHECK-NEXT: [[TMP7:%.*]] = load i32, ptr [[TMP6]], align 4
// CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds [[STRUCT_ANON]], ptr [[A]], i32 0, i32 1
// CHECK-NEXT: [[TMP9:%.*]] = load i8, ptr [[TMP8]], align 4
// CHECK-NEXT: [[TMP10:%.*]] = getelementptr inbounds [[STRUCT_ANON]], ptr [[A]], i32 0, i32 2
// CHECK-NEXT: [[TMP11:%.*]] = load i32, ptr [[TMP10]], align 4
// CHECK-NEXT: call void (i32, ...) @varargs_simple(i32 noundef 0, i32 [[TMP7]], i8 [[TMP9]], i32 [[TMP11]])
// CHECK-NEXT: store <4 x i32> <i32 1, i32 1, i32 1, i32 1>, ptr [[V]], align 16
// CHECK-NEXT: [[TMP12:%.*]] = load <4 x i32>, ptr [[V]], align 16
// CHECK-NEXT: call void (i32, ...) @varargs_simple(i32 noundef 0, <4 x i32> noundef [[TMP12]])
// CHECK-NEXT: [[TMP13:%.*]] = getelementptr inbounds [[STRUCT_ANON_0]], ptr [[T]], i32 0, i32 0
// CHECK-NEXT: [[TMP14:%.*]] = load i8, ptr [[TMP13]], align 1
// CHECK-NEXT: [[TMP15:%.*]] = getelementptr inbounds [[STRUCT_ANON_0]], ptr [[T]], i32 0, i32 1
// CHECK-NEXT: [[TMP16:%.*]] = load i8, ptr [[TMP15]], align 1
// CHECK-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT_ANON_0]], ptr [[T]], i32 0, i32 0
// CHECK-NEXT: [[TMP18:%.*]] = load i8, ptr [[TMP17]], align 1
// CHECK-NEXT: [[TMP19:%.*]] = getelementptr inbounds [[STRUCT_ANON_0]], ptr [[T]], i32 0, i32 1
// CHECK-NEXT: [[TMP20:%.*]] = load i8, ptr [[TMP19]], align 1
// CHECK-NEXT: [[TMP21:%.*]] = getelementptr inbounds [[STRUCT_ANON_0]], ptr [[T]], i32 0, i32 0
// CHECK-NEXT: [[TMP22:%.*]] = load i8, ptr [[TMP21]], align 1
// CHECK-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT_ANON_0]], ptr [[T]], i32 0, i32 1
// CHECK-NEXT: [[TMP24:%.*]] = load i8, ptr [[TMP23]], align 1
// CHECK-NEXT: call void (i32, ...) @varargs_simple(i32 noundef 0, i8 [[TMP14]], i8 [[TMP16]], i8 [[TMP18]], i8 [[TMP20]], i32 noundef 0, i8 [[TMP22]], i8 [[TMP24]])
// CHECK-NEXT: ret void
//
void foo() {
char c = '\x1';
short s = 1;
int i = 1;
long l = 1;
float f = 1.f;
double d = 1.;
varargs_simple(0, c, s, i, l, f, d);

struct {int x; char c; int y;} a = {1, '\x1', 1};
varargs_simple(0, a);

typedef int __attribute__((ext_vector_type(4))) int4;
int4 v = {1, 1, 1, 1};
varargs_simple(0, v);

struct {char c, d;} t;
varargs_simple(0, t, t, 0, t);
}

typedef struct {long x; long y;} S;
extern void varargs_complex(S, S, ...);

// CHECK-LABEL: define dso_local void @bar(
// CHECK-SAME: ) #[[ATTR0]] {
// CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: [[S:%.*]] = alloca [[STRUCT_S:%.*]], align 8
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[S]], ptr align 8 @__const.bar.s, i64 16, i1 false)
// CHECK-NEXT: call void (ptr, ptr, ...) @varargs_complex(ptr noundef byval([[STRUCT_S]]) align 8 [[S]], ptr noundef byval([[STRUCT_S]]) align 8 [[S]], i32 noundef 1, i64 noundef 1, double noundef 1.000000e+00)
// CHECK-NEXT: ret void
//
void bar() {
S s = {1l, 1l};
varargs_complex(s, s, 1, 1l, 1.0);
}
50 changes: 50 additions & 0 deletions clang/test/CodeGenCUDA/template-class-static-member.cu
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// RUN: %clang_cc1 -triple amdgcn-amd-amdhsa -fcuda-is-device \
// RUN: -emit-llvm -o - -x hip %s | FileCheck -check-prefix=DEV %s

// RUN: %clang_cc1 -triple x86_64-gnu-linux -std=c++11 \
// RUN: -emit-llvm -o - -x hip %s | FileCheck -check-prefix=HOST %s

// Negative tests.

// RUN: %clang_cc1 -triple amdgcn-amd-amdhsa -fcuda-is-device \
// RUN: -emit-llvm -o - -x hip %s | FileCheck -check-prefix=DEV-NEG %s

#include "Inputs/cuda.h"

template <class T>
class A {
static int h_member;
__device__ static int d_member;
__constant__ static int c_member;
__managed__ static int m_member;
const static int const_member = 0;
};

template <class T>
int A<T>::h_member;

template <class T>
__device__ int A<T>::d_member;

template <class T>
__constant__ int A<T>::c_member;

template <class T>
__managed__ int A<T>::m_member;

template <class T>
const int A<T>::const_member;

template class A<int>;

//DEV-DAG: @_ZN1AIiE8d_memberE = internal addrspace(1) global i32 0, comdat, align 4
//DEV-DAG: @_ZN1AIiE8c_memberE = internal addrspace(4) global i32 0, comdat, align 4
//DEV-DAG: @_ZN1AIiE8m_memberE = internal addrspace(1) externally_initialized global ptr addrspace(1) null
//DEV-DAG: @_ZN1AIiE12const_memberE = internal addrspace(4) constant i32 0, comdat, align 4
//DEV-NEG-NOT: @_ZN1AIiE8h_memberE

//HOST-DAG: @_ZN1AIiE8h_memberE = weak_odr global i32 0, comdat, align 4
//HOST-DAG: @_ZN1AIiE8d_memberE = internal global i32 undef, comdat, align 4
//HOST-DAG: @_ZN1AIiE8c_memberE = internal global i32 undef, comdat, align 4
//HOST-DAG: @_ZN1AIiE8m_memberE = internal externally_initialized global ptr null
//HOST-DAG: @_ZN1AIiE12const_memberE = weak_odr constant i32 0, comdat, align 4
30 changes: 30 additions & 0 deletions clang/test/CodeGenCXX/arm64-generated-fn-attr.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// RUN: %clang_cc1 -triple aarch64 -mbranch-target-enforce -msign-return-address=all -fcxx-exceptions -fexceptions -emit-llvm %s -o - | FileCheck %s

// Check that functions generated by clang have the correct attributes

class Example {
public:
Example();
int fn();
};

// Initialization of var1 causes __cxx_global_var_init and __tls_init to be generated
thread_local Example var1;
extern thread_local Example var2;
extern void fn();

int testfn() noexcept {
// Calling fn in a noexcept function causes __clang_call_terminate to be generated
fn();
// Use of var1 and var2 causes TLS wrapper functions to be generated
return var1.fn() + var2.fn();
}

// CHECK: define {{.*}} @__cxx_global_var_init() [[ATTR1:#[0-9]+]]
// CHECK: define {{.*}} @__clang_call_terminate({{.*}}) [[ATTR2:#[0-9]+]]
// CHECK: define {{.*}} @_ZTW4var1() [[ATTR1]]
// CHECK: define {{.*}} @_ZTW4var2() [[ATTR1]]
// CHECK: define {{.*}} @__tls_init() [[ATTR1]]

// CHECK: attributes [[ATTR1]] = { {{.*}}"branch-target-enforcement" {{.*}}"sign-return-address"="all" "sign-return-address-key"="a_key"
// CHECK: attributes [[ATTR2]] = { {{.*}}"branch-target-enforcement" {{.*}}"sign-return-address"="all" "sign-return-address-key"="a_key"
1 change: 0 additions & 1 deletion clang/test/CodeGenCXX/bitfield-access-empty.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
// RUN: %clang_cc1 -triple=bpf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s
// RUN: %clang_cc1 -triple=csky %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s
// RUN: %clang_cc1 -triple=hexagon-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s
// RUN: %clang_cc1 -triple=le64-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s
// RUN: %clang_cc1 -triple=loongarch32-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s
// RUN: %clang_cc1 -triple=nvptx-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s
// RUN: %clang_cc1 -triple=riscv32 %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s
Expand Down
1 change: 0 additions & 1 deletion clang/test/CodeGenCXX/bitfield-access-tail.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
// RUN: %clang_cc1 -triple=bpf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT64 %s
// RUN: %clang_cc1 -triple=csky %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT32 %s
// RUN: %clang_cc1 -triple=hexagon-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT32 %s
// RUN: %clang_cc1 -triple=le64-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT64 %s
// RUN: %clang_cc1 -triple=loongarch32-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT32 %s
// RUN: %clang_cc1 -triple=nvptx-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT32 %s
// RUN: %clang_cc1 -triple=riscv32 %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT32 %s
Expand Down
1 change: 1 addition & 0 deletions clang/test/CodeGenCXX/cxx1z-constexpr-if.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -std=c++1z %s -emit-llvm -fblocks -triple x86_64-apple-darwin10 -o - | FileCheck %s --implicit-check-not=should_not_be_used
// RUN: %clang_cc1 -std=c++1z %s -emit-llvm -fblocks -triple x86_64-apple-darwin10 -o - -fexperimental-new-constant-interpreter | FileCheck %s --implicit-check-not=should_not_be_used

void should_be_used_1();
void should_be_used_2();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ void f3_to_f2() {
// CHECK: [[f2:%.*]] = alloca <2 x float>
// CHECK: store <4 x double> <double 3.000000e+00, double 3.000000e+00, double 3.000000e+00, double 3.000000e+00>, ptr [[d4]]
// CHECK: [[vecd4:%.*]] = load <4 x double>, ptr [[d4]]
// CHECK: [[vecd2:%.*]] = shufflevector <4 x double> [[vecd4]], <4 x double> poison, <2 x i32> <i32 0, i32 1>
// CHECK: [[vecf2:%.*]] = fptrunc <2 x double> [[vecd2]] to <2 x float>
// CHECK: [[vecf4:%.*]] = fptrunc <4 x double> [[vecd4]] to <4 x float>
// CHECK: [[vecf2:%.*]] = shufflevector <4 x float> [[vecf4]], <4 x float> poison, <2 x i32> <i32 0, i32 1>
// CHECK: store <2 x float> [[vecf2]], ptr [[f2]]
void d4_to_f2() {
vector<double,4> d4 = 3.0;
Expand All @@ -55,8 +55,8 @@ void f2_to_i2() {
// CHECK: [[i2:%.*]] = alloca <2 x i32>
// CHECK: store <4 x double> <double 5.000000e+00, double 5.000000e+00, double 5.000000e+00, double 5.000000e+00>, ptr [[d4]]
// CHECK: [[vecd4:%.*]] = load <4 x double>, ptr [[d4]]
// CHECK: [[vecd2:%.*]] = shufflevector <4 x double> [[vecd4]], <4 x double> poison, <2 x i32> <i32 0, i32 1>
// CHECK: [[veci2]] = fptosi <2 x double> [[vecd2]] to <2 x i32>
// CHECK: [[veci4:%.*]] = fptosi <4 x double> [[vecd4]] to <4 x i32>
// CHECK: [[veci2:%.*]] = shufflevector <4 x i32> [[veci4]], <4 x i32> poison, <2 x i32> <i32 0, i32 1>
// CHECK: store <2 x i32> [[veci2]], ptr [[i2]]
void d4_to_i2() {
vector<double,4> d4 = 5.0;
Expand All @@ -81,8 +81,8 @@ void d4_to_l4() {
// CHECK: [[i2:%.*]] = alloca <2 x i32>
// CHECK: store <4 x i64> <i64 7, i64 7, i64 7, i64 7>, ptr [[l4]]
// CHECK: [[vecl4:%.*]] = load <4 x i64>, ptr [[l4]]
// CHECK: [[vecl2:%.*]] = shufflevector <4 x i64> [[vecl4]], <4 x i64> poison, <2 x i32> <i32 0, i32 1>
// CHECK: [[veci2:%.*]] = trunc <2 x i64> [[vecl2]] to <2 x i32>
// CHECK: [[veci4:%.*]] = trunc <4 x i64> [[vecl4]] to <4 x i32>
// CHECK: [[veci2:%.*]] = shufflevector <4 x i32> [[veci4]], <4 x i32> poison, <2 x i32> <i32 0, i32 1>
// CHECK: store <2 x i32> [[veci2]], ptr [[i2]]
void l4_to_i2() {
vector<long, 4> l4 = 7;
Expand All @@ -108,9 +108,9 @@ void i2_to_b2() {
// CHECK: [[b2:%.*]] = alloca i8
// CHECK: store <4 x double> <double 9.000000e+00, double 9.000000e+00, double 9.000000e+00, double 9.000000e+00>, ptr [[d4]]
// CHECK: [[vecd4:%.*]] = load <4 x double>, ptr [[d4]]
// CHECK: [[vecd2:%.*]] = shufflevector <4 x double> [[vecd4]], <4 x double> poison, <2 x i32> <i32 0, i32 1>
// CHECK: [[vecb2:%.*]] = fcmp une <2 x double> [[vecd2]], zeroinitializer
// CHECK: [[vecb8:%.*]] = shufflevector <2 x i1> [[vecb2]], <2 x i1> poison, <8 x i32> <i32 0, i32 1, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison>
// CHECK: [[vecb4:%.*]] = fcmp une <4 x double> [[vecd4]], zeroinitializer
// CHECK: [[vecd2:%.*]] = shufflevector <4 x i1> [[vecb4]], <4 x i1> poison, <2 x i32> <i32 0, i32 1>
// CHECK: [[vecb8:%.*]] = shufflevector <2 x i1> [[vecd2]], <2 x i1> poison, <8 x i32> <i32 0, i32 1, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison>
// CHECK: [[i8:%.*]] = bitcast <8 x i1> [[vecb8]] to i8
// CHECK: store i8 [[i8]], ptr [[b2]]
void d4_to_b2() {
Expand Down
34 changes: 1 addition & 33 deletions clang/test/CodeGenHLSL/builtins/dot.hlsl
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \
// RUN: dxil-pc-shadermodel6.3-library %s -fnative-half-type \
// RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s \
// RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s \
// RUN: --check-prefixes=CHECK,NATIVE_HALF
// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \
// RUN: dxil-pc-shadermodel6.3-library %s -emit-llvm -disable-llvm-passes \
Expand Down Expand Up @@ -156,38 +156,6 @@ float test_dot_float3_splat(float p0, float3 p1) { return dot(p0, p1); }
// CHECK: ret float %dx.dot
float test_dot_float4_splat(float p0, float4 p1) { return dot(p0, p1); }

// CHECK: %conv = sitofp i32 %1 to float
// CHECK: %splat.splatinsert = insertelement <2 x float> poison, float %conv, i64 0
// CHECK: %splat.splat = shufflevector <2 x float> %splat.splatinsert, <2 x float> poison, <2 x i32> zeroinitializer
// CHECK: %dx.dot = call float @llvm.dx.dot2.v2f32(<2 x float> %0, <2 x float> %splat.splat)
// CHECK: ret float %dx.dot
float test_builtin_dot_float2_int_splat(float2 p0, int p1) {
return dot(p0, p1);
}

// CHECK: %conv = sitofp i32 %1 to float
// CHECK: %splat.splatinsert = insertelement <3 x float> poison, float %conv, i64 0
// CHECK: %splat.splat = shufflevector <3 x float> %splat.splatinsert, <3 x float> poison, <3 x i32> zeroinitializer
// CHECK: %dx.dot = call float @llvm.dx.dot3.v3f32(<3 x float> %0, <3 x float> %splat.splat)
// CHECK: ret float %dx.dot
float test_builtin_dot_float3_int_splat(float3 p0, int p1) {
return dot(p0, p1);
}

// CHECK: %dx.dot = fmul double %0, %1
// CHECK: ret double %dx.dot
double test_dot_double(double p0, double p1) { return dot(p0, p1); }

// CHECK: %conv = zext i1 %tobool to i32
// CHECK: %dx.dot = mul i32 %conv, %1
// CHECK: ret i32 %dx.dot
int test_dot_bool_scalar_arg0_type_promotion(bool p0, int p1) {
return dot(p0, p1);
}

// CHECK: %conv = zext i1 %tobool to i32
// CHECK: %dx.dot = mul i32 %0, %conv
// CHECK: ret i32 %dx.dot
int test_dot_bool_scalar_arg1_type_promotion(int p0, bool p1) {
return dot(p0, p1);
}
24 changes: 0 additions & 24 deletions clang/test/CodeGenHLSL/builtins/lerp.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -86,27 +86,3 @@ float3 test_lerp_float3_splat(float p0, float3 p1) { return lerp(p0, p1, p1); }
// SPIR_CHECK: %hlsl.lerp = call <4 x float> @llvm.spv.lerp.v4f32(<4 x float> %splat.splat, <4 x float> %[[b]], <4 x float> %[[c]])
// CHECK: ret <4 x float> %hlsl.lerp
float4 test_lerp_float4_splat(float p0, float4 p1) { return lerp(p0, p1, p1); }

// CHECK: %[[a:.*]] = load <2 x float>, ptr %p0.addr, align 8
// CHECK: %[[b:.*]] = load <2 x float>, ptr %p0.addr, align 8
// CHECK: %conv = sitofp i32 {{.*}} to float
// CHECK: %splat.splatinsert = insertelement <2 x float> poison, float %conv, i64 0
// CHECK: %splat.splat = shufflevector <2 x float> %splat.splatinsert, <2 x float> poison, <2 x i32> zeroinitializer
// DXIL_CHECK: %hlsl.lerp = call <2 x float> @llvm.dx.lerp.v2f32(<2 x float> %[[a]], <2 x float> %[[b]], <2 x float> %splat.splat)
// SPIR_CHECK: %hlsl.lerp = call <2 x float> @llvm.spv.lerp.v2f32(<2 x float> %[[a]], <2 x float> %[[b]], <2 x float> %splat.splat)
// CHECK: ret <2 x float> %hlsl.lerp
float2 test_lerp_float2_int_splat(float2 p0, int p1) {
return lerp(p0, p0, p1);
}

// CHECK: %[[a:.*]] = load <3 x float>, ptr %p0.addr, align 16
// CHECK: %[[b:.*]] = load <3 x float>, ptr %p0.addr, align 16
// CHECK: %conv = sitofp i32 {{.*}} to float
// CHECK: %splat.splatinsert = insertelement <3 x float> poison, float %conv, i64 0
// CHECK: %splat.splat = shufflevector <3 x float> %splat.splatinsert, <3 x float> poison, <3 x i32> zeroinitializer
// DXIL_CHECK: %hlsl.lerp = call <3 x float> @llvm.dx.lerp.v3f32(<3 x float> %[[a]], <3 x float> %[[b]], <3 x float> %splat.splat)
// SPIR_CHECK: %hlsl.lerp = call <3 x float> @llvm.spv.lerp.v3f32(<3 x float> %[[a]], <3 x float> %[[b]], <3 x float> %splat.splat)
// CHECK: ret <3 x float> %hlsl.lerp
float3 test_lerp_float3_int_splat(float3 p0, int p1) {
return lerp(p0, p0, p1);
}
22 changes: 0 additions & 22 deletions clang/test/CodeGenHLSL/builtins/mad.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -281,25 +281,3 @@ float3 test_mad_float3_splat(float p0, float3 p1, float3 p2) { return mad(p0, p1
// CHECK: %hlsl.fmad = call <4 x float> @llvm.fmuladd.v4f32(<4 x float> %splat.splat, <4 x float> %[[p1]], <4 x float> %[[p2]])
// CHECK: ret <4 x float> %hlsl.fmad
float4 test_mad_float4_splat(float p0, float4 p1, float4 p2) { return mad(p0, p1, p2); }

// CHECK: %[[p0:.*]] = load <2 x float>, ptr %p0.addr, align 8
// CHECK: %[[p1:.*]] = load <2 x float>, ptr %p1.addr, align 8
// CHECK: %conv = sitofp i32 %{{.*}} to float
// CHECK: %splat.splatinsert = insertelement <2 x float> poison, float %conv, i64 0
// CHECK: %splat.splat = shufflevector <2 x float> %splat.splatinsert, <2 x float> poison, <2 x i32> zeroinitializer
// CHECK: %hlsl.fmad = call <2 x float> @llvm.fmuladd.v2f32(<2 x float> %[[p0]], <2 x float> %[[p1]], <2 x float> %splat.splat)
// CHECK: ret <2 x float> %hlsl.fmad
float2 test_mad_float2_int_splat(float2 p0, float2 p1, int p2) {
return mad(p0, p1, p2);
}

// CHECK: %[[p0:.*]] = load <3 x float>, ptr %p0.addr, align 16
// CHECK: %[[p1:.*]] = load <3 x float>, ptr %p1.addr, align 16
// CHECK: %conv = sitofp i32 %{{.*}} to float
// CHECK: %splat.splatinsert = insertelement <3 x float> poison, float %conv, i64 0
// CHECK: %splat.splat = shufflevector <3 x float> %splat.splatinsert, <3 x float> poison, <3 x i32> zeroinitializer
// CHECK: %hlsl.fmad = call <3 x float> @llvm.fmuladd.v3f32(<3 x float> %[[p0]], <3 x float> %[[p1]], <3 x float> %splat.splat)
// CHECK: ret <3 x float> %hlsl.fmad
float3 test_mad_float3_int_splat(float3 p0, float3 p1, int p2) {
return mad(p0, p1, p2);
}
28 changes: 14 additions & 14 deletions clang/test/Driver/print-enabled-extensions/aarch64-a64fx.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,19 @@
// CHECK-NEXT: Architecture Feature(s) Description
// CHECK-NEXT: FEAT_AES, FEAT_PMULL Enable AES support
// CHECK-NEXT: FEAT_AdvSIMD Enable Advanced SIMD instructions
// CHECK-NEXT: FEAT_CRC32 Enable ARMv8 CRC-32 checksum instructions
// CHECK-NEXT: FEAT_DPB Enable v8.2 data Cache Clean to Point of Persistence
// CHECK-NEXT: FEAT_FCMA Enable v8.3-A Floating-point complex number support
// CHECK-NEXT: FEAT_FP Enable ARMv8
// CHECK-NEXT: FEAT_FP16 Full FP16
// CHECK-NEXT: FEAT_LOR Enables ARM v8.1 Limited Ordering Regions extension
// CHECK-NEXT: FEAT_LSE Enable ARMv8.1 Large System Extension (LSE) atomic instructions
// CHECK-NEXT: FEAT_PAN Enables ARM v8.1 Privileged Access-Never extension
// CHECK-NEXT: FEAT_PAN2 Enable v8.2 PAN s1e1R and s1e1W Variants
// CHECK-NEXT: FEAT_PMUv3 Enable Code Generation for ARMv8 PMUv3 Performance Monitors extension
// CHECK-NEXT: FEAT_RAS, FEAT_RASv1p1 Enable ARMv8 Reliability, Availability and Serviceability Extensions
// CHECK-NEXT: FEAT_RDM Enable ARMv8.1 Rounding Double Multiply Add/Subtract instructions
// CHECK-NEXT: FEAT_CRC32 Enable Armv8.0-A CRC-32 checksum instructions
// CHECK-NEXT: FEAT_DPB Enable Armv8.2-A data Cache Clean to Point of Persistence
// CHECK-NEXT: FEAT_FCMA Enable Armv8.3-A Floating-point complex number support
// CHECK-NEXT: FEAT_FP Enable Armv8.0-A Floating Point Extensions
// CHECK-NEXT: FEAT_FP16 Enable half-precision floating-point data processing
// CHECK-NEXT: FEAT_LOR Enable Armv8.1-A Limited Ordering Regions extension
// CHECK-NEXT: FEAT_LSE Enable Armv8.1-A Large System Extension (LSE) atomic instructions
// CHECK-NEXT: FEAT_PAN Enable Armv8.1-A Privileged Access-Never extension
// CHECK-NEXT: FEAT_PAN2 Enable Armv8.2-A PAN s1e1R and s1e1W Variants
// CHECK-NEXT: FEAT_PMUv3 Enable Armv8.0-A PMUv3 Performance Monitors extension
// CHECK-NEXT: FEAT_RAS, FEAT_RASv1p1 Enable Armv8.0-A Reliability, Availability and Serviceability Extensions
// CHECK-NEXT: FEAT_RDM Enable Armv8.1-A Rounding Double Multiply Add/Subtract instructions
// CHECK-NEXT: FEAT_SHA1, FEAT_SHA256 Enable SHA1 and SHA256 support
// CHECK-NEXT: FEAT_SVE Enable Scalable Vector Extension (SVE) instructions
// CHECK-NEXT: FEAT_UAO Enable v8.2 UAO PState
// CHECK-NEXT: FEAT_VHE Enables ARM v8.1 Virtual Host extension
// CHECK-NEXT: FEAT_UAO Enable Armv8.2-A UAO PState
// CHECK-NEXT: FEAT_VHE Enable Armv8.1-A Virtual Host extension
62 changes: 31 additions & 31 deletions clang/test/Driver/print-enabled-extensions/aarch64-ampere1.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,50 +5,50 @@
// CHECK-EMPTY:
// CHECK-NEXT: Architecture Feature(s) Description
// CHECK-NEXT: FEAT_AES, FEAT_PMULL Enable AES support
// CHECK-NEXT: FEAT_AMUv1 Enable v8.4-A Activity Monitors extension
// CHECK-NEXT: FEAT_AMUv1p1 Enable v8.6-A Activity Monitors Virtualization support
// CHECK-NEXT: FEAT_AMUv1 Enable Armv8.4-A Activity Monitors extension
// CHECK-NEXT: FEAT_AMUv1p1 Enable Armv8.6-A Activity Monitors Virtualization support
// CHECK-NEXT: FEAT_AdvSIMD Enable Advanced SIMD instructions
// CHECK-NEXT: FEAT_BF16 Enable BFloat16 Extension
// CHECK-NEXT: FEAT_BTI Enable Branch Target Identification
// CHECK-NEXT: FEAT_CCIDX Enable v8.3-A Extend of the CCSIDR number of sets
// CHECK-NEXT: FEAT_CRC32 Enable ARMv8 CRC-32 checksum instructions
// CHECK-NEXT: FEAT_CCIDX Enable Armv8.3-A Extend of the CCSIDR number of sets
// CHECK-NEXT: FEAT_CRC32 Enable Armv8.0-A CRC-32 checksum instructions
// CHECK-NEXT: FEAT_CSV2_2 Enable architectural speculation restriction
// CHECK-NEXT: FEAT_DIT Enable v8.4-A Data Independent Timing instructions
// CHECK-NEXT: FEAT_DPB Enable v8.2 data Cache Clean to Point of Persistence
// CHECK-NEXT: FEAT_DPB2 Enable v8.5 Cache Clean to Point of Deep Persistence
// CHECK-NEXT: FEAT_DIT Enable Armv8.4-A Data Independent Timing instructions
// CHECK-NEXT: FEAT_DPB Enable Armv8.2-A data Cache Clean to Point of Persistence
// CHECK-NEXT: FEAT_DPB2 Enable Armv8.5-A Cache Clean to Point of Deep Persistence
// CHECK-NEXT: FEAT_DotProd Enable dot product support
// CHECK-NEXT: FEAT_ECV Enable enhanced counter virtualization extension
// CHECK-NEXT: FEAT_FCMA Enable v8.3-A Floating-point complex number support
// CHECK-NEXT: FEAT_FCMA Enable Armv8.3-A Floating-point complex number support
// CHECK-NEXT: FEAT_FGT Enable fine grained virtualization traps extension
// CHECK-NEXT: FEAT_FHM Enable FP16 FML instructions
// CHECK-NEXT: FEAT_FP Enable ARMv8
// CHECK-NEXT: FEAT_FP16 Full FP16
// CHECK-NEXT: FEAT_FP Enable Armv8.0-A Floating Point Extensions
// CHECK-NEXT: FEAT_FP16 Enable half-precision floating-point data processing
// CHECK-NEXT: FEAT_FRINTTS Enable FRInt[32|64][Z|X] instructions that round a floating-point number to an integer (in FP format) forcing it to fit into a 32- or 64-bit int
// CHECK-NEXT: FEAT_FlagM Enable v8.4-A Flag Manipulation Instructions
// CHECK-NEXT: FEAT_FlagM Enable Armv8.4-A Flag Manipulation instructions
// CHECK-NEXT: FEAT_FlagM2 Enable alternative NZCV format for floating point comparisons
// CHECK-NEXT: FEAT_I8MM Enable Matrix Multiply Int8 Extension
// CHECK-NEXT: FEAT_JSCVT Enable v8.3-A JavaScript FP conversion instructions
// CHECK-NEXT: FEAT_LOR Enables ARM v8.1 Limited Ordering Regions extension
// CHECK-NEXT: FEAT_JSCVT Enable Armv8.3-A JavaScript FP conversion instructions
// CHECK-NEXT: FEAT_LOR Enable Armv8.1-A Limited Ordering Regions extension
// CHECK-NEXT: FEAT_LRCPC Enable support for RCPC extension
// CHECK-NEXT: FEAT_LRCPC2 Enable v8.4-A RCPC instructions with Immediate Offsets
// CHECK-NEXT: FEAT_LSE Enable ARMv8.1 Large System Extension (LSE) atomic instructions
// CHECK-NEXT: FEAT_LSE2 Enable ARMv8.4 Large System Extension 2 (LSE2) atomicity rules
// CHECK-NEXT: FEAT_MPAM Enable v8.4-A Memory system Partitioning and Monitoring extension
// CHECK-NEXT: FEAT_NV, FEAT_NV2 Enable v8.4-A Nested Virtualization Enchancement
// CHECK-NEXT: FEAT_PAN Enables ARM v8.1 Privileged Access-Never extension
// CHECK-NEXT: FEAT_PAN2 Enable v8.2 PAN s1e1R and s1e1W Variants
// CHECK-NEXT: FEAT_PAuth Enable v8.3-A Pointer Authentication extension
// CHECK-NEXT: FEAT_PMUv3 Enable Code Generation for ARMv8 PMUv3 Performance Monitors extension
// CHECK-NEXT: FEAT_RAS, FEAT_RASv1p1 Enable ARMv8 Reliability, Availability and Serviceability Extensions
// CHECK-NEXT: FEAT_RDM Enable ARMv8.1 Rounding Double Multiply Add/Subtract instructions
// CHECK-NEXT: FEAT_LRCPC2 Enable Armv8.4-A RCPC instructions with Immediate Offsets
// CHECK-NEXT: FEAT_LSE Enable Armv8.1-A Large System Extension (LSE) atomic instructions
// CHECK-NEXT: FEAT_LSE2 Enable Armv8.4-A Large System Extension 2 (LSE2) atomicity rules
// CHECK-NEXT: FEAT_MPAM Enable Armv8.4-A Memory system Partitioning and Monitoring extension
// CHECK-NEXT: FEAT_NV, FEAT_NV2 Enable Armv8.4-A Nested Virtualization Enchancement
// CHECK-NEXT: FEAT_PAN Enable Armv8.1-A Privileged Access-Never extension
// CHECK-NEXT: FEAT_PAN2 Enable Armv8.2-A PAN s1e1R and s1e1W Variants
// CHECK-NEXT: FEAT_PAuth Enable Armv8.3-A Pointer Authentication extension
// CHECK-NEXT: FEAT_PMUv3 Enable Armv8.0-A PMUv3 Performance Monitors extension
// CHECK-NEXT: FEAT_RAS, FEAT_RASv1p1 Enable Armv8.0-A Reliability, Availability and Serviceability Extensions
// CHECK-NEXT: FEAT_RDM Enable Armv8.1-A Rounding Double Multiply Add/Subtract instructions
// CHECK-NEXT: FEAT_RNG Enable Random Number generation instructions
// CHECK-NEXT: FEAT_SB Enable v8.5 Speculation Barrier
// CHECK-NEXT: FEAT_SEL2 Enable v8.4-A Secure Exception Level 2 extension
// CHECK-NEXT: FEAT_SB Enable Armv8.5-A Speculation Barrier
// CHECK-NEXT: FEAT_SEL2 Enable Armv8.4-A Secure Exception Level 2 extension
// CHECK-NEXT: FEAT_SHA1, FEAT_SHA256 Enable SHA1 and SHA256 support
// CHECK-NEXT: FEAT_SHA3, FEAT_SHA512 Enable SHA512 and SHA3 support
// CHECK-NEXT: FEAT_SPECRES Enable v8.5a execution and data prediction invalidation instructions
// CHECK-NEXT: FEAT_SPECRES Enable Armv8.5-A execution and data prediction invalidation instructions
// CHECK-NEXT: FEAT_SSBS, FEAT_SSBS2 Enable Speculative Store Bypass Safe bit
// CHECK-NEXT: FEAT_TLBIOS, FEAT_TLBIRANGE Enable v8.4-A TLB Range and Maintenance Instructions
// CHECK-NEXT: FEAT_TRF Enable v8.4-A Trace extension
// CHECK-NEXT: FEAT_UAO Enable v8.2 UAO PState
// CHECK-NEXT: FEAT_VHE Enables ARM v8.1 Virtual Host extension
// CHECK-NEXT: FEAT_TLBIOS, FEAT_TLBIRANGE Enable Armv8.4-A TLB Range and Maintenance instructions
// CHECK-NEXT: FEAT_TRF Enable Armv8.4-A Trace extension
// CHECK-NEXT: FEAT_UAO Enable Armv8.2-A UAO PState
// CHECK-NEXT: FEAT_VHE Enable Armv8.1-A Virtual Host extension
Loading