From: Francois Pichet Date: Sat, 7 May 2011 17:30:27 +0000 (+0000) Subject: Add support for _if_exists and __if_not_exists at namespace/global scope. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f986038beed360c031de8654cfba43a5d3184605;p=clang Add support for _if_exists and __if_not_exists at namespace/global scope. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@131050 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index adf72d0a4b..611c5d63aa 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -1308,7 +1308,9 @@ private: StmtResult ParseReturnStatement(ParsedAttributes &Attr); StmtResult ParseAsmStatement(bool &msAsm); StmtResult FuzzyParseMicrosoftAsmStatement(SourceLocation AsmLoc); + bool ParseMicrosoftIfExistsCondition(bool& Result); void ParseMicrosoftIfExistsStatement(StmtVector &Stmts); + void ParseMicrosoftIfExistsDeclaration(); bool ParseAsmOperandsOpt(llvm::SmallVectorImpl &Names, llvm::SmallVectorImpl &Constraints, llvm::SmallVectorImpl &Exprs); diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp index 12ab5e2767..6cc8b57b61 100644 --- a/lib/Parse/ParseStmt.cpp +++ b/lib/Parse/ParseStmt.cpp @@ -2008,51 +2008,18 @@ StmtResult Parser::ParseCXXCatchBlock() { } void Parser::ParseMicrosoftIfExistsStatement(StmtVector &Stmts) { - 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(); - - SourceLocation LParenLoc = Tok.getLocation(); - if (Tok.isNot(tok::l_paren)) { - Diag(Tok, diag::err_expected_lparen_after) << IfExistsLoc; - SkipUntil(tok::semi); + bool Result; + if (ParseMicrosoftIfExistsCondition(Result)) return; - } - ConsumeParen(); // eat the '('. - // Parse nested-name-specifier. - CXXScopeSpec SS; - ParseOptionalCXXScopeSpecifier(SS, ParsedType(), false); - - // Check nested-name specifier. - if (SS.isInvalid()) { - SkipUntil(tok::semi); - return; - } - - // Parse the unqualified-id. - UnqualifiedId Name; - if (ParseUnqualifiedId(SS, false, true, true, ParsedType(), Name)) { - SkipUntil(tok::semi); - return; - } - - if (MatchRHSPunctuation(tok::r_paren, LParenLoc).isInvalid()) - return; - if (Tok.isNot(tok::l_brace)) { Diag(Tok, diag::err_expected_lbrace); return; } ConsumeBrace(); - // Check if the symbol exists. - bool Exist = Actions.CheckMicrosoftIfExistsSymbol(SS, Name); - - // If the condition is false skip the tokens until the '}' - if ((Condition.is(tok::kw___if_exists) && !Exist) || - (Condition.is(tok::kw___if_not_exists) && Exist)) { + // Condition is false skip all inside the {}. + if (!Result) { SkipUntil(tok::r_brace, false); return; } diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp index 4d08699bdd..263a4916b6 100644 --- a/lib/Parse/Parser.cpp +++ b/lib/Parse/Parser.cpp @@ -20,6 +20,7 @@ #include "RAIIObjectsForParser.h" #include "ParsePragma.h" #include "clang/AST/DeclTemplate.h" +#include "clang/AST/ASTConsumer.h" using namespace clang; Parser::Parser(Preprocessor &pp, Sema &actions) @@ -653,6 +654,11 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs, // FIXME: Detect C++ linkage specifications here? goto dont_know; + case tok::kw___if_exists: + case tok::kw___if_not_exists: + ParseMicrosoftIfExistsDeclaration(); + return DeclGroupPtrTy(); + default: dont_know: // We can't tell whether this is a function-definition or declaration yet. @@ -1374,3 +1380,80 @@ void Parser::CodeCompleteMacroArgument(IdentifierInfo *Macro, void Parser::CodeCompleteNaturalLanguage() { Actions.CodeCompleteNaturalLanguage(); } + +bool Parser::ParseMicrosoftIfExistsCondition(bool& 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(); + + SourceLocation LParenLoc = Tok.getLocation(); + if (Tok.isNot(tok::l_paren)) { + Diag(Tok, diag::err_expected_lparen_after) << IfExistsLoc; + SkipUntil(tok::semi); + return true; + } + ConsumeParen(); // eat the '('. + + // Parse nested-name-specifier. + CXXScopeSpec SS; + ParseOptionalCXXScopeSpecifier(SS, ParsedType(), false); + + // Check nested-name specifier. + if (SS.isInvalid()) { + SkipUntil(tok::semi); + return true; + } + + // Parse the unqualified-id. + UnqualifiedId Name; + if (ParseUnqualifiedId(SS, false, true, true, ParsedType(), Name)) { + SkipUntil(tok::semi); + return true; + } + + if (MatchRHSPunctuation(tok::r_paren, LParenLoc).isInvalid()) + return true; + + // Check if the symbol exists. + bool Exist = Actions.CheckMicrosoftIfExistsSymbol(SS, Name); + + Result = ((Condition.is(tok::kw___if_exists) && Exist) || + (Condition.is(tok::kw___if_not_exists) && !Exist)); + + return false; +} + +void Parser::ParseMicrosoftIfExistsDeclaration() { + bool Result; + if (ParseMicrosoftIfExistsCondition(Result)) + return; + + if (Tok.isNot(tok::l_brace)) { + Diag(Tok, diag::err_expected_lbrace); + return; + } + ConsumeBrace(); + + // Condition is false skip all inside the {}. + if (!Result) { + SkipUntil(tok::r_brace, false); + return; + } + + // Condition is true, parse the declaration. + while (Tok.isNot(tok::r_brace)) { + 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(); +} diff --git a/test/Parser/MicrosoftExtensions.cpp b/test/Parser/MicrosoftExtensions.cpp index 933231d5f7..292d3e1239 100644 --- a/test/Parser/MicrosoftExtensions.cpp +++ b/test/Parser/MicrosoftExtensions.cpp @@ -174,26 +174,36 @@ private: }; int __if_exists_test() { - int b=0; - - __if_exists(IF_EXISTS::Type) { b++; b++; } - __if_exists(IF_EXISTS::Type_not) { this wont compile. } - __if_not_exists(IF_EXISTS::Type) { this wont compile. } - __if_not_exists(IF_EXISTS::Type_not) { b++; b++; } +} + + +__if_exists(IF_EXISTS::Type) { + int var23; +} + +__if_exists(IF_EXISTS::Type_not) { + this wont compile. +} + +__if_not_exists(IF_EXISTS::Type) { + this wont compile. +} +__if_not_exists(IF_EXISTS::Type_not) { + int var244; }