[cfe-commits] r162937 - in /cfe/trunk: include/clang/Parse/Parser.h lib/Lex/PPMacroExpansion.cpp lib/Parse/ParseExpr.cpp test/SemaCXX/libstdcxx_is_pod_hack.cpp
Douglas Gregor
dgregor at apple.com
Thu Aug 30 13:04:44 PDT 2012
Author: dgregor
Date: Thu Aug 30 15:04:43 2012
New Revision: 162937
URL: http://llvm.org/viewvc/llvm-project?rev=162937&view=rev
Log:
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.
Modified:
cfe/trunk/include/clang/Parse/Parser.h
cfe/trunk/lib/Lex/PPMacroExpansion.cpp
cfe/trunk/lib/Parse/ParseExpr.cpp
cfe/trunk/test/SemaCXX/libstdcxx_is_pod_hack.cpp
Modified: cfe/trunk/include/clang/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=162937&r1=162936&r2=162937&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Thu Aug 30 15:04:43 2012
@@ -164,6 +164,10 @@
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;
Modified: cfe/trunk/lib/Lex/PPMacroExpansion.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/PPMacroExpansion.cpp?rev=162937&r1=162936&r2=162937&view=diff
==============================================================================
--- cfe/trunk/lib/Lex/PPMacroExpansion.cpp (original)
+++ cfe/trunk/lib/Lex/PPMacroExpansion.cpp Thu Aug 30 15:04:43 2012
@@ -719,22 +719,12 @@
// "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)
Modified: cfe/trunk/lib/Parse/ParseExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExpr.cpp?rev=162937&r1=162936&r2=162937&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseExpr.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExpr.cpp Thu Aug 30 15:04:43 2012
@@ -741,6 +741,55 @@
// 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 @@
// '.'.
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()) ||
Modified: cfe/trunk/test/SemaCXX/libstdcxx_is_pod_hack.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/libstdcxx_is_pod_hack.cpp?rev=162937&r1=162936&r2=162937&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/libstdcxx_is_pod_hack.cpp (original)
+++ cfe/trunk/test/SemaCXX/libstdcxx_is_pod_hack.cpp Thu Aug 30 15:04:43 2012
@@ -8,6 +8,7 @@
template<typename T>
struct __is_pod {
+ __is_pod() {}
};
__is_pod<int> ipi;
@@ -28,6 +29,13 @@
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
More information about the cfe-commits
mailing list