diff --git a/clang/include/clang/AST/ASTImportError.h b/clang/include/clang/AST/ASTImportError.h --- a/clang/include/clang/AST/ASTImportError.h +++ b/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 diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -84,7 +84,6 @@ using ExpectedName = llvm::Expected; std::string ASTImportError::toString() const { - // FIXME: Improve error texts. switch (Error) { case NameConflict: return "NameConflict"; @@ -97,7 +96,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 +1069,8 @@ ExpectedType ASTNodeImporter::VisitType(const Type *T) { Importer.FromDiag(SourceLocation(), diag::err_unsupported_ast_node) << T->getTypeClassName(); - return make_error(ASTImportError::UnsupportedConstruct); + return make_error(ASTImportError::UnsupportedConstruct, + T->getTypeClassName()); } ExpectedType ASTNodeImporter::VisitAtomicType(const AtomicType *T){ @@ -1715,7 +1719,8 @@ if (RT && RT->getDecl() == D) { Importer.FromDiag(D->getLocation(), diag::err_unsupported_ast_node) << D->getDeclKindName(); - return make_error(ASTImportError::UnsupportedConstruct); + return make_error(ASTImportError::UnsupportedConstruct, + D->getDeclKindName()); } } } @@ -2238,13 +2243,15 @@ ExpectedDecl ASTNodeImporter::VisitDecl(Decl *D) { Importer.FromDiag(D->getLocation(), diag::err_unsupported_ast_node) << D->getDeclKindName(); - return make_error(ASTImportError::UnsupportedConstruct); + return make_error(ASTImportError::UnsupportedConstruct, + D->getDeclKindName()); } ExpectedDecl ASTNodeImporter::VisitImportDecl(ImportDecl *D) { Importer.FromDiag(D->getLocation(), diag::err_unsupported_ast_node) << D->getDeclKindName(); - return make_error(ASTImportError::UnsupportedConstruct); + return make_error(ASTImportError::UnsupportedConstruct, + D->getDeclKindName()); } ExpectedDecl ASTNodeImporter::VisitEmptyDecl(EmptyDecl *D) { @@ -3893,7 +3900,13 @@ Importer.ToDiag(FoundField->getLocation(), diag::note_odr_value_here) << FoundField->getType(); - return make_error(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::NameConflict, + std::move(ErrMessage)); } } @@ -3972,7 +3985,13 @@ Importer.ToDiag(FoundField->getLocation(), diag::note_odr_value_here) << FoundField->getType(); - return make_error(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::NameConflict, + std::move(ErrMessage)); } } @@ -4163,7 +4182,13 @@ Importer.ToDiag(FoundIvar->getLocation(), diag::note_odr_value_here) << FoundIvar->getType(); - return make_error(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::NameConflict, + std::move(ErrMessage)); } } @@ -4471,7 +4496,14 @@ diag::note_odr_objc_method_here) << D->isInstanceMethod() << Name; - return make_error(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::NameConflict, + std::move(ErrMessage)); } // Check the number of parameters. @@ -4483,7 +4515,13 @@ diag::note_odr_objc_method_here) << D->isInstanceMethod() << Name; - return make_error(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::NameConflict, + std::move(ErrMessage)); } // Check parameter types. @@ -4499,7 +4537,13 @@ Importer.ToDiag((*FoundP)->getLocation(), diag::note_odr_value_here) << (*FoundP)->getType(); - return make_error(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::NameConflict, + std::move(ErrMessage)); } } @@ -4512,7 +4556,12 @@ diag::note_odr_objc_method_here) << D->isInstanceMethod() << Name; - return make_error(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::NameConflict, + std::move(ErrMessage)); } // FIXME: Any other bits we need to merge? @@ -5479,7 +5528,13 @@ Importer.ToDiag(FoundProp->getLocation(), diag::note_odr_value_here) << FoundProp->getType(); - return make_error(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::NameConflict, + std::move(ErrMessage)); } // FIXME: Check property attributes, getters, setters, etc.? @@ -5924,7 +5979,12 @@ } } else { // ODR violation. // FIXME HandleNameConflict - return make_error(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::NameConflict, + std::move(ErrMessage)); } } @@ -6422,13 +6482,15 @@ ExpectedStmt ASTNodeImporter::VisitStmt(Stmt *S) { Importer.FromDiag(S->getBeginLoc(), diag::err_unsupported_ast_node) << S->getStmtClassName(); - return make_error(ASTImportError::UnsupportedConstruct); + return make_error(ASTImportError::UnsupportedConstruct, + S->getStmtClassName()); } ExpectedStmt ASTNodeImporter::VisitGCCAsmStmt(GCCAsmStmt *S) { if (Importer.returnWithErrorInTest()) - return make_error(ASTImportError::UnsupportedConstruct); + return make_error(ASTImportError::UnsupportedConstruct, + S->getStmtClassName()); SmallVector Names; for (unsigned I = 0, E = S->getNumOutputs(); I != E; I++) { IdentifierInfo *ToII = Importer.Import(S->getOutputIdentifier(I)); @@ -6936,7 +6998,8 @@ ExpectedStmt ASTNodeImporter::VisitExpr(Expr *E) { Importer.FromDiag(E->getBeginLoc(), diag::err_unsupported_ast_node) << E->getStmtClassName(); - return make_error(ASTImportError::UnsupportedConstruct); + return make_error(ASTImportError::UnsupportedConstruct, + E->getStmtClassName()); } ExpectedStmt ASTNodeImporter::VisitSourceLocExpr(SourceLocExpr *E) { @@ -7630,7 +7693,8 @@ } default: llvm_unreachable("Cast expression of unsupported type!"); - return make_error(ASTImportError::UnsupportedConstruct); + return make_error(ASTImportError::UnsupportedConstruct, + E->getCastKindName()); } } @@ -8507,7 +8571,8 @@ ToOperatorLoc, ToRParenLoc, ToAngleBrackets); } else { llvm_unreachable("Unknown cast type"); - return make_error(); + return make_error(ASTImportError::Unknown, + E->getCastName()); } } @@ -8702,7 +8767,8 @@ // FIXME: Handle BlockDecl when we implement importing BlockExpr in // ASTNodeImporter. - return make_error(ASTImportError::UnsupportedConstruct); + return make_error(ASTImportError::UnsupportedConstruct, + "BlockDecl"); } ExpectedTypePtr ASTImporter::Import(const Type *FromT) { @@ -10045,7 +10111,8 @@ unsigned NumDecls) { if (ODRHandling == ODRHandlingType::Conservative) // Report error at any name conflict. - return make_error(ASTImportError::NameConflict); + return make_error(ASTImportError::NameConflict, + Name.getAsString()); else // Allow to create the new Decl with the same name. return Name;