diff options
Diffstat (limited to 'clang')
-rw-r--r-- | clang/include/clang/Basic/DiagnosticSemaKinds.td | 2 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 16 | ||||
-rw-r--r-- | clang/test/Sema/c89.c | 4 |
3 files changed, 19 insertions, 3 deletions
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 1ca349920e8..8e88f3d0dd1 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -3626,6 +3626,8 @@ def warn_typecheck_zero_static_array_size : Warning< def err_array_size_non_int : Error<"size of array has non-integer type %0">; def err_init_element_not_constant : Error< "initializer element is not a compile-time constant">; +def ext_aggregate_init_not_constant : Extension< + "initializer for aggregate is not a compile-time constant">, InGroup<C99>; def err_local_cant_init : Error< "'__local' variable cannot have an initializer">; def err_block_extern_cant_init : Error< diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index aeae35aba97..840a735e1b5 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -7777,9 +7777,19 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, // C99 6.7.8p4: All the expressions in an initializer for an object that has // static storage duration shall be constant expressions or string literals. // C++ does not have this restriction. - if (!getLangOpts().CPlusPlus && !VDecl->isInvalidDecl() && - VDecl->getStorageClass() == SC_Static) - CheckForConstantInitializer(Init, DclT); + if (!getLangOpts().CPlusPlus && !VDecl->isInvalidDecl()) { + if (VDecl->getStorageClass() == SC_Static) + CheckForConstantInitializer(Init, DclT); + // C89 is stricter than C99 for non-static aggregate types. + // C89 6.5.7p3: All the expressions [...] in an initializer list + // for an object that has aggregate or union type shall be + // constant expressions. + else if (!getLangOpts().C99 && VDecl->getType()->isAggregateType() && + !Init->isConstantInitializer(Context, false)) + Diag(Init->getExprLoc(), + diag::ext_aggregate_init_not_constant) + << Init->getSourceRange(); + } } else if (VDecl->isStaticDataMember() && VDecl->getLexicalDeclContext()->isRecord()) { // This is an in-class initialization for a static data member, e.g., diff --git a/clang/test/Sema/c89.c b/clang/test/Sema/c89.c index a410a626eda..557acf6d62d 100644 --- a/clang/test/Sema/c89.c +++ b/clang/test/Sema/c89.c @@ -116,3 +116,7 @@ long long ll1 = /* expected-warning {{'long long' is an extension when C99 mode unsigned long long ull1 = /* expected-warning {{'long long' is an extension when C99 mode is not enabled}} */ 42ULL; /* expected-warning {{'long long' is an extension when C99 mode is not enabled}} */ +void test17(int v, int w) { + int a[2] = { v, w }; /* expected-warning {{initializer for aggregate is not a compile-time constant}} */ +} + |