Index: clang/include/clang/AST/PrettyPrinter.h =================================================================== --- clang/include/clang/AST/PrettyPrinter.h +++ clang/include/clang/AST/PrettyPrinter.h @@ -234,6 +234,20 @@ std::function remapPath; }; +/// A PrinterHelper that prints more helpful diagnostics for some +/// sub-expressions within failing boolean expression, such as substituting +/// template parameters for actual types. +class ExpandTemplateArgumentsPrinterHelper : public PrinterHelper { +public: + explicit ExpandTemplateArgumentsPrinterHelper(const PrintingPolicy &P) + : Policy(P) {} + + bool handledStmt(Stmt *E, raw_ostream &OS) override; + +private: + const PrintingPolicy Policy; +}; + } // end namespace clang #endif Index: clang/lib/AST/StmtPrinter.cpp =================================================================== --- clang/lib/AST/StmtPrinter.cpp +++ clang/lib/AST/StmtPrinter.cpp @@ -2472,3 +2472,26 @@ // Implement virtual destructor. PrinterHelper::~PrinterHelper() = default; + +//===----------------------------------------------------------------------===// +// ExpandTemplateArgumentsPrinterHelper +//===----------------------------------------------------------------------===// + +bool ExpandTemplateArgumentsPrinterHelper::handledStmt(Stmt *E, + raw_ostream &OS) { + const auto *DR = dyn_cast(E); + if (DR && DR->getQualifier()) { + // If this is a qualified name, expand the template arguments in nested + // qualifiers. + DR->getQualifier()->print(OS, Policy, true); + // Then print the decl itself. + const ValueDecl *VD = DR->getDecl(); + OS << VD->getName(); + if (const auto *IV = dyn_cast(VD)) { + // This is a template variable, print the expanded template arguments. + printTemplateArgumentList(OS, IV->getTemplateArgs().asArray(), Policy); + } + return true; + } + return false; +} \ No newline at end of file Index: clang/lib/Sema/SemaExceptionSpec.cpp =================================================================== --- clang/lib/Sema/SemaExceptionSpec.cpp +++ clang/lib/Sema/SemaExceptionSpec.cpp @@ -423,7 +423,11 @@ case EST_NoexceptTrue: OS << "noexcept("; assert(OldProto->getNoexceptExpr() != nullptr && "Expected non-null Expr"); - OldProto->getNoexceptExpr()->printPretty(OS, nullptr, getPrintingPolicy()); + { + PrintingPolicy Policy = getPrintingPolicy(); + ExpandTemplateArgumentsPrinterHelper Helper(Policy); + OldProto->getNoexceptExpr()->printPretty(OS, &Helper, Policy); + } OS << ")"; break; case EST_NoThrow: Index: clang/lib/Sema/SemaTemplate.cpp =================================================================== --- clang/lib/Sema/SemaTemplate.cpp +++ clang/lib/Sema/SemaTemplate.cpp @@ -3115,40 +3115,6 @@ return Cond; } -namespace { - -// A PrinterHelper that prints more helpful diagnostics for some sub-expressions -// within failing boolean expression, such as substituting template parameters -// for actual types. -class FailedBooleanConditionPrinterHelper : public PrinterHelper { -public: - explicit FailedBooleanConditionPrinterHelper(const PrintingPolicy &P) - : Policy(P) {} - - bool handledStmt(Stmt *E, raw_ostream &OS) override { - const auto *DR = dyn_cast(E); - if (DR && DR->getQualifier()) { - // If this is a qualified name, expand the template arguments in nested - // qualifiers. - DR->getQualifier()->print(OS, Policy, true); - // Then print the decl itself. - const ValueDecl *VD = DR->getDecl(); - OS << VD->getName(); - if (const auto *IV = dyn_cast(VD)) { - // This is a template variable, print the expanded template arguments. - printTemplateArgumentList(OS, IV->getTemplateArgs().asArray(), Policy); - } - return true; - } - return false; - } - -private: - const PrintingPolicy Policy; -}; - -} // end anonymous namespace - std::pair Sema::findFailedBooleanCondition(Expr *Cond) { Cond = lookThroughRangesV3Condition(PP, Cond); @@ -3187,7 +3153,7 @@ llvm::raw_string_ostream Out(Description); PrintingPolicy Policy = getPrintingPolicy(); Policy.PrintCanonicalTypes = true; - FailedBooleanConditionPrinterHelper Helper(Policy); + ExpandTemplateArgumentsPrinterHelper Helper(Policy); FailedCond->printPretty(Out, &Helper, Policy, 0, "\n", nullptr); } return { FailedCond, Description }; Index: clang/test/SemaCXX/exception-spec.cpp =================================================================== --- clang/test/SemaCXX/exception-spec.cpp +++ clang/test/SemaCXX/exception-spec.cpp @@ -52,3 +52,21 @@ D2 &operator=(const D2&); // expected-error {{more lax}} }; } + +namespace MissingOnTemplate { + template + struct type_dependant_noexcept { + static constexpr const bool value = (sizeof(T) < 4); + }; + + template void a_fct(T) noexcept(type_dependant_noexcept::value); // expected-note {{previous}} + template void a_fct(T); // expected-error {{missing exception specification 'noexcept(type_dependant_noexcept::value)'}} +} + +namespace abc { + struct A {}; +} // namespace abc + +namespace MissingOnTemplate { + template<>void a_fct(abc::A); // expected-error {{missing exception specification 'noexcept(type_dependant_noexcept::value)'}} expected-note {{previous}} +} \ No newline at end of file