@@ -2914,32 +2914,93 @@ static void handleWeakImportAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
29142914 D->addAttr (::new (S.Context ) WeakImportAttr (S.Context , AL));
29152915}
29162916
2917+ // Checks whether an argument of launch_bounds-like attribute is
2918+ // acceptable, performs implicit conversion to Rvalue, and returns
2919+ // non-nullptr Expr result on success. Otherwise, it returns nullptr
2920+ // and may output an error.
2921+ template <class Attribute >
2922+ static Expr *makeAttributeArgExpr (Sema &S, Expr *E, const Attribute &Attr,
2923+ const unsigned Idx) {
2924+ if (S.DiagnoseUnexpandedParameterPack (E))
2925+ return nullptr ;
2926+
2927+ // Accept template arguments for now as they depend on something else.
2928+ // We'll get to check them when they eventually get instantiated.
2929+ if (E->isValueDependent ())
2930+ return E;
2931+
2932+ std::optional<llvm::APSInt> I = llvm::APSInt (64 );
2933+ if (!(I = E->getIntegerConstantExpr (S.Context ))) {
2934+ S.Diag (E->getExprLoc (), diag::err_attribute_argument_n_type)
2935+ << &Attr << Idx << AANT_ArgumentIntegerConstant << E->getSourceRange ();
2936+ return nullptr ;
2937+ }
2938+ // Make sure we can fit it in 32 bits.
2939+ if (!I->isIntN (32 )) {
2940+ S.Diag (E->getExprLoc (), diag::err_ice_too_large)
2941+ << toString (*I, 10 , false ) << 32 << /* Unsigned */ 1 ;
2942+ return nullptr ;
2943+ }
2944+ if (*I < 0 )
2945+ S.Diag (E->getExprLoc (), diag::err_attribute_requires_positive_integer)
2946+ << &Attr << /* non-negative*/ 1 << E->getSourceRange ();
2947+
2948+ // We may need to perform implicit conversion of the argument.
2949+ InitializedEntity Entity = InitializedEntity::InitializeParameter (
2950+ S.Context , S.Context .getConstType (S.Context .IntTy ), /* consume*/ false );
2951+ ExprResult ValArg = S.PerformCopyInitialization (Entity, SourceLocation (), E);
2952+ assert (!ValArg.isInvalid () &&
2953+ " Unexpected PerformCopyInitialization() failure." );
2954+
2955+ return ValArg.getAs <Expr>();
2956+ }
2957+
29172958// Handles reqd_work_group_size and work_group_size_hint.
29182959template <typename WorkGroupAttr>
29192960static void handleWorkGroupSize (Sema &S, Decl *D, const ParsedAttr &AL) {
2920- uint32_t WGSize[3 ];
2961+ Expr * WGSize[3 ];
29212962 for (unsigned i = 0 ; i < 3 ; ++i) {
2922- const Expr *E = AL.getArgAsExpr (i);
2923- if (!S. checkUInt32Argument (AL, E, WGSize[i], i,
2924- /* StrictlyUnsigned= */ true ))
2963+ if ( Expr *E = makeAttributeArgExpr (S, AL.getArgAsExpr (i), AL, i))
2964+ WGSize[i] = E;
2965+ else
29252966 return ;
29262967 }
29272968
2928- if (!llvm::all_of (WGSize, [](uint32_t Size) { return Size == 0 ; })) {
2969+ auto IsZero = [&](Expr *E) {
2970+ if (E->isValueDependent ())
2971+ return false ;
2972+ std::optional<llvm::APSInt> I = E->getIntegerConstantExpr (S.Context );
2973+ assert (I && " Non-integer constant expr" );
2974+ return I->isZero ();
2975+ };
2976+
2977+ if (!llvm::all_of (WGSize, IsZero)) {
29292978 for (unsigned i = 0 ; i < 3 ; ++i) {
29302979 const Expr *E = AL.getArgAsExpr (i);
2931- if (WGSize[i] == 0 ) {
2980+ if (IsZero ( WGSize[i]) ) {
29322981 S.Diag (AL.getLoc (), diag::err_attribute_argument_is_zero)
29332982 << AL << E->getSourceRange ();
29342983 return ;
29352984 }
29362985 }
29372986 }
29382987
2988+ auto Equal = [&](Expr *LHS, Expr *RHS) {
2989+ if (LHS->isValueDependent () || RHS->isValueDependent ())
2990+ return true ;
2991+ std::optional<llvm::APSInt> L = LHS->getIntegerConstantExpr (S.Context );
2992+ assert (L && " Non-integer constant expr" );
2993+ std::optional<llvm::APSInt> R = RHS->getIntegerConstantExpr (S.Context );
2994+ assert (L && " Non-integer constant expr" );
2995+ return L == R;
2996+ };
2997+
29392998 WorkGroupAttr *Existing = D->getAttr <WorkGroupAttr>();
2940- if (Existing && !(Existing->getXDim () == WGSize[0 ] &&
2941- Existing->getYDim () == WGSize[1 ] &&
2942- Existing->getZDim () == WGSize[2 ]))
2999+ if (Existing &&
3000+ !llvm::equal (std::initializer_list<Expr *>{Existing->getXDim (),
3001+ Existing->getYDim (),
3002+ Existing->getZDim ()},
3003+ WGSize, Equal))
29433004 S.Diag (AL.getLoc (), diag::warn_duplicate_attribute) << AL;
29443005
29453006 D->addAttr (::new (S.Context )
0 commit comments