SemaInit.cpp revision 09f41cf63f4df0bf4e98ee473e44e9a95b68f0ff
1//===--- SemaInit.cpp - Semantic Analysis for Initializers ----------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10//  This file implements semantic analysis for initializers.
11//
12//===----------------------------------------------------------------------===//
13
14#include "Sema.h"
15#include "clang/AST/ASTContext.h"
16#include "clang/AST/Expr.h"
17#include "clang/Basic/Diagnostic.h"
18#include <algorithm> // for std::count_if
19#include <functional> // for std::mem_fun
20
21namespace clang {
22
23InitListChecker::InitListChecker(Sema *S, InitListExpr *IL, QualType &T) {
24  hadError = false;
25  SemaRef = S;
26
27  unsigned newIndex = 0;
28
29  CheckExplicitInitList(IL, T, newIndex);
30}
31
32int InitListChecker::numArrayElements(QualType DeclType) {
33  // FIXME: use a proper constant
34  int maxElements = 0x7FFFFFFF;
35  if (const ConstantArrayType *CAT =
36        SemaRef->Context.getAsConstantArrayType(DeclType)) {
37    maxElements = static_cast<int>(CAT->getSize().getZExtValue());
38  }
39  return maxElements;
40}
41
42int InitListChecker::numStructUnionElements(QualType DeclType) {
43  RecordDecl *structDecl = DeclType->getAsRecordType()->getDecl();
44  const int InitializableMembers
45    = std::count_if(structDecl->field_begin(), structDecl->field_end(),
46                    std::mem_fun(&FieldDecl::getDeclName));
47  if (structDecl->isUnion())
48    return std::min(InitializableMembers, 1);
49  return InitializableMembers - structDecl->hasFlexibleArrayMember();
50}
51
52void InitListChecker::CheckImplicitInitList(InitListExpr *ParentIList,
53                                            QualType T, unsigned &Index) {
54  llvm::SmallVector<Expr*, 4> InitExprs;
55  int maxElements = 0;
56
57  if (T->isArrayType())
58    maxElements = numArrayElements(T);
59  else if (T->isStructureType() || T->isUnionType())
60    maxElements = numStructUnionElements(T);
61  else if (T->isVectorType())
62    maxElements = T->getAsVectorType()->getNumElements();
63  else
64    assert(0 && "CheckImplicitInitList(): Illegal type");
65
66  if (maxElements == 0) {
67    SemaRef->Diag(ParentIList->getInit(Index)->getLocStart(),
68                  diag::err_implicit_empty_initializer);
69    hadError = true;
70    return;
71  }
72
73  // Check the element types *before* we create the implicit init list;
74  // otherwise, we might end up taking the wrong number of elements
75  unsigned NewIndex = Index;
76  CheckListElementTypes(ParentIList, T, NewIndex);
77
78  for (int i = 0; i < maxElements; ++i) {
79    // Don't attempt to go past the end of the init list
80    if (Index >= ParentIList->getNumInits())
81      break;
82    Expr* expr = ParentIList->getInit(Index);
83
84    // Add the expr to the new implicit init list and remove if from the old.
85    InitExprs.push_back(expr);
86    ParentIList->removeInit(Index);
87  }
88  // Synthesize an "implicit" InitListExpr (marked by the invalid source locs).
89  InitListExpr *ILE = new InitListExpr(SourceLocation(),
90                                       &InitExprs[0], InitExprs.size(),
91                                       SourceLocation(),
92                                       ParentIList->hadDesignators());
93  ILE->setType(T);
94
95  // Modify the parent InitListExpr to point to the implicit InitListExpr.
96  ParentIList->addInit(Index, ILE);
97}
98
99void InitListChecker::CheckExplicitInitList(InitListExpr *IList, QualType &T,
100                                            unsigned &Index) {
101  assert(IList->isExplicit() && "Illegal Implicit InitListExpr");
102
103  CheckListElementTypes(IList, T, Index);
104  IList->setType(T);
105  if (hadError)
106    return;
107
108  if (Index < IList->getNumInits()) {
109    // We have leftover initializers
110    if (IList->getNumInits() > 0 &&
111        SemaRef->IsStringLiteralInit(IList->getInit(Index), T)) {
112      // Special-case
113      SemaRef->Diag(IList->getInit(Index)->getLocStart(),
114                    diag::err_excess_initializers_in_char_array_initializer)
115        << IList->getInit(Index)->getSourceRange();
116      hadError = true;
117    } else if (!T->isIncompleteType()) {
118      // Don't warn for incomplete types, since we'll get an error elsewhere
119      SemaRef->Diag(IList->getInit(Index)->getLocStart(),
120                    diag::warn_excess_initializers)
121        << IList->getInit(Index)->getSourceRange();
122    }
123  }
124
125  if (T->isScalarType())
126    SemaRef->Diag(IList->getLocStart(), diag::warn_braces_around_scalar_init)
127      << IList->getSourceRange();
128}
129
130void InitListChecker::CheckListElementTypes(InitListExpr *IList,
131                                            QualType &DeclType,
132                                            unsigned &Index) {
133  if (DeclType->isScalarType()) {
134    CheckScalarType(IList, DeclType, Index);
135  } else if (DeclType->isVectorType()) {
136    CheckVectorType(IList, DeclType, Index);
137  } else if (DeclType->isAggregateType() || DeclType->isUnionType()) {
138    if (DeclType->isStructureType() || DeclType->isUnionType())
139      CheckStructUnionTypes(IList, DeclType, Index);
140    else if (DeclType->isArrayType())
141      CheckArrayType(IList, DeclType, Index);
142    else
143      assert(0 && "Aggregate that isn't a function or array?!");
144  } else if (DeclType->isVoidType() || DeclType->isFunctionType()) {
145    // This type is invalid, issue a diagnostic.
146    Index++;
147    SemaRef->Diag(IList->getLocStart(), diag::err_illegal_initializer_type)
148      << DeclType;
149    hadError = true;
150  } else {
151    // In C, all types are either scalars or aggregates, but
152    // additional handling is needed here for C++ (and possibly others?).
153    assert(0 && "Unsupported initializer type");
154  }
155}
156
157void InitListChecker::CheckSubElementType(InitListExpr *IList,
158                                          QualType ElemType,
159                                          unsigned &Index) {
160  Expr* expr = IList->getInit(Index);
161  if (InitListExpr *SubInitList = dyn_cast<InitListExpr>(expr)) {
162    unsigned newIndex = 0;
163    CheckExplicitInitList(SubInitList, ElemType, newIndex);
164    Index++;
165  } else if (StringLiteral *lit =
166             SemaRef->IsStringLiteralInit(expr, ElemType)) {
167    SemaRef->CheckStringLiteralInit(lit, ElemType);
168    Index++;
169  } else if (ElemType->isScalarType()) {
170    CheckScalarType(IList, ElemType, Index);
171  } else if (expr->getType()->getAsRecordType() &&
172             SemaRef->Context.typesAreCompatible(
173               expr->getType().getUnqualifiedType(),
174               ElemType.getUnqualifiedType())) {
175    Index++;
176    // FIXME: Add checking
177  } else {
178    CheckImplicitInitList(IList, ElemType, Index);
179    Index++;
180  }
181}
182
183void InitListChecker::CheckScalarType(InitListExpr *IList, QualType &DeclType,
184                                      unsigned &Index) {
185  if (Index < IList->getNumInits()) {
186    Expr* expr = IList->getInit(Index);
187    if (isa<InitListExpr>(expr)) {
188      SemaRef->Diag(IList->getLocStart(),
189                    diag::err_many_braces_around_scalar_init)
190        << IList->getSourceRange();
191      hadError = true;
192      ++Index;
193      return;
194    }
195    Expr *savExpr = expr; // Might be promoted by CheckSingleInitializer.
196    if (SemaRef->CheckSingleInitializer(expr, DeclType, false))
197      hadError = true; // types weren't compatible.
198    else if (savExpr != expr)
199      // The type was promoted, update initializer list.
200      IList->setInit(Index, expr);
201    ++Index;
202  } else {
203    SemaRef->Diag(IList->getLocStart(), diag::err_empty_scalar_initializer)
204      << IList->getSourceRange();
205    hadError = true;
206    return;
207  }
208}
209
210void InitListChecker::CheckVectorType(InitListExpr *IList, QualType DeclType,
211                                      unsigned &Index) {
212  if (Index < IList->getNumInits()) {
213    const VectorType *VT = DeclType->getAsVectorType();
214    int maxElements = VT->getNumElements();
215    QualType elementType = VT->getElementType();
216
217    for (int i = 0; i < maxElements; ++i) {
218      // Don't attempt to go past the end of the init list
219      if (Index >= IList->getNumInits())
220        break;
221      CheckSubElementType(IList, elementType, Index);
222    }
223  }
224}
225
226void InitListChecker::CheckArrayType(InitListExpr *IList, QualType &DeclType,
227                                     unsigned &Index) {
228  // Check for the special-case of initializing an array with a string.
229  if (Index < IList->getNumInits()) {
230    if (StringLiteral *lit =
231        SemaRef->IsStringLiteralInit(IList->getInit(Index), DeclType)) {
232      SemaRef->CheckStringLiteralInit(lit, DeclType);
233      ++Index;
234      return;
235    }
236  }
237  if (const VariableArrayType *VAT =
238        SemaRef->Context.getAsVariableArrayType(DeclType)) {
239    // Check for VLAs; in standard C it would be possible to check this
240    // earlier, but I don't know where clang accepts VLAs (gcc accepts
241    // them in all sorts of strange places).
242    SemaRef->Diag(VAT->getSizeExpr()->getLocStart(),
243                  diag::err_variable_object_no_init)
244      << VAT->getSizeExpr()->getSourceRange();
245    hadError = true;
246    return;
247  }
248
249  int maxElements = numArrayElements(DeclType);
250  QualType elementType = SemaRef->Context.getAsArrayType(DeclType)
251                             ->getElementType();
252  int numElements = 0;
253  for (int i = 0; i < maxElements; ++i, ++numElements) {
254    // Don't attempt to go past the end of the init list
255    if (Index >= IList->getNumInits())
256      break;
257    CheckSubElementType(IList, elementType, Index);
258  }
259  if (DeclType->isIncompleteArrayType()) {
260    // If this is an incomplete array type, the actual type needs to
261    // be calculated here.
262    if (numElements == 0) {
263      // Sizing an array implicitly to zero is not allowed by ISO C,
264      // but is supported by GNU.
265      SemaRef->Diag(IList->getLocStart(),
266                    diag::ext_typecheck_zero_array_size);
267    }
268
269    llvm::APSInt ConstVal(32);
270    ConstVal = numElements;
271    DeclType = SemaRef->Context.getConstantArrayType(elementType, ConstVal,
272                                                     ArrayType::Normal, 0);
273  }
274}
275
276void InitListChecker::CheckStructUnionTypes(InitListExpr *IList,
277                                            QualType DeclType,
278                                            unsigned &Index) {
279  RecordDecl* structDecl = DeclType->getAsRecordType()->getDecl();
280
281  // If the record is invalid, some of it's members are invalid. To avoid
282  // confusion, we forgo checking the intializer for the entire record.
283  if (structDecl->isInvalidDecl()) {
284    hadError = true;
285    return;
286  }
287  // If structDecl is a forward declaration, this loop won't do anything;
288  // That's okay, because an error should get printed out elsewhere. It
289  // might be worthwhile to skip over the rest of the initializer, though.
290  RecordDecl *RD = DeclType->getAsRecordType()->getDecl();
291  for (RecordDecl::field_iterator Field = RD->field_begin(),
292                               FieldEnd = RD->field_end();
293       Field != FieldEnd; ++Field) {
294    // If we've hit the flexible array member at the end, we're done.
295    if (Field->getType()->isIncompleteArrayType())
296      break;
297
298    // Don't attempt to go past the end of the init list
299    if (Index >= IList->getNumInits())
300      break;
301
302    if (!Field->getIdentifier()) {
303      // Don't initialize unnamed fields, e.g. "int : 20;"
304      continue;
305    }
306
307    CheckSubElementType(IList, Field->getType(), Index);
308    if (DeclType->isUnionType())
309      break;
310  }
311
312  // FIXME: Implement flexible array initialization GCC extension (it's a
313  // really messy extension to implement, unfortunately...the necessary
314  // information isn't actually even here!)
315}
316} // end namespace clang
317
318