================
@@ -956,42 +958,112 @@ static llvm::Value 
*getArrayIndexingBound(CodeGenFunction &CGF,
   return nullptr;
 }
 
-const Expr *
-CodeGenFunction::BuildCountedByFieldExpr(const Expr *Base,
-                                         const ValueDecl *CountedByVD) {
+namespace {
+
+/// \p MemberExprBaseVisitor returns the base \p DeclRefExpr of a field access.
+class MemberExprBaseVisitor
+    : public StmtVisitor<MemberExprBaseVisitor, Expr *> {
+  const RecordDecl *ExpectedRD;
+
+  bool IsExpectedRecordDecl(const Expr *E) const {
+    QualType Ty = E->getType();
+    if (Ty->isPointerType())
+      Ty = Ty->getPointeeType();
+    return ExpectedRD == Ty->getAsRecordDecl();
+  }
+
+public:
+  MemberExprBaseVisitor(const RecordDecl *ExpectedRD)
+      : ExpectedRD(ExpectedRD) { }
+
+  
//===--------------------------------------------------------------------===//
+  //                            Visitor Methods
+  
//===--------------------------------------------------------------------===//
+
+  // Note: if we build C++ support for counted_by, then we'll have to handle
+  // horrors like this:
+  //
+  //     struct S {
+  //       int x, y;
+  //       int blah[] __attribute__((counted_by(x)));
+  //     } s;
+  //
+  //     int foo(int index, int val) {
+  //       int (S::*IHatePMDs)[] = &S::blah;
+  //       (s.*IHatePMDs)[index] = val;
+  //     }
+
+  Expr *Visit(Expr *E) {
+    return StmtVisitor<MemberExprBaseVisitor, Expr *>::Visit(E);
+  }
+
+  Expr *VisitCastExpr(CastExpr *E) {
+    return IsExpectedRecordDecl(E) ? E : Visit(E->getSubExpr());
+  }
+  Expr *VisitCompoundLiteralExpr(CompoundLiteralExpr *E) {
+    return IsExpectedRecordDecl(E) ? E : nullptr;
+  }
+  Expr *VisitDeclRefExpr(DeclRefExpr *E) {
+    return IsExpectedRecordDecl(E) ? E : nullptr;
+  }
+  Expr *VisitMemberExpr(MemberExpr *E) {
+    Expr *Res = Visit(E->getBase());
+    return !Res && IsExpectedRecordDecl(E) ? E : Res;
+  }
+  Expr *VisitParenExpr(ParenExpr *E) {
+    return IsExpectedRecordDecl(E) ? E : Visit(E->getSubExpr());
+  }
+
+  Expr *VisitArraySubscriptExpr(ArraySubscriptExpr *E) {
+    return Visit(E->getBase());
+  }
+  Expr *VisitImplicitCastExpr(CastExpr *E) { return Visit(E->getSubExpr()); }
+  Expr *VisitUnaryOperator(UnaryOperator *E) { return Visit(E->getSubExpr()); }
+};
+
+} // end anonymous namespace
+
+llvm::Value *
+CodeGenFunction::EmitCountedByFieldExpr(const Expr *Base,
+                                        const ValueDecl *CountedByVD) {
+  const DeclContext *DC = CountedByVD->getLexicalDeclContext();
+  const auto *CountedByRD = cast<RecordDecl>(DC);
+
   // Find the outer struct expr (i.e. p in p->a.b.c.d).
-  Expr *CountedByExpr = const_cast<Expr *>(Base)->IgnoreParenImpCasts();
-
-  // Work our way up the expression until we reach the DeclRefExpr.
-  while (!isa<DeclRefExpr>(CountedByExpr))
-    if (const auto *ME = dyn_cast<MemberExpr>(CountedByExpr))
-      CountedByExpr = ME->getBase()->IgnoreParenImpCasts();
-
-  // Add back an implicit cast to create the required pr-value.
-  CountedByExpr = ImplicitCastExpr::Create(
-      getContext(), CountedByExpr->getType(), CK_LValueToRValue, CountedByExpr,
-      nullptr, VK_PRValue, FPOptionsOverride());
-
-  if (const auto *IFD = dyn_cast<IndirectFieldDecl>(CountedByVD)) {
-    // The counted_by field is inside an anonymous struct / union. The
-    // IndirectFieldDecl has the correct order of FieldDecls to build this
-    // easily. (Yay!)
-    for (NamedDecl *ND : IFD->chain()) {
-      auto *VD = cast<ValueDecl>(ND);
-      CountedByExpr =
-          MemberExpr::CreateImplicit(getContext(), CountedByExpr,
-                                     CountedByExpr->getType()->isPointerType(),
-                                     VD, VD->getType(), VK_LValue, 
OK_Ordinary);
-    }
-  } else {
-    CountedByExpr = MemberExpr::CreateImplicit(
-        getContext(), const_cast<Expr *>(CountedByExpr),
-        CountedByExpr->getType()->isPointerType(),
-        const_cast<ValueDecl *>(CountedByVD), CountedByVD->getType(), 
VK_LValue,
-        OK_Ordinary);
+  Expr *CountedByExpr =
+      MemberExprBaseVisitor(CountedByRD).Visit(const_cast<Expr *>(Base));
+  if (!CountedByExpr)
+    return nullptr;
+
+  llvm::Value *Res = nullptr;
+  if (CountedByExpr->getType()->isPointerType())
+    Res = EmitPointerWithAlignment(CountedByExpr).getPointer();
----------------
efriedma-quic wrote:

We generally don't track previously emitted values for an Expr.  I think you'd 
want to change CodeGenFunction::EmitArraySubscriptExpr to have a special 
codepath for emitting array subscripts with a counted_by bound.  (While you're 
computing/emitting indexing for the counted_by field, you can also emit the 
indexing for the array itself at the same time.  So we just skip the code that 
would normally emit the base, and just use the base computed by your code 
instead.)

https://github.com/llvm/llvm-project/pull/73730
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to