[clang] [Clang] Generate the GEP instead of adding AST nodes (PR #73730)

Nick Desaulniers via cfe-commits cfe-commits at lists.llvm.org
Thu Dec 7 09:00:55 PST 2023


================
@@ -994,31 +1010,55 @@ class MemberExprBaseVisitor
   //     }
 
   Expr *Visit(Expr *E) {
-    return StmtVisitor<MemberExprBaseVisitor, Expr *>::Visit(E);
+    return StmtVisitor<StructAccessBase, Expr *>::Visit(E);
   }
 
-  Expr *VisitCastExpr(CastExpr *E) {
-    return IsExpectedRecordDecl(E) ? E : Visit(E->getSubExpr());
-  }
-  Expr *VisitCompoundLiteralExpr(CompoundLiteralExpr *E) {
-    return IsExpectedRecordDecl(E) ? E : nullptr;
-  }
+  // These are the types we expect to return (in order of most to least
+  // likely):
+  //
+  //   1. DeclRefExpr - This is the expression for the base of the structure.
+  //      It's exactly what we want to build an access to the \p counted_by
+  //      field.
+  //   2. MemberExpr - This is the expression that has the same \p RecordDecl
+  //      as the flexble array member's lexical enclosing \p RecordDecl. This
+  //      allows us to catch things like: "p->p->array"
+  //   3. CompoundLiteralExpr - This is for people who create something
+  //      heretical like (struct foo has a flexible array member):
+  //
+  //        (struct foo){ 1, 2 }.blah[idx];
   Expr *VisitDeclRefExpr(DeclRefExpr *E) {
     return IsExpectedRecordDecl(E) ? E : nullptr;
   }
   Expr *VisitMemberExpr(MemberExpr *E) {
+    if (IsExpectedRecordDecl(E) && E->isArrow())
+      return E;
     Expr *Res = Visit(E->getBase());
     return !Res && IsExpectedRecordDecl(E) ? E : Res;
   }
-  Expr *VisitParenExpr(ParenExpr *E) {
-    return IsExpectedRecordDecl(E) ? E : Visit(E->getSubExpr());
+  Expr *VisitCompoundLiteralExpr(CompoundLiteralExpr *E) {
+    return IsExpectedRecordDecl(E) ? E : nullptr;
   }
 
+  // "Pass This On" --The Knife
   Expr *VisitArraySubscriptExpr(ArraySubscriptExpr *E) {
+    if (IsExpectedRecordDecl(E))
+      return E;
     return Visit(E->getBase());
   }
-  Expr *VisitImplicitCastExpr(CastExpr *E) { return Visit(E->getSubExpr()); }
-  Expr *VisitUnaryOperator(UnaryOperator *E) { return Visit(E->getSubExpr()); }
+  Expr *VisitCastExpr(CastExpr *E) { return Visit(E->getSubExpr()); }
+  Expr *VisitImplicitCastExpr(ImplicitCastExpr *E) {
+    return Visit(E->getSubExpr());
+  }
+  Expr *VisitParenExpr(ParenExpr *E) { return Visit(E->getSubExpr()); }
+  Expr *VisitUnaryAddrOf(UnaryOperator *E) { return Visit(E->getSubExpr()); }
+  Expr *VisitUnaryDeref(UnaryOperator *E) { return Visit(E->getSubExpr()); }
+
+  // Invalid operations. Pointer arithmetic may lead to security violations.
+  Expr *VisitBinaryOperator(BinaryOperator *E) { return nullptr; }
+  Expr *VisitUnaryPostDec(UnaryOperator *E) { return nullptr; }
+  Expr *VisitUnaryPostInc(UnaryOperator *E) { return nullptr; }
+  Expr *VisitUnaryPreDec(UnaryOperator *E) { return nullptr; }
+  Expr *VisitUnaryPreInc(UnaryOperator *E) { return nullptr; }
----------------
nickdesaulniers wrote:

If you don't provide implementations for these, does the default behavior of StatementVisitor do the same thing?

https://github.com/llvm/llvm-project/pull/73730


More information about the cfe-commits mailing list