diff options
author | rdivacky <rdivacky@FreeBSD.org> | 2010-02-16 09:31:36 +0000 |
---|---|---|
committer | rdivacky <rdivacky@FreeBSD.org> | 2010-02-16 09:31:36 +0000 |
commit | fd035e6496665b1f1197868e21cb0a4594e8db6e (patch) | |
tree | 53010172e19c77ea447bcd89e117cda052ab52e0 /lib/Sema/SemaStmt.cpp | |
parent | 2fce988e86bc01829142e4362d4eff1af0925147 (diff) | |
download | FreeBSD-src-fd035e6496665b1f1197868e21cb0a4594e8db6e.zip FreeBSD-src-fd035e6496665b1f1197868e21cb0a4594e8db6e.tar.gz |
Update clang to r96341.
Diffstat (limited to 'lib/Sema/SemaStmt.cpp')
-rw-r--r-- | lib/Sema/SemaStmt.cpp | 178 |
1 files changed, 149 insertions, 29 deletions
diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index 0c207fa..fa42634 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/lib/Sema/SemaStmt.cpp @@ -93,6 +93,15 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S) { if (isa<ObjCImplicitSetterGetterRefExpr>(E)) DiagID = diag::warn_unused_property_expr; + if (const CXXExprWithTemporaries *Temps = dyn_cast<CXXExprWithTemporaries>(E)) + E = Temps->getSubExpr(); + if (const CXXZeroInitValueExpr *Zero = dyn_cast<CXXZeroInitValueExpr>(E)) { + if (const RecordType *RecordT = Zero->getType()->getAs<RecordType>()) + if (CXXRecordDecl *RecordD = dyn_cast<CXXRecordDecl>(RecordT->getDecl())) + if (!RecordD->hasTrivialDestructor()) + return; + } + if (const CallExpr *CE = dyn_cast<CallExpr>(E)) { // If the callee has attribute pure, const, or warn_unused_result, warn with // a more specific message to make it clear what is happening. @@ -370,6 +379,22 @@ static bool CmpCaseVals(const std::pair<llvm::APSInt, CaseStmt*>& lhs, return false; } +/// CmpEnumVals - Comparison predicate for sorting enumeration values. +/// +static bool CmpEnumVals(const std::pair<llvm::APSInt, EnumConstantDecl*>& lhs, + const std::pair<llvm::APSInt, EnumConstantDecl*>& rhs) +{ + return lhs.first < rhs.first; +} + +/// EqEnumVals - Comparison preficate for uniqing enumeration values. +/// +static bool EqEnumVals(const std::pair<llvm::APSInt, EnumConstantDecl*>& lhs, + const std::pair<llvm::APSInt, EnumConstantDecl*>& rhs) +{ + return lhs.first == rhs.first; +} + /// GetTypeBeforeIntegralPromotion - Returns the pre-promotion type of /// potentially integral-promoted expression @p expr. static QualType GetTypeBeforeIntegralPromotion(const Expr* expr) { @@ -482,6 +507,16 @@ static bool CheckCXXSwitchCondition(Sema &S, SourceLocation SwitchLoc, return false; } +/// ActOnSwitchBodyError - This is called if there is an error parsing the +/// body of the switch stmt instead of ActOnFinishSwitchStmt. +void Sema::ActOnSwitchBodyError(SourceLocation SwitchLoc, StmtArg Switch, + StmtArg Body) { + // Keep the switch stack balanced. + assert(getSwitchStack().back() == (SwitchStmt*)Switch.get() && + "switch stack missing push/pop!"); + getSwitchStack().pop_back(); +} + Action::OwningStmtResult Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, StmtArg Switch, StmtArg Body) { @@ -550,7 +585,8 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, StmtArg Switch, CaseValsTy CaseVals; // Keep track of any GNU case ranges we see. The APSInt is the low value. - std::vector<std::pair<llvm::APSInt, CaseStmt*> > CaseRanges; + typedef std::vector<std::pair<llvm::APSInt, CaseStmt*> > CaseRangesTy; + CaseRangesTy CaseRanges; DefaultStmt *TheDefaultStmt = 0; @@ -713,6 +749,75 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, StmtArg Switch, } } } + + // Check to see if switch is over an Enum and handles all of its + // values + const EnumType* ET = dyn_cast<EnumType>(CondTypeBeforePromotion); + // If switch has default case, then ignore it. + if (!CaseListIsErroneous && !TheDefaultStmt && ET) { + const EnumDecl *ED = ET->getDecl(); + typedef llvm::SmallVector<std::pair<llvm::APSInt, EnumConstantDecl*>, 64> EnumValsTy; + EnumValsTy EnumVals; + + // Gather all enum values, set their type and sort them, allowing easier comparison + // with CaseVals. + for (EnumDecl::enumerator_iterator EDI = ED->enumerator_begin(); EDI != ED->enumerator_end(); EDI++) { + llvm::APSInt Val = (*EDI)->getInitVal(); + if(Val.getBitWidth() < CondWidth) + Val.extend(CondWidth); + Val.setIsSigned(CondIsSigned); + EnumVals.push_back(std::make_pair(Val, (*EDI))); + } + std::stable_sort(EnumVals.begin(), EnumVals.end(), CmpEnumVals); + EnumValsTy::iterator EIend = std::unique(EnumVals.begin(), EnumVals.end(), EqEnumVals); + // See which case values aren't in enum + EnumValsTy::const_iterator EI = EnumVals.begin(); + for (CaseValsTy::const_iterator CI = CaseVals.begin(); CI != CaseVals.end(); CI++) { + while (EI != EIend && EI->first < CI->first) + EI++; + if (EI == EIend || EI->first > CI->first) + Diag(CI->second->getLHS()->getExprLoc(), diag::not_in_enum) << ED->getDeclName(); + } + // See which of case ranges aren't in enum + EI = EnumVals.begin(); + for (CaseRangesTy::const_iterator RI = CaseRanges.begin(); RI != CaseRanges.end() && EI != EIend; RI++) { + while (EI != EIend && EI->first < RI->first) + EI++; + + if (EI == EIend || EI->first != RI->first) { + Diag(RI->second->getLHS()->getExprLoc(), diag::not_in_enum) << ED->getDeclName(); + } + + llvm::APSInt Hi = RI->second->getRHS()->EvaluateAsInt(Context); + while (EI != EIend && EI->first < Hi) + EI++; + if (EI == EIend || EI->first != Hi) + Diag(RI->second->getRHS()->getExprLoc(), diag::not_in_enum) << ED->getDeclName(); + } + //Check which enum vals aren't in switch + CaseValsTy::const_iterator CI = CaseVals.begin(); + CaseRangesTy::const_iterator RI = CaseRanges.begin(); + EI = EnumVals.begin(); + for (; EI != EIend; EI++) { + //Drop unneeded case values + llvm::APSInt CIVal; + while (CI != CaseVals.end() && CI->first < EI->first) + CI++; + + if (CI != CaseVals.end() && CI->first == EI->first) + continue; + + //Drop unneeded case ranges + for (; RI != CaseRanges.end(); RI++) { + llvm::APSInt Hi = RI->second->getRHS()->EvaluateAsInt(Context); + if (EI->first <= Hi) + break; + } + + if (RI == CaseRanges.end() || EI->first < RI->first) + Diag(CondExpr->getExprLoc(), diag::warn_missing_cases) << EI->second->getDeclName(); + } + } } // FIXME: If the case list was broken is some way, we don't have a good system @@ -863,7 +968,7 @@ Sema::ActOnObjCForCollectionStmt(SourceLocation ForLoc, << FirstType << First->getSourceRange(); } if (Second) { - DefaultFunctionArrayConversion(Second); + DefaultFunctionArrayLvalueConversion(Second); QualType SecondType = Second->getType(); if (!SecondType->isObjCObjectPointerType()) Diag(ForLoc, diag::err_collection_expr_type) @@ -896,10 +1001,10 @@ Sema::ActOnIndirectGotoStmt(SourceLocation GotoLoc, SourceLocation StarLoc, Expr* E = DestExp.takeAs<Expr>(); if (!E->isTypeDependent()) { QualType ETy = E->getType(); + QualType DestTy = Context.getPointerType(Context.VoidTy.withConst()); AssignConvertType ConvTy = - CheckSingleAssignmentConstraints(Context.VoidPtrTy, E); - if (DiagnoseAssignmentResult(ConvTy, StarLoc, Context.VoidPtrTy, ETy, - E, AA_Passing)) + CheckSingleAssignmentConstraints(DestTy, E); + if (DiagnoseAssignmentResult(ConvTy, StarLoc, DestTy, ETy, E, AA_Passing)) return StmtError(); } return Owned(new (Context) IndirectGotoStmt(GotoLoc, StarLoc, E)); @@ -937,7 +1042,7 @@ Sema::ActOnBlockReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { if (RetValExp) { // Don't call UsualUnaryConversions(), since we don't want to do // integer promotions here. - DefaultFunctionArrayConversion(RetValExp); + DefaultFunctionArrayLvalueConversion(RetValExp); CurBlock->ReturnType = RetValExp->getType(); if (BlockDeclRefExpr *CDRE = dyn_cast<BlockDeclRefExpr>(RetValExp)) { // We have to remove a 'const' added to copied-in variable which was @@ -981,11 +1086,19 @@ Sema::ActOnBlockReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { // In C++ the return statement is handled via a copy initialization. // the C version of which boils down to CheckSingleAssignmentConstraints. - // FIXME: Leaks RetValExp. - if (PerformCopyInitialization(RetValExp, FnRetType, AA_Returning)) + OwningExprResult Res = PerformCopyInitialization( + InitializedEntity::InitializeResult(ReturnLoc, + FnRetType), + SourceLocation(), + Owned(RetValExp)); + if (Res.isInvalid()) { + // FIXME: Cleanup temporaries here, anyway? return StmtError(); - - if (RetValExp) CheckReturnStackAddr(RetValExp, FnRetType, ReturnLoc); + } + + RetValExp = Res.takeAs<Expr>(); + if (RetValExp) + CheckReturnStackAddr(RetValExp, FnRetType, ReturnLoc); } return Owned(new (Context) ReturnStmt(ReturnLoc, RetValExp)); @@ -1025,7 +1138,8 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, ExprArg rex) { QualType FnRetType; if (const FunctionDecl *FD = getCurFunctionDecl()) { FnRetType = FD->getResultType(); - if (FD->hasAttr<NoReturnAttr>()) + if (FD->hasAttr<NoReturnAttr>() || + FD->getType()->getAs<FunctionType>()->getNoReturnAttr()) Diag(ReturnLoc, diag::warn_noreturn_function_has_return_expr) << getCurFunctionOrMethodDecl()->getDeclName(); } else if (ObjCMethodDecl *MD = getCurMethodDecl()) @@ -1121,6 +1235,10 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, ExprArg rex) { /// This method checks to see if the argument is an acceptable l-value and /// returns false if it is a case we can handle. static bool CheckAsmLValue(const Expr *E, Sema &S) { + // Type dependent expressions will be checked during instantiation. + if (E->isTypeDependent()) + return false; + if (E->isLvalue(S.Context) == Expr::LV_Valid) return false; // Cool, this is an lvalue. @@ -1148,7 +1266,7 @@ Sema::OwningStmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc, bool IsVolatile, unsigned NumOutputs, unsigned NumInputs, - std::string *Names, + IdentifierInfo **Names, MultiExprArg constraints, MultiExprArg exprs, ExprArg asmString, @@ -1175,9 +1293,11 @@ Sema::OwningStmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc, return StmtError(Diag(Literal->getLocStart(),diag::err_asm_wide_character) << Literal->getSourceRange()); - TargetInfo::ConstraintInfo Info(Literal->getStrData(), - Literal->getByteLength(), - Names[i]); + llvm::StringRef OutputName; + if (Names[i]) + OutputName = Names[i]->getName(); + + TargetInfo::ConstraintInfo Info(Literal->getString(), OutputName); if (!Context.Target.validateOutputConstraint(Info)) return StmtError(Diag(Literal->getLocStart(), diag::err_asm_invalid_output_constraint) @@ -1202,9 +1322,11 @@ Sema::OwningStmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc, return StmtError(Diag(Literal->getLocStart(),diag::err_asm_wide_character) << Literal->getSourceRange()); - TargetInfo::ConstraintInfo Info(Literal->getStrData(), - Literal->getByteLength(), - Names[i]); + llvm::StringRef InputName; + if (Names[i]) + InputName = Names[i]->getName(); + + TargetInfo::ConstraintInfo Info(Literal->getString(), InputName); if (!Context.Target.validateInputConstraint(OutputConstraintInfos.data(), NumOutputs, Info)) { return StmtError(Diag(Literal->getLocStart(), @@ -1232,7 +1354,7 @@ Sema::OwningStmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc, } } - DefaultFunctionArrayConversion(Exprs[i]); + DefaultFunctionArrayLvalueConversion(Exprs[i]); InputConstraintInfos.push_back(Info); } @@ -1244,11 +1366,9 @@ Sema::OwningStmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc, return StmtError(Diag(Literal->getLocStart(),diag::err_asm_wide_character) << Literal->getSourceRange()); - std::string Clobber(Literal->getStrData(), - Literal->getStrData() + - Literal->getByteLength()); + llvm::StringRef Clobber = Literal->getString(); - if (!Context.Target.isValidGCCRegisterName(Clobber.c_str())) + if (!Context.Target.isValidGCCRegisterName(Clobber)) return StmtError(Diag(Literal->getLocStart(), diag::err_asm_unknown_register_name) << Clobber); } @@ -1258,9 +1378,9 @@ Sema::OwningStmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc, asmString.release(); clobbers.release(); AsmStmt *NS = - new (Context) AsmStmt(AsmLoc, IsSimple, IsVolatile, MSAsm, NumOutputs, - NumInputs, Names, Constraints, Exprs, AsmString, - NumClobbers, Clobbers, RParenLoc); + new (Context) AsmStmt(Context, AsmLoc, IsSimple, IsVolatile, MSAsm, + NumOutputs, NumInputs, Names, Constraints, Exprs, + AsmString, NumClobbers, Clobbers, RParenLoc); // Validate the asm string, ensuring it makes sense given the operands we // have. llvm::SmallVector<AsmStmt::AsmStringPiece, 8> Pieces; @@ -1527,7 +1647,7 @@ Sema::ActOnCXXTryBlock(SourceLocation TryLoc, StmtArg TryBlock, CurFunctionNeedsScopeChecking = true; RawHandlers.release(); - return Owned(new (Context) CXXTryStmt(TryLoc, - static_cast<Stmt*>(TryBlock.release()), - Handlers, NumHandlers)); + return Owned(CXXTryStmt::Create(Context, TryLoc, + static_cast<Stmt*>(TryBlock.release()), + Handlers, NumHandlers)); } |