courbet created this revision. Herald added a subscriber: cfe-commits. `static_assert(std::is_same<U, V>::value, "message")` now prints the value of U and V.
Repository: rC Clang https://reviews.llvm.org/D54903 Files: lib/Sema/SemaTemplate.cpp test/SemaCXX/static-assert.cpp Index: test/SemaCXX/static-assert.cpp =================================================================== --- test/SemaCXX/static-assert.cpp +++ test/SemaCXX/static-assert.cpp @@ -68,3 +68,27 @@ }; static_assert(first_trait<X>::value && second_trait<X>::value, "message"); // expected-error{{static_assert failed due to requirement 'second_trait<X>::value' "message"}} + +namespace std { + +template <typename T, typename U> +struct is_same { + static const bool value = false; +}; + +template <typename T> +struct is_same<T, T> { + static const bool value = true; +}; + +} // namespace std + +struct ExampleTypes { + using T = int; + using U = float; +}; + +template <typename T, typename U> +class StaticAssertIsSame { + static_assert(std::is_same<ExampleTypes::T, ExampleTypes::U>::value, "message"); // expected-error{{static_assert failed due to requirement 'int and float are the same type' "message"}} +}; Index: lib/Sema/SemaTemplate.cpp =================================================================== --- lib/Sema/SemaTemplate.cpp +++ lib/Sema/SemaTemplate.cpp @@ -3052,6 +3052,48 @@ return Cond; } +// Pretty prints std::is_same<U, V> 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<ClassTemplateSpecializationDecl>(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<DeclRefExpr>(FailedCond)) { + const auto *const Var = dyn_cast<VarDecl>(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<Expr *, std::string> 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<X>::value && second_trait<X>::value, "message"); // expected-error{{static_assert failed due to requirement 'second_trait<X>::value' "message"}} + +namespace std { + +template <typename T, typename U> +struct is_same { + static const bool value = false; +}; + +template <typename T> +struct is_same<T, T> { + static const bool value = true; +}; + +} // namespace std + +struct ExampleTypes { + using T = int; + using U = float; +}; + +template <typename T, typename U> +class StaticAssertIsSame { + static_assert(std::is_same<ExampleTypes::T, ExampleTypes::U>::value, "message"); // expected-error{{static_assert failed due to requirement 'int and float are the same type' "message"}} +}; Index: lib/Sema/SemaTemplate.cpp =================================================================== --- lib/Sema/SemaTemplate.cpp +++ lib/Sema/SemaTemplate.cpp @@ -3052,6 +3052,48 @@ return Cond; } +// Pretty prints std::is_same<U, V> 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<ClassTemplateSpecializationDecl>(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<DeclRefExpr>(FailedCond)) { + const auto *const Var = dyn_cast<VarDecl>(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<Expr *, std::string> 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 }; }
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits