diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index 26ff4246487b8..370e2aa193f9a 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -210,10 +210,6 @@ class Parser : public CodeCompletionHandler { const Token &getCurToken() const { return Tok; } Scope *getCurScope() const { return Actions.getCurScope(); } - void incrementMSManglingNumber() const { - return Actions.incrementMSManglingNumber(); - } - // Type forwarding. All of these are statically 'void*', but they may all be // different actual classes based on the actions in place. typedef OpaquePtr DeclGroupPtrTy; @@ -384,78 +380,6 @@ class Parser : public CodeCompletionHandler { return MightBeCXXScopeToken() && TryAnnotateCXXScopeToken(EnteringContext); } - //===--------------------------------------------------------------------===// - // Scope manipulation - - /// ParseScope - Introduces a new scope for parsing. The kind of - /// scope is determined by ScopeFlags. Objects of this type should - /// be created on the stack to coincide with the position where the - /// parser enters the new scope, and this object's constructor will - /// create that new scope. Similarly, once the object is destroyed - /// the parser will exit the scope. - class ParseScope { - Parser *Self; - ParseScope(const ParseScope &) = delete; - void operator=(const ParseScope &) = delete; - - public: - // ParseScope - Construct a new object to manage a scope in the - // parser Self where the new Scope is created with the flags - // ScopeFlags, but only when we aren't about to enter a compound statement. - ParseScope(Parser *Self, unsigned ScopeFlags, bool EnteredScope = true, - bool BeforeCompoundStmt = false) - : Self(Self) { - if (EnteredScope && !BeforeCompoundStmt) - Self->EnterScope(ScopeFlags); - else { - if (BeforeCompoundStmt) - Self->incrementMSManglingNumber(); - - this->Self = nullptr; - } - } - - // Exit - Exit the scope associated with this object now, rather - // than waiting until the object is destroyed. - void Exit() { - if (Self) { - Self->ExitScope(); - Self = nullptr; - } - } - - ~ParseScope() { Exit(); } - }; - - /// Introduces zero or more scopes for parsing. The scopes will all be exited - /// when the object is destroyed. - class MultiParseScope { - Parser &Self; - unsigned NumScopes = 0; - - MultiParseScope(const MultiParseScope &) = delete; - - public: - MultiParseScope(Parser &Self) : Self(Self) {} - void Enter(unsigned ScopeFlags) { - Self.EnterScope(ScopeFlags); - ++NumScopes; - } - void Exit() { - while (NumScopes) { - Self.ExitScope(); - --NumScopes; - } - } - ~MultiParseScope() { Exit(); } - }; - - /// EnterScope - Start a new scope. - void EnterScope(unsigned ScopeFlags); - - /// ExitScope - Pop a scope off the scope stack. - void ExitScope(); - //===--------------------------------------------------------------------===// // Diagnostic Emission and Error recovery. @@ -546,11 +470,6 @@ class Parser : public CodeCompletionHandler { StackExhaustionHandler StackHandler; - /// ScopeCache - Cache scopes to reduce malloc traffic. - static constexpr int ScopeCacheSize = 16; - unsigned NumCachedScopes; - Scope *ScopeCache[ScopeCacheSize]; - /// Identifiers used for SEH handling in Borland. These are only /// allowed in particular circumstances // __except block @@ -2532,7 +2451,7 @@ class Parser : public CodeCompletionHandler { assert(SS.isSet() && "C++ scope was not set!"); CreatedScope = true; - P.EnterScope(0); // Not a decl scope. + P.Actions.EnterScope(0); // Not a decl scope. if (!P.Actions.ActOnCXXEnterDeclaratorScope(P.getCurScope(), SS)) EnteredScope = true; @@ -2544,7 +2463,7 @@ class Parser : public CodeCompletionHandler { P.Actions.ActOnCXXExitDeclaratorScope(P.getCurScope(), SS); } if (CreatedScope) - P.ExitScope(); + P.Actions.ExitScope(); } }; diff --git a/clang/include/clang/Sema/Scope.h b/clang/include/clang/Sema/Scope.h index 0d1c0ff6a1e91..01d5471992efa 100644 --- a/clang/include/clang/Sema/Scope.h +++ b/clang/include/clang/Sema/Scope.h @@ -29,11 +29,11 @@ class raw_ostream; } // namespace llvm namespace clang { - class Decl; class DeclContext; class UsingDirectiveDecl; class VarDecl; +class Sema; /// Scope - A scope is a transient data structure that is used while parsing the /// program. It assists with resolving identifiers to the appropriate @@ -667,6 +667,45 @@ class Scope { void dump() const; }; +/// ParseScope - Introduces a new scope for parsing. The kind of +/// scope is determined by ScopeFlags. Objects of this type should +/// be created on the stack to coincide with the position where the +/// parser enters the new scope, and this object's constructor will +/// create that new scope. Similarly, once the object is destroyed +/// the parser will exit the scope. +class ParseScope { + Sema *S; + ParseScope(const ParseScope &) = delete; + void operator=(const ParseScope &) = delete; + +public: + // ParseScope - Construct a new object to manage a scope in the + // parser Self where the new Scope is created with the flags + // ScopeFlags, but only when we aren't about to enter a compound statement. + ParseScope(Sema &S, unsigned ScopeFlags, bool EnteredScope = true, + bool BeforeCompoundStmt = false); + + // Exit - Exit the scope associated with this object now, rather + // than waiting until the object is destroyed. + void Exit(); + + ~ParseScope() { Exit(); } +}; + +/// Introduces zero or more scopes for parsing. The scopes will all be exited +/// when the object is destroyed. +class MultiParseScope { + Sema &S; + unsigned NumScopes = 0; + + MultiParseScope(const MultiParseScope &) = delete; + +public: + MultiParseScope(Sema &S) : S(S) {} + void Enter(unsigned ScopeFlags); + void Exit(); + ~MultiParseScope() { Exit(); } +}; } // namespace clang #endif // LLVM_CLANG_SEMA_SCOPE_H diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index c5711ab7ea751..b86a9eaed305e 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -1200,6 +1200,15 @@ class Sema final : public SemaBase { /// Scope actions. void ActOnTranslationUnitScope(Scope *S); + /// EnterScope - Start a new scope. + void EnterScope(unsigned ScopeFlags); + + /// ExitScope - Pop a scope off the scope stack. + void ExitScope(); + + /// Delete the scope stack and all cached scopes. + void FreeScopes(); + /// Determine whether \param D is function like (function or function /// template) for parsing. bool isDeclaratorFunctionLike(Declarator &D); @@ -1575,10 +1584,12 @@ class Sema final : public SemaBase { sema::SemaPPCallbacks *SemaPPCallbackHandler; /// The parser's current scope. - /// - /// The parser maintains this state here. Scope *CurScope; + /// ScopeCache - Cache scopes to reduce malloc traffic. + static constexpr unsigned MaxScopeCacheSize = 16; + SmallVector, MaxScopeCacheSize> ScopeCache; + mutable IdentifierInfo *Ident_super; std::unique_ptr AMDGPUPtr; @@ -4218,7 +4229,7 @@ class Sema final : public SemaBase { TopLevelStmtDecl *ActOnStartTopLevelStmtDecl(Scope *S); void ActOnFinishTopLevelStmtDecl(TopLevelStmtDecl *D, Stmt *Statement); - void ActOnPopScope(SourceLocation Loc, Scope *S); + void ActOnPopScope(Scope *S); /// ParsedFreeStandingDeclSpec - This method is invoked when a declspec with /// no declarator (e.g. "struct foo;") is parsed. @@ -11066,6 +11077,37 @@ class Sema final : public SemaBase { BuildForRangeKind Kind, ArrayRef LifetimeExtendTemps = {}); + /// Set the type of a for-range declaration whose for-range or expansion + /// initialiser is dependent. + void ActOnDependentForRangeInitializer(VarDecl *LoopVar, + BuildForRangeKind BFRK); + + /// Holds the 'begin' and 'end' variables of a range-based for loop or + /// expansion statement; begin-expr and end-expr are also provided; the + /// latter are used in some diagnostics. + struct ForRangeBeginEndInfo { + VarDecl *BeginVar = nullptr; + VarDecl *EndVar = nullptr; + Expr *BeginExpr = nullptr; + Expr *EndExpr = nullptr; + bool isValid() const { return BeginVar != nullptr && EndVar != nullptr; } + }; + + /// Determine begin-expr and end-expr and build variable declarations for + /// them as per [stmt.ranged]. + ForRangeBeginEndInfo BuildCXXForRangeBeginEndVars( + Scope *S, VarDecl *RangeVar, SourceLocation ColonLoc, + SourceLocation CoawaitLoc, + ArrayRef LifetimeExtendTemps, + BuildForRangeKind Kind, bool Constexpr, + StmtResult *RebuildResult = nullptr, + llvm::function_ref RebuildWithDereference = {}); + + /// Build the range variable of a range-based for loop or iterating + /// expansion statement and return its DeclStmt. + StmtResult BuildCXXForRangeRangeVar(Scope *S, Expr *Range, QualType Type, + bool Constexpr = false); + /// FinishCXXForRangeStmt - Attach the body to a C++0x for-range statement. /// This is a separate step from ActOnCXXForRangeStmt because analysis of the /// body cannot be performed until after the type of the range variable is @@ -11207,6 +11249,9 @@ class Sema final : public SemaBase { SourceLocation Loc, unsigned NumParams); + void ApplyForRangeOrExpansionStatementLifetimeExtension( + VarDecl *RangeVar, ArrayRef Temporaries); + private: /// Check whether the given statement can have musttail applied to it, /// issuing a diagnostic and returning false if not. diff --git a/clang/lib/Interpreter/IncrementalParser.cpp b/clang/lib/Interpreter/IncrementalParser.cpp index bf08911e23533..b2439a518a464 100644 --- a/clang/lib/Interpreter/IncrementalParser.cpp +++ b/clang/lib/Interpreter/IncrementalParser.cpp @@ -63,10 +63,10 @@ IncrementalParser::ParseOrWrapTopLevelDecl() { P->ConsumeAnyToken(); // FIXME: Clang does not call ExitScope on finalizing the regular TU, we // might want to do that around HandleEndOfTranslationUnit. - P->ExitScope(); + S.ExitScope(); S.CurContext = nullptr; // Start a new PTU. - P->EnterScope(Scope::DeclScope); + S.EnterScope(Scope::DeclScope); S.ActOnTranslationUnitScope(P->getCurScope()); } diff --git a/clang/lib/Parse/ParseCXXInlineMethods.cpp b/clang/lib/Parse/ParseCXXInlineMethods.cpp index 74e25002e468b..90e274ed51c89 100644 --- a/clang/lib/Parse/ParseCXXInlineMethods.cpp +++ b/clang/lib/Parse/ParseCXXInlineMethods.cpp @@ -328,7 +328,8 @@ struct Parser::ReenterTemplateScopeRAII { TemplateParameterDepthRAII CurTemplateDepthTracker; ReenterTemplateScopeRAII(Parser &P, Decl *MaybeTemplated, bool Enter = true) - : P(P), Scopes(P), CurTemplateDepthTracker(P.TemplateParameterDepth) { + : P(P), Scopes(P.Actions), + CurTemplateDepthTracker(P.TemplateParameterDepth) { if (Enter) { CurTemplateDepthTracker.addDepth( P.ReenterTemplateScopes(Scopes, MaybeTemplated)); @@ -510,7 +511,7 @@ void Parser::ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM) { // }; // Setup the CurScope to match the function DeclContext - we have such // assumption in IsInFnTryBlockHandler(). - ParseScope FnScope(this, Scope::FnScope); + ParseScope FnScope(Actions, Scope::FnScope); Sema::ContextRAII FnContext(Actions, FunctionToPush, /*NewThisContext=*/false); Sema::FunctionScopeRAII PopFnContext(Actions); @@ -597,8 +598,8 @@ void Parser::ParseLexedMethodDef(LexedMethod &LM) { // Parse the method body. Function body parsing code is similar enough // to be re-used for method bodies as well. - ParseScope FnScope(this, Scope::FnScope | Scope::DeclScope | - Scope::CompoundStmtScope); + ParseScope FnScope(Actions, Scope::FnScope | Scope::DeclScope | + Scope::CompoundStmtScope); Sema::FPFeaturesStateRAII SaveFPFeatures(Actions); Actions.ActOnStartOfFunctionDef(getCurScope(), LM.D); diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 5e1ff2be28f38..ecf1cba8cff6f 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -677,9 +677,9 @@ void Parser::ParseGNUAttributeArgs( if (normalizeAttrName(AttrName->getName()) == "enable_if" && D && D->isFunctionDeclarator()) { const DeclaratorChunk::FunctionTypeInfo& FTI = D->getFunctionTypeInfo(); - PrototypeScope.emplace(this, Scope::FunctionPrototypeScope | - Scope::FunctionDeclarationScope | - Scope::DeclScope); + PrototypeScope.emplace(Actions, Scope::FunctionPrototypeScope | + Scope::FunctionDeclarationScope | + Scope::DeclScope); for (unsigned i = 0; i != FTI.NumParams; ++i) { ParmVarDecl *Param = cast(FTI.Params[i].Param); Actions.ActOnReenterCXXMethodParameter(getCurScope(), Param); @@ -2454,7 +2454,7 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes( if (ThisDecl && P.getLangOpts().CPlusPlus) { Scope *S = nullptr; if (D.getCXXScopeSpec().isSet()) { - P.EnterScope(0); + P.Actions.EnterScope(0); S = P.getCurScope(); } if (ThisDecl && !ThisDecl->isInvalidDecl()) { @@ -2472,7 +2472,7 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes( if (Entered) P.Actions.ActOnCXXExitDeclInitializer(S, ThisDecl); if (S) - P.ExitScope(); + P.Actions.ExitScope(); } ThisDecl = nullptr; } @@ -4826,7 +4826,7 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc, if (T.consumeOpen()) return; - ParseScope StructScope(this, Scope::ClassScope|Scope::DeclScope); + ParseScope StructScope(Actions, Scope::ClassScope|Scope::DeclScope); Actions.ActOnTagStartDefinition(getCurScope(), TagDecl); // `LateAttrParseExperimentalExtOnly=true` requests that only attributes @@ -5338,7 +5338,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl, SkipBodyInfo *SkipBody) { // Enter the scope of the enum body and start the definition. - ParseScope EnumScope(this, Scope::DeclScope | Scope::EnumScope); + ParseScope EnumScope(Actions, Scope::DeclScope | Scope::EnumScope); Actions.ActOnTagStartDefinition(getCurScope(), EnumDecl); BalancedDelimiterTracker T(*this, tok::l_brace); @@ -5681,8 +5681,8 @@ Parser::DeclGroupPtrTy Parser::ParseTopLevelStmtDecl() { // Parse a top-level-stmt. Parser::StmtVector Stmts; ParsedStmtContext SubStmtCtx = ParsedStmtContext(); - ParseScope FnScope(this, Scope::FnScope | Scope::DeclScope | - Scope::CompoundStmtScope); + ParseScope FnScope(Actions, Scope::FnScope | Scope::DeclScope | + Scope::CompoundStmtScope); TopLevelStmtDecl *TLSD = Actions.ActOnStartTopLevelStmtDecl(getCurScope()); StmtResult R = ParseStatementOrDeclaration(Stmts, SubStmtCtx); Actions.ActOnFinishTopLevelStmtDecl(TLSD, R.get()); @@ -6804,9 +6804,9 @@ void Parser::ParseDirectDeclarator(Declarator &D) { // Enter function-declaration scope, limiting any declarators to the // function prototype scope, including parameter declarators. ParseScope PrototypeScope( - this, Scope::FunctionPrototypeScope | Scope::DeclScope | - (IsFunctionDeclaration ? Scope::FunctionDeclarationScope - : Scope::NoScope)); + Actions, Scope::FunctionPrototypeScope | Scope::DeclScope | + (IsFunctionDeclaration ? Scope::FunctionDeclarationScope + : Scope::NoScope)); // The paren may be part of a C++ direct initializer, eg. "int x(1);". // In such a case, check if we actually have a function declarator; if it @@ -7085,7 +7085,7 @@ void Parser::ParseParenDeclarator(Declarator &D) { // Enter function-declaration scope, limiting any declarators to the // function prototype scope, including parameter declarators. - ParseScope PrototypeScope(this, + ParseScope PrototypeScope(Actions, Scope::FunctionPrototypeScope | Scope::DeclScope | (D.isFunctionDeclaratorAFunctionDeclaration() ? Scope::FunctionDeclarationScope @@ -8126,7 +8126,7 @@ TypeResult Parser::ParseTypeFromString(StringRef TypeStr, StringRef Context, ConsumeAnyToken(); // Enter a new scope. - ParseScope LocalScope(this, 0); + ParseScope LocalScope(Actions, 0); // Parse the type. TypeResult Result = ParseTypeName(nullptr); diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index d8ed7e3ff96bd..fc7b4d2eb92bf 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -199,7 +199,7 @@ Parser::DeclGroupPtrTy Parser::ParseNamespace(DeclaratorContext Context, : diag::ext_inline_namespace); // Enter a scope for the namespace. - ParseScope NamespaceScope(this, Scope::DeclScope); + ParseScope NamespaceScope(Actions, Scope::DeclScope); UsingDirectiveDecl *ImplicitUsingDirectiveDecl = nullptr; Decl *NamespcDecl = Actions.ActOnStartNamespaceDef( @@ -246,7 +246,7 @@ void Parser::ParseInnerNamespace(const InnerNamespaceInfoList &InnerNSs, // Handle a nested namespace definition. // FIXME: Preserve the source information through to the AST rather than // desugaring it here. - ParseScope NamespaceScope(this, Scope::DeclScope); + ParseScope NamespaceScope(Actions, Scope::DeclScope); UsingDirectiveDecl *ImplicitUsingDirectiveDecl = nullptr; Decl *NamespcDecl = Actions.ActOnStartNamespaceDef( getCurScope(), InnerNSs[index].InlineLoc, InnerNSs[index].NamespaceLoc, @@ -316,7 +316,7 @@ Decl *Parser::ParseLinkage(ParsingDeclSpec &DS, DeclaratorContext Context) { assert(isTokenStringLiteral() && "Not a string literal!"); ExprResult Lang = ParseUnevaluatedStringLiteralExpression(); - ParseScope LinkageScope(this, Scope::DeclScope); + ParseScope LinkageScope(Actions, Scope::DeclScope); Decl *LinkageSpec = Lang.isInvalid() ? nullptr @@ -409,7 +409,7 @@ Decl *Parser::ParseExportDeclaration() { return nullptr; } - ParseScope ExportScope(this, Scope::DeclScope); + ParseScope ExportScope(Actions, Scope::DeclScope); Decl *ExportDecl = Actions.ActOnStartExportDecl( getCurScope(), ExportLoc, Tok.is(tok::l_brace) ? Tok.getLocation() : SourceLocation()); @@ -3385,7 +3385,7 @@ void Parser::SkipCXXMemberSpecification(SourceLocation RecordLoc, // within a template argument). if (Tok.is(tok::colon)) { // Enter the scope of the class so that we can correctly parse its bases. - ParseScope ClassScope(this, Scope::ClassScope | Scope::DeclScope); + ParseScope ClassScope(Actions, Scope::ClassScope | Scope::DeclScope); ParsingClassDefinition ParsingDef(*this, TagDecl, /*NonNestedClass*/ true, TagType == DeclSpec::TST_interface); auto OldContext = @@ -3573,7 +3573,7 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc, } // Enter a scope for the class. - ParseScope ClassScope(this, Scope::ClassScope | Scope::DeclScope); + ParseScope ClassScope(Actions, Scope::ClassScope | Scope::DeclScope); // Note that we are parsing a new (potentially-nested) class definition. ParsingClassDefinition ParsingDef(*this, TagDecl, NonNestedClass, @@ -3678,8 +3678,8 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc, } if (Tok.is(tok::colon)) { - ParseScope InheritanceScope(this, getCurScope()->getFlags() | - Scope::ClassInheritanceScope); + ParseScope InheritanceScope(Actions, getCurScope()->getFlags() | + Scope::ClassInheritanceScope); ParseBaseClause(TagDecl); if (!Tok.is(tok::l_brace)) { @@ -4192,9 +4192,9 @@ void Parser::ParseTrailingRequiresClause(Declarator &D) { DeclScopeObj.EnterDeclaratorScope(); ExprResult TrailingRequiresClause; - ParseScope ParamScope(this, Scope::DeclScope | - Scope::FunctionDeclarationScope | - Scope::FunctionPrototypeScope); + ParseScope ParamScope(Actions, Scope::DeclScope | + Scope::FunctionDeclarationScope | + Scope::FunctionPrototypeScope); Actions.ActOnStartTrailingRequiresClause(getCurScope(), D); diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp index ea3b1749717d2..1f26f886aa702 100644 --- a/clang/lib/Parse/ParseExpr.cpp +++ b/clang/lib/Parse/ParseExpr.cpp @@ -3275,8 +3275,9 @@ ExprResult Parser::ParseBlockLiteralExpression() { // argument decls, decls within the compound expression, etc. This also // allows determining whether a variable reference inside the block is // within or outside of the block. - ParseScope BlockScope(this, Scope::BlockScope | Scope::FnScope | - Scope::CompoundStmtScope | Scope::DeclScope); + ParseScope BlockScope(Actions, Scope::BlockScope | Scope::FnScope | + Scope::CompoundStmtScope | + Scope::DeclScope); // Inform sema that we are starting a block. Actions.ActOnBlockStart(CaretLoc, getCurScope()); diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp index 7a5d28caf8521..73abf2733be01 100644 --- a/clang/lib/Parse/ParseExprCXX.cpp +++ b/clang/lib/Parse/ParseExprCXX.cpp @@ -1219,9 +1219,9 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( Declarator D(DS, ParsedAttributesView::none(), DeclaratorContext::LambdaExpr); TemplateParameterDepthRAII CurTemplateDepthTracker(TemplateParameterDepth); - ParseScope LambdaScope(this, Scope::LambdaScope | Scope::DeclScope | - Scope::FunctionDeclarationScope | - Scope::FunctionPrototypeScope); + ParseScope LambdaScope(Actions, Scope::LambdaScope | Scope::DeclScope | + Scope::FunctionDeclarationScope | + Scope::FunctionPrototypeScope); Actions.PushLambdaScope(); Actions.ActOnLambdaExpressionAfterIntroducer(Intro, getCurScope()); @@ -1249,7 +1249,7 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( D.takeAttributesAppending(Attributes); } - MultiParseScope TemplateParamScope(*this); + MultiParseScope TemplateParamScope(Actions); if (Tok.is(tok::less)) { Diag(Tok, getLangOpts().CPlusPlus20 ? diag::warn_cxx17_compat_lambda_template_parameter_list @@ -1313,9 +1313,9 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( bool HasSpecifiers = false; SourceLocation MutableLoc; - ParseScope Prototype(this, Scope::FunctionPrototypeScope | - Scope::FunctionDeclarationScope | - Scope::DeclScope); + ParseScope Prototype(Actions, Scope::FunctionPrototypeScope | + Scope::FunctionDeclarationScope | + Scope::DeclScope); // Parse parameter-declaration-clause. SmallVector ParamInfo; @@ -1469,7 +1469,7 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( // it. unsigned ScopeFlags = Scope::BlockScope | Scope::FnScope | Scope::DeclScope | Scope::CompoundStmtScope; - ParseScope BodyScope(this, ScopeFlags); + ParseScope BodyScope(Actions, ScopeFlags); Actions.ActOnStartOfLambdaDefinition(Intro, D, DS); @@ -3139,8 +3139,8 @@ ExprResult Parser::ParseRequiresExpression() { BalancedDelimiterTracker Parens(*this, tok::l_paren); if (Tok.is(tok::l_paren)) { // requirement parameter list is present. - ParseScope LocalParametersScope(this, Scope::FunctionPrototypeScope | - Scope::DeclScope); + ParseScope LocalParametersScope(Actions, Scope::FunctionPrototypeScope | + Scope::DeclScope); Parens.consumeOpen(); if (!Tok.is(tok::r_paren)) { ParsedAttributes FirstArgAttrs(getAttrFactory()); @@ -3169,7 +3169,7 @@ ExprResult Parser::ParseRequiresExpression() { EnterExpressionEvaluationContext Ctx( Actions, Sema::ExpressionEvaluationContext::Unevaluated); - ParseScope BodyScope(this, Scope::DeclScope); + ParseScope BodyScope(Actions, Scope::DeclScope); // Create a separate diagnostic pool for RequiresExprBodyDecl. // Dependent diagnostics are attached to this Decl and non-depenedent // diagnostics are surfaced after this parse. diff --git a/clang/lib/Parse/ParseHLSL.cpp b/clang/lib/Parse/ParseHLSL.cpp index c727ee3a1f1a6..f1fc21bee25a6 100644 --- a/clang/lib/Parse/ParseHLSL.cpp +++ b/clang/lib/Parse/ParseHLSL.cpp @@ -65,7 +65,7 @@ Decl *Parser::ParseHLSLBuffer(SourceLocation &DeclEnd, MaybeParseHLSLAnnotations(Attrs, nullptr); - ParseScope BufferScope(this, Scope::DeclScope); + ParseScope BufferScope(Actions, Scope::DeclScope); BalancedDelimiterTracker T(*this, tok::l_brace); if (T.consumeOpen()) { Diag(Tok, diag::err_expected) << tok::l_brace; diff --git a/clang/lib/Parse/ParseObjc.cpp b/clang/lib/Parse/ParseObjc.cpp index 0b9f113d9edc7..27f5a6a54613f 100644 --- a/clang/lib/Parse/ParseObjc.cpp +++ b/clang/lib/Parse/ParseObjc.cpp @@ -1224,8 +1224,9 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, SmallVector KeyIdents; SmallVector KeyLocs; SmallVector ArgInfos; - ParseScope PrototypeScope(this, Scope::FunctionPrototypeScope | - Scope::FunctionDeclarationScope | Scope::DeclScope); + ParseScope PrototypeScope(Actions, Scope::FunctionPrototypeScope | + Scope::FunctionDeclarationScope | + Scope::DeclScope); AttributePool allParamAttrs(AttrFactory); while (true) { @@ -1701,7 +1702,7 @@ void Parser::ParseObjCClassInstanceVariables(ObjCContainerDecl *interfaceDecl, assert(Tok.is(tok::l_brace) && "expected {"); SmallVector AllIvarDecls; - ParseScope ClassScope(this, Scope::DeclScope | Scope::ClassScope); + ParseScope ClassScope(Actions, Scope::DeclScope | Scope::ClassScope); BalancedDelimiterTracker T(*this, tok::l_brace); T.consumeOpen(); @@ -2237,7 +2238,7 @@ Parser::ParseObjCSynchronizedStmt(SourceLocation atLoc) { Actions.ObjC().ActOnObjCAtSynchronizedOperand(atLoc, operand.get()); // Parse the compound statement within a new scope. - ParseScope bodyScope(this, Scope::DeclScope | Scope::CompoundStmtScope); + ParseScope bodyScope(Actions, Scope::DeclScope | Scope::CompoundStmtScope); StmtResult body(ParseCompoundStatementBody()); bodyScope.Exit(); @@ -2263,7 +2264,7 @@ StmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) { } StmtVector CatchStmts; StmtResult FinallyStmt; - ParseScope TryScope(this, Scope::DeclScope | Scope::CompoundStmtScope); + ParseScope TryScope(Actions, Scope::DeclScope | Scope::CompoundStmtScope); StmtResult TryBody(ParseCompoundStatementBody()); TryScope.Exit(); if (TryBody.isInvalid()) @@ -2284,9 +2285,9 @@ StmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) { ConsumeToken(); // consume catch if (Tok.is(tok::l_paren)) { ConsumeParen(); - ParseScope CatchScope(this, Scope::DeclScope | - Scope::CompoundStmtScope | - Scope::AtCatchScope); + ParseScope CatchScope(Actions, Scope::DeclScope | + Scope::CompoundStmtScope | + Scope::AtCatchScope); if (Tok.isNot(tok::ellipsis)) { DeclSpec DS(AttrFactory); ParsedTemplateInfo TemplateInfo; @@ -2331,7 +2332,7 @@ StmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) { } else { assert(Tok.isObjCAtKeyword(tok::objc_finally) && "Lookahead confused?"); ConsumeToken(); // consume finally - ParseScope FinallyScope(this, + ParseScope FinallyScope(Actions, Scope::DeclScope | Scope::CompoundStmtScope); bool ShouldCapture = @@ -2378,7 +2379,7 @@ Parser::ParseObjCAutoreleasePoolStmt(SourceLocation atLoc) { } // Enter a scope to hold everything within the compound stmt. Compound // statements can always hold declarations. - ParseScope BodyScope(this, Scope::DeclScope | Scope::CompoundStmtScope); + ParseScope BodyScope(Actions, Scope::DeclScope | Scope::CompoundStmtScope); StmtResult AutoreleasePoolBody(ParseCompoundStatementBody()); @@ -3295,9 +3296,10 @@ void Parser::ParseLexedObjCMethodDefs(LexedMethod &LM, bool parseMethod) { assert(Tok.isOneOf(tok::l_brace, tok::kw_try, tok::colon) && "Inline objective-c method not starting with '{' or 'try' or ':'"); // Enter a scope for the method or c-function body. - ParseScope BodyScope( - this, (parseMethod ? Scope::ObjCMethodScope : Scope::NoScope) | - Scope::FnScope | Scope::DeclScope | Scope::CompoundStmtScope); + ParseScope BodyScope(Actions, + (parseMethod ? Scope::ObjCMethodScope : Scope::NoScope) | + Scope::FnScope | Scope::DeclScope | + Scope::CompoundStmtScope); Sema::FPFeaturesStateRAII SaveFPFeatures(Actions); // Tell the actions module that we have entered a method or c-function definition diff --git a/clang/lib/Parse/ParseOpenACC.cpp b/clang/lib/Parse/ParseOpenACC.cpp index b79a956d51505..78418ee0a8b2e 100644 --- a/clang/lib/Parse/ParseOpenACC.cpp +++ b/clang/lib/Parse/ParseOpenACC.cpp @@ -1682,7 +1682,7 @@ StmtResult Parser::ParseOpenACCDirectiveStmt() { getActions().OpenACC(), DirInfo.DirKind, DirInfo.DirLoc, {}, DirInfo.Clauses); ParsingOpenACCDirectiveRAII DirScope(*this, /*Value=*/false); - ParseScope ACCScope(this, getOpenACCScopeFlags(DirInfo.DirKind)); + ParseScope ACCScope(Actions, getOpenACCScopeFlags(DirInfo.DirKind)); AssocStmt = getActions().OpenACC().ActOnAssociatedStmt( DirInfo.StartLoc, DirInfo.DirKind, DirInfo.AtomicKind, DirInfo.Clauses, diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp index 32a406e2c065f..8118dff41b89d 100644 --- a/clang/lib/Parse/ParseOpenMP.cpp +++ b/clang/lib/Parse/ParseOpenMP.cpp @@ -246,9 +246,9 @@ Parser::ParseOpenMPDeclareReductionDirective(AccessSpecifier AS) { unsigned I = 0, E = ReductionTypes.size(); for (Decl *D : DRD.get()) { TentativeParsingAction TPA(*this); - ParseScope OMPDRScope(this, Scope::FnScope | Scope::DeclScope | - Scope::CompoundStmtScope | - Scope::OpenMPDirectiveScope); + ParseScope OMPDRScope(Actions, Scope::FnScope | Scope::DeclScope | + Scope::CompoundStmtScope | + Scope::OpenMPDirectiveScope); // Parse expression. Actions.OpenMP().ActOnOpenMPDeclareReductionCombinerStart(getCurScope(), D); ExprResult CombinerResult = Actions.ActOnFinishFullExpr( @@ -282,9 +282,9 @@ Parser::ParseOpenMPDeclareReductionDirective(AccessSpecifier AS) { !T.expectAndConsume(diag::err_expected_lparen_after, "initializer") && IsCorrect; if (Tok.isNot(tok::annot_pragma_openmp_end)) { - ParseScope OMPDRScope(this, Scope::FnScope | Scope::DeclScope | - Scope::CompoundStmtScope | - Scope::OpenMPDirectiveScope); + ParseScope OMPDRScope(Actions, Scope::FnScope | Scope::DeclScope | + Scope::CompoundStmtScope | + Scope::OpenMPDirectiveScope); // Parse expression. VarDecl *OmpPrivParm = Actions.OpenMP().ActOnOpenMPDeclareReductionInitializerStart( @@ -463,7 +463,7 @@ Parser::ParseOpenMPDeclareMapperDirective(AccessSpecifier AS) { SourceLocation Loc = Tok.getLocation(); unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope | Scope::CompoundStmtScope | Scope::OpenMPDirectiveScope; - ParseScope OMPDirectiveScope(this, ScopeFlags); + ParseScope OMPDirectiveScope(Actions, ScopeFlags); Actions.OpenMP().StartOpenMPDSABlock(OMPD_declare_mapper, DirName, getCurScope(), Loc); @@ -611,14 +611,15 @@ namespace { class FNContextRAII final { Parser &P; Sema::CXXThisScopeRAII *ThisScope; - Parser::MultiParseScope Scopes; + MultiParseScope Scopes; bool HasFunScope = false; FNContextRAII() = delete; FNContextRAII(const FNContextRAII &) = delete; FNContextRAII &operator=(const FNContextRAII &) = delete; public: - FNContextRAII(Parser &P, Parser::DeclGroupPtrTy Ptr) : P(P), Scopes(P) { + FNContextRAII(Parser &P, Parser::DeclGroupPtrTy Ptr) + : P(P), Scopes(P.getActions()) { Decl *D = *Ptr.get().begin(); NamedDecl *ND = dyn_cast(D); RecordDecl *RD = dyn_cast_or_null(D->getDeclContext()); @@ -2332,7 +2333,7 @@ StmtResult Parser::ParseOpenMPExecutableDirective( ScopeFlags |= Scope::OpenMPLoopDirectiveScope; if (isOpenMPSimdDirective(DKind)) ScopeFlags |= Scope::OpenMPSimdDirectiveScope; - ParseScope OMPDirectiveScope(this, ScopeFlags); + ParseScope OMPDirectiveScope(Actions, ScopeFlags); Actions.OpenMP().StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope(), Loc); @@ -2459,7 +2460,7 @@ StmtResult Parser::ParseOpenMPInformationalDirective( DeclarationNameInfo DirName; unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope | Scope::CompoundStmtScope | Scope::OpenMPDirectiveScope; - ParseScope OMPDirectiveScope(this, ScopeFlags); + ParseScope OMPDirectiveScope(Actions, ScopeFlags); Actions.OpenMP().StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope(), Loc); @@ -4748,7 +4749,7 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind, // where iterator-specifier is [ iterator-type ] identifier = // range-specification HasIterator = true; - EnterScope(Scope::OpenMPDirectiveScope | Scope::DeclScope); + Actions.EnterScope(Scope::OpenMPDirectiveScope | Scope::DeclScope); ExprResult IteratorRes = ParseOpenMPIteratorsExpr(); Data.DepModOrTailExpr = IteratorRes.get(); // Parse ',' @@ -4861,7 +4862,7 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind, // Handle optional iterator map modifier. if (Tok.is(tok::identifier) && PP.getSpelling(Tok) == "iterator") { HasIterator = true; - EnterScope(Scope::OpenMPDirectiveScope | Scope::DeclScope); + Actions.EnterScope(Scope::OpenMPDirectiveScope | Scope::DeclScope); Data.MapTypeModifiers.push_back(OMPC_MAP_MODIFIER_iterator); Data.MapTypeModifiersLoc.push_back(Tok.getLocation()); ExprResult IteratorRes = ParseOpenMPIteratorsExpr(); @@ -4969,7 +4970,7 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind, Tail = parseOpenMPAllocateClauseModifiers(*this, Kind, Data); } else { HasIterator = true; - EnterScope(Scope::OpenMPDirectiveScope | Scope::DeclScope); + Actions.EnterScope(Scope::OpenMPDirectiveScope | Scope::DeclScope); Tail = ParseOpenMPIteratorsExpr(); } Tail = Actions.ActOnFinishFullExpr(Tail.get(), T.getOpenLocation(), @@ -5028,7 +5029,7 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind, const bool MayHaveTail = (Kind == OMPC_linear || Kind == OMPC_aligned); while (IsComma || (Tok.isNot(tok::r_paren) && Tok.isNot(tok::colon) && Tok.isNot(tok::annot_pragma_openmp_end))) { - ParseScope OMPListScope(this, Scope::OpenMPDirectiveScope); + ParseScope OMPListScope(Actions, Scope::OpenMPDirectiveScope); ColonProtectionRAIIObject ColonRAII(*this, MayHaveTail); if (!ParseOpenMPReservedLocator(Kind, Data, getLangOpts())) { // Parse variable @@ -5143,7 +5144,7 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind, Data.RLoc = T.getCloseLocation(); // Exit from scope when the iterator is used in depend clause. if (HasIterator) - ExitScope(); + Actions.ExitScope(); return (Kind != OMPC_depend && Kind != OMPC_doacross && Kind != OMPC_map && Vars.empty()) || (MustHaveTail && !Data.DepModOrTailExpr && StepFound) || diff --git a/clang/lib/Parse/ParsePragma.cpp b/clang/lib/Parse/ParsePragma.cpp index 7c2b9280f0b76..487d38a9e9e6a 100644 --- a/clang/lib/Parse/ParsePragma.cpp +++ b/clang/lib/Parse/ParsePragma.cpp @@ -934,8 +934,8 @@ StmtResult Parser::HandlePragmaCaptured() SourceLocation Loc = Tok.getLocation(); - ParseScope CapturedRegionScope(this, Scope::FnScope | Scope::DeclScope | - Scope::CompoundStmtScope); + ParseScope CapturedRegionScope(Actions, Scope::FnScope | Scope::DeclScope | + Scope::CompoundStmtScope); Actions.ActOnCapturedRegionStart(Loc, getCurScope(), CR_Default, /*NumParams=*/1); diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp index 0c652fc3c16f3..59eac05e8f39e 100644 --- a/clang/lib/Parse/ParseStmt.cpp +++ b/clang/lib/Parse/ParseStmt.cpp @@ -645,8 +645,8 @@ StmtResult Parser::ParseSEHExceptBlock(SourceLocation ExceptLoc) { if (ExpectAndConsume(tok::l_paren)) return StmtError(); - ParseScope ExpectScope(this, Scope::DeclScope | Scope::ControlScope | - Scope::SEHExceptScope); + ParseScope ExpectScope(Actions, Scope::DeclScope | Scope::ControlScope | + Scope::SEHExceptScope); if (getLangOpts().Borland) { Ident__exception_info->setIsPoisoned(false); @@ -692,7 +692,7 @@ StmtResult Parser::ParseSEHFinallyBlock(SourceLocation FinallyLoc) { if (Tok.isNot(tok::l_brace)) return StmtError(Diag(Tok, diag::err_expected) << tok::l_brace); - ParseScope FinallyScope(this, 0); + ParseScope FinallyScope(Actions, 0); Actions.ActOnStartSEHFinallyBlock(); StmtResult Block(ParseCompoundStatement()); @@ -1003,7 +1003,7 @@ StmtResult Parser::ParseCompoundStatement(bool isStmtExpr, // Enter a scope to hold everything within the compound stmt. Compound // statements can always hold declarations. - ParseScope CompoundScope(this, ScopeFlags); + ParseScope CompoundScope(Actions, ScopeFlags); // Parse the statements in the body. StmtResult R; @@ -1494,7 +1494,7 @@ StmtResult Parser::ParseIfStatement(SourceLocation *TrailingElseLoc) { // while, for, and switch statements are local to the if, while, for, or // switch statement (including the controlled statement). // - ParseScope IfScope(this, Scope::DeclScope | Scope::ControlScope, C99orCXX); + ParseScope IfScope(Actions, Scope::DeclScope | Scope::ControlScope, C99orCXX); // Parse the condition. StmtResult InitStmt; @@ -1534,7 +1534,7 @@ StmtResult Parser::ParseIfStatement(SourceLocation *TrailingElseLoc) { // would have to notify ParseStatement not to create a new scope. It's // simpler to let it create a new scope. // - ParseScope InnerScope(this, Scope::DeclScope, C99orCXX, IsBracedThen); + ParseScope InnerScope(Actions, Scope::DeclScope, C99orCXX, IsBracedThen); MisleadingIndentationChecker MIChecker(*this, MSK_if, IfLoc); @@ -1585,7 +1585,7 @@ StmtResult Parser::ParseIfStatement(SourceLocation *TrailingElseLoc) { // The substatement in a selection-statement (each substatement, in the else // form of the if statement) implicitly defines a local scope. // - ParseScope InnerScope(this, Scope::DeclScope, C99orCXX, + ParseScope InnerScope(Actions, Scope::DeclScope, C99orCXX, Tok.is(tok::l_brace)); MisleadingIndentationChecker MIChecker(*this, MSK_else, ElseLoc); @@ -1691,7 +1691,7 @@ StmtResult Parser::ParseSwitchStatement(SourceLocation *TrailingElseLoc, unsigned ScopeFlags = Scope::SwitchScope; if (C99orCXX) ScopeFlags |= Scope::DeclScope | Scope::ControlScope; - ParseScope SwitchScope(this, ScopeFlags); + ParseScope SwitchScope(Actions, ScopeFlags); // Parse the condition. StmtResult InitStmt; @@ -1731,7 +1731,8 @@ StmtResult Parser::ParseSwitchStatement(SourceLocation *TrailingElseLoc, // getCurScope()->AddFlags(Scope::BreakScope); getCurScope()->setPrecedingLabel(PrecedingLabel); - ParseScope InnerScope(this, Scope::DeclScope, C99orCXX, Tok.is(tok::l_brace)); + ParseScope InnerScope(Actions, Scope::DeclScope, C99orCXX, + Tok.is(tok::l_brace)); // We have incremented the mangling number for the SwitchScope and the // InnerScope, which is one too many. @@ -1780,7 +1781,7 @@ StmtResult Parser::ParseWhileStatement(SourceLocation *TrailingElseLoc, Scope::DeclScope | Scope::ControlScope; else ScopeFlags = Scope::BreakScope | Scope::ContinueScope; - ParseScope WhileScope(this, ScopeFlags); + ParseScope WhileScope(Actions, ScopeFlags); // Parse the condition. Sema::ConditionResult Cond; @@ -1807,7 +1808,8 @@ StmtResult Parser::ParseWhileStatement(SourceLocation *TrailingElseLoc, // See comments in ParseIfStatement for why we create a scope for the // condition and a new scope for substatement in C++. // - ParseScope InnerScope(this, Scope::DeclScope, C99orCXX, Tok.is(tok::l_brace)); + ParseScope InnerScope(Actions, Scope::DeclScope, C99orCXX, + Tok.is(tok::l_brace)); MisleadingIndentationChecker MIChecker(*this, MSK_while, WhileLoc); @@ -1838,7 +1840,7 @@ StmtResult Parser::ParseDoStatement(LabelDecl *PrecedingLabel) { else ScopeFlags = Scope::BreakScope | Scope::ContinueScope; - ParseScope DoScope(this, ScopeFlags); + ParseScope DoScope(Actions, ScopeFlags); // OpenACC Restricts a do-while-loop inside of certain construct/clause // combinations, so diagnose that here in OpenACC mode. @@ -1855,7 +1857,8 @@ StmtResult Parser::ParseDoStatement(LabelDecl *PrecedingLabel) { // which is entered and exited each time through the loop. // bool C99orCXX = getLangOpts().C99 || getLangOpts().CPlusPlus; - ParseScope InnerScope(this, Scope::DeclScope, C99orCXX, Tok.is(tok::l_brace)); + ParseScope InnerScope(Actions, Scope::DeclScope, C99orCXX, + Tok.is(tok::l_brace)); // Read the body statement. StmtResult Body(ParseStatement()); @@ -2013,7 +2016,7 @@ Parser::ParseForStatement(SourceLocation *TrailingElseLoc, if (CXXExpansionStmtDecl) ScopeFlags |= Scope::TemplateParamScope; - ParseScope ForScope(this, ScopeFlags); + ParseScope ForScope(Actions, ScopeFlags); BalancedDelimiterTracker T(*this, tok::l_paren); T.consumeOpen(); @@ -2333,7 +2336,7 @@ Parser::ParseForStatement(SourceLocation *TrailingElseLoc, // See comments in ParseIfStatement for why we create a scope for // for-init-statement/condition and a new scope for substatement in C++. // - ParseScope InnerScope(this, Scope::DeclScope, C99orCXXorObjC, + ParseScope InnerScope(Actions, Scope::DeclScope, C99orCXXorObjC, Tok.is(tok::l_brace)); // The body of the for loop has the same local mangling number as the @@ -2698,8 +2701,8 @@ StmtResult Parser::ParseCXXCatchBlock(bool FnCatch) { // The name in a catch exception-declaration is local to the handler and // shall not be redeclared in the outermost block of the handler. ParseScope CatchScope( - this, Scope::DeclScope | Scope::ControlScope | Scope::CatchScope | - (FnCatch ? Scope::FnTryCatchScope : Scope::NoScope)); + Actions, Scope::DeclScope | Scope::ControlScope | Scope::CatchScope | + (FnCatch ? Scope::FnTryCatchScope : Scope::NoScope)); // exception-declaration is equivalent to '...' or a parameter-declaration // without default arguments. diff --git a/clang/lib/Parse/ParseTemplate.cpp b/clang/lib/Parse/ParseTemplate.cpp index 330a9c6aea0c5..78a4892f3b47e 100644 --- a/clang/lib/Parse/ParseTemplate.cpp +++ b/clang/lib/Parse/ParseTemplate.cpp @@ -50,7 +50,7 @@ Parser::DeclGroupPtrTy Parser::ParseTemplateDeclarationOrSpecialization( assert(Tok.isOneOf(tok::kw_export, tok::kw_template) && "Token does not start a template declaration."); - MultiParseScope TemplateParamScopes(*this); + MultiParseScope TemplateParamScopes(Actions); // Tell the action that names should be checked in the context of // the declaration to come. @@ -700,7 +700,7 @@ NamedDecl *Parser::ParseTemplateTemplateParameter(unsigned Depth, SourceLocation LAngleLoc, RAngleLoc; ExprResult OptionalRequiresClauseConstraintER; { - MultiParseScope TemplateParmScope(*this); + MultiParseScope TemplateParmScope(Actions); if (ParseTemplateParameters(TemplateParmScope, Depth + 1, TemplateParams, LAngleLoc, RAngleLoc)) { return nullptr; @@ -1456,7 +1456,7 @@ void Parser::ParseLateTemplatedFuncDef(LateParsedTemplate &LPT) { Sema::ContextRAII GlobalSavedContext( Actions, Actions.Context.getTranslationUnitDecl()); - MultiParseScope Scopes(*this); + MultiParseScope Scopes(Actions); // Get the list of DeclContexts to reenter. SmallVector DeclContextsToReenter; @@ -1493,8 +1493,8 @@ void Parser::ParseLateTemplatedFuncDef(LateParsedTemplate &LPT) { // Parse the method body. Function body parsing code is similar enough // to be re-used for method bodies as well. - ParseScope FnScope(this, Scope::FnScope | Scope::DeclScope | - Scope::CompoundStmtScope); + ParseScope FnScope(Actions, Scope::FnScope | Scope::DeclScope | + Scope::CompoundStmtScope); // Recreate the containing function DeclContext. Sema::ContextRAII FunctionSavedContext(Actions, FunD->getLexicalParent()); diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp index a6fc676f23a51..4aa14e0b6d7a8 100644 --- a/clang/lib/Parse/Parser.cpp +++ b/clang/lib/Parse/Parser.cpp @@ -64,7 +64,6 @@ Parser::Parser(Preprocessor &pp, Sema &actions, bool skipFunctionBodies) Tok.startToken(); Tok.setKind(tok::eof); Actions.CurScope = nullptr; - NumCachedScopes = 0; CurParsedObjCImpl = nullptr; // Add #pragma handlers. These are removed and destroyed in the @@ -416,33 +415,6 @@ bool Parser::SkipUntil(ArrayRef Toks, SkipUntilFlags Flags) { //===----------------------------------------------------------------------===// // Scope manipulation //===----------------------------------------------------------------------===// - -void Parser::EnterScope(unsigned ScopeFlags) { - if (NumCachedScopes) { - Scope *N = ScopeCache[--NumCachedScopes]; - N->Init(getCurScope(), ScopeFlags); - Actions.CurScope = N; - } else { - Actions.CurScope = new Scope(getCurScope(), ScopeFlags, Diags); - } -} - -void Parser::ExitScope() { - assert(getCurScope() && "Scope imbalance!"); - - // Inform the actions module that this scope is going away if there are any - // decls in it. - Actions.ActOnPopScope(Tok.getLocation(), getCurScope()); - - Scope *OldScope = getCurScope(); - Actions.CurScope = OldScope->getParent(); - - if (NumCachedScopes == ScopeCacheSize) - delete OldScope; - else - ScopeCache[NumCachedScopes++] = OldScope; -} - Parser::ParseScopeFlags::ParseScopeFlags(Parser *Self, unsigned ScopeFlags, bool ManageFlags) : CurScope(ManageFlags ? Self->getCurScope() : nullptr) { @@ -463,13 +435,7 @@ Parser::ParseScopeFlags::~ParseScopeFlags() { //===----------------------------------------------------------------------===// Parser::~Parser() { - // If we still have scopes active, delete the scope tree. - delete getCurScope(); - Actions.CurScope = nullptr; - - // Free the scope cache. - for (unsigned i = 0, e = NumCachedScopes; i != e; ++i) - delete ScopeCache[i]; + Actions.FreeScopes(); resetPragmaHandlers(); @@ -483,7 +449,7 @@ Parser::~Parser() { void Parser::Initialize() { // Create the translation unit scope. Install it as the current scope. assert(getCurScope() == nullptr && "A scope is already active?"); - EnterScope(Scope::DeclScope); + Actions.EnterScope(Scope::DeclScope); Actions.ActOnTranslationUnitScope(getCurScope()); // Initialization for Objective-C context sensitive keywords recognition. @@ -1275,8 +1241,8 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D, LateParsedAttrs->empty() && Actions.canDelayFunctionBody(D)) { MultiTemplateParamsArg TemplateParameterLists(*TemplateInfo.TemplateParams); - ParseScope BodyScope(this, Scope::FnScope | Scope::DeclScope | - Scope::CompoundStmtScope); + ParseScope BodyScope(Actions, Scope::FnScope | Scope::DeclScope | + Scope::CompoundStmtScope); Scope *ParentScope = getCurScope()->getParent(); D.setFunctionDefinitionKind(FunctionDefinitionKind::Definition); @@ -1304,8 +1270,8 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D, if (CurParsedObjCImpl && !TemplateInfo.TemplateParams && (Tok.is(tok::l_brace) || Tok.is(tok::kw_try) || Tok.is(tok::colon)) && Actions.CurContext->isTranslationUnit()) { - ParseScope BodyScope(this, Scope::FnScope | Scope::DeclScope | - Scope::CompoundStmtScope); + ParseScope BodyScope(Actions, Scope::FnScope | Scope::DeclScope | + Scope::CompoundStmtScope); Scope *ParentScope = getCurScope()->getParent(); D.setFunctionDefinitionKind(FunctionDefinitionKind::Definition); @@ -1323,8 +1289,8 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D, } // Enter a scope for the function body. - ParseScope BodyScope(this, Scope::FnScope | Scope::DeclScope | - Scope::CompoundStmtScope); + ParseScope BodyScope(Actions, Scope::FnScope | Scope::DeclScope | + Scope::CompoundStmtScope); // Parse function body eagerly if it is either '= delete;' or '= default;' as // ActOnStartOfFunctionDef needs to know whether the function is deleted. @@ -1476,8 +1442,9 @@ void Parser::ParseKNRParamDeclarations(Declarator &D) { // Enter function-declaration scope, limiting any declarators to the // function prototype scope, including parameter declarators. - ParseScope PrototypeScope(this, Scope::FunctionPrototypeScope | - Scope::FunctionDeclarationScope | Scope::DeclScope); + ParseScope PrototypeScope(Actions, Scope::FunctionPrototypeScope | + Scope::FunctionDeclarationScope | + Scope::DeclScope); // Read all the argument declarations. while (isDeclarationSpecifier(ImplicitTypenameContext::No)) { diff --git a/clang/lib/Sema/Scope.cpp b/clang/lib/Sema/Scope.cpp index e66cce255230b..79938b5db5b52 100644 --- a/clang/lib/Sema/Scope.cpp +++ b/clang/lib/Sema/Scope.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "clang/Sema/Scope.h" +#include "clang/Sema/Sema.h" #include "clang/AST/Decl.h" #include "llvm/Support/raw_ostream.h" @@ -268,3 +269,35 @@ void Scope::dumpImpl(raw_ostream &OS) const { else OS << "NRVO is not allowed\n"; } + +ParseScope::ParseScope(Sema &S, unsigned ScopeFlags, bool EnteredScope, + bool BeforeCompoundStmt) + : S(&S) { + if (EnteredScope && !BeforeCompoundStmt) + S.EnterScope(ScopeFlags); + else { + if (BeforeCompoundStmt) + S.incrementMSManglingNumber(); + + this->S = nullptr; + } +} + +void ParseScope::Exit() { + if (S) { + S->ExitScope(); + S = nullptr; + } +} + +void MultiParseScope::Enter(unsigned ScopeFlags) { + S.EnterScope(ScopeFlags); + ++NumScopes; +} + +void MultiParseScope::Exit() { + while (NumScopes) { + S.ExitScope(); + --NumScopes; + } +} diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index 5fbfb4023ee4d..efd33fd393dd0 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -620,6 +620,7 @@ Sema::~Sema() { // Detach from the PP callback handler which outlives Sema since it's owned // by the preprocessor. SemaPPCallbackHandler->reset(); + FreeScopes(); } void Sema::runWithSufficientStackSpace(SourceLocation Loc, @@ -2962,3 +2963,34 @@ Attr *Sema::CreateAnnotationAttr(const ParsedAttr &AL) { return CreateAnnotationAttr(AL, Str, Args); } + +void Sema::EnterScope(unsigned ScopeFlags) { + if (!ScopeCache.empty()) { + Scope *N = ScopeCache.pop_back_val().release(); + N->Init(getCurScope(), ScopeFlags); + CurScope = N; + } else { + CurScope = new Scope(getCurScope(), ScopeFlags, Diags); + } +} + +void Sema::ExitScope() { + assert(getCurScope() && "Scope imbalance!"); + ActOnPopScope(getCurScope()); + Scope *OldScope = getCurScope(); + CurScope = OldScope->getParent(); + if (ScopeCache.size() == MaxScopeCacheSize) + delete OldScope; + else + ScopeCache.emplace_back(OldScope); +} + +void Sema::FreeScopes() { + // Take care not to delete 'CurScope' twice. + auto IsCurScope = [&](auto& S) { return S.get() == CurScope; }; + if (llvm::find_if(ScopeCache, IsCurScope) == ScopeCache.end()) + delete CurScope; + + ScopeCache.clear(); + CurScope = nullptr; +} diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 180f532561ece..c260df676570c 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -2255,7 +2255,7 @@ static void CheckPoppedLabel(LabelDecl *L, Sema &S, << L); } -void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) { +void Sema::ActOnPopScope(Scope *S) { S->applyNRVO(); if (S->decl_empty()) return; diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index 655fa31bbf5c7..da1005f8a6d80 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -2409,8 +2409,8 @@ void NoteForRangeBeginEndFunction(Sema &SemaRef, Expr *E, } /// Build a variable declaration for a for-range statement. -VarDecl *BuildForRangeVarDecl(Sema &SemaRef, SourceLocation Loc, - QualType Type, StringRef Name) { +VarDecl *BuildForRangeVarDecl(Sema &SemaRef, SourceLocation Loc, QualType Type, + StringRef Name, bool ForExpansionStmt) { DeclContext *DC = SemaRef.CurContext; IdentifierInfo *II = &SemaRef.PP.getIdentifierTable().get(Name); TypeSourceInfo *TInfo = SemaRef.Context.getTrivialTypeSourceInfo(Type, Loc); @@ -2420,7 +2420,6 @@ VarDecl *BuildForRangeVarDecl(Sema &SemaRef, SourceLocation Loc, Decl->setCXXForRangeImplicitVar(true); return Decl; } - } static bool ObjCEnumerationCollection(Expr *Collection) { @@ -2428,6 +2427,25 @@ static bool ObjCEnumerationCollection(Expr *Collection) { && Collection->getType()->getAs() != nullptr; } +StmtResult Sema::BuildCXXForRangeRangeVar(Scope *S, Expr *Range, QualType Type, + bool Constexpr) { + + // Divide by 2, since the variables are in the inner scope (loop body). + const auto DepthStr = std::to_string(S->getDepth() / 2); + SourceLocation RangeLoc = Range->getBeginLoc(); + VarDecl *RangeVar = BuildForRangeVarDecl( + *this, RangeLoc, Type, std::string("__range") + DepthStr, Constexpr); + if (FinishForRangeVarDecl(*this, RangeVar, Range, RangeLoc, + diag::err_for_range_deduction_failure)) + + return StmtError(); + + // Claim the type doesn't contain auto: we've already done the checking. + DeclGroupPtrTy RangeGroup = + BuildDeclaratorGroup(MutableArrayRef((Decl **)&RangeVar, 1)); + return ActOnDeclStmt(RangeGroup, RangeLoc, RangeLoc); +} + StmtResult Sema::ActOnCXXForRangeStmt( Scope *S, SourceLocation ForLoc, SourceLocation CoawaitLoc, Stmt *InitStmt, Stmt *First, SourceLocation ColonLoc, Expr *Range, SourceLocation RParenLoc, @@ -2472,22 +2490,8 @@ StmtResult Sema::ActOnCXXForRangeStmt( } // Build auto && __range = range-init - // Divide by 2, since the variables are in the inner scope (loop body). - const auto DepthStr = std::to_string(S->getDepth() / 2); - SourceLocation RangeLoc = Range->getBeginLoc(); - VarDecl *RangeVar = BuildForRangeVarDecl(*this, RangeLoc, - Context.getAutoRRefDeductType(), - std::string("__range") + DepthStr); - if (FinishForRangeVarDecl(*this, RangeVar, Range, RangeLoc, - diag::err_for_range_deduction_failure)) { - ActOnInitializerError(LoopVar); - return StmtError(); - } - - // Claim the type doesn't contain auto: we've already done the checking. - DeclGroupPtrTy RangeGroup = - BuildDeclaratorGroup(MutableArrayRef((Decl **)&RangeVar, 1)); - StmtResult RangeDecl = ActOnDeclStmt(RangeGroup, RangeLoc, RangeLoc); + auto RangeDecl = + BuildCXXForRangeRangeVar(S, Range, Context.getAutoRRefDeductType()); if (RangeDecl.isInvalid()) { ActOnInitializerError(LoopVar); return StmtError(); @@ -2686,6 +2690,226 @@ static StmtResult RebuildForRangeWithDereference(Sema &SemaRef, Scope *S, AdjustedRange.get(), RParenLoc, Sema::BFRK_Rebuild); } +void Sema::ApplyForRangeOrExpansionStatementLifetimeExtension( + VarDecl *RangeVar, ArrayRef Temporaries) { + if (Temporaries.empty()) + return; + + InitializedEntity Entity = InitializedEntity::InitializeVariable(RangeVar); + for (auto *MTE : Temporaries) + MTE->setExtendingDecl(RangeVar, Entity.allocateManglingNumber()); +} + +Sema::ForRangeBeginEndInfo Sema::BuildCXXForRangeBeginEndVars( + Scope *S, VarDecl *RangeVar, SourceLocation ColonLoc, + SourceLocation CoawaitLoc, + ArrayRef LifetimeExtendTemps, + BuildForRangeKind Kind, bool Constexpr, StmtResult *RebuildResult, + llvm::function_ref RebuildWithDereference) { + QualType RangeVarType = RangeVar->getType(); + SourceLocation RangeLoc = RangeVar->getLocation(); + const QualType RangeVarNonRefType = RangeVarType.getNonReferenceType(); + + ExprResult BeginRangeRef = + BuildDeclRefExpr(RangeVar, RangeVarNonRefType, VK_LValue, ColonLoc); + if (BeginRangeRef.isInvalid()) + return {}; + + ExprResult EndRangeRef = + BuildDeclRefExpr(RangeVar, RangeVarNonRefType, VK_LValue, ColonLoc); + if (EndRangeRef.isInvalid()) + return {}; + + QualType AutoType = Context.getAutoDeductType(); + Expr *Range = RangeVar->getInit(); + if (!Range) + return {}; + QualType RangeType = Range->getType(); + + if (RequireCompleteType(RangeLoc, RangeType, + diag::err_for_range_incomplete_type)) + return {}; + + // P2718R0 - Lifetime extension in range-based for loops. + if (getLangOpts().CPlusPlus23) + ApplyForRangeOrExpansionStatementLifetimeExtension(RangeVar, + LifetimeExtendTemps); + + // Build auto __begin = begin-expr, __end = end-expr. + // Divide by 2, since the variables are in the inner scope (loop body). + const auto DepthStr = std::to_string(S->getDepth() / 2); + VarDecl *BeginVar = + BuildForRangeVarDecl(*this, ColonLoc, AutoType, + std::string("__begin") + DepthStr, Constexpr); + VarDecl *EndVar = + BuildForRangeVarDecl(*this, ColonLoc, AutoType, + std::string("__end") + DepthStr, Constexpr); + + // Build begin-expr and end-expr and attach to __begin and __end variables. + ExprResult BeginExpr, EndExpr; + if (const ArrayType *UnqAT = RangeType->getAsArrayTypeUnsafe()) { + // - if _RangeT is an array type, begin-expr and end-expr are __range and + // __range + __bound, respectively, where __bound is the array bound. If + // _RangeT is an array of unknown size or an array of incomplete type, + // the program is ill-formed; + + // begin-expr is __range. + BeginExpr = BeginRangeRef; + if (!CoawaitLoc.isInvalid()) { + BeginExpr = ActOnCoawaitExpr(S, ColonLoc, BeginExpr.get()); + if (BeginExpr.isInvalid()) + return {}; + } + if (FinishForRangeVarDecl(*this, BeginVar, BeginRangeRef.get(), ColonLoc, + diag::err_for_range_iter_deduction_failure)) { + NoteForRangeBeginEndFunction(*this, BeginExpr.get(), BEF_begin); + return {}; + } + + // Find the array bound. + ExprResult BoundExpr; + if (const ConstantArrayType *CAT = dyn_cast(UnqAT)) + BoundExpr = IntegerLiteral::Create( + Context, CAT->getSize(), Context.getPointerDiffType(), RangeLoc); + else if (const VariableArrayType *VAT = + dyn_cast(UnqAT)) { + // For a variably modified type we can't just use the expression within + // the array bounds, since we don't want that to be re-evaluated here. + // Rather, we need to determine what it was when the array was first + // created - so we resort to using sizeof(vla)/sizeof(element). + // For e.g. + // void f(int b) { + // int vla[b]; + // b = -1; <-- This should not affect the num of iterations below + // for (int &c : vla) { .. } + // } + + // FIXME: This results in codegen generating IR that recalculates the + // run-time number of elements (as opposed to just using the IR Value + // that corresponds to the run-time value of each bound that was + // generated when the array was created.) If this proves too embarrassing + // even for unoptimized IR, consider passing a magic-value/cookie to + // codegen that then knows to simply use that initial llvm::Value (that + // corresponds to the bound at time of array creation) within + // getelementptr. But be prepared to pay the price of increasing a + // customized form of coupling between the two components - which could + // be hard to maintain as the codebase evolves. + + ExprResult SizeOfVLAExprR = ActOnUnaryExprOrTypeTraitExpr( + EndVar->getLocation(), UETT_SizeOf, + /*IsType=*/true, + CreateParsedType(VAT->desugar(), Context.getTrivialTypeSourceInfo( + VAT->desugar(), RangeLoc)) + .getAsOpaquePtr(), + EndVar->getSourceRange()); + if (SizeOfVLAExprR.isInvalid()) + return {}; + + ExprResult SizeOfEachElementExprR = ActOnUnaryExprOrTypeTraitExpr( + EndVar->getLocation(), UETT_SizeOf, + /*IsType=*/true, + CreateParsedType(VAT->desugar(), Context.getTrivialTypeSourceInfo( + VAT->getElementType(), RangeLoc)) + .getAsOpaquePtr(), + EndVar->getSourceRange()); + if (SizeOfEachElementExprR.isInvalid()) + return {}; + + BoundExpr = + ActOnBinOp(S, EndVar->getLocation(), tok::slash, SizeOfVLAExprR.get(), + SizeOfEachElementExprR.get()); + if (BoundExpr.isInvalid()) + return {}; + + } else { + // Can't be a DependentSizedArrayType or an IncompleteArrayType since + // UnqAT is not incomplete and Range is not type-dependent. + llvm_unreachable("Unexpected array type in for-range"); + } + + // end-expr is __range + __bound. + EndExpr = + ActOnBinOp(S, ColonLoc, tok::plus, EndRangeRef.get(), BoundExpr.get()); + if (EndExpr.isInvalid()) + return {}; + if (FinishForRangeVarDecl(*this, EndVar, EndExpr.get(), ColonLoc, + diag::err_for_range_iter_deduction_failure)) { + NoteForRangeBeginEndFunction(*this, EndExpr.get(), BEF_end); + return {}; + } + } else { + OverloadCandidateSet CandidateSet(RangeLoc, + OverloadCandidateSet::CSK_Normal); + BeginEndFunction BEFFailure; + ForRangeStatus RangeStatus = + BuildNonArrayForRange(*this, BeginRangeRef.get(), EndRangeRef.get(), + RangeType, BeginVar, EndVar, ColonLoc, CoawaitLoc, + &CandidateSet, &BeginExpr, &EndExpr, &BEFFailure); + + if (Kind == BFRK_Build && RangeStatus == FRS_NoViableFunction && + BEFFailure == BEF_begin) { + // If the range is being built from an array parameter, emit a + // a diagnostic that it is being treated as a pointer. + if (DeclRefExpr *DRE = dyn_cast(Range)) { + if (ParmVarDecl *PVD = dyn_cast(DRE->getDecl())) { + QualType ArrayTy = PVD->getOriginalType(); + QualType PointerTy = PVD->getType(); + if (PointerTy->isPointerType() && ArrayTy->isArrayType()) { + Diag(Range->getBeginLoc(), diag::err_range_on_array_parameter) + << RangeLoc << PVD << ArrayTy << PointerTy; + Diag(PVD->getLocation(), diag::note_declared_at); + return {}; + } + } + } + + // If building the range failed, try dereferencing the range expression + // unless a diagnostic was issued or the end function is problematic. + if (RebuildWithDereference) { + assert(RebuildResult); + StmtResult SR = RebuildWithDereference(); + if (SR.isInvalid() || SR.isUsable()) { + *RebuildResult = SR; + return {}; + } + } + } + + // Otherwise, emit diagnostics if we haven't already. + if (RangeStatus == FRS_NoViableFunction) { + Expr *Range = BEFFailure ? EndRangeRef.get() : BeginRangeRef.get(); + CandidateSet.NoteCandidates( + PartialDiagnosticAt(Range->getBeginLoc(), + PDiag(diag::err_for_range_invalid) + << RangeLoc << Range->getType() + << BEFFailure), + *this, OCD_AllCandidates, Range); + } + // Return an error if no fix was discovered. + if (RangeStatus != FRS_Success) + return {}; + } + + assert(!BeginExpr.isInvalid() && !EndExpr.isInvalid() && + "invalid range expression in for loop"); + + return {BeginVar, EndVar, BeginExpr.get(), EndExpr.get()}; +} + +void Sema::ActOnDependentForRangeInitializer(VarDecl *LoopVar, + BuildForRangeKind BFRK) { + // Deduce any 'auto's in the loop variable as 'DependentTy'. We'll fill + // them in properly when we instantiate the loop. + if (!LoopVar->isInvalidDecl() && BFRK != BFRK_Check) { + if (auto *DD = dyn_cast(LoopVar)) + for (auto *Binding : DD->bindings()) { + if (!Binding->isParameterPack()) + Binding->setType(Context.DependentTy); + } + LoopVar->setType(SubstAutoTypeDependent(LoopVar->getType())); + } +} + StmtResult Sema::BuildCXXForRangeStmt( SourceLocation ForLoc, SourceLocation CoawaitLoc, Stmt *InitStmt, SourceLocation ColonLoc, Stmt *RangeDecl, Stmt *Begin, Stmt *End, @@ -2717,216 +2941,36 @@ StmtResult Sema::BuildCXXForRangeStmt( if (RangeVarType->isDependentType()) { // The range is implicitly used as a placeholder when it is dependent. RangeVar->markUsed(Context); - - // Deduce any 'auto's in the loop variable as 'DependentTy'. We'll fill - // them in properly when we instantiate the loop. - if (!LoopVar->isInvalidDecl() && Kind != BFRK_Check) { - if (auto *DD = dyn_cast(LoopVar)) - for (auto *Binding : DD->bindings()) { - if (!Binding->isParameterPack()) - Binding->setType(Context.DependentTy); - } - LoopVar->setType(SubstAutoTypeDependent(LoopVar->getType())); - } + ActOnDependentForRangeInitializer(LoopVar, Kind); } else if (!BeginDeclStmt.get()) { - SourceLocation RangeLoc = RangeVar->getLocation(); - - const QualType RangeVarNonRefType = RangeVarType.getNonReferenceType(); - - ExprResult BeginRangeRef = BuildDeclRefExpr(RangeVar, RangeVarNonRefType, - VK_LValue, ColonLoc); - if (BeginRangeRef.isInvalid()) - return StmtError(); - - ExprResult EndRangeRef = BuildDeclRefExpr(RangeVar, RangeVarNonRefType, - VK_LValue, ColonLoc); - if (EndRangeRef.isInvalid()) - return StmtError(); + StmtResult RebuildResult; + auto RebuildWithDereference = [&] { + return RebuildForRangeWithDereference( + *this, S, ForLoc, CoawaitLoc, InitStmt, LoopVarDecl, ColonLoc, + RangeVar->getInit(), RangeVar->getLocation(), RParenLoc); + }; - QualType AutoType = Context.getAutoDeductType(); - Expr *Range = RangeVar->getInit(); - if (!Range) - return StmtError(); - QualType RangeType = Range->getType(); + auto BeginRangeRefTy = RangeVar->getType().getNonReferenceType(); + auto [BeginVar, EndVar, BeginExpr, EndExpr] = BuildCXXForRangeBeginEndVars( + S, RangeVar, ColonLoc, CoawaitLoc, LifetimeExtendTemps, Kind, + /*Constexpr=*/false, &RebuildResult, RebuildWithDereference); - if (RequireCompleteType(RangeLoc, RangeType, - diag::err_for_range_incomplete_type)) + if (!RebuildResult.isUnset()) + return RebuildResult; + if (!BeginVar || !EndVar) return StmtError(); - // P2718R0 - Lifetime extension in range-based for loops. - if (getLangOpts().CPlusPlus23 && !LifetimeExtendTemps.empty()) { - InitializedEntity Entity = - InitializedEntity::InitializeVariable(RangeVar); - for (auto *MTE : LifetimeExtendTemps) - MTE->setExtendingDecl(RangeVar, Entity.allocateManglingNumber()); - } - - // Build auto __begin = begin-expr, __end = end-expr. - // Divide by 2, since the variables are in the inner scope (loop body). - const auto DepthStr = std::to_string(S->getDepth() / 2); - VarDecl *BeginVar = BuildForRangeVarDecl(*this, ColonLoc, AutoType, - std::string("__begin") + DepthStr); - VarDecl *EndVar = BuildForRangeVarDecl(*this, ColonLoc, AutoType, - std::string("__end") + DepthStr); - - // Build begin-expr and end-expr and attach to __begin and __end variables. - ExprResult BeginExpr, EndExpr; - if (const ArrayType *UnqAT = RangeType->getAsArrayTypeUnsafe()) { - // - if _RangeT is an array type, begin-expr and end-expr are __range and - // __range + __bound, respectively, where __bound is the array bound. If - // _RangeT is an array of unknown size or an array of incomplete type, - // the program is ill-formed; - - // begin-expr is __range. - BeginExpr = BeginRangeRef; - if (!CoawaitLoc.isInvalid()) { - BeginExpr = ActOnCoawaitExpr(S, ColonLoc, BeginExpr.get()); - if (BeginExpr.isInvalid()) - return StmtError(); - } - if (FinishForRangeVarDecl(*this, BeginVar, BeginRangeRef.get(), ColonLoc, - diag::err_for_range_iter_deduction_failure)) { - NoteForRangeBeginEndFunction(*this, BeginExpr.get(), BEF_begin); - return StmtError(); - } - - // Find the array bound. - ExprResult BoundExpr; - if (const ConstantArrayType *CAT = dyn_cast(UnqAT)) - BoundExpr = IntegerLiteral::Create( - Context, CAT->getSize(), Context.getPointerDiffType(), RangeLoc); - else if (const VariableArrayType *VAT = - dyn_cast(UnqAT)) { - // For a variably modified type we can't just use the expression within - // the array bounds, since we don't want that to be re-evaluated here. - // Rather, we need to determine what it was when the array was first - // created - so we resort to using sizeof(vla)/sizeof(element). - // For e.g. - // void f(int b) { - // int vla[b]; - // b = -1; <-- This should not affect the num of iterations below - // for (int &c : vla) { .. } - // } - - // FIXME: This results in codegen generating IR that recalculates the - // run-time number of elements (as opposed to just using the IR Value - // that corresponds to the run-time value of each bound that was - // generated when the array was created.) If this proves too embarrassing - // even for unoptimized IR, consider passing a magic-value/cookie to - // codegen that then knows to simply use that initial llvm::Value (that - // corresponds to the bound at time of array creation) within - // getelementptr. But be prepared to pay the price of increasing a - // customized form of coupling between the two components - which could - // be hard to maintain as the codebase evolves. - - ExprResult SizeOfVLAExprR = ActOnUnaryExprOrTypeTraitExpr( - EndVar->getLocation(), UETT_SizeOf, - /*IsType=*/true, - CreateParsedType(VAT->desugar(), Context.getTrivialTypeSourceInfo( - VAT->desugar(), RangeLoc)) - .getAsOpaquePtr(), - EndVar->getSourceRange()); - if (SizeOfVLAExprR.isInvalid()) - return StmtError(); - - ExprResult SizeOfEachElementExprR = ActOnUnaryExprOrTypeTraitExpr( - EndVar->getLocation(), UETT_SizeOf, - /*IsType=*/true, - CreateParsedType(VAT->desugar(), - Context.getTrivialTypeSourceInfo( - VAT->getElementType(), RangeLoc)) - .getAsOpaquePtr(), - EndVar->getSourceRange()); - if (SizeOfEachElementExprR.isInvalid()) - return StmtError(); - - BoundExpr = - ActOnBinOp(S, EndVar->getLocation(), tok::slash, - SizeOfVLAExprR.get(), SizeOfEachElementExprR.get()); - if (BoundExpr.isInvalid()) - return StmtError(); - - } else { - // Can't be a DependentSizedArrayType or an IncompleteArrayType since - // UnqAT is not incomplete and Range is not type-dependent. - llvm_unreachable("Unexpected array type in for-range"); - } - - // end-expr is __range + __bound. - EndExpr = ActOnBinOp(S, ColonLoc, tok::plus, EndRangeRef.get(), - BoundExpr.get()); - if (EndExpr.isInvalid()) - return StmtError(); - if (FinishForRangeVarDecl(*this, EndVar, EndExpr.get(), ColonLoc, - diag::err_for_range_iter_deduction_failure)) { - NoteForRangeBeginEndFunction(*this, EndExpr.get(), BEF_end); - return StmtError(); - } - } else { - OverloadCandidateSet CandidateSet(RangeLoc, - OverloadCandidateSet::CSK_Normal); - BeginEndFunction BEFFailure; - ForRangeStatus RangeStatus = BuildNonArrayForRange( - *this, BeginRangeRef.get(), EndRangeRef.get(), RangeType, BeginVar, - EndVar, ColonLoc, CoawaitLoc, &CandidateSet, &BeginExpr, &EndExpr, - &BEFFailure); - - if (Kind == BFRK_Build && RangeStatus == FRS_NoViableFunction && - BEFFailure == BEF_begin) { - // If the range is being built from an array parameter, emit a - // a diagnostic that it is being treated as a pointer. - if (DeclRefExpr *DRE = dyn_cast(Range)) { - if (ParmVarDecl *PVD = dyn_cast(DRE->getDecl())) { - QualType ArrayTy = PVD->getOriginalType(); - QualType PointerTy = PVD->getType(); - if (PointerTy->isPointerType() && ArrayTy->isArrayType()) { - Diag(Range->getBeginLoc(), diag::err_range_on_array_parameter) - << RangeLoc << PVD << ArrayTy << PointerTy; - Diag(PVD->getLocation(), diag::note_declared_at); - return StmtError(); - } - } - } - - // If building the range failed, try dereferencing the range expression - // unless a diagnostic was issued or the end function is problematic. - StmtResult SR = RebuildForRangeWithDereference(*this, S, ForLoc, - CoawaitLoc, InitStmt, - LoopVarDecl, ColonLoc, - Range, RangeLoc, - RParenLoc); - if (SR.isInvalid() || SR.isUsable()) - return SR; - } - - // Otherwise, emit diagnostics if we haven't already. - if (RangeStatus == FRS_NoViableFunction) { - Expr *Range = BEFFailure ? EndRangeRef.get() : BeginRangeRef.get(); - CandidateSet.NoteCandidates( - PartialDiagnosticAt(Range->getBeginLoc(), - PDiag(diag::err_for_range_invalid) - << RangeLoc << Range->getType() - << BEFFailure), - *this, OCD_AllCandidates, Range); - } - // Return an error if no fix was discovered. - if (RangeStatus != FRS_Success) - return StmtError(); - } - - assert(!BeginExpr.isInvalid() && !EndExpr.isInvalid() && - "invalid range expression in for loop"); - // C++11 [dcl.spec.auto]p7: BeginType and EndType must be the same. // C++1z removes this restriction. + SourceLocation RangeLoc = RangeVar->getLocation(); QualType BeginType = BeginVar->getType(), EndType = EndVar->getType(); if (!Context.hasSameType(BeginType, EndType)) { Diag(RangeLoc, getLangOpts().CPlusPlus17 ? diag::warn_for_range_begin_end_types_differ : diag::ext_for_range_begin_end_types_differ) << BeginType << EndType; - NoteForRangeBeginEndFunction(*this, BeginExpr.get(), BEF_begin); - NoteForRangeBeginEndFunction(*this, EndExpr.get(), BEF_end); + NoteForRangeBeginEndFunction(*this, BeginExpr, BEF_begin); + NoteForRangeBeginEndFunction(*this, EndExpr, BEF_end); } BeginDeclStmt = @@ -2955,10 +2999,10 @@ StmtResult Sema::BuildCXXForRangeStmt( ActOnFinishFullExpr(NotEqExpr.get(), /*DiscardedValue*/ false); if (NotEqExpr.isInvalid()) { Diag(RangeLoc, diag::note_for_range_invalid_iterator) - << RangeLoc << 0 << BeginRangeRef.get()->getType(); - NoteForRangeBeginEndFunction(*this, BeginExpr.get(), BEF_begin); + << RangeLoc << 0 << BeginRangeRefTy; + NoteForRangeBeginEndFunction(*this, BeginExpr, BEF_begin); if (!Context.hasSameType(BeginType, EndType)) - NoteForRangeBeginEndFunction(*this, EndExpr.get(), BEF_end); + NoteForRangeBeginEndFunction(*this, EndExpr, BEF_end); return StmtError(); } @@ -2978,8 +3022,8 @@ StmtResult Sema::BuildCXXForRangeStmt( IncrExpr = ActOnFinishFullExpr(IncrExpr.get(), /*DiscardedValue*/ false); if (IncrExpr.isInvalid()) { Diag(RangeLoc, diag::note_for_range_invalid_iterator) - << RangeLoc << 2 << BeginRangeRef.get()->getType() ; - NoteForRangeBeginEndFunction(*this, BeginExpr.get(), BEF_begin); + << RangeLoc << 2 << BeginRangeRefTy; + NoteForRangeBeginEndFunction(*this, BeginExpr, BEF_begin); return StmtError(); } @@ -2992,8 +3036,8 @@ StmtResult Sema::BuildCXXForRangeStmt( ExprResult DerefExpr = ActOnUnaryOp(S, ColonLoc, tok::star, BeginRef.get()); if (DerefExpr.isInvalid()) { Diag(RangeLoc, diag::note_for_range_invalid_iterator) - << RangeLoc << 1 << BeginRangeRef.get()->getType(); - NoteForRangeBeginEndFunction(*this, BeginExpr.get(), BEF_begin); + << RangeLoc << 1 << BeginRangeRefTy; + NoteForRangeBeginEndFunction(*this, BeginExpr, BEF_begin); return StmtError(); } @@ -3003,7 +3047,7 @@ StmtResult Sema::BuildCXXForRangeStmt( AddInitializerToDecl(LoopVar, DerefExpr.get(), /*DirectInit=*/false); if (LoopVar->isInvalidDecl() || (LoopVar->getInit() && LoopVar->getInit()->containsErrors())) - NoteForRangeBeginEndFunction(*this, BeginExpr.get(), BEF_begin); + NoteForRangeBeginEndFunction(*this, BeginExpr, BEF_begin); } }