Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Amend template specialization DXASSERT conditions #6617

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 43 additions & 39 deletions tools/clang/lib/Sema/SemaHLSL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -830,11 +830,10 @@ GetOrCreateTemplateSpecialization(ASTContext &context, Sema &sema,
if (specializationDecl->getInstantiatedFrom().isNull()) {
// InstantiateClassTemplateSpecialization returns true if it finds an
// error.
DXVERIFY_NOMSG(false ==
sema.InstantiateClassTemplateSpecialization(
NoLoc, specializationDecl,
TemplateSpecializationKind::TSK_ImplicitInstantiation,
true));
if (sema.InstantiateClassTemplateSpecialization(
NoLoc, specializationDecl,
TemplateSpecializationKind::TSK_ImplicitInstantiation, true))
return QualType();
}
return context.getTemplateSpecializationType(
TemplateName(templateDecl), templateArgs.data(), templateArgs.size(),
Expand All @@ -845,18 +844,20 @@ GetOrCreateTemplateSpecialization(ASTContext &context, Sema &sema,
context, TagDecl::TagKind::TTK_Class, currentDeclContext, NoLoc, NoLoc,
templateDecl, templateArgsForDecl.data(), templateArgsForDecl.size(),
nullptr);
// InstantiateClassTemplateSpecialization returns true if it finds an error.
DXVERIFY_NOMSG(false ==
sema.InstantiateClassTemplateSpecialization(
NoLoc, specializationDecl,
TemplateSpecializationKind::TSK_ImplicitInstantiation,
true));
// template specialization isn't performed if a fatal error has occurred
if (!sema.Diags.hasFatalErrorOccurred()) {
// InstantiateClassTemplateSpecialization returns true if it finds an error.
[[maybe_unused]] bool errorFound =
sema.InstantiateClassTemplateSpecialization(
NoLoc, specializationDecl,
TemplateSpecializationKind::TSK_ImplicitInstantiation, true);
assert(!errorFound && "template specialization failed");
}
templateDecl->AddSpecialization(specializationDecl, InsertPos);
specializationDecl->setImplicit(true);

QualType canonType = context.getTypeDeclType(specializationDecl);
DXASSERT(isa<RecordType>(canonType),
"type of non-dependent specialization is not a RecordType");
assert(isa<RecordType>(canonType) &&
"type of non-dependent specialization is not a RecordType");
TemplateArgumentListInfo templateArgumentList(NoLoc, NoLoc);
TemplateArgumentLocInfo NoTemplateArgumentLocInfo;
for (unsigned i = 0; i < templateArgs.size(); i++) {
Expand Down Expand Up @@ -891,16 +892,17 @@ static QualType GetOrCreateMatrixSpecialization(
context, *sema, matrixTemplateDecl,
ArrayRef<TemplateArgument>(templateArgs));

#ifndef NDEBUG
// Verify that we can read the field member from the template record.
DXASSERT(matrixSpecializationType->getAsCXXRecordDecl(),
if (!matrixSpecializationType.isNull() &&
!sema->Diags.hasFatalErrorOccurred()) {
assert(matrixSpecializationType->getAsCXXRecordDecl() &&
"type of non-dependent specialization is not a RecordType");
DeclContext::lookup_result lookupResult =
matrixSpecializationType->getAsCXXRecordDecl()->lookup(
DeclarationName(&context.Idents.get(StringRef("h"))));
DXASSERT(!lookupResult.empty(),
// Verify that we can read the field member from the template record.
[[maybe_unused]] DeclContext::lookup_result lookupResult =
matrixSpecializationType->getAsCXXRecordDecl()->lookup(
DeclarationName(&context.Idents.get(StringRef("h"))));
assert(!lookupResult.empty() &&
"otherwise matrix handle cannot be looked up");
#endif
}

return matrixSpecializationType;
}
Expand All @@ -926,16 +928,17 @@ GetOrCreateVectorSpecialization(ASTContext &context, Sema *sema,
context, *sema, vectorTemplateDecl,
ArrayRef<TemplateArgument>(templateArgs));

#ifndef NDEBUG
// Verify that we can read the field member from the template record.
DXASSERT(vectorSpecializationType->getAsCXXRecordDecl(),
if (!vectorSpecializationType.isNull() &&
!sema->Diags.hasFatalErrorOccurred()) {
assert(vectorSpecializationType->getAsCXXRecordDecl() &&
"type of non-dependent specialization is not a RecordType");
DeclContext::lookup_result lookupResult =
vectorSpecializationType->getAsCXXRecordDecl()->lookup(
DeclarationName(&context.Idents.get(StringRef("h"))));
DXASSERT(!lookupResult.empty(),
// Verify that we can read the field member from the template record.
[[maybe_unused]] DeclContext::lookup_result lookupResult =
vectorSpecializationType->getAsCXXRecordDecl()->lookup(
DeclarationName(&context.Idents.get(StringRef("h"))));
assert(!lookupResult.empty() &&
"otherwise vector handle cannot be looked up");
#endif
}

return vectorSpecializationType;
}
Expand All @@ -954,16 +957,16 @@ GetOrCreateNodeOutputRecordSpecialization(ASTContext &context, Sema *sema,
QualType specializationType = GetOrCreateTemplateSpecialization(
context, *sema, templateDecl, ArrayRef<TemplateArgument>(templateArgs));

#ifdef DBG
// Verify that we can read the field member from the template record.
DXASSERT(specializationType->getAsCXXRecordDecl(),
if (!specializationType.isNull() && !sema->Diags.hasFatalErrorOccurred()) {
assert(specializationType->getAsCXXRecordDecl() &&
"type of non-dependent specialization is not a RecordType");
DeclContext::lookup_result lookupResult =
specializationType->getAsCXXRecordDecl()->lookup(
DeclarationName(&context.Idents.get(StringRef("h"))));
DXASSERT(!lookupResult.empty(),
// Verify that we can read the field member from the template record.
[[maybe_unused]] DeclContext::lookup_result lookupResult =
specializationType->getAsCXXRecordDecl()->lookup(
DeclarationName(&context.Idents.get(StringRef("h"))));
assert(!lookupResult.empty() &&
"otherwise *NodeOutputRecords handle cannot be looked up");
#endif
}

return specializationType;
}
Expand Down Expand Up @@ -5097,12 +5100,13 @@ class HLSLExternalSource : public ExternalSemaSource {
// This is a bit of a special case we need to handle. Because the
// buffer types don't use their template parameter in a way that would
// force instantiation, we need to force specialization here.
GetOrCreateTemplateSpecialization(
QualType Ty = GetOrCreateTemplateSpecialization(
*m_context, *m_sema,
cast<ClassTemplateDecl>(
TST->getTemplateName().getAsTemplateDecl()),
llvm::ArrayRef<TemplateArgument>(TST->getArgs(),
TST->getNumArgs()));
return Ty.isNull();
}
if (const RecordType *recordType = argType->getAs<RecordType>()) {
if (!recordType->getDecl()->isCompleteDefinition()) {
Expand Down
22 changes: 22 additions & 0 deletions tools/clang/test/DXC/specialization_with_fatal_error.hlsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// RUN: %dxc -T lib_6_8 -verify %s

// Clang suppresses template specialization if a fatal error has been
// registered (this reduces the risk of a cascade of secondary errors).
// However, DXC asserted if a template specialization failed - which
// prevented the error diagnostic being generated.
// We check here that an assert is no longer raised if a fatal error
// has been registered, and that the error diagnostic is generated.

float a;

// the include file doesn't exist - this should produce a fatal error diagnostic
// expected-error@+1 {{'a.h' file not found}}
#include "a.h"

void b() {};

int3 c(int X) {
// an assert was triggered for the expression below when include file a.h
// doesn't exist, and the error diagnostic expected above was not produced.
return X.xxx;
}
Loading