@@ -2352,78 +2352,26 @@ static void handleUnusedAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
23522352 D->addAttr (::new (S.Context ) UnusedAttr (S.Context , AL));
23532353}
23542354
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;
23772357 if (S.getLangOpts ().HLSL && AL.getNumArgs ()) {
23782358 S.Diag (AL.getLoc (), diag::err_hlsl_init_priority_unsupported);
23792359 return ;
23802360 }
2361+ if (AL.getNumArgs () &&
2362+ !checkUInt32Argument (S, AL, AL.getArgAsExpr (0 ), priority))
2363+ return ;
23812364
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+ }
23922367
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))
24142372 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- }
24252373
2426- D->addAttr (CtorDtorAttr::Create (S.Context , Priority , AL));
2374+ D->addAttr (:: new (S.Context ) DestructorAttr (S. Context , AL, priority ));
24272375}
24282376
24292377template <typename AttrTy>
@@ -3940,9 +3888,16 @@ static void handleInitPriorityAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
39403888 return ;
39413889 }
39423890
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 ();
39443899 return ;
3945-
3900+ }
39463901 D->addAttr (::new (S.Context ) InitPriorityAttr (S.Context , AL, prioritynum));
39473902}
39483903
@@ -8975,13 +8930,13 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL,
89758930 handlePassObjectSizeAttr (S, D, AL);
89768931 break ;
89778932 case ParsedAttr::AT_Constructor:
8978- handleCtorDtorAttr<ConstructorAttr> (S, D, AL);
8933+ handleConstructorAttr (S, D, AL);
89798934 break ;
89808935 case ParsedAttr::AT_Deprecated:
89818936 handleDeprecatedAttr (S, D, AL);
89828937 break ;
89838938 case ParsedAttr::AT_Destructor:
8984- handleCtorDtorAttr<DestructorAttr> (S, D, AL);
8939+ handleDestructorAttr (S, D, AL);
89858940 break ;
89868941 case ParsedAttr::AT_EnableIf:
89878942 handleEnableIfAttr (S, D, AL);
0 commit comments