@@ -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