aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2009-01-22 00:58:24 +0000
committerDouglas Gregor <dgregor@apple.com>2009-01-22 00:58:24 +0000
commit05c13a3411782108d65aab3c77b1a231a4963bc0 (patch)
tree06c579135c022b061f4665e7607296b0920c9261
parentdb2868616b966c96a5014e58892c27cea377477c (diff)
Initial implementation of semantic analysis and ASTs for C99
designated initializers. This implementation should cover all of the constraints in C99 6.7.8, including long, complex designations and computing the size of incomplete array types initialized with a designated initializer. Please see the new test-case and holler if you find cases where this doesn't work. There are still some wrinkles with GNU's anonymous structs and anonymous unions (it isn't clear how these should work; we'll just follow GCC's lead) and with designated initializers for the members of a union. I'll tackle those very soon. CodeGen is still nonexistent, and there's some leftover code in the parser's representation of designators that I'll also need to clean up. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@62737 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/AST/Expr.h218
-rw-r--r--include/clang/AST/StmtNodes.def1
-rw-r--r--include/clang/Basic/DiagnosticKinds.def22
-rw-r--r--include/clang/Parse/Action.h21
-rw-r--r--include/clang/Parse/Designator.h65
-rw-r--r--lib/AST/Expr.cpp111
-rw-r--r--lib/AST/StmtPrinter.cpp4
-rw-r--r--lib/Parse/ParseInit.cpp36
-rw-r--r--lib/Sema/Sema.cpp4
-rw-r--r--lib/Sema/Sema.h14
-rw-r--r--lib/Sema/SemaDecl.cpp3
-rw-r--r--lib/Sema/SemaInit.cpp391
-rw-r--r--test/Sema/designated-initializers.c78
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;
+ } e