Hi Richard, this seems to have an unwanted side-effect on -Wunused-value (test case attached). Could you take a look?
Cheers, Daniel On Fri, Mar 24, 2017 at 2:14 AM, Richard Smith via cfe-commits < cfe-commits@lists.llvm.org> wrote: > Author: rsmith > Date: Thu Mar 23 20:14:25 2017 > New Revision: 298676 > > URL: http://llvm.org/viewvc/llvm-project?rev=298676&view=rev > Log: > Fix handling of initialization from parenthesized initializer list. > > This change fixes a crash on initialization of a reference from ({}) during > template instantiation and incidentally improves diagnostics. > > This reverts a prior attempt to handle this in r286721. Instead, we teach > the > initialization code that initialization cannot be performed if a source > type > is required and the initializer is an initializer list (which is not an > expression and does not have a type), and likewise for function-style cast > expressions. > > Modified: > cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td > cfe/trunk/include/clang/Sema/Initialization.h > cfe/trunk/include/clang/Sema/Sema.h > cfe/trunk/lib/Sema/SemaDecl.cpp > cfe/trunk/lib/Sema/SemaExprCXX.cpp > cfe/trunk/lib/Sema/SemaInit.cpp > cfe/trunk/test/SemaCXX/cxx0x-initializer-constructor.cpp > cfe/trunk/test/SemaCXX/cxx0x-initializer-references.cpp > cfe/trunk/test/SemaCXX/cxx0x-initializer-scalars.cpp > cfe/trunk/test/SemaCXX/type-convert-construct.cpp > > Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/ > DiagnosticSemaKinds.td?rev=298676&r1=298675&r2=298676&view=diff > ============================================================ > ================== > --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original) > +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Thu Mar 23 > 20:14:25 2017 > @@ -1814,8 +1814,9 @@ def note_uninit_fixit_remove_cond : Note > "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 err_list_init_in_parens : Error< > + "cannot initialize %select{non-class|reference}0 type %1 with a " > + "parenthesized initializer list">; > > def warn_unsequenced_mod_mod : Warning< > "multiple unsequenced modifications to %0">, InGroup<Unsequenced>; > @@ -5865,8 +5866,8 @@ def err_builtin_func_cast_more_than_one_ > "function-style cast to a builtin type can only take one argument">; > def err_value_init_for_array_type : Error< > "array types cannot be value-initialized">; > -def err_value_init_for_function_type : Error< > - "function types cannot be value-initialized">; > +def err_init_for_function_type : Error< > + "cannot create object of function type %0">; > def warn_format_nonliteral_noargs : Warning< > "format string is not a string literal (potentially insecure)">, > InGroup<FormatSecurity>; > > Modified: cfe/trunk/include/clang/Sema/Initialization.h > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/ > clang/Sema/Initialization.h?rev=298676&r1=298675&r2=298676&view=diff > ============================================================ > ================== > --- cfe/trunk/include/clang/Sema/Initialization.h (original) > +++ cfe/trunk/include/clang/Sema/Initialization.h Thu Mar 23 20:14:25 2017 > @@ -822,6 +822,8 @@ public: > enum FailureKind { > /// \brief Too many initializers provided for a reference. > FK_TooManyInitsForReference, > + /// \brief Reference initialized from a parenthesized initializer > list. > + FK_ParenthesizedListInitForReference, > /// \brief Array must be initialized with an initializer list. > FK_ArrayNeedsInitList, > /// \brief Array must be initialized with an initializer list or a > @@ -866,6 +868,8 @@ public: > FK_ConversionFromPropertyFailed, > /// \brief Too many initializers for scalar > FK_TooManyInitsForScalar, > + /// \brief Scalar initialized from a parenthesized initializer list. > + FK_ParenthesizedListInitForScalar, > /// \brief Reference initialization from an initializer list > FK_ReferenceBindingToInitList, > /// \brief Initialization of some unused destination type with an > @@ -892,7 +896,7 @@ public: > /// having its address taken. > FK_AddressOfUnaddressableFunction, > /// \brief List-copy-initialization chose an explicit constructor. > - FK_ExplicitConstructor > + FK_ExplicitConstructor, > }; > > private: > > Modified: cfe/trunk/include/clang/Sema/Sema.h > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/ > clang/Sema/Sema.h?rev=298676&r1=298675&r2=298676&view=diff > ============================================================ > ================== > --- cfe/trunk/include/clang/Sema/Sema.h (original) > +++ cfe/trunk/include/clang/Sema/Sema.h Thu Mar 23 20:14:25 2017 > @@ -1822,7 +1822,6 @@ public: > void AddInitializerToDecl(Decl *dcl, Expr *init, bool DirectInit); > void ActOnUninitializedDecl(Decl *dcl); > void ActOnInitializerError(Decl *Dcl); > - bool canInitializeWithParenthesizedList(QualType TargetType); > > void ActOnPureSpecifier(Decl *D, SourceLocation PureSpecLoc); > void ActOnCXXForRangeDecl(Decl *D); > > Modified: cfe/trunk/lib/Sema/SemaDecl.cpp > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/ > SemaDecl.cpp?rev=298676&r1=298675&r2=298676&view=diff > ============================================================ > ================== > --- cfe/trunk/lib/Sema/SemaDecl.cpp (original) > +++ cfe/trunk/lib/Sema/SemaDecl.cpp Thu Mar 23 20:14:25 2017 > @@ -10102,18 +10102,6 @@ void Sema::AddInitializerToDecl(Decl *Re > // Perform the initialization. > ParenListExpr *CXXDirectInit = dyn_cast<ParenListExpr>(Init); > if (!VDecl->isInvalidDecl()) { > - // Handle errors like: int a({0}) > - if (CXXDirectInit && CXXDirectInit->getNumExprs() == 1 && > - !canInitializeWithParenthesizedList(VDecl->getType())) > - if (auto IList = dyn_cast<InitListExpr>(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 = InitializationKind::CreateForInit( > VDecl->getLocation(), DirectInit, Init); > @@ -10413,18 +10401,6 @@ void Sema::ActOnInitializerError(Decl *D > // 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) { > // If there is no declaration, there was an error parsing it. Just > ignore it. > if (!RealDecl) > > Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/ > SemaExprCXX.cpp?rev=298676&r1=298675&r2=298676&view=diff > ============================================================ > ================== > --- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original) > +++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Thu Mar 23 20:14:25 2017 > @@ -1228,17 +1228,6 @@ Sema::ActOnCXXTypeConstructExpr(ParsedTy > 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<InitListExpr>(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 > @@ -1295,46 +1284,51 @@ Sema::BuildCXXTypeConstructExpr(TypeSour > } > > // C++ [expr.type.conv]p1: > - // If the expression list is a single expression, the type conversion > - // expression is equivalent (in definedness, and if defined in meaning) > to the > - // corresponding cast expression. > - if (Exprs.size() == 1 && !ListInitialization) { > + // If the expression list is a parenthesized single expression, the type > + // conversion expression is equivalent (in definedness, and if defined > in > + // meaning) to the corresponding cast expression. > + if (Exprs.size() == 1 && !ListInitialization && > + !isa<InitListExpr>(Exprs[0])) { > Expr *Arg = Exprs[0]; > return BuildCXXFunctionalCastExpr(TInfo, Ty, LParenLoc, Arg, > RParenLoc); > } > > - // C++14 [expr.type.conv]p2: The expression T(), where T is a > - // simple-type-specifier or typename-specifier for a non-array > complete > - // object type or the (possibly cv-qualified) void type, creates a > prvalue > - // of the specified type, whose value is that produced by > value-initializing > - // an object of type T. > + // For an expression of the form T(), T shall not be an array type. > QualType ElemTy = Ty; > if (Ty->isArrayType()) { > if (!ListInitialization) > - return ExprError(Diag(TyBeginLoc, > - diag::err_value_init_for_array_type) << > FullRange); > + return ExprError(Diag(TyBeginLoc, diag::err_value_init_for_ > array_type) > + << FullRange); > ElemTy = Context.getBaseElementType(Ty); > } > > - if (!ListInitialization && Ty->isFunctionType()) > - return ExprError(Diag(TyBeginLoc, diag::err_value_init_for_ > function_type) > - << FullRange); > - > + // There doesn't seem to be an explicit rule against this but sanity > demands > + // we only construct objects with object types. > + if (Ty->isFunctionType()) > + return ExprError(Diag(TyBeginLoc, diag::err_init_for_function_type) > + << Ty << FullRange); > + > + // C++17 [expr.type.conv]p2: > + // If the type is cv void and the initializer is (), the expression > is a > + // prvalue of the specified type that performs no initialization. > if (!Ty->isVoidType() && > RequireCompleteType(TyBeginLoc, ElemTy, > diag::err_invalid_incomplete_type_use, > FullRange)) > return ExprError(); > > + // Otherwise, the expression is a prvalue of the specified type whose > + // result object is direct-initialized (11.6) with the initializer. > InitializationSequence InitSeq(*this, Entity, Kind, Exprs); > ExprResult Result = InitSeq.Perform(*this, Entity, Kind, Exprs); > > - if (Result.isInvalid() || !ListInitialization) > + if (Result.isInvalid()) > return Result; > > Expr *Inner = Result.get(); > if (CXXBindTemporaryExpr *BTE = dyn_cast_or_null< > CXXBindTemporaryExpr>(Inner)) > Inner = BTE->getSubExpr(); > - if (!isa<CXXTemporaryObjectExpr>(Inner)) { > + if (!isa<CXXTemporaryObjectExpr>(Inner) && > + !isa<CXXScalarValueInitExpr>(Inner)) { > // If we created a CXXTemporaryObjectExpr, that node also represents > the > // functional cast. Otherwise, create an explicit cast to represent > // the syntactic form of a functional-style cast that was used here. > @@ -1590,20 +1584,8 @@ Sema::ActOnCXXNew(SourceLocation StartLo > return ExprError(); > > SourceRange DirectInitRange; > - if (ParenListExpr *List = dyn_cast_or_null<ParenListExpr>(Initializer)) > { > + if (ParenListExpr *List = dyn_cast_or_null<ParenListExpr>(Initializer)) > DirectInitRange = List->getSourceRange(); > - // Handle errors like: new int a({0}) > - if (List->getNumExprs() == 1 && > - !canInitializeWithParenthesizedList(AllocType)) > - if (auto IList = dyn_cast<InitListExpr>(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, > > Modified: cfe/trunk/lib/Sema/SemaInit.cpp > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/ > SemaInit.cpp?rev=298676&r1=298675&r2=298676&view=diff > ============================================================ > ================== > --- cfe/trunk/lib/Sema/SemaInit.cpp (original) > +++ cfe/trunk/lib/Sema/SemaInit.cpp Thu Mar 23 20:14:25 2017 > @@ -3112,6 +3112,7 @@ bool InitializationSequence::isAmbiguous > > switch (getFailureKind()) { > case FK_TooManyInitsForReference: > + case FK_ParenthesizedListInitForReference: > case FK_ArrayNeedsInitList: > case FK_ArrayNeedsInitListOrStringLiteral: > case FK_ArrayNeedsInitListOrWideStringLiteral: > @@ -3129,6 +3130,7 @@ bool InitializationSequence::isAmbiguous > case FK_ConversionFailed: > case FK_ConversionFromPropertyFailed: > case FK_TooManyInitsForScalar: > + case FK_ParenthesizedListInitForScalar: > case FK_ReferenceBindingToInitList: > case FK_InitListBadDestinationType: > case FK_DefaultInitOfConst: > @@ -5179,6 +5181,12 @@ void InitializationSequence::InitializeF > // (Therefore, multiple arguments are not permitted.) > if (Args.size() != 1) > SetFailed(FK_TooManyInitsForReference); > + // C++17 [dcl.init.ref]p5: > + // A reference [...] is initialized by an expression [...] as > follows: > + // If the initializer is not an expression, presumably we should > reject, > + // but the standard fails to actually say so. > + else if (isa<InitListExpr>(Args[0])) > + SetFailed(FK_ParenthesizedListInitForReference); > else > TryReferenceInitialization(S, Entity, Kind, Args[0], *this); > return; > @@ -5344,11 +5352,16 @@ void InitializationSequence::InitializeF > return; > } > > + assert(Args.size() >= 1 && "Zero-argument case handled above"); > + > + // The remaining cases all need a source type. > if (Args.size() > 1) { > SetFailed(FK_TooManyInitsForScalar); > return; > + } else if (isa<InitListExpr>(Args[0])) { > + SetFailed(FK_ParenthesizedListInitForScalar); > + return; > } > - assert(Args.size() == 1 && "Zero-argument case handled above"); > > // - Otherwise, if the source type is a (possibly cv-qualified) class > // type, conversion functions are considered. > @@ -7389,6 +7402,10 @@ bool InitializationSequence::Diagnose(Se > S.Diag(Kind.getLocation(), diag::err_reference_has_multiple_inits) > << SourceRange(Args.front()->getLocStart(), > Args.back()->getLocEnd()); > break; > + case FK_ParenthesizedListInitForReference: > + S.Diag(Kind.getLocation(), diag::err_list_init_in_parens) > + << 1 << Entity.getType() << Args[0]->getSourceRange(); > + break; > > case FK_ArrayNeedsInitList: > S.Diag(Kind.getLocation(), diag::err_array_init_not_init_list) << 0; > @@ -7600,6 +7617,11 @@ bool InitializationSequence::Diagnose(Se > break; > } > > + case FK_ParenthesizedListInitForScalar: > + S.Diag(Kind.getLocation(), diag::err_list_init_in_parens) > + << 0 << Entity.getType() << Args[0]->getSourceRange(); > + break; > + > case FK_ReferenceBindingToInitList: > S.Diag(Kind.getLocation(), diag::err_reference_bind_init_list) > << DestType.getNonReferenceType() << Args[0]->getSourceRange(); > @@ -7782,6 +7804,10 @@ void InitializationSequence::dump(raw_os > OS << "too many initializers for reference"; > break; > > + case FK_ParenthesizedListInitForReference: > + OS << "parenthesized list init for reference"; > + break; > + > case FK_ArrayNeedsInitList: > OS << "array requires initializer list"; > break; > @@ -7866,6 +7892,10 @@ void InitializationSequence::dump(raw_os > OS << "too many initializers for scalar"; > break; > > + case FK_ParenthesizedListInitForScalar: > + OS << "parenthesized list init for reference"; > + break; > + > case FK_ReferenceBindingToInitList: > OS << "referencing binding to initializer list"; > break; > > Modified: cfe/trunk/test/SemaCXX/cxx0x-initializer-constructor.cpp > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/ > SemaCXX/cxx0x-initializer-constructor.cpp?rev=298676&r1= > 298675&r2=298676&view=diff > ============================================================ > ================== > --- cfe/trunk/test/SemaCXX/cxx0x-initializer-constructor.cpp (original) > +++ cfe/trunk/test/SemaCXX/cxx0x-initializer-constructor.cpp Thu Mar 23 > 20:14:25 2017 > @@ -173,8 +173,7 @@ namespace objects { > // invalid > H h1({1, 2}); // expected-error {{no matching constructor}} > (void) new H({1, 2}); // expected-error {{no matching constructor}} > - // FIXME: Bad diagnostic, mentions void type instead of init list. > - (void) H({1, 2}); // expected-error {{no matching conversion}} > + (void) H({1, 2}); // expected-error {{no matching constructor}} > > // valid (by copy constructor). > H h2({1, nullptr}); > > Modified: cfe/trunk/test/SemaCXX/cxx0x-initializer-references.cpp > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/ > SemaCXX/cxx0x-initializer-references.cpp?rev=298676&r1= > 298675&r2=298676&view=diff > ============================================================ > ================== > --- cfe/trunk/test/SemaCXX/cxx0x-initializer-references.cpp (original) > +++ cfe/trunk/test/SemaCXX/cxx0x-initializer-references.cpp Thu Mar 23 > 20:14:25 2017 > @@ -71,10 +71,22 @@ namespace reference { > static_assert(sizeof(h({1, 2})) == sizeof(two), "bad overload > resolution"); > } > > + struct X {}; > + > void edge_cases() { > - 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}} > + int const &b({0}); // expected-error {{cannot initialize reference > type 'const int &' with a parenthesized initializer list}} > + const int (&arr)[3] ({1, 2, 3}); // expected-error {{cannot > initialize reference type 'const int (&)[3]' with a parenthesized > initializer list}} > + const X &x({}); // expected-error {{cannot initialize reference type > 'const reference::X &' with a parenthesized initializer list}} > + } > + > + template<typename T> void dependent_edge_cases() { > + T b({}); // expected-error-re 3{{cannot initialize reference type > {{.*}} with a parenthesized init}} > + T({}); // expected-error-re 3{{cannot initialize reference type > {{.*}} with a parenthesized init}} > } > + template void dependent_edge_cases<X>(); // ok > + template void dependent_edge_cases<const int&>(); // expected-note > {{instantiation of}} > + template void dependent_edge_cases<const int(&)[1]>(); // expected-note > {{instantiation of}} > + template void dependent_edge_cases<const X&>(); // expected-note > {{instantiation of}} > } > > namespace PR12182 { > > Modified: cfe/trunk/test/SemaCXX/cxx0x-initializer-scalars.cpp > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/ > SemaCXX/cxx0x-initializer-scalars.cpp?rev=298676&r1= > 298675&r2=298676&view=diff > ============================================================ > ================== > --- cfe/trunk/test/SemaCXX/cxx0x-initializer-scalars.cpp (original) > +++ cfe/trunk/test/SemaCXX/cxx0x-initializer-scalars.cpp Thu Mar 23 > 20:14:25 2017 > @@ -91,13 +91,13 @@ namespace integral { > } > > void edge_cases() { > - 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 a({0}); // expected-error {{cannot initialize non-class type > 'int' with a parenthesized initializer list}} > + (void) int({0}); // expected-error {{cannot initialize non-class type > 'int' with a parenthesized initializer list}} > + new int({0}); // expected-error {{cannot initialize non-class type > 'int' with a parenthesized initializer list}} > > - int *b({0}); // expected-error {{list-initializer for non-class type > 'int *' must not be parenthesized}} > + int *b({0}); // expected-error {{cannot initialize non-class type > 'int *' with a parenthesized initializer list}} > typedef int *intptr; > - int *c = intptr({0}); // expected-error {{list-initializer for > non-class type 'intptr' (aka 'int *') must not be parenthesized}} > + int *c = intptr({0}); // expected-error {{cannot initialize > non-class type 'intptr' (aka 'int *') with a parenthesized initializer > list}} > } > > template<typename T> void dependent_edge_cases() { > > Modified: cfe/trunk/test/SemaCXX/type-convert-construct.cpp > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/ > SemaCXX/type-convert-construct.cpp?rev=298676&r1= > 298675&r2=298676&view=diff > ============================================================ > ================== > --- cfe/trunk/test/SemaCXX/type-convert-construct.cpp (original) > +++ cfe/trunk/test/SemaCXX/type-convert-construct.cpp Thu Mar 23 20:14:25 > 2017 > @@ -8,7 +8,15 @@ void f() { > typedef int arr[]; > int v3 = arr(); // expected-error {{array types cannot be > value-initialized}} > typedef void fn_ty(); > - fn_ty(); // expected-error {{function types cannot be > value-initialized}} > + fn_ty(); // expected-error {{cannot create object of function type > 'fn_ty'}} > + fn_ty(0); // expected-error {{functional-style cast from 'int' to > 'fn_ty'}} > + fn_ty(0, 0); // expected-error {{cannot create object of function type > 'fn_ty'}} > +#if __cplusplus >= 201103L > + fn_ty{}; // expected-error {{cannot create object of function type > 'fn_ty'}} > + fn_ty{0}; // expected-error {{cannot create object of function type > 'fn_ty'}} > + fn_ty{0, 0}; // expected-error {{cannot create object of function type > 'fn_ty'}} > + fn_ty({}); // expected-error {{cannot create object of function type > 'fn_ty'}} > +#endif > int v4 = int(); > int v5 = int; // expected-error {{expected '(' for function-style cast > or type construction}} > typedef int T; > > > _______________________________________________ > cfe-commits mailing list > cfe-commits@lists.llvm.org > http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits >
unused.patch
Description: Binary data
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits