summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema/SemaTemplate.cpp
diff options
context:
space:
mode:
authorClement Courbet <courbet@google.com>2018-12-04 07:59:57 +0000
committerClement Courbet <courbet@google.com>2018-12-04 07:59:57 +0000
commit9d432e0d1412bfdbea7a0d18295d63c7d30d3952 (patch)
tree8b0a68beb96ebdbc6efb5bf086a2cd9eac5c9727 /clang/lib/Sema/SemaTemplate.cpp
parent6ba64170efd231be0a747186b2a6152efddd0261 (diff)
downloadbcm5719-llvm-9d432e0d1412bfdbea7a0d18295d63c7d30d3952.tar.gz
bcm5719-llvm-9d432e0d1412bfdbea7a0d18295d63c7d30d3952.zip
[WIP][Sema] Improve static_assert diagnostics for type traits.
Summary: In our codebase, `static_assert(std::some_type_trait<Ts...>::value, "msg")` (where `some_type_trait` is an std type_trait and `Ts...` is the appropriate template parameters) account for 11.2% of the `static_assert`s. In these cases, the `Ts` are typically not spelled out explicitly, e.g. `static_assert(std::is_same<SomeT::TypeT, typename SomeDependentT::value_type>::value, "message");` The diagnostic when the assert fails is typically not very useful, e.g. `static_assert failed due to requirement 'std::is_same<SomeT::TypeT, typename SomeDependentT::value_type>::value' "message"` This change makes the diagnostic spell out the types explicitly , e.g. `static_assert failed due to requirement 'std::is_same<int, float>::value' "message"` See tests for more examples. After this is submitted, I intend to handle `static_assert(!std::some_type_trait<Ts...>::value, "msg")`, which is another 6.6% of static_asserts. Subscribers: cfe-commits Differential Revision: https://reviews.llvm.org/D54903 llvm-svn: 348239
Diffstat (limited to 'clang/lib/Sema/SemaTemplate.cpp')
-rw-r--r--clang/lib/Sema/SemaTemplate.cpp24
1 files changed, 23 insertions, 1 deletions
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index a4da62b6cb4..56302d62484 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -3052,6 +3052,28 @@ static Expr *lookThroughRangesV3Condition(Preprocessor &PP, Expr *Cond) {
return Cond;
}
+// 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 *FailedCond,
+ const PrintingPolicy &Policy) {
+ const auto *DR = dyn_cast<DeclRefExpr>(FailedCond);
+ 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<VarTemplateSpecializationDecl>(VD)) {
+ // This is a template variable, print the expanded template arguments.
+ printTemplateArgumentList(OS, IV->getTemplateArgs().asArray(), Policy);
+ }
+ return;
+ }
+ FailedCond->printPretty(OS, nullptr, Policy);
+}
+
std::pair<Expr *, std::string>
Sema::findFailedBooleanCondition(Expr *Cond, bool AllowTopLevelCond) {
Cond = lookThroughRangesV3Condition(PP, Cond);
@@ -3093,7 +3115,7 @@ Sema::findFailedBooleanCondition(Expr *Cond, bool AllowTopLevelCond) {
std::string Description;
{
llvm::raw_string_ostream Out(Description);
- FailedCond->printPretty(Out, nullptr, getPrintingPolicy());
+ prettyPrintFailedBooleanCondition(Out, FailedCond, getPrintingPolicy());
}
return { FailedCond, Description };
}
OpenPOWER on IntegriCloud