diff options
author | Douglas Gregor <dgregor@apple.com> | 2011-10-24 22:31:10 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2011-10-24 22:31:10 +0000 |
commit | 43edb32f1f032c366ad06faec09832912f538ba6 (patch) | |
tree | c2aefe872230813f17a7b1e56007334f8f0a41fe /clang/lib/Parse/Parser.cpp | |
parent | 9190e19b6609ae889cd7d9f82e31a81a2267d7af (diff) | |
download | bcm5719-llvm-43edb32f1f032c366ad06faec09832912f538ba6.tar.gz bcm5719-llvm-43edb32f1f032c366ad06faec09832912f538ba6.zip |
Rework Microsoft __if_exists/__if_not_exists parsing and semantic
analysis to separate dependent names from non-dependent names. For
dependent names, we'll behave differently from Visual C++:
- For __if_exists/__if_not_exists at class scope, we'll just warn
and then ignore them.
- For __if_exists/__if_not_exists in statements, we'll treat the
inner statement as a compound statement, which we only instantiate
in templates where the dependent name (after instantiation)
exists. This behavior is different from VC++, but it's as close as
we can get without encroaching ridiculousness.
The latter part (dependent statements) is not yet implemented.
llvm-svn: 142864
Diffstat (limited to 'clang/lib/Parse/Parser.cpp')
-rw-r--r-- | clang/lib/Parse/Parser.cpp | 81 |
1 files changed, 48 insertions, 33 deletions
diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp index 2face304c0a..90bed04e753 100644 --- a/clang/lib/Parse/Parser.cpp +++ b/clang/lib/Parse/Parser.cpp @@ -1470,81 +1470,91 @@ void Parser::CodeCompleteNaturalLanguage() { Actions.CodeCompleteNaturalLanguage(); } -bool Parser::ParseMicrosoftIfExistsCondition(bool& Result) { +bool Parser::ParseMicrosoftIfExistsCondition(IfExistsCondition& Result) { assert((Tok.is(tok::kw___if_exists) || Tok.is(tok::kw___if_not_exists)) && "Expected '__if_exists' or '__if_not_exists'"); - Token Condition = Tok; - SourceLocation IfExistsLoc = ConsumeToken(); + Result.IsIfExists = Tok.is(tok::kw___if_exists); + Result.KeywordLoc = ConsumeToken(); BalancedDelimiterTracker T(*this, tok::l_paren); if (T.consumeOpen()) { - Diag(Tok, diag::err_expected_lparen_after) << IfExistsLoc; - SkipUntil(tok::semi); + Diag(Tok, diag::err_expected_lparen_after) + << (Result.IsIfExists? "__if_exists" : "__if_not_exists"); return true; } // Parse nested-name-specifier. - CXXScopeSpec SS; - ParseOptionalCXXScopeSpecifier(SS, ParsedType(), false); + ParseOptionalCXXScopeSpecifier(Result.SS, ParsedType(), false); // Check nested-name specifier. - if (SS.isInvalid()) { - SkipUntil(tok::semi); + if (Result.SS.isInvalid()) { + T.skipToEnd(); return true; } // Parse the unqualified-id. - UnqualifiedId Name; - if (ParseUnqualifiedId(SS, false, true, true, ParsedType(), Name)) { - SkipUntil(tok::semi); + if (ParseUnqualifiedId(Result.SS, false, true, true, ParsedType(), + Result.Name)) { + T.skipToEnd(); return true; } - T.consumeClose(); - if (T.getCloseLocation().isInvalid()) + if (T.consumeClose()) return true; - + // Check if the symbol exists. - bool Exist = Actions.CheckMicrosoftIfExistsSymbol(SS, Name); + switch (Actions.CheckMicrosoftIfExistsSymbol(getCurScope(), Result.SS, + Result.Name)) { + case Sema::IER_Exists: + Result.Behavior = Result.IsIfExists ? IEB_Parse : IEB_Skip; + break; - Result = ((Condition.is(tok::kw___if_exists) && Exist) || - (Condition.is(tok::kw___if_not_exists) && !Exist)); + case Sema::IER_DoesNotExist: + Result.Behavior = !Result.IsIfExists ? IEB_Parse : IEB_Skip; + break; + + case Sema::IER_Dependent: + Result.Behavior = IEB_Dependent; + break; + } return false; } void Parser::ParseMicrosoftIfExistsExternalDeclaration() { - bool Result; + IfExistsCondition Result; if (ParseMicrosoftIfExistsCondition(Result)) return; - if (Tok.isNot(tok::l_brace)) { + BalancedDelimiterTracker Braces(*this, tok::l_brace); + if (Braces.consumeOpen()) { Diag(Tok, diag::err_expected_lbrace); return; } - ConsumeBrace(); - // Condition is false skip all inside the {}. - if (!Result) { - SkipUntil(tok::r_brace, false); + switch (Result.Behavior) { + case IEB_Parse: + // Parse declarations below. + break; + + case IEB_Dependent: + llvm_unreachable("Cannot have a dependent external declaration"); + + case IEB_Skip: + Braces.skipToEnd(); return; } - // Condition is true, parse the declaration. - while (Tok.isNot(tok::r_brace)) { + // Parse the declarations. + while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) { ParsedAttributesWithRange attrs(AttrFactory); MaybeParseCXX0XAttributes(attrs); MaybeParseMicrosoftAttributes(attrs); DeclGroupPtrTy Result = ParseExternalDeclaration(attrs); if (Result && !getCurScope()->getParent()) Actions.getASTConsumer().HandleTopLevelDecl(Result.get()); - } - - if (Tok.isNot(tok::r_brace)) { - Diag(Tok, diag::err_expected_rbrace); - return; - } - ConsumeBrace(); + } + Braces.consumeClose(); } Parser::DeclGroupPtrTy Parser::ParseModuleImport() { @@ -1629,3 +1639,8 @@ bool Parser::BalancedDelimiterTracker::consumeClose() { } return true; } + +void Parser::BalancedDelimiterTracker::skipToEnd() { + P.SkipUntil(Close, false); + Cleanup = false; +} |