================
@@ -1079,4 +1079,89 @@ bool DiagnoseUnguardedBuiltins::VisitCallExpr(CallExpr 
*CE) {
 void SemaAMDGPU::DiagnoseUnguardedBuiltinUsage(FunctionDecl *FD) {
   DiagnoseUnguardedBuiltins(SemaRef).IssueDiagnostics(FD->getBody());
 }
+
+static FieldDecl *getNamedBarrierField(const RecordDecl *R) {
+  for (FieldDecl *FD : R->fields()) {
+    QualType FDTy = FD->getType();
+    if (FDTy->isAMDGPUNamedBarrierTypeOrWrapper())
+      return FD;
+  }
+
+  return nullptr;
+}
+
+void SemaAMDGPU::checkNamedBarrierWrapper(RecordDecl *R) {
+  ASTContext &Context = getASTContext();
+  if (R->isInvalidDecl())
+    return;
+
+  if (!Context.getTargetInfo().hasAMDGPUTypes() &&
+      (!Context.getAuxTargetInfo() ||
+       !Context.getAuxTargetInfo()->hasAMDGPUTypes()))
+    return;
+
+  bool IsWrapper = false;
+  std::function<void()> DiagWrapperNote;
+
+  // First, check if this is a named barrier wrapper by virtue of the class
+  // declaring a named barrier field. This covers both C and C++.
+  if (FieldDecl *NamedBarrField = getNamedBarrierField(R)) {
+    // If this record contains a named barrier field, it must have only one
+    // field.
+    if (R->getNumFields() > 1) {
+      SemaRef.Diag(NamedBarrField->getLocation(),
+                   diag::err_amdgcn_invalid_field_not_a_wrapper)
+          << NamedBarrField->getType();
+      SemaRef.Diag(
+          R->getLocation(),
+          diag::note_amdgcn_not_a_named_barrier_wrapper_too_many_fields)
+          << R->getDeclName();
+      return;
+    }
+
+    IsWrapper = true;
+    DiagWrapperNote = [this, R, NamedBarrField]() {
+      SemaRef.Diag(NamedBarrField->getLocation(),
+                   diag::note_amdgcn_named_barrier_reason_field)
+          << R->getDeclName() << NamedBarrField->getDeclName();
+    };
+  }
+
+  // Then, for C++ classes, check if this is a named barrier wrapper by virtue
+  // of inheriting one.
+  const auto *CxxR = dyn_cast<CXXRecordDecl>(R);
+  if (CxxR && !IsWrapper) {
+    for (CXXBaseSpecifier BS : CxxR->bases()) {
+      const RecordDecl *Base = BS.getType()->getAsRecordDecl();
+      if (!Base || !Base->hasAttr<AMDGPUNamedBarrierWrapperAttr>())
+        continue;
+
+      IsWrapper = true;
+      DiagWrapperNote = [this, BS, R]() {
+        // Print using the CXXBaseSpecifier type as it includes the template
+        // parameters.
+        SemaRef.Diag(BS.getBeginLoc(),
+                     diag::note_amdgcn_named_barrier_reason_inherited)
+            << R->getDeclName() << BS.getType();
+      };
+    }
+  }
+
+  if (!IsWrapper)
+    return;
+
+  // Set the attribute even if the wrapper may be found to be invalid later.
+  R->addAttr(
+      AMDGPUNamedBarrierWrapperAttr::CreateImplicit(Context, SourceRange()));
----------------
Pierre-vh wrote:

You can only derive from complete types in C++, so if we get here, it means the 
base classes must have been type-checked, as Clang does type-checking and 
parsing at the same time.

I double checked it, once with my own understanding and once with Claude's, and 
it does appear to work that way.
If we check a derived class, it means the base is complete and `ActOnFields` 
was called on it.

https://github.com/llvm/llvm-project/pull/207687
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to