oontvoo created this revision.
Herald added subscribers: cfe-commits, martong.
Herald added a reviewer: shafik.
Herald added a project: clang.
This helps avoiding hacks downstream.
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D83529
Files:
clang/include/clang/AST/Stmt.h
clang/include/clang/Parse/Parser.h
clang/include/clang/Sema/Sema.h
clang/lib/AST/ASTImporter.cpp
clang/lib/AST/Stmt.cpp
clang/lib/Parse/ParseStmt.cpp
clang/lib/Sema/SemaStmt.cpp
clang/lib/Sema/TreeTransform.h
clang/lib/Serialization/ASTReaderStmt.cpp
Index: clang/lib/Serialization/ASTReaderStmt.cpp
===================================================================
--- clang/lib/Serialization/ASTReaderStmt.cpp
+++ clang/lib/Serialization/ASTReaderStmt.cpp
@@ -271,6 +271,8 @@
S->setConditionVariable(Record.getContext(), readDeclAs<VarDecl>());
S->setWhileLoc(readSourceLocation());
+ S->setLParenLoc(readSourceLocation());
+ S->setRParenLoc(readSourceLocation());
}
void ASTStmtReader::VisitDoStmt(DoStmt *S) {
Index: clang/lib/Sema/TreeTransform.h
===================================================================
--- clang/lib/Sema/TreeTransform.h
+++ clang/lib/Sema/TreeTransform.h
@@ -1347,9 +1347,10 @@
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
- StmtResult RebuildWhileStmt(SourceLocation WhileLoc,
- Sema::ConditionResult Cond, Stmt *Body) {
- return getSema().ActOnWhileStmt(WhileLoc, Cond, Body);
+ StmtResult RebuildWhileStmt(SourceLocation WhileLoc, SourceLocation LParenLoc,
+ Sema::ConditionResult Cond,
+ SourceLocation RParenLoc, Stmt *Body) {
+ return getSema().ActOnWhileStmt(WhileLoc, LParenLoc, Cond, RParenLoc, Body);
}
/// Build a new do-while statement.
@@ -7335,7 +7336,8 @@
Body.get() == S->getBody())
return Owned(S);
- return getDerived().RebuildWhileStmt(S->getWhileLoc(), Cond, Body.get());
+ return getDerived().RebuildWhileStmt(S->getWhileLoc(), S->getLParenLoc(),
+ Cond, S->getRParenLoc(), Body.get());
}
template<typename Derived>
Index: clang/lib/Sema/SemaStmt.cpp
===================================================================
--- clang/lib/Sema/SemaStmt.cpp
+++ clang/lib/Sema/SemaStmt.cpp
@@ -1328,8 +1328,9 @@
}
}
-StmtResult Sema::ActOnWhileStmt(SourceLocation WhileLoc, ConditionResult Cond,
- Stmt *Body) {
+StmtResult Sema::ActOnWhileStmt(SourceLocation WhileLoc,
+ SourceLocation LParenLoc, ConditionResult Cond,
+ SourceLocation RParenLoc, Stmt *Body) {
if (Cond.isInvalid())
return StmtError();
@@ -1344,7 +1345,7 @@
getCurCompoundScope().setHasEmptyLoopBodies();
return WhileStmt::Create(Context, CondVal.first, CondVal.second, Body,
- WhileLoc);
+ WhileLoc, LParenLoc, RParenLoc);
}
StmtResult
Index: clang/lib/Parse/ParseStmt.cpp
===================================================================
--- clang/lib/Parse/ParseStmt.cpp
+++ clang/lib/Parse/ParseStmt.cpp
@@ -1156,10 +1156,14 @@
/// should try to recover harder. It returns false if the condition is
/// successfully parsed. Note that a successful parse can still have semantic
/// errors in the condition.
+/// Additionally, if LParenLoc and RParenLoc are non-null, it will assign
+/// the location of the outer-most '(' and ')', respectively, to them.
bool Parser::ParseParenExprOrCondition(StmtResult *InitStmt,
Sema::ConditionResult &Cond,
SourceLocation Loc,
- Sema::ConditionKind CK) {
+ Sema::ConditionKind CK,
+ SourceLocation *LParenLoc,
+ SourceLocation *RParenLoc) {
BalancedDelimiterTracker T(*this, tok::l_paren);
T.consumeOpen();
@@ -1189,6 +1193,13 @@
// Otherwise the condition is valid or the rparen is present.
T.consumeClose();
+ if (LParenLoc != nullptr) {
+ *LParenLoc = T.getOpenLocation();
+ }
+ if (RParenLoc != nullptr) {
+ *RParenLoc = T.getCloseLocation();
+ }
+
// Check for extraneous ')'s to catch things like "if (foo())) {". We know
// that all callers are looking for a statement after the condition, so ")"
// isn't valid.
@@ -1582,8 +1593,10 @@
// Parse the condition.
Sema::ConditionResult Cond;
+ SourceLocation LParen;
+ SourceLocation RParen;
if (ParseParenExprOrCondition(nullptr, Cond, WhileLoc,
- Sema::ConditionKind::Boolean))
+ Sema::ConditionKind::Boolean, &LParen, &RParen))
return StmtError();
// C99 6.8.5p5 - In C99, the body of the while statement is a scope, even if
@@ -1613,7 +1626,7 @@
if (Cond.isInvalid() || Body.isInvalid())
return StmtError();
- return Actions.ActOnWhileStmt(WhileLoc, Cond, Body.get());
+ return Actions.ActOnWhileStmt(WhileLoc, LParen, Cond, RParen, Body.get());
}
/// ParseDoStatement
Index: clang/lib/AST/Stmt.cpp
===================================================================
--- clang/lib/AST/Stmt.cpp
+++ clang/lib/AST/Stmt.cpp
@@ -1012,7 +1012,8 @@
}
WhileStmt::WhileStmt(const ASTContext &Ctx, VarDecl *Var, Expr *Cond,
- Stmt *Body, SourceLocation WL)
+ Stmt *Body, SourceLocation WL, SourceLocation LParenLoc,
+ SourceLocation RParenLoc)
: Stmt(WhileStmtClass) {
bool HasVar = Var != nullptr;
WhileStmtBits.HasVar = HasVar;
@@ -1023,6 +1024,8 @@
setConditionVariable(Ctx, Var);
setWhileLoc(WL);
+ setLParenLoc(LParenLoc);
+ setRParenLoc(RParenLoc);
}
WhileStmt::WhileStmt(EmptyShell Empty, bool HasVar)
@@ -1031,12 +1034,14 @@
}
WhileStmt *WhileStmt::Create(const ASTContext &Ctx, VarDecl *Var, Expr *Cond,
- Stmt *Body, SourceLocation WL) {
+ Stmt *Body, SourceLocation WL,
+ SourceLocation LParenLoc,
+ SourceLocation RParenLoc) {
bool HasVar = Var != nullptr;
void *Mem =
Ctx.Allocate(totalSizeToAlloc<Stmt *>(NumMandatoryStmtPtr + HasVar),
alignof(WhileStmt));
- return new (Mem) WhileStmt(Ctx, Var, Cond, Body, WL);
+ return new (Mem) WhileStmt(Ctx, Var, Cond, Body, WL, LParenLoc, RParenLoc);
}
WhileStmt *WhileStmt::CreateEmpty(const ASTContext &Ctx, bool HasVar) {
Index: clang/lib/AST/ASTImporter.cpp
===================================================================
--- clang/lib/AST/ASTImporter.cpp
+++ clang/lib/AST/ASTImporter.cpp
@@ -6117,11 +6117,13 @@
auto ToCond = importChecked(Err, S->getCond());
auto ToBody = importChecked(Err, S->getBody());
auto ToWhileLoc = importChecked(Err, S->getWhileLoc());
+ auto ToLParenLoc = importChecked(Err, S->getLParenLoc());
+ auto ToRParenLoc = importChecked(Err, S->getRParenLoc());
if (Err)
return std::move(Err);
return WhileStmt::Create(Importer.getToContext(), ToConditionVariable, ToCond,
- ToBody, ToWhileLoc);
+ ToBody, ToWhileLoc, ToLParenLoc, ToRParenLoc);
}
ExpectedStmt ASTNodeImporter::VisitDoStmt(DoStmt *S) {
Index: clang/include/clang/Sema/Sema.h
===================================================================
--- clang/include/clang/Sema/Sema.h
+++ clang/include/clang/Sema/Sema.h
@@ -4377,7 +4377,8 @@
ConditionResult Cond);
StmtResult ActOnFinishSwitchStmt(SourceLocation SwitchLoc,
Stmt *Switch, Stmt *Body);
- StmtResult ActOnWhileStmt(SourceLocation WhileLoc, ConditionResult Cond,
+ StmtResult ActOnWhileStmt(SourceLocation WhileLoc, SourceLocation LParenLoc,
+ ConditionResult Cond, SourceLocation RParenLoc,
Stmt *Body);
StmtResult ActOnDoStmt(SourceLocation DoLoc, Stmt *Body,
SourceLocation WhileLoc, SourceLocation CondLParen,
Index: clang/include/clang/Parse/Parser.h
===================================================================
--- clang/include/clang/Parse/Parser.h
+++ clang/include/clang/Parse/Parser.h
@@ -2071,8 +2071,9 @@
StmtResult ParseCompoundStatementBody(bool isStmtExpr = false);
bool ParseParenExprOrCondition(StmtResult *InitStmt,
Sema::ConditionResult &CondResult,
- SourceLocation Loc,
- Sema::ConditionKind CK);
+ SourceLocation Loc, Sema::ConditionKind CK,
+ SourceLocation *LParenLoc = nullptr,
+ SourceLocation *RParenLoc = nullptr);
StmtResult ParseIfStatement(SourceLocation *TrailingElseLoc);
StmtResult ParseSwitchStatement(SourceLocation *TrailingElseLoc);
StmtResult ParseWhileStatement(SourceLocation *TrailingElseLoc);
Index: clang/include/clang/AST/Stmt.h
===================================================================
--- clang/include/clang/AST/Stmt.h
+++ clang/include/clang/AST/Stmt.h
@@ -2277,6 +2277,8 @@
enum { VarOffset = 0, BodyOffsetFromCond = 1 };
enum { NumMandatoryStmtPtr = 2 };
+ SourceLocation LParenLoc, RParenLoc;
+
unsigned varOffset() const { return VarOffset; }
unsigned condOffset() const { return VarOffset + hasVarStorage(); }
unsigned bodyOffset() const { return condOffset() + BodyOffsetFromCond; }
@@ -2287,7 +2289,7 @@
/// Build a while statement.
WhileStmt(const ASTContext &Ctx, VarDecl *Var, Expr *Cond, Stmt *Body,
- SourceLocation WL);
+ SourceLocation WL, SourceLocation LP, SourceLocation RP);
/// Build an empty while statement.
explicit WhileStmt(EmptyShell Empty, bool HasVar);
@@ -2295,7 +2297,8 @@
public:
/// Create a while statement.
static WhileStmt *Create(const ASTContext &Ctx, VarDecl *Var, Expr *Cond,
- Stmt *Body, SourceLocation WL);
+ Stmt *Body, SourceLocation WL, SourceLocation LP,
+ SourceLocation RP);
/// Create an empty while statement optionally with storage for
/// a condition variable.
@@ -2359,6 +2362,11 @@
SourceLocation getWhileLoc() const { return WhileStmtBits.WhileLoc; }
void setWhileLoc(SourceLocation L) { WhileStmtBits.WhileLoc = L; }
+ SourceLocation getLParenLoc() const { return LParenLoc; }
+ void setLParenLoc(SourceLocation L) { LParenLoc = L; }
+ SourceLocation getRParenLoc() const { return RParenLoc; }
+ void setRParenLoc(SourceLocation L) { RParenLoc = L; }
+
SourceLocation getBeginLoc() const { return getWhileLoc(); }
SourceLocation getEndLoc() const LLVM_READONLY {
return getBody()->getEndLoc();
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits