aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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;
+ } 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);
}