implicit-exception-spec.cpp 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. // RUN: %clang_cc1 -fsyntax-only -fcxx-exceptions -verify -std=c++11 -Wall %s
  2. template<bool b> struct ExceptionIf { static int f(); };
  3. template<> struct ExceptionIf<false> { typedef int f; };
  4. // The exception specification of a defaulted default constructor depends on
  5. // the contents of in-class member initializers. However, the in-class member
  6. // initializers can depend on the exception specification of the constructor,
  7. // since the class is considered complete within them. We reject any such cases.
  8. namespace InClassInitializers {
  9. // Noexcept::Noexcept() is implicitly declared as noexcept(false), because it
  10. // directly invokes ThrowSomething(). However...
  11. //
  12. // If noexcept(Noexcept()) is false, then Noexcept() is a constant expression,
  13. // so noexcept(Noexcept()) is true. But if noexcept(Noexcept()) is true, then
  14. // Noexcept::Noexcept is not declared constexpr, therefore noexcept(Noexcept())
  15. // is false.
  16. bool ThrowSomething() noexcept(false);
  17. struct ConstExpr {
  18. bool b = noexcept(ConstExpr()) && ThrowSomething(); // expected-error {{exception specification is not available until end of class definition}}
  19. };
  20. // We can use it now.
  21. bool w = noexcept(ConstExpr());
  22. // Much more obviously broken: we can't parse the initializer without already
  23. // knowing whether it produces a noexcept expression.
  24. struct TemplateArg {
  25. int n = ExceptionIf<noexcept(TemplateArg())>::f(); // expected-error {{exception specification is not available until end of class definition}}
  26. };
  27. bool x = noexcept(TemplateArg());
  28. // And within a nested class.
  29. struct Nested {
  30. struct Inner {
  31. int n = ExceptionIf<noexcept(Nested())>::f(); // expected-error {{exception specification is not available until end of class definition}}
  32. } inner;
  33. };
  34. bool y = noexcept(Nested());
  35. bool z = noexcept(Nested::Inner());
  36. }
  37. // FIXME:
  38. // The same problem arises in delayed parsing of exception specifications,
  39. // which clang does not yet support.
  40. namespace ExceptionSpecification {
  41. struct Nested { // expected-note {{not complete}}
  42. struct T {
  43. T() noexcept(!noexcept(Nested())); // expected-error {{incomplete type}}
  44. } t;
  45. };
  46. }
  47. // FIXME:
  48. // The same problem arises in delayed parsing of default arguments,
  49. // which clang does not yet support.
  50. namespace DefaultArgument {
  51. struct Default { // expected-note {{defined here}}
  52. struct T {
  53. T(int = ExceptionIf<noexcept(Default())::f()); // expected-error {{call to implicitly-deleted default constructor}}
  54. } t;
  55. };
  56. }