diff options
-rw-r--r-- | include/clang/AST/Expr.h | 218 | ||||
-rw-r--r-- | include/clang/AST/StmtNodes.def | 1 | ||||
-rw-r--r-- | include/clang/Basic/DiagnosticKinds.def | 22 | ||||
-rw-r--r-- | include/clang/Parse/Action.h | 21 | ||||
-rw-r--r-- | include/clang/Parse/Designator.h | 65 | ||||
-rw-r--r-- | lib/AST/Expr.cpp | 111 | ||||
-rw-r--r-- | lib/AST/StmtPrinter.cpp | 4 | ||||
-rw-r--r-- | lib/Parse/ParseInit.cpp | 36 | ||||
-rw-r--r-- | lib/Sema/Sema.cpp | 4 | ||||
-rw-r--r-- | lib/Sema/Sema.h | 14 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 3 | ||||
-rw-r--r-- | lib/Sema/SemaInit.cpp | 391 | ||||
-rw-r--r-- | test/Sema/designated-initializers.c | 78 |
13 files changed, 912 insertions, 56 deletions
diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index 2f2d4a6e39..9d73707359 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -1706,6 +1706,224 @@ private: InitListExpr() : Expr(InitListExprClass, QualType()) {} }; +/// @brief Represents a C99 designated initializer expression. +/// +/// A designated initializer expression (C99 6.7.8) contains one or +/// more designators (which can be field designators, array +/// designators, or GNU array-range designators) followed by an +/// expression that initializes the field or element(s) that the +/// designators refer to. For example, given: +/// +/// @code +/// struct point { +/// double x; +/// double y; +/// }; +/// struct point ptarray[10] = { [2].y = 1.0, [2].x = 2.0, [0].x = 1.0 }; +/// @endcode +/// +/// The InitListExpr contains three DesignatedInitExprs, the first of +/// which covers @c [2].y=1.0. This DesignatedInitExpr will have two +/// designators, one array designator for @c [2] followed by one field +/// designator for @c .y. The initalization expression will be 1.0. +class DesignatedInitExpr : public Expr { + /// The location of the '=' or ':' prior to the actual initializer + /// expression. + SourceLocation EqualOrColonLoc; + + /// Whether this designated initializer used the GNU deprecated ':' + /// syntax rather than the C99 '=' syntax. + bool UsesColonSyntax : 1; + + /// The number of designators in this initializer expression. + unsigned NumDesignators : 15; + + /// The number of subexpressions of this initializer expression, + /// which contains both the initializer and any additional + /// expressions used by array and array-range designators. + unsigned NumSubExprs : 16; + + DesignatedInitExpr(QualType Ty, unsigned NumDesignators, + SourceLocation EqualOrColonLoc, bool UsesColonSyntax, + unsigned NumSubExprs) + : Expr(DesignatedInitExprClass, Ty), + EqualOrColonLoc(EqualOrColonLoc), UsesColonSyntax(UsesColonSyntax), + NumDesignators(NumDesignators), NumSubExprs(NumSubExprs) { } + +public: + /// A field designator, e.g., ".x". + struct FieldDesignator { + /// Refers to the field that is being initialized. The low bit + /// of this field determines whether this is actually a pointer + /// to an IdentifierInfo (if 1) or a FieldDecl (if 0). When + /// initially constructed, a field designator will store an + /// IdentifierInfo*. After semantic analysis has resolved that + /// name, the field designator will instead store a FieldDecl*. + uintptr_t NameOrField; + + /// The location of the '.' in the designated initializer. + unsigned DotLoc; + + /// The location of the field name in the designated initializer. + unsigned FieldLoc; + }; + + /// An array or GNU array-range designator, e.g., "[9]" or "[10..15]". + struct ArrayOrRangeDesignator { + /// Location of the first index expression within the designated + /// initializer expression's list of subexpressions. + unsigned Index; + /// The location of the '[' starting the array range designator. + unsigned LBracketLoc; + /// The location of the ellipsis separating the start and end + /// indices. Only valid for GNU array-range designators. + unsigned EllipsisLoc; + /// The location of the ']' terminating the array range designator. + unsigned RBracketLoc; + }; + + /// @brief Represents a single C99 designator. + /// + /// @todo This class is infuriatingly similar to clang::Designator, + /// but minor differences (storing indices vs. storing pointers) + /// keep us from reusing it. Try harder, later, to rectify these + /// differences. + class Designator { + /// @brief The kind of designator this describes. + enum { + FieldDesignator, + ArrayDesignator, + ArrayRangeDesignator + } Kind; + + union { + /// A field designator, e.g., ".x". + struct FieldDesignator Field; + /// An array or GNU array-range designator, e.g., "[9]" or "[10..15]". + struct ArrayOrRangeDesignator ArrayOrRange; + }; + friend class DesignatedInitExpr; + + public: + /// @brief Initializes a field designator. + Designator(const IdentifierInfo *FieldName, SourceLocation DotLoc, + SourceLocation FieldLoc) + : Kind(FieldDesignator) { + Field.NameOrField = reinterpret_cast<uintptr_t>(FieldName) | 0x01; + Field.DotLoc = DotLoc.getRawEncoding(); + Field.FieldLoc = FieldLoc.getRawEncoding(); + } + + /// @brief Initializes an array designator. + Designator(unsigned Index, SourceLocation LBracketLoc, + SourceLocation RBracketLoc) + : Kind(ArrayDesignator) { + ArrayOrRange.Index = Index; + ArrayOrRange.LBracketLoc = LBracketLoc.getRawEncoding(); + ArrayOrRange.EllipsisLoc = SourceLocation().getRawEncoding(); + ArrayOrRange.RBracketLoc = RBracketLoc.getRawEncoding(); + } + + /// @brief Initializes a GNU array-range designator. + Designator(unsigned Index, SourceLocation LBracketLoc, + SourceLocation EllipsisLoc, SourceLocation RBracketLoc) + : Kind(ArrayRangeDesignator) { + ArrayOrRange.Index = Index; + ArrayOrRange.LBracketLoc = LBracketLoc.getRawEncoding(); + ArrayOrRange.EllipsisLoc = EllipsisLoc.getRawEncoding(); + ArrayOrRange.RBracketLoc = RBracketLoc.getRawEncoding(); + } + + bool isFieldDesignator() const { return Kind == FieldDesignator; } + bool isArrayDesignator() const { return Kind == ArrayDesignator; } + bool isArrayRangeDesignator() const { return Kind == ArrayRangeDesignator; } + + IdentifierInfo * getFieldName(); + + FieldDecl *getField() { + assert(Kind == FieldDesignator && "Only valid on a field designator"); + if (Field.NameOrField & 0x01) + return 0; + else + return reinterpret_cast<FieldDecl *>(Field.NameOrField); + } + + void setField(FieldDecl *FD) { + assert(Kind == FieldDesignator && "Only valid on a field designator"); + Field.NameOrField = reinterpret_cast<uintptr_t>(FD); + } + + SourceLocation getFieldLoc() const { + assert(Kind == FieldDesignator && "Only valid on a field designator"); + return SourceLocation::getFromRawEncoding(Field.FieldLoc); + } + + SourceLocation getLBracketLoc() const { + assert((Kind == ArrayDesignator || Kind == ArrayRangeDesignator) && + "Only valid on an array or array-range designator"); + return SourceLocation::getFromRawEncoding(ArrayOrRange.LBracketLoc); + } + + SourceLocation getRBracketLoc() const { + assert((Kind == ArrayDesignator || Kind == ArrayRangeDesignator) && + "Only valid on an array or array-range designator"); + return SourceLocation::getFromRawEncoding(ArrayOrRange.RBracketLoc); + } + + SourceLocation getEllipsisLoc() const { + assert(Kind == ArrayRangeDesignator && + "Only valid on an array-range designator"); + return SourceLocation::getFromRawEncoding(ArrayOrRange.EllipsisLoc); + } + }; + + static DesignatedInitExpr *Create(ASTContext &C, Designator *Designators, + unsigned NumDesignators, + Expr **IndexExprs, unsigned NumIndexExprs, + SourceLocation EqualOrColonLoc, + bool UsesColonSyntax, Expr *Init); + + /// @brief Returns the number of designators in this initializer. + unsigned size() const { return NumDesignators; } + + // Iterator access to the designators. + typedef Designator* designators_iterator; + designators_iterator designators_begin(); + designators_iterator designators_end(); + + Expr *getArrayIndex(const Designator& D); + Expr *getArrayRangeStart(const Designator& D); + Expr *getArrayRangeEnd(const Designator& D); + + /// @brief Retrieve the location of the '=' that precedes the + /// initializer value itself, if present. + SourceLocation getEqualOrColonLoc() const { return EqualOrColonLoc; } + + /// @brief Determines whether this designated initializer used the + /// GNU 'fieldname:' syntax or the C99 '=' syntax. + bool usesColonSyntax() const { return UsesColonSyntax; } + + /// @brief Retrieve the initializer value. + Expr *getInit() const { + return cast<Expr>(*const_cast<DesignatedInitExpr*>(this)->child_begin()); + } + + void setInit(Expr *init) { + *child_begin() = init; + } + + virtual SourceRange getSourceRange() const; + + static bool classof(const Stmt *T) { + return T->getStmtClass() == DesignatedInitExprClass; + } + static bool classof(const DesignatedInitExpr *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + //===----------------------------------------------------------------------===// // Clang Extensions //===----------------------------------------------------------------------===// diff --git a/include/clang/AST/StmtNodes.def b/include/clang/AST/StmtNodes.def index 2f86c93e6d..e8d4a56c50 100644 --- a/include/clang/AST/StmtNodes.def +++ b/include/clang/AST/StmtNodes.def @@ -85,6 +85,7 @@ STMT(CStyleCastExpr , ExplicitCastExpr) STMT(CompoundLiteralExpr , Expr) STMT(ExtVectorElementExpr , Expr) STMT(InitListExpr , Expr) +STMT(DesignatedInitExpr , Expr) STMT(VAArgExpr , Expr) // GNU Extensions. diff --git a/include/clang/Basic/DiagnosticKinds.def b/include/clang/Basic/DiagnosticKinds.def index a43bbbb5ec..664d3af365 100644 --- a/include/clang/Basic/DiagnosticKinds.def +++ b/include/clang/Basic/DiagnosticKinds.def @@ -698,6 +698,28 @@ DIAG(err_hex_escape_no_digits, ERROR, DIAG(ext_predef_outside_function, WARNING, "predefined identifier is only valid inside function") +// C99 Designated Initializers +DIAG(err_array_designator_nonconstant, ERROR, + "array designator value must be a constant expression") +DIAG(err_array_designator_negative, ERROR, + "array designator value '%0' is negative") +DIAG(err_array_designator_empty_range, ERROR, + "array designator range [%0, %1] is empty") +DIAG(err_array_designator_non_array, ERROR, + "array designator cannot initialize non-array type %0") +DIAG(err_array_designator_too_large, ERROR, + "array designator index (%0) exceeds array bounds (%1)") +DIAG(err_field_designator_non_aggr, ERROR, + "field designator cannot initialize a %select{non-struct, non-union|non-class}0 type %1") +DIAG(err_field_designator_unknown, ERROR, + "field designator %0 does not refer to any field in type %1") +DIAG(err_field_designator_nonfield, ERROR, + "field designator %0 does not refer to a non-static data member") +DIAG(note_field_designator_found, NOTE, + "field designator refers here") +DIAG(err_designator_for_scalar_init, ERROR, + "designator in initializer for scalar type %0") + // Declarations. DIAG(err_typename_requires_specqual, ERROR, "type name requires a specifier or qualifier") diff --git a/include/clang/Parse/Action.h b/include/clang/Parse/Action.h index 559512701a..5d87b17221 100644 --- a/include/clang/Parse/Action.h +++ b/include/clang/Parse/Action.h @@ -32,6 +32,7 @@ namespace clang { class Scope; class Action; class Selector; + class Designation; class InitListDesignations; // Lex. class Preprocessor; @@ -641,6 +642,26 @@ public: SourceLocation RParenLoc) { return ExprEmpty(); } + /// @brief Parsed a C99 designated initializer. + /// + /// @param Desig Contains the designation with one or more designators. + /// + /// @param Loc The location of the '=' or ':' prior to the + /// initialization expression. + /// + /// @param UsedColonSyntax If true, then this designated initializer + /// used the deprecated GNU syntax @c fieldname:foo rather than the + /// C99 syntax @c .fieldname=foo. + /// + /// @param Init The value that the entity (or entities) described by + /// the designation will be initialized with. + virtual OwningExprResult ActOnDesignatedInitializer(Designation &Desig, + SourceLocation Loc, + bool UsedColonSyntax, + OwningExprResult Init) { + return ExprEmpty(); + } + virtual OwningExprResult ActOnCastExpr(SourceLocation LParenLoc, TypeTy *Ty, SourceLocation RParenLoc, ExprArg Op) { return ExprEmpty(); diff --git a/include/clang/Parse/Designator.h b/include/clang/Parse/Designator.h index cf3f8777d5..a76fff3ef2 100644 --- a/include/clang/Parse/Designator.h +++ b/include/clang/Parse/Designator.h @@ -37,12 +37,18 @@ private: struct FieldDesignatorInfo { const IdentifierInfo *II; + unsigned DotLoc; + unsigned NameLoc; }; struct ArrayDesignatorInfo { Action::ExprTy *Index; + unsigned LBracketLoc; + mutable unsigned RBracketLoc; }; struct ArrayRangeDesignatorInfo { Action::ExprTy *Start, *End; + unsigned LBracketLoc, EllipsisLoc; + mutable unsigned RBracketLoc; }; union { @@ -62,6 +68,16 @@ public: assert(isFieldDesignator() && "Invalid accessor"); return FieldInfo.II; } + + SourceLocation getDotLoc() const { + assert(isFieldDesignator() && "Invalid accessor"); + return SourceLocation::getFromRawEncoding(FieldInfo.DotLoc); + } + + SourceLocation getFieldLoc() const { + assert(isFieldDesignator() && "Invalid accessor"); + return SourceLocation::getFromRawEncoding(FieldInfo.NameLoc); + } Action::ExprTy *getArrayIndex() const { assert(isArrayDesignator() && "Invalid accessor"); @@ -77,28 +93,69 @@ public: return ArrayRangeInfo.End; } - - static Designator getField(const IdentifierInfo *II) { + SourceLocation getLBracketLoc() const { + assert((isArrayDesignator() || isArrayRangeDesignator()) && + "Invalid accessor"); + if (isArrayDesignator()) + return SourceLocation::getFromRawEncoding(ArrayInfo.LBracketLoc); + else + return SourceLocation::getFromRawEncoding(ArrayRangeInfo.LBracketLoc); + } + + SourceLocation getRBracketLoc() const { + assert((isArrayDesignator() || isArrayRangeDesignator()) && + "Invalid accessor"); + if (isArrayDesignator()) + return SourceLocation::getFromRawEncoding(ArrayInfo.RBracketLoc); + else + return SourceLocation::getFromRawEncoding(ArrayRangeInfo.RBracketLoc); + } + + SourceLocation getEllipsisLoc() const { + assert(isArrayRangeDesignator() && "Invalid accessor"); + return SourceLocation::getFromRawEncoding(ArrayRangeInfo.EllipsisLoc); + } + + static Designator getField(const IdentifierInfo *II, SourceLocation DotLoc, + SourceLocation NameLoc) { Designator D; D.Kind = FieldDesignator; D.FieldInfo.II = II; + D.FieldInfo.DotLoc = DotLoc.getRawEncoding(); + D.FieldInfo.NameLoc = NameLoc.getRawEncoding(); return D; } - static Designator getArray(Action::ExprTy *Index) { + static Designator getArray(Action::ExprTy *Index, SourceLocation LBracketLoc) { Designator D; D.Kind = ArrayDesignator; D.ArrayInfo.Index = Index; + D.ArrayInfo.LBracketLoc = LBracketLoc.getRawEncoding(); + D.ArrayInfo.RBracketLoc = 0; return D; } - static Designator getArrayRange(Action::ExprTy *Start, Action::ExprTy *End) { + static Designator getArrayRange(Action::ExprTy *Start, Action::ExprTy *End, + SourceLocation LBracketLoc, + SourceLocation EllipsisLoc) { Designator D; D.Kind = ArrayRangeDesignator; D.ArrayRangeInfo.Start = Start; D.ArrayRangeInfo.End = End; + D.ArrayRangeInfo.LBracketLoc = LBracketLoc.getRawEncoding(); + D.ArrayRangeInfo.EllipsisLoc = EllipsisLoc.getRawEncoding(); + D.ArrayRangeInfo.RBracketLoc = 0; return D; } + + void setRBracketLoc(SourceLocation RBracketLoc) const { + assert((isArrayDesignator() || isArrayRangeDesignator()) && + "Invalid accessor"); + if (isArrayDesignator()) + ArrayInfo.RBracketLoc = RBracketLoc.getRawEncoding(); + else + ArrayRangeInfo.RBracketLoc = RBracketLoc.getRawEncoding(); + } /// ClearExprs - Null out any expression references, which prevents them from /// being 'delete'd later. diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index 03b49499ee..70b63fea1b 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -1349,6 +1349,106 @@ void SizeOfAlignOfExpr::Destroy(ASTContext& C) { } //===----------------------------------------------------------------------===// +// DesignatedInitExpr +//===----------------------------------------------------------------------===// + +IdentifierInfo *DesignatedInitExpr::Designator::getFieldName() { + assert(Kind == FieldDesignator && "Only valid on a field designator"); + if (Field.NameOrField & 0x01) + return reinterpret_cast<IdentifierInfo *>(Field.NameOrField&~0x01); + else + return getField()->getIdentifier(); +} + +DesignatedInitExpr * +DesignatedInitExpr::Create(ASTContext &C, Designator *Designators, + unsigned NumDesignators, + Expr **IndexExprs, unsigned NumIndexExprs, + SourceLocation ColonOrEqualLoc, + bool UsesColonSyntax, Expr *Init) { + void *Mem = C.getAllocator().Allocate(sizeof(DesignatedInitExpr) + + sizeof(Designator) * NumDesignators + + sizeof(Stmt *) * (NumIndexExprs + 1), + 8); + DesignatedInitExpr *DIE + = new (Mem) DesignatedInitExpr(C.VoidTy, NumDesignators, + ColonOrEqualLoc, UsesColonSyntax, + NumIndexExprs + 1); + + // Fill in the designators + unsigned ExpectedNumSubExprs = 0; + designators_iterator Desig = DIE->designators_begin(); + for (unsigned Idx = 0; Idx < NumDesignators; ++Idx, ++Desig) { + new (static_cast<void*>(Desig)) Designator(Designators[Idx]); + if (Designators[Idx].isArrayDesignator()) + ++ExpectedNumSubExprs; + else if (Designators[Idx].isArrayRangeDesignator()) + ExpectedNumSubExprs += 2; + } + assert(ExpectedNumSubExprs == NumIndexExprs && "Wrong number of indices!"); + + // Fill in the subexpressions, including the initializer expression. + child_iterator Child = DIE->child_begin(); + *Child++ = Init; + for (unsigned Idx = 0; Idx < NumIndexExprs; ++Idx, ++Child) + *Child = IndexExprs[Idx]; + + return DIE; +} + +SourceRange DesignatedInitExpr::getSourceRange() const { + SourceLocation StartLoc; + Designator &First = *const_cast<DesignatedInitExpr*>(this)->designators_begin(); + if (First.isFieldDesignator()) { + if (UsesColonSyntax) + StartLoc = SourceLocation::getFromRawEncoding(First.Field.FieldLoc); + else + StartLoc = SourceLocation::getFromRawEncoding(First.Field.DotLoc); + } else + StartLoc = SourceLocation::getFromRawEncoding(First.ArrayOrRange.LBracketLoc); + return SourceRange(StartLoc, getInit()->getSourceRange().getEnd()); +} + +DesignatedInitExpr::designators_iterator DesignatedInitExpr::designators_begin() { + char* Ptr = static_cast<char*>(static_cast<void *>(this)); + Ptr += sizeof(DesignatedInitExpr); + return static_cast<Designator*>(static_cast<void*>(Ptr)); +} + +DesignatedInitExpr::designators_iterator DesignatedInitExpr::designators_end() { + return designators_begin() + NumDesignators; +} + +Expr *DesignatedInitExpr::getArrayIndex(const Designator& D) { + assert(D.Kind == Designator::ArrayDesignator && "Requires array designator"); + char* Ptr = static_cast<char*>(static_cast<void *>(this)); + Ptr += sizeof(DesignatedInitExpr); + Ptr += sizeof(Designator) * NumDesignators; + Stmt **SubExprs = reinterpret_cast<Stmt**>(reinterpret_cast<void**>(Ptr)); + return cast<Expr>(*(SubExprs + D.ArrayOrRange.Index + 1)); +} + +Expr *DesignatedInitExpr::getArrayRangeStart(const Designator& D) { + assert(D.Kind == Designator::ArrayRangeDesignator && + "Requires array range designator"); + char* Ptr = static_cast<char*>(static_cast<void *>(this)); + Ptr += sizeof(DesignatedInitExpr); + Ptr += sizeof(Designator) * NumDesignators; + Stmt **SubExprs = reinterpret_cast<Stmt**>(reinterpret_cast<void**>(Ptr)); + return cast<Expr>(*(SubExprs + D.ArrayOrRange.Index + 1)); +} + +Expr *DesignatedInitExpr::getArrayRangeEnd(const Designator& D) { + assert(D.Kind == Designator::ArrayRangeDesignator && + "Requires array range designator"); + char* Ptr = static_cast<char*>(static_cast<void *>(this)); + Ptr += sizeof(DesignatedInitExpr); + Ptr += sizeof(Designator) * NumDesignators; + Stmt **SubExprs = reinterpret_cast<Stmt**>(reinterpret_cast<void**>(Ptr)); + return cast<Expr>(*(SubExprs + D.ArrayOrRange.Index + 2)); +} + +//===----------------------------------------------------------------------===// // ExprIterator. //===----------------------------------------------------------------------===// @@ -1533,6 +1633,17 @@ Stmt::child_iterator InitListExpr::child_end() { return InitExprs.size() ? &InitExprs[0] + InitExprs.size() : 0; } +/// DesignatedInitExpr +Stmt::child_iterator DesignatedInitExpr::child_begin() { + char* Ptr = static_cast<char*>(static_cast<void *>(this)); + Ptr += sizeof(DesignatedInitExpr); + Ptr += sizeof(Designator) * NumDesignators; + return reinterpret_cast<Stmt**>(reinterpret_cast<void**>(Ptr)); +} +Stmt::child_iterator DesignatedInitExpr::child_end() { + return child_iterator(&*child_begin() + NumSubExprs); +} + // ObjCStringLiteral Stmt::child_iterator ObjCStringLiteral::child_begin() { return child_iterator(); diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp index a3a16aec5b..80de5b8ae4 100644 --- a/lib/AST/StmtPrinter.cpp +++ b/lib/AST/StmtPrinter.cpp @@ -877,6 +877,10 @@ void StmtPrinter::VisitInitListExpr(InitListExpr* Node) { OS << " }"; } +void StmtPrinter::VisitDesignatedInitExpr(DesignatedInitExpr *Node) { + // FIXME! +} + void StmtPrinter::VisitVAArgExpr(VAArgExpr *Node) { OS << "va_arg("; PrintExpr(Node->getSubExpr()); diff --git a/lib/Parse/ParseInit.cpp b/lib/Parse/ParseInit.cpp index ff73b0b9e1..b5d0ec05db 100644 --- a/lib/Parse/ParseInit.cpp +++ b/lib/Parse/ParseInit.cpp @@ -68,13 +68,16 @@ ParseInitializerWithPotentialDesignator(InitListDesignations &Designations, if (Tok.is(tok::identifier)) { Diag(Tok, diag::ext_gnu_old_style_field_designator); - Designation &D = Designations.CreateDesignation(InitNum); - D.AddDesignator(Designator::getField(Tok.getIdentifierInfo())); - ConsumeToken(); // Eat the identifier. + const IdentifierInfo *FieldName = Tok.getIdentifierInfo(); + SourceLocation NameLoc = ConsumeToken(); // Eat the identifier. assert(Tok.is(tok::colon) && "MayBeDesignationStart not working properly!"); - ConsumeToken(); - return ParseInitializer(); + SourceLocation ColonLoc = ConsumeToken(); + + Designation &D = Designations.CreateDesignation(InitNum); + D.AddDesignator(Designator::getField(FieldName, SourceLocation(), NameLoc)); + return Actions.ActOnDesignatedInitializer(D, ColonLoc, true, + ParseInitializer()); } // Desig - This is initialized when we see our first designator. We may have @@ -86,7 +89,7 @@ ParseInitializerWithPotentialDesignator(InitListDesignations &Designations, while (Tok.is(tok::period) || Tok.is(tok::l_square)) { if (Tok.is(tok::period)) { // designator: '.' identifier - ConsumeToken(); + SourceLocation DotLoc = ConsumeToken(); // Create designation if we haven't already. if (Desig == 0) @@ -97,7 +100,8 @@ ParseInitializerWithPotentialDesignator(InitListDesignations &Designations, return ExprError(); } - Desig->AddDesignator(Designator::getField(Tok.getIdentifierInfo())); + Desig->AddDesignator(Designator::getField(Tok.getIdentifierInfo(), DotLoc, + Tok.getLocation())); ConsumeToken(); // Eat the identifier. continue; } @@ -179,11 +183,12 @@ ParseInitializerWithPotentialDesignator(InitListDesignations &Designations, // If this is a normal array designator, remember it. if (Tok.isNot(tok::ellipsis)) { - Desig->AddDesignator(Designator::getArray(Idx.release())); + Desig->AddDesignator(Designator::getArray(Idx.release(), + StartLoc)); } else { // Handle the gnu array range extension. Diag(Tok, diag::ext_gnu_array_range); - ConsumeToken(); + SourceLocation EllipsisLoc = ConsumeToken(); OwningExprResult RHS(ParseConstantExpression()); if (RHS.isInvalid()) { @@ -191,10 +196,12 @@ ParseInitializerWithPotentialDesignator(InitListDesignations &Designations, return move(RHS); } Desig->AddDesignator(Designator::getArrayRange(Idx.release(), - RHS.release())); + RHS.release(), + StartLoc, EllipsisLoc)); } - MatchRHSPunctuation(tok::r_square, StartLoc); + SourceLocation EndLoc = MatchRHSPunctuation(tok::r_square, StartLoc); + Desig->getDesignator(Desig->getNumDesignators() - 1).setRBracketLoc(EndLoc); } // Okay, we're done with the designator sequence. We know that there must be @@ -205,8 +212,9 @@ ParseInitializerWithPotentialDesignator(InitListDesignations &Designations, // Handle a normal designator sequence end, which is an equal. if (Tok.is(tok::equal)) { - ConsumeToken(); - return ParseInitializer(); + SourceLocation EqualLoc = ConsumeToken(); + return Actions.ActOnDesignatedInitializer(*Desig, EqualLoc, false, + ParseInitializer()); } // We read some number of designators and found something that isn't an = or @@ -274,7 +282,7 @@ Parser::OwningExprResult Parser::ParseBraceInitializer() { // If we had an erroneous initializer, and we had a potentially valid // designator, make sure to remove the designator from // InitExprDesignations, otherwise we'll end up with a designator with no - // making initializer. + // matching initializer. if (SubElt.isInvalid()) InitExprDesignations.EraseDesignation(InitExprs.size()); } diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp index 423b049124..a8cc404907 100644 --- a/lib/Sema/Sema.cpp +++ b/lib/Sema/Sema.cpp @@ -179,10 +179,10 @@ void Sema::ImpCastExprToType(Expr *&Expr, QualType Ty, bool isLvalue) { } void Sema::DeleteExpr(ExprTy *E) { - static_cast<Expr*>(E)->Destroy(Context); + if (E) static_cast<Expr*>(E)->Destroy(Context); } void Sema::DeleteStmt(StmtTy *S) { - static_cast<Stmt*>(S)->Destroy(Context); + if (S) static_cast<Stmt*>(S)->Destroy(Context); } /// ActOnEndOfTranslationUnit - This is called at the very end of the diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 49e3eb8b5c..b574dc360e 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -43,6 +43,7 @@ namespace clang { class Stmt; class Expr; class InitListExpr; + class DesignatedInitExpr; class CallExpr; class DeclRefExpr; class VarDecl; @@ -1043,6 +1044,11 @@ public: InitListDesignations &Designators, SourceLocation RParenLoc); + virtual OwningExprResult ActOnDesignatedInitializer(Designation &Desig, + SourceLocation Loc, + bool UsedColonSyntax, + OwningExprResult Init); + virtual OwningExprResult ActOnBinOp(Scope *S, SourceLocation TokLoc, tok::TokenKind Kind, ExprArg LHS, ExprArg RHS); @@ -1833,15 +1839,17 @@ class InitListChecker { void CheckListElementTypes(InitListExpr *IList, QualType &DeclType, unsigned &Index); void CheckSubElementType(InitListExpr *IList, QualType ElemType, - unsigned &Index); + Expr *expr, unsigned &Index); // FIXME: Does DeclType need to be a reference type? void CheckScalarType(InitListExpr *IList, QualType &DeclType, - unsigned &Index); + Expr *expr, unsigned &Index); void CheckVectorType(InitListExpr *IList, QualType DeclType, unsigned &Index); void CheckStructUnionTypes(InitListExpr *IList, QualType DeclType, unsigned &Index); void CheckArrayType(InitListExpr *IList, QualType &DeclType, unsigned &Index); - + bool CheckDesignatedInitializer(InitListExpr *IList, DesignatedInitExpr *DIE, + QualType DeclType, FieldDecl *&DesignatedField, + llvm::APSInt &DesignatedIndex, unsigned &Index); int numArrayElements(QualType DeclType); int numStructUnionElements(QualType DeclType); public: diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index c1741da3b6..dbf1e7b416 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -2184,6 +2184,9 @@ bool Sema::CheckArithmeticConstantExpression(const Expr* Init) { } bool Sema::CheckForConstantInitializer(Expr *Init, QualType DclT) { + if (DesignatedInitExpr *DIE = dyn_cast<DesignatedInitExpr>(Init)) + Init = DIE->getInit(); + Init = Init->IgnoreParens(); if (Init->isEvaluatable(Context)) diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index f9c91ecaab..163dac94b9 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -12,13 +12,14 @@ //===----------------------------------------------------------------------===// #include "Sema.h" +#include "clang/Parse/Designator.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Expr.h" #include "clang/Basic/Diagnostic.h" #include <algorithm> // for std::count_if #include <functional> // for std::mem_fun -namespace clang { +using namespace clang; InitListChecker::InitListChecker(Sema *S, InitListExpr *IL, QualType &T) { hadError = false; @@ -131,7 +132,7 @@ void InitListChecker::CheckListElementTypes(InitListExpr *IList, QualType &DeclType, unsigned &Index) { if (DeclType->isScalarType()) { - CheckScalarType(IList, DeclType, Index); + CheckScalarType(IList, DeclType, 0, Index); } else if (DeclType->isVectorType()) { CheckVectorType(IList, DeclType, Index); } else if (DeclType->isAggregateType() || DeclType->isUnionType()) { @@ -156,8 +157,8 @@ void InitListChecker::CheckListElementTypes(InitListExpr *IList, void InitListChecker::CheckSubElementType(InitListExpr *IList, QualType ElemType, + Expr *expr, unsigned &Index) { - Expr* expr = IList->getInit(Index); if (InitListExpr *SubInitList = dyn_cast<InitListExpr>(expr)) { unsigned newIndex = 0; CheckExplicitInitList(SubInitList, ElemType, newIndex); @@ -167,7 +168,7 @@ void InitListChecker::CheckSubElementType(InitListExpr *IList, SemaRef->CheckStringLiteralInit(lit, ElemType); Index++; } else if (ElemType->isScalarType()) { - CheckScalarType(IList, ElemType, Index); + CheckScalarType(IList, ElemType, expr, Index); } else if (expr->getType()->getAsRecordType() && SemaRef->Context.typesAreCompatible( expr->getType().getUnqualifiedType(), @@ -180,10 +181,11 @@ void InitListChecker::CheckSubElementType(InitListExpr *IList, } } -void InitListChecker::CheckScalarType(InitListExpr *IList, QualType &DeclType, - unsigned &Index) { +void InitListChecker::CheckScalarType(InitListExpr *IList, QualType &DeclType, + Expr *expr, unsigned &Index) { if (Index < IList->getNumInits()) { - Expr* expr = IList->getInit(Index); + if (!expr) + expr = IList->getInit(Index); if (isa<InitListExpr>(expr)) { SemaRef->Diag(IList->getLocStart(), diag::err_many_braces_around_scalar_init) @@ -191,13 +193,26 @@ void InitListChecker::CheckScalarType(InitListExpr *IList, QualType &DeclType, hadError = true; ++Index; return; + } else if (isa<DesignatedInitExpr>(expr)) { + SemaRef->Diag(expr->getSourceRange().getBegin(), + diag::err_designator_for_scalar_init) + << DeclType << expr->getSourceRange(); + hadError = true; + ++Index; + return; } + Expr *savExpr = expr; // Might be promoted by CheckSingleInitializer. if (SemaRef->CheckSingleInitializer(expr, DeclType, false)) hadError = true; // types weren't compatible. - else if (savExpr != expr) + else if (savExpr != expr) { // The type was promoted, update initializer list. - IList->setInit(Index, expr); + if (DesignatedInitExpr *DIE + = dyn_cast<DesignatedInitExpr>(IList->getInit(Index))) + DIE->setInit(expr); + else + IList->setInit(Index, expr); + } ++Index; } else { SemaRef->Diag(IList->getLocStart(), diag::err_empty_scalar_initializer) @@ -218,7 +233,7 @@ void InitListChecker::CheckVectorType(InitListExpr *IList, QualType DeclType, // Don't attempt to go past the end of the init list if (Index >= IList->getNumInits()) break; - CheckSubElementType(IList, elementType, Index); + CheckSubElementType(IList, elementType, IList->getInit(Index), Index); } |