Michael137 created this revision.
Michael137 added reviewers: martong, balazske.
Herald added a reviewer: a.sidorin.
Herald added a reviewer: shafik.
Herald added a project: All.
Michael137 requested review of this revision.
Herald added subscribers: cfe-commits, wangpc.
Herald added a project: clang.

This patch adds a new `ASTImportError::Message` which is used
to more accurately describe a failure when `ASTImportError::log`
is called. We then set this error message throughout ASTImporter.

The motivation for this is that in upcoming patches LLDB will
check `ASTImportError`s and log them on failures. At the moment
these logs wouldn't be helpful since we wouldn't be able to
differentiate between the different conflicts that occur
during a single import process.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D154709

Files:
  clang/include/clang/AST/ASTImportError.h
  clang/lib/AST/ASTImporter.cpp

Index: clang/lib/AST/ASTImporter.cpp
===================================================================
--- clang/lib/AST/ASTImporter.cpp
+++ clang/lib/AST/ASTImporter.cpp
@@ -14,6 +14,7 @@
 #include "clang/AST/ASTImporter.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/ASTDiagnostic.h"
+#include "clang/AST/ASTImportError.h"
 #include "clang/AST/ASTImporterSharedState.h"
 #include "clang/AST/ASTStructuralEquivalence.h"
 #include "clang/AST/Attr.h"
@@ -34,6 +35,7 @@
 #include "clang/AST/LambdaCapture.h"
 #include "clang/AST/NestedNameSpecifier.h"
 #include "clang/AST/OperationKinds.h"
+#include "clang/AST/PrettyPrinter.h"
 #include "clang/AST/Stmt.h"
 #include "clang/AST/StmtCXX.h"
 #include "clang/AST/StmtObjC.h"
@@ -61,7 +63,9 @@
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/Support/Casting.h"
 #include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/FormatVariadic.h"
 #include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/raw_ostream.h"
 #include <algorithm>
 #include <cassert>
 #include <cstddef>
@@ -84,7 +88,6 @@
   using ExpectedName = llvm::Expected<DeclarationName>;
 
   std::string ASTImportError::toString() const {
-    // FIXME: Improve error texts.
     switch (Error) {
     case NameConflict:
       return "NameConflict";
@@ -97,7 +100,11 @@
     return "Invalid error code.";
   }
 
-  void ASTImportError::log(raw_ostream &OS) const { OS << toString(); }
+  void ASTImportError::log(raw_ostream &OS) const {
+    OS << toString();
+    if (!Message.empty())
+      OS << ": " << Message;
+  }
 
   std::error_code ASTImportError::convertToErrorCode() const {
     llvm_unreachable("Function not implemented.");
@@ -1066,7 +1073,8 @@
 ExpectedType ASTNodeImporter::VisitType(const Type *T) {
   Importer.FromDiag(SourceLocation(), diag::err_unsupported_ast_node)
     << T->getTypeClassName();
-  return make_error<ASTImportError>(ASTImportError::UnsupportedConstruct);
+  return make_error<ASTImportError>(ASTImportError::UnsupportedConstruct,
+                                    T->getTypeClassName());
 }
 
 ExpectedType ASTNodeImporter::VisitAtomicType(const AtomicType *T){
@@ -1715,7 +1723,8 @@
       if (RT && RT->getDecl() == D) {
         Importer.FromDiag(D->getLocation(), diag::err_unsupported_ast_node)
             << D->getDeclKindName();
-        return make_error<ASTImportError>(ASTImportError::UnsupportedConstruct);
+        return make_error<ASTImportError>(ASTImportError::UnsupportedConstruct,
+                                          D->getDeclKindName());
       }
     }
   }
@@ -2238,13 +2247,15 @@
 ExpectedDecl ASTNodeImporter::VisitDecl(Decl *D) {
   Importer.FromDiag(D->getLocation(), diag::err_unsupported_ast_node)
     << D->getDeclKindName();
-  return make_error<ASTImportError>(ASTImportError::UnsupportedConstruct);
+  return make_error<ASTImportError>(ASTImportError::UnsupportedConstruct,
+                                    D->getDeclKindName());
 }
 
 ExpectedDecl ASTNodeImporter::VisitImportDecl(ImportDecl *D) {
   Importer.FromDiag(D->getLocation(), diag::err_unsupported_ast_node)
       << D->getDeclKindName();
-  return make_error<ASTImportError>(ASTImportError::UnsupportedConstruct);
+  return make_error<ASTImportError>(ASTImportError::UnsupportedConstruct,
+                                    D->getDeclKindName());
 }
 
 ExpectedDecl ASTNodeImporter::VisitEmptyDecl(EmptyDecl *D) {
@@ -3893,7 +3904,13 @@
       Importer.ToDiag(FoundField->getLocation(), diag::note_odr_value_here)
         << FoundField->getType();
 
-      return make_error<ASTImportError>(ASTImportError::NameConflict);
+      std::string ErrMessage;
+      llvm::raw_string_ostream OS(ErrMessage);
+      OS << "Field '" << Name.getAsString()
+         << "' declared with incompatible types in different TUs ('"
+         << D->getType() << "' and '" << FoundField->getType() << "')";
+      return make_error<ASTImportError>(ASTImportError::NameConflict,
+                                        std::move(ErrMessage));
     }
   }
 
@@ -3972,7 +3989,13 @@
       Importer.ToDiag(FoundField->getLocation(), diag::note_odr_value_here)
         << FoundField->getType();
 
-      return make_error<ASTImportError>(ASTImportError::NameConflict);
+      std::string ErrMessage;
+      llvm::raw_string_ostream OS(ErrMessage);
+      OS << "IndirectField '" << Name.getAsString()
+         << "' declared with incompatible types in different TUs ('"
+         << D->getType() << "' and '" << FoundField->getType() << "')";
+      return make_error<ASTImportError>(ASTImportError::NameConflict,
+                                        std::move(ErrMessage));
     }
   }
 
@@ -4163,7 +4186,13 @@
       Importer.ToDiag(FoundIvar->getLocation(), diag::note_odr_value_here)
         << FoundIvar->getType();
 
-      return make_error<ASTImportError>(ASTImportError::NameConflict);
+      std::string ErrMessage;
+      llvm::raw_string_ostream OS(ErrMessage);
+      OS << "ObjCIvarDecl '" << Name.getAsString()
+         << "' declared with incompatible types in different TUs ('"
+         << D->getType() << "' and '" << FoundIvar->getType() << "')";
+      return make_error<ASTImportError>(ASTImportError::NameConflict,
+                                        std::move(ErrMessage));
     }
   }
 
@@ -4471,7 +4500,14 @@
                         diag::note_odr_objc_method_here)
           << D->isInstanceMethod() << Name;
 
-        return make_error<ASTImportError>(ASTImportError::NameConflict);
+        std::string ErrMessage;
+        llvm::raw_string_ostream OS(ErrMessage);
+        OS << "ObjCMethodDecl '" << Name.getAsString()
+           << "' has incompatible result types in different TUs ('"
+           << D->getReturnType() << "' and '" << FoundMethod->getReturnType()
+           << "')";
+        return make_error<ASTImportError>(ASTImportError::NameConflict,
+                                          std::move(ErrMessage));
       }
 
       // Check the number of parameters.
@@ -4483,7 +4519,13 @@
                         diag::note_odr_objc_method_here)
           << D->isInstanceMethod() << Name;
 
-        return make_error<ASTImportError>(ASTImportError::NameConflict);
+        std::string ErrMessage;
+        llvm::raw_string_ostream OS(ErrMessage);
+        OS << "ObjCMethodDecl '" << Name.getAsString()
+           << "' has a different number of parameters in different TUs ('"
+           << D->param_size() << "' and '" << FoundMethod->param_size() << "')";
+        return make_error<ASTImportError>(ASTImportError::NameConflict,
+                                          std::move(ErrMessage));
       }
 
       // Check parameter types.
@@ -4499,7 +4541,13 @@
           Importer.ToDiag((*FoundP)->getLocation(), diag::note_odr_value_here)
             << (*FoundP)->getType();
 
-          return make_error<ASTImportError>(ASTImportError::NameConflict);
+          std::string ErrMessage;
+          llvm::raw_string_ostream OS(ErrMessage);
+          OS << "ObjCMethodDecl '" << Name.getAsString()
+             << "' has a parameter with different types in different TUs ('"
+             << (*P)->getType() << "' and '" << (*FoundP)->getType() << "')";
+          return make_error<ASTImportError>(ASTImportError::NameConflict,
+                                            std::move(ErrMessage));
         }
       }
 
@@ -4512,7 +4560,12 @@
                         diag::note_odr_objc_method_here)
           << D->isInstanceMethod() << Name;
 
-        return make_error<ASTImportError>(ASTImportError::NameConflict);
+        std::string ErrMessage;
+        llvm::raw_string_ostream OS(ErrMessage);
+        OS << "ObjCMethodDecl '" << Name.getAsString()
+           << "' is variadic in one TU but not the other";
+        return make_error<ASTImportError>(ASTImportError::NameConflict,
+                                          std::move(ErrMessage));
       }
 
       // FIXME: Any other bits we need to merge?
@@ -5479,7 +5532,13 @@
         Importer.ToDiag(FoundProp->getLocation(), diag::note_odr_value_here)
           << FoundProp->getType();
 
-        return make_error<ASTImportError>(ASTImportError::NameConflict);
+        std::string ErrMessage;
+        llvm::raw_string_ostream OS(ErrMessage);
+        OS << "ObjCPropertyDecl '" << Name.getAsString()
+           << "' declared with incompatible types in different TUs ('"
+           << D->getType() << "' and '" << FoundProp->getType() << "')";
+        return make_error<ASTImportError>(ASTImportError::NameConflict,
+                                          std::move(ErrMessage));
       }
 
       // FIXME: Check property attributes, getters, setters, etc.?
@@ -5924,7 +5983,12 @@
       }
     } else { // ODR violation.
       // FIXME HandleNameConflict
-      return make_error<ASTImportError>(ASTImportError::NameConflict);
+      std::string ErrMessage;
+      llvm::raw_string_ostream OS(ErrMessage);
+      OS << "ClassTemplateSpecializationDecl '" << D->getName()
+         << "' has incompatible definitions in different TUs.";
+      return make_error<ASTImportError>(ASTImportError::NameConflict,
+                                        std::move(ErrMessage));
     }
   }
 
@@ -6422,13 +6486,15 @@
 ExpectedStmt ASTNodeImporter::VisitStmt(Stmt *S) {
   Importer.FromDiag(S->getBeginLoc(), diag::err_unsupported_ast_node)
       << S->getStmtClassName();
-  return make_error<ASTImportError>(ASTImportError::UnsupportedConstruct);
+  return make_error<ASTImportError>(ASTImportError::UnsupportedConstruct,
+                                    S->getStmtClassName());
 }
 
 
 ExpectedStmt ASTNodeImporter::VisitGCCAsmStmt(GCCAsmStmt *S) {
   if (Importer.returnWithErrorInTest())
-    return make_error<ASTImportError>(ASTImportError::UnsupportedConstruct);
+    return make_error<ASTImportError>(ASTImportError::UnsupportedConstruct,
+                                      S->getStmtClassName());
   SmallVector<IdentifierInfo *, 4> Names;
   for (unsigned I = 0, E = S->getNumOutputs(); I != E; I++) {
     IdentifierInfo *ToII = Importer.Import(S->getOutputIdentifier(I));
@@ -6936,7 +7002,8 @@
 ExpectedStmt ASTNodeImporter::VisitExpr(Expr *E) {
   Importer.FromDiag(E->getBeginLoc(), diag::err_unsupported_ast_node)
       << E->getStmtClassName();
-  return make_error<ASTImportError>(ASTImportError::UnsupportedConstruct);
+  return make_error<ASTImportError>(ASTImportError::UnsupportedConstruct,
+                                    E->getStmtClassName());
 }
 
 ExpectedStmt ASTNodeImporter::VisitSourceLocExpr(SourceLocExpr *E) {
@@ -7630,7 +7697,8 @@
   }
   default:
     llvm_unreachable("Cast expression of unsupported type!");
-    return make_error<ASTImportError>(ASTImportError::UnsupportedConstruct);
+    return make_error<ASTImportError>(ASTImportError::UnsupportedConstruct,
+                                      E->getCastKindName());
   }
 }
 
@@ -8507,7 +8575,8 @@
         ToOperatorLoc, ToRParenLoc, ToAngleBrackets);
   } else {
     llvm_unreachable("Unknown cast type");
-    return make_error<ASTImportError>();
+    return make_error<ASTImportError>(ASTImportError::Unknown,
+                                      E->getCastName());
   }
 }
 
@@ -8702,7 +8771,8 @@
 
   // FIXME: Handle BlockDecl when we implement importing BlockExpr in
   //        ASTNodeImporter.
-  return make_error<ASTImportError>(ASTImportError::UnsupportedConstruct);
+  return make_error<ASTImportError>(ASTImportError::UnsupportedConstruct,
+                                    "BlockDecl");
 }
 
 ExpectedTypePtr ASTImporter::Import(const Type *FromT) {
@@ -10045,7 +10115,8 @@
                                                           unsigned NumDecls) {
   if (ODRHandling == ODRHandlingType::Conservative)
     // Report error at any name conflict.
-    return make_error<ASTImportError>(ASTImportError::NameConflict);
+    return make_error<ASTImportError>(ASTImportError::NameConflict,
+                                      Name.getAsString());
   else
     // Allow to create the new Decl with the same name.
     return Name;
Index: clang/include/clang/AST/ASTImportError.h
===================================================================
--- clang/include/clang/AST/ASTImportError.h
+++ clang/include/clang/AST/ASTImportError.h
@@ -32,17 +32,24 @@
   static char ID;
 
   ASTImportError() : Error(Unknown) {}
-  ASTImportError(const ASTImportError &Other) : Error(Other.Error) {}
-  ASTImportError &operator=(const ASTImportError &Other) {
-    Error = Other.Error;
-    return *this;
-  }
+
+  ASTImportError(const ASTImportError &) = default;
+  ASTImportError(ASTImportError &&) = default;
+
+  ASTImportError &operator=(const ASTImportError &) = default;
+  ASTImportError &operator=(ASTImportError &&) = default;
+
+  ASTImportError(ErrorKind Error, std::string Message)
+      : Error(Error), Message(std::move(Message)) {}
   ASTImportError(ErrorKind Error) : Error(Error) {}
 
   std::string toString() const;
 
   void log(llvm::raw_ostream &OS) const override;
   std::error_code convertToErrorCode() const override;
+
+private:
+  std::string Message;
 };
 
 } // namespace clang
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to