================ @@ -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()) { ---------------- erichkeane wrote:
Do a `if (D->isInvalidDecl()) return;` here. Else this can result in some weirdness at times I think? https://github.com/llvm/llvm-project/pull/141238 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits