[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