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