[PATCH] D54903: [WIP][Sema] Improve static_assert diagnostics.
Clement Courbet via Phabricator via cfe-commits
cfe-commits at lists.llvm.org
Mon Nov 26 08:31:45 PST 2018
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 };
}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D54903.175274.patch
Type: text/x-patch
Size: 3510 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20181126/d86df4d2/attachment.bin>
More information about the cfe-commits
mailing list