From: Chris Lattner Date: Sun, 10 Oct 2010 18:16:20 +0000 (+0000) Subject: fix PR8217, a silent miscompilation of invalid code. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=16c5dea6c2d3e4cf529de9d9b37f6a40441acb2c;p=clang fix PR8217, a silent miscompilation of invalid code. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@116166 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index e8600f4c9b..f49726d476 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -2876,12 +2876,12 @@ public: unsigned getNumInits() const { return InitExprs.size(); } - const Expr* getInit(unsigned Init) const { + const Expr *getInit(unsigned Init) const { assert(Init < getNumInits() && "Initializer access out of range!"); return cast_or_null(InitExprs[Init]); } - Expr* getInit(unsigned Init) { + Expr *getInit(unsigned Init) { assert(Init < getNumInits() && "Initializer access out of range!"); return cast_or_null(InitExprs[Init]); } diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 7eb5453fa8..770f837c2f 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -2152,6 +2152,8 @@ def err_member_def_does_not_match : Error< "out-of-line definition of %0 does not match any declaration in %1">; def err_nonstatic_member_out_of_line : Error< "non-static data member defined out-of-line">; +def err_nonstatic_flexible_variable : Error< + "non-static initialization of a variable with flexible array member">; def err_qualified_typedef_declarator : Error< "typedef declarator cannot be qualified">; def err_qualified_param_declarator : Error< diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 8efd49580f..424e6d19a4 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -1591,7 +1591,6 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) { /// no declarator (e.g. "struct foo;") is parsed. Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, DeclSpec &DS) { - // FIXME: Error on auto/register at file scope // FIXME: Error on inline/virtual/explicit // FIXME: Warn on useless __thread // FIXME: Warn on useless const/volatile @@ -2686,7 +2685,7 @@ static void SetNestedNameSpecifier(DeclaratorDecl *DD, Declarator &D) { } NamedDecl* -Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC, +Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, QualType R, TypeSourceInfo *TInfo, LookupResult &Previous, MultiTemplateParamsArg TemplateParamLists, @@ -2821,7 +2820,7 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC, ProcessDeclAttributes(S, NewVD, D); // Handle GNU asm-label extension (encoded as an attribute). - if (Expr *E = (Expr*) D.getAsmLabel()) { + if (Expr *E = (Expr*)D.getAsmLabel()) { // The parser guarantees this is a string. StringLiteral *SE = cast(E); NewVD->addAttr(::new (Context) AsmLabelAttr(SE->getStrTokenLoc(0), @@ -2991,7 +2990,7 @@ void Sema::CheckVariableDeclaration(VarDecl *NewVD, // This includes arrays of objects with address space qualifiers, but not // automatic variables that point to other address spaces. // ISO/IEC TR 18037 S5.1.2 - if (NewVD->hasLocalStorage() && (T.getAddressSpace() != 0)) { + if (NewVD->hasLocalStorage() && T.getAddressSpace() != 0) { Diag(NewVD->getLocation(), diag::err_as_qualified_auto_decl); return NewVD->setInvalidDecl(); } @@ -2999,7 +2998,7 @@ void Sema::CheckVariableDeclaration(VarDecl *NewVD, if (NewVD->hasLocalStorage() && T.isObjCGCWeak() && !NewVD->hasAttr()) Diag(NewVD->getLocation(), diag::warn_attribute_weak_on_local); - + bool isVM = T->isVariablyModifiedType(); if (isVM || NewVD->hasAttr() || NewVD->hasAttr()) @@ -4326,6 +4325,17 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) { Init->setType(DclT); } + + // If this variable is a local declaration with record type, make sure it + // doesn't have a flexible member initialization. We only support this as a + // global/static definition. + if (VDecl->hasLocalStorage()) + if (const RecordType *RT = VDecl->getType()->getAs()) + if (RT->getDecl()->hasFlexibleArrayMember() && isa(Init)) { + Diag(VDecl->getLocation(), diag::err_nonstatic_flexible_variable); + VDecl->setInvalidDecl(); + } + // Check any implicit conversions within the expression. CheckImplicitConversions(Init, VDecl->getLocation()); diff --git a/test/Sema/flexible-array-init.c b/test/Sema/flexible-array-init.c index e03881cdbc..a0f1acd071 100644 --- a/test/Sema/flexible-array-init.c +++ b/test/Sema/flexible-array-init.c @@ -7,7 +7,9 @@ struct one { struct one x2 = { 5, 1, 2, 3 }; // expected-warning{{flexible array initialization is a GNU extension}} void test() { - struct one x3 = {5, {1, 2, 3}}; // expected-warning{{flexible array initialization is a GNU extension}} + struct one x3 = {5, {1, 2, 3}}; // \ + // expected-warning{{flexible array initialization is a GNU extension}} \ + // expected-error {{non-static initialization of a variable with flexible array member}} } struct foo { @@ -56,3 +58,18 @@ struct Y { int e; struct X xs[]; // expected-warning{{'struct X' may not be used as an array element due to flexible array member}} }; + + +// PR8217 +struct PR8217a { + int i; + char v[]; +}; + +void PR8217() { + struct PR8217a foo1 = { .i = 0, .v = "foo" }; // expected-error {{non-static initialization of a variable with flexible array member}} + struct PR8217a foo2 = { .i = 0 }; // expected-error {{non-static initialization of a variable with flexible array member}} + struct PR8217a foo3 = { .i = 0, .v = { 'b', 'a', 'r', '\0' } }; // expected-error {{non-static initialization of a variable with flexible array member}} + struct PR8217a bar; +} + diff --git a/test/Sema/init.c b/test/Sema/init.c index 76f35303d7..f8110079d0 100644 --- a/test/Sema/init.c +++ b/test/Sema/init.c @@ -143,3 +143,4 @@ int PR4386_a = ((void *) PR4386_bar) != 0; int PR4386_b = ((void *) PR4386_foo) != 0; // expected-error{{initializer element is not a compile-time constant}} int PR4386_c = ((void *) PR4386_zed) != 0; int PR4386_zed() __attribute((weak)); +