Make sure parens/braces/brackets are correctly balanced.

In a line like:

(;

the semicolon leaves Parser:ParenCount unbalanced (it's 1 even though we stopped looking for a right paren).
This may affect later parsing and result in bad recovery for parsing errors.

llvm-svn: 106213
This commit is contained in:
Argyrios Kyrtzidis 2010-06-17 10:52:18 +00:00
parent fa533e7652
commit 355094ef06
5 changed files with 34 additions and 1 deletions

View File

@ -72,6 +72,7 @@ namespace prec {
class Parser {
friend class PragmaUnusedHandler;
friend class ColonProtectionRAIIObject;
friend class ParenBraceBracketBalancer;
PrettyStackTraceParserEntry CrashInfo;
Preprocessor &PP;

View File

@ -309,6 +309,8 @@ AttributeList* Parser::ParseMicrosoftTypeAttributes(AttributeList *CurrAttr) {
Parser::DeclGroupPtrTy Parser::ParseDeclaration(unsigned Context,
SourceLocation &DeclEnd,
CXX0XAttributeList Attr) {
ParenBraceBracketBalancer BalancerRAIIObj(*this);
DeclPtrTy SingleDecl;
switch (Tok.getKind()) {
case tok::kw_template:

View File

@ -78,6 +78,8 @@ Parser::ParseStatementOrDeclaration(bool OnlyStatement) {
const char *SemiError = 0;
OwningStmtResult Res(Actions);
ParenBraceBracketBalancer BalancerRAIIObj(*this);
CXX0XAttributeList Attr;
if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier())
Attr = ParseCXX0XAttributes();

View File

@ -127,7 +127,16 @@ SourceLocation Parser::MatchRHSPunctuation(tok::TokenKind RHSTok,
}
Diag(Tok, DID);
Diag(LHSLoc, diag::note_matching) << LHSName;
SkipUntil(RHSTok);
if (!SkipUntil(RHSTok)) {
// We stopped before finding a RHS token, e.g. we encountered a ';'.
// Balance Paren/Brace/Bracket counting.
switch (RHSTok) {
default: break;
case tok::r_paren : assert(ParenCount > 0); --ParenCount; break;
case tok::r_brace : assert(BraceCount > 0); --BraceCount; break;
case tok::r_square: assert(BracketCount > 0); --BracketCount; break;
}
}
return R;
}
@ -401,6 +410,8 @@ void Parser::ParseTranslationUnit() {
///
/// [C++0x/GNU] 'extern' 'template' declaration
Parser::DeclGroupPtrTy Parser::ParseExternalDeclaration(CXX0XAttributeList Attr) {
ParenBraceBracketBalancer BalancerRAIIObj(*this);
DeclPtrTy SingleDecl;
switch (Tok.getKind()) {
case tok::semi:

View File

@ -80,6 +80,23 @@ namespace clang {
}
};
/// \brief RAII object that makes sure paren/bracket/brace count is correct
/// after declaration/statement parsing, even when there's a parsing error.
class ParenBraceBracketBalancer {
Parser &P;
unsigned short ParenCount, BracketCount, BraceCount;
public:
ParenBraceBracketBalancer(Parser &p)
: P(p), ParenCount(p.ParenCount), BracketCount(p.BracketCount),
BraceCount(p.BraceCount) { }
~ParenBraceBracketBalancer() {
P.ParenCount = ParenCount;
P.BracketCount = BracketCount;
P.BraceCount = BraceCount;
}
};
} // end namespace clang
#endif