summaryrefslogtreecommitdiffstats
path: root/clang/lib/Parse/ParseDecl.cpp
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2010-12-01 17:42:47 +0000
committerDouglas Gregor <dgregor@apple.com>2010-12-01 17:42:47 +0000
commitd1f69f6a1d1dc321cca8f7e903454ded41f3b26a (patch)
treea61fc77969149a9f69e6c19083c06a379150fba6 /clang/lib/Parse/ParseDecl.cpp
parentbe00735bcf4468a4bf768e7c15859b61fb32e134 (diff)
downloadbcm5719-llvm-d1f69f6a1d1dc321cca8f7e903454ded41f3b26a.tar.gz
bcm5719-llvm-d1f69f6a1d1dc321cca8f7e903454ded41f3b26a.zip
After parsing a ':' in an enum-specifier within class context,
disambiguate between an expression (for a bit-field width) and a type (for a fixed underlying type). Since the disambiguation can be expensive (due to tentative parsing), we perform a simplistic disambiguation based on one-token lookahead before going into the full-blown tentative parsing. Based on a patch by Daniel Wallin. llvm-svn: 120582
Diffstat (limited to 'clang/lib/Parse/ParseDecl.cpp')
-rw-r--r--clang/lib/Parse/ParseDecl.cpp54
1 files changed, 50 insertions, 4 deletions
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index db02c783515..f1fb7b29a12 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -1921,7 +1921,6 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc,
Actions.ActOnTagFinishDefinition(getCurScope(), TagDecl, RBraceLoc);
}
-
/// ParseEnumSpecifier
/// enum-specifier: [C99 6.7.2.2]
/// 'enum' identifier[opt] '{' enumerator-list '}'
@@ -2014,10 +2013,57 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
TypeResult BaseType;
+ // Parse the fixed underlying type.
if (getLang().CPlusPlus0x && Tok.is(tok::colon)) {
- ConsumeToken();
- SourceRange Range;
- BaseType = ParseTypeName(&Range);
+ bool PossibleBitfield = false;
+ if (getCurScope()->getFlags() & Scope::ClassScope) {
+ // If we're in class scope, this can either be an enum declaration with
+ // an underlying type, or a declaration of a bitfield member. We try to
+ // use a simple disambiguation scheme first to catch the common cases
+ // (integer literal, sizeof); if it's still ambiguous, we then consider
+ // anything that's a simple-type-specifier followed by '(' as an
+ // expression. This suffices because function types are not valid
+ // underlying types anyway.
+ TPResult TPR = isExpressionOrTypeSpecifierSimple(NextToken().getKind());
+ // If the next token starts an expression, we know we're parsing a
+ // bit-field. This is the common case.
+ if (TPR == TPResult::True())
+ PossibleBitfield = true;
+ // If the next token starts a type-specifier-seq, it may be either a
+ // a fixed underlying type or the start of a function-style cast in C++;
+ // lookahead one more token to see if it's obvious that we have a
+ // fixed underlying type.
+ else if (TPR == TPResult::False() &&
+ GetLookAheadToken(2).getKind() == tok::semi) {
+ // Consume the ':'.
+ ConsumeToken();
+ } else {
+ // We have the start of a type-specifier-seq, so we have to perform
+ // tentative parsing to determine whether we have an expression or a
+ // type.
+ TentativeParsingAction TPA(*this);
+
+ // Consume the ':'.
+ ConsumeToken();
+
+ if (isCXXDeclarationSpecifier() != TPResult::True()) {
+ // We'll parse this as a bitfield later.
+ PossibleBitfield = true;
+ TPA.Revert();
+ } else {
+ // We have a type-specifier-seq.
+ TPA.Commit();
+ }
+ }
+ } else {
+ // Consume the ':'.
+ ConsumeToken();
+ }
+
+ if (!PossibleBitfield) {
+ SourceRange Range;
+ BaseType = ParseTypeName(&Range);
+ }
}
// There are three options here. If we have 'enum foo;', then this is a
OpenPOWER on IntegriCloud