================
@@ -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

Reply via email to