Skip to content

Commit

Permalink
Implement the Microsoft __if_exists/if_not_exists extension in initia…
Browse files Browse the repository at this point in the history
…lizer-list.

Necessary to parse Microsoft ATL code.

Example: 
  int array[] = {
    0, 
    __if_exists(CLASS::Type) {2, }
    3
  };

will declare an array of 2 or 3 elements depending on if CLASS::Type exists or not.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@146447 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
fpichet committed Dec 12, 2011
1 parent 2e17322 commit 9d24a8b
Show file tree
Hide file tree
Showing 4 changed files with 111 additions and 0 deletions.
2 changes: 2 additions & 0 deletions include/clang/Parse/Parser.h
Expand Up @@ -1548,6 +1548,8 @@ class Parser : public CodeCompletionHandler {
void ParseMicrosoftIfExistsExternalDeclaration();
void ParseMicrosoftIfExistsClassDeclaration(DeclSpec::TST TagType,
AccessSpecifier& CurAS);
bool ParseMicrosoftIfExistsBraceInitializer(ExprVector &InitExprs,
bool &InitExprsOk);
bool ParseAsmOperandsOpt(SmallVectorImpl<IdentifierInfo *> &Names,
SmallVectorImpl<Expr *> &Constraints,
SmallVectorImpl<Expr *> &Exprs);
Expand Down
74 changes: 74 additions & 0 deletions lib/Parse/ParseInit.cpp
Expand Up @@ -340,6 +340,17 @@ ExprResult Parser::ParseBraceInitializer() {
bool InitExprsOk = true;

while (1) {
// Handle Microsoft __if_exists/if_not_exists if necessary.
if (getLang().MicrosoftExt && (Tok.is(tok::kw___if_exists) ||
Tok.is(tok::kw___if_not_exists))) {
if (ParseMicrosoftIfExistsBraceInitializer(InitExprs, InitExprsOk)) {
if (Tok.isNot(tok::comma)) break;
ConsumeToken();
}
if (Tok.is(tok::r_brace)) break;
continue;
}

// Parse: designation[opt] initializer

// If we know that this cannot be a designation, just parse the nested
Expand Down Expand Up @@ -392,3 +403,66 @@ ExprResult Parser::ParseBraceInitializer() {
return ExprError(); // an error occurred.
}


// Return true if a comma (or closing brace) is necessary after the
// __if_exists/if_not_exists statement.
bool Parser::ParseMicrosoftIfExistsBraceInitializer(ExprVector &InitExprs,
bool &InitExprsOk) {
bool trailingComma = false;
IfExistsCondition Result;
if (ParseMicrosoftIfExistsCondition(Result))
return false;

BalancedDelimiterTracker Braces(*this, tok::l_brace);
if (Braces.consumeOpen()) {
Diag(Tok, diag::err_expected_lbrace);
return 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 false;
}

while (Tok.isNot(tok::eof)) {
trailingComma = false;
// If we know that this cannot be a designation, just parse the nested
// initializer directly.
ExprResult SubElt;
if (MayBeDesignationStart(Tok.getKind(), PP))
SubElt = ParseInitializerWithPotentialDesignator();
else
SubElt = ParseInitializer();

if (Tok.is(tok::ellipsis))
SubElt = Actions.ActOnPackExpansion(SubElt.get(), ConsumeToken());

// If we couldn't parse the subelement, bail out.
if (!SubElt.isInvalid())
InitExprs.push_back(SubElt.release());
else
InitExprsOk = false;

if (Tok.is(tok::comma)) {
ConsumeToken();
trailingComma = true;
}

if (Tok.is(tok::r_brace))
break;
}

Braces.consumeClose();

return !trailingComma;
}
29 changes: 29 additions & 0 deletions test/Parser/MicrosoftExtensions.cpp
Expand Up @@ -215,6 +215,35 @@ __if_not_exists(IF_EXISTS::Type_not) {
int var244;
}

int __if_exists_init_list() {

int array1[] = {
0,
__if_exists(IF_EXISTS::Type) {2, }
3
};

int array2[] = {
0,
__if_exists(IF_EXISTS::Type_not) { this wont compile }
3
};

int array3[] = {
0,
__if_not_exists(IF_EXISTS::Type_not) {2, }
3
};

int array4[] = {
0,
__if_not_exists(IF_EXISTS::Type) { this wont compile }
3
};

}


class IF_EXISTS_CLASS_TEST {
__if_exists(IF_EXISTS::Type) {
// __if_exists, __if_not_exists can nest
Expand Down
6 changes: 6 additions & 0 deletions test/SemaTemplate/ms-if-exists.cpp
Expand Up @@ -47,6 +47,12 @@ void f(T t) {
int *i = t; // expected-error{{no viable conversion from 'HasFoo' to 'int *'}}
{ }
}

int array2[] = {
0,
__if_exists(T::bar) {2, }// expected-warning{{dependent __if_exists declarations are ignored}}
3
};
}

template void f(HasFoo); // expected-note{{in instantiation of function template specialization 'f<HasFoo>' requested here}}
Expand Down

0 comments on commit 9d24a8b

Please sign in to comment.