blob: 6a9275fbe8a649f285c75de631111ff7ba74bacc [file] [log] [blame]
Steve Naroff0cca7492008-05-01 22:18:59 +00001//===--- 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"
Daniel Dunbar12bc6922008-08-11 03:27:53 +000017#include "clang/Basic/Diagnostic.h"
Douglas Gregor44b43212008-12-11 16:49:14 +000018#include <algorithm> // for std::count_if
19#include <functional> // for std::mem_fun
Steve Naroff0cca7492008-05-01 22:18:59 +000020
21namespace clang {
22
23InitListChecker::InitListChecker(Sema *S, InitListExpr *IL, QualType &T) {
24 hadError = false;
25 SemaRef = S;
Eli Friedmanc9c0ea62008-05-19 20:00:43 +000026
Eli Friedmanb85f7072008-05-19 19:16:24 +000027 unsigned newIndex = 0;
Eli Friedmanc9c0ea62008-05-19 20:00:43 +000028
Eli Friedmanb85f7072008-05-19 19:16:24 +000029 CheckExplicitInitList(IL, T, newIndex);
Steve Naroff0cca7492008-05-01 22:18:59 +000030}
31
32int InitListChecker::numArrayElements(QualType DeclType) {
Eli Friedman638e1442008-05-25 13:22:35 +000033 // FIXME: use a proper constant
34 int maxElements = 0x7FFFFFFF;
Chris Lattnerc63a1f22008-08-04 07:31:14 +000035 if (const ConstantArrayType *CAT =
36 SemaRef->Context.getAsConstantArrayType(DeclType)) {
Steve Naroff0cca7492008-05-01 22:18:59 +000037 maxElements = static_cast<int>(CAT->getSize().getZExtValue());
38 }
39 return maxElements;
40}
41
42int InitListChecker::numStructUnionElements(QualType DeclType) {
43 RecordDecl *structDecl = DeclType->getAsRecordType()->getDecl();
Douglas Gregore267ff32008-12-11 20:41:00 +000044 const int InitializableMembers
Douglas Gregor44b43212008-12-11 16:49:14 +000045 = std::count_if(structDecl->field_begin(), structDecl->field_end(),
46 std::mem_fun(&FieldDecl::getDeclName));
Argyrios Kyrtzidis39ba4ae2008-06-09 23:19:58 +000047 if (structDecl->isUnion())
Eli Friedmanf84eda32008-05-25 14:03:31 +000048 return std::min(InitializableMembers, 1);
49 return InitializableMembers - structDecl->hasFlexibleArrayMember();
Steve Naroff0cca7492008-05-01 22:18:59 +000050}
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);
Eli Friedmanb85f7072008-05-19 19:16:24 +000061 else if (T->isVectorType())
62 maxElements = T->getAsVectorType()->getNumElements();
Steve Naroff0cca7492008-05-01 22:18:59 +000063 else
64 assert(0 && "CheckImplicitInitList(): Illegal type");
Eli Friedmanb85f7072008-05-19 19:16:24 +000065
Eli Friedman402256f2008-05-25 13:49:22 +000066 if (maxElements == 0) {
67 SemaRef->Diag(ParentIList->getInit(Index)->getLocStart(),
68 diag::err_implicit_empty_initializer);
69 hadError = true;
70 return;
71 }
72
Eli Friedmanb85f7072008-05-19 19:16:24 +000073 // 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
Steve Naroff0cca7492008-05-01 22:18:59 +000078 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(),
Chris Lattner418f6c72008-10-26 23:43:26 +000091 SourceLocation(),
92 ParentIList->hadDesignators());
Douglas Gregor83233a42009-01-07 21:26:07 +000093 ILE->setImplicit();
Steve Naroff0cca7492008-05-01 22:18:59 +000094 ILE->setType(T);
Eli Friedmanc9c0ea62008-05-19 20:00:43 +000095
Steve Naroff0cca7492008-05-01 22:18:59 +000096 // Modify the parent InitListExpr to point to the implicit InitListExpr.
97 ParentIList->addInit(Index, ILE);
Steve Naroff0cca7492008-05-01 22:18:59 +000098}
99
Steve Naroffa647caa2008-05-06 00:23:44 +0000100void InitListChecker::CheckExplicitInitList(InitListExpr *IList, QualType &T,
Steve Naroff0cca7492008-05-01 22:18:59 +0000101 unsigned &Index) {
Eli Friedmanc9c0ea62008-05-19 20:00:43 +0000102 assert(IList->isExplicit() && "Illegal Implicit InitListExpr");
Eli Friedmanc9c0ea62008-05-19 20:00:43 +0000103
Eli Friedmanb85f7072008-05-19 19:16:24 +0000104 CheckListElementTypes(IList, T, Index);
Steve Naroffa647caa2008-05-06 00:23:44 +0000105 IList->setType(T);
Eli Friedman638e1442008-05-25 13:22:35 +0000106 if (hadError)
107 return;
Eli Friedmanc9c0ea62008-05-19 20:00:43 +0000108
Eli Friedman638e1442008-05-25 13:22:35 +0000109 if (Index < IList->getNumInits()) {
Eli Friedmanc9c0ea62008-05-19 20:00:43 +0000110 // We have leftover initializers
111 if (IList->getNumInits() > 0 &&
112 SemaRef->IsStringLiteralInit(IList->getInit(Index), T)) {
Eli Friedmanbb504d32008-05-19 20:12:18 +0000113 // Special-case
Eli Friedmanc9c0ea62008-05-19 20:00:43 +0000114 SemaRef->Diag(IList->getInit(Index)->getLocStart(),
Chris Lattnerdcd5ef12008-11-19 05:27:50 +0000115 diag::err_excess_initializers_in_char_array_initializer)
116 << IList->getInit(Index)->getSourceRange();
Eli Friedmanc9c0ea62008-05-19 20:00:43 +0000117 hadError = true;
Eli Friedmand8dc2102008-05-20 05:25:56 +0000118 } else if (!T->isIncompleteType()) {
119 // Don't warn for incomplete types, since we'll get an error elsewhere
Eli Friedmanc9c0ea62008-05-19 20:00:43 +0000120 SemaRef->Diag(IList->getInit(Index)->getLocStart(),
Chris Lattnerdcd5ef12008-11-19 05:27:50 +0000121 diag::warn_excess_initializers)
122 << IList->getInit(Index)->getSourceRange();
Eli Friedmanc9c0ea62008-05-19 20:00:43 +0000123 }
124 }
Eli Friedmancda25a92008-05-19 20:20:43 +0000125
Eli Friedman638e1442008-05-25 13:22:35 +0000126 if (T->isScalarType())
Chris Lattnerdcd5ef12008-11-19 05:27:50 +0000127 SemaRef->Diag(IList->getLocStart(), diag::warn_braces_around_scalar_init)
128 << IList->getSourceRange();
Steve Naroff0cca7492008-05-01 22:18:59 +0000129}
130
Eli Friedmanb85f7072008-05-19 19:16:24 +0000131void InitListChecker::CheckListElementTypes(InitListExpr *IList,
132 QualType &DeclType,
133 unsigned &Index) {
Eli Friedmanc9c0ea62008-05-19 20:00:43 +0000134 if (DeclType->isScalarType()) {
Steve Naroff0cca7492008-05-01 22:18:59 +0000135 CheckScalarType(IList, DeclType, Index);
Eli Friedmanc9c0ea62008-05-19 20:00:43 +0000136 } else if (DeclType->isVectorType()) {
Steve Naroff0cca7492008-05-01 22:18:59 +0000137 CheckVectorType(IList, DeclType, Index);
Eli Friedmanc9c0ea62008-05-19 20:00:43 +0000138 } else if (DeclType->isAggregateType() || DeclType->isUnionType()) {
Steve Naroff0cca7492008-05-01 22:18:59 +0000139 if (DeclType->isStructureType() || DeclType->isUnionType())
140 CheckStructUnionTypes(IList, DeclType, Index);
141 else if (DeclType->isArrayType())
142 CheckArrayType(IList, DeclType, Index);
143 else
144 assert(0 && "Aggregate that isn't a function or array?!");
Steve Naroff61353522008-08-10 16:05:48 +0000145 } else if (DeclType->isVoidType() || DeclType->isFunctionType()) {
146 // This type is invalid, issue a diagnostic.
Eli Friedmand8dc2102008-05-20 05:25:56 +0000147 Index++;
Chris Lattnerf3a41af2008-11-20 06:38:18 +0000148 SemaRef->Diag(IList->getLocStart(), diag::err_illegal_initializer_type)
Chris Lattnerd1625842008-11-24 06:25:27 +0000149 << DeclType;
Eli Friedmand8dc2102008-05-20 05:25:56 +0000150 hadError = true;
Steve Naroff0cca7492008-05-01 22:18:59 +0000151 } else {
152 // In C, all types are either scalars or aggregates, but
153 // additional handling is needed here for C++ (and possibly others?).
154 assert(0 && "Unsupported initializer type");
155 }
156}
157
Eli Friedmanb85f7072008-05-19 19:16:24 +0000158void InitListChecker::CheckSubElementType(InitListExpr *IList,
159 QualType ElemType,
160 unsigned &Index) {
161 Expr* expr = IList->getInit(Index);
Eli Friedmanc9c0ea62008-05-19 20:00:43 +0000162 if (InitListExpr *SubInitList = dyn_cast<InitListExpr>(expr)) {
163 unsigned newIndex = 0;
164 CheckExplicitInitList(SubInitList, ElemType, newIndex);
165 Index++;
Eli Friedmanb85f7072008-05-19 19:16:24 +0000166 } else if (StringLiteral *lit =
167 SemaRef->IsStringLiteralInit(expr, ElemType)) {
168 SemaRef->CheckStringLiteralInit(lit, ElemType);
169 Index++;
Eli Friedmanc9c0ea62008-05-19 20:00:43 +0000170 } else if (ElemType->isScalarType()) {
171 CheckScalarType(IList, ElemType, Index);
Eli Friedmanb85f7072008-05-19 19:16:24 +0000172 } else if (expr->getType()->getAsRecordType() &&
Eli Friedmanc92e5e42008-06-09 03:52:40 +0000173 SemaRef->Context.typesAreCompatible(
174 expr->getType().getUnqualifiedType(),
175 ElemType.getUnqualifiedType())) {
Eli Friedmanb85f7072008-05-19 19:16:24 +0000176 Index++;
177 // FIXME: Add checking
178 } else {
179 CheckImplicitInitList(IList, ElemType, Index);
180 Index++;
181 }
182}
183
Steve Naroff0cca7492008-05-01 22:18:59 +0000184void InitListChecker::CheckScalarType(InitListExpr *IList, QualType &DeclType,
185 unsigned &Index) {
186 if (Index < IList->getNumInits()) {
187 Expr* expr = IList->getInit(Index);
Eli Friedmanc9c0ea62008-05-19 20:00:43 +0000188 if (isa<InitListExpr>(expr)) {
Eli Friedmanbb504d32008-05-19 20:12:18 +0000189 SemaRef->Diag(IList->getLocStart(),
Chris Lattnerdcd5ef12008-11-19 05:27:50 +0000190 diag::err_many_braces_around_scalar_init)
191 << IList->getSourceRange();
Eli Friedmanbb504d32008-05-19 20:12:18 +0000192 hadError = true;
193 ++Index;
194 return;
Steve Naroff0cca7492008-05-01 22:18:59 +0000195 }
Eli Friedmanc9c0ea62008-05-19 20:00:43 +0000196 Expr *savExpr = expr; // Might be promoted by CheckSingleInitializer.
197 if (SemaRef->CheckSingleInitializer(expr, DeclType))
Eli Friedmanbb504d32008-05-19 20:12:18 +0000198 hadError = true; // types weren't compatible.
Eli Friedmanc9c0ea62008-05-19 20:00:43 +0000199 else if (savExpr != expr)
200 // The type was promoted, update initializer list.
201 IList->setInit(Index, expr);
Steve Naroff0cca7492008-05-01 22:18:59 +0000202 ++Index;
Eli Friedmanbb504d32008-05-19 20:12:18 +0000203 } else {
Chris Lattnerdcd5ef12008-11-19 05:27:50 +0000204 SemaRef->Diag(IList->getLocStart(), diag::err_empty_scalar_initializer)
205 << IList->getSourceRange();
Eli Friedmanbb504d32008-05-19 20:12:18 +0000206 hadError = true;
207 return;
Steve Naroff0cca7492008-05-01 22:18:59 +0000208 }
Steve Naroff0cca7492008-05-01 22:18:59 +0000209}
210
211void InitListChecker::CheckVectorType(InitListExpr *IList, QualType DeclType,
212 unsigned &Index) {
213 if (Index < IList->getNumInits()) {
214 const VectorType *VT = DeclType->getAsVectorType();
215 int maxElements = VT->getNumElements();
216 QualType elementType = VT->getElementType();
217
218 for (int i = 0; i < maxElements; ++i) {
219 // Don't attempt to go past the end of the init list
220 if (Index >= IList->getNumInits())
221 break;
Eli Friedmanb85f7072008-05-19 19:16:24 +0000222 CheckSubElementType(IList, elementType, Index);
Steve Naroff0cca7492008-05-01 22:18:59 +0000223 }
224 }
225}
226
227void InitListChecker::CheckArrayType(InitListExpr *IList, QualType &DeclType,
228 unsigned &Index) {
229 // Check for the special-case of initializing an array with a string.
230 if (Index < IList->getNumInits()) {
231 if (StringLiteral *lit =
232 SemaRef->IsStringLiteralInit(IList->getInit(Index), DeclType)) {
233 SemaRef->CheckStringLiteralInit(lit, DeclType);
234 ++Index;
Steve Naroff0cca7492008-05-01 22:18:59 +0000235 return;
236 }
237 }
Chris Lattnerc63a1f22008-08-04 07:31:14 +0000238 if (const VariableArrayType *VAT =
239 SemaRef->Context.getAsVariableArrayType(DeclType)) {
Eli Friedman638e1442008-05-25 13:22:35 +0000240 // Check for VLAs; in standard C it would be possible to check this
241 // earlier, but I don't know where clang accepts VLAs (gcc accepts
242 // them in all sorts of strange places).
243 SemaRef->Diag(VAT->getSizeExpr()->getLocStart(),
Chris Lattnerdcd5ef12008-11-19 05:27:50 +0000244 diag::err_variable_object_no_init)
245 << VAT->getSizeExpr()->getSourceRange();
Eli Friedman638e1442008-05-25 13:22:35 +0000246 hadError = true;
247 return;
248 }
249
Steve Naroff0cca7492008-05-01 22:18:59 +0000250 int maxElements = numArrayElements(DeclType);
Chris Lattnerc63a1f22008-08-04 07:31:14 +0000251 QualType elementType = SemaRef->Context.getAsArrayType(DeclType)
252 ->getElementType();
Steve Naroff0cca7492008-05-01 22:18:59 +0000253 int numElements = 0;
254 for (int i = 0; i < maxElements; ++i, ++numElements) {
255 // Don't attempt to go past the end of the init list
256 if (Index >= IList->getNumInits())
257 break;
Eli Friedmanb85f7072008-05-19 19:16:24 +0000258 CheckSubElementType(IList, elementType, Index);
Steve Naroff0cca7492008-05-01 22:18:59 +0000259 }
260 if (DeclType->isIncompleteArrayType()) {
261 // If this is an incomplete array type, the actual type needs to
Daniel Dunbar396f0bf2008-08-18 20:28:46 +0000262 // be calculated here.
Steve Naroff0cca7492008-05-01 22:18:59 +0000263 if (numElements == 0) {
Daniel Dunbar396f0bf2008-08-18 20:28:46 +0000264 // Sizing an array implicitly to zero is not allowed by ISO C,
265 // but is supported by GNU.
Steve Naroff0cca7492008-05-01 22:18:59 +0000266 SemaRef->Diag(IList->getLocStart(),
Daniel Dunbar396f0bf2008-08-18 20:28:46 +0000267 diag::ext_typecheck_zero_array_size);
Steve Naroff0cca7492008-05-01 22:18:59 +0000268 }
Daniel Dunbar396f0bf2008-08-18 20:28:46 +0000269
270 llvm::APSInt ConstVal(32);
271 ConstVal = numElements;
272 DeclType = SemaRef->Context.getConstantArrayType(elementType, ConstVal,
273 ArrayType::Normal, 0);
Steve Naroff0cca7492008-05-01 22:18:59 +0000274 }
275}
276
277void InitListChecker::CheckStructUnionTypes(InitListExpr *IList,
278 QualType DeclType,
Eli Friedmanb85f7072008-05-19 19:16:24 +0000279 unsigned &Index) {
280 RecordDecl* structDecl = DeclType->getAsRecordType()->getDecl();
Steve Naroff0cca7492008-05-01 22:18:59 +0000281
Eli Friedmanb85f7072008-05-19 19:16:24 +0000282 // If the record is invalid, some of it's members are invalid. To avoid
283 // confusion, we forgo checking the intializer for the entire record.
284 if (structDecl->isInvalidDecl()) {
285 hadError = true;
286 return;
287 }
288 // If structDecl is a forward declaration, this loop won't do anything;
289 // That's okay, because an error should get printed out elsewhere. It
290 // might be worthwhile to skip over the rest of the initializer, though.
Douglas Gregor44b43212008-12-11 16:49:14 +0000291 RecordDecl *RD = DeclType->getAsRecordType()->getDecl();
292 for (RecordDecl::field_iterator Field = RD->field_begin(),
293 FieldEnd = RD->field_end();
294 Field != FieldEnd; ++Field) {
295 // If we've hit the flexible array member at the end, we're done.
296 if (Field->getType()->isIncompleteArrayType())
297 break;
298
Eli Friedmanb85f7072008-05-19 19:16:24 +0000299 // Don't attempt to go past the end of the init list
300 if (Index >= IList->getNumInits())
301 break;
Douglas Gregor44b43212008-12-11 16:49:14 +0000302
303 if (!Field->getIdentifier()) {
Eli Friedmanb85f7072008-05-19 19:16:24 +0000304 // Don't initialize unnamed fields, e.g. "int : 20;"
305 continue;
Steve Naroff0cca7492008-05-01 22:18:59 +0000306 }
Douglas Gregor44b43212008-12-11 16:49:14 +0000307
308 CheckSubElementType(IList, Field->getType(), Index);
Eli Friedmanb85f7072008-05-19 19:16:24 +0000309 if (DeclType->isUnionType())
310 break;
Steve Naroff0cca7492008-05-01 22:18:59 +0000311 }
Douglas Gregor44b43212008-12-11 16:49:14 +0000312
Eli Friedmanb85f7072008-05-19 19:16:24 +0000313 // FIXME: Implement flexible array initialization GCC extension (it's a
314 // really messy extension to implement, unfortunately...the necessary
315 // information isn't actually even here!)
Steve Naroff0cca7492008-05-01 22:18:59 +0000316}
317} // end namespace clang
318