Add support for _if_exists and __if_not_exists at namespace/global scope.

llvm-svn: 131050
This commit is contained in:
Francois Pichet 2011-05-07 17:30:27 +00:00
parent af32728a57
commit a5b3fcbc02
4 changed files with 106 additions and 44 deletions

View File

@ -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<IdentifierInfo *> &Names,
llvm::SmallVectorImpl<ExprTy *> &Constraints,
llvm::SmallVectorImpl<ExprTy *> &Exprs);

View File

@ -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;
}

View File

@ -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();
}

View File

@ -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;
}