summaryrefslogtreecommitdiffstats
path: root/clang/lib/Parse
diff options
context:
space:
mode:
authorPeter Collingbourne <peter@pcc.me.uk>2016-06-23 18:11:15 +0000
committerPeter Collingbourne <peter@pcc.me.uk>2016-06-23 18:11:15 +0000
commitb77ebd749af6171a565c19139849fc7d8d4209e4 (patch)
tree124ac4e509017b031febc648fd1cd2d9d0ac75e9 /clang/lib/Parse
parent38bb1c15fdf76ab0632c0062d06867cb6c93c7af (diff)
downloadbcm5719-llvm-b77ebd749af6171a565c19139849fc7d8d4209e4.tar.gz
bcm5719-llvm-b77ebd749af6171a565c19139849fc7d8d4209e4.zip
Revert r273548, "Rearrange condition handling so that semantic checks on a condition variable"
as it caused a regression in -Wfor-loop-analysis. llvm-svn: 273589
Diffstat (limited to 'clang/lib/Parse')
-rw-r--r--clang/lib/Parse/ParseDeclCXX.cpp7
-rw-r--r--clang/lib/Parse/ParseExprCXX.cpp44
-rw-r--r--clang/lib/Parse/ParseStmt.cpp80
3 files changed, 78 insertions, 53 deletions
diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp
index 5718e1e50e9..d55b2d9442c 100644
--- a/clang/lib/Parse/ParseDeclCXX.cpp
+++ b/clang/lib/Parse/ParseDeclCXX.cpp
@@ -3420,11 +3420,10 @@ Parser::tryParseExceptionSpecification(bool Delayed,
NoexceptExpr = ParseConstantExpression();
T.consumeClose();
// The argument must be contextually convertible to bool. We use
- // CheckBooleanCondition for this purpose.
- // FIXME: Add a proper Sema entry point for this.
+ // ActOnBooleanCondition for this purpose.
if (!NoexceptExpr.isInvalid()) {
- NoexceptExpr =
- Actions.CheckBooleanCondition(KeywordLoc, NoexceptExpr.get());
+ NoexceptExpr = Actions.ActOnBooleanCondition(getCurScope(), KeywordLoc,
+ NoexceptExpr.get());
NoexceptRange = SourceRange(KeywordLoc, T.getCloseLocation());
} else {
NoexceptType = EST_None;
diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp
index 00f20e5e7b7..b0740970d88 100644
--- a/clang/lib/Parse/ParseExprCXX.cpp
+++ b/clang/lib/Parse/ParseExprCXX.cpp
@@ -1726,19 +1726,27 @@ Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) {
/// [GNU] type-specifier-seq declarator simple-asm-expr[opt] attributes[opt]
/// '=' assignment-expression
///
+/// \param ExprOut if the condition was parsed as an expression, the parsed
+/// expression.
+///
+/// \param DeclOut if the condition was parsed as a declaration, the parsed
+/// declaration.
+///
/// \param Loc The location of the start of the statement that requires this
/// condition, e.g., the "for" in a for loop.
///
/// \param ConvertToBoolean Whether the condition expression should be
/// converted to a boolean value.
///
-/// \returns The parsed condition.
-Sema::ConditionResult Parser::ParseCXXCondition(SourceLocation Loc,
- Sema::ConditionKind CK) {
+/// \returns true if there was a parsing, false otherwise.
+bool Parser::ParseCXXCondition(ExprResult &ExprOut,
+ Decl *&DeclOut,
+ SourceLocation Loc,
+ bool ConvertToBoolean) {
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Condition);
cutOffParsing();
- return Sema::ConditionError();
+ return true;
}
ParsedAttributesWithRange attrs(AttrFactory);
@@ -1748,11 +1756,16 @@ Sema::ConditionResult Parser::ParseCXXCondition(SourceLocation Loc,
ProhibitAttributes(attrs);
// Parse the expression.
- ExprResult Expr = ParseExpression(); // expression
- if (Expr.isInvalid())
- return Sema::ConditionError();
+ ExprOut = ParseExpression(); // expression
+ DeclOut = nullptr;
+ if (ExprOut.isInvalid())
+ return true;
- return Actions.ActOnCondition(getCurScope(), Loc, Expr.get(), CK);
+ // If required, convert to a boolean value.
+ if (ConvertToBoolean)
+ ExprOut
+ = Actions.ActOnBooleanCondition(getCurScope(), Loc, ExprOut.get());
+ return ExprOut.isInvalid();
}
// type-specifier-seq
@@ -1770,7 +1783,7 @@ Sema::ConditionResult Parser::ParseCXXCondition(SourceLocation Loc,
ExprResult AsmLabel(ParseSimpleAsm(&Loc));
if (AsmLabel.isInvalid()) {
SkipUntil(tok::semi, StopAtSemi);
- return Sema::ConditionError();
+ return true;
}
DeclaratorInfo.setAsmLabel(AsmLabel.get());
DeclaratorInfo.SetRangeEnd(Loc);
@@ -1782,9 +1795,8 @@ Sema::ConditionResult Parser::ParseCXXCondition(SourceLocation Loc,
// Type-check the declaration itself.
DeclResult Dcl = Actions.ActOnCXXConditionDeclaration(getCurScope(),
DeclaratorInfo);
- if (Dcl.isInvalid())
- return Sema::ConditionError();
- Decl *DeclOut = Dcl.get();
+ DeclOut = Dcl.get();
+ ExprOut = ExprError();
// '=' assignment-expression
// If a '==' or '+=' is found, suggest a fixit to '='.
@@ -1804,11 +1816,12 @@ Sema::ConditionResult Parser::ParseCXXCondition(SourceLocation Loc,
SourceLocation LParen = ConsumeParen(), RParen = LParen;
if (SkipUntil(tok::r_paren, StopAtSemi | StopBeforeMatch))
RParen = ConsumeParen();
- Diag(DeclOut->getLocation(),
+ Diag(DeclOut ? DeclOut->getLocation() : LParen,
diag::err_expected_init_in_condition_lparen)
<< SourceRange(LParen, RParen);
} else {
- Diag(DeclOut->getLocation(), diag::err_expected_init_in_condition);
+ Diag(DeclOut ? DeclOut->getLocation() : Tok.getLocation(),
+ diag::err_expected_init_in_condition);
}
if (!InitExpr.isInvalid())
@@ -1821,7 +1834,8 @@ Sema::ConditionResult Parser::ParseCXXCondition(SourceLocation Loc,
// (This is currently handled by Sema).
Actions.FinalizeDeclaration(DeclOut);
- return Actions.ActOnConditionVariable(DeclOut, Loc, CK);
+
+ return false;
}
/// ParseCXXSimpleTypeSpecifier - [C++ 7.1.5.2] Simple type specifiers.
diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp
index c849554238e..8173d09cbbe 100644
--- a/clang/lib/Parse/ParseStmt.cpp
+++ b/clang/lib/Parse/ParseStmt.cpp
@@ -1052,28 +1052,29 @@ StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) {
/// 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.
-bool Parser::ParseParenExprOrCondition(Sema::ConditionResult &Cond,
+bool Parser::ParseParenExprOrCondition(ExprResult &ExprResult,
+ Decl *&DeclResult,
SourceLocation Loc,
- Sema::ConditionKind CK) {
+ bool ConvertToBoolean) {
BalancedDelimiterTracker T(*this, tok::l_paren);
T.consumeOpen();
if (getLangOpts().CPlusPlus)
- Cond = ParseCXXCondition(Loc, CK);
+ ParseCXXCondition(ExprResult, DeclResult, Loc, ConvertToBoolean);
else {
- ExprResult CondExpr = ParseExpression();
+ ExprResult = ParseExpression();
+ DeclResult = nullptr;
// If required, convert to a boolean value.
- if (CondExpr.isInvalid())
- Cond = Sema::ConditionError();
- else
- Cond = Actions.ActOnCondition(getCurScope(), Loc, CondExpr.get(), CK);
+ if (!ExprResult.isInvalid() && ConvertToBoolean)
+ ExprResult
+ = Actions.ActOnBooleanCondition(getCurScope(), Loc, ExprResult.get());
}
// If the parser was confused by the condition and we don't have a ')', try to
// recover by skipping ahead to a semi and bailing out. If condexp is
// semantically invalid but we have well formed code, keep going.
- if (Cond.isInvalid() && Tok.isNot(tok::r_paren)) {
+ if (ExprResult.isInvalid() && !DeclResult && Tok.isNot(tok::r_paren)) {
SkipUntil(tok::semi);
// Skipping may have stopped if it found the containing ')'. If so, we can
// continue parsing the if statement.
@@ -1131,10 +1132,13 @@ StmtResult Parser::ParseIfStatement(SourceLocation *TrailingElseLoc) {
ParseScope IfScope(this, Scope::DeclScope | Scope::ControlScope, C99orCXX);
// Parse the condition.
- Sema::ConditionResult Cond;
- if (ParseParenExprOrCondition(Cond, IfLoc, Sema::ConditionKind::Boolean))
+ ExprResult CondExp;
+ Decl *CondVar = nullptr;
+ if (ParseParenExprOrCondition(CondExp, CondVar, IfLoc, true))
return StmtError();
+ FullExprArg FullCondExp(Actions.MakeFullExpr(CondExp.get(), IfLoc));
+
// C99 6.8.4p3 - In C99, the body of the if statement is a scope, even if
// there is no compound stmt. C90 does not have this clause. We only do this
// if the body isn't a compound statement to avoid push/pop in common cases.
@@ -1217,8 +1221,8 @@ StmtResult Parser::ParseIfStatement(SourceLocation *TrailingElseLoc) {
if (ElseStmt.isInvalid())
ElseStmt = Actions.ActOnNullStmt(ElseStmtLoc);
- return Actions.ActOnIfStmt(IfLoc, Cond, ThenStmt.get(), ElseLoc,
- ElseStmt.get());
+ return Actions.ActOnIfStmt(IfLoc, FullCondExp, CondVar, ThenStmt.get(),
+ ElseLoc, ElseStmt.get());
}
/// ParseSwitchStatement
@@ -1255,11 +1259,13 @@ StmtResult Parser::ParseSwitchStatement(SourceLocation *TrailingElseLoc) {
ParseScope SwitchScope(this, ScopeFlags);
// Parse the condition.
- Sema::ConditionResult Cond;
- if (ParseParenExprOrCondition(Cond, SwitchLoc, Sema::ConditionKind::Switch))
+ ExprResult Cond;
+ Decl *CondVar = nullptr;
+ if (ParseParenExprOrCondition(Cond, CondVar, SwitchLoc, false))
return StmtError();
- StmtResult Switch = Actions.ActOnStartOfSwitchStmt(SwitchLoc, Cond);
+ StmtResult Switch
+ = Actions.ActOnStartOfSwitchStmt(SwitchLoc, Cond.get(), CondVar);
if (Switch.isInvalid()) {
// Skip the switch body.
@@ -1341,10 +1347,13 @@ StmtResult Parser::ParseWhileStatement(SourceLocation *TrailingElseLoc) {
ParseScope WhileScope(this, ScopeFlags);
// Parse the condition.
- Sema::ConditionResult Cond;
- if (ParseParenExprOrCondition(Cond, WhileLoc, Sema::ConditionKind::Boolean))
+ ExprResult Cond;
+ Decl *CondVar = nullptr;
+ if (ParseParenExprOrCondition(Cond, CondVar, WhileLoc, true))
return StmtError();
+ FullExprArg FullCond(Actions.MakeFullExpr(Cond.get(), WhileLoc));
+
// C99 6.8.5p5 - In C99, the body of the while statement is a scope, even if
// there is no compound stmt. C90 does not have this clause. We only do this
// if the body isn't a compound statement to avoid push/pop in common cases.
@@ -1365,10 +1374,10 @@ StmtResult Parser::ParseWhileStatement(SourceLocation *TrailingElseLoc) {
InnerScope.Exit();
WhileScope.Exit();
- if (Cond.isInvalid() || Body.isInvalid())
+ if ((Cond.isInvalid() && !CondVar) || Body.isInvalid())
return StmtError();
- return Actions.ActOnWhileStmt(WhileLoc, Cond, Body.get());
+ return Actions.ActOnWhileStmt(WhileLoc, FullCond, CondVar, Body.get());
}
/// ParseDoStatement
@@ -1526,10 +1535,12 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) {
bool ForEach = false, ForRange = false;
StmtResult FirstPart;
- Sema::ConditionResult SecondPart;
+ bool SecondPartIsInvalid = false;
+ FullExprArg SecondPart(Actions);
ExprResult Collection;
ForRangeInit ForRangeInit;
FullExprArg ThirdPart(Actions);
+ Decl *SecondVar = nullptr;
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteOrdinaryName(getCurScope(),
@@ -1634,7 +1645,7 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) {
Diag(Tok, diag::err_for_range_expected_decl)
<< FirstPart.get()->getSourceRange();
SkipUntil(tok::r_paren, StopBeforeMatch);
- SecondPart = Sema::ConditionError();
+ SecondPartIsInvalid = true;
} else {
if (!Value.isInvalid()) {
Diag(Tok, diag::err_expected_semi_for);
@@ -1649,28 +1660,29 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) {
// Parse the second part of the for specifier.
getCurScope()->AddFlags(Scope::BreakScope | Scope::ContinueScope);
- if (!ForEach && !ForRange && !SecondPart.isInvalid()) {
+ if (!ForEach && !ForRange) {
+ assert(!SecondPart.get() && "Shouldn't have a second expression yet.");
// Parse the second part of the for specifier.
if (Tok.is(tok::semi)) { // for (...;;
// no second part.
} else if (Tok.is(tok::r_paren)) {
// missing both semicolons.
} else {
+ ExprResult Second;
if (getLangOpts().CPlusPlus)
- SecondPart = ParseCXXCondition(ForLoc, Sema::ConditionKind::Boolean);
+ ParseCXXCondition(Second, SecondVar, ForLoc, true);
else {
- ExprResult SecondExpr = ParseExpression();
- if (SecondExpr.isInvalid())
- SecondPart = Sema::ConditionError();
- else
- SecondPart =
- Actions.ActOnCondition(getCurScope(), ForLoc, SecondExpr.get(),
- Sema::ConditionKind::Boolean);
+ Second = ParseExpression();
+ if (!Second.isInvalid())
+ Second = Actions.ActOnBooleanCondition(getCurScope(), ForLoc,
+ Second.get());
}
+ SecondPartIsInvalid = Second.isInvalid();
+ SecondPart = Actions.MakeFullExpr(Second.get(), ForLoc);
}
if (Tok.isNot(tok::semi)) {
- if (!SecondPart.isInvalid())
+ if (!SecondPartIsInvalid || SecondVar)
Diag(Tok, diag::err_expected_semi_for);
else
// Skip until semicolon or rparen, don't consume it.
@@ -1769,8 +1781,8 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) {
return Actions.FinishCXXForRangeStmt(ForRangeStmt.get(), Body.get());
return Actions.ActOnForStmt(ForLoc, T.getOpenLocation(), FirstPart.get(),
- SecondPart, ThirdPart, T.getCloseLocation(),
- Body.get());
+ SecondPart, SecondVar, ThirdPart,
+ T.getCloseLocation(), Body.get());
}
/// ParseGotoStatement
OpenPOWER on IntegriCloud