diff options
author | Clement Courbet <courbet@google.com> | 2018-12-04 07:59:57 +0000 |
---|---|---|
committer | Clement Courbet <courbet@google.com> | 2018-12-04 07:59:57 +0000 |
commit | 9d432e0d1412bfdbea7a0d18295d63c7d30d3952 (patch) | |
tree | 8b0a68beb96ebdbc6efb5bf086a2cd9eac5c9727 /clang/lib/Sema/SemaTemplate.cpp | |
parent | 6ba64170efd231be0a747186b2a6152efddd0261 (diff) | |
download | bcm5719-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.cpp | 24 |
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 }; } |