loladiro created this revision. loladiro added reviewers: EricWF, aaron.ballman, rsmith. loladiro added a subscriber: cfe-commits. loladiro set the repository for this revision to rL LLVM.
This hooks up the detailed diagnostics why constant initialization was not possible if require_constant_initialization reports an error. I have updated the test to account for the new notes. Everything works fine, except that in C++11 mode we get: ``` error: 'note' diagnostics expected but not seen: File /data/llvm/tools/clang/test/SemaCXX/attr-require-constant-initialization.cpp Line 229 (directive at /data/llvm/tools/clang/test/SemaCXX/attr-require-constant-initialization.cpp:231): non-constexpr constructor 'NonLit' cannot be used in a constant expression error: 'note' diagnostics seen but not expected: (frontend): non-literal type 'NonLit' cannot be used in a constant expression ``` This is because of an ImplicitValueInitExpr that gets passed into CheckLiteralType, but since ImplicitValueInitExpr doesn't have source information we get an invalid source location. I'm not really sure how to fix that (Is it possible to test for a note without source location?). Adding the proper source locations to ImplicitValueInitExpr seemed like a bigger undertaking than was warranted for this patch, so I'd appreciate guidance on how to proceed. Repository: rL LLVM https://reviews.llvm.org/D24371 Files: lib/Sema/SemaDecl.cpp test/SemaCXX/attr-require-constant-initialization.cpp
Index: test/SemaCXX/attr-require-constant-initialization.cpp =================================================================== --- test/SemaCXX/attr-require-constant-initialization.cpp +++ test/SemaCXX/attr-require-constant-initialization.cpp @@ -7,9 +7,9 @@ #define ATTR __attribute__((require_constant_initialization)) // expected-note 0+ {{expanded from macro}} -int ReturnInt(); +int ReturnInt(); // expected-note 0+ {{declared here}} -struct PODType { +struct PODType { // expected-note 0+ {{declared here}} int value; int value2; }; @@ -20,17 +20,17 @@ struct LitType { constexpr LitType() : value(0) {} constexpr LitType(int x) : value(x) {} - LitType(void *) : value(-1) {} + LitType(void *) : value(-1) {} // expected-note 0+ {{declared here}} int value; }; #endif -struct NonLit { +struct NonLit { // expected-note 0+ {{declared here}} #if __cplusplus >= 201402L constexpr NonLit() : value(0) {} constexpr NonLit(int x) : value(x) {} #else - NonLit() : value(0) {} + NonLit() : value(0) {} // expected-note 0+ {{declared here}} NonLit(int x) : value(x) {} #endif NonLit(void *) : value(-1) {} @@ -82,23 +82,44 @@ const int non_global = 42; ATTR static const int &local_init = non_global; // expected-error {{variable does not have a constant initializer}} // expected-note@-1 {{required by 'require_constant_initializer' attribute here}} +#if __cplusplus >= 201103L + // expected-note@-3 {{reference to 'non_global' is not a constant expression}} + // expected-note@-5 {{declared here}} +#else + // expected-note@-6 {{subexpression not valid in a constant expression}} +#endif ATTR static const int &global_init = glvalue_int; ATTR static const int &temp_init = 42; } ATTR const int &temp_ref = 42; ATTR const int &temp_ref2 = ReturnInt(); // expected-error {{variable does not have a constant initializer}} // expected-note@-1 {{required by 'require_constant_initializer' attribute here}} +#if __cplusplus >= 201103L +// expected-note@-3 {{non-constexpr function 'ReturnInt' cannot be used in a constant expression}} +#else +// expected-note@-5 {{subexpression not valid in a constant expression}} +#endif ATTR const NonLit &nl_temp_ref = 42; // expected-error {{variable does not have a constant initializer}} // expected-note@-1 {{required by 'require_constant_initializer' attribute here}} +#if __cplusplus >= 201103L +// expected-note@-3 {{non-literal type 'const NonLit' cannot be used in a constant expression}} +#else +// expected-note@-5 {{subexpression not valid in a constant expression}} +#endif #if __cplusplus >= 201103L ATTR const LitType &lit_temp_ref = 42; ATTR const int &subobj_ref = LitType{}.value; #endif ATTR const int &nl_subobj_ref = NonLit().value; // expected-error {{variable does not have a constant initializer}} // expected-note@-1 {{required by 'require_constant_initializer' attribute here}} +#if __cplusplus >= 201103L +// expected-note-re@-3 {{non-literal type '{{.*}}' cannot be used in a constant expression}} +#else +// expected-note@-5 {{subexpression not valid in a constant expression}} +#endif struct TT1 { ATTR static const int &no_init; @@ -116,6 +137,8 @@ #if __cplusplus >= 201103L thread_local const int &TT1::tl_glvalue_init = glvalue_int; thread_local const int &TT1::tl_temp_init = 42; // expected-error {{variable does not have a constant initializer}} +// expected-note@-1 {{reference to temporary is not a constant expression}} +// expected-note@-2 {{temporary created here}} #endif // [basic.start.static]p2.2 @@ -129,17 +152,21 @@ #else ATTR static PODType pod; // expected-error {{variable does not have a constant initializer}} // expected-note@-1 {{required by 'require_constant_initializer' attribute here}} +// expected-note@-2 {{non-constexpr constructor 'PODType' cannot be used in a constant expression}} #endif ATTR static PODType pot2 = {ReturnInt()}; // expected-error {{variable does not have a constant initializer}} - // expected-note@-1 {{required by 'require_constant_initializer' attribute here}} - + // expected-note@-1 {{required by 'require_constant_initializer' attribute here}} #if __cplusplus >= 201103L + // expected-note@-3 {{non-constexpr function 'ReturnInt' cannot be used in a constant expression}} + constexpr LitType l; ATTR static LitType static_lit = l; ATTR static LitType static_lit2 = (void *)0; // expected-error {{variable does not have a constant initializer}} // expected-note@-1 {{required by 'require_constant_initializer' attribute here}} + // expected-note@-2 {{non-constexpr constructor 'LitType' cannot be used in a constant expression}} ATTR static LitType static_lit3 = ReturnInt(); // expected-error {{variable does not have a constant initializer}} // expected-note@-1 {{required by 'require_constant_initializer' attribute here}} + // expected-note@-2 {{non-constexpr function 'ReturnInt' cannot be used in a constant expression}} ATTR thread_local LitType tls = 42; #endif } @@ -157,15 +184,21 @@ ATTR static const NonLit non_lit_copy_init; // expected-note {{required by 'require_constant_initializer' attribute here}} #endif }; -PODType TT2::pod_noinit; +PODType TT2::pod_noinit; // expected-note 0+ {{declared here}} #if __cplusplus >= 201103L // expected-error@-2 {{variable does not have a constant initializer}} +// expected-note@-3 {{non-constexpr constructor 'PODType' cannot be used in a constant expression}} #endif PODType TT2::pod_copy_init(TT2::pod_noinit); // expected-error {{variable does not have a constant initializer}} +#if __cplusplus >= 201103L +// expected-note@-2 {{read of non-constexpr variable 'pod_noinit' is not allowed in a constant expression}} +// expected-note@-3 {{in call to 'PODType(pod_noinit)'}} +#endif #if __cplusplus >= 201402L const NonLit TT2::non_lit(42); const NonLit TT2::non_lit_list_init = {42}; const NonLit TT2::non_lit_copy_init = 42; // expected-error {{variable does not have a constant initializer}} +// expected-note@-1 {{subexpression not valid in a constant expression}} #endif #if __cplusplus >= 201103L @@ -183,19 +216,25 @@ #else ATTR NonLit nl_ctor; // expected-error {{variable does not have a constant initializer}} // expected-note@-1 {{required by 'require_constant_initializer' attribute here}} +// expected-note@-2 {{non-constexpr constructor 'NonLit' cannot be used in a constant expression}} ATTR NonLit nl_ctor2{}; // expected-error {{variable does not have a constant initializer}} // expected-note@-1 {{required by 'require_constant_initializer' attribute here}} +// expected-note@-2 {{non-constexpr constructor 'NonLit' cannot be used in a constant expression}} ATTR NonLit nl_ctor3 = {}; // expected-error {{variable does not have a constant initializer}} // expected-note@-1 {{required by 'require_constant_initializer' attribute here}} +// expected-note@-2 {{non-constexpr constructor 'NonLit' cannot be used in a constant expression}} ATTR thread_local NonLit nl_ctor_tl = {}; // expected-error {{variable does not have a constant initializer}} // expected-note@-1 {{required by 'require_constant_initializer' attribute here}} +// expected-note@-2 {{non-constexpr constructor 'NonLit' cannot be used in a constant expression}} ATTR StoresNonLit snl; // expected-error {{variable does not have a constant initializer}} // expected-note@-1 {{required by 'require_constant_initializer' attribute here}} +// expected-note@-2 {{non-constexpr constructor 'NonLit' cannot be used in a constant expression}} #endif // Non-literal types cannot appear in the initializer of a non-literal type. ATTR int nl_in_init = NonLit{42}.value; // expected-error {{variable does not have a constant initializer}} // expected-note@-1 {{required by 'require_constant_initializer' attribute here}} +// expected-note@-2 {{subexpression not valid in a constant expression}} ATTR int lit_in_init = LitType{42}.value; #endif @@ -218,8 +257,9 @@ ATTR PODType pod_full_init = {1, 2}; ATTR PODType pod_non_constexpr_init = {1, ReturnInt()}; // expected-error {{variable does not have a constant initializer}} // expected-note@-1 {{required by 'require_constant_initializer' attribute here}} - #if __cplusplus >= 201103L +// expected-note@-3 {{non-constexpr function 'ReturnInt' cannot be used in a constant expression}} + ATTR int val_init{}; ATTR int brace_init = {}; #endif @@ -233,15 +273,17 @@ // initializer struct NotC { constexpr NotC(void *) {} - NotC(int) {} + NotC(int) {} // expected-note {{declared here}} }; template <class T> struct TestCtor { constexpr TestCtor(int x) : value(x) {} + // expected-note@-1 {{non-constexpr constructor 'NotC' cannot be used in a constant expression}} T value; }; ATTR TestCtor<NotC> t(42); // expected-error {{variable does not have a constant initializer}} // expected-note@-1 {{required by 'require_constant_initializer' attribute here}} +// expected-note@-2 {{in call to 'TestCtor(42)'}} #endif // Test various array types Index: lib/Sema/SemaDecl.cpp =================================================================== --- lib/Sema/SemaDecl.cpp +++ lib/Sema/SemaDecl.cpp @@ -10532,6 +10532,12 @@ << Init->getSourceRange(); Diag(attr->getLocation(), diag::note_declared_required_constant_init_here) << attr->getRange(); + APValue Value; + SmallVector<PartialDiagnosticAt, 8> Notes; + cast<Expr>(var->ensureEvaluatedStmt()->Value)->EvaluateAsInitializer( + Value, getASTContext(), var, Notes); + for (auto &it : Notes) + Diag(it.first, it.second); } } else if (!var->isConstexpr() && IsGlobal &&
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits