Index: include/clang/Sema/ScopeInfo.h =================================================================== --- include/clang/Sema/ScopeInfo.h +++ include/clang/Sema/ScopeInfo.h @@ -469,144 +469,144 @@ void Clear(); }; -class CapturingScopeInfo : public FunctionScopeInfo { -protected: - CapturingScopeInfo(const CapturingScopeInfo&) = default; +class Capture { + // There are three categories of capture: capturing 'this', capturing + // local variables, and C++1y initialized captures (which can have an + // arbitrary initializer, and don't really capture in the traditional + // sense at all). + // + // There are three ways to capture a local variable: + // - capture by copy in the C++11 sense, + // - capture by reference in the C++11 sense, and + // - __block capture. + // Lambdas explicitly specify capture by copy or capture by reference. + // For blocks, __block capture applies to variables with that annotation, + // variables of reference type are captured by reference, and other + // variables are captured by copy. + enum CaptureKind { + Cap_ByCopy, Cap_ByRef, Cap_Block, Cap_VLA + }; + enum { + IsNestedCapture = 0x1, + IsThisCaptured = 0x2 + }; + + /// The variable being captured (if we are not capturing 'this') and whether + /// this is a nested capture, and whether we are capturing 'this' + llvm::PointerIntPair VarAndNestedAndThis; + + /// Expression to initialize a field of the given type, and the kind of + /// capture (if this is a capture and not an init-capture). The expression + /// is only required if we are capturing ByVal and the variable's type has + /// a non-trivial copy constructor. + llvm::PointerIntPair InitExprAndCaptureKind; + + /// \brief The source location at which the first capture occurred. + SourceLocation Loc; + + /// \brief The location of the ellipsis that expands a parameter pack. + SourceLocation EllipsisLoc; + + /// \brief The type as it was captured, which is in effect the type of the + /// non-static data member that would hold the capture. + QualType CaptureType; + + /// \brief Whether an explicit capture has been odr-used in the body of the + /// lambda. + bool ODRUsed = false; + + /// \brief Whether an explicit capture has been non-odr-used in the body of + /// the lambda. + bool NonODRUsed = false; public: - enum ImplicitCaptureStyle { - ImpCap_None, ImpCap_LambdaByval, ImpCap_LambdaByref, ImpCap_Block, - ImpCap_CapturedRegion - }; + Capture(VarDecl *Var, bool Block, bool ByRef, bool IsNested, + SourceLocation Loc, SourceLocation EllipsisLoc, + QualType CaptureType, Expr *Cpy) + : VarAndNestedAndThis(Var, IsNested ? IsNestedCapture : 0), + InitExprAndCaptureKind( + Cpy, !Var ? Cap_VLA : Block ? Cap_Block : ByRef ? Cap_ByRef + : Cap_ByCopy), + Loc(Loc), EllipsisLoc(EllipsisLoc), CaptureType(CaptureType) {} - ImplicitCaptureStyle ImpCaptureStyle; + enum IsThisCapture { ThisCapture }; + Capture(IsThisCapture, bool IsNested, SourceLocation Loc, + QualType CaptureType, Expr *Cpy, const bool ByCopy) + : VarAndNestedAndThis( + nullptr, (IsThisCaptured | (IsNested ? IsNestedCapture : 0))), + InitExprAndCaptureKind(Cpy, ByCopy ? Cap_ByCopy : Cap_ByRef), + Loc(Loc), CaptureType(CaptureType) {} - class Capture { - // There are three categories of capture: capturing 'this', capturing - // local variables, and C++1y initialized captures (which can have an - // arbitrary initializer, and don't really capture in the traditional - // sense at all). - // - // There are three ways to capture a local variable: - // - capture by copy in the C++11 sense, - // - capture by reference in the C++11 sense, and - // - __block capture. - // Lambdas explicitly specify capture by copy or capture by reference. - // For blocks, __block capture applies to variables with that annotation, - // variables of reference type are captured by reference, and other - // variables are captured by copy. - enum CaptureKind { - Cap_ByCopy, Cap_ByRef, Cap_Block, Cap_VLA - }; - enum { - IsNestedCapture = 0x1, - IsThisCaptured = 0x2 - }; + bool isThisCapture() const { + return VarAndNestedAndThis.getInt() & IsThisCaptured; + } - /// The variable being captured (if we are not capturing 'this') and whether - /// this is a nested capture, and whether we are capturing 'this' - llvm::PointerIntPair VarAndNestedAndThis; - - /// Expression to initialize a field of the given type, and the kind of - /// capture (if this is a capture and not an init-capture). The expression - /// is only required if we are capturing ByVal and the variable's type has - /// a non-trivial copy constructor. - llvm::PointerIntPair InitExprAndCaptureKind; - - /// \brief The source location at which the first capture occurred. - SourceLocation Loc; + bool isVariableCapture() const { + return !isThisCapture() && !isVLATypeCapture(); + } - /// \brief The location of the ellipsis that expands a parameter pack. - SourceLocation EllipsisLoc; + bool isCopyCapture() const { + return InitExprAndCaptureKind.getInt() == Cap_ByCopy; + } - /// \brief The type as it was captured, which is in effect the type of the - /// non-static data member that would hold the capture. - QualType CaptureType; - - /// \brief Whether an explicit capture has been odr-used in the body of the - /// lambda. - bool ODRUsed = false; - - /// \brief Whether an explicit capture has been non-odr-used in the body of - /// the lambda. - bool NonODRUsed = false; + bool isReferenceCapture() const { + return InitExprAndCaptureKind.getInt() == Cap_ByRef; + } - public: - Capture(VarDecl *Var, bool Block, bool ByRef, bool IsNested, - SourceLocation Loc, SourceLocation EllipsisLoc, - QualType CaptureType, Expr *Cpy) - : VarAndNestedAndThis(Var, IsNested ? IsNestedCapture : 0), - InitExprAndCaptureKind( - Cpy, !Var ? Cap_VLA : Block ? Cap_Block : ByRef ? Cap_ByRef - : Cap_ByCopy), - Loc(Loc), EllipsisLoc(EllipsisLoc), CaptureType(CaptureType) {} - - enum IsThisCapture { ThisCapture }; - Capture(IsThisCapture, bool IsNested, SourceLocation Loc, - QualType CaptureType, Expr *Cpy, const bool ByCopy) - : VarAndNestedAndThis( - nullptr, (IsThisCaptured | (IsNested ? IsNestedCapture : 0))), - InitExprAndCaptureKind(Cpy, ByCopy ? Cap_ByCopy : Cap_ByRef), - Loc(Loc), CaptureType(CaptureType) {} + bool isBlockCapture() const { + return InitExprAndCaptureKind.getInt() == Cap_Block; + } - bool isThisCapture() const { - return VarAndNestedAndThis.getInt() & IsThisCaptured; - } + bool isVLATypeCapture() const { + return InitExprAndCaptureKind.getInt() == Cap_VLA; + } - bool isVariableCapture() const { - return !isThisCapture() && !isVLATypeCapture(); - } + bool isNested() const { + return VarAndNestedAndThis.getInt() & IsNestedCapture; + } - bool isCopyCapture() const { - return InitExprAndCaptureKind.getInt() == Cap_ByCopy; - } + bool isODRUsed() const { return ODRUsed; } + bool isNonODRUsed() const { return NonODRUsed; } + void markUsed(bool IsODRUse) { (IsODRUse ? ODRUsed : NonODRUsed) = true; } - bool isReferenceCapture() const { - return InitExprAndCaptureKind.getInt() == Cap_ByRef; - } + VarDecl *getVariable() const { + assert(isVariableCapture()); + return VarAndNestedAndThis.getPointer(); + } - bool isBlockCapture() const { - return InitExprAndCaptureKind.getInt() == Cap_Block; - } + /// \brief Retrieve the location at which this variable was captured. + SourceLocation getLocation() const { return Loc; } - bool isVLATypeCapture() const { - return InitExprAndCaptureKind.getInt() == Cap_VLA; - } + /// \brief Retrieve the source location of the ellipsis, whose presence + /// indicates that the capture is a pack expansion. + SourceLocation getEllipsisLoc() const { return EllipsisLoc; } - bool isNested() const { - return VarAndNestedAndThis.getInt() & IsNestedCapture; - } + /// \brief Retrieve the capture type for this capture, which is effectively + /// the type of the non-static data member in the lambda/block structure + /// that would store this capture. + QualType getCaptureType() const { + assert(!isThisCapture()); + return CaptureType; + } - bool isODRUsed() const { return ODRUsed; } - bool isNonODRUsed() const { return NonODRUsed; } - void markUsed(bool IsODRUse) { (IsODRUse ? ODRUsed : NonODRUsed) = true; } - - VarDecl *getVariable() const { - assert(isVariableCapture()); - return VarAndNestedAndThis.getPointer(); - } - - /// \brief Retrieve the location at which this variable was captured. - SourceLocation getLocation() const { return Loc; } - - /// \brief Retrieve the source location of the ellipsis, whose presence - /// indicates that the capture is a pack expansion. - SourceLocation getEllipsisLoc() const { return EllipsisLoc; } - - /// \brief Retrieve the capture type for this capture, which is effectively - /// the type of the non-static data member in the lambda/block structure - /// that would store this capture. - QualType getCaptureType() const { - assert(!isThisCapture()); - return CaptureType; - } + Expr *getInitExpr() const { + assert(!isVLATypeCapture() && "no init expression for type capture"); + return static_cast(InitExprAndCaptureKind.getPointer()); + } +}; - Expr *getInitExpr() const { - assert(!isVLATypeCapture() && "no init expression for type capture"); - return static_cast(InitExprAndCaptureKind.getPointer()); - } +class CapturingScopeInfo : public FunctionScopeInfo { +protected: + CapturingScopeInfo(const CapturingScopeInfo&) = default; + +public: + enum ImplicitCaptureStyle { + ImpCap_None, ImpCap_LambdaByval, ImpCap_LambdaByref, ImpCap_Block, + ImpCap_CapturedRegion }; + ImplicitCaptureStyle ImpCaptureStyle; + CapturingScopeInfo(DiagnosticsEngine &Diag, ImplicitCaptureStyle Style) : FunctionScopeInfo(Diag), ImpCaptureStyle(Style) {} Index: include/clang/Sema/Sema.h =================================================================== --- include/clang/Sema/Sema.h +++ include/clang/Sema/Sema.h @@ -30,7 +30,6 @@ #include "clang/AST/TypeLoc.h" #include "clang/AST/TypeOrdering.h" #include "clang/Basic/ExpressionTraits.h" -#include "clang/Basic/LangOptions.h" #include "clang/Basic/Module.h" #include "clang/Basic/OpenMPKinds.h" #include "clang/Basic/PragmaKinds.h" @@ -45,7 +44,6 @@ #include "clang/Sema/ObjCMethodList.h" #include "clang/Sema/Ownership.h" #include "clang/Sema/Scope.h" -#include "clang/Sema/ScopeInfo.h" #include "clang/Sema/TypoCorrection.h" #include "clang/Sema/Weak.h" #include "llvm/ADT/ArrayRef.h" @@ -201,6 +199,7 @@ namespace sema { class AccessedEntity; class BlockScopeInfo; + class Capture; class CapturedRegionScopeInfo; class CapturingScopeInfo; class CompoundScopeInfo; @@ -1322,23 +1321,7 @@ return FunctionScopes.back(); } - sema::FunctionScopeInfo *getEnclosingFunction() const { - if (FunctionScopes.empty()) - return nullptr; - - for (int e = FunctionScopes.size()-1; e >= 0; --e) { - if (isa(FunctionScopes[e])) - continue; - return FunctionScopes[e]; - } - return nullptr; - } - - template - void recordUseOfEvaluatedWeak(const ExprT *E, bool IsRead=true) { - if (!isUnevaluatedContext()) - getCurFunction()->recordUseOfWeak(E, IsRead); - } + sema::FunctionScopeInfo *getEnclosingFunction() const; void PushCompoundScope(bool IsStmtExpr); void PopCompoundScope(); @@ -5553,10 +5536,10 @@ Scope *CurScope); /// \brief Does copying/destroying the captured variable have side effects? - bool CaptureHasSideEffects(const sema::LambdaScopeInfo::Capture &From); + bool CaptureHasSideEffects(const sema::Capture &From); /// \brief Diagnose if an explicit lambda capture is unused. - void DiagnoseUnusedLambdaCapture(const sema::LambdaScopeInfo::Capture &From); + void DiagnoseUnusedLambdaCapture(const sema::Capture &From); /// \brief Complete a lambda-expression having processed and attached the /// lambda body. Index: include/clang/Sema/SemaLambda.h =================================================================== --- include/clang/Sema/SemaLambda.h +++ include/clang/Sema/SemaLambda.h @@ -15,9 +15,13 @@ #ifndef LLVM_CLANG_SEMA_SEMALAMBDA_H #define LLVM_CLANG_SEMA_SEMALAMBDA_H + #include "clang/AST/ASTLambda.h" -#include "clang/Sema/ScopeInfo.h" + namespace clang { +namespace sema { +class FunctionScopeInfo; +} class Sema; /// \brief Examines the FunctionScopeInfo stack to determine the nearest Index: lib/Sema/Sema.cpp =================================================================== --- lib/Sema/Sema.cpp +++ lib/Sema/Sema.cpp @@ -1426,6 +1426,18 @@ return CurBSI; } +FunctionScopeInfo *Sema::getEnclosingFunction() const { + if (FunctionScopes.empty()) + return nullptr; + + for (int e = FunctionScopes.size() - 1; e >= 0; --e) { + if (isa(FunctionScopes[e])) + continue; + return FunctionScopes[e]; + } + return nullptr; +} + LambdaScopeInfo *Sema::getCurLambda(bool IgnoreNonLambdaCapturingScope) { if (FunctionScopes.empty()) return nullptr; Index: lib/Sema/SemaCoroutine.cpp =================================================================== --- lib/Sema/SemaCoroutine.cpp +++ lib/Sema/SemaCoroutine.cpp @@ -19,6 +19,7 @@ #include "clang/Lex/Preprocessor.h" #include "clang/Sema/Initialization.h" #include "clang/Sema/Overload.h" +#include "clang/Sema/ScopeInfo.h" #include "clang/Sema/SemaInternal.h" using namespace clang; Index: lib/Sema/SemaDecl.cpp =================================================================== --- lib/Sema/SemaDecl.cpp +++ lib/Sema/SemaDecl.cpp @@ -6930,7 +6930,7 @@ /// variable \p VD, or an invalid source location otherwise. static SourceLocation getCaptureLocation(const LambdaScopeInfo *LSI, const VarDecl *VD) { - for (const LambdaScopeInfo::Capture &Capture : LSI->Captures) { + for (const Capture &Capture : LSI->Captures) { if (Capture.isVariableCapture() && Capture.getVariable() == VD) return Capture.getLocation(); } Index: lib/Sema/SemaDeclAttr.cpp =================================================================== --- lib/Sema/SemaDeclAttr.cpp +++ lib/Sema/SemaDeclAttr.cpp @@ -31,6 +31,7 @@ #include "clang/Sema/Initialization.h" #include "clang/Sema/Lookup.h" #include "clang/Sema/Scope.h" +#include "clang/Sema/ScopeInfo.h" #include "clang/Sema/SemaInternal.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringExtras.h" Index: lib/Sema/SemaExpr.cpp =================================================================== --- lib/Sema/SemaExpr.cpp +++ lib/Sema/SemaExpr.cpp @@ -1679,9 +1679,9 @@ MarkDeclRefReferenced(E); if (getLangOpts().ObjCWeak && isa(D) && - Ty.getObjCLifetime() == Qualifiers::OCL_Weak && + Ty.getObjCLifetime() == Qualifiers::OCL_Weak && !isUnevaluatedContext() && !Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, E->getLocStart())) - recordUseOfEvaluatedWeak(E); + getCurFunction()->recordUseOfWeak(E); FieldDecl *FD = dyn_cast(D); if (IndirectFieldDecl *IFD = dyn_cast(D)) @@ -2431,8 +2431,9 @@ IV->getLocation(), SelfExpr.get(), true, true); if (IV->getType().getObjCLifetime() == Qualifiers::OCL_Weak) { - if (!Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, Loc)) - recordUseOfEvaluatedWeak(Result); + if (!isUnevaluatedContext() && + !Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, Loc)) + getCurFunction()->recordUseOfWeak(Result); } if (getLangOpts().ObjCAutoRefCount) { if (CurContext->isClosure()) @@ -13045,7 +13046,7 @@ // Set the captured variables on the block. // FIXME: Share capture structure between BlockDecl and CapturingScopeInfo! SmallVector Captures; - for (CapturingScopeInfo::Capture &Cap : BSI->Captures) { + for (Capture &Cap : BSI->Captures) { if (Cap.isThisCapture()) continue; BlockDecl::Capture NewCap(Cap.getVariable(), Cap.isBlockCapture(), @@ -14144,7 +14145,7 @@ // Similarly to mutable captures in lambda, all the OpenMP captures by copy // are mutable in the sense that user can change their value - they are // private instances of the captured declarations. - const CapturingScopeInfo::Capture &Cap = CSI->getCapture(Var); + const Capture &Cap = CSI->getCapture(Var); if (Cap.isCopyCapture() && !(isa(CSI) && cast(CSI)->Mutable) && !(isa(CSI) && Index: lib/Sema/SemaExprMember.cpp =================================================================== --- lib/Sema/SemaExprMember.cpp +++ lib/Sema/SemaExprMember.cpp @@ -1479,8 +1479,9 @@ IsArrow); if (IV->getType().getObjCLifetime() == Qualifiers::OCL_Weak) { - if (!S.Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, MemberLoc)) - S.recordUseOfEvaluatedWeak(Result); + if (!S.isUnevaluatedContext() && + !S.Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, MemberLoc)) + S.getCurFunction()->recordUseOfWeak(Result); } return Result; Index: lib/Sema/SemaLambda.cpp =================================================================== --- lib/Sema/SemaLambda.cpp +++ lib/Sema/SemaLambda.cpp @@ -1388,8 +1388,9 @@ Class->addDecl(Conversion); } -static ExprResult performLambdaVarCaptureInitialization( - Sema &S, const LambdaScopeInfo::Capture &Capture, FieldDecl *Field) { +static ExprResult performLambdaVarCaptureInitialization(Sema &S, + const Capture &Capture, + FieldDecl *Field) { assert(Capture.isVariableCapture() && "not a variable capture"); auto *Var = Capture.getVariable(); @@ -1443,7 +1444,7 @@ llvm_unreachable("Unknown implicit capture style"); } -bool Sema::CaptureHasSideEffects(const LambdaScopeInfo::Capture &From) { +bool Sema::CaptureHasSideEffects(const Capture &From) { if (!From.isVLATypeCapture()) { Expr *Init = From.getInitExpr(); if (Init && Init->HasSideEffects(Context)) @@ -1468,7 +1469,7 @@ return false; } -void Sema::DiagnoseUnusedLambdaCapture(const LambdaScopeInfo::Capture &From) { +void Sema::DiagnoseUnusedLambdaCapture(const Capture &From) { if (CaptureHasSideEffects(From)) return; @@ -1523,7 +1524,7 @@ // Translate captures. auto CurField = Class->field_begin(); for (unsigned I = 0, N = LSI->Captures.size(); I != N; ++I, ++CurField) { - const LambdaScopeInfo::Capture &From = LSI->Captures[I]; + const Capture &From = LSI->Captures[I]; assert(!From.isBlockCapture() && "Cannot capture __block variables"); bool IsImplicit = I >= LSI->NumExplicitCaptures; Index: lib/Sema/SemaPseudoObject.cpp =================================================================== --- lib/Sema/SemaPseudoObject.cpp +++ lib/Sema/SemaPseudoObject.cpp @@ -965,11 +965,11 @@ } ExprResult ObjCPropertyOpBuilder::complete(Expr *SyntacticForm) { - if (isWeakProperty() && + if (isWeakProperty() && !S.isUnevaluatedContext() && !S.Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, SyntacticForm->getLocStart())) - S.recordUseOfEvaluatedWeak(SyntacticRefExpr, - SyntacticRefExpr->isMessagingGetter()); + S.getCurFunction()->recordUseOfWeak(SyntacticRefExpr, + SyntacticRefExpr->isMessagingGetter()); return PseudoOpBuilder::complete(SyntacticForm); } Index: lib/Sema/SemaStmt.cpp =================================================================== --- lib/Sema/SemaStmt.cpp +++ lib/Sema/SemaStmt.cpp @@ -4040,32 +4040,29 @@ return RD; } -static void buildCapturedStmtCaptureList( - SmallVectorImpl &Captures, - SmallVectorImpl &CaptureInits, - ArrayRef Candidates) { - - typedef ArrayRef::const_iterator CaptureIter; - for (CaptureIter Cap = Candidates.begin(); Cap != Candidates.end(); ++Cap) { - - if (Cap->isThisCapture()) { - Captures.push_back(CapturedStmt::Capture(Cap->getLocation(), +static void +buildCapturedStmtCaptureList(SmallVectorImpl &Captures, + SmallVectorImpl &CaptureInits, + ArrayRef Candidates) { + for (const sema::Capture &Cap : Candidates) { + if (Cap.isThisCapture()) { + Captures.push_back(CapturedStmt::Capture(Cap.getLocation(), CapturedStmt::VCK_This)); - CaptureInits.push_back(Cap->getInitExpr()); + CaptureInits.push_back(Cap.getInitExpr()); continue; - } else if (Cap->isVLATypeCapture()) { + } else if (Cap.isVLATypeCapture()) { Captures.push_back( - CapturedStmt::Capture(Cap->getLocation(), CapturedStmt::VCK_VLAType)); + CapturedStmt::Capture(Cap.getLocation(), CapturedStmt::VCK_VLAType)); CaptureInits.push_back(nullptr); continue; } - Captures.push_back(CapturedStmt::Capture(Cap->getLocation(), - Cap->isReferenceCapture() + Captures.push_back(CapturedStmt::Capture(Cap.getLocation(), + Cap.isReferenceCapture() ? CapturedStmt::VCK_ByRef : CapturedStmt::VCK_ByCopy, - Cap->getVariable())); - CaptureInits.push_back(Cap->getInitExpr()); + Cap.getVariable())); + CaptureInits.push_back(Cap.getInitExpr()); } }