[AST] add parenthesis locations for IfStmt and SwitchStmt

Differential Revision: https://reviews.llvm.org/D85696
This commit is contained in:
Zequan Wu 2020-08-10 16:29:33 -07:00
parent 3c5758964c
commit 94c6ceab53
11 changed files with 118 additions and 63 deletions

View File

@ -1895,6 +1895,8 @@ class IfStmt final
// Present if and only if hasElseStorage().
enum { InitOffset = 0, ThenOffsetFromCond = 1, ElseOffsetFromCond = 2 };
enum { NumMandatoryStmtPtr = 2 };
SourceLocation LParenLoc;
SourceLocation RParenLoc;
unsigned numTrailingObjects(OverloadToken<Stmt *>) const {
return NumMandatoryStmtPtr + hasElseStorage() + hasVarStorage() +
@ -1915,7 +1917,8 @@ class IfStmt final
/// Build an if/then/else statement.
IfStmt(const ASTContext &Ctx, SourceLocation IL, bool IsConstexpr, Stmt *Init,
VarDecl *Var, Expr *Cond, Stmt *Then, SourceLocation EL, Stmt *Else);
VarDecl *Var, Expr *Cond, SourceLocation LParenLoc,
SourceLocation RParenLoc, Stmt *Then, SourceLocation EL, Stmt *Else);
/// Build an empty if/then/else statement.
explicit IfStmt(EmptyShell Empty, bool HasElse, bool HasVar, bool HasInit);
@ -1924,7 +1927,8 @@ public:
/// Create an IfStmt.
static IfStmt *Create(const ASTContext &Ctx, SourceLocation IL,
bool IsConstexpr, Stmt *Init, VarDecl *Var, Expr *Cond,
Stmt *Then, SourceLocation EL = SourceLocation(),
SourceLocation LPL, SourceLocation RPL, Stmt *Then,
SourceLocation EL = SourceLocation(),
Stmt *Else = nullptr);
/// Create an empty IfStmt optionally with storage for an else statement,
@ -2054,6 +2058,10 @@ public:
return getElse()->getEndLoc();
return getThen()->getEndLoc();
}
SourceLocation getLParenLoc() const { return LParenLoc; }
void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
SourceLocation getRParenLoc() const { return RParenLoc; }
void setRParenLoc(SourceLocation Loc) { RParenLoc = Loc; }
// Iterators over subexpressions. The iterators will include iterating
// over the initialization expression referenced by the condition variable.
@ -2101,6 +2109,8 @@ class SwitchStmt final : public Stmt,
// Always present.
enum { InitOffset = 0, BodyOffsetFromCond = 1 };
enum { NumMandatoryStmtPtr = 2 };
SourceLocation LParenLoc;
SourceLocation RParenLoc;
unsigned numTrailingObjects(OverloadToken<Stmt *>) const {
return NumMandatoryStmtPtr + hasInitStorage() + hasVarStorage();
@ -2114,7 +2124,8 @@ class SwitchStmt final : public Stmt,
unsigned bodyOffset() const { return condOffset() + BodyOffsetFromCond; }
/// Build a switch statement.
SwitchStmt(const ASTContext &Ctx, Stmt *Init, VarDecl *Var, Expr *Cond);
SwitchStmt(const ASTContext &Ctx, Stmt *Init, VarDecl *Var, Expr *Cond,
SourceLocation LParenLoc, SourceLocation RParenLoc);
/// Build a empty switch statement.
explicit SwitchStmt(EmptyShell Empty, bool HasInit, bool HasVar);
@ -2122,7 +2133,8 @@ class SwitchStmt final : public Stmt,
public:
/// Create a switch statement.
static SwitchStmt *Create(const ASTContext &Ctx, Stmt *Init, VarDecl *Var,
Expr *Cond);
Expr *Cond, SourceLocation LParenLoc,
SourceLocation RParenLoc);
/// Create an empty switch statement optionally with storage for
/// an init expression and a condition variable.
@ -2210,6 +2222,10 @@ public:
SourceLocation getSwitchLoc() const { return SwitchStmtBits.SwitchLoc; }
void setSwitchLoc(SourceLocation L) { SwitchStmtBits.SwitchLoc = L; }
SourceLocation getLParenLoc() const { return LParenLoc; }
void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
SourceLocation getRParenLoc() const { return RParenLoc; }
void setRParenLoc(SourceLocation Loc) { RParenLoc = Loc; }
void setBody(Stmt *S, SourceLocation SL) {
setBody(S);

View File

@ -4380,16 +4380,17 @@ public:
class ConditionResult;
StmtResult ActOnIfStmt(SourceLocation IfLoc, bool IsConstexpr,
Stmt *InitStmt,
ConditionResult Cond, Stmt *ThenVal,
SourceLocation ElseLoc, Stmt *ElseVal);
SourceLocation LParenLoc, Stmt *InitStmt,
ConditionResult Cond, SourceLocation RParenLoc,
Stmt *ThenVal, SourceLocation ElseLoc, Stmt *ElseVal);
StmtResult BuildIfStmt(SourceLocation IfLoc, bool IsConstexpr,
Stmt *InitStmt,
ConditionResult Cond, Stmt *ThenVal,
SourceLocation ElseLoc, Stmt *ElseVal);
SourceLocation LParenLoc, Stmt *InitStmt,
ConditionResult Cond, SourceLocation RParenLoc,
Stmt *ThenVal, SourceLocation ElseLoc, Stmt *ElseVal);
StmtResult ActOnStartOfSwitchStmt(SourceLocation SwitchLoc,
Stmt *InitStmt,
ConditionResult Cond);
SourceLocation LParenLoc, Stmt *InitStmt,
ConditionResult Cond,
SourceLocation RParenLoc);
StmtResult ActOnFinishSwitchStmt(SourceLocation SwitchLoc,
Stmt *Switch, Stmt *Body);
StmtResult ActOnWhileStmt(SourceLocation WhileLoc, SourceLocation LParenLoc,

View File

@ -6067,6 +6067,8 @@ ExpectedStmt ASTNodeImporter::VisitIfStmt(IfStmt *S) {
auto ToInit = importChecked(Err, S->getInit());
auto ToConditionVariable = importChecked(Err, S->getConditionVariable());
auto ToCond = importChecked(Err, S->getCond());
auto ToLParenLoc = importChecked(Err, S->getLParenLoc());
auto ToRParenLoc = importChecked(Err, S->getRParenLoc());
auto ToThen = importChecked(Err, S->getThen());
auto ToElseLoc = importChecked(Err, S->getElseLoc());
auto ToElse = importChecked(Err, S->getElse());
@ -6074,8 +6076,8 @@ ExpectedStmt ASTNodeImporter::VisitIfStmt(IfStmt *S) {
return std::move(Err);
return IfStmt::Create(Importer.getToContext(), ToIfLoc, S->isConstexpr(),
ToInit, ToConditionVariable, ToCond, ToThen, ToElseLoc,
ToElse);
ToInit, ToConditionVariable, ToCond, ToLParenLoc,
ToRParenLoc, ToThen, ToElseLoc, ToElse);
}
ExpectedStmt ASTNodeImporter::VisitSwitchStmt(SwitchStmt *S) {
@ -6084,13 +6086,16 @@ ExpectedStmt ASTNodeImporter::VisitSwitchStmt(SwitchStmt *S) {
auto ToInit = importChecked(Err, S->getInit());
auto ToConditionVariable = importChecked(Err, S->getConditionVariable());
auto ToCond = importChecked(Err, S->getCond());
auto ToLParenLoc = importChecked(Err, S->getLParenLoc());
auto ToRParenLoc = importChecked(Err, S->getRParenLoc());
auto ToBody = importChecked(Err, S->getBody());
auto ToSwitchLoc = importChecked(Err, S->getSwitchLoc());
if (Err)
return std::move(Err);
auto *ToStmt = SwitchStmt::Create(Importer.getToContext(), ToInit,
ToConditionVariable, ToCond);
auto *ToStmt =
SwitchStmt::Create(Importer.getToContext(), ToInit, ToConditionVariable,
ToCond, ToLParenLoc, ToRParenLoc);
ToStmt->setBody(ToBody);
ToStmt->setSwitchLoc(ToSwitchLoc);

View File

@ -827,9 +827,9 @@ void MSAsmStmt::initialize(const ASTContext &C, StringRef asmstr,
}
IfStmt::IfStmt(const ASTContext &Ctx, SourceLocation IL, bool IsConstexpr,
Stmt *Init, VarDecl *Var, Expr *Cond, Stmt *Then,
SourceLocation EL, Stmt *Else)
: Stmt(IfStmtClass) {
Stmt *Init, VarDecl *Var, Expr *Cond, SourceLocation LPL,
SourceLocation RPL, Stmt *Then, SourceLocation EL, Stmt *Else)
: Stmt(IfStmtClass), LParenLoc(LPL), RParenLoc(RPL) {
bool HasElse = Else != nullptr;
bool HasVar = Var != nullptr;
bool HasInit = Init != nullptr;
@ -862,7 +862,8 @@ IfStmt::IfStmt(EmptyShell Empty, bool HasElse, bool HasVar, bool HasInit)
IfStmt *IfStmt::Create(const ASTContext &Ctx, SourceLocation IL,
bool IsConstexpr, Stmt *Init, VarDecl *Var, Expr *Cond,
Stmt *Then, SourceLocation EL, Stmt *Else) {
SourceLocation LPL, SourceLocation RPL, Stmt *Then,
SourceLocation EL, Stmt *Else) {
bool HasElse = Else != nullptr;
bool HasVar = Var != nullptr;
bool HasInit = Init != nullptr;
@ -871,7 +872,7 @@ IfStmt *IfStmt::Create(const ASTContext &Ctx, SourceLocation IL,
NumMandatoryStmtPtr + HasElse + HasVar + HasInit, HasElse),
alignof(IfStmt));
return new (Mem)
IfStmt(Ctx, IL, IsConstexpr, Init, Var, Cond, Then, EL, Else);
IfStmt(Ctx, IL, IsConstexpr, Init, Var, Cond, LPL, RPL, Then, EL, Else);
}
IfStmt *IfStmt::CreateEmpty(const ASTContext &Ctx, bool HasElse, bool HasVar,
@ -947,8 +948,10 @@ void ForStmt::setConditionVariable(const ASTContext &C, VarDecl *V) {
}
SwitchStmt::SwitchStmt(const ASTContext &Ctx, Stmt *Init, VarDecl *Var,
Expr *Cond)
: Stmt(SwitchStmtClass), FirstCase(nullptr) {
Expr *Cond, SourceLocation LParenLoc,
SourceLocation RParenLoc)
: Stmt(SwitchStmtClass), FirstCase(nullptr), LParenLoc(LParenLoc),
RParenLoc(RParenLoc) {
bool HasInit = Init != nullptr;
bool HasVar = Var != nullptr;
SwitchStmtBits.HasInit = HasInit;
@ -973,13 +976,14 @@ SwitchStmt::SwitchStmt(EmptyShell Empty, bool HasInit, bool HasVar)
}
SwitchStmt *SwitchStmt::Create(const ASTContext &Ctx, Stmt *Init, VarDecl *Var,
Expr *Cond) {
Expr *Cond, SourceLocation LParenLoc,
SourceLocation RParenLoc) {
bool HasInit = Init != nullptr;
bool HasVar = Var != nullptr;
void *Mem = Ctx.Allocate(
totalSizeToAlloc<Stmt *>(NumMandatoryStmtPtr + HasInit + HasVar),
alignof(SwitchStmt));
return new (Mem) SwitchStmt(Ctx, Init, Var, Cond);
return new (Mem) SwitchStmt(Ctx, Init, Var, Cond, LParenLoc, RParenLoc);
}
SwitchStmt *SwitchStmt::CreateEmpty(const ASTContext &Ctx, bool HasInit,

View File

@ -468,6 +468,8 @@ static Stmt *create_call_once(ASTContext &C, const FunctionDecl *D) {
/* Init=*/nullptr,
/* Var=*/nullptr,
/* Cond=*/FlagCheck,
/* LPL=*/SourceLocation(),
/* RPL=*/SourceLocation(),
/* Then=*/M.makeCompound({CallbackCall, FlagAssignment}));
return Out;
@ -552,6 +554,8 @@ static Stmt *create_dispatch_once(ASTContext &C, const FunctionDecl *D) {
/* Init=*/nullptr,
/* Var=*/nullptr,
/* Cond=*/GuardCondition,
/* LPL=*/SourceLocation(),
/* RPL=*/SourceLocation(),
/* Then=*/CS);
return If;
}
@ -655,11 +659,13 @@ static Stmt *create_OSAtomicCompareAndSwap(ASTContext &C, const FunctionDecl *D)
Stmt *Else = M.makeReturn(RetVal);
/// Construct the If.
auto *If = IfStmt::Create(C, SourceLocation(),
/* IsConstexpr=*/false,
/* Init=*/nullptr,
/* Var=*/nullptr, Comparison, Body,
SourceLocation(), Else);
auto *If =
IfStmt::Create(C, SourceLocation(),
/* IsConstexpr=*/false,
/* Init=*/nullptr,
/* Var=*/nullptr, Comparison,
/* LPL=*/SourceLocation(),
/* RPL=*/SourceLocation(), Body, SourceLocation(), Else);
return If;
}

View File

@ -1350,9 +1350,12 @@ StmtResult Parser::ParseIfStatement(SourceLocation *TrailingElseLoc) {
// Parse the condition.
StmtResult InitStmt;
Sema::ConditionResult Cond;
SourceLocation LParen;
SourceLocation RParen;
if (ParseParenExprOrCondition(&InitStmt, Cond, IfLoc,
IsConstexpr ? Sema::ConditionKind::ConstexprIf
: Sema::ConditionKind::Boolean))
: Sema::ConditionKind::Boolean,
&LParen, &RParen))
return StmtError();
llvm::Optional<bool> ConstexprCondition;
@ -1465,8 +1468,8 @@ StmtResult Parser::ParseIfStatement(SourceLocation *TrailingElseLoc) {
if (ElseStmt.isInvalid())
ElseStmt = Actions.ActOnNullStmt(ElseStmtLoc);
return Actions.ActOnIfStmt(IfLoc, IsConstexpr, InitStmt.get(), Cond,
ThenStmt.get(), ElseLoc, ElseStmt.get());
return Actions.ActOnIfStmt(IfLoc, IsConstexpr, LParen, InitStmt.get(), Cond,
RParen, ThenStmt.get(), ElseLoc, ElseStmt.get());
}
/// ParseSwitchStatement
@ -1505,12 +1508,14 @@ StmtResult Parser::ParseSwitchStatement(SourceLocation *TrailingElseLoc) {
// Parse the condition.
StmtResult InitStmt;
Sema::ConditionResult Cond;
SourceLocation LParen;
SourceLocation RParen;
if (ParseParenExprOrCondition(&InitStmt, Cond, SwitchLoc,
Sema::ConditionKind::Switch))
Sema::ConditionKind::Switch, &LParen, &RParen))
return StmtError();
StmtResult Switch =
Actions.ActOnStartOfSwitchStmt(SwitchLoc, InitStmt.get(), Cond);
StmtResult Switch = Actions.ActOnStartOfSwitchStmt(
SwitchLoc, LParen, InitStmt.get(), Cond, RParen);
if (Switch.isInvalid()) {
// Skip the switch body.

View File

@ -8022,10 +8022,10 @@ private:
if (ReturnFalse.isInvalid())
return StmtError();
return S.ActOnIfStmt(Loc, false, nullptr,
return S.ActOnIfStmt(Loc, false, Loc, nullptr,
S.ActOnCondition(nullptr, Loc, NotCond.get(),
Sema::ConditionKind::Boolean),
ReturnFalse.get(), SourceLocation(), nullptr);
Loc, ReturnFalse.get(), SourceLocation(), nullptr);
}
StmtResult visitSubobjectArray(QualType Type, llvm::APInt Size,
@ -8177,9 +8177,9 @@ private:
return StmtError();
// if (...)
return S.ActOnIfStmt(Loc, /*IsConstexpr=*/false, InitStmt, Cond,
ReturnStmt.get(), /*ElseLoc=*/SourceLocation(),
/*Else=*/nullptr);
return S.ActOnIfStmt(Loc, /*IsConstexpr=*/false, Loc, InitStmt, Cond, Loc,
ReturnStmt.get(),
/*ElseLoc=*/SourceLocation(), /*Else=*/nullptr);
}
case DefaultedComparisonKind::NotEqual:

View File

@ -574,11 +574,11 @@ public:
};
}
StmtResult
Sema::ActOnIfStmt(SourceLocation IfLoc, bool IsConstexpr, Stmt *InitStmt,
ConditionResult Cond,
Stmt *thenStmt, SourceLocation ElseLoc,
Stmt *elseStmt) {
StmtResult Sema::ActOnIfStmt(SourceLocation IfLoc, bool IsConstexpr,
SourceLocation LParenLoc, Stmt *InitStmt,
ConditionResult Cond, SourceLocation RParenLoc,
Stmt *thenStmt, SourceLocation ElseLoc,
Stmt *elseStmt) {
if (Cond.isInvalid())
Cond = ConditionResult(
*this, nullptr,
@ -597,12 +597,13 @@ Sema::ActOnIfStmt(SourceLocation IfLoc, bool IsConstexpr, Stmt *InitStmt,
DiagnoseEmptyStmtBody(CondExpr->getEndLoc(), thenStmt,
diag::warn_empty_if_body);
return BuildIfStmt(IfLoc, IsConstexpr, InitStmt, Cond, thenStmt, ElseLoc,
elseStmt);
return BuildIfStmt(IfLoc, IsConstexpr, LParenLoc, InitStmt, Cond, RParenLoc,
thenStmt, ElseLoc, elseStmt);
}
StmtResult Sema::BuildIfStmt(SourceLocation IfLoc, bool IsConstexpr,
Stmt *InitStmt, ConditionResult Cond,
SourceLocation LParenLoc, Stmt *InitStmt,
ConditionResult Cond, SourceLocation RParenLoc,
Stmt *thenStmt, SourceLocation ElseLoc,
Stmt *elseStmt) {
if (Cond.isInvalid())
@ -612,7 +613,8 @@ StmtResult Sema::BuildIfStmt(SourceLocation IfLoc, bool IsConstexpr,
setFunctionHasBranchProtectedScope();
return IfStmt::Create(Context, IfLoc, IsConstexpr, InitStmt, Cond.get().first,
Cond.get().second, thenStmt, ElseLoc, elseStmt);
Cond.get().second, LParenLoc, RParenLoc, thenStmt,
ElseLoc, elseStmt);
}
namespace {
@ -739,7 +741,9 @@ ExprResult Sema::CheckSwitchCondition(SourceLocation SwitchLoc, Expr *Cond) {
}
StmtResult Sema::ActOnStartOfSwitchStmt(SourceLocation SwitchLoc,
Stmt *InitStmt, ConditionResult Cond) {
SourceLocation LParenLoc,
Stmt *InitStmt, ConditionResult Cond,
SourceLocation RParenLoc) {
Expr *CondExpr = Cond.get().second;
assert((Cond.isInvalid() || CondExpr) && "switch with no condition");
@ -761,7 +765,8 @@ StmtResult Sema::ActOnStartOfSwitchStmt(SourceLocation SwitchLoc,
setFunctionHasBranchIntoScope();
auto *SS = SwitchStmt::Create(Context, InitStmt, Cond.get().first, CondExpr);
auto *SS = SwitchStmt::Create(Context, InitStmt, Cond.get().first, CondExpr,
LParenLoc, RParenLoc);
getCurFunction()->SwitchStack.push_back(
FunctionScopeInfo::SwitchInfo(SS, false));
return SS;

View File

@ -1319,19 +1319,23 @@ public:
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
StmtResult RebuildIfStmt(SourceLocation IfLoc, bool IsConstexpr,
Sema::ConditionResult Cond, Stmt *Init, Stmt *Then,
SourceLocation LParenLoc, Sema::ConditionResult Cond,
SourceLocation RParenLoc, Stmt *Init, Stmt *Then,
SourceLocation ElseLoc, Stmt *Else) {
return getSema().ActOnIfStmt(IfLoc, IsConstexpr, Init, Cond, Then,
ElseLoc, Else);
return getSema().ActOnIfStmt(IfLoc, IsConstexpr, LParenLoc, Init, Cond,
RParenLoc, Then, ElseLoc, Else);
}
/// Start building a new switch statement.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
StmtResult RebuildSwitchStmtStart(SourceLocation SwitchLoc, Stmt *Init,
Sema::ConditionResult Cond) {
return getSema().ActOnStartOfSwitchStmt(SwitchLoc, Init, Cond);
StmtResult RebuildSwitchStmtStart(SourceLocation SwitchLoc,
SourceLocation LParenLoc, Stmt *Init,
Sema::ConditionResult Cond,
SourceLocation RParenLoc) {
return getSema().ActOnStartOfSwitchStmt(SwitchLoc, LParenLoc, Init, Cond,
RParenLoc);
}
/// Attach the body to the switch statement.
@ -7289,9 +7293,9 @@ TreeTransform<Derived>::TransformIfStmt(IfStmt *S) {
Else.get() == S->getElse())
return S;
return getDerived().RebuildIfStmt(S->getIfLoc(), S->isConstexpr(), Cond,
Init.get(), Then.get(), S->getElseLoc(),
Else.get());
return getDerived().RebuildIfStmt(
S->getIfLoc(), S->isConstexpr(), S->getLParenLoc(), Cond,
S->getRParenLoc(), Init.get(), Then.get(), S->getElseLoc(), Else.get());
}
template<typename Derived>
@ -7310,8 +7314,9 @@ TreeTransform<Derived>::TransformSwitchStmt(SwitchStmt *S) {
return StmtError();
// Rebuild the switch statement.
StmtResult Switch
= getDerived().RebuildSwitchStmtStart(S->getSwitchLoc(), Init.get(), Cond);
StmtResult Switch =
getDerived().RebuildSwitchStmtStart(S->getSwitchLoc(), S->getLParenLoc(),
Init.get(), Cond, S->getRParenLoc());
if (Switch.isInvalid())
return StmtError();

View File

@ -226,6 +226,8 @@ void ASTStmtReader::VisitIfStmt(IfStmt *S) {
S->setInit(Record.readSubStmt());
S->setIfLoc(readSourceLocation());
S->setLParenLoc(readSourceLocation());
S->setRParenLoc(readSourceLocation());
if (HasElse)
S->setElseLoc(readSourceLocation());
}
@ -247,6 +249,8 @@ void ASTStmtReader::VisitSwitchStmt(SwitchStmt *S) {
S->setConditionVariable(Record.getContext(), readDeclAs<VarDecl>());
S->setSwitchLoc(readSourceLocation());
S->setLParenLoc(readSourceLocation());
S->setRParenLoc(readSourceLocation());
SwitchCase *PrevSC = nullptr;
for (auto E = Record.size(); Record.getIdx() != E; ) {

View File

@ -152,6 +152,8 @@ void ASTStmtWriter::VisitIfStmt(IfStmt *S) {
Record.AddStmt(S->getInit());
Record.AddSourceLocation(S->getIfLoc());
Record.AddSourceLocation(S->getLParenLoc());
Record.AddSourceLocation(S->getRParenLoc());
if (HasElse)
Record.AddSourceLocation(S->getElseLoc());
@ -175,6 +177,8 @@ void ASTStmtWriter::VisitSwitchStmt(SwitchStmt *S) {
Record.AddDeclRef(S->getConditionVariable());
Record.AddSourceLocation(S->getSwitchLoc());
Record.AddSourceLocation(S->getLParenLoc());
Record.AddSourceLocation(S->getRParenLoc());
for (SwitchCase *SC = S->getSwitchCaseList(); SC;
SC = SC->getNextSwitchCase())