@@ -2388,11 +2388,57 @@ static void handleCHERIMethodSuffix(Sema &S, Decl *D, const ParsedAttr &Attr) {
2388
2388
D->addAttr (::new (S.Context ) CHERIMethodSuffixAttr (S.Context , Attr, Str));
2389
2389
}
2390
2390
2391
- static void handleCHERICompartmentName (Sema &S, Decl *D, const ParsedAttr &Attr) {
2391
+ static void handleCHERICompartmentName (Sema &S, Decl *D, const ParsedAttr &Attr,
2392
+ Sema::DeclAttributeLocation DAL) {
2393
+ // cheri_compartment is both:
2394
+ //
2395
+ // * a Declaration attribute: marks the function as a compartment
2396
+ // entry point
2397
+ // * a Function Type attribute: affects the calling convention
2398
+ //
2399
+ // That's the reason why we don't short-circuit using hasDeclarator
2400
+ // (as other handlers do) as Sema::GetTypeForDeclarator only does
2401
+ // the Function Type part.
2402
+ //
2403
+ // BUT because it is a Function Type attribute, when the attribute
2404
+ // is initially attached to the DeclSpec, Sema::GetTypeForDeclarator
2405
+ // distributes it to the first DeclChunk which is a function. Thus,
2406
+ // the attribute is always be present at the DeclChunk level (but
2407
+ // not always at the DeclSpec level). In order to not possibly
2408
+ // process it twice, we always skip the DeclSpec level.
2409
+ //
2410
+ // **Attention**: The attribute is not always initially attached to
2411
+ // the DeclSpec especially when it follows a pointer:
2412
+ //
2413
+ // - cheri_compartment(...) void f(): attached to DeclSpec
2414
+ // - void * cheri_compartment(...) f(): attached to DeclChunk
2415
+ if (DAL == Sema::DAL_DeclSpec)
2416
+ return ;
2417
+
2392
2418
StringRef Str;
2393
2419
SourceLocation LiteralLoc;
2394
2420
if (!S.checkStringLiteralArgumentAttr (Attr, 0 , Str, &LiteralLoc))
2395
2421
return ;
2422
+
2423
+ // cheri_compartment is considered as function type attribute
2424
+
2425
+ const auto *FD = dyn_cast<FunctionDecl>(D);
2426
+
2427
+ if (FD && FD->getReturnType ()->isVoidType ()) {
2428
+ S.Diag (Attr.getLoc (), diag::warn_cheri_compartment_void_return_type);
2429
+
2430
+ if (SourceRange SR = FD->getReturnTypeSourceRange (); SR.isValid ()) {
2431
+ S.Diag (SR.getBegin (), diag::note_cheri_compartment_void_return_type)
2432
+ << FixItHint::CreateReplacement (SR, " int" );
2433
+ }
2434
+ } else {
2435
+ if (!S.Diags .isIgnored (diag::warn_cheri_compartment_void_return_type,
2436
+ LiteralLoc)) {
2437
+ D->addAttr (::new (S.Context ) WarnUnusedResultAttr (
2438
+ S.Context , Attr, " CHERI compartment call" ));
2439
+ }
2440
+ }
2441
+
2396
2442
D->addAttr (::new (S.Context ) CHERICompartmentNameAttr (S.Context , Attr, Str));
2397
2443
}
2398
2444
@@ -8932,7 +8978,8 @@ static bool MustDelayAttributeArguments(const ParsedAttr &AL) {
8932
8978
// / silently ignore it if a GNU attribute.
8933
8979
static void
8934
8980
ProcessDeclAttribute (Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL,
8935
- const Sema::ProcessDeclAttributeOptions &Options) {
8981
+ const Sema::ProcessDeclAttributeOptions &Options,
8982
+ Sema::DeclAttributeLocation DAL = Sema::DAL_Unspecified) {
8936
8983
if (AL.isInvalid () || AL.getKind () == ParsedAttr::IgnoredAttribute)
8937
8984
return ;
8938
8985
@@ -9441,7 +9488,7 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL,
9441
9488
handleCHERIMethodSuffix (S, D, AL);
9442
9489
break ;
9443
9490
case ParsedAttr::AT_CHERICompartmentName:
9444
- handleCHERICompartmentName (S, D, AL);
9491
+ handleCHERICompartmentName (S, D, AL, DAL );
9445
9492
break ;
9446
9493
case ParsedAttr::AT_InterruptState:
9447
9494
handleInterruptState (S, D, AL);
@@ -9755,12 +9802,13 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL,
9755
9802
// / attribute list to the specified decl, ignoring any type attributes.
9756
9803
void Sema::ProcessDeclAttributeList (
9757
9804
Scope *S, Decl *D, const ParsedAttributesView &AttrList,
9805
+ Sema::DeclAttributeLocation DAL,
9758
9806
const ProcessDeclAttributeOptions &Options) {
9759
9807
if (AttrList.empty ())
9760
9808
return ;
9761
9809
9762
9810
for (const ParsedAttr &AL : AttrList)
9763
- ProcessDeclAttribute (*this , S, D, AL, Options);
9811
+ ProcessDeclAttribute (*this , S, D, AL, Options, DAL );
9764
9812
9765
9813
// FIXME: We should be able to handle these cases in TableGen.
9766
9814
// GCC accepts
@@ -10011,6 +10059,7 @@ void Sema::ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD) {
10011
10059
// Apply decl attributes from the DeclSpec if present.
10012
10060
if (!PD.getDeclSpec ().getAttributes ().empty ()) {
10013
10061
ProcessDeclAttributeList (S, D, PD.getDeclSpec ().getAttributes (),
10062
+ DAL_DeclSpec,
10014
10063
ProcessDeclAttributeOptions ()
10015
10064
.WithIncludeCXX11Attributes (false )
10016
10065
.WithIgnoreTypeAttributes (true ));
@@ -10022,13 +10071,14 @@ void Sema::ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD) {
10022
10071
// when X is a decl attribute.
10023
10072
for (unsigned i = 0 , e = PD.getNumTypeObjects (); i != e; ++i) {
10024
10073
ProcessDeclAttributeList (S, D, PD.getTypeObject (i).getAttrs (),
10074
+ DAL_DeclChunk,
10025
10075
ProcessDeclAttributeOptions ()
10026
10076
.WithIncludeCXX11Attributes (false )
10027
10077
.WithIgnoreTypeAttributes (true ));
10028
10078
}
10029
10079
10030
10080
// Finally, apply any attributes on the decl itself.
10031
- ProcessDeclAttributeList (S, D, PD.getAttributes ());
10081
+ ProcessDeclAttributeList (S, D, PD.getAttributes (), DAL_Decl );
10032
10082
10033
10083
// Apply additional attributes specified by '#pragma clang attribute'.
10034
10084
AddPragmaAttributes (S, D);
0 commit comments