Skip to content

Commit

Permalink
[Clang] Improve type traits recognition in __has_builtin (llvm#111516)
Browse files Browse the repository at this point in the history
`__has_builtin` was relying on reversible identifiers and string
matching to recognize builtin-type traits, leading to some newer type
traits not being recognized.

Fixes llvm#111477
  • Loading branch information
cor3ntin authored Oct 8, 2024
1 parent 9f3c559 commit 75611ca
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 21 deletions.
2 changes: 2 additions & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -408,6 +408,8 @@ Bug Fixes to Compiler Builtins

- ``__noop`` can now be used in a constant expression. (#GH102064)

- Fix ``__has_builtin`` incorrectly returning ``false`` for some C++ type traits. (#GH111477)

Bug Fixes to Attribute Support
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Expand Down
5 changes: 4 additions & 1 deletion clang/include/clang/Basic/TokenKinds.def
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,10 @@
#ifndef EXPRESSION_TRAIT
#define EXPRESSION_TRAIT(I,E,K) KEYWORD(I,K)
#endif
#ifndef TRANSFORM_TYPE_TRAIT_DEF
#define TRANSFORM_TYPE_TRAIT_DEF(K, Trait) KEYWORD(__##Trait, KEYCXX)
#endif

#ifndef ALIAS
#define ALIAS(X,Y,Z)
#endif
Expand Down Expand Up @@ -534,7 +538,6 @@ TYPE_TRAIT_1(__has_unique_object_representations,
TYPE_TRAIT_2(__is_layout_compatible, IsLayoutCompatible, KEYCXX)
TYPE_TRAIT_2(__is_pointer_interconvertible_base_of, IsPointerInterconvertibleBaseOf, KEYCXX)

#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) KEYWORD(__##Trait, KEYCXX)
#include "clang/Basic/TransformTypeTraits.def"

// Clang-only C++ Type Traits
Expand Down
52 changes: 33 additions & 19 deletions clang/lib/Lex/PPMacroExpansion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1616,6 +1616,34 @@ asm("_ZNKSt8time_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE3putES3_"
"RSt8ios_basecPK2tmPKcSB_");
#endif

static bool IsBuiltinTrait(Token &Tok) {

#define TYPE_TRAIT_1(Spelling, Name, Key) \
case tok::kw_##Spelling: \
return true;
#define TYPE_TRAIT_2(Spelling, Name, Key) \
case tok::kw_##Spelling: \
return true;
#define TYPE_TRAIT_N(Spelling, Name, Key) \
case tok::kw_##Spelling: \
return true;
#define ARRAY_TYPE_TRAIT(Spelling, Name, Key) \
case tok::kw_##Spelling: \
return true;
#define EXPRESSION_TRAIT(Spelling, Name, Key) \
case tok::kw_##Spelling: \
return true;
#define TRANSFORM_TYPE_TRAIT_DEF(K, Spelling) \
case tok::kw___##Spelling: \
return true;

switch (Tok.getKind()) {
default:
return false;
#include "clang/Basic/TokenKinds.def"
}
}

/// ExpandBuiltinMacro - If an identifier token is read that is to be expanded
/// as a builtin macro, handle it and return the next token as 'Tok'.
void Preprocessor::ExpandBuiltinMacro(Token &Tok) {
Expand Down Expand Up @@ -1814,25 +1842,11 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) {
getTargetInfo().getTargetOpts().FeatureMap);
}
return true;
} else if (II->getTokenID() != tok::identifier ||
II->hasRevertedTokenIDToIdentifier()) {
// Treat all keywords that introduce a custom syntax of the form
//
// '__some_keyword' '(' [...] ')'
//
// as being "builtin functions", even if the syntax isn't a valid
// function call (for example, because the builtin takes a type
// argument).
if (II->getName().starts_with("__builtin_") ||
II->getName().starts_with("__is_") ||
II->getName().starts_with("__has_"))
return true;
return llvm::StringSwitch<bool>(II->getName())
.Case("__array_rank", true)
.Case("__array_extent", true)
#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) .Case("__" #Trait, true)
#include "clang/Basic/TransformTypeTraits.def"
.Default(false);
} else if (IsBuiltinTrait(Tok)) {
return true;
} else if (II->getTokenID() != tok::identifier &&
II->getName().starts_with("__builtin_")) {
return true;
} else {
return llvm::StringSwitch<bool>(II->getName())
// Report builtin templates as being builtins.
Expand Down
6 changes: 5 additions & 1 deletion clang/test/Preprocessor/feature_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,11 @@
!__has_builtin(__underlying_type) || \
!__has_builtin(__is_trivial) || \
!__has_builtin(__is_same_as) || \
!__has_builtin(__has_unique_object_representations)
!__has_builtin(__has_unique_object_representations) || \
!__has_builtin(__is_trivially_equality_comparable) || \
!__has_builtin(__reference_constructs_from_temporary) || \
!__has_builtin(__reference_binds_to_temporary) || \
!__has_builtin(__reference_converts_from_temporary)
#error Clang should have these
#endif

Expand Down

0 comments on commit 75611ca

Please sign in to comment.