[clang] nolock/noalloc attributes (PR #84983)

via cfe-commits cfe-commits at lists.llvm.org
Mon Mar 18 06:51:24 PDT 2024


================
@@ -3922,6 +3922,42 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, NamedDecl *&OldD, Scope *S,
     return true;
   }
 
+  const auto OldFX = Old->getFunctionEffects();
+  const auto NewFX = New->getFunctionEffects();
+  if (OldFX != NewFX) {
+    const auto Diffs = FunctionEffectSet::differences(OldFX, NewFX);
+    for (const auto &Item : Diffs) {
+      const FunctionEffect *Effect = Item.first;
+      const bool Adding = Item.second;
+      if (Effect->diagnoseRedeclaration(Adding, *Old, OldFX, *New, NewFX)) {
+        Diag(New->getLocation(),
+             diag::warn_mismatched_func_effect_redeclaration)
+            << Effect->name();
+        Diag(Old->getLocation(), diag::note_previous_declaration);
+      }
+    }
+
+    const auto MergedFX = OldFX | NewFX;
+
+    // Having diagnosed any problems, prevent further errors by applying the
+    // merged set of effects to both declarations.
+    auto applyMergedFX = [&](FunctionDecl *FD) {
+      const auto *FPT = FD->getType()->getAs<FunctionProtoType>();
+      FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
+      EPI.FunctionEffects = MergedFX;
+      QualType ModQT = Context.getFunctionType(FD->getReturnType(),
+                                               FPT->getParamTypes(), EPI);
+
+      FD->setType(ModQT);
+    };
+
+    applyMergedFX(Old);
+    applyMergedFX(New);
+
+    OldQType = Old->getType();
----------------
Sirraide wrote:

@dougsonos So, update, I just talked to Aaron about this, and generally speaking, it’s better to avoid modifying the `Old` declaration (even in cases where it wouldn’t change the behaviour of the program) as that may be a source of possible confusion for e.g. tools that are consuming the AST but don’t know about this.

I think I’ve mentioned this already, but an alternative that comes to mind would be to just look at all declarations of a function (starting at the most recent one, because that one will most likely have the attribute on it) and consider a function to be effectively `nolock`/`noalloc` if any of them are `nolock`/`noalloc`. Iirc, there was some code somewhere that is only checking the canonical decl, so that would have to be updated as a result.

https://github.com/llvm/llvm-project/pull/84983


More information about the cfe-commits mailing list