aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian Redl <sebastian.redl@getdesigned.at>2011-10-16 18:19:28 +0000
committerSebastian Redl <sebastian.redl@getdesigned.at>2011-10-16 18:19:28 +0000
commitc223518ebf72e1709dc8938cd9384161ea5ec0bb (patch)
treeb0cc8157bb5fc6a91382e44c611d414208f09524
parent3ff5c86d409a55d0e64a28c07197ee3e791166c2 (diff)
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
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td3
-rw-r--r--lib/Sema/SemaInit.cpp35
-rw-r--r--test/SemaCXX/cxx0x-initializer-aggregates.cpp26
-rw-r--r--test/SemaCXX/generalized-initializers.cpp35
4 files changed, 54 insertions, 45 deletions
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<DiagGroup<"missing-braces">>, 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<InitListExpr *, InitListExpr *> 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<InitListExpr>(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<InitListExpr>(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<int> il = { 1, 2, 3 };
std::initializer_list<double> 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
- }
-}