[clang] [Clang] Explain why a type trait evaluated to false. (PR #141238)
Erich Keane via cfe-commits
cfe-commits at lists.llvm.org
Fri May 23 09:48:13 PDT 2025
================
@@ -1917,3 +1917,190 @@ ExprResult Sema::BuildExpressionTrait(ExpressionTrait ET, SourceLocation KWLoc,
return new (Context)
ExpressionTraitExpr(KWLoc, ET, Queried, Value, RParen, Context.BoolTy);
}
+
+static std::optional<TypeTrait> StdNameToTypeTrait(StringRef Name) {
+ return llvm::StringSwitch<std::optional<TypeTrait>>(Name)
+ .Case("is_trivially_relocatable",
+ TypeTrait::UTT_IsCppTriviallyRelocatable)
+ .Default(std::nullopt);
+}
+
+using ExtractedTypeTraitInfo =
+ std::optional<std::pair<TypeTrait, llvm::SmallVector<QualType, 1>>>;
+
+// Recognize type traits that are builting type traits, or known standard
+// type traits in <type_traits>. Note that at this point we assume the
+// trait evaluated to false, so we need only to recognize the shape of the
+// outer-most symbol.
+static ExtractedTypeTraitInfo ExtractTypeTraitFromExpression(const Expr *E) {
+ llvm::SmallVector<QualType, 1> Args;
+ std::optional<TypeTrait> Trait;
+
+ // builtins
+ if (const auto *TraitExpr = dyn_cast<TypeTraitExpr>(E)) {
+ Trait = TraitExpr->getTrait();
+ for (const auto *Arg : TraitExpr->getArgs())
+ Args.push_back(Arg->getType());
+ return {{Trait.value(), std::move(Args)}};
+ }
+ const auto *Ref = dyn_cast<DeclRefExpr>(E);
+ if (!Ref)
+ return std::nullopt;
+
+ // std::is_xxx_v<>
+ if (const auto *VD =
+ dyn_cast<VarTemplateSpecializationDecl>(Ref->getDecl())) {
+ if (!VD->isInStdNamespace())
+ return std::nullopt;
+ StringRef Name = VD->getIdentifier()->getName();
+ if (!Name.consume_back("_v"))
+ return std::nullopt;
+ Trait = StdNameToTypeTrait(Name);
+ if (!Trait)
+ return std::nullopt;
+ for (const auto &Arg : VD->getTemplateArgs().asArray())
+ Args.push_back(Arg.getAsType());
+ return {{Trait.value(), std::move(Args)}};
+ }
+
+ // std::is_xxx<>::value
+ if (const auto *VD = dyn_cast<VarDecl>(Ref->getDecl());
+ Ref->hasQualifier() && VD && VD->getIdentifier()->isStr("value")) {
+ const Type *T = Ref->getQualifier()->getAsType();
+ if (!T)
+ return std::nullopt;
+ const TemplateSpecializationType *Ts =
+ T->getAs<TemplateSpecializationType>();
+ if (!Ts)
+ return std::nullopt;
+ const TemplateDecl *D = Ts->getTemplateName().getAsTemplateDecl();
+ if (!D || !D->isInStdNamespace())
+ return std::nullopt;
+ Trait = StdNameToTypeTrait(D->getIdentifier()->getName());
+ if (!Trait)
+ return std::nullopt;
+ for (const auto &Arg : Ts->template_arguments())
+ Args.push_back(Arg.getAsType());
+ return {{Trait.value(), std::move(Args)}};
+ }
+ return std::nullopt;
+}
+
+static void DiagnoseNonTriviallyRelocatableReason(Sema &SemaRef,
+ SourceLocation Loc,
+ const CXXRecordDecl *D) {
+ for (const CXXBaseSpecifier &B : D->bases()) {
+ const auto *BaseDecl = B.getType()->getAsCXXRecordDecl();
+ if (!BaseDecl)
+ continue;
----------------
erichkeane wrote:
.... CAN this happen?
https://github.com/llvm/llvm-project/pull/141238
More information about the cfe-commits
mailing list