@@ -2352,78 +2352,26 @@ static void handleUnusedAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
2352
2352
D->addAttr (::new (S.Context ) UnusedAttr (S.Context , AL));
2353
2353
}
2354
2354
2355
- static bool diagnoseInvalidPriority (Sema &S, uint32_t Priority,
2356
- const ParsedAttr &A,
2357
- SourceLocation PriorityLoc) {
2358
- constexpr uint32_t ReservedPriorityLower = 101 , ReservedPriorityUpper = 65535 ;
2359
-
2360
- // Only perform the priority check if the attribute is outside of a system
2361
- // header. Values <= 100 are reserved for the implementation, and libc++
2362
- // benefits from being able to specify values in that range. Values > 65535
2363
- // are reserved for historical reasons.
2364
- if ((Priority < ReservedPriorityLower || Priority > ReservedPriorityUpper) &&
2365
- !S.getSourceManager ().isInSystemHeader (A.getLoc ())) {
2366
- S.Diag (A.getLoc (), diag::err_attribute_argument_out_of_range)
2367
- << PriorityLoc << A << ReservedPriorityLower << ReservedPriorityUpper;
2368
- A.setInvalid ();
2369
- return true ;
2370
- }
2371
- return false ;
2372
- }
2373
-
2374
- template <typename CtorDtorAttr>
2375
- static void handleCtorDtorAttr (Sema &S, Decl *D, const ParsedAttr &AL) {
2376
- uint32_t Priority = CtorDtorAttr::DefaultPriority;
2355
+ static void handleConstructorAttr (Sema &S, Decl *D, const ParsedAttr &AL) {
2356
+ uint32_t priority = ConstructorAttr::DefaultPriority;
2377
2357
if (S.getLangOpts ().HLSL && AL.getNumArgs ()) {
2378
2358
S.Diag (AL.getLoc (), diag::err_hlsl_init_priority_unsupported);
2379
2359
return ;
2380
2360
}
2361
+ if (AL.getNumArgs () &&
2362
+ !checkUInt32Argument (S, AL, AL.getArgAsExpr (0 ), priority))
2363
+ return ;
2381
2364
2382
- // If we're given an argument for the priority, check that it's valid.
2383
- if (AL.getNumArgs ()) {
2384
- if (!checkUInt32Argument (S, AL, AL.getArgAsExpr (0 ), Priority))
2385
- return ;
2386
-
2387
- // Ensure the priority is in a reasonable range.
2388
- if (diagnoseInvalidPriority (S, Priority, AL,
2389
- AL.getArgAsExpr (0 )->getExprLoc ()))
2390
- return ;
2391
- }
2365
+ D->addAttr (::new (S.Context ) ConstructorAttr (S.Context , AL, priority));
2366
+ }
2392
2367
2393
- // Ensure the function we're attaching to is something that is sensible to
2394
- // automatically call before or after main(); it should accept no arguments.
2395
- // In theory, a void return type is the only truly safe return type (consider
2396
- // that calling conventions may place returned values in a hidden pointer
2397
- // argument passed to the function that will not be present when called
2398
- // automatically). However, there is a significant amount of existing code
2399
- // which uses an int return type. So we will accept void, int, and
2400
- // unsigned int return types. Any other return type, or a non-void parameter
2401
- // list is treated as an error because it's a form of type system
2402
- // incompatibility. The function also cannot be a member function. We allow
2403
- // K&R C functions because that's a difficult edge case where it depends on
2404
- // how the function is defined as to whether it does or does not expect
2405
- // arguments.
2406
- const auto *FD = cast<FunctionDecl>(D);
2407
- QualType RetTy = FD->getReturnType ();
2408
- if (!(RetTy->isVoidType () ||
2409
- RetTy->isSpecificBuiltinType (BuiltinType::UInt) ||
2410
- RetTy->isSpecificBuiltinType (BuiltinType::Int)) ||
2411
- (FD->hasPrototype () && FD->getNumParams () != 0 )) {
2412
- S.Diag (AL.getLoc (), diag::err_ctor_dtor_attr_on_non_void_func)
2413
- << AL << FD->getSourceRange ();
2368
+ static void handleDestructorAttr (Sema &S, Decl *D, const ParsedAttr &AL) {
2369
+ uint32_t priority = DestructorAttr::DefaultPriority;
2370
+ if (AL.getNumArgs () &&
2371
+ !checkUInt32Argument (S, AL, AL.getArgAsExpr (0 ), priority))
2414
2372
return ;
2415
- } else if (const auto *MD = dyn_cast<CXXMethodDecl>(FD);
2416
- MD && MD->isInstance ()) {
2417
- S.Diag (AL.getLoc (), diag::err_ctor_dtor_member_func)
2418
- << AL << FD->getSourceRange ();
2419
- return ;
2420
- } else if (FD->isConsteval ()) {
2421
- S.Diag (AL.getLoc (), diag::err_ctordtor_attr_consteval)
2422
- << AL << FD->getSourceRange ();
2423
- return ;
2424
- }
2425
2373
2426
- D->addAttr (CtorDtorAttr::Create (S.Context , Priority , AL));
2374
+ D->addAttr (:: new (S.Context ) DestructorAttr (S. Context , AL, priority ));
2427
2375
}
2428
2376
2429
2377
template <typename AttrTy>
@@ -3940,9 +3888,16 @@ static void handleInitPriorityAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
3940
3888
return ;
3941
3889
}
3942
3890
3943
- if (diagnoseInvalidPriority (S, prioritynum, AL, E->getExprLoc ()))
3891
+ // Only perform the priority check if the attribute is outside of a system
3892
+ // header. Values <= 100 are reserved for the implementation, and libc++
3893
+ // benefits from being able to specify values in that range.
3894
+ if ((prioritynum < 101 || prioritynum > 65535 ) &&
3895
+ !S.getSourceManager ().isInSystemHeader (AL.getLoc ())) {
3896
+ S.Diag (AL.getLoc (), diag::err_attribute_argument_out_of_range)
3897
+ << E->getSourceRange () << AL << 101 << 65535 ;
3898
+ AL.setInvalid ();
3944
3899
return ;
3945
-
3900
+ }
3946
3901
D->addAttr (::new (S.Context ) InitPriorityAttr (S.Context , AL, prioritynum));
3947
3902
}
3948
3903
@@ -8975,13 +8930,13 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL,
8975
8930
handlePassObjectSizeAttr (S, D, AL);
8976
8931
break ;
8977
8932
case ParsedAttr::AT_Constructor:
8978
- handleCtorDtorAttr<ConstructorAttr> (S, D, AL);
8933
+ handleConstructorAttr (S, D, AL);
8979
8934
break ;
8980
8935
case ParsedAttr::AT_Deprecated:
8981
8936
handleDeprecatedAttr (S, D, AL);
8982
8937
break ;
8983
8938
case ParsedAttr::AT_Destructor:
8984
- handleCtorDtorAttr<DestructorAttr> (S, D, AL);
8939
+ handleDestructorAttr (S, D, AL);
8985
8940
break ;
8986
8941
case ParsedAttr::AT_EnableIf:
8987
8942
handleEnableIfAttr (S, D, AL);
0 commit comments