aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Sema
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2024-02-07 14:37:28 +0000
committerDimitry Andric <dim@FreeBSD.org>2024-02-07 14:37:28 +0000
commit4fdf604ba667503ae582304cebdd3df426778a6b (patch)
treeaae65a5d1b0a1b1acd9389fc36a0baf5fc1918c7 /clang/lib/Sema
parent2d835ae8657273e3aa8b9ef3201fb8df5563af9d (diff)
Vendor import of llvm-project branch release/18.x llvmorg-18.1.0-rc2-0-gc6c86965d967.vendor/llvm-project/llvmorg-18.1.0-rc2-0-gc6c86965d967
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r--clang/lib/Sema/SemaChecking.cpp55
-rw-r--r--clang/lib/Sema/SemaConcept.cpp8
-rw-r--r--clang/lib/Sema/SemaDecl.cpp3
-rw-r--r--clang/lib/Sema/SemaExpr.cpp6
-rw-r--r--clang/lib/Sema/SemaInit.cpp40
-rw-r--r--clang/lib/Sema/SemaOverload.cpp82
-rw-r--r--clang/lib/Sema/SemaTemplate.cpp44
-rw-r--r--clang/lib/Sema/SemaType.cpp21
8 files changed, 114 insertions, 145 deletions
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 7833d5a2ea20..09b7e1c62fbd 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -7545,47 +7545,43 @@ void Sema::checkCall(NamedDecl *FDecl, const FunctionProtoType *Proto,
}
}
- // If the callee uses AArch64 SME ZA state but the caller doesn't define
- // any, then this is an error.
- FunctionType::ArmStateValue ArmZAState =
+ FunctionType::ArmStateValue CalleeArmZAState =
FunctionType::getArmZAState(ExtInfo.AArch64SMEAttributes);
- if (ArmZAState != FunctionType::ARM_None) {
+ FunctionType::ArmStateValue CalleeArmZT0State =
+ FunctionType::getArmZT0State(ExtInfo.AArch64SMEAttributes);
+ if (CalleeArmZAState != FunctionType::ARM_None ||
+ CalleeArmZT0State != FunctionType::ARM_None) {
bool CallerHasZAState = false;
+ bool CallerHasZT0State = false;
if (const auto *CallerFD = dyn_cast<FunctionDecl>(CurContext)) {
auto *Attr = CallerFD->getAttr<ArmNewAttr>();
if (Attr && Attr->isNewZA())
CallerHasZAState = true;
- else if (const auto *FPT =
- CallerFD->getType()->getAs<FunctionProtoType>())
- CallerHasZAState = FunctionType::getArmZAState(
- FPT->getExtProtoInfo().AArch64SMEAttributes) !=
- FunctionType::ARM_None;
- }
-
- if (!CallerHasZAState)
- Diag(Loc, diag::err_sme_za_call_no_za_state);
- }
-
- // If the callee uses AArch64 SME ZT0 state but the caller doesn't define
- // any, then this is an error.
- FunctionType::ArmStateValue ArmZT0State =
- FunctionType::getArmZT0State(ExtInfo.AArch64SMEAttributes);
- if (ArmZT0State != FunctionType::ARM_None) {
- bool CallerHasZT0State = false;
- if (const auto *CallerFD = dyn_cast<FunctionDecl>(CurContext)) {
- auto *Attr = CallerFD->getAttr<ArmNewAttr>();
if (Attr && Attr->isNewZT0())
CallerHasZT0State = true;
- else if (const auto *FPT =
- CallerFD->getType()->getAs<FunctionProtoType>())
- CallerHasZT0State =
+ if (const auto *FPT = CallerFD->getType()->getAs<FunctionProtoType>()) {
+ CallerHasZAState |=
+ FunctionType::getArmZAState(
+ FPT->getExtProtoInfo().AArch64SMEAttributes) !=
+ FunctionType::ARM_None;
+ CallerHasZT0State |=
FunctionType::getArmZT0State(
FPT->getExtProtoInfo().AArch64SMEAttributes) !=
FunctionType::ARM_None;
+ }
}
- if (!CallerHasZT0State)
+ if (CalleeArmZAState != FunctionType::ARM_None && !CallerHasZAState)
+ Diag(Loc, diag::err_sme_za_call_no_za_state);
+
+ if (CalleeArmZT0State != FunctionType::ARM_None && !CallerHasZT0State)
Diag(Loc, diag::err_sme_zt0_call_no_zt0_state);
+
+ if (CallerHasZAState && CalleeArmZAState == FunctionType::ARM_None &&
+ CalleeArmZT0State != FunctionType::ARM_None) {
+ Diag(Loc, diag::err_sme_unimplemented_za_save_restore);
+ Diag(Loc, diag::note_sme_use_preserves_za);
+ }
}
}
@@ -7643,9 +7639,8 @@ bool Sema::CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall,
unsigned NumArgs = TheCall->getNumArgs();
Expr *ImplicitThis = nullptr;
- if (IsMemberOperatorCall && !FDecl->isStatic() &&
- !FDecl->hasCXXExplicitFunctionObjectParameter()) {
- // If this is a call to a non-static member operator, hide the first
+ if (IsMemberOperatorCall && !FDecl->hasCXXExplicitFunctionObjectParameter()) {
+ // If this is a call to a member operator, hide the first
// argument from checkCall.
// FIXME: Our choice of AST representation here is less than ideal.
ImplicitThis = Args[0];
diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp
index acfc00f41254..88fc846c89e4 100644
--- a/clang/lib/Sema/SemaConcept.cpp
+++ b/clang/lib/Sema/SemaConcept.cpp
@@ -612,8 +612,12 @@ bool Sema::SetupConstraintScope(
// If this is a member function, make sure we get the parameters that
// reference the original primary template.
- if (const auto *FromMemTempl =
- PrimaryTemplate->getInstantiatedFromMemberTemplate()) {
+ // We walk up the instantiated template chain so that nested lambdas get
+ // handled properly.
+ for (FunctionTemplateDecl *FromMemTempl =
+ PrimaryTemplate->getInstantiatedFromMemberTemplate();
+ FromMemTempl;
+ FromMemTempl = FromMemTempl->getInstantiatedFromMemberTemplate()) {
if (addInstantiatedParametersToScope(FD, FromMemTempl->getTemplatedDecl(),
Scope, MLTAL))
return true;
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index f9bf1d14bdc4..a300badc6d02 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -12752,7 +12752,8 @@ namespace {
}
if (OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(E)) {
- HandleValue(OVE->getSourceExpr());
+ if (Expr *SE = OVE->getSourceExpr())
+ HandleValue(SE);
return;
}
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 6413a48f809a..4efcb3590355 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -11142,7 +11142,8 @@ QualType Sema::CheckVectorOperands(ExprResult &LHS, ExprResult &RHS,
if (VecType->getVectorKind() == VectorKind::SveFixedLengthData ||
VecType->getVectorKind() == VectorKind::SveFixedLengthPredicate)
return true;
- if (VecType->getVectorKind() == VectorKind::RVVFixedLengthData) {
+ if (VecType->getVectorKind() == VectorKind::RVVFixedLengthData ||
+ VecType->getVectorKind() == VectorKind::RVVFixedLengthMask) {
SVEorRVV = 1;
return true;
}
@@ -11173,7 +11174,8 @@ QualType Sema::CheckVectorOperands(ExprResult &LHS, ExprResult &RHS,
SecondVecType->getVectorKind() ==
VectorKind::SveFixedLengthPredicate)
return true;
- if (SecondVecType->getVectorKind() == VectorKind::RVVFixedLengthData) {
+ if (SecondVecType->getVectorKind() == VectorKind::RVVFixedLengthData ||
+ SecondVecType->getVectorKind() == VectorKind::RVVFixedLengthMask) {
SVEorRVV = 1;
return true;
}
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index 91e4cb7b68a2..457fa377355a 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -4200,7 +4200,7 @@ static OverloadingResult ResolveConstructorOverload(
/// \param IsListInit Is this list-initialization?
/// \param IsInitListCopy Is this non-list-initialization resulting from a
/// list-initialization from {x} where x is the same
-/// aggregate type as the entity?
+/// type as the entity?
static void TryConstructorInitialization(Sema &S,
const InitializedEntity &Entity,
const InitializationKind &Kind,
@@ -4230,14 +4230,6 @@ static void TryConstructorInitialization(Sema &S,
Entity.getKind() !=
InitializedEntity::EK_LambdaToBlockConversionBlockElement);
- bool CopyElisionPossible = false;
- auto ElideConstructor = [&] {
- // Convert qualifications if necessary.
- Sequence.AddQualificationConversionStep(DestType, VK_PRValue);
- if (ILE)
- Sequence.RewrapReferenceInitList(DestType, ILE);
- };
-
// C++17 [dcl.init]p17:
// - If the initializer expression is a prvalue and the cv-unqualified
// version of the source type is the same class as the class of the
@@ -4250,17 +4242,11 @@ static void TryConstructorInitialization(Sema &S,
if (S.getLangOpts().CPlusPlus17 && !RequireActualConstructor &&
UnwrappedArgs.size() == 1 && UnwrappedArgs[0]->isPRValue() &&
S.Context.hasSameUnqualifiedType(UnwrappedArgs[0]->getType(), DestType)) {
- if (ILE && !DestType->isAggregateType()) {
- // CWG2311: T{ prvalue_of_type_T } is not eligible for copy elision
- // Make this an elision if this won't call an initializer-list
- // constructor. (Always on an aggregate type or check constructors first.)
- assert(!IsInitListCopy &&
- "IsInitListCopy only possible with aggregate types");
- CopyElisionPossible = true;
- } else {
- ElideConstructor();
- return;
- }
+ // Convert qualifications if necessary.
+ Sequence.AddQualificationConversionStep(DestType, VK_PRValue);
+ if (ILE)
+ Sequence.RewrapReferenceInitList(DestType, ILE);
+ return;
}
const RecordType *DestRecordType = DestType->getAs<RecordType>();
@@ -4305,12 +4291,6 @@ static void TryConstructorInitialization(Sema &S,
S, Kind.getLocation(), Args, CandidateSet, DestType, Ctors, Best,
CopyInitialization, AllowExplicit,
/*OnlyListConstructors=*/true, IsListInit, RequireActualConstructor);
-
- if (CopyElisionPossible && Result == OR_No_Viable_Function) {
- // No initializer list candidate
- ElideConstructor();
- return;
- }
}
// C++11 [over.match.list]p1:
@@ -4592,9 +4572,9 @@ static void TryListInitialization(Sema &S,
return;
}
- // C++11 [dcl.init.list]p3, per DR1467 and DR2137:
- // - If T is an aggregate class and the initializer list has a single element
- // of type cv U, where U is T or a class derived from T, the object is
+ // C++11 [dcl.init.list]p3, per DR1467:
+ // - If T is a class type and the initializer list has a single element of
+ // type cv U, where U is T or a class derived from T, the object is
// initialized from that element (by copy-initialization for
// copy-list-initialization, or by direct-initialization for
// direct-list-initialization).
@@ -4605,7 +4585,7 @@ static void TryListInitialization(Sema &S,
// - Otherwise, if T is an aggregate, [...] (continue below).
if (S.getLangOpts().CPlusPlus11 && InitList->getNumInits() == 1 &&
!IsDesignatedInit) {
- if (DestType->isRecordType() && DestType->isAggregateType()) {
+ if (DestType->isRecordType()) {
QualType InitType = InitList->getInit(0)->getType();
if (S.Context.hasSameUnqualifiedType(InitType, DestType) ||
S.IsDerivedFrom(InitList->getBeginLoc(), InitType, DestType)) {
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 030878899b81..940bcccb9e26 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -1568,37 +1568,19 @@ TryUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
// called for those cases.
if (CXXConstructorDecl *Constructor
= dyn_cast<CXXConstructorDecl>(ICS.UserDefined.ConversionFunction)) {
- QualType FromType;
- SourceLocation FromLoc;
- // C++11 [over.ics.list]p6, per DR2137:
- // C++17 [over.ics.list]p6:
- // If C is not an initializer-list constructor and the initializer list
- // has a single element of type cv U, where U is X or a class derived
- // from X, the implicit conversion sequence has Exact Match rank if U is
- // X, or Conversion rank if U is derived from X.
- if (const auto *InitList = dyn_cast<InitListExpr>(From);
- InitList && InitList->getNumInits() == 1 &&
- !S.isInitListConstructor(Constructor)) {
- const Expr *SingleInit = InitList->getInit(0);
- FromType = SingleInit->getType();
- FromLoc = SingleInit->getBeginLoc();
- } else {
- FromType = From->getType();
- FromLoc = From->getBeginLoc();
- }
- QualType FromCanon =
- S.Context.getCanonicalType(FromType.getUnqualifiedType());
+ QualType FromCanon
+ = S.Context.getCanonicalType(From->getType().getUnqualifiedType());
QualType ToCanon
= S.Context.getCanonicalType(ToType).getUnqualifiedType();
if (Constructor->isCopyConstructor() &&
(FromCanon == ToCanon ||
- S.IsDerivedFrom(FromLoc, FromCanon, ToCanon))) {
+ S.IsDerivedFrom(From->getBeginLoc(), FromCanon, ToCanon))) {
// Turn this into a "standard" conversion sequence, so that it
// gets ranked with standard conversion sequences.
DeclAccessPair Found = ICS.UserDefined.FoundConversionFunction;
ICS.setStandard();
ICS.Standard.setAsIdentityConversion();
- ICS.Standard.setFromType(FromType);
+ ICS.Standard.setFromType(From->getType());
ICS.Standard.setAllToTypes(ToType);
ICS.Standard.CopyConstructor = Constructor;
ICS.Standard.FoundCopyConstructor = Found;
@@ -5324,18 +5306,18 @@ TryListConversion(Sema &S, InitListExpr *From, QualType ToType,
IsDesignatedInit)
return Result;
- // Per DR1467 and DR2137:
- // If the parameter type is an aggregate class X and the initializer list
- // has a single element of type cv U, where U is X or a class derived from
- // X, the implicit conversion sequence is the one required to convert the
- // element to the parameter type.
+ // Per DR1467:
+ // If the parameter type is a class X and the initializer list has a single
+ // element of type cv U, where U is X or a class derived from X, the
+ // implicit conversion sequence is the one required to convert the element
+ // to the parameter type.
//
// Otherwise, if the parameter type is a character array [... ]
// and the initializer list has a single element that is an
// appropriately-typed string literal (8.5.2 [dcl.init.string]), the
// implicit conversion sequence is the identity conversion.
if (From->getNumInits() == 1 && !IsDesignatedInit) {
- if (ToType->isRecordType() && ToType->isAggregateType()) {
+ if (ToType->isRecordType()) {
QualType InitType = From->getInit(0)->getType();
if (S.Context.hasSameUnqualifiedType(InitType, ToType) ||
S.IsDerivedFrom(From->getBeginLoc(), InitType, ToType))
@@ -5682,10 +5664,15 @@ static ImplicitConversionSequence TryObjectArgumentInitialization(
assert(FromType->isRecordType());
QualType ClassType = S.Context.getTypeDeclType(ActingContext);
- // [class.dtor]p2: A destructor can be invoked for a const, volatile or
- // const volatile object.
+ // C++98 [class.dtor]p2:
+ // A destructor can be invoked for a const, volatile or const volatile
+ // object.
+ // C++98 [over.match.funcs]p4:
+ // For static member functions, the implicit object parameter is considered
+ // to match any object (since if the function is selected, the object is
+ // discarded).
Qualifiers Quals = Method->getMethodQualifiers();
- if (isa<CXXDestructorDecl>(Method)) {
+ if (isa<CXXDestructorDecl>(Method) || Method->isStatic()) {
Quals.addConst();
Quals.addVolatile();
}
@@ -15079,7 +15066,7 @@ ExprResult Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
CXXMethodDecl *Method = cast<CXXMethodDecl>(FnDecl);
SmallVector<Expr *, 2> MethodArgs;
- // Handle 'this' parameter if the selected function is not static.
+ // Initialize the object parameter.
if (Method->isExplicitObjectMemberFunction()) {
ExprResult Res =
InitializeExplicitObjectArgument(*this, Args[0], Method);
@@ -15087,7 +15074,7 @@ ExprResult Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
return ExprError();
Args[0] = Res.get();
ArgExpr = Args;
- } else if (Method->isInstance()) {
+ } else {
ExprResult Arg0 = PerformImplicitObjectArgumentInitialization(
Args[0], /*Qualifier=*/nullptr, Best->FoundDecl, Method);
if (Arg0.isInvalid())
@@ -15115,15 +15102,9 @@ ExprResult Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
ExprValueKind VK = Expr::getValueKindForType(ResultTy);
ResultTy = ResultTy.getNonLValueExprType(Context);
- CallExpr *TheCall;
- if (Method->isInstance())
- TheCall = CXXOperatorCallExpr::Create(
- Context, OO_Subscript, FnExpr.get(), MethodArgs, ResultTy, VK,
- RLoc, CurFPFeatureOverrides());
- else
- TheCall =
- CallExpr::Create(Context, FnExpr.get(), MethodArgs, ResultTy, VK,
- RLoc, CurFPFeatureOverrides());
+ CallExpr *TheCall = CXXOperatorCallExpr::Create(
+ Context, OO_Subscript, FnExpr.get(), MethodArgs, ResultTy, VK, RLoc,
+ CurFPFeatureOverrides());
if (CheckCallReturnType(FnDecl->getReturnType(), LLoc, TheCall, FnDecl))
return ExprError();
@@ -15751,15 +15732,13 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj,
bool IsError = false;
- // Initialize the implicit object parameter if needed.
- // Since C++23, this could also be a call to a static call operator
- // which we emit as a regular CallExpr.
+ // Initialize the object parameter.
llvm::SmallVector<Expr *, 8> NewArgs;
if (Method->isExplicitObjectMemberFunction()) {
// FIXME: we should do that during the definition of the lambda when we can.
DiagnoseInvalidExplicitObjectParameterInLambda(Method);
PrepareExplicitObjectArgument(*this, Method, Obj, Args, NewArgs);
- } else if (Method->isInstance()) {
+ } else {
ExprResult ObjRes = PerformImplicitObjectArgumentInitialization(
Object.get(), /*Qualifier=*/nullptr, Best->FoundDecl, Method);
if (ObjRes.isInvalid())
@@ -15793,14 +15772,9 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj,
ExprValueKind VK = Expr::getValueKindForType(ResultTy);
ResultTy = ResultTy.getNonLValueExprType(Context);
- CallExpr *TheCall;
- if (Method->isInstance())
- TheCall = CXXOperatorCallExpr::Create(Context, OO_Call, NewFn.get(),
- MethodArgs, ResultTy, VK, RParenLoc,
- CurFPFeatureOverrides());
- else
- TheCall = CallExpr::Create(Context, NewFn.get(), MethodArgs, ResultTy, VK,
- RParenLoc, CurFPFeatureOverrides());
+ CallExpr *TheCall = CXXOperatorCallExpr::Create(
+ Context, OO_Call, NewFn.get(), MethodArgs, ResultTy, VK, RParenLoc,
+ CurFPFeatureOverrides());
if (CheckCallReturnType(Method->getReturnType(), LParenLoc, TheCall, Method))
return true;
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 9bfa71dc8bcf..a381d876a54c 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -7412,9 +7412,9 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
if (ArgResult.isInvalid())
return ExprError();
- // Prior to C++20, enforce restrictions on possible template argument
- // values.
- if (!getLangOpts().CPlusPlus20 && Value.isLValue()) {
+ if (Value.isLValue()) {
+ APValue::LValueBase Base = Value.getLValueBase();
+ auto *VD = const_cast<ValueDecl *>(Base.dyn_cast<const ValueDecl *>());
// For a non-type template-parameter of pointer or reference type,
// the value of the constant expression shall not refer to
assert(ParamType->isPointerType() || ParamType->isReferenceType() ||
@@ -7423,8 +7423,6 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
// -- a string literal
// -- the result of a typeid expression, or
// -- a predefined __func__ variable
- APValue::LValueBase Base = Value.getLValueBase();
- auto *VD = const_cast<ValueDecl *>(Base.dyn_cast<const ValueDecl *>());
if (Base &&
(!VD ||
isa<LifetimeExtendedTemporaryDecl, UnnamedGlobalConstantDecl>(VD))) {
@@ -7432,24 +7430,30 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
<< Arg->getSourceRange();
return ExprError();
}
- // -- a subobject [until C++20]
- if (Value.hasLValuePath() && Value.getLValuePath().size() == 1 &&
- VD && VD->getType()->isArrayType() &&
+
+ if (Value.hasLValuePath() && Value.getLValuePath().size() == 1 && VD &&
+ VD->getType()->isArrayType() &&
Value.getLValuePath()[0].getAsArrayIndex() == 0 &&
!Value.isLValueOnePastTheEnd() && ParamType->isPointerType()) {
- // Per defect report (no number yet):
- // ... other than a pointer to the first element of a complete array
- // object.
- } else if (!Value.hasLValuePath() || Value.getLValuePath().size() ||
- Value.isLValueOnePastTheEnd()) {
- Diag(StartLoc, diag::err_non_type_template_arg_subobject)
- << Value.getAsString(Context, ParamType);
- return ExprError();
+ SugaredConverted = TemplateArgument(VD, ParamType);
+ CanonicalConverted = TemplateArgument(
+ cast<ValueDecl>(VD->getCanonicalDecl()), CanonParamType);
+ return ArgResult.get();
+ }
+
+ // -- a subobject [until C++20]
+ if (!getLangOpts().CPlusPlus20) {
+ if (!Value.hasLValuePath() || Value.getLValuePath().size() ||
+ Value.isLValueOnePastTheEnd()) {
+ Diag(StartLoc, diag::err_non_type_template_arg_subobject)
+ << Value.getAsString(Context, ParamType);
+ return ExprError();
+ }
+ assert((VD || !ParamType->isReferenceType()) &&
+ "null reference should not be a constant expression");
+ assert((!VD || !ParamType->isNullPtrType()) &&
+ "non-null value of type nullptr_t?");
}
- assert((VD || !ParamType->isReferenceType()) &&
- "null reference should not be a constant expression");
- assert((!VD || !ParamType->isNullPtrType()) &&
- "non-null value of type nullptr_t?");
}
if (Value.isAddrLabelDiff())
diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index 9cb6c0a4ef24..92086d7277fd 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -8646,21 +8646,30 @@ static void HandleRISCVRVVVectorBitsTypeAttr(QualType &CurType,
ASTContext::BuiltinVectorTypeInfo Info =
S.Context.getBuiltinVectorTypeInfo(CurType->castAs<BuiltinType>());
- unsigned EltSize = S.Context.getTypeSize(Info.ElementType);
unsigned MinElts = Info.EC.getKnownMinValue();
+ VectorKind VecKind = VectorKind::RVVFixedLengthData;
+ unsigned ExpectedSize = VScale->first * MinElts;
+ QualType EltType = CurType->getRVVEltType(S.Context);
+ unsigned EltSize = S.Context.getTypeSize(EltType);
+ unsigned NumElts;
+ if (Info.ElementType == S.Context.BoolTy) {
+ NumElts = VecSize / S.Context.getCharWidth();
+ VecKind = VectorKind::RVVFixedLengthMask;
+ } else {
+ ExpectedSize *= EltSize;
+ NumElts = VecSize / EltSize;
+ }
+
// The attribute vector size must match -mrvv-vector-bits.
- unsigned ExpectedSize = VScale->first * MinElts * EltSize;
- if (VecSize != ExpectedSize) {
+ if (ExpectedSize % 8 != 0 || VecSize != ExpectedSize) {
S.Diag(Attr.getLoc(), diag::err_attribute_bad_rvv_vector_size)
<< VecSize << ExpectedSize;
Attr.setInvalid();
return;
}
- VectorKind VecKind = VectorKind::RVVFixedLengthData;
- VecSize /= EltSize;
- CurType = S.Context.getVectorType(Info.ElementType, VecSize, VecKind);
+ CurType = S.Context.getVectorType(EltType, NumElts, VecKind);
}
/// Handle OpenCL Access Qualifier Attribute.