//===--- SemaStmt.cpp - Semantic Analysis for Statements ------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements semantic analysis for statements.
//
//===----------------------------------------------------------------------===//
#include "Sema.h"
#include "clang/AST/APValue.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/Expr.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/Diagnostic.h"
using namespace clang;
Sema::OwningStmtResult Sema::ActOnExprStmt(ExprArg expr) {
Expr *E = static_cast<Expr*>(expr.release());
assert(E && "ActOnExprStmt(): missing expression");
// C99 6.8.3p2: The expression in an expression statement is evaluated as a
// void expression for its side effects. Conversion to void allows any
// operand, even incomplete types.
// Same thing in for stmt first clause (when expr) and third clause.
return Owned(static_cast<Stmt*>(E));
}
Sema::OwningStmtResult Sema::ActOnNullStmt(SourceLocation SemiLoc) {
return Owned(new NullStmt(SemiLoc));
}
Sema::OwningStmtResult Sema::ActOnDeclStmt(DeclTy *decl,
SourceLocation StartLoc,
SourceLocation EndLoc) {
if (decl == 0)
return StmtError();
ScopedDecl *SD = cast<ScopedDecl>(static_cast<Decl *>(decl));
// This is a temporary hack until we are always passing around
// DeclGroupRefs.
llvm::SmallVector<Decl*, 10> decls;
while (SD) {
ScopedDecl* d = SD;
SD = SD->getNextDeclarator();
d->setNextDeclarator(0);
decls.push_back(d);
}
assert (!decls.empty());
if (decls.size() == 1) {
DeclGroupOwningRef DG(*decls.begin());
return Owned(new DeclStmt(DG, StartLoc, EndLoc));
}
else {
DeclGroupOwningRef DG(DeclGroup::Create(Context, decls.size(), &decls[0]));
return Owned(new DeclStmt(DG, StartLoc, EndLoc));
}
}
Action::OwningStmtResult
Sema::ActOnCompoundStmt(SourceLocation L, SourceLocation R,
MultiStmtArg elts, bool isStmtExpr) {
unsigned NumElts = elts.size();
Stmt **Elts = reinterpret_cast<Stmt**>(elts.release());
// If we're in C89 mode, check that we don't have any decls after stmts. If
// so, emit an extension diagnostic.
if (!getLangOptions().C99 && !getLangOptions().CPlusPlus) {
// Note that __extension__ can be around a decl.
unsigned i = 0;
// Skip over all declarations.
for (; i != NumElts && isa<DeclStmt>(Elts[i]); ++i)
/*empty*/;
// We found the end of the list or a statement. Scan for another declstmt.
for (; i != NumElts && !isa<DeclStmt>(Elts[i]); ++i)
/*empty*/;
if (i != NumElts) {
ScopedDecl *D = *cast<DeclStmt>(Elts[i])->decl_begin();
Diag(D->getLocation(), diag::ext_mixed_decls_code);
}
}
// Warn about unused expressions in statements.
for (unsigned i = 0; i != NumElts; ++i) {
Expr *E = dyn_cast<Expr>(Elts[i]);
if (!E) continue;
// Warn about expressions with unused results.
if (E->hasLocalSideEffect() || E->getType()->isVoidType())
continue;
// The last expr in a stmt expr really is used.
if (isStmtExpr && i == NumElts-1)
continue;
/// DiagnoseDeadExpr - This expression is side-effect free and evaluated in
/// a context where the result is unused. Emit a diagnostic to warn about
/// this.
if (const BinaryOperator *BO = dyn_cast<BinaryOperator>(E))
Diag(BO->getOperatorLoc(), diag::warn_unused_expr)
<< BO->getLHS()->getSourceRange() << BO->getRHS()->getSourceRange();
else if (const UnaryOperator *UO = dyn_cast<UnaryOperator>(E))
Diag(UO->getOperatorLoc(), diag::warn_unused_expr)
<< UO->getSubExpr()->getSourceRange();
else
Diag(E->getExprLoc(), diag::warn_unused_expr) << E->getSourceRange();
}
return Owned(new CompoundStmt(Elts, NumElts, L, R));
}
Action::OwningStmtResult
Sema::ActOnCaseStmt(SourceLocation CaseLoc, ExprArg lhsval