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. llvm-svn: 162937
This commit is contained in:
parent
fdf98763ac
commit
8bea83a866
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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()) ||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue