<div dir="ltr">Hi Alp,<div><br></div><div>this broke loading REVERTIBLE_TYPE_TRAITs from PCH files, PR21036. It wasn't obvious to me how to fix this (ASTIdentifierLookupTrait::ReadData in ASTReader.cpp would have to write to ContextualKeywords when HasRevertedTokenIDToIdentifier is set from what I understand, but it's not clear how to get to the Parser from there), so I reverted this in r218292 for now.</div><div><br></div><div>Nico</div></div><div class="gmail_extra"><br><div class="gmail_quote">On Tue, Dec 17, 2013 at 6:12 AM, Alp Toker <span dir="ltr"><<a href="mailto:alp@nuanti.com" target="_blank">alp@nuanti.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: alp<br>
Date: Tue Dec 17 08:12:30 2013<br>
New Revision: 197496<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=197496&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=197496&view=rev</a><br>
Log:<br>
Simplify RevertibleTypeTraits as a form of contextual keyword<br>
<br>
Now that we emit diagnostics for keyword-as-identifier hacks (-Wkeyword-compat)<br>
we can go ahead and simplify some of the old revertible keyword support.<br>
<br>
This commit adds a TryIdentKeywordUpgrade() function to mirror the recently<br>
added TryKeywordIdentFallback() and uses it to replace the hard-coded list of<br>
REVERTIBLE_TYPE_TRAITs.<br>
<br>
Modified:<br>
    cfe/trunk/include/clang/Parse/Parser.h<br>
    cfe/trunk/lib/Parse/ParseDeclCXX.cpp<br>
    cfe/trunk/lib/Parse/ParseExpr.cpp<br>
    cfe/trunk/lib/Parse/Parser.cpp<br>
<br>
Modified: cfe/trunk/include/clang/Parse/Parser.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=197496&r1=197495&r2=197496&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=197496&r1=197495&r2=197496&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/include/clang/Parse/Parser.h (original)<br>
+++ cfe/trunk/include/clang/Parse/Parser.h Tue Dec 17 08:12:30 2013<br>
@@ -136,9 +136,10 @@ class Parser : public CodeCompletionHand<br>
   mutable IdentifierInfo *Ident_final;<br>
   mutable IdentifierInfo *Ident_override;<br>
<br>
-  // C++ type trait keywords that can be reverted to identifiers and still be<br>
-  // used as type traits.<br>
-  llvm::SmallDenseMap<IdentifierInfo *, tok::TokenKind> RevertibleTypeTraits;<br>
+  // Some token kinds such as C++ type traits can be reverted to identifiers and<br>
+  // still get used as keywords depending on context.<br>
+  llvm::SmallDenseMap<const IdentifierInfo *, tok::TokenKind><br>
+  ContextualKeywords;<br>
<br>
   OwningPtr<PragmaHandler> AlignHandler;<br>
   OwningPtr<PragmaHandler> GCCVisibilityHandler;<br>
@@ -574,6 +575,12 @@ private:<br>
   /// otherwise emits a diagnostic and returns true.<br>
   bool TryKeywordIdentFallback(bool DisableKeyword);<br>
<br>
+  /// TryIdentKeywordUpgrade - Convert the current identifier token back to<br>
+  /// its original kind and return true if it was disabled by<br>
+  /// TryKeywordIdentFallback(), otherwise return false. Use this to<br>
+  /// contextually enable keywords.<br>
+  bool TryIdentKeywordUpgrade();<br>
+<br>
   /// \brief Get the TemplateIdAnnotation from the token.<br>
   TemplateIdAnnotation *takeTemplateIdAnnotation(const Token &tok);<br>
<br>
<br>
Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=197496&r1=197495&r2=197496&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=197496&r1=197495&r2=197496&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original)<br>
+++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Tue Dec 17 08:12:30 2013<br>
@@ -1180,31 +1180,17 @@ void Parser::ParseClassSpecifier(tok::To<br>
   // C++11 attributes<br>
   SourceLocation AttrFixitLoc = Tok.getLocation();<br>
<br>
-  if (TagType == DeclSpec::TST_struct &&<br>
-      !Tok.is(tok::identifier) &&<br>
-      Tok.getIdentifierInfo() &&<br>
-      (Tok.is(tok::kw___is_arithmetic) ||<br>
-       Tok.is(tok::kw___is_convertible) ||<br>
-       Tok.is(tok::kw___is_empty) ||<br>
-       Tok.is(tok::kw___is_floating_point) ||<br>
-       Tok.is(tok::kw___is_function) ||<br>
-       Tok.is(tok::kw___is_fundamental) ||<br>
-       Tok.is(tok::kw___is_integral) ||<br>
-       Tok.is(tok::kw___is_member_function_pointer) ||<br>
-       Tok.is(tok::kw___is_member_pointer) ||<br>
-       Tok.is(tok::kw___is_pod) ||<br>
-       Tok.is(tok::kw___is_pointer) ||<br>
-       Tok.is(tok::kw___is_same) ||<br>
-       Tok.is(tok::kw___is_scalar) ||<br>
-       Tok.is(tok::kw___is_signed) ||<br>
-       Tok.is(tok::kw___is_unsigned) ||<br>
-       Tok.is(tok::kw___is_void)))<br>
-    // GNU libstdc++ 4.2 and libc++ use certain intrinsic names as the<br>
-    // name of struct templates, but some are keywords in GCC >= 4.3<br>
-    // and Clang. Therefore, when we see the token sequence "struct<br>
-    // X", make X into a normal identifier rather than a keyword, to<br>
-    // allow libstdc++ 4.2 and libc++ to work properly.<br>
-    TryKeywordIdentFallback(true);<br>
+  // GNU libstdc++ and libc++ use certain intrinsic names as the<br>
+  // name of struct templates, but some are keywords in GCC >= 4.3<br>
+  // MSVC and Clang. For compatibility, convert the token to an identifier<br>
+  // and issue a warning diagnostic.<br>
+  if (TagType == DeclSpec::TST_struct && !Tok.is(tok::identifier) &&<br>
+      !Tok.isAnnotation()) {<br>
+    const IdentifierInfo *II = Tok.getIdentifierInfo();<br>
+    // We rarely end up here so the following check is efficient.<br>
+    if (II && II->getName().startswith("__is_"))<br>
+      TryKeywordIdentFallback(true);<br>
+  }<br>
<br>
   // Parse the (optional) nested-name-specifier.<br>
   CXXScopeSpec &SS = DS.getTypeSpecScope();<br>
<br>
Modified: cfe/trunk/lib/Parse/ParseExpr.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExpr.cpp?rev=197496&r1=197495&r2=197496&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExpr.cpp?rev=197496&r1=197495&r2=197496&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Parse/ParseExpr.cpp (original)<br>
+++ cfe/trunk/lib/Parse/ParseExpr.cpp Tue Dec 17 08:12:30 2013<br>
@@ -715,48 +715,11 @@ ExprResult Parser::ParseCastExpression(b<br>
       // If this identifier was reverted from a token ID, and the next token<br>
       // is a parenthesis, this is likely to be a use of a type trait. Check<br>
       // those tokens.<br>
-      if (Next.is(tok::l_paren) &&<br>
-          Tok.is(tok::identifier) &&<br>
-          Tok.getIdentifierInfo()->hasRevertedTokenIDToIdentifier()) {<br>
-        IdentifierInfo *II = Tok.getIdentifierInfo();<br>
-        // Build up the mapping of revertible type traits, for future use.<br>
-        if (RevertibleTypeTraits.empty()) {<br>
-#define RTT_JOIN(X,Y) X##Y<br>
-#define REVERTIBLE_TYPE_TRAIT(Name)                         \<br>
-          RevertibleTypeTraits[PP.getIdentifierInfo(#Name)] \<br>
-            = RTT_JOIN(tok::kw_,Name)<br>
-<br>
-          REVERTIBLE_TYPE_TRAIT(__is_arithmetic);<br>
-          REVERTIBLE_TYPE_TRAIT(__is_convertible);<br>
-          REVERTIBLE_TYPE_TRAIT(__is_empty);<br>
-          REVERTIBLE_TYPE_TRAIT(__is_floating_point);<br>
-          REVERTIBLE_TYPE_TRAIT(__is_function);<br>
-          REVERTIBLE_TYPE_TRAIT(__is_fundamental);<br>
-          REVERTIBLE_TYPE_TRAIT(__is_integral);<br>
-          REVERTIBLE_TYPE_TRAIT(__is_member_function_pointer);<br>
-          REVERTIBLE_TYPE_TRAIT(__is_member_pointer);<br>
-          REVERTIBLE_TYPE_TRAIT(__is_pod);<br>
-          REVERTIBLE_TYPE_TRAIT(__is_pointer);<br>
-          REVERTIBLE_TYPE_TRAIT(__is_same);<br>
-          REVERTIBLE_TYPE_TRAIT(__is_scalar);<br>
-          REVERTIBLE_TYPE_TRAIT(__is_signed);<br>
-          REVERTIBLE_TYPE_TRAIT(__is_unsigned);<br>
-          REVERTIBLE_TYPE_TRAIT(__is_void);<br>
-#undef REVERTIBLE_TYPE_TRAIT<br>
-#undef RTT_JOIN<br>
-        }<br>
-<br>
-        // If we find that this is in fact the name of a type trait,<br>
-        // update the token kind in place and parse again to treat it as<br>
-        // the appropriate kind of type trait.<br>
-        llvm::SmallDenseMap<IdentifierInfo *, tok::TokenKind>::iterator Known<br>
-          = RevertibleTypeTraits.find(II);<br>
-        if (Known != RevertibleTypeTraits.end()) {<br>
-          Tok.setKind(Known->second);<br>
-          return ParseCastExpression(isUnaryExpression, isAddressOfOperand,<br>
-                                     NotCastExpr, isTypeCast);<br>
-        }<br>
-      }<br>
+      if (Next.is(tok::l_paren) && Tok.is(tok::identifier) &&<br>
+          Tok.getIdentifierInfo()->hasRevertedTokenIDToIdentifier() &&<br>
+          TryIdentKeywordUpgrade())<br>
+        return ParseCastExpression(isUnaryExpression, isAddressOfOperand,<br>
+                                   NotCastExpr, isTypeCast);<br>
<br>
       if (Next.is(tok::coloncolon) ||<br>
           (!ColonIsSacred && Next.is(tok::colon)) ||<br>
<br>
Modified: cfe/trunk/lib/Parse/Parser.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/Parser.cpp?rev=197496&r1=197495&r2=197496&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/Parser.cpp?rev=197496&r1=197495&r2=197496&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Parse/Parser.cpp (original)<br>
+++ cfe/trunk/lib/Parse/Parser.cpp Tue Dec 17 08:12:30 2013<br>
@@ -1517,16 +1517,34 @@ Parser::TryAnnotateName(bool IsAddressOf<br>
 }<br>
<br>
 bool Parser::TryKeywordIdentFallback(bool DisableKeyword) {<br>
-  assert(Tok.isNot(tok::identifier));<br>
+  assert(!Tok.is(tok::identifier) && !Tok.isAnnotation());<br>
   Diag(Tok, diag::ext_keyword_as_ident)<br>
     << PP.getSpelling(Tok)<br>
     << DisableKeyword;<br>
-  if (DisableKeyword)<br>
-    Tok.getIdentifierInfo()->RevertTokenIDToIdentifier();<br>
+  if (DisableKeyword) {<br>
+    IdentifierInfo *II = Tok.getIdentifierInfo();<br>
+    ContextualKeywords[II] = Tok.getKind();<br>
+    II->RevertTokenIDToIdentifier();<br>
+  }<br>
   Tok.setKind(tok::identifier);<br>
   return true;<br>
 }<br>
<br>
+bool Parser::TryIdentKeywordUpgrade() {<br>
+  assert(Tok.is(tok::identifier));<br>
+  const IdentifierInfo *II = Tok.getIdentifierInfo();<br>
+  assert(II->hasRevertedTokenIDToIdentifier());<br>
+  // If we find that this is in fact the name of a type trait,<br>
+  // update the token kind in place and parse again to treat it as<br>
+  // the appropriate kind of type trait.<br>
+  llvm::SmallDenseMap<const IdentifierInfo *, tok::TokenKind>::iterator Known =<br>
+      ContextualKeywords.find(II);<br>
+  if (Known == ContextualKeywords.end())<br>
+    return false;<br>
+  Tok.setKind(Known->second);<br>
+  return true;<br>
+}<br>
+<br>
 /// TryAnnotateTypeOrScopeToken - If the current token position is on a<br>
 /// typename (possibly qualified in C++) or a C++ scope specifier not followed<br>
 /// by a typename, TryAnnotateTypeOrScopeToken will replace one or more tokens<br>
<br>
<br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@cs.uiuc.edu">cfe-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits</a><br>
</blockquote></div><br></div>