- Fixed a crash-on-valid with consteval evaluation of a list-initialized
constructor for a temporary object. This fixes
`Issue 55871 <https://github.com/llvm/llvm-project/issues/55871>`_.
+- Fix `#57008 <https://github.com/llvm/llvm-project/issues/57008>`_ - Builtin
+ C++ language extension type traits instantiated by a template with unexpected
+ number of arguments cause an assertion fault.
Improvements to Clang's diagnostics
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
const char *getTraitSpelling(TypeTrait T) LLVM_READONLY;
const char *getTraitSpelling(ArrayTypeTrait T) LLVM_READONLY;
const char *getTraitSpelling(UnaryExprOrTypeTrait T) LLVM_READONLY;
+
+/// Return the arity of the type trait \p T.
+unsigned getTypeTraitArity(TypeTrait T) LLVM_READONLY;
+
} // namespace clang
#endif
bool isQualifiedMemberAccess(Expr *E);
QualType CheckAddressOfOperand(ExprResult &Operand, SourceLocation OpLoc);
+ bool CheckTypeTraitArity(unsigned Arity, SourceLocation Loc, size_t N);
+
ExprResult CreateUnaryExprOrTypeTraitExpr(TypeSourceInfo *TInfo,
SourceLocation OpLoc,
UnaryExprOrTypeTrait ExprKind,
#include "clang/Basic/TokenKinds.def"
};
+static constexpr const unsigned TypeTraitArities[] = {
+#define TYPE_TRAIT_1(Spelling, Name, Key) 1,
+#include "clang/Basic/TokenKinds.def"
+#define TYPE_TRAIT_2(Spelling, Name, Key) 2,
+#include "clang/Basic/TokenKinds.def"
+#define TYPE_TRAIT_N(Spelling, Name, Key) 0,
+#include "clang/Basic/TokenKinds.def"
+};
+
const char *clang::getTraitName(TypeTrait T) {
assert(T <= TT_Last && "invalid enum value!");
return TypeTraitNames[T];
assert(T <= UETT_Last && "invalid enum value!");
return UnaryExprOrTypeTraitSpellings[T];
}
+
+unsigned clang::getTypeTraitArity(TypeTrait T) {
+ assert(T <= TT_Last && "invalid enum value!");
+ return TypeTraitArities[T];
+}
}
}
-static unsigned TypeTraitArity(tok::TokenKind kind) {
- switch (kind) {
- default: llvm_unreachable("Not a known type trait");
-#define TYPE_TRAIT(N,Spelling,K) case tok::kw_##Spelling: return N;
-#include "clang/Basic/TokenKinds.def"
- }
-}
-
/// Parse the built-in type-trait pseudo-functions that allow
/// implementation of the TR1/C++11 type traits templates.
///
///
ExprResult Parser::ParseTypeTrait() {
tok::TokenKind Kind = Tok.getKind();
- unsigned Arity = TypeTraitArity(Kind);
SourceLocation Loc = ConsumeToken();
SourceLocation EndLoc = Parens.getCloseLocation();
- if (Arity && Args.size() != Arity) {
- Diag(EndLoc, diag::err_type_trait_arity)
- << Arity << 0 << (Arity > 1) << (int)Args.size() << SourceRange(Loc);
- return ExprError();
- }
-
- if (!Arity && Args.empty()) {
- Diag(EndLoc, diag::err_type_trait_arity)
- << 1 << 1 << 1 << (int)Args.size() << SourceRange(Loc);
- return ExprError();
- }
-
return Actions.ActOnTypeTrait(TypeTraitFromTokKind(Kind), Loc, Args, EndLoc);
}
}
}
+bool Sema::CheckTypeTraitArity(unsigned Arity, SourceLocation Loc, size_t N) {
+ if (Arity && N != Arity) {
+ Diag(Loc, diag::err_type_trait_arity)
+ << Arity << 0 << (Arity > 1) << (int)N << SourceRange(Loc);
+ return false;
+ }
+
+ if (!Arity && N == 0) {
+ Diag(Loc, diag::err_type_trait_arity)
+ << 1 << 1 << 1 << (int)N << SourceRange(Loc);
+ return false;
+ }
+ return true;
+}
+
ExprResult Sema::BuildTypeTrait(TypeTrait Kind, SourceLocation KWLoc,
ArrayRef<TypeSourceInfo *> Args,
SourceLocation RParenLoc) {
+ if (!CheckTypeTraitArity(getTypeTraitArity(Kind), KWLoc, Args.size()))
+ return ExprError();
QualType ResultType = Context.getLogicalOperationType();
if (Kind <= UTT_Last && !CheckUnaryTypeTraitTypeCompleteness(
--- /dev/null
+// RUN: %clang_cc1 -fsyntax-only %s -verify
+
+// Shouldn't crash here
+// Reported by https://github.com/llvm/llvm-project/issues/57008
+template<class... Ts> bool b = __is_constructible(Ts...); // expected-error{{type trait requires 1 or more arguments}}
+bool x = b<>; // expected-note{{in instantiation of variable template specialization}}