Index: cfe/trunk/include/clang/Basic/DiagnosticGroups.td =================================================================== --- cfe/trunk/include/clang/Basic/DiagnosticGroups.td +++ cfe/trunk/include/clang/Basic/DiagnosticGroups.td @@ -100,7 +100,6 @@ def GNUConditionalOmittedOperand : DiagGroup<"gnu-conditional-omitted-operand">; def ConfigMacros : DiagGroup<"config-macros">; def : DiagGroup<"ctor-dtor-privacy">; -def GNUDesignator : DiagGroup<"gnu-designator">; def GNUStringLiteralOperatorTemplate : DiagGroup<"gnu-string-literal-operator-template">; def UndefinedVarTemplate : DiagGroup<"undefined-var-template">; @@ -146,6 +145,12 @@ DeprecatedWritableStr]>, DiagCategory<"Deprecations">; +def CXX2aDesignator : DiagGroup<"c++20-designator">; +// Allow -Wno-c99-designator to be used to turn off all warnings on valid C99 +// designators (including the warning controlled by -Wc++20-designator). +def C99Designator : DiagGroup<"c99-designator", [CXX2aDesignator]>; +def GNUDesignator : DiagGroup<"gnu-designator">; + def DynamicExceptionSpec : DiagGroup<"dynamic-exception-spec", [DeprecatedDynamicExceptionSpec]>; @@ -896,7 +901,7 @@ // A warning group for warnings about using C++2a features as extensions in // earlier C++ versions. -def CXX2a : DiagGroup<"c++2a-extensions">; +def CXX2a : DiagGroup<"c++2a-extensions", [CXX2aDesignator]>; def : DiagGroup<"c++0x-extensions", [CXX11]>; def : DiagGroup<"c++1y-extensions", [CXX14]>; @@ -909,7 +914,7 @@ def C11 : DiagGroup<"c11-extensions">; // A warning group for warnings about using C99 features as extensions. -def C99 : DiagGroup<"c99-extensions">; +def C99 : DiagGroup<"c99-extensions", [C99Designator]>; // A warning group for warnings about GCC extensions. def GNU : DiagGroup<"gnu", [GNUAlignofExpression, GNUAnonymousStruct, Index: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td @@ -154,7 +154,7 @@ // C99 Designated Initializers def ext_designated_init : Extension< - "designated initializers are a C99 feature">, InGroup; + "designated initializers are a C99 feature">, InGroup; def err_array_designator_negative : Error< "array designator value '%0' is negative">; def err_array_designator_empty_range : Error< @@ -173,15 +173,17 @@ def note_field_designator_found : Note<"field designator refers here">; def err_designator_for_scalar_init : Error< "designator in initializer for scalar type %0">; -def warn_subobject_initializer_overrides : Warning< - "subobject initialization overrides initialization of other fields " - "within its enclosing subobject">, InGroup; def warn_initializer_overrides : Warning< - "initializer overrides prior initialization of this subobject">, - InGroup; + "initializer %select{partially |}0overrides prior initialization of " + "this subobject">, InGroup; +def ext_initializer_overrides : ExtWarn, + InGroup, SFINAEFailure; +def err_initializer_overrides_destructed : Error< + "initializer would partially override prior initialization of object of " + "type %1 with non-trivial destruction">; def note_previous_initializer : Note< "previous initialization %select{|with side effects }0is here" - "%select{| (side effects may not occur at run time)}0">; + "%select{| (side effects will not occur at run time)}0">; def err_designator_into_flexible_array_member : Error< "designator into flexible array member subobject">; def note_flexible_array_member : Note< @@ -189,6 +191,28 @@ def ext_flexible_array_init : Extension< "flexible array initialization is a GNU extension">, InGroup; +// C++20 designated initializers +def ext_cxx_designated_init : Extension< + "designated initializers are a C++20 extension">, InGroup; +def warn_cxx17_compat_designated_init : Warning< + "designated initializers are incompatible with C++ standards before C++20">, + InGroup, DefaultIgnore; +def ext_designated_init_mixed : ExtWarn< + "mixture of designated and non-designated initializers in the same " + "initializer list is a C99 extension">, InGroup; +def note_designated_init_mixed : Note< + "first non-designated initializer is here">; +def ext_designated_init_array : ExtWarn< + "array designators are a C99 extension">, InGroup; +def ext_designated_init_nested : ExtWarn< + "nested designators are a C99 extension">, InGroup; +def ext_designated_init_reordered : ExtWarn< + "ISO C++ requires field designators to be specified in declaration order; " + "field %1 will be initialized after field %0">, InGroup, + SFINAEFailure; +def note_previous_field_init : Note< + "previous initialization for field %0 is here">; + // Declarations. def ext_plain_complex : ExtWarn< "plain '_Complex' requires a type specifier; assuming '_Complex double'">; Index: cfe/trunk/include/clang/Sema/Sema.h =================================================================== --- cfe/trunk/include/clang/Sema/Sema.h +++ cfe/trunk/include/clang/Sema/Sema.h @@ -2775,6 +2775,9 @@ Expr *Value, bool AllowNRVO = true); + bool CanPerformAggregateInitializationForOverloadResolution( + const InitializedEntity &Entity, InitListExpr *From); + bool CanPerformCopyInitialization(const InitializedEntity &Entity, ExprResult Init); ExprResult PerformCopyInitialization(const InitializedEntity &Entity, @@ -4636,6 +4639,10 @@ MultiExprArg InitArgList, SourceLocation RBraceLoc); + ExprResult BuildInitList(SourceLocation LBraceLoc, + MultiExprArg InitArgList, + SourceLocation RBraceLoc); + ExprResult ActOnDesignatedInitializer(Designation &Desig, SourceLocation Loc, bool GNUSyntax, Index: cfe/trunk/lib/Sema/SemaExpr.cpp =================================================================== --- cfe/trunk/lib/Sema/SemaExpr.cpp +++ cfe/trunk/lib/Sema/SemaExpr.cpp @@ -6107,6 +6107,77 @@ ExprResult Sema::ActOnInitList(SourceLocation LBraceLoc, MultiExprArg InitArgList, SourceLocation RBraceLoc) { + // Only produce each kind of designated initialization diagnostic once. + SourceLocation FirstDesignator; + bool DiagnosedArrayDesignator = false; + bool DiagnosedNestedDesignator = false; + bool DiagnosedMixedDesignator = false; + + // Check that any designated initializers are syntactically valid in the + // current language mode. + for (unsigned I = 0, E = InitArgList.size(); I != E; ++I) { + if (auto *DIE = dyn_cast(InitArgList[I])) { + if (FirstDesignator.isInvalid()) + FirstDesignator = DIE->getBeginLoc(); + + if (!getLangOpts().CPlusPlus) + break; + + if (!DiagnosedNestedDesignator && DIE->size() > 1) { + DiagnosedNestedDesignator = true; + Diag(DIE->getBeginLoc(), diag::ext_designated_init_nested) + << DIE->getDesignatorsSourceRange(); + } + + for (auto &Desig : DIE->designators()) { + if (!Desig.isFieldDesignator() && !DiagnosedArrayDesignator) { + DiagnosedArrayDesignator = true; + Diag(Desig.getBeginLoc(), diag::ext_designated_init_array) + << Desig.getSourceRange(); + } + } + + if (!DiagnosedMixedDesignator && + !isa(InitArgList[0])) { + DiagnosedMixedDesignator = true; + Diag(DIE->getBeginLoc(), diag::ext_designated_init_mixed) + << DIE->getSourceRange(); + Diag(InitArgList[0]->getBeginLoc(), diag::note_designated_init_mixed) + << InitArgList[0]->getSourceRange(); + } + } else if (getLangOpts().CPlusPlus && !DiagnosedMixedDesignator && + isa(InitArgList[0])) { + DiagnosedMixedDesignator = true; + auto *DIE = cast(InitArgList[0]); + Diag(DIE->getBeginLoc(), diag::ext_designated_init_mixed) + << DIE->getSourceRange(); + Diag(InitArgList[I]->getBeginLoc(), diag::note_designated_init_mixed) + << InitArgList[I]->getSourceRange(); + } + } + + if (FirstDesignator.isValid()) { + // Only diagnose designated initiaization as a C++20 extension if we didn't + // already diagnose use of (non-C++20) C99 designator syntax. + if (getLangOpts().CPlusPlus && !DiagnosedArrayDesignator && + !DiagnosedNestedDesignator && !DiagnosedMixedDesignator) { + Diag(FirstDesignator, getLangOpts().CPlusPlus2a + ? diag::warn_cxx17_compat_designated_init + : diag::ext_cxx_designated_init); + } else if (!getLangOpts().CPlusPlus && !getLangOpts().C99) { + Diag(FirstDesignator, diag::ext_designated_init); + } + } + + return BuildInitList(LBraceLoc, InitArgList, RBraceLoc); +} + +ExprResult +Sema::BuildInitList(SourceLocation LBraceLoc, MultiExprArg InitArgList, + SourceLocation RBraceLoc) { + // Semantic analysis for initializers is done by ActOnDeclarator() and + // CheckInitializer() - it requires knowledge of the object being initialized. + // Immediately handle non-overload placeholders. Overloads can be // resolved contextually, but everything else here can't. for (unsigned I = 0, E = InitArgList.size(); I != E; ++I) { @@ -6121,9 +6192,6 @@ } } - // Semantic analysis for initializers is done by ActOnDeclarator() and - // CheckInitializer() - it requires knowledge of the object being initialized. - InitListExpr *E = new (Context) InitListExpr(Context, LBraceLoc, InitArgList, RBraceLoc); E->setType(Context.VoidTy); // FIXME: just a place holder for now. Index: cfe/trunk/lib/Sema/SemaInit.cpp =================================================================== --- cfe/trunk/lib/Sema/SemaInit.cpp +++ cfe/trunk/lib/Sema/SemaInit.cpp @@ -281,6 +281,7 @@ bool hadError = false; bool VerifyOnly; // No diagnostics. bool TreatUnavailableAsInvalid; // Used only in VerifyOnly mode. + bool InOverloadResolution; InitListExpr *FullyStructuredList = nullptr; NoInitExpr *DummyExpr = nullptr; @@ -372,6 +373,63 @@ ExprResult PerformEmptyInit(SourceLocation Loc, const InitializedEntity &Entity); + /// Diagnose that OldInit (or part thereof) has been overridden by NewInit. + void diagnoseInitOverride(Expr *OldInit, SourceRange NewInitRange, + bool FullyOverwritten = true) { + // Overriding an initializer via a designator is valid with C99 designated + // initializers, but ill-formed with C++20 designated initializers. + unsigned DiagID = SemaRef.getLangOpts().CPlusPlus + ? diag::ext_initializer_overrides + : diag::warn_initializer_overrides; + + if (InOverloadResolution && SemaRef.getLangOpts().CPlusPlus) { + // In overload resolution, we have to strictly enforce the rules, and so + // don't allow any overriding of prior initializers. This matters for a + // case such as: + // + // union U { int a, b; }; + // struct S { int a, b; }; + // void f(U), f(S); + // + // Here, f({.a = 1, .b = 2}) is required to call the struct overload. For + // consistency, we disallow all overriding of prior initializers in + // overload resolution, not only overriding of union members. + hadError = true; + } else if (OldInit->getType().isDestructedType() && !FullyOverwritten) { + // If we'll be keeping around the old initializer but overwriting part of + // the object it initialized, and that object is not trivially + // destructible, this can leak. Don't allow that, not even as an + // extension. + // + // FIXME: It might be reasonable to allow this in cases where the part of + // the initializer that we're overriding has trivial destruction. + DiagID = diag::err_initializer_overrides_destructed; + } else if (!OldInit->getSourceRange().isValid()) { + // We need to check on source range validity because the previous + // initializer does not have to be an explicit initializer. e.g., + // + // struct P { int a, b; }; + // struct PP { struct P p } l = { { .a = 2 }, .p.b = 3 }; + // + // There is an overwrite taking place because the first braced initializer + // list "{ .a = 2 }" already provides value for .p.b (which is zero). + // + // Such overwrites are harmless, so we don't diagnose them. (Note that in + // C++, this cannot be reached unless we've already seen and diagnosed a + // different conformance issue, such as a mixture of designated and + // non-designated initializers or a multi-level designator.) + return; + } + + if (!VerifyOnly) { + SemaRef.Diag(NewInitRange.getBegin(), DiagID) + << NewInitRange << FullyOverwritten << OldInit->getType(); + SemaRef.Diag(OldInit->getBeginLoc(), diag::note_previous_initializer) + << (OldInit->HasSideEffects(SemaRef.Context) && FullyOverwritten) + << OldInit->getSourceRange(); + } + } + // Explanation on the "FillWithNoInit" mode: // // Assume we have the following definitions (Case#1): @@ -410,9 +468,9 @@ SourceLocation Loc); public: - InitListChecker(Sema &S, const InitializedEntity &Entity, - InitListExpr *IL, QualType &T, bool VerifyOnly, - bool TreatUnavailableAsInvalid); + InitListChecker(Sema &S, const InitializedEntity &Entity, InitListExpr *IL, + QualType &T, bool VerifyOnly, bool TreatUnavailableAsInvalid, + bool InOverloadResolution = false); bool HadError() { return hadError; } // Retrieves the fully-structured initializer list used for @@ -877,9 +935,11 @@ InitListChecker::InitListChecker(Sema &S, const InitializedEntity &Entity, InitListExpr *IL, QualType &T, bool VerifyOnly, - bool TreatUnavailableAsInvalid) + bool TreatUnavailableAsInvalid, + bool InOverloadResolution) : SemaRef(S), VerifyOnly(VerifyOnly), - TreatUnavailableAsInvalid(TreatUnavailableAsInvalid) { + TreatUnavailableAsInvalid(TreatUnavailableAsInvalid), + InOverloadResolution(InOverloadResolution) { if (!VerifyOnly || hasAnyDesignatedInits(IL)) { FullyStructuredList = createInitListExpr(T, IL->getSourceRange(), IL->getNumInits()); @@ -1959,7 +2019,8 @@ } // If there's a default initializer, use it. - if (isa(RD) && cast(RD)->hasInClassInitializer()) { + if (isa(RD) && + cast(RD)->hasInClassInitializer()) { if (!StructuredList) return; for (RecordDecl::field_iterator FieldEnd = RD->field_end(); @@ -2276,7 +2337,9 @@ /// /// @param NextField If non-NULL and the first designator in @p DIE is /// a field, this will be set to the field declaration corresponding -/// to the field named by the designator. +/// to the field named by the designator. On input, this is expected to be +/// the next field that would be initialized in the absence of designation, +/// if the complete object being initialized is a struct. /// /// @param NextElementIndex If non-NULL and the first designator in @p /// DIE is an array designator or GNU array-range designator, this @@ -2344,53 +2407,41 @@ SourceRange(D->getBeginLoc(), DIE->getEndLoc())); else if (InitListExpr *Result = dyn_cast(ExistingInit)) StructuredList = Result; - else if (!VerifyOnly) { - if (DesignatedInitUpdateExpr *E = - dyn_cast(ExistingInit)) - StructuredList = E->getUpdater(); - else { - DesignatedInitUpdateExpr *DIUE = new (SemaRef.Context) - DesignatedInitUpdateExpr(SemaRef.Context, D->getBeginLoc(), - ExistingInit, DIE->getEndLoc()); - StructuredList->updateInit(SemaRef.Context, StructuredIndex, DIUE); - StructuredList = DIUE->getUpdater(); - } - - // We need to check on source range validity because the previous - // initializer does not have to be an explicit initializer. e.g., + else { + // We are creating an initializer list that initializes the + // subobjects of the current object, but there was already an + // initialization that completely initialized the current + // subobject, e.g., by a compound literal: // - // struct P { int a, b; }; - // struct PP { struct P p } l = { { .a = 2 }, .p.b = 3 }; + // struct X { int a, b; }; + // struct X xs[] = { [0] = (struct X) { 1, 2 }, [0].b = 3 }; // - // There is an overwrite taking place because the first braced initializer - // list "{ .a = 2 }" already provides value for .p.b (which is zero). - if (ExistingInit->getSourceRange().isValid()) { - // We are creating an initializer list that initializes the - // subobjects of the current object, but there was already an - // initialization that completely initialized the current - // subobject, e.g., by a compound literal: - // - // struct X { int a, b; }; - // struct X xs[] = { [0] = (struct X) { 1, 2 }, [0].b = 3 }; - // - // Here, xs[0].a == 1 and xs[0].b == 3, since the second, - // designated initializer re-initializes only its current object - // subobject [0].b. - SemaRef.Diag(D->getBeginLoc(), - diag::warn_subobject_initializer_overrides) - << SourceRange(D->getBeginLoc(), DIE->getEndLoc()); - - SemaRef.Diag(ExistingInit->getBeginLoc(), - diag::note_previous_initializer) - << /*FIXME:has side effects=*/0 << ExistingInit->getSourceRange(); + // Here, xs[0].a == 1 and xs[0].b == 3, since the second, + // designated initializer re-initializes only its current object + // subobject [0].b. + diagnoseInitOverride(ExistingInit, + SourceRange(D->getBeginLoc(), DIE->getEndLoc()), + /*FullyOverwritten=*/false); + + if (!VerifyOnly) { + if (DesignatedInitUpdateExpr *E = + dyn_cast(ExistingInit)) + StructuredList = E->getUpdater(); + else { + DesignatedInitUpdateExpr *DIUE = new (SemaRef.Context) + DesignatedInitUpdateExpr(SemaRef.Context, D->getBeginLoc(), + ExistingInit, DIE->getEndLoc()); + StructuredList->updateInit(SemaRef.Context, StructuredIndex, DIUE); + StructuredList = DIUE->getUpdater(); + } + } else { + // We don't need to track the structured representation of a + // designated init update of an already-fully-initialized object in + // verify-only mode. The only reason we would need the structure is + // to determine where the uninitialized "holes" are, and in this + // case, we know there aren't any and we can't introduce any. + StructuredList = nullptr; } - } else { - // We don't need to track the structured representation of a designated - // init update of an already-fully-initialized object in verify-only - // mode. The only reason we would need the structure is to determine - // where the uninitialized "holes" are, and in this case, we know there - // aren't any and we can't introduce any. - StructuredList = nullptr; } } } @@ -2475,10 +2526,11 @@ } } - unsigned FieldIndex = 0; - + unsigned NumBases = 0; if (auto *CXXRD = dyn_cast(RT->getDecl())) - FieldIndex = CXXRD->getNumBases(); + NumBases = CXXRD->getNumBases(); + + unsigned FieldIndex = NumBases; for (auto *FI : RT->getDecl()->fields()) { if (FI->isUnnamedBitfield()) @@ -2504,15 +2556,10 @@ && "A union should never have more than one initializer!"); Expr *ExistingInit = StructuredList->getInit(0); - if (ExistingInit && !VerifyOnly) { + if (ExistingInit) { // We're about to throw away an initializer, emit warning. - SemaRef.Diag(D->getFieldLoc(), - diag::warn_initializer_overrides) - << D->getSourceRange(); - SemaRef.Diag(ExistingInit->getBeginLoc(), - diag::note_previous_initializer) - << /*FIXME:has side effects=*/0 - << ExistingInit->getSourceRange(); + diagnoseInitOverride( + ExistingInit, SourceRange(D->getBeginLoc(), DIE->getEndLoc())); } // remove existing initializer @@ -2535,6 +2582,54 @@ return true; } + // C++20 [dcl.init.list]p3: + // The ordered identifiers in the designators of the designated- + // initializer-list shall form a subsequence of the ordered identifiers + // in the direct non-static data members of T. + // + // Note that this is not a condition on forming the aggregate + // initialization, only on actually performing initialization, + // so it is not checked in VerifyOnly mode. + // + // FIXME: This is the only reordering diagnostic we produce, and it only + // catches cases where we have a top-level field designator that jumps + // backwards. This is the only such case that is reachable in an + // otherwise-valid C++20 program, so is the only case that's required for + // conformance, but for consistency, we should diagnose all the other + // cases where a designator takes us backwards too. + if (IsFirstDesignator && !VerifyOnly && SemaRef.getLangOpts().CPlusPlus && + NextField && + (*NextField == RT->getDecl()->field_end() || + (*NextField)->getFieldIndex() > Field->getFieldIndex() + 1)) { + // Find the field that we just initialized. + FieldDecl *PrevField = nullptr; + for (auto FI = RT->getDecl()->field_begin(); + FI != RT->getDecl()->field_end(); ++FI) { + if (FI->isUnnamedBitfield()) + continue; + if (*NextField != RT->getDecl()->field_end() && + declaresSameEntity(*FI, **NextField)) + break; + PrevField = *FI; + } + + if (PrevField && + PrevField->getFieldIndex() > KnownField->getFieldIndex()) { + SemaRef.Diag(DIE->getBeginLoc(), diag::ext_designated_init_reordered) + << KnownField << PrevField << DIE->getSourceRange(); + + unsigned OldIndex = NumBases + PrevField->getFieldIndex(); + if (StructuredList && OldIndex <= StructuredList->getNumInits()) { + if (Expr *PrevInit = StructuredList->getInit(OldIndex)) { + SemaRef.Diag(PrevInit->getBeginLoc(), + diag::note_previous_field_init) + << PrevField << PrevInit->getSourceRange(); + } + } + } + } + + // Update the designator with the field declaration. if (!VerifyOnly) D->setField(*Field); @@ -2875,7 +2970,7 @@ if (!IsFullyOverwritten) return Result; - if (ExistingInit && !VerifyOnly) { + if (ExistingInit) { // We are creating an initializer list that initializes the // subobjects of the current object, but there was already an // initialization that completely initialized the current @@ -2895,11 +2990,7 @@ // struct X xs[] = { [0] = (struct X) { 1, 2 }, [0].b = 3 }; // // This case is handled by CheckDesignatedInitializer. - SemaRef.Diag(InitRange.getBegin(), - diag::warn_subobject_initializer_overrides) - << InitRange; - SemaRef.Diag(ExistingInit->getBeginLoc(), diag::note_previous_initializer) - << /*FIXME:has side effects=*/0 << ExistingInit->getSourceRange(); + diagnoseInitOverride(ExistingInit, InitRange); } unsigned ExpectedNumInits = 0; @@ -2968,24 +3059,23 @@ if (Expr *PrevInit = StructuredList->updateInit(SemaRef.Context, StructuredIndex, expr)) { // This initializer overwrites a previous initializer. Warn. - // We need to check on source range validity because the previous - // initializer does not have to be an explicit initializer. - // struct P { int a, b; }; - // struct PP { struct P p } l = { { .a = 2 }, .p.b = 3 }; - // There is an overwrite taking place because the first braced initializer - // list "{ .a = 2 }' already provides value for .p.b (which is zero). - if (PrevInit->getSourceRange().isValid() && !VerifyOnly) { - SemaRef.Diag(expr->getBeginLoc(), diag::warn_initializer_overrides) - << expr->getSourceRange(); - - SemaRef.Diag(PrevInit->getBeginLoc(), diag::note_previous_initializer) - << /*FIXME:has side effects=*/0 << PrevInit->getSourceRange(); - } + diagnoseInitOverride(PrevInit, expr->getSourceRange()); } ++StructuredIndex; } +/// Determine whether we can perform aggregate initialization for the purposes +/// of overload resolution. +bool Sema::CanPerformAggregateInitializationForOverloadResolution( + const InitializedEntity &Entity, InitListExpr *From) { + QualType Type = Entity.getType(); + InitListChecker Check(*this, Entity, From, Type, /*VerifyOnly=*/true, + /*TreatUnavailableAsInvalid=*/false, + /*InOverloadResolution=*/true); + return !Check.HadError(); +} + /// Check that the given Index expression is a valid array designator /// value. This is essentially just a wrapper around /// VerifyIntegerConstantExpression that also checks for negative values @@ -3019,6 +3109,7 @@ bool Invalid = false; SmallVector Designators; SmallVector InitExpressions; + bool HasArrayDesignator = false; // Build designators and check array designator expressions. for (unsigned Idx = 0; Idx < Desig.getNumDesignators(); ++Idx) { @@ -3042,6 +3133,7 @@ D.getRBracketLoc())); InitExpressions.push_back(Index); } + HasArrayDesignator = true; break; } @@ -3085,6 +3177,7 @@ InitExpressions.push_back(EndIndex); } } + HasArrayDesignator = true; break; } } @@ -3096,17 +3189,8 @@ // Clear out the expressions within the designation. Desig.ClearExprs(*this); - DesignatedInitExpr *DIE - = DesignatedInitExpr::Create(Context, - Designators, - InitExpressions, Loc, GNUSyntax, - Init.getAs()); - - if (!getLangOpts().C99) - Diag(DIE->getBeginLoc(), diag::ext_designated_init) - << DIE->getSourceRange(); - - return DIE; + return DesignatedInitExpr::Create(Context, Designators, InitExpressions, Loc, + GNUSyntax, Init.getAs()); } //===----------------------------------------------------------------------===// Index: cfe/trunk/lib/Sema/SemaOverload.cpp =================================================================== --- cfe/trunk/lib/Sema/SemaOverload.cpp +++ cfe/trunk/lib/Sema/SemaOverload.cpp @@ -4920,13 +4920,11 @@ // Type is an aggregate, argument is an init list. At this point it comes // down to checking whether the initialization works. // FIXME: Find out whether this parameter is consumed or not. - // FIXME: Expose SemaInit's aggregate initialization code so that we don't - // need to call into the initialization code here; overload resolution - // should not be doing that. InitializedEntity Entity = InitializedEntity::InitializeParameter(S.Context, ToType, /*Consumed=*/false); - if (S.CanPerformCopyInitialization(Entity, From)) { + if (S.CanPerformAggregateInitializationForOverloadResolution(Entity, + From)) { Result.setUserDefined(); Result.UserDefined.Before.setAsIdentityConversion(); // Initializer lists don't have a type. Index: cfe/trunk/lib/Sema/TreeTransform.h =================================================================== --- cfe/trunk/lib/Sema/TreeTransform.h +++ cfe/trunk/lib/Sema/TreeTransform.h @@ -2416,7 +2416,7 @@ ExprResult RebuildInitList(SourceLocation LBraceLoc, MultiExprArg Inits, SourceLocation RBraceLoc) { - return SemaRef.ActOnInitList(LBraceLoc, Inits, RBraceLoc); + return SemaRef.BuildInitList(LBraceLoc, Inits, RBraceLoc); } /// Build a new designated initializer expression. Index: cfe/trunk/test/Analysis/globals.cpp =================================================================== --- cfe/trunk/test/Analysis/globals.cpp +++ cfe/trunk/test/Analysis/globals.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=core -verify %s +// RUN: %clang_analyze_cc1 -analyzer-checker=core -verify -std=c++2a %s static const unsigned long long scull = 0; Index: cfe/trunk/test/CXX/expr/expr.const/p2-0x.cpp =================================================================== --- cfe/trunk/test/CXX/expr/expr.const/p2-0x.cpp +++ cfe/trunk/test/CXX/expr/expr.const/p2-0x.cpp @@ -360,7 +360,7 @@ extern const U pu; constexpr const int *pua = &pu.a; constexpr const int *pub = &pu.b; - constexpr U pu = { .b = 1 }; // expected-warning {{C99 feature}} + constexpr U pu = { .b = 1 }; // expected-warning {{C++20 extension}} constexpr const int a2 = *pua; // expected-error {{constant expression}} expected-note {{read of member 'a' of union with active member 'b'}} constexpr const int b2 = *pub; // ok } Index: cfe/trunk/test/CodeGenObjCXX/designated-initializers.mm =================================================================== --- cfe/trunk/test/CodeGenObjCXX/designated-initializers.mm +++ cfe/trunk/test/CodeGenObjCXX/designated-initializers.mm @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple arm64 %s -verify -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -triple arm64 %s -verify -emit-llvm -o - -Wno-c99-designator | FileCheck %s // expected-no-diagnostics // Make sure we don't enter an infinite loop (rdar://21942503) Index: cfe/trunk/test/PCH/cxx1y-default-initializer.cpp =================================================================== --- cfe/trunk/test/PCH/cxx1y-default-initializer.cpp +++ cfe/trunk/test/PCH/cxx1y-default-initializer.cpp @@ -37,8 +37,8 @@ static_assert(A{}.z == 3, ""); static_assert(A{1}.z == 4, ""); -static_assert(A{.y = 5}.z == 5, ""); // expected-warning {{C99}} -static_assert(A{3, .y = 1}.z == 4, ""); // expected-warning {{C99}} +static_assert(A{.y = 5}.z == 5, ""); // expected-warning {{C++20}} +static_assert(A{3, .y = 1}.z == 4, ""); // expected-warning {{C99}} expected-note {{here}} static_assert(make().z == 3, ""); static_assert(make(12).z == 15, ""); static_assert(C().c == 0, ""); Index: cfe/trunk/test/Parser/cxx0x-lambda-expressions.cpp =================================================================== --- cfe/trunk/test/Parser/cxx0x-lambda-expressions.cpp +++ cfe/trunk/test/Parser/cxx0x-lambda-expressions.cpp @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -fsyntax-only -Wno-unused-value -verify -std=c++11 %s -// RUN: %clang_cc1 -fsyntax-only -Wno-unused-value -verify -std=c++2a %s +// RUN: %clang_cc1 -fsyntax-only -Wno-unused-value -verify -std=c++11 -Wno-c99-designator %s +// RUN: %clang_cc1 -fsyntax-only -Wno-unused-value -verify -std=c++2a -Wno-c99-designator %s enum E { e }; Index: cfe/trunk/test/Parser/objc-init.m =================================================================== --- cfe/trunk/test/Parser/objc-init.m +++ cfe/trunk/test/Parser/objc-init.m @@ -1,7 +1,7 @@ // RUN: %clang_cc1 -fsyntax-only -fobjc-runtime=macosx-fragile -verify -pedantic -Wno-objc-root-class %s -// RUN: %clang_cc1 -fsyntax-only -fobjc-runtime=macosx-fragile -verify -x objective-c++ -Wno-objc-root-class %s -// RUN: %clang_cc1 -fsyntax-only -fobjc-runtime=macosx-fragile -verify -x objective-c++ -Wno-objc-root-class -std=c++98 %s -// RUN: %clang_cc1 -fsyntax-only -fobjc-runtime=macosx-fragile -verify -x objective-c++ -Wno-objc-root-class -std=c++11 %s +// RUN: %clang_cc1 -fsyntax-only -fobjc-runtime=macosx-fragile -verify -x objective-c++ -Wno-c99-designator -Wno-objc-root-class %s +// RUN: %clang_cc1 -fsyntax-only -fobjc-runtime=macosx-fragile -verify -x objective-c++ -Wno-c99-designator -Wno-objc-root-class -std=c++98 %s +// RUN: %clang_cc1 -fsyntax-only -fobjc-runtime=macosx-fragile -verify -x objective-c++ -Wno-c99-designator -Wno-objc-root-class -std=c++11 %s // rdar://5707001 @interface NSNumber; Index: cfe/trunk/test/Sema/designated-initializers.c =================================================================== --- cfe/trunk/test/Sema/designated-initializers.c +++ cfe/trunk/test/Sema/designated-initializers.c @@ -130,10 +130,10 @@ void test() { struct X xs[] = { [0] = (struct X){1, 2}, // expected-note 2 {{previous initialization is here}} - [0].c = 3, // expected-warning{{subobject initialization overrides initialization of other fields within its enclosing subobject}} + [0].c = 3, // expected-warning{{initializer partially overrides prior initialization of this subobject}} (struct X) {4, 5, 6}, // expected-note{{previous initialization is here}} - [1].b = get8(), // expected-warning{{subobject initialization overrides initialization of other fields within its enclosing subobject}} - [0].b = 8 // expected-warning{{subobject initialization overrides initialization of other fields within its enclosing subobject}} + [1].b = get8(), // expected-warning{{initializer partially overrides prior initialization of this subobject}} + [0].b = 8 // expected-warning{{initializer partially overrides prior initialization of this subobject}} }; } @@ -331,20 +331,20 @@ char L[6]; int M; } overwrite_string[] = { - { { "foo" }, 1 }, // expected-note {{previous initialization is here}} - [0].L[2] = 'x' // expected-warning{{subobject initialization overrides initialization of other fields}} + { { "foo" }, 1 }, // expected-note{{previous initialization is here}} + [0].L[2] = 'x' // expected-warning{{initializer partially overrides prior initialization of this subobject}} }; struct overwrite_string_struct2 { char L[6]; int M; } overwrite_string2[] = { { { "foo" }, 1 }, // expected-note{{previous initialization is here}} - [0].L[4] = 'x' // expected-warning{{subobject initialization overrides initialization of other fields}} + [0].L[4] = 'x' // expected-warning{{initializer partially overrides prior initialization of this subobject}} }; struct overwrite_string_struct overwrite_string3[] = { "foo", 1, // expected-note{{previous initialization is here}} - [0].L[4] = 'x' // expected-warning{{subobject initialization overrides initialization of other fields}} + [0].L[4] = 'x' // expected-warning{{initializer partially overrides prior initialization of this subobject}} }; struct overwrite_string_struct overwrite_string4[] = { Index: cfe/trunk/test/Sema/static-assert.c =================================================================== --- cfe/trunk/test/Sema/static-assert.c +++ cfe/trunk/test/Sema/static-assert.c @@ -1,6 +1,6 @@ // RUN: %clang_cc1 -std=c11 -fsyntax-only -verify %s // RUN: %clang_cc1 -std=c99 -pedantic -fsyntax-only -verify=expected,ext %s -// RUN: %clang_cc1 -xc++ -std=c++11 -pedantic -fsyntax-only -verify=expected,ext %s +// RUN: %clang_cc1 -xc++ -std=c++11 -pedantic -fsyntax-only -verify=expected,ext,cxx %s _Static_assert("foo", "string is nonzero"); // ext-warning {{'_Static_assert' is a C11 extension}} #ifndef __cplusplus @@ -42,10 +42,7 @@ } typedef UNION(unsigned, struct A) U1; // ext-warning 3 {{'_Static_assert' is a C11 extension}} -UNION(char[2], short) u2 = { .one = { 'a', 'b' } }; // ext-warning 3 {{'_Static_assert' is a C11 extension}} -#if defined(__cplusplus) -// ext-warning@-2 {{designated initializers are a C99 feature}} -#endif +UNION(char[2], short) u2 = { .one = { 'a', 'b' } }; // ext-warning 3 {{'_Static_assert' is a C11 extension}} cxx-warning {{designated initializers are a C++20 extension}} typedef UNION(char, short) U3; // expected-error {{static_assert failed due to requirement 'sizeof(char) == sizeof(short)' "type size mismatch"}} \ // ext-warning 3 {{'_Static_assert' is a C11 extension}} typedef UNION(float, 0.5f) U4; // expected-error {{expected a type}} \ Index: cfe/trunk/test/SemaCXX/aggregate-initialization.cpp =================================================================== --- cfe/trunk/test/SemaCXX/aggregate-initialization.cpp +++ cfe/trunk/test/SemaCXX/aggregate-initialization.cpp @@ -1,6 +1,7 @@ -// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s -// RUN: %clang_cc1 -fsyntax-only -verify -std=c++14 %s -// RUN: %clang_cc1 -fsyntax-only -verify -std=c++17 %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++14 %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++17 %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++2a %s // Verify that using an initializer list for a non-aggregate looks for // constructors.. Index: cfe/trunk/test/SemaCXX/c99.cpp =================================================================== --- cfe/trunk/test/SemaCXX/c99.cpp +++ cfe/trunk/test/SemaCXX/c99.cpp @@ -1,9 +1,70 @@ -// RUN: %clang_cc1 -fsyntax-only -pedantic -verify %s +// RUN: %clang_cc1 -fsyntax-only -pedantic -verify=expected,cxx17 -std=c++17 %s +// RUN: %clang_cc1 -fsyntax-only -pedantic -verify=expected,cxx20 -std=c++2a %s + +// cxx17-warning@* 0+{{designated initializers are a C++20 extension}} + void f1(int i[static 5]) { // expected-error{{C99}} } struct Point { int x; int y; int z[]; }; // expected-warning{{flexible array members are a C99 feature}} -Point p1 = { .x = 17, // expected-warning{{designated initializers are a C99 feature}} - y: 25 }; // expected-warning{{designated initializers are a C99 feature}} \ - // expected-warning{{use of GNU old-style field designator extension}} +Point p1 = { .x = 17, + y: 25 }; // expected-warning{{use of GNU old-style field designator extension}} + +Point p2 = { + .x = 17, // expected-warning {{mixture of designated and non-designated initializers in the same initializer list is a C99 extension}} + 25 // expected-note {{first non-designated initializer}} +}; + +Point p3 = { + .x = 17, // expected-note {{previous initialization is here}} + .x = 18, // expected-warning {{initializer overrides prior initialization of this subobject}} +}; + +Point p4 = { + .x = 17, // expected-warning {{mixture of designated and non-designated initializers in the same initializer list is a C99 extension}} + 25, // expected-note {{first non-designated initializer}} + // expected-note@-1 {{previous initialization is here}} + .y = 18, // expected-warning {{initializer overrides prior initialization of this subobject}} +}; + +int arr[1] = {[0] = 0}; // expected-warning {{array designators are a C99 extension}} + +struct Pt { int x, y; }; +struct Rect { Pt tl, br; }; +Rect r = { + .tl.x = 0 // expected-warning {{nested designators are a C99 extension}} +}; + +struct NonTrivial { + NonTrivial(); + ~NonTrivial(); +}; +struct S { + int a; + NonTrivial b; +}; +struct T { + S s; +}; +S f(); + +T t1 = { + .s = f() +}; + +// It's important that we reject this; we would not destroy the existing +// 'NonTrivial' object before overwriting it (and even calling its destructor +// would not necessarily be correct). +T t2 = { + .s = f(), // expected-note {{previous}} + .s.b = NonTrivial() // expected-error {{initializer would partially override prior initialization of object of type 'S' with non-trivial destruction}} + // expected-warning@-1 {{nested}} +}; + +// FIXME: It might be reasonable to accept this. +T t3 = { + .s = f(), // expected-note {{previous}} + .s.a = 0 // expected-error {{initializer would partially override prior initialization of object of type 'S' with non-trivial destruction}} + // expected-warning@-1 {{nested}} +}; Index: cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp =================================================================== --- cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp +++ cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple x86_64-linux -Wno-string-plus-int -Wno-pointer-arith -Wno-zero-length-array -fsyntax-only -fcxx-exceptions -verify -std=c++11 -pedantic %s -Wno-comment -Wno-tautological-pointer-compare -Wno-bool-conversion +// RUN: %clang_cc1 -triple x86_64-linux -Wno-string-plus-int -Wno-pointer-arith -Wno-zero-length-array -Wno-c99-designator -fsyntax-only -fcxx-exceptions -verify -std=c++11 -pedantic %s -Wno-comment -Wno-tautological-pointer-compare -Wno-bool-conversion namespace StaticAssertFoldTest { @@ -566,7 +566,7 @@ expected-error {{static_assert expression is not an integral constant expression}} \ expected-note {{in call to 'fail(zs[1][0][1][0])'}} -constexpr int arr[40] = { 1, 2, 3, [8] = 4 }; // expected-warning {{C99 feature}} +constexpr int arr[40] = { 1, 2, 3, [8] = 4 }; constexpr int SumNonzero(const int *p) { return *p + (*p ? SumNonzero(p+1) : 0); } @@ -979,7 +979,7 @@ int b; }; -constexpr U u[4] = { { .a = 0 }, { .b = 1 }, { .a = 2 }, { .b = 3 } }; // expected-warning 4{{C99 feature}} +constexpr U u[4] = { { .a = 0 }, { .b = 1 }, { .a = 2 }, { .b = 3 } }; static_assert(u[0].a == 0, ""); static_assert(u[0].b, ""); // expected-error {{constant expression}} expected-note {{read of member 'b' of union with active member 'a'}} static_assert(u[1].b == 1, ""); Index: cfe/trunk/test/SemaCXX/constexpr-printing.cpp =================================================================== --- cfe/trunk/test/SemaCXX/constexpr-printing.cpp +++ cfe/trunk/test/SemaCXX/constexpr-printing.cpp @@ -41,11 +41,7 @@ expected-note {{in call to 'test_printing(12, 3.976200e+01, 3+4i, 1.290000e+01+3.600000e+00i, &u2.T::arr[4], u2.another.arr[2], {5, 1, 2, 3}, {{{}}, {{}}, &u1.T::arr[2]})'}} struct V { - // FIXME: when we can generate these as constexpr constructors, remove the - // explicit definitions. - constexpr V() : arr{[255] = 42} {} - constexpr V(const V &v) : arr{[255] = 42} {} - int arr[256]; + int arr[256] = {[255] = 42}; // expected-warning {{C99}} }; constexpr V v; constexpr int get(const int *p) { return *p; } // expected-note {{read of dereferenced one-past-the-end pointer}} Index: cfe/trunk/test/SemaCXX/cxx0x-initializer-constructor.cpp =================================================================== --- cfe/trunk/test/SemaCXX/cxx0x-initializer-constructor.cpp +++ cfe/trunk/test/SemaCXX/cxx0x-initializer-constructor.cpp @@ -406,6 +406,6 @@ 0, 1 }; // expected-error {{ambiguous}} expected-note {{in implicit initialization of array element 2}} C c2[3] = { - [0] = 1, [2] = 3 + [0] = 1, [2] = 3 // expected-warning {{C99}} }; // expected-error {{ambiguous}} expected-note {{in implicit initialization of array element 1}} } Index: cfe/trunk/test/SemaCXX/cxx2a-initializer-aggregates.cpp =================================================================== --- cfe/trunk/test/SemaCXX/cxx2a-initializer-aggregates.cpp +++ cfe/trunk/test/SemaCXX/cxx2a-initializer-aggregates.cpp @@ -1,4 +1,9 @@ -// RUN: %clang_cc1 -std=c++2a %s -verify +// RUN: %clang_cc1 -std=c++2a %s -verify=expected,pedantic,override,reorder -pedantic-errors +// RUN: %clang_cc1 -std=c++2a %s -verify=expected,pedantic -Werror=c99-designator -Wno-reorder -Wno-initializer-overrides +// RUN: %clang_cc1 -std=c++2a %s -verify=expected,reorder -Wno-c99-designator -Werror=reorder -Wno-initializer-overrides +// RUN: %clang_cc1 -std=c++2a %s -verify=expected,override -Wno-c99-designator -Wno-reorder -Werror=initializer-overrides +// RUN: %clang_cc1 -std=c++2a %s -verify -Wno-c99-designator -Wno-reorder -Wno-initializer-overrides + namespace class_with_ctor { struct A { // expected-note 6{{candidate}} @@ -21,3 +26,105 @@ C c1 = {{}, {}}; // ok, call default ctor twice C c2 = {{1, 2}, {3, 4}}; // expected-error 2{{no matching constructor}} } + +namespace designator { +struct A { int x, y; }; +struct B { A a; }; + +A a1 = { + .y = 1, // reorder-note {{previous initialization for field 'y' is here}} + .x = 2 // reorder-error {{ISO C++ requires field designators to be specified in declaration order; field 'y' will be initialized after field 'x'}} +}; +int arr[3] = {[1] = 5}; // pedantic-error {{array designators are a C99 extension}} +B b = {.a.x = 0}; // pedantic-error {{nested designators are a C99 extension}} +A a2 = { + .x = 1, // pedantic-error {{mixture of designated and non-designated initializers in the same initializer list is a C99 extension}} + 2 // pedantic-note {{first non-designated initializer is here}} +}; +A a3 = { + 1, // pedantic-note {{first non-designated initializer is here}} + .y = 2 // pedantic-error {{mixture of designated and non-designated initializers in the same initializer list is a C99 extension}} +}; +A a4 = { + .x = 1, // override-note {{previous}} + .x = 1 // override-error {{overrides prior initialization}} +}; +A a5 = { + .y = 1, // override-note {{previous}} + .y = 1 // override-error {{overrides prior initialization}} +}; +struct C { int :0, x, :0, y, :0; }; +C c = { + .x = 1, // override-note {{previous}} + .x = 1, // override-error {{overrides prior initialization}} override-note {{previous}} + .y = 1, // override-note {{previous}} + .y = 1, // override-error {{overrides prior initialization}} + .x = 1, // reorder-error {{declaration order}} override-error {{overrides prior initialization}} override-note {{previous}} + .x = 1, // override-error {{overrides prior initialization}} +}; +} + +namespace base_class { + struct base { + int x; + }; + struct derived : base { + int y; + }; + derived d = {.x = 1, .y = 2}; // expected-error {{'x' does not refer to any field}} +} + +namespace union_ { + union U { int a, b; }; + U u = { + .a = 1, // override-note {{here}} + .b = 2, // override-error {{overrides prior}} + }; +} + +namespace overload_resolution { + struct A { int x, y; }; + union B { int x, y; }; + + void f(A a); + void f(B b) = delete; + void g() { f({.x = 1, .y = 2}); } // ok, calls non-union overload + + // As an extension of the union case, overload resolution won't pick any + // candidate where a field initializer would be overridden. + struct A2 { int x, other, y; }; + int f(A2); + void g2() { int k = f({.x = 1, 2, .y = 3}); (void)k; } // pedantic-error {{mixture of designated and non-designated}} pedantic-note {{here}} + + struct C { int x; }; + void h(A a); // expected-note {{candidate}} + void h(C c); // expected-note {{candidate}} + void i() { + h({.x = 1, .y = 2}); + h({.y = 1, .x = 2}); // reorder-error {{declaration order}} reorder-note {{previous}} + h({.x = 1}); // expected-error {{ambiguous}} + } + + struct D { int y, x; }; + void j(A a); // expected-note {{candidate}} + void j(D d); // expected-note {{candidate}} + void k() { + j({.x = 1, .y = 2}); // expected-error {{ambiguous}} + } +} + +namespace deduction { + struct A { int x, y; }; + union B { int x, y; }; + + template void f(decltype(T{.x = 1, .y = 2}) = {}); + template void f(decltype(U{.x = 1, .y = 2}) = {}) = delete; + void g() { f(); } // ok, calls non-union overload + + struct C { int y, x; }; + template void h(decltype(T{.y = 1, .x = 2}) = {}) = delete; + template void h(decltype(U{.y = 1, .x = 2}) = {}); + void i() { + h(); // ok, selects C overload by SFINAE + } +} Index: cfe/trunk/test/SemaCXX/decltype.cpp =================================================================== --- cfe/trunk/test/SemaCXX/decltype.cpp +++ cfe/trunk/test/SemaCXX/decltype.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify -Wno-c99-designator %s // PR5290 int const f0(); @@ -80,22 +80,22 @@ struct P1 { char x[6]; } g1 = { "foo" }; struct LP1 { struct P1 p1; }; - // expected-warning@+3 {{subobject initialization overrides}} + // expected-warning@+3 {{initializer partially overrides}} // expected-note@+2 {{previous initialization}} // expected-note@+1 {{previous definition}} template void foo(decltype(T(LP1{ .p1 = g1, .p1.x[1] = 'x' }))) {} - // expected-warning@+3 {{subobject initialization overrides}} + // expected-warning@+3 {{initializer partially overrides}} // expected-note@+2 {{previous initialization}} template void foo(decltype(T(LP1{ .p1 = g1, .p1.x[1] = 'r' }))) {} // okay - // expected-warning@+3 {{subobject initialization overrides}} + // expected-warning@+3 {{initializer partially overrides}} // expected-note@+2 {{previous initialization}} template void foo(decltype(T(LP1{ .p1 = { "foo" }, .p1.x[1] = 'x'}))) {} // okay - // expected-warning@+3 {{subobject initialization overrides}} + // expected-warning@+3 {{initializer partially overrides}} // expected-note@+2 {{previous initialization}} // expected-error@+1 {{redefinition of 'foo'}} template void foo(decltype(T(LP1{ .p1 = g1, .p1.x[1] = 'x' }))) {} Index: cfe/trunk/test/SemaCXX/designated-initializers-base-class.cpp =================================================================== --- cfe/trunk/test/SemaCXX/designated-initializers-base-class.cpp +++ cfe/trunk/test/SemaCXX/designated-initializers-base-class.cpp @@ -1,5 +1,4 @@ // RUN: %clang_cc1 %s -std=c++1z -fsyntax-only -verify -Winitializer-overrides -// expected-no-diagnostics struct B { int x; @@ -9,4 +8,4 @@ int y; }; -void test() { D d = {1, .y = 2}; } +void test() { D d = {1, .y = 2}; } // expected-warning {{C99 extension}} expected-note {{}} Index: cfe/trunk/test/SemaCXX/designated-initializers.cpp =================================================================== --- cfe/trunk/test/SemaCXX/designated-initializers.cpp +++ cfe/trunk/test/SemaCXX/designated-initializers.cpp @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify -Winitializer-overrides %s -// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify -Woverride-init %s +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify -Wno-reorder -Wno-c99-designator -Winitializer-overrides %s +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify -Wno-reorder -Wno-c99-designator -Woverride-init %s template struct Foo { struct SubFoo { Index: cfe/trunk/test/SemaCXX/eval-crashes.cpp =================================================================== --- cfe/trunk/test/SemaCXX/eval-crashes.cpp +++ cfe/trunk/test/SemaCXX/eval-crashes.cpp @@ -37,7 +37,7 @@ struct X { Y_t a; }; - struct X foo[2] = {[0 ... 1] = {.a = (Y_t){.c = 0}}}; + struct X foo[2] = {[0 ... 1] = {.a = (Y_t){.c = 0}}}; // expected-warning {{C99 extension}} } namespace pr33140_6 { Index: cfe/trunk/test/SemaCXX/member-init.cpp =================================================================== --- cfe/trunk/test/SemaCXX/member-init.cpp +++ cfe/trunk/test/SemaCXX/member-init.cpp @@ -184,7 +184,7 @@ namespace PR22056 { template struct S { - int x[3] = {[N] = 3}; + int x[3] = {[N] = 3}; // expected-warning {{C99 extension}} }; } Index: cfe/trunk/test/SemaObjCXX/message.mm =================================================================== --- cfe/trunk/test/SemaObjCXX/message.mm +++ cfe/trunk/test/SemaObjCXX/message.mm @@ -84,7 +84,7 @@ #if __cplusplus <= 199711L // expected-warning@-2 {{'typename' occurs outside of a template}} #endif - int array[5] = {[3] = 2}; + int array[5] = {[3] = 2}; // expected-warning {{C99 extension}} return [super method]; } @end Index: cfe/trunk/test/SemaTemplate/instantiate-c99.cpp =================================================================== --- cfe/trunk/test/SemaTemplate/instantiate-c99.cpp +++ cfe/trunk/test/SemaTemplate/instantiate-c99.cpp @@ -1,6 +1,6 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s -// RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 %s -// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s +// RUN: %clang_cc1 -Wno-c99-extensions -Wno-reorder -fsyntax-only -verify %s +// RUN: %clang_cc1 -Wno-c99-extensions -Wno-reorder -fsyntax-only -verify -std=c++98 %s +// RUN: %clang_cc1 -Wno-c99-extensions -Wno-reorder -fsyntax-only -verify -std=c++11 %s // Test template instantiation for C99-specific features. Index: cfe/trunk/test/SemaTemplate/instantiate-init.cpp =================================================================== --- cfe/trunk/test/SemaTemplate/instantiate-init.cpp +++ cfe/trunk/test/SemaTemplate/instantiate-init.cpp @@ -151,8 +151,8 @@ // Check that an init list update doesn't "lose" the pack-ness of an expression. template void f() { - g(AA{0, [0].n = N} ...); // expected-warning 3{{overrides prior init}} expected-note 3{{previous init}} - g(AA{N, [0].n = 0} ...); // expected-warning 3{{overrides prior init}} expected-note 3{{previous init}} + g(AA{0, [0].n = N} ...); // expected-warning 3{{extension}} expected-note {{here}} expected-warning 3{{overrides prior init}} expected-note 3{{previous init}} + g(AA{N, [0].n = 0} ...); // expected-warning 3{{extension}} expected-note {{here}} expected-warning 3{{overrides prior init}} expected-note 3{{previous init}} }; void g(AA, AA);