diff options
-rw-r--r-- | include/clang/Parse/Parser.h | 4 | ||||
-rw-r--r-- | lib/Lex/PPMacroExpansion.cpp | 14 | ||||
-rw-r--r-- | lib/Parse/ParseExpr.cpp | 51 | ||||
-rw-r--r-- | test/SemaCXX/libstdcxx_is_pod_hack.cpp | 12 |
4 files changed, 66 insertions, 15 deletions
diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index a348c6281d..dfe9c28a40 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -164,6 +164,10 @@ class Parser : public CodeCompletionHandler { mutable IdentifierInfo *Ident_final; mutable IdentifierInfo *Ident_override; + // C++ type trait keywords that have can be reverted to identifiers and + // still used as type traits. + llvm::SmallDenseMap<IdentifierInfo *, tok::TokenKind> RevertableTypeTraits; + OwningPtr<PragmaHandler> AlignHandler; OwningPtr<PragmaHandler> GCCVisibilityHandler; OwningPtr<PragmaHandler> OptionsHandler; 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()) || diff --git a/test/SemaCXX/libstdcxx_is_pod_hack.cpp b/test/SemaCXX/libstdcxx_is_pod_hack.cpp index 3ac233627c..1ba3721c8c 100644 --- a/test/SemaCXX/libstdcxx_is_pod_hack.cpp +++ b/test/SemaCXX/libstdcxx_is_pod_hack.cpp @@ -8,6 +8,7 @@ template<typename T> struct __is_pod { + __is_pod() {} }; __is_pod<int> ipi; @@ -28,6 +29,13 @@ struct test_is_signed { bool check_signed = test_is_signed::__is_signed; -#if __has_feature(is_pod) -# error __is_pod won't work now anyway +template<bool B> struct must_be_true {}; +template<> struct must_be_true<false>; + +void foo() { + bool b = __is_pod(int); + must_be_true<__is_pod(int)> mbt; +} +#if !__has_feature(is_pod) +# error __is_pod should still be available. #endif |