diff options
author | Francois Pichet <pichet2000@gmail.com> | 2011-12-12 23:24:39 +0000 |
---|---|---|
committer | Francois Pichet <pichet2000@gmail.com> | 2011-12-12 23:24:39 +0000 |
commit | 9d24a8be93b28488dbfb9bbe8aa6fe35b21a5b0c (patch) | |
tree | 2b4a322ce4bea3d1ee2c6505ac2a7c48b2c2bd83 | |
parent | 2e1732299461634b9791ddfe6e3770c6be3a3675 (diff) |
Implement the Microsoft __if_exists/if_not_exists extension in initializer-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
-rw-r--r-- | include/clang/Parse/Parser.h | 2 | ||||
-rw-r--r-- | lib/Parse/ParseInit.cpp | 74 | ||||
-rw-r--r-- | test/Parser/MicrosoftExtensions.cpp | 29 | ||||
-rw-r--r-- | test/SemaTemplate/ms-if-exists.cpp | 6 |
4 files changed, 111 insertions, 0 deletions
diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index a60800630e..07d21bfeed 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -1548,6 +1548,8 @@ private: 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); diff --git a/lib/Parse/ParseInit.cpp b/lib/Parse/ParseInit.cpp index 33abc93254..ba7a024ac5 100644 --- a/lib/Parse/ParseInit.cpp +++ b/lib/Parse/ParseInit.cpp @@ -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 @@ -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; +} diff --git a/test/Parser/MicrosoftExtensions.cpp b/test/Parser/MicrosoftExtensions.cpp index 0c5459cba2..89394c303c 100644 --- a/test/Parser/MicrosoftExtensions.cpp +++ b/test/Parser/MicrosoftExtensions.cpp @@ -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 diff --git a/test/SemaTemplate/ms-if-exists.cpp b/test/SemaTemplate/ms-if-exists.cpp index 8ac4e2418c..04f4a63623 100644 --- a/test/SemaTemplate/ms-if-exists.cpp +++ b/test/SemaTemplate/ms-if-exists.cpp @@ -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}} |