diff --git a/tools/clang/lib/Sema/SemaHLSL.cpp b/tools/clang/lib/Sema/SemaHLSL.cpp index 6e58c0e872..16fbb9b5d9 100644 --- a/tools/clang/lib/Sema/SemaHLSL.cpp +++ b/tools/clang/lib/Sema/SemaHLSL.cpp @@ -850,11 +850,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(), @@ -865,18 +864,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(canonType), - "type of non-dependent specialization is not a RecordType"); + assert(isa(canonType) && + "type of non-dependent specialization is not a RecordType"); TemplateArgumentListInfo templateArgumentList(NoLoc, NoLoc); TemplateArgumentLocInfo NoTemplateArgumentLocInfo; for (unsigned i = 0; i < templateArgs.size(); i++) { @@ -911,16 +912,17 @@ static QualType GetOrCreateMatrixSpecialization( context, *sema, matrixTemplateDecl, ArrayRef(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; } @@ -946,16 +948,17 @@ GetOrCreateVectorSpecialization(ASTContext &context, Sema *sema, context, *sema, vectorTemplateDecl, ArrayRef(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; } @@ -974,16 +977,16 @@ GetOrCreateNodeOutputRecordSpecialization(ASTContext &context, Sema *sema, QualType specializationType = GetOrCreateTemplateSpecialization( context, *sema, templateDecl, ArrayRef(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; } diff --git a/tools/clang/test/DXC/specialization_with_fatal_error.hlsl b/tools/clang/test/DXC/specialization_with_fatal_error.hlsl new file mode 100644 index 0000000000..c5e20d9bb7 --- /dev/null +++ b/tools/clang/test/DXC/specialization_with_fatal_error.hlsl @@ -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; +}