[clang] b7ac68d - [clang][ASTImporter] Simplify code of attribute import [NFC].

Balázs Kéri via cfe-commits cfe-commits at lists.llvm.org
Thu Oct 7 03:53:11 PDT 2021


Author: Balázs Kéri
Date: 2021-10-07T13:07:21+02:00
New Revision: b7ac68d01ef9a126ea0eb26b3526a78c9d39533a

URL: https://github.com/llvm/llvm-project/commit/b7ac68d01ef9a126ea0eb26b3526a78c9d39533a
DIFF: https://github.com/llvm/llvm-project/commit/b7ac68d01ef9a126ea0eb26b3526a78c9d39533a.diff

LOG: [clang][ASTImporter] Simplify code of attribute import [NFC].

The code of `ASTImporter::Import(const Attr *)` was repetitive,
it is now simplified. (There is still room for improvement but
probably only after big changes.)

Reviewed By: martong, steakhal

Differential Revision: https://reviews.llvm.org/D110810

Added: 
    

Modified: 
    clang/lib/AST/ASTImporter.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index df19f608a60ce..f0fcdd66560e5 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -8513,7 +8513,8 @@ template <typename T> struct AttrArgArrayImporter {
 };
 
 class AttrImporter {
-  Error Err = Error::success();
+  Error Err{Error::success()};
+  Attr *ToAttr = nullptr;
   ASTImporter &Importer;
   ASTNodeImporter NImporter;
 
@@ -8522,15 +8523,14 @@ class AttrImporter {
 
   // Create an "importer" for an attribute parameter.
   // Result of the 'value()' of that object is to be passed to the function
-  // 'createImpoprtedAttr', in the order that is expected by the attribute
-  // class.
+  // 'importAttr', in the order that is expected by the attribute class.
   template <class T> AttrArgImporter<T> importArg(const T &From) {
     return AttrArgImporter<T>(NImporter, Err, From);
   }
 
   // Create an "importer" for an attribute parameter that has array type.
   // Result of the 'value()' of that object is to be passed to the function
-  // 'createImpoprtedAttr', then the size of the array as next argument.
+  // 'importAttr', then the size of the array as next argument.
   template <typename T>
   AttrArgArrayImporter<T> importArrayArg(const llvm::iterator_range<T *> &From,
                                          unsigned ArraySize) {
@@ -8543,10 +8543,13 @@ class AttrImporter {
   // (The 'Create' with 'ASTContext' first and 'AttributeCommonInfo' last is
   // used here.) As much data is copied or imported from the old attribute
   // as possible. The passed arguments should be already imported.
+  // If an import error happens, the internal error is set to it, and any
+  // further import attempt is ignored.
   template <typename T, typename... Arg>
-  Expected<Attr *> createImportedAttr(const T *FromAttr, Arg &&...ImportedArg) {
+  void importAttr(const T *FromAttr, Arg &&...ImportedArg) {
     static_assert(std::is_base_of<Attr, T>::value,
                   "T should be subclass of Attr.");
+    assert(!ToAttr && "Use one AttrImporter to import one Attribute object.");
 
     const IdentifierInfo *ToAttrName = Importer.Import(FromAttr->getAttrName());
     const IdentifierInfo *ToScopeName =
@@ -8557,262 +8560,177 @@ class AttrImporter {
         NImporter.importChecked(Err, FromAttr->getScopeLoc());
 
     if (Err)
-      return std::move(Err);
+      return;
 
     AttributeCommonInfo ToI(ToAttrName, ToScopeName, ToAttrRange, ToScopeLoc,
                             FromAttr->getParsedKind(), FromAttr->getSyntax(),
                             FromAttr->getAttributeSpellingListIndex());
     // The "SemanticSpelling" is not needed to be passed to the constructor.
     // That value is recalculated from the SpellingListIndex if needed.
-    T *ToAttr = T::Create(Importer.getToContext(),
-                          std::forward<Arg>(ImportedArg)..., ToI);
+    ToAttr = T::Create(Importer.getToContext(),
+                       std::forward<Arg>(ImportedArg)..., ToI);
 
     ToAttr->setImplicit(FromAttr->isImplicit());
     ToAttr->setPackExpansion(FromAttr->isPackExpansion());
     if (auto *ToInheritableAttr = dyn_cast<InheritableAttr>(ToAttr))
       ToInheritableAttr->setInherited(FromAttr->isInherited());
+  }
+
+  // Create a clone of the 'FromAttr' and import its source range only.
+  // This causes objects with invalid references to be created if the 'FromAttr'
+  // contains other data that should be imported.
+  void cloneAttr(const Attr *FromAttr) {
+    assert(!ToAttr && "Use one AttrImporter to import one Attribute object.");
 
+    SourceRange ToRange = NImporter.importChecked(Err, FromAttr->getRange());
+    if (Err)
+      return;
+
+    ToAttr = FromAttr->clone(Importer.getToContext());
+    ToAttr->setRange(ToRange);
+  }
+
+  // Get the result of the previous import attempt (can be used only once).
+  llvm::Expected<Attr *> getResult() && {
+    if (Err)
+      return std::move(Err);
+    assert(ToAttr && "Attribute should be created.");
     return ToAttr;
   }
 };
 
 Expected<Attr *> ASTImporter::Import(const Attr *FromAttr) {
-  Attr *ToAttr = nullptr;
-  // FIXME: Use AttrImporter as much as possible, try to remove the import
-  // of range from here.
-  SourceRange ToRange;
-  if (Error Err = importInto(ToRange, FromAttr->getRange()))
-    return std::move(Err);
+  AttrImporter AI(*this);
 
   // FIXME: Is there some kind of AttrVisitor to use here?
   switch (FromAttr->getKind()) {
   case attr::Aligned: {
     auto *From = cast<AlignedAttr>(FromAttr);
-    AlignedAttr *To;
-    auto CreateAlign = [&](bool IsAlignmentExpr, void *Alignment) {
-      return AlignedAttr::Create(ToContext, IsAlignmentExpr, Alignment, ToRange,
-                                 From->getSyntax(),
-                                 From->getSemanticSpelling());
-    };
-    if (From->isAlignmentExpr()) {
-      if (auto ToEOrErr = Import(From->getAlignmentExpr()))
-        To = CreateAlign(true, *ToEOrErr);
-      else
-        return ToEOrErr.takeError();
-    } else {
-      if (auto ToTOrErr = Import(From->getAlignmentType()))
-        To = CreateAlign(false, *ToTOrErr);
-      else
-        return ToTOrErr.takeError();
-    }
-    To->setInherited(From->isInherited());
-    To->setPackExpansion(From->isPackExpansion());
-    To->setImplicit(From->isImplicit());
-    ToAttr = To;
+    if (From->isAlignmentExpr())
+      AI.importAttr(From, true, AI.importArg(From->getAlignmentExpr()).value());
+    else
+      AI.importAttr(From, false,
+                    AI.importArg(From->getAlignmentType()).value());
     break;
   }
+
   case attr::Format: {
     const auto *From = cast<FormatAttr>(FromAttr);
-    FormatAttr *To;
-    IdentifierInfo *ToAttrType = Import(From->getType());
-    To = FormatAttr::Create(ToContext, ToAttrType, From->getFormatIdx(),
-                            From->getFirstArg(), ToRange, From->getSyntax());
-    To->setInherited(From->isInherited());
-    ToAttr = To;
+    AI.importAttr(From, Import(From->getType()), From->getFormatIdx(),
+                  From->getFirstArg());
     break;
   }
 
   case attr::AssertCapability: {
     const auto *From = cast<AssertCapabilityAttr>(FromAttr);
-    AttrImporter AI(*this);
-    Expected<Attr *> ToAttrOrErr = AI.createImportedAttr(
-        From, AI.importArrayArg(From->args(), From->args_size()).value(),
-        From->args_size());
-    if (ToAttrOrErr)
-      ToAttr = *ToAttrOrErr;
-    else
-      return ToAttrOrErr.takeError();
+    AI.importAttr(From,
+                  AI.importArrayArg(From->args(), From->args_size()).value(),
+                  From->args_size());
     break;
   }
   case attr::AcquireCapability: {
     const auto *From = cast<AcquireCapabilityAttr>(FromAttr);
-    AttrImporter AI(*this);
-    Expected<Attr *> ToAttrOrErr = AI.createImportedAttr(
-        From, AI.importArrayArg(From->args(), From->args_size()).value(),
-        From->args_size());
-    if (ToAttrOrErr)
-      ToAttr = *ToAttrOrErr;
-    else
-      return ToAttrOrErr.takeError();
+    AI.importAttr(From,
+                  AI.importArrayArg(From->args(), From->args_size()).value(),
+                  From->args_size());
     break;
   }
   case attr::TryAcquireCapability: {
     const auto *From = cast<TryAcquireCapabilityAttr>(FromAttr);
-    AttrImporter AI(*this);
-    Expected<Attr *> ToAttrOrErr = AI.createImportedAttr(
-        From, AI.importArg(From->getSuccessValue()).value(),
-        AI.importArrayArg(From->args(), From->args_size()).value(),
-        From->args_size());
-    if (ToAttrOrErr)
-      ToAttr = *ToAttrOrErr;
-    else
-      return ToAttrOrErr.takeError();
+    AI.importAttr(From, AI.importArg(From->getSuccessValue()).value(),
+                  AI.importArrayArg(From->args(), From->args_size()).value(),
+                  From->args_size());
     break;
   }
   case attr::ReleaseCapability: {
     const auto *From = cast<ReleaseCapabilityAttr>(FromAttr);
-    AttrImporter AI(*this);
-    Expected<Attr *> ToAttrOrErr = AI.createImportedAttr(
-        From, AI.importArrayArg(From->args(), From->args_size()).value(),
-        From->args_size());
-    if (ToAttrOrErr)
-      ToAttr = *ToAttrOrErr;
-    else
-      return ToAttrOrErr.takeError();
+    AI.importAttr(From,
+                  AI.importArrayArg(From->args(), From->args_size()).value(),
+                  From->args_size());
     break;
   }
   case attr::RequiresCapability: {
     const auto *From = cast<RequiresCapabilityAttr>(FromAttr);
-    AttrImporter AI(*this);
-    Expected<Attr *> ToAttrOrErr = AI.createImportedAttr(
-        From, AI.importArrayArg(From->args(), From->args_size()).value(),
-        From->args_size());
-    if (ToAttrOrErr)
-      ToAttr = *ToAttrOrErr;
-    else
-      return ToAttrOrErr.takeError();
+    AI.importAttr(From,
+                  AI.importArrayArg(From->args(), From->args_size()).value(),
+                  From->args_size());
     break;
   }
   case attr::GuardedBy: {
     const auto *From = cast<GuardedByAttr>(FromAttr);
-    AttrImporter AI(*this);
-    Expected<Attr *> ToAttrOrErr =
-        AI.createImportedAttr(From, AI.importArg(From->getArg()).value());
-    if (ToAttrOrErr)
-      ToAttr = *ToAttrOrErr;
-    else
-      return ToAttrOrErr.takeError();
+    AI.importAttr(From, AI.importArg(From->getArg()).value());
     break;
   }
   case attr::PtGuardedBy: {
     const auto *From = cast<PtGuardedByAttr>(FromAttr);
-    AttrImporter AI(*this);
-    Expected<Attr *> ToAttrOrErr =
-        AI.createImportedAttr(From, AI.importArg(From->getArg()).value());
-    if (ToAttrOrErr)
-      ToAttr = *ToAttrOrErr;
-    else
-      return ToAttrOrErr.takeError();
+    AI.importAttr(From, AI.importArg(From->getArg()).value());
     break;
   }
   case attr::AcquiredAfter: {
     const auto *From = cast<AcquiredAfterAttr>(FromAttr);
-    AttrImporter AI(*this);
-    Expected<Attr *> ToAttrOrErr = AI.createImportedAttr(
-        From, AI.importArrayArg(From->args(), From->args_size()).value(),
-        From->args_size());
-    if (ToAttrOrErr)
-      ToAttr = *ToAttrOrErr;
-    else
-      return ToAttrOrErr.takeError();
+    AI.importAttr(From,
+                  AI.importArrayArg(From->args(), From->args_size()).value(),
+                  From->args_size());
     break;
   }
   case attr::AcquiredBefore: {
     const auto *From = cast<AcquiredBeforeAttr>(FromAttr);
-    AttrImporter AI(*this);
-    Expected<Attr *> ToAttrOrErr = AI.createImportedAttr(
-        From, AI.importArrayArg(From->args(), From->args_size()).value(),
-        From->args_size());
-    if (ToAttrOrErr)
-      ToAttr = *ToAttrOrErr;
-    else
-      return ToAttrOrErr.takeError();
+    AI.importAttr(From,
+                  AI.importArrayArg(From->args(), From->args_size()).value(),
+                  From->args_size());
     break;
   }
   case attr::AssertExclusiveLock: {
     const auto *From = cast<AssertExclusiveLockAttr>(FromAttr);
-    AttrImporter AI(*this);
-    Expected<Attr *> ToAttrOrErr = AI.createImportedAttr(
-        From, AI.importArrayArg(From->args(), From->args_size()).value(),
-        From->args_size());
-    if (ToAttrOrErr)
-      ToAttr = *ToAttrOrErr;
-    else
-      return ToAttrOrErr.takeError();
+    AI.importAttr(From,
+                  AI.importArrayArg(From->args(), From->args_size()).value(),
+                  From->args_size());
     break;
   }
   case attr::AssertSharedLock: {
     const auto *From = cast<AssertSharedLockAttr>(FromAttr);
-    AttrImporter AI(*this);
-    Expected<Attr *> ToAttrOrErr = AI.createImportedAttr(
-        From, AI.importArrayArg(From->args(), From->args_size()).value(),
-        From->args_size());
-    if (ToAttrOrErr)
-      ToAttr = *ToAttrOrErr;
-    else
-      return ToAttrOrErr.takeError();
+    AI.importAttr(From,
+                  AI.importArrayArg(From->args(), From->args_size()).value(),
+                  From->args_size());
     break;
   }
   case attr::ExclusiveTrylockFunction: {
     const auto *From = cast<ExclusiveTrylockFunctionAttr>(FromAttr);
-    AttrImporter AI(*this);
-    Expected<Attr *> ToAttrOrErr = AI.createImportedAttr(
-        From, AI.importArg(From->getSuccessValue()).value(),
-        AI.importArrayArg(From->args(), From->args_size()).value(),
-        From->args_size());
-    if (ToAttrOrErr)
-      ToAttr = *ToAttrOrErr;
-    else
-      return ToAttrOrErr.takeError();
+    AI.importAttr(From, AI.importArg(From->getSuccessValue()).value(),
+                  AI.importArrayArg(From->args(), From->args_size()).value(),
+                  From->args_size());
     break;
   }
   case attr::SharedTrylockFunction: {
     const auto *From = cast<SharedTrylockFunctionAttr>(FromAttr);
-    AttrImporter AI(*this);
-    Expected<Attr *> ToAttrOrErr = AI.createImportedAttr(
-        From, AI.importArg(From->getSuccessValue()).value(),
-        AI.importArrayArg(From->args(), From->args_size()).value(),
-        From->args_size());
-    if (ToAttrOrErr)
-      ToAttr = *ToAttrOrErr;
-    else
-      return ToAttrOrErr.takeError();
+    AI.importAttr(From, AI.importArg(From->getSuccessValue()).value(),
+                  AI.importArrayArg(From->args(), From->args_size()).value(),
+                  From->args_size());
     break;
   }
   case attr::LockReturned: {
     const auto *From = cast<LockReturnedAttr>(FromAttr);
-    AttrImporter AI(*this);
-    Expected<Attr *> ToAttrOrErr =
-        AI.createImportedAttr(From, AI.importArg(From->getArg()).value());
-    if (ToAttrOrErr)
-      ToAttr = *ToAttrOrErr;
-    else
-      return ToAttrOrErr.takeError();
+    AI.importAttr(From, AI.importArg(From->getArg()).value());
     break;
   }
   case attr::LocksExcluded: {
     const auto *From = cast<LocksExcludedAttr>(FromAttr);
-    AttrImporter AI(*this);
-    Expected<Attr *> ToAttrOrErr = AI.createImportedAttr(
-        From, AI.importArrayArg(From->args(), From->args_size()).value(),
-        From->args_size());
-    if (ToAttrOrErr)
-      ToAttr = *ToAttrOrErr;
-    else
-      return ToAttrOrErr.takeError();
+    AI.importAttr(From,
+                  AI.importArrayArg(From->args(), From->args_size()).value(),
+                  From->args_size());
     break;
   }
 
-  default:
-    // FIXME: 'clone' copies every member but some of them should be imported.
-    // Handle other Attrs that have parameters that should be imported.
-    ToAttr = FromAttr->clone(ToContext);
-    ToAttr->setRange(ToRange);
+  default: {
+    // The default branch works for attributes that have no arguments to import.
+    // FIXME: Handle every attribute type that has arguments of type to import
+    // (most often Expr* or Decl* or type) in the switch above.
+    AI.cloneAttr(FromAttr);
     break;
   }
-  assert(ToAttr && "Attribute should be created.");
-  
-  return ToAttr;
+  }
+
+  return std::move(AI).getResult();
 }
 
 Decl *ASTImporter::GetAlreadyImportedOrNull(const Decl *FromD) const {


        


More information about the cfe-commits mailing list