diff options
Diffstat (limited to 'lib/Sema/SemaStmt.cpp')
-rw-r--r-- | lib/Sema/SemaStmt.cpp | 448 |
1 files changed, 281 insertions, 167 deletions
diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index 278e6d66828b..22ed93082065 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/lib/Sema/SemaStmt.cpp @@ -19,6 +19,7 @@ #include "clang/AST/EvaluatedExprVisitor.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" +#include "clang/AST/RecursiveASTVisitor.h" #include "clang/AST/StmtCXX.h" #include "clang/AST/StmtObjC.h" #include "clang/AST/TypeLoc.h" @@ -184,6 +185,12 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S) { const Expr *E = dyn_cast_or_null<Expr>(S); if (!E) return; + + // If we are in an unevaluated expression context, then there can be no unused + // results because the results aren't expected to be used in the first place. + if (isUnevaluatedContext()) + return; + SourceLocation ExprLoc = E->IgnoreParens()->getExprLoc(); // In most cases, we don't want to warn if the expression is written in a // macro body, or if the macro comes from a system header. If the offending @@ -364,6 +371,23 @@ Sema::ActOnCaseStmt(SourceLocation CaseLoc, Expr *LHSVal, return StmtError(); } + ExprResult LHS = + CorrectDelayedTyposInExpr(LHSVal, [this](class Expr *E) { + if (!getLangOpts().CPlusPlus11) + return VerifyIntegerConstantExpression(E); + if (Expr *CondExpr = + getCurFunction()->SwitchStack.back()->getCond()) { + QualType CondType = CondExpr->getType(); + llvm::APSInt TempVal; + return CheckConvertedConstantExpression(E, CondType, TempVal, + CCEK_CaseValue); + } + return ExprError(); + }); + if (LHS.isInvalid()) + return StmtError(); + LHSVal = LHS.get(); + if (!getLangOpts().CPlusPlus11) { // C99 6.8.4.2p3: The expression shall be an integer constant. // However, GCC allows any evaluatable integer expression. @@ -381,14 +405,19 @@ Sema::ActOnCaseStmt(SourceLocation CaseLoc, Expr *LHSVal, } } - LHSVal = ActOnFinishFullExpr(LHSVal, LHSVal->getExprLoc(), false, - getLangOpts().CPlusPlus11).get(); - if (RHSVal) - RHSVal = ActOnFinishFullExpr(RHSVal, RHSVal->getExprLoc(), false, - getLangOpts().CPlusPlus11).get(); + LHS = ActOnFinishFullExpr(LHSVal, LHSVal->getExprLoc(), false, + getLangOpts().CPlusPlus11); + if (LHS.isInvalid()) + return StmtError(); + + auto RHS = RHSVal ? ActOnFinishFullExpr(RHSVal, RHSVal->getExprLoc(), false, + getLangOpts().CPlusPlus11) + : ExprResult(); + if (RHS.isInvalid()) + return StmtError(); - CaseStmt *CS = new (Context) CaseStmt(LHSVal, RHSVal, CaseLoc, DotDotDotLoc, - ColonLoc); + CaseStmt *CS = new (Context) + CaseStmt(LHS.get(), RHS.get(), CaseLoc, DotDotDotLoc, ColonLoc); getCurFunction()->SwitchStack.back()->addSwitchCase(CS); return CS; } @@ -431,7 +460,11 @@ Sema::ActOnLabelStmt(SourceLocation IdentLoc, LabelDecl *TheDecl, TheDecl->setStmt(LS); if (!TheDecl->isGnuLocal()) { TheDecl->setLocStart(IdentLoc); - TheDecl->setLocation(IdentLoc); + if (!TheDecl->isMSAsmLabel()) { + // Don't update the location of MS ASM labels. These will result in + // a diagnostic, and changing the location here will mess that up. + TheDecl->setLocation(IdentLoc); + } } return LS; } @@ -481,47 +514,6 @@ Sema::ActOnIfStmt(SourceLocation IfLoc, FullExprArg CondVal, Decl *CondVar, thenStmt, ElseLoc, elseStmt); } -/// ConvertIntegerToTypeWarnOnOverflow - Convert the specified APInt to have -/// the specified width and sign. If an overflow occurs, detect it and emit -/// the specified diagnostic. -void Sema::ConvertIntegerToTypeWarnOnOverflow(llvm::APSInt &Val, - unsigned NewWidth, bool NewSign, - SourceLocation Loc, - unsigned DiagID) { - // Perform a conversion to the promoted condition type if needed. - if (NewWidth > Val.getBitWidth()) { - // If this is an extension, just do it. - Val = Val.extend(NewWidth); - Val.setIsSigned(NewSign); - - // If the input was signed and negative and the output is - // unsigned, don't bother to warn: this is implementation-defined - // behavior. - // FIXME: Introduce a second, default-ignored warning for this case? - } else if (NewWidth < Val.getBitWidth()) { - // If this is a truncation, check for overflow. - llvm::APSInt ConvVal(Val); - ConvVal = ConvVal.trunc(NewWidth); - ConvVal.setIsSigned(NewSign); - ConvVal = ConvVal.extend(Val.getBitWidth()); - ConvVal.setIsSigned(Val.isSigned()); - if (ConvVal != Val) - Diag(Loc, DiagID) << Val.toString(10) << ConvVal.toString(10); - - // Regardless of whether a diagnostic was emitted, really do the - // truncation. - Val = Val.trunc(NewWidth); - Val.setIsSigned(NewSign); - } else if (NewSign != Val.isSigned()) { - // Convert the sign to match the sign of the condition. This can cause - // overflow as well: unsigned(INTMIN) - // We don't diagnose this overflow, because it is implementation-defined - // behavior. - // FIXME: Introduce a second, default-ignored warning for this case? - Val.setIsSigned(NewSign); - } -} - namespace { struct CaseCompareFunctor { bool operator()(const std::pair<llvm::APSInt, CaseStmt*> &LHS, @@ -671,33 +663,63 @@ Sema::ActOnStartOfSwitchStmt(SourceLocation SwitchLoc, Expr *Cond, } static void AdjustAPSInt(llvm::APSInt &Val, unsigned BitWidth, bool IsSigned) { - if (Val.getBitWidth() < BitWidth) - Val = Val.extend(BitWidth); - else if (Val.getBitWidth() > BitWidth) - Val = Val.trunc(BitWidth); + Val = Val.extOrTrunc(BitWidth); Val.setIsSigned(IsSigned); } +/// Check the specified case value is in range for the given unpromoted switch +/// type. +static void checkCaseValue(Sema &S, SourceLocation Loc, const llvm::APSInt &Val, + unsigned UnpromotedWidth, bool UnpromotedSign) { + // If the case value was signed and negative and the switch expression is + // unsigned, don't bother to warn: this is implementation-defined behavior. + // FIXME: Introduce a second, default-ignored warning for this case? + if (UnpromotedWidth < Val.getBitWidth()) { + llvm::APSInt ConvVal(Val); + AdjustAPSInt(ConvVal, UnpromotedWidth, UnpromotedSign); + AdjustAPSInt(ConvVal, Val.getBitWidth(), Val.isSigned()); + // FIXME: Use different diagnostics for overflow in conversion to promoted + // type versus "switch expression cannot have this value". Use proper + // IntRange checking rather than just looking at the unpromoted type here. + if (ConvVal != Val) + S.Diag(Loc, diag::warn_case_value_overflow) << Val.toString(10) + << ConvVal.toString(10); + } +} + +typedef SmallVector<std::pair<llvm::APSInt, EnumConstantDecl*>, 64> EnumValsTy; + /// Returns true if we should emit a diagnostic about this case expression not /// being a part of the enum used in the switch controlling expression. -static bool ShouldDiagnoseSwitchCaseNotInEnum(const ASTContext &Ctx, +static bool ShouldDiagnoseSwitchCaseNotInEnum(const Sema &S, const EnumDecl *ED, - const Expr *CaseExpr) { - // Don't warn if the 'case' expression refers to a static const variable of - // the enum type. - CaseExpr = CaseExpr->IgnoreParenImpCasts(); - if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CaseExpr)) { + const Expr *CaseExpr, + EnumValsTy::iterator &EI, + EnumValsTy::iterator &EIEnd, + const llvm::APSInt &Val) { + bool FlagType = ED->hasAttr<FlagEnumAttr>(); + + if (const DeclRefExpr *DRE = + dyn_cast<DeclRefExpr>(CaseExpr->IgnoreParenImpCasts())) { if (const VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl())) { - if (!VD->hasGlobalStorage()) - return true; QualType VarType = VD->getType(); - if (!VarType.isConstQualified()) - return true; - QualType EnumType = Ctx.getTypeDeclType(ED); - if (Ctx.hasSameUnqualifiedType(EnumType, VarType)) + QualType EnumType = S.Context.getTypeDeclType(ED); + if (VD->hasGlobalStorage() && VarType.isConstQualified() && + S.Context.hasSameUnqualifiedType(EnumType, VarType)) return false; } } + + if (FlagType) { + return !S.IsValueInFlagEnum(ED, Val, false); + } else { + while (EI != EIEnd && EI->first < Val) + EI++; + + if (EI != EIEnd && EI->first == Val) + return false; + } + return true; } @@ -708,9 +730,10 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch, assert(SS == getCurFunction()->SwitchStack.back() && "switch stack missing push/pop!"); + getCurFunction()->SwitchStack.pop_back(); + if (!BodyStmt) return StmtError(); SS->setBody(BodyStmt, SwitchLoc); - getCurFunction()->SwitchStack.pop_back(); Expr *CondExpr = SS->getCond(); if (!CondExpr) return StmtError(); @@ -744,13 +767,20 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch, } } - // Get the bitwidth of the switched-on value before promotions. We must + // Get the bitwidth of the switched-on value after promotions. We must // convert the integer case values to this width before comparison. bool HasDependentValue = CondExpr->isTypeDependent() || CondExpr->isValueDependent(); - unsigned CondWidth + unsigned CondWidth = HasDependentValue ? 0 : Context.getIntWidth(CondType); + bool CondIsSigned = CondType->isSignedIntegerOrEnumerationType(); + + // Get the width and signedness that the condition might actually have, for + // warning purposes. + // FIXME: Grab an IntRange for the condition rather than using the unpromoted + // type. + unsigned CondWidthBeforePromotion = HasDependentValue ? 0 : Context.getIntWidth(CondTypeBeforePromotion); - bool CondIsSigned + bool CondIsSignedBeforePromotion = CondTypeBeforePromotion->isSignedIntegerOrEnumerationType(); // Accumulate all of the case values in a vector so that we can sort them @@ -816,15 +846,13 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch, Lo = ImpCastExprToType(Lo, CondType, CK_IntegralCast).get(); } - // Convert the value to the same width/sign as the condition had prior to - // integral promotions. - // - // FIXME: This causes us to reject valid code: - // switch ((char)c) { case 256: case 0: return 0; } - // Here we claim there is a duplicated condition value, but there is not. - ConvertIntegerToTypeWarnOnOverflow(LoVal, CondWidth, CondIsSigned, - Lo->getLocStart(), - diag::warn_case_value_overflow); + // Check the unconverted value is within the range of possible values of + // the switch expression. + checkCaseValue(*this, Lo->getLocStart(), LoVal, + CondWidthBeforePromotion, CondIsSignedBeforePromotion); + + // Convert the value to the same width/sign as the condition. + AdjustAPSInt(LoVal, CondWidth, CondIsSigned); CS->setLHS(Lo); @@ -847,9 +875,8 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch, llvm::APSInt ConstantCondValue; bool HasConstantCond = false; if (!HasDependentValue && !TheDefaultStmt) { - HasConstantCond - = CondExprBeforePromotion->EvaluateAsInt(ConstantCondValue, Context, - Expr::SE_AllowSideEffects); + HasConstantCond = CondExpr->EvaluateAsInt(ConstantCondValue, Context, + Expr::SE_AllowSideEffects); assert(!HasConstantCond || (ConstantCondValue.getBitWidth() == CondWidth && ConstantCondValue.isSigned() == CondIsSigned)); @@ -935,10 +962,13 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch, Hi = ImpCastExprToType(Hi, CondType, CK_IntegralCast).get(); } + // Check the unconverted value is within the range of possible values of + // the switch expression. + checkCaseValue(*this, Hi->getLocStart(), HiVal, + CondWidthBeforePromotion, CondIsSignedBeforePromotion); + // Convert the value to the same width/sign as the condition. - ConvertIntegerToTypeWarnOnOverflow(HiVal, CondWidth, CondIsSigned, - Hi->getLocStart(), - diag::warn_case_value_overflow); + AdjustAPSInt(HiVal, CondWidth, CondIsSigned); CR->setRHS(Hi); @@ -1029,8 +1059,6 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch, // If switch has default case, then ignore it. if (!CaseListIsErroneous && !HasConstantCond && ET) { const EnumDecl *ED = ET->getDecl(); - typedef SmallVector<std::pair<llvm::APSInt, EnumConstantDecl*>, 64> - EnumValsTy; EnumValsTy EnumVals; // Gather all enum values, set their type and sort them, @@ -1041,57 +1069,48 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch, EnumVals.push_back(std::make_pair(Val, EDI)); } std::stable_sort(EnumVals.begin(), EnumVals.end(), CmpEnumVals); - EnumValsTy::iterator EIend = + auto EI = EnumVals.begin(), 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) { - Expr *CaseExpr = CI->second->getLHS(); - if (ShouldDiagnoseSwitchCaseNotInEnum(Context, ED, CaseExpr)) - Diag(CaseExpr->getExprLoc(), diag::warn_not_in_enum) - << CondTypeBeforePromotion; - } + CI != CaseVals.end(); CI++) { + Expr *CaseExpr = CI->second->getLHS(); + if (ShouldDiagnoseSwitchCaseNotInEnum(*this, ED, CaseExpr, EI, EIEnd, + CI->first)) + Diag(CaseExpr->getExprLoc(), diag::warn_not_in_enum) + << CondTypeBeforePromotion; } + // 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) { - Expr *CaseExpr = RI->second->getLHS(); - if (ShouldDiagnoseSwitchCaseNotInEnum(Context, ED, CaseExpr)) - Diag(CaseExpr->getExprLoc(), diag::warn_not_in_enum) - << CondTypeBeforePromotion; - } + RI != CaseRanges.end(); RI++) { + Expr *CaseExpr = RI->second->getLHS(); + if (ShouldDiagnoseSwitchCaseNotInEnum(*this, ED, CaseExpr, EI, EIEnd, + RI->first)) + Diag(CaseExpr->getExprLoc(), diag::warn_not_in_enum) + << CondTypeBeforePromotion; llvm::APSInt Hi = RI->second->getRHS()->EvaluateKnownConstInt(Context); AdjustAPSInt(Hi, CondWidth, CondIsSigned); - while (EI != EIend && EI->first < Hi) - EI++; - if (EI == EIend || EI->first != Hi) { - Expr *CaseExpr = RI->second->getRHS(); - if (ShouldDiagnoseSwitchCaseNotInEnum(Context, ED, CaseExpr)) - Diag(CaseExpr->getExprLoc(), diag::warn_not_in_enum) - << CondTypeBeforePromotion; - } + + CaseExpr = RI->second->getRHS(); + if (ShouldDiagnoseSwitchCaseNotInEnum(*this, ED, CaseExpr, EI, EIEnd, + Hi)) + Diag(CaseExpr->getExprLoc(), diag::warn_not_in_enum) + << CondTypeBeforePromotion; } // Check which enum vals aren't in switch - CaseValsTy::const_iterator CI = CaseVals.begin(); - CaseRangesTy::const_iterator RI = CaseRanges.begin(); + auto CI = CaseVals.begin(); + auto RI = CaseRanges.begin(); bool hasCasesNotInSwitch = false; SmallVector<DeclarationName,8> UnhandledNames; - for (EI = EnumVals.begin(); EI != EIend; EI++){ + for (EI = EnumVals.begin(); EI != EIEnd; EI++){ // Drop unneeded case values while (CI != CaseVals.end() && CI->first < EI->first) CI++; @@ -1178,30 +1197,37 @@ Sema::DiagnoseAssignmentEnum(QualType DstType, QualType SrcType, llvm::APSInt RhsVal = SrcExpr->EvaluateKnownConstInt(Context); AdjustAPSInt(RhsVal, DstWidth, DstIsSigned); const EnumDecl *ED = ET->getDecl(); - typedef SmallVector<std::pair<llvm::APSInt, EnumConstantDecl *>, 64> - EnumValsTy; - EnumValsTy EnumVals; - - // Gather all enum values, set their type and sort them, - // allowing easier comparison with rhs constant. - for (auto *EDI : ED->enumerators()) { - llvm::APSInt Val = EDI->getInitVal(); - AdjustAPSInt(Val, DstWidth, DstIsSigned); - EnumVals.push_back(std::make_pair(Val, EDI)); - } - if (EnumVals.empty()) - return; - std::stable_sort(EnumVals.begin(), EnumVals.end(), CmpEnumVals); - EnumValsTy::iterator EIend = - std::unique(EnumVals.begin(), EnumVals.end(), EqEnumVals); - - // See which values aren't in the enum. - EnumValsTy::const_iterator EI = EnumVals.begin(); - while (EI != EIend && EI->first < RhsVal) - EI++; - if (EI == EIend || EI->first != RhsVal) { - Diag(SrcExpr->getExprLoc(), diag::warn_not_in_enum_assignment) + + if (ED->hasAttr<FlagEnumAttr>()) { + if (!IsValueInFlagEnum(ED, RhsVal, true)) + Diag(SrcExpr->getExprLoc(), diag::warn_not_in_enum_assignment) << DstType.getUnqualifiedType(); + } else { + typedef SmallVector<std::pair<llvm::APSInt, EnumConstantDecl *>, 64> + EnumValsTy; + EnumValsTy EnumVals; + + // Gather all enum values, set their type and sort them, + // allowing easier comparison with rhs constant. + for (auto *EDI : ED->enumerators()) { + llvm::APSInt Val = EDI->getInitVal(); + AdjustAPSInt(Val, DstWidth, DstIsSigned); + EnumVals.push_back(std::make_pair(Val, EDI)); + } + if (EnumVals.empty()) + return; + std::stable_sort(EnumVals.begin(), EnumVals.end(), CmpEnumVals); + EnumValsTy::iterator EIend = + std::unique(EnumVals.begin(), EnumVals.end(), EqEnumVals); + + // See which values aren't in the enum. + EnumValsTy::const_iterator EI = EnumVals.begin(); + while (EI != EIend && EI->first < RhsVal) + EI++; + if (EI == EIend || EI->first != RhsVal) { + Diag(SrcExpr->getExprLoc(), diag::warn_not_in_enum_assignment) + << DstType.getUnqualifiedType(); + } } } } @@ -1260,13 +1286,13 @@ namespace { // the evaluated decls into a vector. Simple is set to true if none // of the excluded constructs are used. class DeclExtractor : public EvaluatedExprVisitor<DeclExtractor> { - llvm::SmallPtrSet<VarDecl*, 8> &Decls; + llvm::SmallPtrSetImpl<VarDecl*> &Decls; SmallVectorImpl<SourceRange> &Ranges; bool Simple; public: typedef EvaluatedExprVisitor<DeclExtractor> Inherited; - DeclExtractor(Sema &S, llvm::SmallPtrSet<VarDecl*, 8> &Decls, + DeclExtractor(Sema &S, llvm::SmallPtrSetImpl<VarDecl*> &Decls, SmallVectorImpl<SourceRange> &Ranges) : Inherited(S.Context), Decls(Decls), @@ -1338,13 +1364,13 @@ namespace { // DeclMatcher checks to see if the decls are used in a non-evauluated // context. class DeclMatcher : public EvaluatedExprVisitor<DeclMatcher> { - llvm::SmallPtrSet<VarDecl*, 8> &Decls; + llvm::SmallPtrSetImpl<VarDecl*> &Decls; bool FoundDecl; public: typedef EvaluatedExprVisitor<DeclMatcher> Inherited; - DeclMatcher(Sema &S, llvm::SmallPtrSet<VarDecl*, 8> &Decls, + DeclMatcher(Sema &S, llvm::SmallPtrSetImpl<VarDecl*> &Decls, Stmt *Statement) : Inherited(S.Context), Decls(Decls), FoundDecl(false) { if (!Statement) return; @@ -1427,8 +1453,8 @@ namespace { if (Decls.size() == 0) return; // Don't warn on volatile, static, or global variables. - for (llvm::SmallPtrSet<VarDecl*, 8>::iterator I = Decls.begin(), - E = Decls.end(); + for (llvm::SmallPtrSetImpl<VarDecl*>::iterator I = Decls.begin(), + E = Decls.end(); I != E; ++I) if ((*I)->getType().isVolatileQualified() || (*I)->hasGlobalStorage()) return; @@ -1443,8 +1469,8 @@ namespace { PDiag << 0; else { PDiag << Decls.size(); - for (llvm::SmallPtrSet<VarDecl*, 8>::iterator I = Decls.begin(), - E = Decls.end(); + for (llvm::SmallPtrSetImpl<VarDecl*>::iterator I = Decls.begin(), + E = Decls.end(); I != E; ++I) PDiag << (*I)->getDeclName(); } @@ -1660,11 +1686,16 @@ Sema::CheckObjCForCollectionOperand(SourceLocation forLoc, Expr *collection) { if (!collection) return ExprError(); + ExprResult result = CorrectDelayedTyposInExpr(collection); + if (!result.isUsable()) + return ExprError(); + collection = result.get(); + // Bail out early if we've got a type-dependent expression. if (collection->isTypeDependent()) return collection; // Perform normal l-value conversion. - ExprResult result = DefaultFunctionArrayLvalueConversion(collection); + result = DefaultFunctionArrayLvalueConversion(collection); if (result.isInvalid()) return ExprError(); collection = result.get(); @@ -2453,7 +2484,7 @@ VarDecl *Sema::getCopyElisionCandidate(QualType ReturnType, // - in a return statement in a function [where] ... // ... the expression is the name of a non-volatile automatic object ... DeclRefExpr *DR = dyn_cast<DeclRefExpr>(E->IgnoreParens()); - if (!DR || DR->refersToEnclosingLocal()) + if (!DR || DR->refersToEnclosingVariableOrCapture()) return nullptr; VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl()); if (!VD) @@ -2621,8 +2652,12 @@ Sema::ActOnCapScopeReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { return StmtError(); RetValExp = Result.get(); + // DR1048: even prior to C++14, we should use the 'auto' deduction rules + // when deducing a return type for a lambda-expression (or by extension + // for a block). These rules differ from the stated C++11 rules only in + // that they remove top-level cv-qualifiers. if (!CurContext->isDependentContext()) - FnRetType = RetValExp->getType(); + FnRetType = RetValExp->getType().getUnqualifiedType(); else FnRetType = CurCap->ReturnType = Context.DependentTy; } else { @@ -2727,14 +2762,54 @@ Sema::ActOnCapScopeReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { return Result; } +namespace { +/// \brief Marks all typedefs in all local classes in a type referenced. +/// +/// In a function like +/// auto f() { +/// struct S { typedef int a; }; +/// return S(); +/// } +/// +/// the local type escapes and could be referenced in some TUs but not in +/// others. Pretend that all local typedefs are always referenced, to not warn +/// on this. This isn't necessary if f has internal linkage, or the typedef +/// is private. +class LocalTypedefNameReferencer + : public RecursiveASTVisitor<LocalTypedefNameReferencer> { +public: + LocalTypedefNameReferencer(Sema &S) : S(S) {} + bool VisitRecordType(const RecordType *RT); +private: + Sema &S; +}; +bool LocalTypedefNameReferencer::VisitRecordType(const RecordType *RT) { + auto *R = dyn_cast<CXXRecordDecl>(RT->getDecl()); + if (!R || !R->isLocalClass() || !R->isLocalClass()->isExternallyVisible() || + R->isDependentType()) + return true; + for (auto *TmpD : R->decls()) + if (auto *T = dyn_cast<TypedefNameDecl>(TmpD)) + if (T->getAccess() != AS_private || R->hasFriends()) + S.MarkAnyDeclReferenced(T->getLocation(), T, /*OdrUse=*/false); + return true; +} +} + +TypeLoc Sema::getReturnTypeLoc(FunctionDecl *FD) const { + TypeLoc TL = FD->getTypeSourceInfo()->getTypeLoc().IgnoreParens(); + while (auto ATL = TL.getAs<AttributedTypeLoc>()) + TL = ATL.getModifiedLoc().IgnoreParens(); + return TL.castAs<FunctionProtoTypeLoc>().getReturnLoc(); +} + /// Deduce the return type for a function from a returned expression, per /// C++1y [dcl.spec.auto]p6. bool Sema::DeduceFunctionTypeFromReturnExpr(FunctionDecl *FD, SourceLocation ReturnLoc, Expr *&RetExpr, AutoType *AT) { - TypeLoc OrigResultType = FD->getTypeSourceInfo()->getTypeLoc(). - IgnoreParens().castAs<FunctionProtoTypeLoc>().getReturnLoc(); + TypeLoc OrigResultType = getReturnTypeLoc(FD); QualType Deduced; if (RetExpr && isa<InitListExpr>(RetExpr)) { @@ -2772,6 +2847,11 @@ bool Sema::DeduceFunctionTypeFromReturnExpr(FunctionDecl *FD, if (DAR != DAR_Succeeded) return true; + + // If a local type is part of the returned type, mark its fields as + // referenced. + LocalTypedefNameReferencer Referencer(*this); + Referencer.TraverseType(RetExpr->getType()); } else { // In the case of a return with no operand, the initializer is considered // to be void(). @@ -2872,7 +2952,7 @@ StmtResult Sema::BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { // FIXME: Add a flag to the ScopeInfo to indicate whether we're performing // deduction. - if (getLangOpts().CPlusPlus1y) { + if (getLangOpts().CPlusPlus14) { if (AutoType *AT = FnRetType->getContainedAutoType()) { FunctionDecl *FD = cast<FunctionDecl>(CurContext); if (DeduceFunctionTypeFromReturnExpr(FD, ReturnLoc, RetValExp, AT)) { @@ -2964,14 +3044,26 @@ StmtResult Sema::BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { Result = new (Context) ReturnStmt(ReturnLoc, RetValExp, nullptr); } else if (!RetValExp && !HasDependentReturnType) { - unsigned DiagID = diag::warn_return_missing_expr; // C90 6.6.6.4p4 - // C99 6.8.6.4p1 (ext_ since GCC warns) - if (getLangOpts().C99) DiagID = diag::ext_return_missing_expr; + FunctionDecl *FD = getCurFunctionDecl(); - if (FunctionDecl *FD = getCurFunctionDecl()) + unsigned DiagID; + if (getLangOpts().CPlusPlus11 && FD && FD->isConstexpr()) { + // C++11 [stmt.return]p2 + DiagID = diag::err_constexpr_return_missing_expr; + FD->setInvalidDecl(); + } else if (getLangOpts().C99) { + // C99 6.8.6.4p1 (ext_ since GCC warns) + DiagID = diag::ext_return_missing_expr; + } else { + // C90 6.6.6.4p4 + DiagID = diag::warn_return_missing_expr; + } + + if (FD) Diag(ReturnLoc, DiagID) << FD->getIdentifier() << 0/*fn*/; else Diag(ReturnLoc, DiagID) << getCurMethodDecl()->getDeclName() << 1/*meth*/; + Result = new (Context) ReturnStmt(ReturnLoc); } else { assert(RetValExp || HasDependentReturnType); @@ -3119,9 +3211,24 @@ Sema::ActOnObjCAtSynchronizedOperand(SourceLocation atLoc, Expr *operand) { if (!type->isDependentType() && !type->isObjCObjectPointerType()) { const PointerType *pointerType = type->getAs<PointerType>(); - if (!pointerType || !pointerType->getPointeeType()->isVoidType()) - return Diag(atLoc, diag::error_objc_synchronized_expects_object) - << type << operand->getSourceRange(); + if (!pointerType || !pointerType->getPointeeType()->isVoidType()) { + if (getLangOpts().CPlusPlus) { + if (RequireCompleteType(atLoc, type, + diag::err_incomplete_receiver_type)) + return Diag(atLoc, diag::error_objc_synchronized_expects_object) + << type << operand->getSourceRange(); + + ExprResult result = PerformContextuallyConvertToObjCPointer(operand); + if (!result.isUsable()) + return Diag(atLoc, diag::error_objc_synchronized_expects_object) + << type << operand->getSourceRange(); + + operand = result.get(); + } else { + return Diag(atLoc, diag::error_objc_synchronized_expects_object) + << type << operand->getSourceRange(); + } + } } // The operand to @synchronized is a full-expression. @@ -3249,15 +3356,16 @@ StmtResult Sema::ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock, return CXXTryStmt::Create(Context, TryLoc, TryBlock, Handlers); } -StmtResult Sema::ActOnSEHTryBlock(bool IsCXXTry, SourceLocation TryLoc, - Stmt *TryBlock, Stmt *Handler, - int HandlerIndex, int HandlerParentIndex) { +StmtResult +Sema::ActOnSEHTryBlock(bool IsCXXTry, + SourceLocation TryLoc, + Stmt *TryBlock, + Stmt *Handler) { assert(TryBlock && Handler); getCurFunction()->setHasBranchProtectedScope(); - return SEHTryStmt::Create(Context, IsCXXTry, TryLoc, TryBlock, Handler, - HandlerIndex, HandlerParentIndex); + return SEHTryStmt::Create(Context,IsCXXTry,TryLoc,TryBlock,Handler); } StmtResult @@ -3330,6 +3438,7 @@ Sema::CreateCapturedStmtRecordDecl(CapturedDecl *&CD, SourceLocation Loc, else RD = RecordDecl::Create(Context, TTK_Struct, DC, Loc, Loc, /*Id=*/nullptr); + RD->setCapturedRecord(); DC->addDecl(RD); RD->setImplicit(); RD->startDefinition(); @@ -3353,6 +3462,11 @@ static void buildCapturedStmtCaptureList( CapturedStmt::VCK_This)); CaptureInits.push_back(Cap->getInitExpr()); continue; + } else if (Cap->isVLATypeCapture()) { + Captures.push_back( + CapturedStmt::Capture(Cap->getLocation(), CapturedStmt::VCK_VLAType)); + CaptureInits.push_back(nullptr); + continue; } assert(Cap->isReferenceCapture() && |