[PATCH] D54903: [Sema] Improve static_assert diagnostics.
Clement Courbet via Phabricator via cfe-commits
cfe-commits at lists.llvm.org
Mon Dec 3 07:00:49 PST 2018
courbet marked an inline comment as done.
courbet added inline comments.
================
Comment at: lib/Sema/SemaTemplate.cpp:3055
+// Print a diagnostic for the failing static_assert expression. Defaults to
+// pretty-printing the expression.
----------------
aaron.ballman wrote:
> courbet wrote:
> > aaron.ballman wrote:
> > > Comment is a bit out of date as this is no longer specific to `static_assert`.
> > >
> > > It looks like this may also change the behavior of enable_if diagnostic reporting. Do you need to update any of those tests from this change? If not, can you devise some tests for that case as well to show that this isn't just a static_assert behavior? (Do a search for `findFailedBooleanCondition` to find where the behavior has changed.)
> > Nope, unfortunately the code that calls this is actually untested...
> > I could not find a test that actually enters the:
> > ```
> > if (TypeAliasTemplateDecl *AliasTemplate =
> > dyn_cast<TypeAliasTemplateDecl>(Template))
> > ```
> > in `Sema::CheckTemplateIdType`.
> >
> > I stopped at the following insanity:
> >
> > ```
> > // RUN: %clang_cc1 -std=c++11 -verify %s
> >
> > template <typename T, typename U>
> > struct is_same {
> > enum { value = 0 };
> > };
> >
> > template <typename T> struct is_same<T, T> {
> > enum { value = 1 };
> > };
> >
> > struct Dispatch {
> > template <typename T> using SameAs = is_same<int, T>;
> > };
> >
> > template <typename DispatchT>
> > struct S {
> > template <typename T> using same = typename DispatchT::template SameAs<T>;
> >
> > template <typename T>
> > static void foo() __attribute__((enable_if(same<T>::value, "")));
> >
> > };
> >
> > void runFoo() {
> > // S<Dispatch>::foo<int>();
> > S<FailedDispatch>::foo<float>();
> >
> > }
> > ```
> >
> > This one exercises the code up to `if (CanonType.isNull()) {`, but I'm not sure how to get a null type here.
> >
> How about this:
> ```
> namespace boost {
> template<bool, typename = void> struct enable_if {};
> template<typename T> struct enable_if<true, T> { typedef T type; };
> }
>
> template<typename T> struct NonTemplateFunction {
> typename boost::enable_if<sizeof(T) == 4, int>::type f();
> };
>
> template <typename T>
> struct Bobble {
> using type = T;
> };
>
> struct Frobble {
> using type = char;
> };
> NonTemplateFunction<Bobble<typename Frobble::type>::type> NTFC;
> ```
> That should trigger the path in `Sema::CheckTypenameType()`, I believe.
This triggers:
```
else if (ClassTemplateDecl *ClassTemplate
= dyn_cast<ClassTemplateDecl>(Template))
```
Modifying it to:
```
namespace boost {
template<bool, typename = void> struct enable_if {};
template<typename T> struct enable_if<true, T> { typedef T type; };
}
template<typename T> struct NonTemplateFunction {
template <typename U> using toto = typename boost::enable_if<sizeof(U) == 4, int>::type;
toto<T> f();
};
template <typename T>
struct Bobble {
using type = T;
};
struct Frobble {
using type = char;
};
NonTemplateFunction<Bobble<typename Frobble::type>::type> NTFC;
```
triggers the same path as my previous example, but not the `IsNull()` test.
Repository:
rC Clang
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D54903/new/
https://reviews.llvm.org/D54903
More information about the cfe-commits
mailing list