@@ -2388,11 +2388,57 @@ static void handleCHERIMethodSuffix(Sema &S, Decl *D, const ParsedAttr &Attr) {
23882388 D->addAttr (::new (S.Context ) CHERIMethodSuffixAttr (S.Context , Attr, Str));
23892389}
23902390
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+
23922418 StringRef Str;
23932419 SourceLocation LiteralLoc;
23942420 if (!S.checkStringLiteralArgumentAttr (Attr, 0 , Str, &LiteralLoc))
23952421 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+
23962442 D->addAttr (::new (S.Context ) CHERICompartmentNameAttr (S.Context , Attr, Str));
23972443}
23982444
@@ -8932,7 +8978,8 @@ static bool MustDelayAttributeArguments(const ParsedAttr &AL) {
89328978// / silently ignore it if a GNU attribute.
89338979static void
89348980ProcessDeclAttribute (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) {
89368983 if (AL.isInvalid () || AL.getKind () == ParsedAttr::IgnoredAttribute)
89378984 return ;
89388985
@@ -9441,7 +9488,7 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL,
94419488 handleCHERIMethodSuffix (S, D, AL);
94429489 break ;
94439490 case ParsedAttr::AT_CHERICompartmentName:
9444- handleCHERICompartmentName (S, D, AL);
9491+ handleCHERICompartmentName (S, D, AL, DAL );
94459492 break ;
94469493 case ParsedAttr::AT_InterruptState:
94479494 handleInterruptState (S, D, AL);
@@ -9755,12 +9802,13 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL,
97559802// / attribute list to the specified decl, ignoring any type attributes.
97569803void Sema::ProcessDeclAttributeList (
97579804 Scope *S, Decl *D, const ParsedAttributesView &AttrList,
9805+ Sema::DeclAttributeLocation DAL,
97589806 const ProcessDeclAttributeOptions &Options) {
97599807 if (AttrList.empty ())
97609808 return ;
97619809
97629810 for (const ParsedAttr &AL : AttrList)
9763- ProcessDeclAttribute (*this , S, D, AL, Options);
9811+ ProcessDeclAttribute (*this , S, D, AL, Options, DAL );
97649812
97659813 // FIXME: We should be able to handle these cases in TableGen.
97669814 // GCC accepts
@@ -10011,6 +10059,7 @@ void Sema::ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD) {
1001110059 // Apply decl attributes from the DeclSpec if present.
1001210060 if (!PD.getDeclSpec ().getAttributes ().empty ()) {
1001310061 ProcessDeclAttributeList (S, D, PD.getDeclSpec ().getAttributes (),
10062+ DAL_DeclSpec,
1001410063 ProcessDeclAttributeOptions ()
1001510064 .WithIncludeCXX11Attributes (false )
1001610065 .WithIgnoreTypeAttributes (true ));
@@ -10022,13 +10071,14 @@ void Sema::ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD) {
1002210071 // when X is a decl attribute.
1002310072 for (unsigned i = 0 , e = PD.getNumTypeObjects (); i != e; ++i) {
1002410073 ProcessDeclAttributeList (S, D, PD.getTypeObject (i).getAttrs (),
10074+ DAL_DeclChunk,
1002510075 ProcessDeclAttributeOptions ()
1002610076 .WithIncludeCXX11Attributes (false )
1002710077 .WithIgnoreTypeAttributes (true ));
1002810078 }
1002910079
1003010080 // Finally, apply any attributes on the decl itself.
10031- ProcessDeclAttributeList (S, D, PD.getAttributes ());
10081+ ProcessDeclAttributeList (S, D, PD.getAttributes (), DAL_Decl );
1003210082
1003310083 // Apply additional attributes specified by '#pragma clang attribute'.
1003410084 AddPragmaAttributes (S, D);
0 commit comments