diff options
Diffstat (limited to 'lib/Sema/SemaStmt.cpp')
-rw-r--r-- | lib/Sema/SemaStmt.cpp | 77 |
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)); } - |