summaryrefslogtreecommitdiffstats
path: root/lib/Sema/SemaStmt.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Sema/SemaStmt.cpp')
-rw-r--r--lib/Sema/SemaStmt.cpp77
1 files changed, 64 insertions, 13 deletions
diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp
index d7c0a54..65f431d 100644
--- a/lib/Sema/SemaStmt.cpp
+++ b/lib/Sema/SemaStmt.cpp
@@ -66,8 +66,30 @@ void Sema::ActOnForEachDeclStmt(DeclGroupPtrTy dg) {
// If we have an invalid decl, just return.
if (DG.isNull() || !DG.isSingleDecl()) return;
+ VarDecl *var = cast<VarDecl>(DG.getSingleDecl());
+
// suppress any potential 'unused variable' warning.
- DG.getSingleDecl()->setUsed();
+ var->setUsed();
+
+ // foreach variables are never actually initialized in the way that
+ // the parser came up with.
+ var->setInit(0);
+
+ // In ARC, we don't need to retain the iteration variable of a fast
+ // enumeration loop. Rather than actually trying to catch that
+ // during declaration processing, we remove the consequences here.
+ if (getLangOptions().ObjCAutoRefCount) {
+ QualType type = var->getType();
+
+ // Only do this if we inferred the lifetime. Inferred lifetime
+ // will show up as a local qualifier because explicit lifetime
+ // should have shown up as an AttributedType instead.
+ if (type.getLocalQualifiers().getObjCLifetime() == Qualifiers::OCL_Strong) {
+ // Add 'const' and mark the variable as pseudo-strong.
+ var->setType(type.withConst());
+ var->setARCPseudoStrong(true);
+ }
+ }
}
void Sema::DiagnoseUnusedExprResult(const Stmt *S) {
@@ -114,6 +136,10 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S) {
}
}
} else if (const ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(E)) {
+ if (getLangOptions().ObjCAutoRefCount && ME->isDelegateInitCall()) {
+ Diag(Loc, diag::err_arc_unused_init_message) << R1;
+ return;
+ }
const ObjCMethodDecl *MD = ME->getMethodDecl();
if (MD && MD->getAttr<WarnUnusedResultAttr>()) {
Diag(Loc, diag::warn_unused_call) << R1 << R2 << "warn_unused_result";
@@ -951,14 +977,13 @@ Sema::ActOnObjCForCollectionStmt(SourceLocation ForLoc,
return StmtError(Diag((*DS->decl_begin())->getLocation(),
diag::err_toomany_element_decls));
- Decl *D = DS->getSingleDecl();
- FirstType = cast<ValueDecl>(D)->getType();
+ VarDecl *D = cast<VarDecl>(DS->getSingleDecl());
+ FirstType = D->getType();
// C99 6.8.5p3: The declaration part of a 'for' statement shall only
// declare identifiers for objects having storage class 'auto' or
// 'register'.
- VarDecl *VD = cast<VarDecl>(D);
- if (VD->isLocalVarDecl() && !VD->hasLocalStorage())
- return StmtError(Diag(VD->getLocation(),
+ if (!D->hasLocalStorage())
+ return StmtError(Diag(D->getLocation(),
diag::err_non_variable_decl_in_for));
} else {
Expr *FirstE = cast<Expr>(First);
@@ -1047,6 +1072,13 @@ static bool FinishForRangeVarDecl(Sema &SemaRef, VarDecl *Decl, Expr *Init,
Decl->setTypeSourceInfo(InitTSI);
Decl->setType(InitTSI->getType());
+ // In ARC, infer lifetime.
+ // FIXME: ARC may want to turn this into 'const __unsafe_unretained' if
+ // we're doing the equivalent of fast iteration.
+ if (SemaRef.getLangOptions().ObjCAutoRefCount &&
+ SemaRef.inferObjCARCLifetime(Decl))
+ Decl->setInvalidDecl();
+
SemaRef.AddInitializerToDecl(Decl, Init, /*DirectInit=*/false,
/*TypeMayContainAuto=*/false);
SemaRef.FinalizeDeclaration(Decl);
@@ -1374,6 +1406,9 @@ Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation ColonLoc,
if (LoopVar->isInvalidDecl())
NoteForRangeBeginEndFunction(*this, BeginExpr.get(), BEF_begin);
}
+ } else {
+ // The range is implicitly used as a placeholder when it is dependent.
+ RangeVar->setUsed();
}
return Owned(new (Context) CXXForRangeStmt(RangeDS,
@@ -1508,7 +1543,8 @@ ExprResult
Sema::PerformMoveOrCopyInitialization(const InitializedEntity &Entity,
const VarDecl *NRVOCandidate,
QualType ResultType,
- Expr *Value) {
+ Expr *Value,
+ bool AllowNRVO) {
// C++0x [class.copy]p33:
// When the criteria for elision of a copy operation are met or would
// be met save for the fact that the source object is a function
@@ -1516,7 +1552,8 @@ Sema::PerformMoveOrCopyInitialization(const InitializedEntity &Entity,
// overload resolution to select the constructor for the copy is first
// performed as if the object were designated by an rvalue.
ExprResult Res = ExprError();
- if (NRVOCandidate || getCopyElisionCandidate(ResultType, Value, true)) {
+ if (AllowNRVO &&
+ (NRVOCandidate || getCopyElisionCandidate(ResultType, Value, true))) {
ImplicitCastExpr AsRvalue(ImplicitCastExpr::OnStack,
Value->getType(), CK_LValueToRValue,
Value, VK_XValue);
@@ -1726,8 +1763,17 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
if (D != diag::ext_return_has_void_expr ||
!getLangOptions().CPlusPlus) {
NamedDecl *CurDecl = getCurFunctionOrMethodDecl();
+
+ int FunctionKind = 0;
+ if (isa<ObjCMethodDecl>(CurDecl))
+ FunctionKind = 1;
+ else if (isa<CXXConstructorDecl>(CurDecl))
+ FunctionKind = 2;
+ else if (isa<CXXDestructorDecl>(CurDecl))
+ FunctionKind = 3;
+
Diag(ReturnLoc, D)
- << CurDecl->getDeclName() << isa<ObjCMethodDecl>(CurDecl)
+ << CurDecl->getDeclName() << FunctionKind
<< RetValExp->getSourceRange();
}
}
@@ -1756,7 +1802,7 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
// overlap restriction of subclause 6.5.16.1 does not apply to the case of
// function return.
- // In C++ the return statement is handled via a copy initialization.
+ // In C++ the return statement is handled via a copy initialization,
// the C version of which boils down to CheckSingleAssignmentConstraints.
NRVOCandidate = getCopyElisionCandidate(FnRetType, RetValExp, false);
InitializedEntity Entity = InitializedEntity::InitializeResult(ReturnLoc,
@@ -1797,7 +1843,7 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
if (getLangOptions().CPlusPlus && FnRetType->isRecordType() &&
!CurContext->isDependentContext())
FunctionScopes.back()->Returns.push_back(Result);
-
+
return Owned(Result);
}
@@ -1955,7 +2001,7 @@ StmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc, bool IsSimple,
llvm::StringRef Clobber = Literal->getString();
- if (!Context.Target.isValidGCCRegisterName(Clobber))
+ if (!Context.Target.isValidClobber(Clobber))
return StmtError(Diag(Literal->getLocStart(),
diag::err_asm_unknown_register_name) << Clobber);
}
@@ -2179,6 +2225,12 @@ Sema::ActOnCXXCatchBlock(SourceLocation CatchLoc, Decl *ExDecl,
HandlerBlock));
}
+StmtResult
+Sema::ActOnObjCAutoreleasePoolStmt(SourceLocation AtLoc, Stmt *Body) {
+ getCurFunction()->setHasBranchProtectedScope();
+ return Owned(new (Context) ObjCAutoreleasePoolStmt(AtLoc, Body));
+}
+
namespace {
class TypeWithHandler {
@@ -2309,4 +2361,3 @@ Sema::ActOnSEHFinallyBlock(SourceLocation Loc,
assert(Block);
return Owned(SEHFinallyStmt::Create(Context,Loc,Block));
}
-
OpenPOWER on IntegriCloud