fhahn updated this revision to Diff 82626. https://reviews.llvm.org/D28148
Files: include/clang/Basic/LangOptions.def include/clang/Frontend/LangStandard.h include/clang/Frontend/LangStandards.def lib/Frontend/CompilerInvocation.cpp lib/Sema/SemaInit.cpp test/Sema/zero-initializer.c
Index: test/Sema/zero-initializer.c =================================================================== --- /dev/null +++ test/Sema/zero-initializer.c @@ -0,0 +1,31 @@ +// RUN: %clang_cc1 -std=c99 -Wmissing-field-initializers -Wmissing-braces + +struct foo { + /* */ + int x; + int y; +}; + +struct bar { + /* */ + struct foo a; + struct foo b; +}; + +int main(void) +{ + struct foo f = { 0 }; // expected-no-diagnostics + struct foo g = { 9 }; // expected-warning {{missing field 'y' initializer}} + struct foo h = { 9, 9 }; // expected-no-diagnostics + struct bar i = { 0 }; // expected-no-diagnostics + struct bar j = { 0, 0 }; // expected-warning {{suggest braces around initialization of suboject}} expected-warning {{missing field 'b' initializer}} + struct bar k = { { 9, 9 }, { 9, 9 } }; // expected-no-diagnostics + struct bar l = { { 9, 9 }, { 0 } }; // expected-no-diagnostics + struct bar m = { { 0 }, { 0 } }; // expected-no-diagnostics + struct bar n = { { 0 }, { 9, 9 } }; // expected-no-diagnostics + struct bar o = { { 9, 9 }, { 0 } }; // expected-no-diagnostics + struct bar p = { { 9 }, { 9, 9 } }; // expected-warning {{missing field 'y' initializer}} + + return f.x + g.x + h.x + i.a.x + j.a.x + k.a.x + l.a.x + m.a.x + n.a.x + + o.a.x + p.a.x; +} Index: lib/Sema/SemaInit.cpp =================================================================== --- lib/Sema/SemaInit.cpp +++ lib/Sema/SemaInit.cpp @@ -880,8 +880,19 @@ StructuredSubobjectInitList->setRBraceLoc(EndLoc); } + bool MissingBracesOkay = false; + + if (SemaRef.getLangOpts().ZeroInitializer && + StructuredSubobjectInitList->getNumInits() == 1) { + if (const IntegerLiteral *lit = dyn_cast<IntegerLiteral>(StructuredSubobjectInitList->getInit(0))) { + if (lit->getValue() == 0) { + MissingBracesOkay = true; + } + } + } + // Complain about missing braces. - if (T->isArrayType() || T->isRecordType()) { + if (!MissingBracesOkay && (T->isArrayType() || T->isRecordType())) { SemaRef.Diag(StructuredSubobjectInitList->getLocStart(), diag::warn_missing_braces) << StructuredSubobjectInitList->getSourceRange() @@ -1828,6 +1839,17 @@ RecordDecl *RD = DeclType->getAs<RecordType>()->getDecl(); RecordDecl::field_iterator FieldEnd = RD->field_end(); bool CheckForMissingFields = true; + + // Check if this is C's zero initializer { 0 } + if (SemaRef.getLangOpts().ZeroInitializer && + IList->getNumInits() == 1) { + if (const IntegerLiteral *lit = dyn_cast<IntegerLiteral>(IList->getInit(0))) { + if (lit->getValue() == 0) { + CheckForMissingFields = false; + } + } + } + while (Index < IList->getNumInits()) { Expr *Init = IList->getInit(Index); Index: lib/Frontend/CompilerInvocation.cpp =================================================================== --- lib/Frontend/CompilerInvocation.cpp +++ lib/Frontend/CompilerInvocation.cpp @@ -1599,6 +1599,7 @@ Opts.GNUInline = Std.isC89(); Opts.HexFloats = Std.hasHexFloats(); Opts.ImplicitInt = Std.hasImplicitInt(); + Opts.ZeroInitializer = Std.hasZeroInitializer(); // Set OpenCL Version. Opts.OpenCL = isOpenCL(LangStd) || IK == IK_OpenCL; Index: include/clang/Frontend/LangStandards.def =================================================================== --- include/clang/Frontend/LangStandards.def +++ include/clang/Frontend/LangStandards.def @@ -30,66 +30,66 @@ // C89-ish modes. LANGSTANDARD(c89, "c89", "ISO C 1990", - C89 | ImplicitInt) + C89 | ImplicitInt | ZeroInitializer) LANGSTANDARD(c90, "c90", "ISO C 1990", - C89 | ImplicitInt) + C89 | ImplicitInt | ZeroInitializer) LANGSTANDARD(iso9899_1990, "iso9899:1990", "ISO C 1990", - C89 | ImplicitInt) + C89 | ImplicitInt | ZeroInitializer) LANGSTANDARD(c94, "iso9899:199409", "ISO C 1990 with amendment 1", - C89 | Digraphs | ImplicitInt) + C89 | Digraphs | ImplicitInt | ZeroInitializer) LANGSTANDARD(gnu89, "gnu89", "ISO C 1990 with GNU extensions", - LineComment | C89 | Digraphs | GNUMode | ImplicitInt) + LineComment | C89 | Digraphs | GNUMode | ImplicitInt | ZeroInitializer) LANGSTANDARD(gnu90, "gnu90", "ISO C 1990 with GNU extensions", - LineComment | C89 | Digraphs | GNUMode | ImplicitInt) + LineComment | C89 | Digraphs | GNUMode | ImplicitInt | ZeroInitializer) // C99-ish modes LANGSTANDARD(c99, "c99", "ISO C 1999", - LineComment | C99 | Digraphs | HexFloat) + LineComment | C99 | Digraphs | HexFloat | ZeroInitializer) LANGSTANDARD(c9x, "c9x", "ISO C 1999", - LineComment | C99 | Digraphs | HexFloat) + LineComment | C99 | Digraphs | HexFloat | ZeroInitializer) LANGSTANDARD(iso9899_1999, "iso9899:1999", "ISO C 1999", - LineComment | C99 | Digraphs | HexFloat) + LineComment | C99 | Digraphs | HexFloat | ZeroInitializer) LANGSTANDARD(iso9899_199x, "iso9899:199x", "ISO C 1999", - LineComment | C99 | Digraphs | HexFloat) + LineComment | C99 | Digraphs | HexFloat | ZeroInitializer) LANGSTANDARD(gnu99, "gnu99", "ISO C 1999 with GNU extensions", - LineComment | C99 | Digraphs | GNUMode | HexFloat) + LineComment | C99 | Digraphs | GNUMode | HexFloat | ZeroInitializer) LANGSTANDARD(gnu9x, "gnu9x", "ISO C 1999 with GNU extensions", - LineComment | C99 | Digraphs | GNUMode | HexFloat) + LineComment | C99 | Digraphs | GNUMode | HexFloat | ZeroInitializer) // C11 modes LANGSTANDARD(c11, "c11", "ISO C 2011", - LineComment | C99 | C11 | Digraphs | HexFloat) + LineComment | C99 | C11 | Digraphs | HexFloat | ZeroInitializer) LANGSTANDARD(c1x, "c1x", "ISO C 2011", - LineComment | C99 | C11 | Digraphs | HexFloat) + LineComment | C99 | C11 | Digraphs | HexFloat | ZeroInitializer) LANGSTANDARD(iso9899_2011, "iso9899:2011", "ISO C 2011", - LineComment | C99 | C11 | Digraphs | HexFloat) + LineComment | C99 | C11 | Digraphs | HexFloat | ZeroInitializer) LANGSTANDARD(iso9899_201x, "iso9899:201x", "ISO C 2011", - LineComment | C99 | C11 | Digraphs | HexFloat) + LineComment | C99 | C11 | Digraphs | HexFloat | ZeroInitializer) LANGSTANDARD(gnu11, "gnu11", "ISO C 2011 with GNU extensions", - LineComment | C99 | C11 | Digraphs | GNUMode | HexFloat) + LineComment | C99 | C11 | Digraphs | GNUMode | HexFloat | ZeroInitializer) LANGSTANDARD(gnu1x, "gnu1x", "ISO C 2011 with GNU extensions", - LineComment | C99 | C11 | Digraphs | GNUMode | HexFloat) + LineComment | C99 | C11 | Digraphs | GNUMode | HexFloat | ZeroInitializer) // C++ modes LANGSTANDARD(cxx98, "c++98", Index: include/clang/Frontend/LangStandard.h =================================================================== --- include/clang/Frontend/LangStandard.h +++ include/clang/Frontend/LangStandard.h @@ -29,7 +29,8 @@ Digraphs = (1 << 8), GNUMode = (1 << 9), HexFloat = (1 << 10), - ImplicitInt = (1 << 11) + ImplicitInt = (1 << 11), + ZeroInitializer = (1 << 12) }; } @@ -91,6 +92,9 @@ /// hasImplicitInt - Language allows variables to be typed as int implicitly. bool hasImplicitInt() const { return Flags & frontend::ImplicitInt; } + /// hasZeroInitializer - Language considers { 0 } idiomatic. + bool hasZeroInitializer() const { return Flags & frontend::ZeroInitializer; } + static const LangStandard &getLangStandardForKind(Kind K); static const LangStandard *getLangStandardForName(StringRef Name); }; Index: include/clang/Basic/LangOptions.def =================================================================== --- include/clang/Basic/LangOptions.def +++ include/clang/Basic/LangOptions.def @@ -111,6 +111,7 @@ LANGOPT(GNUKeywords , 1, 1, "GNU keywords") BENIGN_LANGOPT(ImplicitInt, 1, !C99 && !CPlusPlus, "C89 implicit 'int'") LANGOPT(Digraphs , 1, 0, "digraphs") +LANGOPT(ZeroInitializer , 1, C99, "C's treatment of {0}") BENIGN_LANGOPT(HexFloats , 1, C99, "C99 hexadecimal float constants") LANGOPT(CXXOperatorNames , 1, 0, "C++ operator name keywords") LANGOPT(AppleKext , 1, 0, "Apple kext support")
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits