[llvm-branch-commits] [clang] [Clang] [NFC] Expansion Statements (Part 4: for-range and `ParseScope` refactor) (PR #169683)
https://github.com/Sirraide updated
https://github.com/llvm/llvm-project/pull/169683
>From fe50b932a412885d94733470c9a7ea42fcb36eb5 Mon Sep 17 00:00:00 2001
From: Sirraide
Date: Wed, 26 Nov 2025 16:11:59 +0100
Subject: [PATCH] [Clang] [C++26] Expansion Statements (Part 4)
---
clang/include/clang/Sema/Sema.h | 40 +++
clang/lib/Sema/SemaStmt.cpp | 503 ++--
2 files changed, 316 insertions(+), 227 deletions(-)
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 10bd6bbe5476f..5a7ac72af5df3 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -11178,6 +11178,43 @@ 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 = {},
+ IdentifierInfo *BeginName = nullptr, IdentifierInfo *EndName = nullptr);
+
+ /// Helper used by the expansion statements and for-range code to build
+ /// a variable declaration for e.g. 'begin' and 'end'.
+ VarDecl *BuildForRangeVarDecl(SourceLocation Loc, QualType Type,
+IdentifierInfo *Name, bool Constexpr);
+
+ /// 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
@@ -11323,6 +11360,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/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp
index b74af55d1bea1..9793788fb75b8 100644
--- a/clang/lib/Sema/SemaStmt.cpp
+++ b/clang/lib/Sema/SemaStmt.cpp
@@ -2431,27 +2431,46 @@ void NoteForRangeBeginEndFunction(Sema &SemaRef, Expr
*E,
SemaRef.Diag(Loc, diag::note_for_range_begin_end)
<< BEF << IsTemplate << Description << E->getType();
}
+}
/// Build a variable declaration for a for-range statement.
-VarDecl *BuildForRangeVarDecl(Sema &SemaRef, SourceLocation Loc,
- QualType Type, StringRef Name) {
- DeclContext *DC = SemaRef.CurContext;
- IdentifierInfo *II = &SemaRef.PP.getIdentifierTable().get(Name);
- TypeSourceInfo *TInfo = SemaRef.Context.getTrivialTypeSourceInfo(Type, Loc);
- VarDecl *Decl = VarDecl::Create(SemaRef.Context, DC, Loc, Loc, II, Type,
- TInfo, SC_None);
+VarDecl *Sema::BuildForRangeVarDecl(SourceLocation Loc, QualType Type,
+IdentifierInfo *II, bool Constexpr) {
+ DeclContext *DC = CurContext;
+ TypeSourceInfo *TInfo = Context.getTrivialTypeSourceInfo(Type, Loc);
+ VarDecl *Decl =
+ VarDecl::Create(Context, DC, Loc, Loc, II, Type, TInfo, SC_None);
Decl->setImplicit();
Decl->setCXXForRangeImplicitVar(true);
return Decl;
}
-}
-
static bool ObjCEnumerationCollection(Expr *Collection) {
return !Collection->isTypeDependent()
&& 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);
+ IdentifierInfo
[llvm-branch-commits] [clang] [Clang] [NFC] Expansion Statements (Part 4: for-range and `ParseScope` refactor) (PR #169683)
AaronBallman wrote: > > I'm a bit uncomfortable moving parser related objects to sema. > > Well I would argue it’s ‘parser-related’ in name only; what it does is it > pushes a new scope; the implementation of `ParseScope` only calls Sema > functions; it never actually did anything `Parser`-related in the first place To me, the `ParseScope` object is an RAII one that should live in `RAIIObjectsForParser.h`; it exists for `Parser` and `Sema` to collude on scope management from the perspective of the parser. (e.g., when parsing, you know it's time to enter a new scope so you'd use one of these to manage it automagically for you). Based on that, it seems like this interface should remain at the `Parser` level; Sema should not need to enter new parse scopes in general *except* in the case of doing statement rewriting which should be an exception rather than a regular thing, right? (IOW, I think we'd want to go in the direction of generic facilities to support statement rewriting rather than lower-level facilities like the parser has to use?) This isn't a strongly held opinion btw. https://github.com/llvm/llvm-project/pull/169683 ___ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [clang] [Clang] [NFC] Expansion Statements (Part 4: for-range and `ParseScope` refactor) (PR #169683)
Sirraide wrote: > the implementation of `ParseScope` only calls Sema functions (yes, it does call e.g. `Parser::EnterScope`, but that function in turn only calls Sema functions and doesn’t modify any state of its `Parser` object; and the same applies to all the other `Parser` functions that are called by members of `ParseScope`) https://github.com/llvm/llvm-project/pull/169683 ___ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [clang] [Clang] [NFC] Expansion Statements (Part 4: for-range and `ParseScope` refactor) (PR #169683)
Sirraide wrote: > I'm a bit uncomfortable moving parser related objects to sema. Well I would argue it’s ‘parser-related’ in name only; what it does is it pushes a new scope; the implementation of `ParseScope` only calls Sema functions; it never actually did anything `Parser`-related in the first place https://github.com/llvm/llvm-project/pull/169683 ___ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [clang] [Clang] [NFC] Expansion Statements (Part 4: for-range and `ParseScope` refactor) (PR #169683)
https://github.com/Sirraide updated
https://github.com/llvm/llvm-project/pull/169683
>From 7eb2da8c32aea7203b9437c20dd213673bce80d2 Mon Sep 17 00:00:00 2001
From: Sirraide
Date: Wed, 26 Nov 2025 16:11:59 +0100
Subject: [PATCH] [Clang] [C++26] Expansion Statements (Part 4)
---
clang/include/clang/Parse/Parser.h | 85 +---
clang/include/clang/Sema/Scope.h| 41 +-
clang/include/clang/Sema/Sema.h | 51 +-
clang/lib/Interpreter/IncrementalParser.cpp | 4 +-
clang/lib/Parse/ParseCXXInlineMethods.cpp | 9 +-
clang/lib/Parse/ParseDecl.cpp | 24 +-
clang/lib/Parse/ParseDeclCXX.cpp| 22 +-
clang/lib/Parse/ParseExpr.cpp | 5 +-
clang/lib/Parse/ParseExprCXX.cpp| 22 +-
clang/lib/Parse/ParseHLSL.cpp | 2 +-
clang/lib/Parse/ParseObjc.cpp | 28 +-
clang/lib/Parse/ParseOpenACC.cpp| 2 +-
clang/lib/Parse/ParseOpenMP.cpp | 33 +-
clang/lib/Parse/ParsePragma.cpp | 4 +-
clang/lib/Parse/ParseStmt.cpp | 37 +-
clang/lib/Parse/ParseTemplate.cpp | 10 +-
clang/lib/Parse/Parser.cpp | 55 +--
clang/lib/Sema/Scope.cpp| 33 ++
clang/lib/Sema/Sema.cpp | 32 ++
clang/lib/Sema/SemaDecl.cpp | 2 +-
clang/lib/Sema/SemaStmt.cpp | 487 +++-
21 files changed, 538 insertions(+), 450 deletions(-)
diff --git a/clang/include/clang/Parse/Parser.h
b/clang/include/clang/Parse/Parser.h
index 16f9968b42400..0a555a3b8b27a 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -211,10 +211,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;
@@ -396,78 +392,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.
@@ -558,11 +482,6 @@ class Parser : public CodeCompletionHandler {
StackExhaustionHandler StackHandler;
- /// ScopeCache - Cache scopes to reduce malloc traffic.
- static constexpr int ScopeCacheSize = 16;
- unsigned NumCachedScopes;
- Scope *ScopeCache[ScopeCacheSize];
-
///
[llvm-branch-commits] [clang] [Clang] [NFC] Expansion Statements (Part 4: for-range and `ParseScope` refactor) (PR #169683)
https://github.com/Sirraide updated
https://github.com/llvm/llvm-project/pull/169683
>From 7eb2da8c32aea7203b9437c20dd213673bce80d2 Mon Sep 17 00:00:00 2001
From: Sirraide
Date: Wed, 26 Nov 2025 16:11:59 +0100
Subject: [PATCH] [Clang] [C++26] Expansion Statements (Part 4)
---
clang/include/clang/Parse/Parser.h | 85 +---
clang/include/clang/Sema/Scope.h| 41 +-
clang/include/clang/Sema/Sema.h | 51 +-
clang/lib/Interpreter/IncrementalParser.cpp | 4 +-
clang/lib/Parse/ParseCXXInlineMethods.cpp | 9 +-
clang/lib/Parse/ParseDecl.cpp | 24 +-
clang/lib/Parse/ParseDeclCXX.cpp| 22 +-
clang/lib/Parse/ParseExpr.cpp | 5 +-
clang/lib/Parse/ParseExprCXX.cpp| 22 +-
clang/lib/Parse/ParseHLSL.cpp | 2 +-
clang/lib/Parse/ParseObjc.cpp | 28 +-
clang/lib/Parse/ParseOpenACC.cpp| 2 +-
clang/lib/Parse/ParseOpenMP.cpp | 33 +-
clang/lib/Parse/ParsePragma.cpp | 4 +-
clang/lib/Parse/ParseStmt.cpp | 37 +-
clang/lib/Parse/ParseTemplate.cpp | 10 +-
clang/lib/Parse/Parser.cpp | 55 +--
clang/lib/Sema/Scope.cpp| 33 ++
clang/lib/Sema/Sema.cpp | 32 ++
clang/lib/Sema/SemaDecl.cpp | 2 +-
clang/lib/Sema/SemaStmt.cpp | 487 +++-
21 files changed, 538 insertions(+), 450 deletions(-)
diff --git a/clang/include/clang/Parse/Parser.h
b/clang/include/clang/Parse/Parser.h
index 16f9968b42400..0a555a3b8b27a 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -211,10 +211,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;
@@ -396,78 +392,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.
@@ -558,11 +482,6 @@ class Parser : public CodeCompletionHandler {
StackExhaustionHandler StackHandler;
- /// ScopeCache - Cache scopes to reduce malloc traffic.
- static constexpr int ScopeCacheSize = 16;
- unsigned NumCachedScopes;
- Scope *ScopeCache[ScopeCacheSize];
-
///
[llvm-branch-commits] [clang] [Clang] [NFC] Expansion Statements (Part 4: for-range and `ParseScope` refactor) (PR #169683)
https://github.com/cor3ntin commented: I'm a bit uncomfortable moving parser related objects to sema. @AaronBallman opinions? https://github.com/llvm/llvm-project/pull/169683 ___ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [clang] [Clang] [NFC] Expansion Statements (Part 4: for-range and `ParseScope` refactor) (PR #169683)
https://github.com/erichkeane approved this pull request. https://github.com/llvm/llvm-project/pull/169683 ___ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [clang] [Clang] [NFC] Expansion Statements (Part 4: for-range and `ParseScope` refactor) (PR #169683)
https://github.com/Sirraide updated
https://github.com/llvm/llvm-project/pull/169683
>From 8f5fc6a6cca47d38c82ccd04a5b5184d18421775 Mon Sep 17 00:00:00 2001
From: Sirraide
Date: Wed, 26 Nov 2025 16:11:59 +0100
Subject: [PATCH] [Clang] [C++26] Expansion Statements (Part 4)
---
clang/include/clang/Parse/Parser.h | 85 +---
clang/include/clang/Sema/Scope.h| 41 +-
clang/include/clang/Sema/Sema.h | 51 +-
clang/lib/Interpreter/IncrementalParser.cpp | 4 +-
clang/lib/Parse/ParseCXXInlineMethods.cpp | 9 +-
clang/lib/Parse/ParseDecl.cpp | 24 +-
clang/lib/Parse/ParseDeclCXX.cpp| 22 +-
clang/lib/Parse/ParseExpr.cpp | 5 +-
clang/lib/Parse/ParseExprCXX.cpp| 22 +-
clang/lib/Parse/ParseHLSL.cpp | 2 +-
clang/lib/Parse/ParseObjc.cpp | 28 +-
clang/lib/Parse/ParseOpenACC.cpp| 2 +-
clang/lib/Parse/ParseOpenMP.cpp | 33 +-
clang/lib/Parse/ParsePragma.cpp | 4 +-
clang/lib/Parse/ParseStmt.cpp | 37 +-
clang/lib/Parse/ParseTemplate.cpp | 10 +-
clang/lib/Parse/Parser.cpp | 55 +--
clang/lib/Sema/Scope.cpp| 33 ++
clang/lib/Sema/Sema.cpp | 32 ++
clang/lib/Sema/SemaDecl.cpp | 2 +-
clang/lib/Sema/SemaStmt.cpp | 487 +++-
21 files changed, 538 insertions(+), 450 deletions(-)
diff --git a/clang/include/clang/Parse/Parser.h
b/clang/include/clang/Parse/Parser.h
index 0cef7658be320..f0bdc3d19e62c 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -211,10 +211,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;
@@ -385,78 +381,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.
@@ -547,11 +471,6 @@ class Parser : public CodeCompletionHandler {
StackExhaustionHandler StackHandler;
- /// ScopeCache - Cache scopes to reduce malloc traffic.
- static constexpr int ScopeCacheSize = 16;
- unsigned NumCachedScopes;
- Scope *ScopeCache[ScopeCacheSize];
-
///
[llvm-branch-commits] [clang] [Clang] [NFC] Expansion Statements (Part 4: for-range and `ParseScope` refactor) (PR #169683)
https://github.com/Sirraide updated
https://github.com/llvm/llvm-project/pull/169683
>From 80ed88be015336168e994d9ec3452fa7bb77 Mon Sep 17 00:00:00 2001
From: Sirraide
Date: Wed, 26 Nov 2025 16:11:59 +0100
Subject: [PATCH] [Clang] [C++26] Expansion Statements (Part 4)
---
clang/include/clang/Parse/Parser.h | 85 +---
clang/include/clang/Sema/Scope.h| 41 +-
clang/include/clang/Sema/Sema.h | 51 +-
clang/lib/Interpreter/IncrementalParser.cpp | 4 +-
clang/lib/Parse/ParseCXXInlineMethods.cpp | 9 +-
clang/lib/Parse/ParseDecl.cpp | 24 +-
clang/lib/Parse/ParseDeclCXX.cpp| 22 +-
clang/lib/Parse/ParseExpr.cpp | 5 +-
clang/lib/Parse/ParseExprCXX.cpp| 22 +-
clang/lib/Parse/ParseHLSL.cpp | 2 +-
clang/lib/Parse/ParseObjc.cpp | 28 +-
clang/lib/Parse/ParseOpenACC.cpp| 2 +-
clang/lib/Parse/ParseOpenMP.cpp | 33 +-
clang/lib/Parse/ParsePragma.cpp | 4 +-
clang/lib/Parse/ParseStmt.cpp | 37 +-
clang/lib/Parse/ParseTemplate.cpp | 10 +-
clang/lib/Parse/Parser.cpp | 55 +--
clang/lib/Sema/Scope.cpp| 33 ++
clang/lib/Sema/Sema.cpp | 32 ++
clang/lib/Sema/SemaDecl.cpp | 2 +-
clang/lib/Sema/SemaStmt.cpp | 487 +++-
21 files changed, 538 insertions(+), 450 deletions(-)
diff --git a/clang/include/clang/Parse/Parser.h
b/clang/include/clang/Parse/Parser.h
index fc186fbb9fd7b..f7839f172871f 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -211,10 +211,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;
@@ -385,78 +381,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.
@@ -547,11 +471,6 @@ class Parser : public CodeCompletionHandler {
StackExhaustionHandler StackHandler;
- /// ScopeCache - Cache scopes to reduce malloc traffic.
- static constexpr int ScopeCacheSize = 16;
- unsigned NumCachedScopes;
- Scope *ScopeCache[ScopeCacheSize];
-
///
[llvm-branch-commits] [clang] [Clang] [NFC] Expansion Statements (Part 4: for-range and `ParseScope` refactor) (PR #169683)
https://github.com/Sirraide updated
https://github.com/llvm/llvm-project/pull/169683
>From 26f413ff4d537911520369e1f1833cf940dd2ab8 Mon Sep 17 00:00:00 2001
From: Sirraide
Date: Wed, 26 Nov 2025 16:11:59 +0100
Subject: [PATCH 1/4] [Clang] [C++26] Expansion Statements (Part 4)
---
clang/include/clang/Sema/Sema.h | 34 +++
clang/lib/Sema/SemaStmt.cpp | 503 ++--
2 files changed, 313 insertions(+), 224 deletions(-)
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 707f9eefccf36..7e23bb486bdda 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -11067,6 +11067,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 ForExpansionStmt,
+ 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,
+ bool ForExpansionStmt);
+
/// 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
@@ -11208,6 +11239,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/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp
index 6bb1a27d1800c..3a1d73fdacf09 100644
--- a/clang/lib/Sema/SemaStmt.cpp
+++ b/clang/lib/Sema/SemaStmt.cpp
@@ -2409,8 +2409,13 @@ 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) {
+ // Making the variable constexpr doesn't automatically add 'const' to the
+ // type, so do that now.
+ if (ForExpansionStmt && !Type->isReferenceType())
+Type = Type.withConst();
+
DeclContext *DC = SemaRef.CurContext;
IdentifierInfo *II = &SemaRef.PP.getIdentifierTable().get(Name);
TypeSourceInfo *TInfo = SemaRef.Context.getTrivialTypeSourceInfo(Type, Loc);
@@ -2418,9 +2423,11 @@ VarDecl *BuildForRangeVarDecl(Sema &SemaRef,
SourceLocation Loc,
TInfo, SC_None);
Decl->setImplicit();
Decl->setCXXForRangeImplicitVar(true);
+ if (ForExpansionStmt)
+// CWG 3044: Do not make the variable 'static'.
+Decl->setConstexpr(true);
return Decl;
}
-
}
static bool ObjCEnumerationCollection(Expr *Collection) {
@@ -2428,6 +2435,25 @@ static bool ObjCEnumerationCollection(Expr *Collection) {
&& Collection->getType()->getAs() != nullptr;
}
+StmtResult Sema::BuildCXXForRangeRangeVar(Scope *S, Expr *Range,
+ bool ForExpansionStmt) {
+ // 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,
ForExpansionStmt);
+ if (FinishForRangeVarDecl(*this, RangeVar, Range, RangeLoc,
+
[llvm-branch-commits] [clang] [Clang] [NFC] Expansion Statements (Part 4: for-range and `ParseScope` refactor) (PR #169683)
https://github.com/Sirraide updated
https://github.com/llvm/llvm-project/pull/169683
>From 26f413ff4d537911520369e1f1833cf940dd2ab8 Mon Sep 17 00:00:00 2001
From: Sirraide
Date: Wed, 26 Nov 2025 16:11:59 +0100
Subject: [PATCH 1/4] [Clang] [C++26] Expansion Statements (Part 4)
---
clang/include/clang/Sema/Sema.h | 34 +++
clang/lib/Sema/SemaStmt.cpp | 503 ++--
2 files changed, 313 insertions(+), 224 deletions(-)
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 707f9eefccf36..7e23bb486bdda 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -11067,6 +11067,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 ForExpansionStmt,
+ 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,
+ bool ForExpansionStmt);
+
/// 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
@@ -11208,6 +11239,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/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp
index 6bb1a27d1800c..3a1d73fdacf09 100644
--- a/clang/lib/Sema/SemaStmt.cpp
+++ b/clang/lib/Sema/SemaStmt.cpp
@@ -2409,8 +2409,13 @@ 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) {
+ // Making the variable constexpr doesn't automatically add 'const' to the
+ // type, so do that now.
+ if (ForExpansionStmt && !Type->isReferenceType())
+Type = Type.withConst();
+
DeclContext *DC = SemaRef.CurContext;
IdentifierInfo *II = &SemaRef.PP.getIdentifierTable().get(Name);
TypeSourceInfo *TInfo = SemaRef.Context.getTrivialTypeSourceInfo(Type, Loc);
@@ -2418,9 +2423,11 @@ VarDecl *BuildForRangeVarDecl(Sema &SemaRef,
SourceLocation Loc,
TInfo, SC_None);
Decl->setImplicit();
Decl->setCXXForRangeImplicitVar(true);
+ if (ForExpansionStmt)
+// CWG 3044: Do not make the variable 'static'.
+Decl->setConstexpr(true);
return Decl;
}
-
}
static bool ObjCEnumerationCollection(Expr *Collection) {
@@ -2428,6 +2435,25 @@ static bool ObjCEnumerationCollection(Expr *Collection) {
&& Collection->getType()->getAs() != nullptr;
}
+StmtResult Sema::BuildCXXForRangeRangeVar(Scope *S, Expr *Range,
+ bool ForExpansionStmt) {
+ // 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,
ForExpansionStmt);
+ if (FinishForRangeVarDecl(*this, RangeVar, Range, RangeLoc,
+
[llvm-branch-commits] [clang] [Clang] [NFC] Expansion Statements (Part 4: for-range and `ParseScope` refactor) (PR #169683)
https://github.com/Sirraide updated
https://github.com/llvm/llvm-project/pull/169683
>From 1efe8bb6046ad04eaf0968a550b45540bb2df692 Mon Sep 17 00:00:00 2001
From: Sirraide
Date: Wed, 26 Nov 2025 16:11:59 +0100
Subject: [PATCH 1/4] [Clang] [C++26] Expansion Statements (Part 4)
---
clang/include/clang/Sema/Sema.h | 34 +++
clang/lib/Sema/SemaStmt.cpp | 503 ++--
2 files changed, 313 insertions(+), 224 deletions(-)
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index c5711ab7ea751..35159309bba8a 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -11066,6 +11066,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 ForExpansionStmt,
+ 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,
+ bool ForExpansionStmt);
+
/// 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 +11238,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/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp
index 655fa31bbf5c7..47c8f9ab6725c 100644
--- a/clang/lib/Sema/SemaStmt.cpp
+++ b/clang/lib/Sema/SemaStmt.cpp
@@ -2409,8 +2409,13 @@ 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) {
+ // Making the variable constexpr doesn't automatically add 'const' to the
+ // type, so do that now.
+ if (ForExpansionStmt && !Type->isReferenceType())
+Type = Type.withConst();
+
DeclContext *DC = SemaRef.CurContext;
IdentifierInfo *II = &SemaRef.PP.getIdentifierTable().get(Name);
TypeSourceInfo *TInfo = SemaRef.Context.getTrivialTypeSourceInfo(Type, Loc);
@@ -2418,9 +2423,11 @@ VarDecl *BuildForRangeVarDecl(Sema &SemaRef,
SourceLocation Loc,
TInfo, SC_None);
Decl->setImplicit();
Decl->setCXXForRangeImplicitVar(true);
+ if (ForExpansionStmt)
+// CWG 3044: Do not make the variable 'static'.
+Decl->setConstexpr(true);
return Decl;
}
-
}
static bool ObjCEnumerationCollection(Expr *Collection) {
@@ -2428,6 +2435,25 @@ static bool ObjCEnumerationCollection(Expr *Collection) {
&& Collection->getType()->getAs() != nullptr;
}
+StmtResult Sema::BuildCXXForRangeRangeVar(Scope *S, Expr *Range,
+ bool ForExpansionStmt) {
+ // 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,
ForExpansionStmt);
+ if (FinishForRangeVarDecl(*this, RangeVar, Range, RangeLoc,
+
[llvm-branch-commits] [clang] [Clang] [NFC] Expansion Statements (Part 4: for-range and `ParseScope` refactor) (PR #169683)
https://github.com/Sirraide updated
https://github.com/llvm/llvm-project/pull/169683
>From 1efe8bb6046ad04eaf0968a550b45540bb2df692 Mon Sep 17 00:00:00 2001
From: Sirraide
Date: Wed, 26 Nov 2025 16:11:59 +0100
Subject: [PATCH 1/4] [Clang] [C++26] Expansion Statements (Part 4)
---
clang/include/clang/Sema/Sema.h | 34 +++
clang/lib/Sema/SemaStmt.cpp | 503 ++--
2 files changed, 313 insertions(+), 224 deletions(-)
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index c5711ab7ea751..35159309bba8a 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -11066,6 +11066,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 ForExpansionStmt,
+ 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,
+ bool ForExpansionStmt);
+
/// 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 +11238,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/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp
index 655fa31bbf5c7..47c8f9ab6725c 100644
--- a/clang/lib/Sema/SemaStmt.cpp
+++ b/clang/lib/Sema/SemaStmt.cpp
@@ -2409,8 +2409,13 @@ 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) {
+ // Making the variable constexpr doesn't automatically add 'const' to the
+ // type, so do that now.
+ if (ForExpansionStmt && !Type->isReferenceType())
+Type = Type.withConst();
+
DeclContext *DC = SemaRef.CurContext;
IdentifierInfo *II = &SemaRef.PP.getIdentifierTable().get(Name);
TypeSourceInfo *TInfo = SemaRef.Context.getTrivialTypeSourceInfo(Type, Loc);
@@ -2418,9 +2423,11 @@ VarDecl *BuildForRangeVarDecl(Sema &SemaRef,
SourceLocation Loc,
TInfo, SC_None);
Decl->setImplicit();
Decl->setCXXForRangeImplicitVar(true);
+ if (ForExpansionStmt)
+// CWG 3044: Do not make the variable 'static'.
+Decl->setConstexpr(true);
return Decl;
}
-
}
static bool ObjCEnumerationCollection(Expr *Collection) {
@@ -2428,6 +2435,25 @@ static bool ObjCEnumerationCollection(Expr *Collection) {
&& Collection->getType()->getAs() != nullptr;
}
+StmtResult Sema::BuildCXXForRangeRangeVar(Scope *S, Expr *Range,
+ bool ForExpansionStmt) {
+ // 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,
ForExpansionStmt);
+ if (FinishForRangeVarDecl(*this, RangeVar, Range, RangeLoc,
+
[llvm-branch-commits] [clang] [Clang] [NFC] Expansion Statements (Part 4: for-range and `ParseScope` refactor) (PR #169683)
Sirraide wrote: Update: Iterating expansion statements require building a lambda in Sema (see part 5 in this patch series), which necessitated moving `ParseScope` and friends from the Parser into Sema; I’ve included this refactor in this NFC patch. As an aside, it makes more sense for `ParseScope` etc. to be in Sema anyway since its implementation exclusively calls Sema functions—technically, it does call _some_ parser functions, but _those functions_ then in turn only call Sema functions and don’t actually access any parser state. The only reference to parser state is that the current token location is passed to Sema... but Sema doesn’t do anything w/ it, so I just removed that parameter. https://github.com/llvm/llvm-project/pull/169683 ___ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [clang] [Clang] [NFC] Expansion Statements (Part 4: for-range and `ParseScope` refactor) (PR #169683)
https://github.com/Sirraide edited https://github.com/llvm/llvm-project/pull/169683 ___ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [clang] [Clang] [NFC] Expansion Statements (Part 4: for-range and `ParseScope` refactor) (PR #169683)
https://github.com/Sirraide edited https://github.com/llvm/llvm-project/pull/169683 ___ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
