Index: lib/Sema/SemaTemplate.cpp =================================================================== --- lib/Sema/SemaTemplate.cpp +++ lib/Sema/SemaTemplate.cpp @@ -3052,6 +3052,48 @@ return Cond; } +// Pretty prints std::is_same as 'U and V are the same types'. +static void +prettyPrintFailedIsSameCondition(llvm::raw_string_ostream &OS, + const RecordDecl *Decl, + const PrintingPolicy &PrintPolicy) { + const auto *const TmplDecl = dyn_cast(Decl); + assert(TmplDecl && + "std::is_same should be a ClassTemplateSpecializationDecl"); + const auto &Args = TmplDecl->getTemplateArgs(); + assert(Args.size() == 2 && "std::is_same should have 2 template parameters"); + Args.get(0).getAsType().print(OS, PrintPolicy); + OS << " and "; + Args.get(1).getAsType().print(OS, PrintPolicy); + OS << " are the same type"; +} + +// Print a diagnostic for the failing static_assert expression. Defaults to +// pretty-printing the expression. +static void +prettyPrintFailedBooleanCondition(llvm::raw_string_ostream &OS, + const Expr *const FailedCond, + const PrintingPolicy &PrintPolicy) { + if (const auto *const DR = dyn_cast(FailedCond)) { + const auto *const Var = dyn_cast(DR->getDecl()); + if (Var && Var->isStaticDataMember() && Var->getName() == "value") { + const NestedNameSpecifier *const Qualifier = Var->getQualifier(); + // This might be an std type trait. + const auto *const Record = Qualifier->getAsRecordDecl(); + const auto *const Parent = Qualifier->getPrefix(); + if (Parent && Parent->getPrefix() && + Parent->getPrefix()->getKind() == NestedNameSpecifier::Global && + Parent->getAsNamespace() && + Parent->getAsNamespace()->getName() == "std" && + Record->getName() == "is_same") { + prettyPrintFailedIsSameCondition(OS, Record, PrintPolicy); + return; + } + } + } + FailedCond->printPretty(OS, nullptr, PrintPolicy); +} + std::pair Sema::findFailedBooleanCondition(Expr *Cond, bool AllowTopLevelCond) { Cond = lookThroughRangesV3Condition(PP, Cond); @@ -3093,7 +3135,7 @@ std::string Description; { llvm::raw_string_ostream Out(Description); - FailedCond->printPretty(Out, nullptr, getPrintingPolicy()); + prettyPrintFailedBooleanCondition(Out, FailedCond, getPrintingPolicy()); } return { FailedCond, Description }; } Index: test/SemaCXX/static-assert.cpp =================================================================== --- test/SemaCXX/static-assert.cpp +++ test/SemaCXX/static-assert.cpp @@ -68,3 +68,27 @@ }; static_assert(first_trait::value && second_trait::value, "message"); // expected-error{{static_assert failed due to requirement 'second_trait::value' "message"}} + +namespace std { + +template +struct is_same { + static const bool value = false; +}; + +template +struct is_same { + static const bool value = true; +}; + +} // namespace std + +struct ExampleTypes { + using T = int; + using U = float; +}; + +template +class StaticAssertIsSame { + static_assert(std::is_same::value, "message"); // expected-error{{static_assert failed due to requirement 'int and float are the same type' "message"}} +};