From: Sebastian Redl Date: Sun, 16 Oct 2011 18:19:28 +0000 (+0000) Subject: Diagnose when omitting braces in direct list-initialization in C++0x. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=c223518ebf72e1709dc8938cd9384161ea5ec0bb;p=clang Diagnose when omitting braces in direct list-initialization in C++0x. This also applies to C99-style aggregate literals, should they be used in C++11, since they are effectively identical to constructor call list-initialization syntax. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@142147 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 1fb8fb8b97..2662a19691 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -2798,6 +2798,9 @@ def warn_anon_bitfield_width_exceeds_type_size : Warning< def warn_missing_braces : Warning< "suggest braces around initialization of subobject">, InGroup>, DefaultIgnore; +def err_missing_braces : Error< + "cannot omit braces around initialization of subobject when using direct " + "list-initialization">; def err_redefinition_of_label : Error<"redefinition of label %0">; def err_undeclared_label_use : Error<"use of undeclared label %0">; diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index cef4870638..c566b236e4 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -170,6 +170,7 @@ class InitListChecker { Sema &SemaRef; bool hadError; bool VerifyOnly; // no diagnostics, no structure building + bool AllowBraceElision; std::map SyntacticToSemantic; InitListExpr *FullyStructuredList; @@ -260,7 +261,8 @@ class InitListChecker { public: InitListChecker(Sema &S, const InitializedEntity &Entity, - InitListExpr *IL, QualType &T, bool VerifyOnly); + InitListExpr *IL, QualType &T, bool VerifyOnly, + bool AllowBraceElision); bool HadError() { return hadError; } // @brief Retrieves the fully-structured initializer list used for @@ -466,8 +468,8 @@ InitListChecker::FillInValueInitializations(const InitializedEntity &Entity, InitListChecker::InitListChecker(Sema &S, const InitializedEntity &Entity, InitListExpr *IL, QualType &T, - bool VerifyOnly) - : SemaRef(S), VerifyOnly(VerifyOnly) { + bool VerifyOnly, bool AllowBraceElision) + : SemaRef(S), VerifyOnly(VerifyOnly), AllowBraceElision(AllowBraceElision) { hadError = false; unsigned newIndex = 0; @@ -551,10 +553,14 @@ void InitListChecker::CheckImplicitInitList(const InitializedEntity &Entity, /*SubobjectIsDesignatorContext=*/false, Index, StructuredSubobjectInitList, StructuredSubobjectInitIndex); - unsigned EndIndex = (Index == StartIndex? StartIndex : Index - 1); - if (!VerifyOnly) { + + if (VerifyOnly) { + if (!AllowBraceElision && (T->isArrayType() || T->isRecordType())) + hadError = true; + } else { StructuredSubobjectInitList->setType(T); + unsigned EndIndex = (Index == StartIndex? StartIndex : Index - 1); // Update the structured sub-object initializer so that it's ending // range corresponds with the end of the last initializer it used. if (EndIndex < ParentIList->getNumInits()) { @@ -563,10 +569,11 @@ void InitListChecker::CheckImplicitInitList(const InitializedEntity &Entity, StructuredSubobjectInitList->setRBraceLoc(EndLoc); } - // Warn about missing braces. + // Complain about missing braces. if (T->isArrayType() || T->isRecordType()) { SemaRef.Diag(StructuredSubobjectInitList->getLocStart(), - diag::warn_missing_braces) + AllowBraceElision ? diag::warn_missing_braces : + diag::err_missing_braces) << StructuredSubobjectInitList->getSourceRange() << FixItHint::CreateInsertion( StructuredSubobjectInitList->getLocStart(), "{") @@ -574,6 +581,8 @@ void InitListChecker::CheckImplicitInitList(const InitializedEntity &Entity, SemaRef.PP.getLocForEndOfToken( StructuredSubobjectInitList->getLocEnd()), "}"); + if (!AllowBraceElision) + hadError = true; } } } @@ -2808,7 +2817,9 @@ static void TryListInitialization(Sema &S, } InitListChecker CheckInitList(S, Entity, InitList, - DestType, /*VerifyOnly=*/true); + DestType, /*VerifyOnly=*/true, + Kind.getKind() != InitializationKind::IK_Direct || + !S.getLangOptions().CPlusPlus0x); if (CheckInitList.HadError()) { Sequence.SetFailed(InitializationSequence::FK_ListInitializationFailed); return; @@ -4654,7 +4665,9 @@ InitializationSequence::Perform(Sema &S, InitListExpr *InitList = cast(CurInit.get()); QualType Ty = Step->Type; InitListChecker PerformInitList(S, Entity, InitList, - ResultType ? *ResultType : Ty, /*VerifyOnly=*/false); + ResultType ? *ResultType : Ty, /*VerifyOnly=*/false, + Kind.getKind() != InitializationKind::IK_Direct || + !S.getLangOptions().CPlusPlus0x); if (PerformInitList.HadError()) return ExprError(); @@ -5180,7 +5193,9 @@ bool InitializationSequence::Diagnose(Sema &S, InitListExpr* InitList = cast(Args[0]); QualType DestType = Entity.getType(); InitListChecker DiagnoseInitList(S, Entity, InitList, - DestType, /*VerifyOnly=*/false); + DestType, /*VerifyOnly=*/false, + Kind.getKind() != InitializationKind::IK_Direct || + !S.getLangOptions().CPlusPlus0x); assert(DiagnoseInitList.HadError() && "Inconsistent init list check result."); break; diff --git a/test/SemaCXX/cxx0x-initializer-aggregates.cpp b/test/SemaCXX/cxx0x-initializer-aggregates.cpp new file mode 100644 index 0000000000..687d27246c --- /dev/null +++ b/test/SemaCXX/cxx0x-initializer-aggregates.cpp @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s + +namespace aggregate { + // Direct list initialization does NOT allow braces to be elided! + struct S { + int ar[2]; + struct T { + int i1; + int i2; + } t; + struct U { + int i1; + } u[2]; + struct V { + int var[2]; + } v; + }; + + void test() { + S s1 = { 1, 2, 3 ,4, 5, 6, 7, 8 }; // no-error + S s2{ {1, 2}, {3, 4}, { {5}, {6} }, { {7, 8} } }; // completely braced + S s3{ 1, 2, 3, 4, 5, 6 }; // expected-error 5 {{cannot omit braces}} + S s4{ {1, 2}, {3, 4}, {5, 6}, { {7, 8} } }; // expected-error 2 {{cannot omit braces}} + S s5{ {1, 2}, {3, 4}, { {5}, {6} }, {7, 8} }; // expected-error {{cannot omit braces}} + } +} diff --git a/test/SemaCXX/generalized-initializers.cpp b/test/SemaCXX/generalized-initializers.cpp index a1891c9c32..9e11e267f1 100644 --- a/test/SemaCXX/generalized-initializers.cpp +++ b/test/SemaCXX/generalized-initializers.cpp @@ -40,16 +40,6 @@ namespace std { namespace integral { - int function_call() { - void takes_int(int); - takes_int({1}); - } - - void inline_init() { - (void) int{1}; - (void) new int{1}; - } - void initializer_list() { std::initializer_list il = { 1, 2, 3 }; std::initializer_list dl = { 1.0, 2.0, 3 }; @@ -180,28 +170,3 @@ namespace litb { B g({1, 2, 3}); } - -namespace aggregate { - // Direct list initialization does NOT allow braces to be elided! - struct S { - int ar[2]; - struct T { - int i1; - int i2; - } t; - struct U { - int i1; - } u[2]; - struct V { - int var[2]; - } v; - }; - - void test() { - S s1 = { 1, 2, 3 ,4, 5, 6, 7, 8 }; // no-error - S s2{ {1, 2}, {3, 4}, { {5}, {6} }, { {7, 8} } }; // completely braced - S s3{ 1, 2, 3, 4, 5, 6 }; // xpected-error - S s4{ {1, 2}, {3, 4}, {5, 6}, { {7, 8} } }; // xpected-error - S s5{ {1, 2}, {3, 4}, { {5}, {6} }, {7, 8} }; // xpected-error - } -}