blob: 7333dd507b6635d1119b79c0c9b4129b09142eac [file] [log] [blame]
Reid Spencer5f016e22007-07-11 17:01:13 +00001//===--- SemaStmt.cpp - Semantic Analysis for Statements ------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file was developed by Chris Lattner and is distributed under
6// the University of Illinois Open Source License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file implements semantic analysis for statements.
11//
12//===----------------------------------------------------------------------===//
13
14#include "Sema.h"
15#include "clang/AST/Stmt.h"
16#include "clang/AST/Expr.h"
17#include "clang/Parse/Scope.h"
18#include "clang/Basic/Diagnostic.h"
19#include "clang/Basic/LangOptions.h"
20#include "clang/Lex/IdentifierTable.h"
21using namespace clang;
22
23Sema::StmtResult Sema::ParseExprStmt(ExprTy *expr) {
24 Expr *E = static_cast<Expr*>(expr);
25
26 // Exprs are statements, so there is no need to do a conversion here. However,
27 // diagnose some potentially bad code.
28 if (!E->hasLocalSideEffect())
29 Diag(E->getExprLoc(), diag::warn_unused_expr, E->getSourceRange());
30
31 return E;
32}
33
34
35Sema::StmtResult Sema::ParseNullStmt(SourceLocation SemiLoc) {
36 return new NullStmt(SemiLoc);
37}
38
39Sema::StmtResult Sema::ParseDeclStmt(DeclTy *decl) {
40 if (decl)
41 return new DeclStmt(static_cast<Decl *>(decl));
42 else
43 return true; // error
44}
45
46Action::StmtResult
47Sema::ParseCompoundStmt(SourceLocation L, SourceLocation R,
48 StmtTy **Elts, unsigned NumElts) {
49 return new CompoundStmt((Stmt**)Elts, NumElts);
50}
51
52Action::StmtResult
53Sema::ParseCaseStmt(SourceLocation CaseLoc, ExprTy *lhsval,
54 SourceLocation DotDotDotLoc, ExprTy *RHSVal,
55 SourceLocation ColonLoc, StmtTy *SubStmt) {
56 Expr *LHSVal = ((Expr *)lhsval);
57 assert((LHSVal != 0) && "missing expression in case statement");
58
59 SourceLocation ExpLoc;
60 // C99 6.8.4.2p3: The expression shall be an integer constant.
61 if (!LHSVal->isIntegerConstantExpr(&ExpLoc))
62 return Diag(ExpLoc, diag::err_case_label_not_integer_constant_expr,
63 LHSVal->getSourceRange());
64
65 // FIXME: SEMA for RHS of case range.
66
67 return new CaseStmt(LHSVal, (Expr*)RHSVal, (Stmt*)SubStmt);
68}
69
70Action::StmtResult
71Sema::ParseDefaultStmt(SourceLocation DefaultLoc,
72 SourceLocation ColonLoc, StmtTy *SubStmt) {
73 return new DefaultStmt((Stmt*)SubStmt);
74}
75
76Action::StmtResult
77Sema::ParseLabelStmt(SourceLocation IdentLoc, IdentifierInfo *II,
78 SourceLocation ColonLoc, StmtTy *SubStmt) {
79 // Look up the record for this label identifier.
80 LabelStmt *&LabelDecl = LabelMap[II];
81
82 // If not forward referenced or defined already, just create a new LabelStmt.
83 if (LabelDecl == 0)
84 return LabelDecl = new LabelStmt(IdentLoc, II, (Stmt*)SubStmt);
85
86 assert(LabelDecl->getID() == II && "Label mismatch!");
87
88 // Otherwise, this label was either forward reference or multiply defined. If
89 // multiply defined, reject it now.
90 if (LabelDecl->getSubStmt()) {
91 Diag(IdentLoc, diag::err_redefinition_of_label, LabelDecl->getName());
92 Diag(LabelDecl->getIdentLoc(), diag::err_previous_definition);
93 return (Stmt*)SubStmt;
94 }
95
96 // Otherwise, this label was forward declared, and we just found its real
97 // definition. Fill in the forward definition and return it.
98 LabelDecl->setIdentLoc(IdentLoc);
99 LabelDecl->setSubStmt((Stmt*)SubStmt);
100 return LabelDecl;
101}
102
103Action::StmtResult
104Sema::ParseIfStmt(SourceLocation IfLoc, ExprTy *CondVal,
105 StmtTy *ThenVal, SourceLocation ElseLoc,
106 StmtTy *ElseVal) {
107 Expr *condExpr = (Expr *)CondVal;
108 assert(condExpr && "ParseIfStmt(): missing expression");
109
Steve Naroff90045e82007-07-13 23:32:42 +0000110 QualType condType = DefaultFunctionArrayConversion(condExpr);
Reid Spencer5f016e22007-07-11 17:01:13 +0000111 assert(!condType.isNull() && "ParseIfStmt(): missing expression type");
112
113 if (!condType->isScalarType()) // C99 6.8.4.1p1
114 return Diag(IfLoc, diag::err_typecheck_statement_requires_scalar,
115 condType.getAsString(), condExpr->getSourceRange());
116
117 return new IfStmt(condExpr, (Stmt*)ThenVal, (Stmt*)ElseVal);
118}
119
120Action::StmtResult
121Sema::ParseSwitchStmt(SourceLocation SwitchLoc, ExprTy *Cond, StmtTy *Body) {
122 return new SwitchStmt((Expr*)Cond, (Stmt*)Body);
123}
124
125Action::StmtResult
126Sema::ParseWhileStmt(SourceLocation WhileLoc, ExprTy *Cond, StmtTy *Body) {
127 Expr *condExpr = (Expr *)Cond;
128 assert(condExpr && "ParseWhileStmt(): missing expression");
129
Steve Naroff90045e82007-07-13 23:32:42 +0000130 QualType condType = DefaultFunctionArrayConversion(condExpr);
Reid Spencer5f016e22007-07-11 17:01:13 +0000131 assert(!condType.isNull() && "ParseWhileStmt(): missing expression type");
132
133 if (!condType->isScalarType()) // C99 6.8.5p2
134 return Diag(WhileLoc, diag::err_typecheck_statement_requires_scalar,
135 condType.getAsString(), condExpr->getSourceRange());
136
137 return new WhileStmt(condExpr, (Stmt*)Body);
138}
139
140Action::StmtResult
141Sema::ParseDoStmt(SourceLocation DoLoc, StmtTy *Body,
142 SourceLocation WhileLoc, ExprTy *Cond) {
143 Expr *condExpr = (Expr *)Cond;
144 assert(condExpr && "ParseDoStmt(): missing expression");
145
Steve Naroff90045e82007-07-13 23:32:42 +0000146 QualType condType = DefaultFunctionArrayConversion(condExpr);
Reid Spencer5f016e22007-07-11 17:01:13 +0000147 assert(!condType.isNull() && "ParseDoStmt(): missing expression type");
148
149 if (!condType->isScalarType()) // C99 6.8.5p2
150 return Diag(DoLoc, diag::err_typecheck_statement_requires_scalar,
151 condType.getAsString(), condExpr->getSourceRange());
152
153 return new DoStmt((Stmt*)Body, condExpr);
154}
155
156Action::StmtResult
157Sema::ParseForStmt(SourceLocation ForLoc, SourceLocation LParenLoc,
158 StmtTy *First, ExprTy *Second, ExprTy *Third,
159 SourceLocation RParenLoc, StmtTy *Body) {
160 if (First) {
161 // C99 6.8.5p3: FIXME. Need to hack Parser::ParseForStatement() and
162 // declaration support to create a DeclStmt node. Once this is done,
163 // we can test for DeclStmt vs. Expr (already a sub-class of Stmt).
164 }
165 if (Second) {
166 Expr *testExpr = (Expr *)Second;
Steve Naroff90045e82007-07-13 23:32:42 +0000167 QualType testType = DefaultFunctionArrayConversion(testExpr);
Reid Spencer5f016e22007-07-11 17:01:13 +0000168 assert(!testType.isNull() && "ParseForStmt(): missing test expression type");
169
170 if (!testType->isScalarType()) // C99 6.8.5p2
171 return Diag(ForLoc, diag::err_typecheck_statement_requires_scalar,
172 testType.getAsString(), testExpr->getSourceRange());
173 }
174 return new ForStmt((Stmt*)First, (Expr*)Second, (Expr*)Third, (Stmt*)Body);
175}
176
177
178Action::StmtResult
179Sema::ParseGotoStmt(SourceLocation GotoLoc, SourceLocation LabelLoc,
180 IdentifierInfo *LabelII) {
181 // Look up the record for this label identifier.
182 LabelStmt *&LabelDecl = LabelMap[LabelII];
183
184 // If we haven't seen this label yet, create a forward reference.
185 if (LabelDecl == 0)
186 LabelDecl = new LabelStmt(LabelLoc, LabelII, 0);
187
188 return new GotoStmt(LabelDecl);
189}
190
191Action::StmtResult
192Sema::ParseIndirectGotoStmt(SourceLocation GotoLoc,SourceLocation StarLoc,
193 ExprTy *DestExp) {
194 // FIXME: Verify that the operand is convertible to void*.
195
196 return new IndirectGotoStmt((Expr*)DestExp);
197}
198
199Action::StmtResult
200Sema::ParseContinueStmt(SourceLocation ContinueLoc, Scope *CurScope) {
201 Scope *S = CurScope->getContinueParent();
202 if (!S) {
203 // C99 6.8.6.2p1: A break shall appear only in or as a loop body.
204 Diag(ContinueLoc, diag::err_continue_not_in_loop);
205 return true;
206 }
207
208 // FIXME: Remember that this continue goes with this loop.
209 return new ContinueStmt();
210}
211
212Action::StmtResult
213Sema::ParseBreakStmt(SourceLocation BreakLoc, Scope *CurScope) {
214 Scope *S = CurScope->getBreakParent();
215 if (!S) {
216 // C99 6.8.6.3p1: A break shall appear only in or as a switch/loop body.
217 Diag(BreakLoc, diag::err_break_not_in_loop_or_switch);
218 return true;
219 }
220
221 // FIXME: Remember that this break goes with this loop/switch.
222 return new BreakStmt();
223}
224
225
226Action::StmtResult
Steve Naroff90045e82007-07-13 23:32:42 +0000227Sema::ParseReturnStmt(SourceLocation ReturnLoc, ExprTy *rex) {
228 Expr *RetValExp = static_cast<Expr *>(rex);
Reid Spencer5f016e22007-07-11 17:01:13 +0000229 QualType lhsType = CurFunctionDecl->getResultType();
230
231 if (lhsType->isVoidType()) {
232 if (RetValExp) // C99 6.8.6.4p1 (ext_ since GCC warns)
233 Diag(ReturnLoc, diag::ext_return_has_expr,
234 CurFunctionDecl->getIdentifier()->getName(),
Steve Naroff90045e82007-07-13 23:32:42 +0000235 RetValExp->getSourceRange());
236 return new ReturnStmt(RetValExp);
Reid Spencer5f016e22007-07-11 17:01:13 +0000237 } else {
238 if (!RetValExp) {
239 const char *funcName = CurFunctionDecl->getIdentifier()->getName();
240 if (getLangOptions().C99) // C99 6.8.6.4p1 (ext_ since GCC warns)
241 Diag(ReturnLoc, diag::ext_return_missing_expr, funcName);
242 else // C90 6.6.6.4p4
243 Diag(ReturnLoc, diag::warn_return_missing_expr, funcName);
244 return new ReturnStmt((Expr*)0);
245 }
246 }
247 // we have a non-void function with an expression, continue checking
Steve Naroff90045e82007-07-13 23:32:42 +0000248 QualType rhsType = RetValExp->getType();
Reid Spencer5f016e22007-07-11 17:01:13 +0000249
250 if (lhsType == rhsType) // common case, fast path...
Steve Naroff90045e82007-07-13 23:32:42 +0000251 return new ReturnStmt(RetValExp);
Reid Spencer5f016e22007-07-11 17:01:13 +0000252
253 // C99 6.8.6.4p3(136): The return statement is not an assignment. The
254 // overlap restriction of subclause 6.5.16.1 does not apply to the case of
255 // function return.
Steve Naroff90045e82007-07-13 23:32:42 +0000256 AssignmentCheckResult result = CheckSingleAssignmentConstraints(lhsType,
257 RetValExp);
Reid Spencer5f016e22007-07-11 17:01:13 +0000258 bool hadError = false;
259
260 // decode the result (notice that extensions still return a type).
261 switch (result) {
262 case Compatible:
263 break;
264 case Incompatible:
265 Diag(ReturnLoc, diag::err_typecheck_return_incompatible,
266 lhsType.getAsString(), rhsType.getAsString(),
Steve Naroff90045e82007-07-13 23:32:42 +0000267 RetValExp->getSourceRange());
Reid Spencer5f016e22007-07-11 17:01:13 +0000268 hadError = true;
269 break;
270 case PointerFromInt:
271 // check for null pointer constant (C99 6.3.2.3p3)
Steve Naroff90045e82007-07-13 23:32:42 +0000272 if (!RetValExp->isNullPointerConstant()) {
Reid Spencer5f016e22007-07-11 17:01:13 +0000273 Diag(ReturnLoc, diag::ext_typecheck_return_pointer_int,
274 lhsType.getAsString(), rhsType.getAsString(),
Steve Naroff90045e82007-07-13 23:32:42 +0000275 RetValExp->getSourceRange());
Reid Spencer5f016e22007-07-11 17:01:13 +0000276 }
277 break;
278 case IntFromPointer:
279 Diag(ReturnLoc, diag::ext_typecheck_return_pointer_int,
280 lhsType.getAsString(), rhsType.getAsString(),
Steve Naroff90045e82007-07-13 23:32:42 +0000281 RetValExp->getSourceRange());
Reid Spencer5f016e22007-07-11 17:01:13 +0000282 break;
283 case IncompatiblePointer:
284 Diag(ReturnLoc, diag::ext_typecheck_return_incompatible_pointer,
285 lhsType.getAsString(), rhsType.getAsString(),
Steve Naroff90045e82007-07-13 23:32:42 +0000286 RetValExp->getSourceRange());
Reid Spencer5f016e22007-07-11 17:01:13 +0000287 break;
288 case CompatiblePointerDiscardsQualifiers:
289 Diag(ReturnLoc, diag::ext_typecheck_return_discards_qualifiers,
290 lhsType.getAsString(), rhsType.getAsString(),
Steve Naroff90045e82007-07-13 23:32:42 +0000291 RetValExp->getSourceRange());
Reid Spencer5f016e22007-07-11 17:01:13 +0000292 break;
293 }
294 return new ReturnStmt((Expr*)RetValExp);
295}
296