Commit dd16b3fe authored by Yonghong Song's avatar Yonghong Song
Browse files

[BPF] Restrict preserve_access_index attribute to C only

This patch is a follow-up for commit 4e2ce228
  [BPF] Add preserve_access_index attribute for record definition
to restrict attribute for C only. A new test case is added
to check for this restriction.

Additional code polishing is done based on
Aaron Ballman's suggestion in https://reviews.llvm.org/D69759/new/.

Differential Revision: https://reviews.llvm.org/D70257
parent 4c39f341
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -1584,6 +1584,7 @@ def BPFPreserveAccessIndex : InheritableAttr,
  let Spellings = [Clang<"preserve_access_index">];
  let Subjects = SubjectList<[Record], ErrorDiag>;
  let Documentation = [BPFPreserveAccessIndexDocs];
  let LangOpts = [COnly];
}

def WebAssemblyImportModule : InheritableAttr,
+12 −31
Original line number Diff line number Diff line
@@ -3408,10 +3408,6 @@ static bool IsPreserveAIArrayBase(CodeGenFunction &CGF, const Expr *ArrayBase) {
  if (!ArrayBase || !CGF.getDebugInfo())
    return false;

  const auto *ImplicitCast = dyn_cast<ImplicitCastExpr>(ArrayBase);
  if (!ImplicitCast)
    return false;

  // Only support base as either a MemberExpr or DeclRefExpr.
  // DeclRefExpr to cover cases like:
  //    struct s { int a; int b[10]; };
@@ -3419,39 +3415,24 @@ static bool IsPreserveAIArrayBase(CodeGenFunction &CGF, const Expr *ArrayBase) {
  //    p[1].a
  // p[1] will generate a DeclRefExpr and p[1].a is a MemberExpr.
  // p->b[5] is a MemberExpr example.
  const Expr *E = ImplicitCast->getSubExpr();
  const auto *MemberCast = dyn_cast<MemberExpr>(E);
  if (MemberCast)
    return MemberCast->getMemberDecl()->hasAttr<BPFPreserveAccessIndexAttr>();

  const auto *DeclRefCast = dyn_cast<DeclRefExpr>(E);
  if (DeclRefCast) {
    const VarDecl *VarDef = dyn_cast<VarDecl>(DeclRefCast->getDecl());
  const Expr *E = ArrayBase->IgnoreImpCasts();
  if (const auto *ME = dyn_cast<MemberExpr>(E))
    return ME->getMemberDecl()->hasAttr<BPFPreserveAccessIndexAttr>();

  if (const auto *DRE = dyn_cast<DeclRefExpr>(E)) {
    const auto *VarDef = dyn_cast<VarDecl>(DRE->getDecl());
    if (!VarDef)
      return false;

    const auto *PtrT = dyn_cast<PointerType>(VarDef->getType().getTypePtr());
    const auto *PtrT = VarDef->getType()->getAs<PointerType>();
    if (!PtrT)
      return false;
    const auto *PointeeT = PtrT->getPointeeType().getTypePtr();

    // Peel off typedef's
    const auto *TypedefT = dyn_cast<TypedefType>(PointeeT);
    while (TypedefT) {
      PointeeT = TypedefT->desugar().getTypePtr();
      TypedefT = dyn_cast<TypedefType>(PointeeT);
    }

    // Not a typedef any more, it should be an elaborated type.
    const auto ElaborateT = dyn_cast<ElaboratedType>(PointeeT);
    if (!ElaborateT)
      return false;

    const auto *RecT = dyn_cast<RecordType>(ElaborateT->desugar().getTypePtr());
    if (!RecT)
      return false;

    const auto *PointeeT = PtrT->getPointeeType()
                             ->getUnqualifiedDesugaredType();
    if (const auto *RecT = dyn_cast<RecordType>(PointeeT))
      return RecT->getDecl()->hasAttr<BPFPreserveAccessIndexAttr>();
    return false;
  }

  return false;
+9 −0
Original line number Diff line number Diff line
// RUN: %clang_cc1 -x c++ -triple bpf-pc-linux-gnu -dwarf-version=4 -fsyntax-only -verify %s

#define __reloc__ __attribute__((preserve_access_index))

struct t1 {
  int a;
  int b[4];
  int c:1;
} __reloc__; // expected-warning {{'preserve_access_index' attribute ignored}}