Index: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td @@ -1780,6 +1780,8 @@ "remove the %select{'%1' if its condition|condition if it}0 " "is always %select{false|true}2">; def err_init_incomplete_type : Error<"initialization of incomplete type %0">; +def err_list_init_in_parens : Error<"list-initializer for non-class type %0 " + "must not be parenthesized">; def warn_unsequenced_mod_mod : Warning< "multiple unsequenced modifications to %0">, InGroup; Index: cfe/trunk/include/clang/Sema/Sema.h =================================================================== --- cfe/trunk/include/clang/Sema/Sema.h +++ cfe/trunk/include/clang/Sema/Sema.h @@ -1796,6 +1796,8 @@ bool TypeMayContainAuto); void ActOnUninitializedDecl(Decl *dcl, bool TypeMayContainAuto); void ActOnInitializerError(Decl *Dcl); + bool canInitializeWithParenthesizedList(QualType TargetType); + void ActOnPureSpecifier(Decl *D, SourceLocation PureSpecLoc); void ActOnCXXForRangeDecl(Decl *D); StmtResult ActOnCXXForRangeIdentifier(Scope *S, SourceLocation IdentLoc, Index: cfe/trunk/lib/Sema/SemaDecl.cpp =================================================================== --- cfe/trunk/lib/Sema/SemaDecl.cpp +++ cfe/trunk/lib/Sema/SemaDecl.cpp @@ -9865,6 +9865,18 @@ // Perform the initialization. ParenListExpr *CXXDirectInit = dyn_cast(Init); if (!VDecl->isInvalidDecl()) { + // Handle errors like: int a({0}) + if (CXXDirectInit && CXXDirectInit->getNumExprs() == 1 && + !canInitializeWithParenthesizedList(VDecl->getType())) + if (auto IList = dyn_cast(CXXDirectInit->getExpr(0))) { + Diag(VDecl->getLocation(), diag::err_list_init_in_parens) + << VDecl->getType() << CXXDirectInit->getSourceRange() + << FixItHint::CreateRemoval(CXXDirectInit->getLocStart()) + << FixItHint::CreateRemoval(CXXDirectInit->getLocEnd()); + Init = IList; + CXXDirectInit = nullptr; + } + InitializedEntity Entity = InitializedEntity::InitializeVariable(VDecl); InitializationKind Kind = DirectInit @@ -10171,6 +10183,18 @@ // though. } +/// Checks if an object of the given type can be initialized with parenthesized +/// init-list. +/// +/// \param TargetType Type of object being initialized. +/// +/// The function is used to detect wrong initializations, such as 'int({0})'. +/// +bool Sema::canInitializeWithParenthesizedList(QualType TargetType) { + return TargetType->isDependentType() || TargetType->isRecordType() || + TargetType->getContainedAutoType(); +} + void Sema::ActOnUninitializedDecl(Decl *RealDecl, bool TypeMayContainAuto) { // If there is no declaration, there was an error parsing it. Just ignore it. Index: cfe/trunk/lib/Sema/SemaExprCXX.cpp =================================================================== --- cfe/trunk/lib/Sema/SemaExprCXX.cpp +++ cfe/trunk/lib/Sema/SemaExprCXX.cpp @@ -1221,6 +1221,17 @@ if (!TInfo) TInfo = Context.getTrivialTypeSourceInfo(Ty, SourceLocation()); + // Handle errors like: int({0}) + if (exprs.size() == 1 && !canInitializeWithParenthesizedList(Ty) && + LParenLoc.isValid() && RParenLoc.isValid()) + if (auto IList = dyn_cast(exprs[0])) { + Diag(TInfo->getTypeLoc().getLocStart(), diag::err_list_init_in_parens) + << Ty << IList->getSourceRange() + << FixItHint::CreateRemoval(LParenLoc) + << FixItHint::CreateRemoval(RParenLoc); + LParenLoc = RParenLoc = SourceLocation(); + } + auto Result = BuildCXXTypeConstructExpr(TInfo, LParenLoc, exprs, RParenLoc); // Avoid creating a non-type-dependent expression that contains typos. // Non-type-dependent expressions are liable to be discarded without @@ -1562,8 +1573,20 @@ return ExprError(); SourceRange DirectInitRange; - if (ParenListExpr *List = dyn_cast_or_null(Initializer)) + if (ParenListExpr *List = dyn_cast_or_null(Initializer)) { DirectInitRange = List->getSourceRange(); + // Handle errors like: new int a({0}) + if (List->getNumExprs() == 1 && + !canInitializeWithParenthesizedList(AllocType)) + if (auto IList = dyn_cast(List->getExpr(0))) { + Diag(TInfo->getTypeLoc().getLocStart(), diag::err_list_init_in_parens) + << AllocType << List->getSourceRange() + << FixItHint::CreateRemoval(List->getLocStart()) + << FixItHint::CreateRemoval(List->getLocEnd()); + DirectInitRange = SourceRange(); + Initializer = IList; + } + } return BuildCXXNew(SourceRange(StartLoc, D.getLocEnd()), UseGlobal, PlacementLParen, Index: cfe/trunk/test/SemaCXX/cxx0x-initializer-references.cpp =================================================================== --- cfe/trunk/test/SemaCXX/cxx0x-initializer-references.cpp +++ cfe/trunk/test/SemaCXX/cxx0x-initializer-references.cpp @@ -72,10 +72,9 @@ } void edge_cases() { - // FIXME: very poor error message - int const &b({0}); // expected-error {{could not bind}} + int const &b({0}); // expected-error {{list-initializer for non-class type 'const int &' must not be parenthesized}} + const int (&arr)[3] ({1, 2, 3}); // expected-error {{list-initializer for non-class type 'const int (&)[3]' must not be parenthesized}} } - } namespace PR12182 { Index: cfe/trunk/test/SemaCXX/cxx0x-initializer-scalars.cpp =================================================================== --- cfe/trunk/test/SemaCXX/cxx0x-initializer-scalars.cpp +++ cfe/trunk/test/SemaCXX/cxx0x-initializer-scalars.cpp @@ -91,10 +91,23 @@ } void edge_cases() { - // FIXME: very poor error message - int a({0}); // expected-error {{cannot initialize}} - (void) int({0}); // expected-error {{functional-style cast}} - new int({0}); // expected-error {{cannot initialize}} + int a({0}); // expected-error {{list-initializer for non-class type 'int' must not be parenthesized}} + (void) int({0}); // expected-error {{list-initializer for non-class type 'int' must not be parenthesized}} + new int({0}); // expected-error {{list-initializer for non-class type 'int' must not be parenthesized}} + + int *b({0}); // expected-error {{list-initializer for non-class type 'int *' must not be parenthesized}} + typedef int *intptr; + int *c = intptr({0}); // expected-error {{list-initializer for non-class type 'intptr' (aka 'int *') must not be parenthesized}} + } + + template void dependent_edge_cases() { + T a({0}); + (void) T({0}); + new T({0}); + + T *b({0}); + typedef T *tptr; + T *c = tptr({0}); } void default_argument(int i = {}) {