diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2024-02-07 14:37:28 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2024-02-07 14:37:28 +0000 |
commit | 4fdf604ba667503ae582304cebdd3df426778a6b (patch) | |
tree | aae65a5d1b0a1b1acd9389fc36a0baf5fc1918c7 /clang/lib/Sema | |
parent | 2d835ae8657273e3aa8b9ef3201fb8df5563af9d (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.cpp | 55 | ||||
-rw-r--r-- | clang/lib/Sema/SemaConcept.cpp | 8 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 3 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 6 | ||||
-rw-r--r-- | clang/lib/Sema/SemaInit.cpp | 40 | ||||
-rw-r--r-- | clang/lib/Sema/SemaOverload.cpp | 82 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplate.cpp | 44 | ||||
-rw-r--r-- | clang/lib/Sema/SemaType.cpp | 21 |
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. |