[BPF] Restrict preserve_access_index attribute to C only
authorYonghong Song <yhs@fb.com>
Thu, 14 Nov 2019 18:34:35 +0000 (10:34 -0800)
committerYonghong Song <yhs@fb.com>
Thu, 14 Nov 2019 22:14:59 +0000 (14:14 -0800)
This patch is a follow-up for commit 4e2ce228ae79
  [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

clang/include/clang/Basic/Attr.td
clang/lib/CodeGen/CGExpr.cpp
clang/test/Sema/bpf-attr-preserve-access-index.cpp [new file with mode: 0644]

index 91140c0..ce7ad2c 100644 (file)
@@ -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,
index e32db8c..384e8f7 100644 (file)
@@ -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;
-
-    return RecT->getDecl()->hasAttr<BPFPreserveAccessIndexAttr>();
+    const auto *PointeeT = PtrT->getPointeeType()
+                             ->getUnqualifiedDesugaredType();
+    if (const auto *RecT = dyn_cast<RecordType>(PointeeT))
+      return RecT->getDecl()->hasAttr<BPFPreserveAccessIndexAttr>();
+    return false;
   }
 
   return false;
diff --git a/clang/test/Sema/bpf-attr-preserve-access-index.cpp b/clang/test/Sema/bpf-attr-preserve-access-index.cpp
new file mode 100644 (file)
index 0000000..4a88ec2
--- /dev/null
@@ -0,0 +1,9 @@
+// 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}}