diff options
author | Douglas Gregor <dgregor@apple.com> | 2012-08-30 20:04:43 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2012-08-30 20:04:43 +0000 |
commit | d295970adc93ed4035d18df23673c2a72d124cc8 (patch) | |
tree | 11ebde04a51702b6e41497d589af8804254b9b2f /lib | |
parent | 66341c596f93d0c6475d839db94072b8ebd1cf5b (diff) |
Extend the "__is_pod" hack, which demotes various type trait keywords
(__is_pod, __is_signed, etc.) to normal identifiers if they are
encountered in certain places in the grammar where we know that prior
versions of libstdc++ or libc++ use them, to still allow the use of
these keywords as type traits. Fixes <rdar://problem/9836262> and PR10184.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@162937 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Lex/PPMacroExpansion.cpp | 14 | ||||
-rw-r--r-- | lib/Parse/ParseExpr.cpp | 51 |
2 files changed, 52 insertions, 13 deletions
diff --git a/lib/Lex/PPMacroExpansion.cpp b/lib/Lex/PPMacroExpansion.cpp index 5c5bc00fe2..524f3ab82c 100644 --- a/lib/Lex/PPMacroExpansion.cpp +++ b/lib/Lex/PPMacroExpansion.cpp @@ -719,22 +719,12 @@ static bool HasFeature(const Preprocessor &PP, const IdentifierInfo *II) { // "struct __is_empty" parsing hack hasn't been needed in this // translation unit. If it has, __is_empty reverts to a normal // identifier and __has_feature(is_empty) evaluates false. - .Case("is_empty", - LangOpts.CPlusPlus && - PP.getIdentifierInfo("__is_empty")->getTokenID() - != tok::identifier) + .Case("is_empty", LangOpts.CPlusPlus) .Case("is_enum", LangOpts.CPlusPlus) .Case("is_final", LangOpts.CPlusPlus) .Case("is_literal", LangOpts.CPlusPlus) .Case("is_standard_layout", LangOpts.CPlusPlus) - // __is_pod is available only if the horrible - // "struct __is_pod" parsing hack hasn't been needed in this - // translation unit. If it has, __is_pod reverts to a normal - // identifier and __has_feature(is_pod) evaluates false. - .Case("is_pod", - LangOpts.CPlusPlus && - PP.getIdentifierInfo("__is_pod")->getTokenID() - != tok::identifier) + .Case("is_pod", LangOpts.CPlusPlus) .Case("is_polymorphic", LangOpts.CPlusPlus) .Case("is_trivial", LangOpts.CPlusPlus) .Case("is_trivially_assignable", LangOpts.CPlusPlus) diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp index 8df08b8184..855861380d 100644 --- a/lib/Parse/ParseExpr.cpp +++ b/lib/Parse/ParseExpr.cpp @@ -741,6 +741,55 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, // Avoid the unnecessary parse-time lookup in the common case // where the syntax forbids a type. const Token &Next = NextToken(); + + // If this identifier was reverted from a token ID, and the next token + // is a parenthesis, this is likely to be a use of a type trait. Check + // those tokens. + if (Next.is(tok::l_paren) && + Tok.is(tok::identifier) && + Tok.getIdentifierInfo()->hasRevertedTokenIDToIdentifier()) { + IdentifierInfo *II = Tok.getIdentifierInfo(); + // Build up the mapping of revertable type traits, for future use. + if (RevertableTypeTraits.empty()) { +#define RTT_JOIN2(X) X +#define RTT_JOIN(X,Y) X##Y +#define REVERTABLE_TYPE_TRAIT(Name) \ + RevertableTypeTraits[PP.getIdentifierInfo(#Name)] \ + = RTT_JOIN(tok::kw_,Name) + + REVERTABLE_TYPE_TRAIT(__is_arithmetic); + REVERTABLE_TYPE_TRAIT(__is_convertible); + REVERTABLE_TYPE_TRAIT(__is_empty); + REVERTABLE_TYPE_TRAIT(__is_floating_point); + REVERTABLE_TYPE_TRAIT(__is_function); + REVERTABLE_TYPE_TRAIT(__is_fundamental); + REVERTABLE_TYPE_TRAIT(__is_integral); + REVERTABLE_TYPE_TRAIT(__is_member_function_pointer); + REVERTABLE_TYPE_TRAIT(__is_member_pointer); + REVERTABLE_TYPE_TRAIT(__is_pod); + REVERTABLE_TYPE_TRAIT(__is_pointer); + REVERTABLE_TYPE_TRAIT(__is_same); + REVERTABLE_TYPE_TRAIT(__is_scalar); + REVERTABLE_TYPE_TRAIT(__is_signed); + REVERTABLE_TYPE_TRAIT(__is_unsigned); + REVERTABLE_TYPE_TRAIT(__is_void); +#undef REVERTABLE_TYPE_TRAIT +#undef RTT_JOIN2 +#undef RTT_JOIN + } + + // If we find that this is in fact the name of a type trait, + // update the token kind in place and parse again to treat it as + // the appropriate kind of type trait. + llvm::SmallDenseMap<IdentifierInfo *, tok::TokenKind>::iterator Known + = RevertableTypeTraits.find(II); + if (Known != RevertableTypeTraits.end()) { + Tok.setKind(Known->second); + return ParseCastExpression(isUnaryExpression, isAddressOfOperand, + NotCastExpr, isTypeCast); + } + } + if (Next.is(tok::coloncolon) || (!ColonIsSacred && Next.is(tok::colon)) || Next.is(tok::less) || @@ -758,7 +807,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, // '.'. IdentifierInfo &II = *Tok.getIdentifierInfo(); SourceLocation ILoc = ConsumeToken(); - + // Support 'Class.property' and 'super.property' notation. if (getLangOpts().ObjC1 && Tok.is(tok::period) && (Actions.getTypeName(II, ILoc, getCurScope()) || |