summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNico Weber <nicolasweber@gmx.de>2014-09-23 04:09:56 +0000
committerNico Weber <nicolasweber@gmx.de>2014-09-23 04:09:56 +0000
commit7c3c5bec07b9523a704bc7ba4bbb4e7995511b1c (patch)
treeb3862175c27c98e98e899b9369c7d72f4fc62678
parentf6a42580207fd25b6642eaa3aa2a638c2d3f21f2 (diff)
downloadbcm5719-llvm-7c3c5bec07b9523a704bc7ba4bbb4e7995511b1c.tar.gz
bcm5719-llvm-7c3c5bec07b9523a704bc7ba4bbb4e7995511b1c.zip
Revert r197496, as it broke REVERTIBLE_TYPE_TRAITs from PCH files.
Also add a test to make sure that this doesn't break again. Fixes PR21036. llvm-svn: 218292
-rw-r--r--clang/include/clang/Parse/Parser.h13
-rw-r--r--clang/lib/Parse/ParseDeclCXX.cpp36
-rw-r--r--clang/lib/Parse/ParseExpr.cpp47
-rw-r--r--clang/lib/Parse/Parser.cpp24
-rw-r--r--clang/test/PCH/cxx-traits.cpp12
-rw-r--r--clang/test/PCH/cxx-traits.h4
6 files changed, 85 insertions, 51 deletions
diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h
index 7fe2c7a9192..5aaa6cab91b 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -135,10 +135,9 @@ class Parser : public CodeCompletionHandler {
mutable IdentifierInfo *Ident_final;
mutable IdentifierInfo *Ident_override;
- // Some token kinds such as C++ type traits can be reverted to identifiers and
- // still get used as keywords depending on context.
- llvm::SmallDenseMap<const IdentifierInfo *, tok::TokenKind>
- ContextualKeywords;
+ // C++ type trait keywords that can be reverted to identifiers and still be
+ // used as type traits.
+ llvm::SmallDenseMap<IdentifierInfo *, tok::TokenKind> RevertibleTypeTraits;
std::unique_ptr<PragmaHandler> AlignHandler;
std::unique_ptr<PragmaHandler> GCCVisibilityHandler;
@@ -634,12 +633,6 @@ private:
/// otherwise emits a diagnostic and returns true.
bool TryKeywordIdentFallback(bool DisableKeyword);
- /// TryIdentKeywordUpgrade - Convert the current identifier token back to
- /// its original kind and return true if it was disabled by
- /// TryKeywordIdentFallback(), otherwise return false. Use this to
- /// contextually enable keywords.
- bool TryIdentKeywordUpgrade();
-
/// \brief Get the TemplateIdAnnotation from the token.
TemplateIdAnnotation *takeTemplateIdAnnotation(const Token &tok);
diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp
index b252ed5865c..8ea53966946 100644
--- a/clang/lib/Parse/ParseDeclCXX.cpp
+++ b/clang/lib/Parse/ParseDeclCXX.cpp
@@ -1226,17 +1226,31 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
// C++11 attributes
SourceLocation AttrFixitLoc = Tok.getLocation();
- // GNU libstdc++ and libc++ use certain intrinsic names as the
- // name of struct templates, but some are keywords in GCC >= 4.3
- // MSVC and Clang. For compatibility, convert the token to an identifier
- // and issue a warning diagnostic.
- if (TagType == DeclSpec::TST_struct && !Tok.is(tok::identifier) &&
- !Tok.isAnnotation()) {
- const IdentifierInfo *II = Tok.getIdentifierInfo();
- // We rarely end up here so the following check is efficient.
- if (II && II->getName().startswith("__is_"))
- TryKeywordIdentFallback(true);
- }
+ if (TagType == DeclSpec::TST_struct &&
+ !Tok.is(tok::identifier) &&
+ Tok.getIdentifierInfo() &&
+ (Tok.is(tok::kw___is_arithmetic) ||
+ Tok.is(tok::kw___is_convertible) ||
+ Tok.is(tok::kw___is_empty) ||
+ Tok.is(tok::kw___is_floating_point) ||
+ Tok.is(tok::kw___is_function) ||
+ Tok.is(tok::kw___is_fundamental) ||
+ Tok.is(tok::kw___is_integral) ||
+ Tok.is(tok::kw___is_member_function_pointer) ||
+ Tok.is(tok::kw___is_member_pointer) ||
+ Tok.is(tok::kw___is_pod) ||
+ Tok.is(tok::kw___is_pointer) ||
+ Tok.is(tok::kw___is_same) ||
+ Tok.is(tok::kw___is_scalar) ||
+ Tok.is(tok::kw___is_signed) ||
+ Tok.is(tok::kw___is_unsigned) ||
+ Tok.is(tok::kw___is_void)))
+ // GNU libstdc++ 4.2 and libc++ use certain intrinsic names as the
+ // name of struct templates, but some are keywords in GCC >= 4.3
+ // and Clang. Therefore, when we see the token sequence "struct
+ // X", make X into a normal identifier rather than a keyword, to
+ // allow libstdc++ 4.2 and libc++ to work properly.
+ TryKeywordIdentFallback(true);
// Parse the (optional) nested-name-specifier.
CXXScopeSpec &SS = DS.getTypeSpecScope();
diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp
index 0e4dfb91ad5..2b0daad60f7 100644
--- a/clang/lib/Parse/ParseExpr.cpp
+++ b/clang/lib/Parse/ParseExpr.cpp
@@ -708,11 +708,48 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
// 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() &&
- TryIdentKeywordUpgrade())
- return ParseCastExpression(isUnaryExpression, isAddressOfOperand,
- NotCastExpr, isTypeCast);
+ if (Next.is(tok::l_paren) &&
+ Tok.is(tok::identifier) &&
+ Tok.getIdentifierInfo()->hasRevertedTokenIDToIdentifier()) {
+ IdentifierInfo *II = Tok.getIdentifierInfo();
+ // Build up the mapping of revertible type traits, for future use.
+ if (RevertibleTypeTraits.empty()) {
+#define RTT_JOIN(X,Y) X##Y
+#define REVERTIBLE_TYPE_TRAIT(Name) \
+ RevertibleTypeTraits[PP.getIdentifierInfo(#Name)] \
+ = RTT_JOIN(tok::kw_,Name)
+
+ REVERTIBLE_TYPE_TRAIT(__is_arithmetic);
+ REVERTIBLE_TYPE_TRAIT(__is_convertible);
+ REVERTIBLE_TYPE_TRAIT(__is_empty);
+ REVERTIBLE_TYPE_TRAIT(__is_floating_point);
+ REVERTIBLE_TYPE_TRAIT(__is_function);
+ REVERTIBLE_TYPE_TRAIT(__is_fundamental);
+ REVERTIBLE_TYPE_TRAIT(__is_integral);
+ REVERTIBLE_TYPE_TRAIT(__is_member_function_pointer);
+ REVERTIBLE_TYPE_TRAIT(__is_member_pointer);
+ REVERTIBLE_TYPE_TRAIT(__is_pod);
+ REVERTIBLE_TYPE_TRAIT(__is_pointer);
+ REVERTIBLE_TYPE_TRAIT(__is_same);
+ REVERTIBLE_TYPE_TRAIT(__is_scalar);
+ REVERTIBLE_TYPE_TRAIT(__is_signed);
+ REVERTIBLE_TYPE_TRAIT(__is_unsigned);
+ REVERTIBLE_TYPE_TRAIT(__is_void);
+#undef REVERTIBLE_TYPE_TRAIT
+#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
+ = RevertibleTypeTraits.find(II);
+ if (Known != RevertibleTypeTraits.end()) {
+ Tok.setKind(Known->second);
+ return ParseCastExpression(isUnaryExpression, isAddressOfOperand,
+ NotCastExpr, isTypeCast);
+ }
+ }
if (Next.is(tok::coloncolon) ||
(!ColonIsSacred && Next.is(tok::colon)) ||
diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp
index 808e4266aee..6dcbaf6bb29 100644
--- a/clang/lib/Parse/Parser.cpp
+++ b/clang/lib/Parse/Parser.cpp
@@ -1431,34 +1431,16 @@ Parser::TryAnnotateName(bool IsAddressOfOperand,
}
bool Parser::TryKeywordIdentFallback(bool DisableKeyword) {
- assert(!Tok.is(tok::identifier) && !Tok.isAnnotation());
+ assert(Tok.isNot(tok::identifier));
Diag(Tok, diag::ext_keyword_as_ident)
<< PP.getSpelling(Tok)
<< DisableKeyword;
- if (DisableKeyword) {
- IdentifierInfo *II = Tok.getIdentifierInfo();
- ContextualKeywords[II] = Tok.getKind();
- II->RevertTokenIDToIdentifier();
- }
+ if (DisableKeyword)
+ Tok.getIdentifierInfo()->RevertTokenIDToIdentifier();
Tok.setKind(tok::identifier);
return true;
}
-bool Parser::TryIdentKeywordUpgrade() {
- assert(Tok.is(tok::identifier));
- const IdentifierInfo *II = Tok.getIdentifierInfo();
- assert(II->hasRevertedTokenIDToIdentifier());
- // 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<const IdentifierInfo *, tok::TokenKind>::iterator Known =
- ContextualKeywords.find(II);
- if (Known == ContextualKeywords.end())
- return false;
- Tok.setKind(Known->second);
- return true;
-}
-
/// TryAnnotateTypeOrScopeToken - If the current token position is on a
/// typename (possibly qualified in C++) or a C++ scope specifier not followed
/// by a typename, TryAnnotateTypeOrScopeToken will replace one or more tokens
diff --git a/clang/test/PCH/cxx-traits.cpp b/clang/test/PCH/cxx-traits.cpp
index ffdfccc6f47..42656a3ad5f 100644
--- a/clang/test/PCH/cxx-traits.cpp
+++ b/clang/test/PCH/cxx-traits.cpp
@@ -8,8 +8,12 @@
// expected-no-diagnostics
#endif
-bool _Is_pod_comparator = __is_pod<int>::__value;
-bool _Is_empty_check = __is_empty<int>::__value;
+bool _Is_pod_comparator = n::__is_pod<int>::__value;
+bool _Is_empty_check = n::__is_empty<int>::__value;
-bool default_construct_int = is_trivially_constructible<int>::value;
-bool copy_construct_int = is_trivially_constructible<int, const int&>::value;
+bool default_construct_int = n::is_trivially_constructible<int>::value;
+bool copy_construct_int = n::is_trivially_constructible<int, const int&>::value;
+
+// The built-ins should still work too:
+bool _is_pod_result = __is_pod(int);
+bool _is_empty_result = __is_empty(int);
diff --git a/clang/test/PCH/cxx-traits.h b/clang/test/PCH/cxx-traits.h
index e6f2feb1d11..59ba513ef1d 100644
--- a/clang/test/PCH/cxx-traits.h
+++ b/clang/test/PCH/cxx-traits.h
@@ -1,5 +1,7 @@
// Header for PCH test cxx-traits.cpp
+namespace n {
+
template<typename _Tp>
struct __is_pod { // expected-warning {{keyword '__is_pod' will be made available as an identifier for the remainder of the translation unit}}
enum { __value };
@@ -14,3 +16,5 @@ template<typename T, typename ...Args>
struct is_trivially_constructible {
static const bool value = __is_trivially_constructible(T, Args...);
};
+
+}
OpenPOWER on IntegriCloud