diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Parse/ParseDeclCXX.cpp | 33 | ||||
-rw-r--r-- | lib/Parse/ParseStmt.cpp | 43 | ||||
-rw-r--r-- | lib/Parse/Parser.cpp | 81 | ||||
-rw-r--r-- | lib/Sema/SemaExprCXX.cpp | 30 |
4 files changed, 122 insertions, 65 deletions
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index 7583ccafeb..3d3d7c21cb 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -2757,25 +2757,32 @@ void Parser::ParseMicrosoftAttributes(ParsedAttributes &attrs, void Parser::ParseMicrosoftIfExistsClassDeclaration(DeclSpec::TST TagType, AccessSpecifier& CurAS) { - 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 the declarations below. + break; + + case IEB_Dependent: + Diag(Result.KeywordLoc, diag::warn_microsoft_dependent_exists) + << Result.IsIfExists; + // Fall through to skip. + + case IEB_Skip: + Braces.skipToEnd(); return; } - // Condition is true, parse the declaration. - while (Tok.isNot(tok::r_brace)) { - + while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) { // __if_exists, __if_not_exists can nest. if ((Tok.is(tok::kw___if_exists) || Tok.is(tok::kw___if_not_exists))) { ParseMicrosoftIfExistsClassDeclaration((DeclSpec::TST)TagType, CurAS); @@ -2808,10 +2815,6 @@ void Parser::ParseMicrosoftIfExistsClassDeclaration(DeclSpec::TST TagType, // Parse all the comma separated declarators. ParseCXXClassMemberDeclaration(CurAS, 0); } - - if (Tok.isNot(tok::r_brace)) { - Diag(Tok, diag::err_expected_rbrace); - return; - } - ConsumeBrace(); + + Braces.consumeClose(); } diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp index 8968a43480..5c2ed4e5f5 100644 --- a/lib/Parse/ParseStmt.cpp +++ b/lib/Parse/ParseStmt.cpp @@ -2136,19 +2136,43 @@ StmtResult Parser::ParseCXXCatchBlock() { } void Parser::ParseMicrosoftIfExistsStatement(StmtVector &Stmts) { - bool Result; + IfExistsCondition Result; if (ParseMicrosoftIfExistsCondition(Result)) return; - if (Tok.isNot(tok::l_brace)) { + // Handle dependent statements by parsing the braces as a compound statement. + // This is not the same behavior as Visual C++, which don't treat this as a + // compound statement, but for Clang's type checking we can't have anything + // inside these braces escaping to the surrounding code. + if (Result.Behavior == IEB_Dependent) { + if (!Tok.is(tok::l_brace)) { + Diag(Tok, diag::err_expected_lbrace); + return; + } + + ParsedAttributes Attrs(AttrFactory); + StmtResult Compound = ParseCompoundStatement(Attrs); + // FIXME: We're dropping these statements on the floor. + return; + } + + 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 the statements below. + break; + + case IEB_Dependent: + llvm_unreachable("Dependent case handled above"); + break; + + case IEB_Skip: + Braces.skipToEnd(); return; } @@ -2158,10 +2182,5 @@ void Parser::ParseMicrosoftIfExistsStatement(StmtVector &Stmts) { if (R.isUsable()) Stmts.push_back(R.release()); } - - if (Tok.isNot(tok::r_brace)) { - Diag(Tok, diag::err_expected_rbrace); - return; - } - ConsumeBrace(); + Braces.consumeClose(); } diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp index 2face304c0..90bed04e75 100644 --- a/lib/Parse/Parser.cpp +++ b/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; +} diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 64a9dd9c76..c4571c96d0 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -4665,17 +4665,37 @@ StmtResult Sema::ActOnFinishFullStmt(Stmt *FullStmt) { return MaybeCreateStmtWithCleanups(FullStmt); } -bool Sema::CheckMicrosoftIfExistsSymbol(CXXScopeSpec &SS, - UnqualifiedId &Name) { +Sema::IfExistsResult Sema::CheckMicrosoftIfExistsSymbol(Scope *S, + CXXScopeSpec &SS, + UnqualifiedId &Name) { DeclarationNameInfo TargetNameInfo = GetNameFromUnqualifiedId(Name); DeclarationName TargetName = TargetNameInfo.getName(); if (!TargetName) - return false; + return IER_DoesNotExist; + // If the name itself is dependent, then the result is dependent. + if (TargetName.isDependentName()) + return IER_Dependent; + // Do the redeclaration lookup in the current scope. LookupResult R(*this, TargetNameInfo, Sema::LookupAnyName, Sema::NotForRedeclaration); + LookupParsedName(R, S, &SS); R.suppressDiagnostics(); - LookupParsedName(R, getCurScope(), &SS); - return !R.empty(); + + switch (R.getResultKind()) { + case LookupResult::Found: + case LookupResult::FoundOverloaded: + case LookupResult::FoundUnresolvedValue: + case LookupResult::Ambiguous: + return IER_Exists; + + case LookupResult::NotFound: + return IER_DoesNotExist; + + case LookupResult::NotFoundInCurrentInstantiation: + return IER_Dependent; + } + + return IER_DoesNotExist; } |