diff options
Diffstat (limited to 'contrib/llvm-project/clang/lib/AST/ASTImporter.cpp')
-rw-r--r-- | contrib/llvm-project/clang/lib/AST/ASTImporter.cpp | 2269 |
1 files changed, 1572 insertions, 697 deletions
diff --git a/contrib/llvm-project/clang/lib/AST/ASTImporter.cpp b/contrib/llvm-project/clang/lib/AST/ASTImporter.cpp index 787e02029dae..12734d62ed9f 100644 --- a/contrib/llvm-project/clang/lib/AST/ASTImporter.cpp +++ b/contrib/llvm-project/clang/lib/AST/ASTImporter.cpp @@ -12,9 +12,9 @@ //===----------------------------------------------------------------------===// #include "clang/AST/ASTImporter.h" -#include "clang/AST/ASTImporterSharedState.h" #include "clang/AST/ASTContext.h" #include "clang/AST/ASTDiagnostic.h" +#include "clang/AST/ASTImporterSharedState.h" #include "clang/AST/ASTStructuralEquivalence.h" #include "clang/AST/Attr.h" #include "clang/AST/Decl.h" @@ -56,10 +56,8 @@ #include "llvm/ADT/APSInt.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/None.h" -#include "llvm/ADT/Optional.h" -#include "llvm/ADT/ScopeExit.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/ScopeExit.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Support/Casting.h" #include "llvm/Support/ErrorHandling.h" @@ -68,6 +66,7 @@ #include <cassert> #include <cstddef> #include <memory> +#include <optional> #include <type_traits> #include <utility> @@ -76,6 +75,7 @@ namespace clang { using llvm::make_error; using llvm::Error; using llvm::Expected; + using ExpectedTypePtr = llvm::Expected<const Type *>; using ExpectedType = llvm::Expected<QualType>; using ExpectedStmt = llvm::Expected<Stmt *>; using ExpectedExpr = llvm::Expected<Expr *>; @@ -83,7 +83,7 @@ namespace clang { using ExpectedSLoc = llvm::Expected<SourceLocation>; using ExpectedName = llvm::Expected<DeclarationName>; - std::string ImportError::toString() const { + std::string ASTImportError::toString() const { // FIXME: Improve error texts. switch (Error) { case NameConflict: @@ -97,15 +97,13 @@ namespace clang { return "Invalid error code."; } - void ImportError::log(raw_ostream &OS) const { - OS << toString(); - } + void ASTImportError::log(raw_ostream &OS) const { OS << toString(); } - std::error_code ImportError::convertToErrorCode() const { + std::error_code ASTImportError::convertToErrorCode() const { llvm_unreachable("Function not implemented."); } - char ImportError::ID; + char ASTImportError::ID; template <class T> SmallVector<Decl *, 2> @@ -137,6 +135,46 @@ namespace clang { To->setIsUsed(); } + /// How to handle import errors that occur when import of a child declaration + /// of a DeclContext fails. + class ChildErrorHandlingStrategy { + /// This context is imported (in the 'from' domain). + /// It is nullptr if a non-DeclContext is imported. + const DeclContext *const FromDC; + /// Ignore import errors of the children. + /// If true, the context can be imported successfully if a child + /// of it failed to import. Otherwise the import errors of the child nodes + /// are accumulated (joined) into the import error object of the parent. + /// (Import of a parent can fail in other ways.) + bool const IgnoreChildErrors; + + public: + ChildErrorHandlingStrategy(const DeclContext *FromDC) + : FromDC(FromDC), IgnoreChildErrors(!isa<TagDecl>(FromDC)) {} + ChildErrorHandlingStrategy(const Decl *FromD) + : FromDC(dyn_cast<DeclContext>(FromD)), + IgnoreChildErrors(!isa<TagDecl>(FromD)) {} + + /// Process the import result of a child (of the current declaration). + /// \param ResultErr The import error that can be used as result of + /// importing the parent. This may be changed by the function. + /// \param ChildErr Result of importing a child. Can be success or error. + void handleChildImportResult(Error &ResultErr, Error &&ChildErr) { + if (ChildErr && !IgnoreChildErrors) + ResultErr = joinErrors(std::move(ResultErr), std::move(ChildErr)); + else + consumeError(std::move(ChildErr)); + } + + /// Determine if import failure of a child does not cause import failure of + /// its parent. + bool ignoreChildErrorOnParent(Decl *FromChildD) const { + if (!IgnoreChildErrors || !FromDC) + return false; + return FromDC->containsDecl(FromChildD); + } + }; + class ASTNodeImporter : public TypeVisitor<ASTNodeImporter, ExpectedType>, public DeclVisitor<ASTNodeImporter, ExpectedDecl>, public StmtVisitor<ASTNodeImporter, ExpectedStmt> { @@ -144,13 +182,13 @@ namespace clang { // Use this instead of Importer.importInto . template <typename ImportT> - LLVM_NODISCARD Error importInto(ImportT &To, const ImportT &From) { + [[nodiscard]] Error importInto(ImportT &To, const ImportT &From) { return Importer.importInto(To, From); } // Use this to import pointers of specific type. template <typename ImportT> - LLVM_NODISCARD Error importInto(ImportT *&To, ImportT *From) { + [[nodiscard]] Error importInto(ImportT *&To, ImportT *From) { auto ToOrErr = Importer.Import(From); if (ToOrErr) To = cast_or_null<ImportT>(*ToOrErr); @@ -160,7 +198,9 @@ namespace clang { // Call the import function of ASTImporter for a baseclass of type `T` and // cast the return value to `T`. template <typename T> - Expected<T *> import(T *From) { + auto import(T *From) + -> std::conditional_t<std::is_base_of_v<Type, T>, Expected<const T *>, + Expected<T *>> { auto ToOrErr = Importer.Import(From); if (!ToOrErr) return ToOrErr.takeError(); @@ -168,7 +208,7 @@ namespace clang { } template <typename T> - Expected<T *> import(const T *From) { + auto import(const T *From) { return import(const_cast<T *>(From)); } @@ -178,30 +218,14 @@ namespace clang { return Importer.Import(From); } - // Import an Optional<T> by importing the contained T, if any. - template<typename T> - Expected<Optional<T>> import(Optional<T> From) { + // Import an std::optional<T> by importing the contained T, if any. + template <typename T> + Expected<std::optional<T>> import(std::optional<T> From) { if (!From) - return Optional<T>(); + return std::nullopt; return import(*From); } - // Helper for chaining together multiple imports. If an error is detected, - // subsequent imports will return default constructed nodes, so that failure - // can be detected with a single conditional branch after a sequence of - // imports. - template <typename T> T importChecked(Error &Err, const T &From) { - // Don't attempt to import nodes if we hit an error earlier. - if (Err) - return T{}; - Expected<T> MaybeVal = import(From); - if (!MaybeVal) { - Err = MaybeVal.takeError(); - return T{}; - } - return *MaybeVal; - } - ExplicitSpecifier importExplicitSpecifier(Error &Err, ExplicitSpecifier ESpec); @@ -219,8 +243,8 @@ namespace clang { // then to the already imported Decl. Returns a bool value set to true if // the `FromD` had been imported before. template <typename ToDeclT, typename FromDeclT, typename... Args> - LLVM_NODISCARD bool GetImportedOrCreateDecl(ToDeclT *&ToD, FromDeclT *FromD, - Args &&... args) { + [[nodiscard]] bool GetImportedOrCreateDecl(ToDeclT *&ToD, FromDeclT *FromD, + Args &&...args) { // There may be several overloads of ToDeclT::Create. We must make sure // to call the one which would be chosen by the arguments, thus we use a // wrapper for the overload set. @@ -235,8 +259,8 @@ namespace clang { // GetImportedOrCreateDecl<TypeAliasDecl>(ToTypedef, FromD, ...); template <typename NewDeclT, typename ToDeclT, typename FromDeclT, typename... Args> - LLVM_NODISCARD bool GetImportedOrCreateDecl(ToDeclT *&ToD, FromDeclT *FromD, - Args &&... args) { + [[nodiscard]] bool GetImportedOrCreateDecl(ToDeclT *&ToD, FromDeclT *FromD, + Args &&...args) { CallOverloadedCreateFun<NewDeclT> OC; return GetImportedOrCreateSpecialDecl(ToD, OC, FromD, std::forward<Args>(args)...); @@ -245,9 +269,9 @@ namespace clang { // used, e.g. CXXRecordDecl::CreateLambda . template <typename ToDeclT, typename CreateFunT, typename FromDeclT, typename... Args> - LLVM_NODISCARD bool + [[nodiscard]] bool GetImportedOrCreateSpecialDecl(ToDeclT *&ToD, CreateFunT CreateFun, - FromDeclT *FromD, Args &&... args) { + FromDeclT *FromD, Args &&...args) { if (Importer.getImportDeclErrorIfAny(FromD)) { ToD = nullptr; return true; // Already imported but with error. @@ -258,6 +282,7 @@ namespace clang { ToD = CreateFun(std::forward<Args>(args)...); // Keep track of imported Decls. Importer.RegisterImportedDecl(FromD, ToD); + Importer.SharedState->markAsNewDecl(ToD); InitializeImportedDecl(FromD, ToD); return false; // A new Decl is created. } @@ -313,11 +338,8 @@ namespace clang { auto *ToNamed = cast<NamedDecl>(ToD); DeclContextLookupResult FromLookup = FromDC->lookup(FromNamed->getDeclName()); - for (NamedDecl *ND : FromLookup) - if (ND == FromNamed) { - ToDC->makeDeclVisibleInContext(ToNamed); - break; - } + if (llvm::is_contained(FromLookup, FromNamed)) + ToDC->makeDeclVisibleInContext(ToNamed); } } } @@ -346,53 +368,9 @@ namespace clang { // Importing types ExpectedType VisitType(const Type *T); - ExpectedType VisitAtomicType(const AtomicType *T); - ExpectedType VisitBuiltinType(const BuiltinType *T); - ExpectedType VisitDecayedType(const DecayedType *T); - ExpectedType VisitComplexType(const ComplexType *T); - ExpectedType VisitPointerType(const PointerType *T); - ExpectedType VisitBlockPointerType(const BlockPointerType *T); - ExpectedType VisitLValueReferenceType(const LValueReferenceType *T); - ExpectedType VisitRValueReferenceType(const RValueReferenceType *T); - ExpectedType VisitMemberPointerType(const MemberPointerType *T); - ExpectedType VisitConstantArrayType(const ConstantArrayType *T); - ExpectedType VisitIncompleteArrayType(const IncompleteArrayType *T); - ExpectedType VisitVariableArrayType(const VariableArrayType *T); - ExpectedType VisitDependentSizedArrayType(const DependentSizedArrayType *T); - // FIXME: DependentSizedExtVectorType - ExpectedType VisitVectorType(const VectorType *T); - ExpectedType VisitExtVectorType(const ExtVectorType *T); - ExpectedType VisitFunctionNoProtoType(const FunctionNoProtoType *T); - ExpectedType VisitFunctionProtoType(const FunctionProtoType *T); - ExpectedType VisitUnresolvedUsingType(const UnresolvedUsingType *T); - ExpectedType VisitParenType(const ParenType *T); - ExpectedType VisitTypedefType(const TypedefType *T); - ExpectedType VisitTypeOfExprType(const TypeOfExprType *T); - // FIXME: DependentTypeOfExprType - ExpectedType VisitTypeOfType(const TypeOfType *T); - ExpectedType VisitDecltypeType(const DecltypeType *T); - ExpectedType VisitUnaryTransformType(const UnaryTransformType *T); - ExpectedType VisitAutoType(const AutoType *T); - ExpectedType VisitDeducedTemplateSpecializationType( - const DeducedTemplateSpecializationType *T); - ExpectedType VisitInjectedClassNameType(const InjectedClassNameType *T); - // FIXME: DependentDecltypeType - ExpectedType VisitRecordType(const RecordType *T); - ExpectedType VisitEnumType(const EnumType *T); - ExpectedType VisitAttributedType(const AttributedType *T); - ExpectedType VisitTemplateTypeParmType(const TemplateTypeParmType *T); - ExpectedType VisitSubstTemplateTypeParmType( - const SubstTemplateTypeParmType *T); - ExpectedType VisitTemplateSpecializationType( - const TemplateSpecializationType *T); - ExpectedType VisitElaboratedType(const ElaboratedType *T); - ExpectedType VisitDependentNameType(const DependentNameType *T); - ExpectedType VisitPackExpansionType(const PackExpansionType *T); - ExpectedType VisitDependentTemplateSpecializationType( - const DependentTemplateSpecializationType *T); - ExpectedType VisitObjCInterfaceType(const ObjCInterfaceType *T); - ExpectedType VisitObjCObjectType(const ObjCObjectType *T); - ExpectedType VisitObjCObjectPointerType(const ObjCObjectPointerType *T); +#define TYPE(Class, Base) \ + ExpectedType Visit##Class##Type(const Class##Type *T); +#include "clang/AST/TypeNodes.inc" // Importing declarations Error ImportDeclParts(NamedDecl *D, DeclarationName &Name, NamedDecl *&ToD, @@ -408,6 +386,7 @@ namespace clang { Decl *From, DeclContext *&ToDC, DeclContext *&ToLexicalDC); Error ImportImplicitMethods(const CXXRecordDecl *From, CXXRecordDecl *To); + Error ImportFieldDeclDefinition(const FieldDecl *From, const FieldDecl *To); Expected<CXXCastPath> ImportCastPath(CastExpr *E); Expected<APValue> ImportAPValue(const APValue &FromValue); @@ -444,9 +423,8 @@ namespace clang { Error ImportDefinition( ObjCProtocolDecl *From, ObjCProtocolDecl *To, ImportDefinitionKind Kind = IDK_Default); - Error ImportTemplateArguments( - const TemplateArgument *FromArgs, unsigned NumFromArgs, - SmallVectorImpl<TemplateArgument> &ToArgs); + Error ImportTemplateArguments(ArrayRef<TemplateArgument> FromArgs, + SmallVectorImpl<TemplateArgument> &ToArgs); Expected<TemplateArgument> ImportTemplateArgument(const TemplateArgument &From); @@ -475,21 +453,14 @@ namespace clang { Error ImportDefaultArgOfParmVarDecl(const ParmVarDecl *FromParam, ParmVarDecl *ToParam); + Expected<InheritedConstructor> + ImportInheritedConstructor(const InheritedConstructor &From); + template <typename T> bool hasSameVisibilityContextAndLinkage(T *Found, T *From); - bool IsStructuralMatch(Decl *From, Decl *To, bool Complain); - bool IsStructuralMatch(RecordDecl *FromRecord, RecordDecl *ToRecord, - bool Complain = true); - bool IsStructuralMatch(VarDecl *FromVar, VarDecl *ToVar, - bool Complain = true); - bool IsStructuralMatch(EnumDecl *FromEnum, EnumDecl *ToRecord); - bool IsStructuralMatch(EnumConstantDecl *FromEC, EnumConstantDecl *ToEC); - bool IsStructuralMatch(FunctionTemplateDecl *From, - FunctionTemplateDecl *To); - bool IsStructuralMatch(FunctionDecl *From, FunctionDecl *To); - bool IsStructuralMatch(ClassTemplateDecl *From, ClassTemplateDecl *To); - bool IsStructuralMatch(VarTemplateDecl *From, VarTemplateDecl *To); + bool IsStructuralMatch(Decl *From, Decl *To, bool Complain = true, + bool IgnoreTemplateParmDepth = false); ExpectedDecl VisitDecl(Decl *D); ExpectedDecl VisitImportDecl(ImportDecl *D); ExpectedDecl VisitEmptyDecl(EmptyDecl *D); @@ -528,6 +499,7 @@ namespace clang { ExpectedDecl VisitUsingDecl(UsingDecl *D); ExpectedDecl VisitUsingShadowDecl(UsingShadowDecl *D); ExpectedDecl VisitUsingDirectiveDecl(UsingDirectiveDecl *D); + ExpectedDecl VisitUsingPackDecl(UsingPackDecl *D); ExpectedDecl ImportUsingShadowDecls(BaseUsingDecl *D, BaseUsingDecl *ToSI); ExpectedDecl VisitUsingEnumDecl(UsingEnumDecl *D); ExpectedDecl VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D); @@ -597,6 +569,8 @@ namespace clang { ExpectedStmt VisitSourceLocExpr(SourceLocExpr *E); ExpectedStmt VisitVAArgExpr(VAArgExpr *E); ExpectedStmt VisitChooseExpr(ChooseExpr *E); + ExpectedStmt VisitConvertVectorExpr(ConvertVectorExpr *E); + ExpectedStmt VisitShuffleVectorExpr(ShuffleVectorExpr *E); ExpectedStmt VisitGNUNullExpr(GNUNullExpr *E); ExpectedStmt VisitGenericSelectionExpr(GenericSelectionExpr *E); ExpectedStmt VisitPredefinedExpr(PredefinedExpr *E); @@ -622,6 +596,7 @@ namespace clang { ExpectedStmt VisitBinaryOperator(BinaryOperator *E); ExpectedStmt VisitConditionalOperator(ConditionalOperator *E); ExpectedStmt VisitBinaryConditionalOperator(BinaryConditionalOperator *E); + ExpectedStmt VisitCXXRewrittenBinaryOperator(CXXRewrittenBinaryOperator *E); ExpectedStmt VisitOpaqueValueExpr(OpaqueValueExpr *E); ExpectedStmt VisitArrayTypeTraitExpr(ArrayTypeTraitExpr *E); ExpectedStmt VisitExpressionTraitExpr(ExpressionTraitExpr *E); @@ -667,6 +642,22 @@ namespace clang { ExpectedStmt VisitCXXTypeidExpr(CXXTypeidExpr *E); ExpectedStmt VisitCXXFoldExpr(CXXFoldExpr *E); + // Helper for chaining together multiple imports. If an error is detected, + // subsequent imports will return default constructed nodes, so that failure + // can be detected with a single conditional branch after a sequence of + // imports. + template <typename T> T importChecked(Error &Err, const T &From) { + // Don't attempt to import nodes if we hit an error earlier. + if (Err) + return T{}; + Expected<T> MaybeVal = import(From); + if (!MaybeVal) { + Err = MaybeVal.takeError(); + return T{}; + } + return *MaybeVal; + } + template<typename IIter, typename OIter> Error ImportArrayChecked(IIter Ibegin, IIter Iend, OIter Obegin) { using ItemT = std::remove_reference_t<decltype(*Obegin)>; @@ -754,9 +745,8 @@ ASTNodeImporter::ImportFunctionTemplateWithTemplateArgsFromSpecialization( return std::move(Err); // Import template arguments. - auto TemplArgs = FTSInfo->TemplateArguments->asArray(); - if (Error Err = ImportTemplateArguments(TemplArgs.data(), TemplArgs.size(), - std::get<1>(Result))) + if (Error Err = ImportTemplateArguments(FTSInfo->TemplateArguments->asArray(), + std::get<1>(Result))) return std::move(Err); return Result; @@ -803,7 +793,8 @@ ASTNodeImporter::import(const TemplateArgument &From) { ExpectedType ToTypeOrErr = import(From.getAsType()); if (!ToTypeOrErr) return ToTypeOrErr.takeError(); - return TemplateArgument(*ToTypeOrErr); + return TemplateArgument(*ToTypeOrErr, /*isNullPtr*/ false, + From.getIsDefaulted()); } case TemplateArgument::Integral: { @@ -820,14 +811,27 @@ ASTNodeImporter::import(const TemplateArgument &From) { ExpectedType ToTypeOrErr = import(From.getParamTypeForDecl()); if (!ToTypeOrErr) return ToTypeOrErr.takeError(); - return TemplateArgument(*ToOrErr, *ToTypeOrErr); + return TemplateArgument(dyn_cast<ValueDecl>((*ToOrErr)->getCanonicalDecl()), + *ToTypeOrErr, From.getIsDefaulted()); } case TemplateArgument::NullPtr: { ExpectedType ToTypeOrErr = import(From.getNullPtrType()); if (!ToTypeOrErr) return ToTypeOrErr.takeError(); - return TemplateArgument(*ToTypeOrErr, /*isNullPtr*/true); + return TemplateArgument(*ToTypeOrErr, /*isNullPtr*/ true, + From.getIsDefaulted()); + } + + case TemplateArgument::StructuralValue: { + ExpectedType ToTypeOrErr = import(From.getStructuralValueType()); + if (!ToTypeOrErr) + return ToTypeOrErr.takeError(); + Expected<APValue> ToValueOrErr = import(From.getAsStructuralValue()); + if (!ToValueOrErr) + return ToValueOrErr.takeError(); + return TemplateArgument(Importer.getToContext(), *ToTypeOrErr, + *ToValueOrErr); } case TemplateArgument::Template: { @@ -835,7 +839,7 @@ ASTNodeImporter::import(const TemplateArgument &From) { if (!ToTemplateOrErr) return ToTemplateOrErr.takeError(); - return TemplateArgument(*ToTemplateOrErr); + return TemplateArgument(*ToTemplateOrErr, From.getIsDefaulted()); } case TemplateArgument::TemplateExpansion: { @@ -844,25 +848,24 @@ ASTNodeImporter::import(const TemplateArgument &From) { if (!ToTemplateOrErr) return ToTemplateOrErr.takeError(); - return TemplateArgument( - *ToTemplateOrErr, From.getNumTemplateExpansions()); + return TemplateArgument(*ToTemplateOrErr, From.getNumTemplateExpansions(), + From.getIsDefaulted()); } case TemplateArgument::Expression: if (ExpectedExpr ToExpr = import(From.getAsExpr())) - return TemplateArgument(*ToExpr); + return TemplateArgument(*ToExpr, From.getIsDefaulted()); else return ToExpr.takeError(); case TemplateArgument::Pack: { SmallVector<TemplateArgument, 2> ToPack; ToPack.reserve(From.pack_size()); - if (Error Err = ImportTemplateArguments( - From.pack_begin(), From.pack_size(), ToPack)) + if (Error Err = ImportTemplateArguments(From.pack_elements(), ToPack)) return std::move(Err); return TemplateArgument( - llvm::makeArrayRef(ToPack).copy(Importer.getToContext())); + llvm::ArrayRef(ToPack).copy(Importer.getToContext())); } } @@ -942,7 +945,8 @@ ASTNodeImporter::import(const Designator &D) { if (!ToFieldLocOrErr) return ToFieldLocOrErr.takeError(); - return Designator(ToFieldName, *ToDotLocOrErr, *ToFieldLocOrErr); + return DesignatedInitExpr::Designator::CreateFieldDesignator( + ToFieldName, *ToDotLocOrErr, *ToFieldLocOrErr); } ExpectedSLoc ToLBracketLocOrErr = import(D.getLBracketLoc()); @@ -954,22 +958,50 @@ ASTNodeImporter::import(const Designator &D) { return ToRBracketLocOrErr.takeError(); if (D.isArrayDesignator()) - return Designator(D.getFirstExprIndex(), - *ToLBracketLocOrErr, *ToRBracketLocOrErr); + return Designator::CreateArrayDesignator(D.getArrayIndex(), + *ToLBracketLocOrErr, + *ToRBracketLocOrErr); ExpectedSLoc ToEllipsisLocOrErr = import(D.getEllipsisLoc()); if (!ToEllipsisLocOrErr) return ToEllipsisLocOrErr.takeError(); assert(D.isArrayRangeDesignator()); - return Designator( - D.getFirstExprIndex(), *ToLBracketLocOrErr, *ToEllipsisLocOrErr, + return Designator::CreateArrayRangeDesignator( + D.getArrayIndex(), *ToLBracketLocOrErr, *ToEllipsisLocOrErr, *ToRBracketLocOrErr); } template <> +Expected<ConceptReference *> ASTNodeImporter::import(ConceptReference *From) { + Error Err = Error::success(); + auto ToNNS = importChecked(Err, From->getNestedNameSpecifierLoc()); + auto ToTemplateKWLoc = importChecked(Err, From->getTemplateKWLoc()); + auto ToConceptNameLoc = + importChecked(Err, From->getConceptNameInfo().getLoc()); + auto ToConceptName = importChecked(Err, From->getConceptNameInfo().getName()); + auto ToFoundDecl = importChecked(Err, From->getFoundDecl()); + auto ToNamedConcept = importChecked(Err, From->getNamedConcept()); + if (Err) + return std::move(Err); + TemplateArgumentListInfo ToTAInfo; + const auto *ASTTemplateArgs = From->getTemplateArgsAsWritten(); + if (ASTTemplateArgs) + if (Error Err = ImportTemplateArgumentListInfo(*ASTTemplateArgs, ToTAInfo)) + return std::move(Err); + auto *ConceptRef = ConceptReference::Create( + Importer.getToContext(), ToNNS, ToTemplateKWLoc, + DeclarationNameInfo(ToConceptName, ToConceptNameLoc), ToFoundDecl, + ToNamedConcept, + ASTTemplateArgs ? ASTTemplateArgumentListInfo::Create( + Importer.getToContext(), ToTAInfo) + : nullptr); + return ConceptRef; +} + +template <> Expected<LambdaCapture> ASTNodeImporter::import(const LambdaCapture &From) { - VarDecl *Var = nullptr; + ValueDecl *Var = nullptr; if (From.capturesVariable()) { if (auto VarOrErr = import(From.getCapturedVar())) Var = *VarOrErr; @@ -1029,7 +1061,7 @@ using namespace clang; ExpectedType ASTNodeImporter::VisitType(const Type *T) { Importer.FromDiag(SourceLocation(), diag::err_unsupported_ast_node) << T->getTypeClassName(); - return make_error<ImportError>(ImportError::UnsupportedConstruct); + return make_error<ASTImportError>(ASTImportError::UnsupportedConstruct); } ExpectedType ASTNodeImporter::VisitAtomicType(const AtomicType *T){ @@ -1062,6 +1094,10 @@ ExpectedType ASTNodeImporter::VisitBuiltinType(const BuiltinType *T) { case BuiltinType::Id: \ return Importer.getToContext().SingletonId; #include "clang/Basic/RISCVVTypes.def" +#define WASM_TYPE(Name, Id, SingletonId) \ + case BuiltinType::Id: \ + return Importer.getToContext().SingletonId; +#include "clang/Basic/WebAssemblyReferenceTypes.def" #define SHARED_SINGLETON_TYPE(Expansion) #define BUILTIN_TYPE(Id, SingletonId) \ case BuiltinType::Id: return Importer.getToContext().SingletonId; @@ -1161,12 +1197,12 @@ ASTNodeImporter::VisitMemberPointerType(const MemberPointerType *T) { if (!ToPointeeTypeOrErr) return ToPointeeTypeOrErr.takeError(); - ExpectedType ClassTypeOrErr = import(QualType(T->getClass(), 0)); + ExpectedTypePtr ClassTypeOrErr = import(T->getClass()); if (!ClassTypeOrErr) return ClassTypeOrErr.takeError(); - return Importer.getToContext().getMemberPointerType( - *ToPointeeTypeOrErr, (*ClassTypeOrErr).getTypePtr()); + return Importer.getToContext().getMemberPointerType(*ToPointeeTypeOrErr, + *ClassTypeOrErr); } ExpectedType @@ -1222,6 +1258,18 @@ ExpectedType ASTNodeImporter::VisitDependentSizedArrayType( T->getIndexTypeCVRQualifiers(), ToBracketsRange); } +ExpectedType ASTNodeImporter::VisitDependentSizedExtVectorType( + const DependentSizedExtVectorType *T) { + Error Err = Error::success(); + QualType ToElementType = importChecked(Err, T->getElementType()); + Expr *ToSizeExpr = importChecked(Err, T->getSizeExpr()); + SourceLocation ToAttrLoc = importChecked(Err, T->getAttributeLoc()); + if (Err) + return std::move(Err); + return Importer.getToContext().getDependentSizedExtVectorType( + ToElementType, ToSizeExpr, ToAttrLoc); +} + ExpectedType ASTNodeImporter::VisitVectorType(const VectorType *T) { ExpectedType ToElementTypeOrErr = import(T->getElementType()); if (!ToElementTypeOrErr) @@ -1326,23 +1374,41 @@ ExpectedType ASTNodeImporter::VisitTypedefType(const TypedefType *T) { if (!ToDeclOrErr) return ToDeclOrErr.takeError(); - return Importer.getToContext().getTypeDeclType(*ToDeclOrErr); + TypedefNameDecl *ToDecl = *ToDeclOrErr; + if (ToDecl->getTypeForDecl()) + return QualType(ToDecl->getTypeForDecl(), 0); + + ExpectedType ToUnderlyingTypeOrErr = import(T->desugar()); + if (!ToUnderlyingTypeOrErr) + return ToUnderlyingTypeOrErr.takeError(); + + return Importer.getToContext().getTypedefType(ToDecl, *ToUnderlyingTypeOrErr); } ExpectedType ASTNodeImporter::VisitTypeOfExprType(const TypeOfExprType *T) { ExpectedExpr ToExprOrErr = import(T->getUnderlyingExpr()); if (!ToExprOrErr) return ToExprOrErr.takeError(); - - return Importer.getToContext().getTypeOfExprType(*ToExprOrErr); + return Importer.getToContext().getTypeOfExprType(*ToExprOrErr, T->getKind()); } ExpectedType ASTNodeImporter::VisitTypeOfType(const TypeOfType *T) { - ExpectedType ToUnderlyingTypeOrErr = import(T->getUnderlyingType()); + ExpectedType ToUnderlyingTypeOrErr = import(T->getUnmodifiedType()); if (!ToUnderlyingTypeOrErr) return ToUnderlyingTypeOrErr.takeError(); + return Importer.getToContext().getTypeOfType(*ToUnderlyingTypeOrErr, + T->getKind()); +} - return Importer.getToContext().getTypeOfType(*ToUnderlyingTypeOrErr); +ExpectedType ASTNodeImporter::VisitUsingType(const UsingType *T) { + Expected<UsingShadowDecl *> FoundOrErr = import(T->getFoundDecl()); + if (!FoundOrErr) + return FoundOrErr.takeError(); + Expected<QualType> UnderlyingOrErr = import(T->getUnderlyingType()); + if (!UnderlyingOrErr) + return UnderlyingOrErr.takeError(); + + return Importer.getToContext().getUsingType(*FoundOrErr, *UnderlyingOrErr); } ExpectedType ASTNodeImporter::VisitDecltypeType(const DecltypeType *T) { @@ -1384,9 +1450,7 @@ ExpectedType ASTNodeImporter::VisitAutoType(const AutoType *T) { return ToTypeConstraintConcept.takeError(); SmallVector<TemplateArgument, 2> ToTemplateArgs; - ArrayRef<TemplateArgument> FromTemplateArgs = T->getTypeConstraintArguments(); - if (Error Err = ImportTemplateArguments(FromTemplateArgs.data(), - FromTemplateArgs.size(), + if (Error Err = ImportTemplateArguments(T->getTypeConstraintArguments(), ToTemplateArgs)) return std::move(Err); @@ -1416,20 +1480,11 @@ ExpectedType ASTNodeImporter::VisitInjectedClassNameType( if (!ToDeclOrErr) return ToDeclOrErr.takeError(); - ExpectedType ToInjTypeOrErr = import(T->getInjectedSpecializationType()); - if (!ToInjTypeOrErr) - return ToInjTypeOrErr.takeError(); - - // FIXME: ASTContext::getInjectedClassNameType is not suitable for AST reading - // See comments in InjectedClassNameType definition for details - // return Importer.getToContext().getInjectedClassNameType(D, InjType); - enum { - TypeAlignmentInBits = 4, - TypeAlignment = 1 << TypeAlignmentInBits - }; - - return QualType(new (Importer.getToContext(), TypeAlignment) - InjectedClassNameType(*ToDeclOrErr, *ToInjTypeOrErr), 0); + // The InjectedClassNameType is created in VisitRecordDecl when the + // T->getDecl() is imported. Here we can return the existing type. + const Type *Ty = (*ToDeclOrErr)->getTypeForDecl(); + assert(Ty && isa<InjectedClassNameType>(Ty)); + return QualType(Ty, 0); } ExpectedType ASTNodeImporter::VisitRecordType(const RecordType *T) { @@ -1472,18 +1527,31 @@ ExpectedType ASTNodeImporter::VisitTemplateTypeParmType( ExpectedType ASTNodeImporter::VisitSubstTemplateTypeParmType( const SubstTemplateTypeParmType *T) { - ExpectedType ReplacedOrErr = import(QualType(T->getReplacedParameter(), 0)); + Expected<Decl *> ReplacedOrErr = import(T->getAssociatedDecl()); if (!ReplacedOrErr) return ReplacedOrErr.takeError(); - const TemplateTypeParmType *Replaced = - cast<TemplateTypeParmType>((*ReplacedOrErr).getTypePtr()); ExpectedType ToReplacementTypeOrErr = import(T->getReplacementType()); if (!ToReplacementTypeOrErr) return ToReplacementTypeOrErr.takeError(); return Importer.getToContext().getSubstTemplateTypeParmType( - Replaced, (*ToReplacementTypeOrErr).getCanonicalType()); + *ToReplacementTypeOrErr, *ReplacedOrErr, T->getIndex(), + T->getPackIndex()); +} + +ExpectedType ASTNodeImporter::VisitSubstTemplateTypeParmPackType( + const SubstTemplateTypeParmPackType *T) { + Expected<Decl *> ReplacedOrErr = import(T->getAssociatedDecl()); + if (!ReplacedOrErr) + return ReplacedOrErr.takeError(); + + Expected<TemplateArgument> ToArgumentPack = import(T->getArgumentPack()); + if (!ToArgumentPack) + return ToArgumentPack.takeError(); + + return Importer.getToContext().getSubstTemplateTypeParmPackType( + *ReplacedOrErr, T->getIndex(), T->getFinal(), *ToArgumentPack); } ExpectedType ASTNodeImporter::VisitTemplateSpecializationType( @@ -1493,12 +1561,12 @@ ExpectedType ASTNodeImporter::VisitTemplateSpecializationType( return ToTemplateOrErr.takeError(); SmallVector<TemplateArgument, 2> ToTemplateArgs; - if (Error Err = ImportTemplateArguments( - T->getArgs(), T->getNumArgs(), ToTemplateArgs)) + if (Error Err = + ImportTemplateArguments(T->template_arguments(), ToTemplateArgs)) return std::move(Err); QualType ToCanonType; - if (!QualType(T, 0).isCanonical()) { + if (!T->isCanonicalUnqualified()) { QualType FromCanonType = Importer.getFromContext().getCanonicalType(QualType(T, 0)); if (ExpectedType TyOrErr = import(FromCanonType)) @@ -1551,9 +1619,8 @@ ExpectedType ASTNodeImporter::VisitDependentTemplateSpecializationType( IdentifierInfo *ToName = Importer.Import(T->getIdentifier()); SmallVector<TemplateArgument, 2> ToPack; - ToPack.reserve(T->getNumArgs()); - if (Error Err = ImportTemplateArguments( - T->getArgs(), T->getNumArgs(), ToPack)) + ToPack.reserve(T->template_arguments().size()); + if (Error Err = ImportTemplateArguments(T->template_arguments(), ToPack)) return std::move(Err); return Importer.getToContext().getDependentTemplateSpecializationType( @@ -1626,6 +1693,134 @@ ASTNodeImporter::VisitObjCObjectPointerType(const ObjCObjectPointerType *T) { return Importer.getToContext().getObjCObjectPointerType(*ToPointeeTypeOrErr); } +ExpectedType +ASTNodeImporter::VisitMacroQualifiedType(const MacroQualifiedType *T) { + ExpectedType ToUnderlyingTypeOrErr = import(T->getUnderlyingType()); + if (!ToUnderlyingTypeOrErr) + return ToUnderlyingTypeOrErr.takeError(); + + IdentifierInfo *ToIdentifier = Importer.Import(T->getMacroIdentifier()); + return Importer.getToContext().getMacroQualifiedType(*ToUnderlyingTypeOrErr, + ToIdentifier); +} + +ExpectedType clang::ASTNodeImporter::VisitAdjustedType(const AdjustedType *T) { + Error Err = Error::success(); + QualType ToOriginalType = importChecked(Err, T->getOriginalType()); + QualType ToAdjustedType = importChecked(Err, T->getAdjustedType()); + if (Err) + return std::move(Err); + + return Importer.getToContext().getAdjustedType(ToOriginalType, + ToAdjustedType); +} + +ExpectedType clang::ASTNodeImporter::VisitBitIntType(const BitIntType *T) { + return Importer.getToContext().getBitIntType(T->isUnsigned(), + T->getNumBits()); +} + +ExpectedType clang::ASTNodeImporter::VisitBTFTagAttributedType( + const clang::BTFTagAttributedType *T) { + Error Err = Error::success(); + const BTFTypeTagAttr *ToBTFAttr = importChecked(Err, T->getAttr()); + QualType ToWrappedType = importChecked(Err, T->getWrappedType()); + if (Err) + return std::move(Err); + + return Importer.getToContext().getBTFTagAttributedType(ToBTFAttr, + ToWrappedType); +} + +ExpectedType clang::ASTNodeImporter::VisitConstantMatrixType( + const clang::ConstantMatrixType *T) { + ExpectedType ToElementTypeOrErr = import(T->getElementType()); + if (!ToElementTypeOrErr) + return ToElementTypeOrErr.takeError(); + + return Importer.getToContext().getConstantMatrixType( + *ToElementTypeOrErr, T->getNumRows(), T->getNumColumns()); +} + +ExpectedType clang::ASTNodeImporter::VisitDependentAddressSpaceType( + const clang::DependentAddressSpaceType *T) { + Error Err = Error::success(); + QualType ToPointeeType = importChecked(Err, T->getPointeeType()); + Expr *ToAddrSpaceExpr = importChecked(Err, T->getAddrSpaceExpr()); + SourceLocation ToAttrLoc = importChecked(Err, T->getAttributeLoc()); + if (Err) + return std::move(Err); + + return Importer.getToContext().getDependentAddressSpaceType( + ToPointeeType, ToAddrSpaceExpr, ToAttrLoc); +} + +ExpectedType clang::ASTNodeImporter::VisitDependentBitIntType( + const clang::DependentBitIntType *T) { + ExpectedExpr ToNumBitsExprOrErr = import(T->getNumBitsExpr()); + if (!ToNumBitsExprOrErr) + return ToNumBitsExprOrErr.takeError(); + return Importer.getToContext().getDependentBitIntType(T->isUnsigned(), + *ToNumBitsExprOrErr); +} + +ExpectedType clang::ASTNodeImporter::VisitDependentSizedMatrixType( + const clang::DependentSizedMatrixType *T) { + Error Err = Error::success(); + QualType ToElementType = importChecked(Err, T->getElementType()); + Expr *ToRowExpr = importChecked(Err, T->getRowExpr()); + Expr *ToColumnExpr = importChecked(Err, T->getColumnExpr()); + SourceLocation ToAttrLoc = importChecked(Err, T->getAttributeLoc()); + if (Err) + return std::move(Err); + + return Importer.getToContext().getDependentSizedMatrixType( + ToElementType, ToRowExpr, ToColumnExpr, ToAttrLoc); +} + +ExpectedType clang::ASTNodeImporter::VisitDependentVectorType( + const clang::DependentVectorType *T) { + Error Err = Error::success(); + QualType ToElementType = importChecked(Err, T->getElementType()); + Expr *ToSizeExpr = importChecked(Err, T->getSizeExpr()); + SourceLocation ToAttrLoc = importChecked(Err, T->getAttributeLoc()); + if (Err) + return std::move(Err); + + return Importer.getToContext().getDependentVectorType( + ToElementType, ToSizeExpr, ToAttrLoc, T->getVectorKind()); +} + +ExpectedType clang::ASTNodeImporter::VisitObjCTypeParamType( + const clang::ObjCTypeParamType *T) { + Expected<ObjCTypeParamDecl *> ToDeclOrErr = import(T->getDecl()); + if (!ToDeclOrErr) + return ToDeclOrErr.takeError(); + + SmallVector<ObjCProtocolDecl *, 4> ToProtocols; + for (ObjCProtocolDecl *FromProtocol : T->getProtocols()) { + Expected<ObjCProtocolDecl *> ToProtocolOrErr = import(FromProtocol); + if (!ToProtocolOrErr) + return ToProtocolOrErr.takeError(); + ToProtocols.push_back(*ToProtocolOrErr); + } + + return Importer.getToContext().getObjCTypeParamType(*ToDeclOrErr, + ToProtocols); +} + +ExpectedType clang::ASTNodeImporter::VisitPipeType(const clang::PipeType *T) { + ExpectedType ToElementTypeOrErr = import(T->getElementType()); + if (!ToElementTypeOrErr) + return ToElementTypeOrErr.takeError(); + + ASTContext &ToCtx = Importer.getToContext(); + if (T->isReadOnly()) + return ToCtx.getReadPipeType(*ToElementTypeOrErr); + else + return ToCtx.getWritePipeType(*ToElementTypeOrErr); +} + //---------------------------------------------------------------------------- // Import Declarations //---------------------------------------------------------------------------- @@ -1655,7 +1850,7 @@ Error ASTNodeImporter::ImportDeclParts( if (RT && RT->getDecl() == D) { Importer.FromDiag(D->getLocation(), diag::err_unsupported_ast_node) << D->getDeclKindName(); - return make_error<ImportError>(ImportError::UnsupportedConstruct); + return make_error<ASTImportError>(ASTImportError::UnsupportedConstruct); } } } @@ -1788,60 +1983,35 @@ ASTNodeImporter::ImportDeclContext(DeclContext *FromDC, bool ForceImport) { // because there is an ODR error with two typedefs. As another example, // the client may allow EnumConstantDecls with same names but with // different values in two distinct translation units. - bool AccumulateChildErrors = isa<TagDecl>(FromDC); + ChildErrorHandlingStrategy HandleChildErrors(FromDC); + + auto MightNeedReordering = [](const Decl *D) { + return isa<FieldDecl>(D) || isa<IndirectFieldDecl>(D) || isa<FriendDecl>(D); + }; + // Import everything that might need reordering first. Error ChildErrors = Error::success(); for (auto *From : FromDC->decls()) { + if (!MightNeedReordering(From)) + continue; + ExpectedDecl ImportedOrErr = import(From); // If we are in the process of ImportDefinition(...) for a RecordDecl we // want to make sure that we are also completing each FieldDecl. There // are currently cases where this does not happen and this is correctness // fix since operations such as code generation will expect this to be so. - if (ImportedOrErr) { - FieldDecl *FieldFrom = dyn_cast_or_null<FieldDecl>(From); - Decl *ImportedDecl = *ImportedOrErr; - FieldDecl *FieldTo = dyn_cast_or_null<FieldDecl>(ImportedDecl); - if (FieldFrom && FieldTo) { - RecordDecl *FromRecordDecl = nullptr; - RecordDecl *ToRecordDecl = nullptr; - // If we have a field that is an ArrayType we need to check if the array - // element is a RecordDecl and if so we need to import the defintion. - if (FieldFrom->getType()->isArrayType()) { - // getBaseElementTypeUnsafe(...) handles multi-dimensonal arrays for us. - FromRecordDecl = FieldFrom->getType()->getBaseElementTypeUnsafe()->getAsRecordDecl(); - ToRecordDecl = FieldTo->getType()->getBaseElementTypeUnsafe()->getAsRecordDecl(); - } - - if (!FromRecordDecl || !ToRecordDecl) { - const RecordType *RecordFrom = - FieldFrom->getType()->getAs<RecordType>(); - const RecordType *RecordTo = FieldTo->getType()->getAs<RecordType>(); - - if (RecordFrom && RecordTo) { - FromRecordDecl = RecordFrom->getDecl(); - ToRecordDecl = RecordTo->getDecl(); - } - } - - if (FromRecordDecl && ToRecordDecl) { - if (FromRecordDecl->isCompleteDefinition() && - !ToRecordDecl->isCompleteDefinition()) { - Error Err = ImportDefinition(FromRecordDecl, ToRecordDecl); - - if (Err && AccumulateChildErrors) - ChildErrors = joinErrors(std::move(ChildErrors), std::move(Err)); - else - consumeError(std::move(Err)); - } - } - } - } else { - if (AccumulateChildErrors) - ChildErrors = - joinErrors(std::move(ChildErrors), ImportedOrErr.takeError()); - else - consumeError(ImportedOrErr.takeError()); + if (!ImportedOrErr) { + HandleChildErrors.handleChildImportResult(ChildErrors, + ImportedOrErr.takeError()); + continue; + } + FieldDecl *FieldFrom = dyn_cast_or_null<FieldDecl>(From); + Decl *ImportedDecl = *ImportedOrErr; + FieldDecl *FieldTo = dyn_cast_or_null<FieldDecl>(ImportedDecl); + if (FieldFrom && FieldTo) { + Error Err = ImportFieldDeclDefinition(FieldFrom, FieldTo); + HandleChildErrors.handleChildImportResult(ChildErrors, std::move(Err)); } } @@ -1856,7 +2026,7 @@ ASTNodeImporter::ImportDeclContext(DeclContext *FromDC, bool ForceImport) { // During the import of `a` we import first the dependencies in sequence, // thus the order would be `c`, `b`, `a`. We will get the normal order by // first removing the already imported members and then adding them in the - // order as they apper in the "from" context. + // order as they appear in the "from" context. // // Keeping field order is vital because it determines structure layout. // @@ -1868,9 +2038,6 @@ ASTNodeImporter::ImportDeclContext(DeclContext *FromDC, bool ForceImport) { // interface in LLDB is implemented by the means of the ASTImporter. However, // calling an import at this point would result in an uncontrolled import, we // must avoid that. - const auto *FromRD = dyn_cast<RecordDecl>(FromDC); - if (!FromRD) - return ChildErrors; auto ToDCOrErr = Importer.ImportContext(FromDC); if (!ToDCOrErr) { @@ -1878,15 +2045,17 @@ ASTNodeImporter::ImportDeclContext(DeclContext *FromDC, bool ForceImport) { return ToDCOrErr.takeError(); } - DeclContext *ToDC = *ToDCOrErr; - // Remove all declarations, which may be in wrong order in the - // lexical DeclContext and then add them in the proper order. - for (auto *D : FromRD->decls()) { - if (isa<FieldDecl>(D) || isa<IndirectFieldDecl>(D) || isa<FriendDecl>(D)) { + if (const auto *FromRD = dyn_cast<RecordDecl>(FromDC)) { + DeclContext *ToDC = *ToDCOrErr; + // Remove all declarations, which may be in wrong order in the + // lexical DeclContext and then add them in the proper order. + for (auto *D : FromRD->decls()) { + if (!MightNeedReordering(D)) + continue; + assert(D && "DC contains a null decl"); - Decl *ToD = Importer.GetAlreadyImportedOrNull(D); - // Remove only the decls which we successfully imported. - if (ToD) { + if (Decl *ToD = Importer.GetAlreadyImportedOrNull(D)) { + // Remove only the decls which we successfully imported. assert(ToDC == ToD->getLexicalDeclContext() && ToDC->containsDecl(ToD)); // Remove the decl from its wrong place in the linked list. ToDC->removeDecl(ToD); @@ -1898,9 +2067,53 @@ ASTNodeImporter::ImportDeclContext(DeclContext *FromDC, bool ForceImport) { } } + // Import everything else. + for (auto *From : FromDC->decls()) { + if (MightNeedReordering(From)) + continue; + + ExpectedDecl ImportedOrErr = import(From); + if (!ImportedOrErr) + HandleChildErrors.handleChildImportResult(ChildErrors, + ImportedOrErr.takeError()); + } + return ChildErrors; } +Error ASTNodeImporter::ImportFieldDeclDefinition(const FieldDecl *From, + const FieldDecl *To) { + RecordDecl *FromRecordDecl = nullptr; + RecordDecl *ToRecordDecl = nullptr; + // If we have a field that is an ArrayType we need to check if the array + // element is a RecordDecl and if so we need to import the definition. + QualType FromType = From->getType(); + QualType ToType = To->getType(); + if (FromType->isArrayType()) { + // getBaseElementTypeUnsafe(...) handles multi-dimensonal arrays for us. + FromRecordDecl = FromType->getBaseElementTypeUnsafe()->getAsRecordDecl(); + ToRecordDecl = ToType->getBaseElementTypeUnsafe()->getAsRecordDecl(); + } + + if (!FromRecordDecl || !ToRecordDecl) { + const RecordType *RecordFrom = FromType->getAs<RecordType>(); + const RecordType *RecordTo = ToType->getAs<RecordType>(); + + if (RecordFrom && RecordTo) { + FromRecordDecl = RecordFrom->getDecl(); + ToRecordDecl = RecordTo->getDecl(); + } + } + + if (FromRecordDecl && ToRecordDecl) { + if (FromRecordDecl->isCompleteDefinition() && + !ToRecordDecl->isCompleteDefinition()) + return ImportDefinition(FromRecordDecl, ToRecordDecl); + } + + return Error::success(); +} + Error ASTNodeImporter::ImportDeclContext( Decl *FromD, DeclContext *&ToDC, DeclContext *&ToLexicalDC) { auto ToDCOrErr = Importer.ImportContext(FromD->getDeclContext()); @@ -1991,6 +2204,14 @@ Error ASTNodeImporter::ImportDefinition( } To->startDefinition(); + // Set the definition to complete even if it is really not complete during + // import. Some AST constructs (expressions) require the record layout + // to be calculated (see 'clang::computeDependence') at the time they are + // constructed. Import of such AST node is possible during import of the + // same record, there is no way to have a completely defined record (all + // fields imported) at that time without multiple AST import passes. + if (!Importer.isMinimalImport()) + To->setCompleteDefinition(true); // Complete the definition even if error is returned. // The RecordDecl may be already part of the AST so it is better to // have it in complete state even if something is wrong with it. @@ -2055,9 +2276,10 @@ Error ASTNodeImporter::ImportDefinition( ToCXX->setBases(Bases.data(), Bases.size()); } - if (shouldForceImportDeclContext(Kind)) + if (shouldForceImportDeclContext(Kind)) { if (Error Err = ImportDeclContext(From, /*ForceImport=*/true)) return Err; + } return Error::success(); } @@ -2121,10 +2343,10 @@ Error ASTNodeImporter::ImportDefinition( } Error ASTNodeImporter::ImportTemplateArguments( - const TemplateArgument *FromArgs, unsigned NumFromArgs, + ArrayRef<TemplateArgument> FromArgs, SmallVectorImpl<TemplateArgument> &ToArgs) { - for (unsigned I = 0; I != NumFromArgs; ++I) { - if (auto ToOrErr = import(FromArgs[I])) + for (const auto &Arg : FromArgs) { + if (auto ToOrErr = import(Arg)) ToArgs.push_back(*ToOrErr); else return ToOrErr.takeError(); @@ -2157,110 +2379,33 @@ getStructuralEquivalenceKind(const ASTImporter &Importer) { : StructuralEquivalenceKind::Default; } -bool ASTNodeImporter::IsStructuralMatch(Decl *From, Decl *To, bool Complain) { - StructuralEquivalenceContext Ctx( - Importer.getFromContext(), Importer.getToContext(), - Importer.getNonEquivalentDecls(), getStructuralEquivalenceKind(Importer), - false, Complain); - return Ctx.IsEquivalent(From, To); -} - -bool ASTNodeImporter::IsStructuralMatch(RecordDecl *FromRecord, - RecordDecl *ToRecord, bool Complain) { +bool ASTNodeImporter::IsStructuralMatch(Decl *From, Decl *To, bool Complain, + bool IgnoreTemplateParmDepth) { // Eliminate a potential failure point where we attempt to re-import // something we're trying to import while completing ToRecord. - Decl *ToOrigin = Importer.GetOriginalDecl(ToRecord); + Decl *ToOrigin = Importer.GetOriginalDecl(To); if (ToOrigin) { - auto *ToOriginRecord = dyn_cast<RecordDecl>(ToOrigin); - if (ToOriginRecord) - ToRecord = ToOriginRecord; + To = ToOrigin; } - StructuralEquivalenceContext Ctx(Importer.getFromContext(), - ToRecord->getASTContext(), - Importer.getNonEquivalentDecls(), - getStructuralEquivalenceKind(Importer), - false, Complain); - return Ctx.IsEquivalent(FromRecord, ToRecord); -} - -bool ASTNodeImporter::IsStructuralMatch(VarDecl *FromVar, VarDecl *ToVar, - bool Complain) { - StructuralEquivalenceContext Ctx( - Importer.getFromContext(), Importer.getToContext(), - Importer.getNonEquivalentDecls(), getStructuralEquivalenceKind(Importer), - false, Complain); - return Ctx.IsEquivalent(FromVar, ToVar); -} - -bool ASTNodeImporter::IsStructuralMatch(EnumDecl *FromEnum, EnumDecl *ToEnum) { - // Eliminate a potential failure point where we attempt to re-import - // something we're trying to import while completing ToEnum. - if (Decl *ToOrigin = Importer.GetOriginalDecl(ToEnum)) - if (auto *ToOriginEnum = dyn_cast<EnumDecl>(ToOrigin)) - ToEnum = ToOriginEnum; - - StructuralEquivalenceContext Ctx( - Importer.getFromContext(), Importer.getToContext(), - Importer.getNonEquivalentDecls(), getStructuralEquivalenceKind(Importer)); - return Ctx.IsEquivalent(FromEnum, ToEnum); -} - -bool ASTNodeImporter::IsStructuralMatch(FunctionTemplateDecl *From, - FunctionTemplateDecl *To) { - StructuralEquivalenceContext Ctx( - Importer.getFromContext(), Importer.getToContext(), - Importer.getNonEquivalentDecls(), getStructuralEquivalenceKind(Importer), - false, false); - return Ctx.IsEquivalent(From, To); -} - -bool ASTNodeImporter::IsStructuralMatch(FunctionDecl *From, FunctionDecl *To) { StructuralEquivalenceContext Ctx( Importer.getFromContext(), Importer.getToContext(), Importer.getNonEquivalentDecls(), getStructuralEquivalenceKind(Importer), - false, false); - return Ctx.IsEquivalent(From, To); -} - -bool ASTNodeImporter::IsStructuralMatch(EnumConstantDecl *FromEC, - EnumConstantDecl *ToEC) { - const llvm::APSInt &FromVal = FromEC->getInitVal(); - const llvm::APSInt &ToVal = ToEC->getInitVal(); - - return FromVal.isSigned() == ToVal.isSigned() && - FromVal.getBitWidth() == ToVal.getBitWidth() && - FromVal == ToVal; -} - -bool ASTNodeImporter::IsStructuralMatch(ClassTemplateDecl *From, - ClassTemplateDecl *To) { - StructuralEquivalenceContext Ctx(Importer.getFromContext(), - Importer.getToContext(), - Importer.getNonEquivalentDecls(), - getStructuralEquivalenceKind(Importer)); - return Ctx.IsEquivalent(From, To); -} - -bool ASTNodeImporter::IsStructuralMatch(VarTemplateDecl *From, - VarTemplateDecl *To) { - StructuralEquivalenceContext Ctx(Importer.getFromContext(), - Importer.getToContext(), - Importer.getNonEquivalentDecls(), - getStructuralEquivalenceKind(Importer)); + /*StrictTypeSpelling=*/false, Complain, /*ErrorOnTagTypeMismatch=*/false, + IgnoreTemplateParmDepth); return Ctx.IsEquivalent(From, To); } ExpectedDecl ASTNodeImporter::VisitDecl(Decl *D) { Importer.FromDiag(D->getLocation(), diag::err_unsupported_ast_node) << D->getDeclKindName(); - return make_error<ImportError>(ImportError::UnsupportedConstruct); + return make_error<ASTImportError>(ASTImportError::UnsupportedConstruct); } ExpectedDecl ASTNodeImporter::VisitImportDecl(ImportDecl *D) { Importer.FromDiag(D->getLocation(), diag::err_unsupported_ast_node) << D->getDeclKindName(); - return make_error<ImportError>(ImportError::UnsupportedConstruct); + return make_error<ASTImportError>(ASTImportError::UnsupportedConstruct); } ExpectedDecl ASTNodeImporter::VisitEmptyDecl(EmptyDecl *D) { @@ -2431,10 +2576,10 @@ ExpectedDecl ASTNodeImporter::VisitNamespaceDecl(NamespaceDecl *D) { // Create the "to" namespace, if needed. NamespaceDecl *ToNamespace = MergeWithNamespace; if (!ToNamespace) { - if (GetImportedOrCreateDecl( - ToNamespace, D, Importer.getToContext(), DC, D->isInline(), - *BeginLocOrErr, Loc, Name.getAsIdentifierInfo(), - /*PrevDecl=*/nullptr)) + if (GetImportedOrCreateDecl(ToNamespace, D, Importer.getToContext(), DC, + D->isInline(), *BeginLocOrErr, Loc, + Name.getAsIdentifierInfo(), + /*PrevDecl=*/nullptr, D->isNested())) return ToNamespace; ToNamespace->setRBraceLoc(*RBraceLocOrErr); ToNamespace->setLexicalDeclContext(LexicalDC); @@ -2532,6 +2677,22 @@ ASTNodeImporter::VisitTypedefNameDecl(TypedefNameDecl *D, bool IsAlias) { QualType FromUT = D->getUnderlyingType(); QualType FoundUT = FoundTypedef->getUnderlyingType(); if (Importer.IsStructurallyEquivalent(FromUT, FoundUT)) { + // If the underlying declarations are unnamed records these can be + // imported as different types. We should create a distinct typedef + // node in this case. + // If we found an existing underlying type with a record in a + // different context (than the imported), this is already reason for + // having distinct typedef nodes for these. + // Again this can create situation like + // 'typedef int T; typedef int T;' but this is hard to avoid without + // a rename strategy at import. + if (!FromUT.isNull() && !FoundUT.isNull()) { + RecordDecl *FromR = FromUT->getAsRecordDecl(); + RecordDecl *FoundR = FoundUT->getAsRecordDecl(); + if (FromR && FoundR && + !hasSameVisibilityContextAndLinkage(FoundR, FromR)) + continue; + } // If the "From" context has a complete underlying type but we // already have a complete underlying type then return with that. if (!FromUT->isIncompleteType() && !FoundUT->isIncompleteType()) @@ -2623,9 +2784,11 @@ ASTNodeImporter::VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D) { for (auto *FoundDecl : FoundDecls) { if (!FoundDecl->isInIdentifierNamespace(IDNS)) continue; - if (auto *FoundAlias = dyn_cast<TypeAliasTemplateDecl>(FoundDecl)) - return Importer.MapImported(D, FoundAlias); - ConflictingDecls.push_back(FoundDecl); + if (auto *FoundAlias = dyn_cast<TypeAliasTemplateDecl>(FoundDecl)) { + if (IsStructuralMatch(D, FoundAlias)) + return Importer.MapImported(D, FoundAlias); + ConflictingDecls.push_back(FoundDecl); + } } if (!ConflictingDecls.empty()) { @@ -2834,9 +2997,13 @@ ExpectedDecl ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { } else if (Importer.getToContext().getLangOpts().CPlusPlus) IDNS |= Decl::IDNS_Ordinary | Decl::IDNS_TagFriend; + bool IsDependentContext = DC != LexicalDC ? LexicalDC->isDependentContext() + : DC->isDependentContext(); + bool DependentFriend = IsFriendTemplate && IsDependentContext; + // We may already have a record of the same name; try to find and match it. RecordDecl *PrevDecl = nullptr; - if (!DC->isFunctionOrMethod() && !D->isLambda()) { + if (!DependentFriend && !DC->isFunctionOrMethod() && !D->isLambda()) { SmallVector<NamedDecl *, 4> ConflictingDecls; auto FoundDecls = Importer.findDeclsInToCtx(DC, SearchName); @@ -2923,16 +3090,15 @@ ExpectedDecl ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { return TInfoOrErr.takeError(); if (GetImportedOrCreateSpecialDecl( D2CXX, CXXRecordDecl::CreateLambda, D, Importer.getToContext(), - DC, *TInfoOrErr, Loc, DCXX->isDependentLambda(), + DC, *TInfoOrErr, Loc, DCXX->getLambdaDependencyKind(), DCXX->isGenericLambda(), DCXX->getLambdaCaptureDefault())) return D2CXX; - ExpectedDecl CDeclOrErr = import(DCXX->getLambdaContextDecl()); + CXXRecordDecl::LambdaNumbering Numbering = DCXX->getLambdaNumbering(); + ExpectedDecl CDeclOrErr = import(Numbering.ContextDecl); if (!CDeclOrErr) return CDeclOrErr.takeError(); - D2CXX->setLambdaMangling(DCXX->getLambdaManglingNumber(), *CDeclOrErr, - DCXX->hasKnownLambdaInternalLinkage()); - D2CXX->setDeviceLambdaManglingNumber( - DCXX->getDeviceLambdaManglingNumber()); + Numbering.ContextDecl = *CDeclOrErr; + D2CXX->setLambdaNumbering(Numbering); } else if (DCXX->isInjectedClassName()) { // We have to be careful to do a similar dance to the one in // Sema::ActOnStartCXXMemberDeclarations @@ -2968,8 +3134,6 @@ ExpectedDecl ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { // InjectedClassNameType (see Sema::CheckClassTemplate). Update the // previously set type to the correct value here (ToDescribed is not // available at record create). - // FIXME: The previous type is cleared but not removed from - // ASTContext's internal storage. CXXRecordDecl *Injected = nullptr; for (NamedDecl *Found : D2CXX->noload_lookup(Name)) { auto *Record = dyn_cast<CXXRecordDecl>(Found); @@ -2979,20 +3143,34 @@ ExpectedDecl ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { } } // Create an injected type for the whole redecl chain. + // The chain may contain an already existing injected type at the start, + // if yes this should be reused. We must ensure that only one type + // object exists for the injected type (including the injected record + // declaration), ASTContext does not check it. SmallVector<Decl *, 2> Redecls = getCanonicalForwardRedeclChain(D2CXX); + const Type *FrontTy = + cast<CXXRecordDecl>(Redecls.front())->getTypeForDecl(); + QualType InjSpec; + if (auto *InjTy = FrontTy->getAs<InjectedClassNameType>()) + InjSpec = InjTy->getInjectedSpecializationType(); + else + InjSpec = ToDescribed->getInjectedClassNameSpecialization(); for (auto *R : Redecls) { auto *RI = cast<CXXRecordDecl>(R); - RI->setTypeForDecl(nullptr); - // Below we create a new injected type and assign that to the - // canonical decl, subsequent declarations in the chain will reuse - // that type. - Importer.getToContext().getInjectedClassNameType( - RI, ToDescribed->getInjectedClassNameSpecialization()); + if (R != Redecls.front() || + !isa<InjectedClassNameType>(RI->getTypeForDecl())) + RI->setTypeForDecl(nullptr); + // This function tries to get the injected type from getTypeForDecl, + // then from the previous declaration if possible. If not, it creates + // a new type. + Importer.getToContext().getInjectedClassNameType(RI, InjSpec); } - // Set the new type for the previous injected decl too. + // Set the new type for the injected decl too. if (Injected) { Injected->setTypeForDecl(nullptr); + // This function will copy the injected type from D2CXX into Injected. + // The injected decl does not have a previous decl to copy from. Importer.getToContext().getTypeDeclType(Injected, D2CXX); } } @@ -3124,6 +3302,11 @@ Error ASTNodeImporter::ImportTemplateInformation( case FunctionDecl::TK_FunctionTemplate: return Error::success(); + case FunctionDecl::TK_DependentNonTemplate: + if (Expected<FunctionDecl *> InstFDOrErr = + import(FromFD->getInstantiatedFromDecl())) + ToFD->setInstantiatedFromDecl(*InstFDOrErr); + return Error::success(); case FunctionDecl::TK_MemberSpecialization: { TemplateSpecializationKind TSK = FromFD->getTemplateSpecializationKind(); @@ -3175,27 +3358,25 @@ Error ASTNodeImporter::ImportTemplateInformation( case FunctionDecl::TK_DependentFunctionTemplateSpecialization: { auto *FromInfo = FromFD->getDependentSpecializationInfo(); - UnresolvedSet<8> TemplDecls; - unsigned NumTemplates = FromInfo->getNumTemplates(); - for (unsigned I = 0; I < NumTemplates; I++) { - if (Expected<FunctionTemplateDecl *> ToFTDOrErr = - import(FromInfo->getTemplate(I))) - TemplDecls.addDecl(*ToFTDOrErr); + UnresolvedSet<8> Candidates; + for (FunctionTemplateDecl *FTD : FromInfo->getCandidates()) { + if (Expected<FunctionTemplateDecl *> ToFTDOrErr = import(FTD)) + Candidates.addDecl(*ToFTDOrErr); else return ToFTDOrErr.takeError(); } // Import TemplateArgumentListInfo. TemplateArgumentListInfo ToTAInfo; - if (Error Err = ImportTemplateArgumentListInfo( - FromInfo->getLAngleLoc(), FromInfo->getRAngleLoc(), - llvm::makeArrayRef( - FromInfo->getTemplateArgs(), FromInfo->getNumTemplateArgs()), - ToTAInfo)) - return Err; + const auto *FromTAArgsAsWritten = FromInfo->TemplateArgumentsAsWritten; + if (FromTAArgsAsWritten) + if (Error Err = + ImportTemplateArgumentListInfo(*FromTAArgsAsWritten, ToTAInfo)) + return Err; - ToFD->setDependentTemplateSpecialization(Importer.getToContext(), - TemplDecls, ToTAInfo); + ToFD->setDependentTemplateSpecialization( + Importer.getToContext(), Candidates, + FromTAArgsAsWritten ? &ToTAInfo : nullptr); return Error::success(); } } @@ -3229,9 +3410,12 @@ Error ASTNodeImporter::ImportFunctionDeclBody(FunctionDecl *FromFD, } // Returns true if the given D has a DeclContext up to the TranslationUnitDecl -// which is equal to the given DC. +// which is equal to the given DC, or D is equal to DC. static bool isAncestorDeclContextOf(const DeclContext *DC, const Decl *D) { - const DeclContext *DCi = D->getDeclContext(); + const DeclContext *DCi = dyn_cast<DeclContext>(D); + if (!DCi) + DCi = D->getDeclContext(); + assert(DCi && "Declaration should have a context"); while (DCi != D->getTranslationUnitDecl()) { if (DCi == DC) return true; @@ -3240,31 +3424,200 @@ static bool isAncestorDeclContextOf(const DeclContext *DC, const Decl *D) { return false; } -bool ASTNodeImporter::hasAutoReturnTypeDeclaredInside(FunctionDecl *D) { - QualType FromTy = D->getType(); - const FunctionProtoType *FromFPT = FromTy->getAs<FunctionProtoType>(); - assert(FromFPT && "Must be called on FunctionProtoType"); - if (AutoType *AutoT = FromFPT->getReturnType()->getContainedAutoType()) { - QualType DeducedT = AutoT->getDeducedType(); - if (const RecordType *RecordT = - DeducedT.isNull() ? nullptr : dyn_cast<RecordType>(DeducedT)) { - RecordDecl *RD = RecordT->getDecl(); - assert(RD); - if (isAncestorDeclContextOf(D, RD)) { - assert(RD->getLexicalDeclContext() == RD->getDeclContext()); - return true; - } +// Check if there is a declaration that has 'DC' as parent context and is +// referenced from statement 'S' or one of its children. The search is done in +// BFS order through children of 'S'. +static bool isAncestorDeclContextOf(const DeclContext *DC, const Stmt *S) { + SmallVector<const Stmt *> ToProcess; + ToProcess.push_back(S); + while (!ToProcess.empty()) { + const Stmt *CurrentS = ToProcess.pop_back_val(); + ToProcess.append(CurrentS->child_begin(), CurrentS->child_end()); + if (const auto *DeclRef = dyn_cast<DeclRefExpr>(CurrentS)) { + if (const Decl *D = DeclRef->getDecl()) + if (isAncestorDeclContextOf(DC, D)) + return true; + } else if (const auto *E = + dyn_cast_or_null<SubstNonTypeTemplateParmExpr>(CurrentS)) { + if (const Decl *D = E->getAssociatedDecl()) + if (isAncestorDeclContextOf(DC, D)) + return true; } } - if (const TypedefType *TypedefT = - dyn_cast<TypedefType>(FromFPT->getReturnType())) { - TypedefNameDecl *TD = TypedefT->getDecl(); + return false; +} + +namespace { +/// Check if a type has any reference to a declaration that is inside the body +/// of a function. +/// The \c CheckType(QualType) function should be used to determine +/// this property. +/// +/// The type visitor visits one type object only (not recursive). +/// To find all referenced declarations we must discover all type objects until +/// the canonical type is reached (walk over typedef and similar objects). This +/// is done by loop over all "sugar" type objects. For every such type we must +/// check all declarations that are referenced from it. For this check the +/// visitor is used. In the visit functions all referenced declarations except +/// the one that follows in the sugar chain (if any) must be checked. For this +/// check the same visitor is re-used (it has no state-dependent data). +/// +/// The visit functions have 3 possible return values: +/// - True, found a declaration inside \c ParentDC. +/// - False, found declarations only outside \c ParentDC and it is not possible +/// to find more declarations (the "sugar" chain does not continue). +/// - Empty optional value, found no declarations or only outside \c ParentDC, +/// but it is possible to find more declarations in the type "sugar" chain. +/// The loop over the "sugar" types can be implemented by using type visit +/// functions only (call \c CheckType with the desugared type). With the current +/// solution no visit function is needed if the type has only a desugared type +/// as data. +class IsTypeDeclaredInsideVisitor + : public TypeVisitor<IsTypeDeclaredInsideVisitor, std::optional<bool>> { +public: + IsTypeDeclaredInsideVisitor(const FunctionDecl *ParentDC) + : ParentDC(ParentDC) {} + + bool CheckType(QualType T) { + // Check the chain of "sugar" types. + // The "sugar" types are typedef or similar types that have the same + // canonical type. + if (std::optional<bool> Res = Visit(T.getTypePtr())) + return *Res; + QualType DsT = + T.getSingleStepDesugaredType(ParentDC->getParentASTContext()); + while (DsT != T) { + if (std::optional<bool> Res = Visit(DsT.getTypePtr())) + return *Res; + T = DsT; + DsT = T.getSingleStepDesugaredType(ParentDC->getParentASTContext()); + } + return false; + } + + std::optional<bool> VisitTagType(const TagType *T) { + if (auto *Spec = dyn_cast<ClassTemplateSpecializationDecl>(T->getDecl())) + for (const auto &Arg : Spec->getTemplateArgs().asArray()) + if (checkTemplateArgument(Arg)) + return true; + return isAncestorDeclContextOf(ParentDC, T->getDecl()); + } + + std::optional<bool> VisitPointerType(const PointerType *T) { + return CheckType(T->getPointeeType()); + } + + std::optional<bool> VisitReferenceType(const ReferenceType *T) { + return CheckType(T->getPointeeTypeAsWritten()); + } + + std::optional<bool> VisitTypedefType(const TypedefType *T) { + const TypedefNameDecl *TD = T->getDecl(); assert(TD); - if (isAncestorDeclContextOf(D, TD)) { - assert(TD->getLexicalDeclContext() == TD->getDeclContext()); + return isAncestorDeclContextOf(ParentDC, TD); + } + + std::optional<bool> VisitUsingType(const UsingType *T) { + if (T->getFoundDecl() && + isAncestorDeclContextOf(ParentDC, T->getFoundDecl())) return true; + + return {}; + } + + std::optional<bool> + VisitTemplateSpecializationType(const TemplateSpecializationType *T) { + for (const auto &Arg : T->template_arguments()) + if (checkTemplateArgument(Arg)) + return true; + // This type is a "sugar" to a record type, it can have a desugared type. + return {}; + } + + std::optional<bool> + VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *T) { + // The "associated declaration" can be the same as ParentDC. + if (isAncestorDeclContextOf(ParentDC, T->getAssociatedDecl())) + return true; + return {}; + } + + std::optional<bool> VisitConstantArrayType(const ConstantArrayType *T) { + if (T->getSizeExpr() && isAncestorDeclContextOf(ParentDC, T->getSizeExpr())) + return true; + + return CheckType(T->getElementType()); + } + + std::optional<bool> VisitVariableArrayType(const VariableArrayType *T) { + llvm_unreachable( + "Variable array should not occur in deduced return type of a function"); + } + + std::optional<bool> VisitIncompleteArrayType(const IncompleteArrayType *T) { + llvm_unreachable("Incomplete array should not occur in deduced return type " + "of a function"); + } + + std::optional<bool> VisitDependentArrayType(const IncompleteArrayType *T) { + llvm_unreachable("Dependent array should not occur in deduced return type " + "of a function"); + } + +private: + const DeclContext *const ParentDC; + + bool checkTemplateArgument(const TemplateArgument &Arg) { + switch (Arg.getKind()) { + case TemplateArgument::Null: + return false; + case TemplateArgument::Integral: + return CheckType(Arg.getIntegralType()); + case TemplateArgument::Type: + return CheckType(Arg.getAsType()); + case TemplateArgument::Expression: + return isAncestorDeclContextOf(ParentDC, Arg.getAsExpr()); + case TemplateArgument::Declaration: + // FIXME: The declaration in this case is not allowed to be in a function? + return isAncestorDeclContextOf(ParentDC, Arg.getAsDecl()); + case TemplateArgument::NullPtr: + // FIXME: The type is not allowed to be in the function? + return CheckType(Arg.getNullPtrType()); + case TemplateArgument::StructuralValue: + return CheckType(Arg.getStructuralValueType()); + case TemplateArgument::Pack: + for (const auto &PackArg : Arg.getPackAsArray()) + if (checkTemplateArgument(PackArg)) + return true; + return false; + case TemplateArgument::Template: + // Templates can not be defined locally in functions. + // A template passed as argument can be not in ParentDC. + return false; + case TemplateArgument::TemplateExpansion: + // Templates can not be defined locally in functions. + // A template passed as argument can be not in ParentDC. + return false; } + llvm_unreachable("Unknown TemplateArgument::ArgKind enum"); + }; +}; +} // namespace + +/// This function checks if the function has 'auto' return type that contains +/// a reference (in any way) to a declaration inside the same function. +bool ASTNodeImporter::hasAutoReturnTypeDeclaredInside(FunctionDecl *D) { + QualType FromTy = D->getType(); + const auto *FromFPT = FromTy->getAs<FunctionProtoType>(); + assert(FromFPT && "Must be called on FunctionProtoType"); + + QualType RetT = FromFPT->getReturnType(); + if (isa<AutoType>(RetT.getTypePtr())) { + FunctionDecl *Def = D->getDefinition(); + IsTypeDeclaredInsideVisitor Visitor(Def ? Def : D); + return Visitor.CheckType(RetT); } + return false; } @@ -3399,11 +3752,14 @@ ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { return std::move(Err); QualType FromTy = D->getType(); + TypeSourceInfo *FromTSI = D->getTypeSourceInfo(); // Set to true if we do not import the type of the function as is. There are // cases when the original type would result in an infinite recursion during // the import. To avoid an infinite recursion when importing, we create the // FunctionDecl with a simplified function type and update it only after the // relevant AST nodes are already imported. + // The type is related to TypeSourceInfo (it references the type), so we must + // do the same with TypeSourceInfo. bool UsedDifferentProtoType = false; if (const auto *FromFPT = FromTy->getAs<FunctionProtoType>()) { QualType FromReturnTy = FromFPT->getReturnType(); @@ -3430,13 +3786,16 @@ ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { } FromTy = Importer.getFromContext().getFunctionType( FromReturnTy, FromFPT->getParamTypes(), FromEPI); + FromTSI = Importer.getFromContext().getTrivialTypeSourceInfo( + FromTy, D->getBeginLoc()); } Error Err = Error::success(); auto T = importChecked(Err, FromTy); - auto TInfo = importChecked(Err, D->getTypeSourceInfo()); + auto TInfo = importChecked(Err, FromTSI); auto ToInnerLocStart = importChecked(Err, D->getInnerLocStart()); auto ToEndLoc = importChecked(Err, D->getEndLoc()); + auto ToDefaultLoc = importChecked(Err, D->getDefaultLoc()); auto ToQualifierLoc = importChecked(Err, D->getQualifierLoc()); auto TrailingRequiresClause = importChecked(Err, D->getTrailingRequiresClause()); @@ -3445,7 +3804,7 @@ ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { // Import the function parameters. SmallVector<ParmVarDecl *, 8> Parameters; - for (auto P : D->parameters()) { + for (auto *P : D->parameters()) { if (Expected<ParmVarDecl *> ToPOrErr = import(P)) Parameters.push_back(*ToPOrErr); else @@ -3459,13 +3818,19 @@ ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { importExplicitSpecifier(Err, FromConstructor->getExplicitSpecifier()); if (Err) return std::move(Err); + auto ToInheritedConstructor = InheritedConstructor(); + if (FromConstructor->isInheritingConstructor()) { + Expected<InheritedConstructor> ImportedInheritedCtor = + import(FromConstructor->getInheritedConstructor()); + if (!ImportedInheritedCtor) + return ImportedInheritedCtor.takeError(); + ToInheritedConstructor = *ImportedInheritedCtor; + } if (GetImportedOrCreateDecl<CXXConstructorDecl>( ToFunction, D, Importer.getToContext(), cast<CXXRecordDecl>(DC), - ToInnerLocStart, NameInfo, T, TInfo, ESpec, D->isInlineSpecified(), - D->isImplicit(), D->getConstexprKind(), - InheritedConstructor(), // FIXME: Properly import inherited - // constructor info - TrailingRequiresClause)) + ToInnerLocStart, NameInfo, T, TInfo, ESpec, D->UsesFPIntrin(), + D->isInlineSpecified(), D->isImplicit(), D->getConstexprKind(), + ToInheritedConstructor, TrailingRequiresClause)) return ToFunction; } else if (CXXDestructorDecl *FromDtor = dyn_cast<CXXDestructorDecl>(D)) { @@ -3477,9 +3842,10 @@ ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { return std::move(Err); if (GetImportedOrCreateDecl<CXXDestructorDecl>( - ToFunction, D, Importer.getToContext(), cast<CXXRecordDecl>(DC), - ToInnerLocStart, NameInfo, T, TInfo, D->isInlineSpecified(), - D->isImplicit(), D->getConstexprKind(), TrailingRequiresClause)) + ToFunction, D, Importer.getToContext(), cast<CXXRecordDecl>(DC), + ToInnerLocStart, NameInfo, T, TInfo, D->UsesFPIntrin(), + D->isInlineSpecified(), D->isImplicit(), D->getConstexprKind(), + TrailingRequiresClause)) return ToFunction; CXXDestructorDecl *ToDtor = cast<CXXDestructorDecl>(ToFunction); @@ -3493,15 +3859,16 @@ ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { return std::move(Err); if (GetImportedOrCreateDecl<CXXConversionDecl>( ToFunction, D, Importer.getToContext(), cast<CXXRecordDecl>(DC), - ToInnerLocStart, NameInfo, T, TInfo, D->isInlineSpecified(), ESpec, - D->getConstexprKind(), SourceLocation(), TrailingRequiresClause)) + ToInnerLocStart, NameInfo, T, TInfo, D->UsesFPIntrin(), + D->isInlineSpecified(), ESpec, D->getConstexprKind(), + SourceLocation(), TrailingRequiresClause)) return ToFunction; } else if (auto *Method = dyn_cast<CXXMethodDecl>(D)) { if (GetImportedOrCreateDecl<CXXMethodDecl>( ToFunction, D, Importer.getToContext(), cast<CXXRecordDecl>(DC), ToInnerLocStart, NameInfo, T, TInfo, Method->getStorageClass(), - Method->isInlineSpecified(), D->getConstexprKind(), - SourceLocation(), TrailingRequiresClause)) + Method->UsesFPIntrin(), Method->isInlineSpecified(), + D->getConstexprKind(), SourceLocation(), TrailingRequiresClause)) return ToFunction; } else if (auto *Guide = dyn_cast<CXXDeductionGuideDecl>(D)) { ExplicitSpecifier ESpec = @@ -3515,13 +3882,13 @@ ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { NameInfo, T, TInfo, ToEndLoc, Ctor)) return ToFunction; cast<CXXDeductionGuideDecl>(ToFunction) - ->setIsCopyDeductionCandidate(Guide->isCopyDeductionCandidate()); + ->setDeductionCandidateKind(Guide->getDeductionCandidateKind()); } else { if (GetImportedOrCreateDecl( ToFunction, D, Importer.getToContext(), DC, ToInnerLocStart, - NameInfo, T, TInfo, D->getStorageClass(), D->isInlineSpecified(), - D->hasWrittenPrototype(), D->getConstexprKind(), - TrailingRequiresClause)) + NameInfo, T, TInfo, D->getStorageClass(), D->UsesFPIntrin(), + D->isInlineSpecified(), D->hasWrittenPrototype(), + D->getConstexprKind(), TrailingRequiresClause)) return ToFunction; } @@ -3542,11 +3909,14 @@ ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { ToFunction->setLexicalDeclContext(LexicalDC); ToFunction->setVirtualAsWritten(D->isVirtualAsWritten()); ToFunction->setTrivial(D->isTrivial()); - ToFunction->setPure(D->isPure()); + ToFunction->setIsPureVirtual(D->isPureVirtual()); ToFunction->setDefaulted(D->isDefaulted()); ToFunction->setExplicitlyDefaulted(D->isExplicitlyDefaulted()); ToFunction->setDeletedAsWritten(D->isDeletedAsWritten()); + ToFunction->setFriendConstraintRefersToEnclosingTemplate( + D->FriendConstraintRefersToEnclosingTemplate()); ToFunction->setRangeEnd(ToEndLoc); + ToFunction->setDefaultLoc(ToDefaultLoc); // Set the parameters. for (auto *Param : Parameters) { @@ -3591,6 +3961,15 @@ ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { } } + // If it is a template, import all related things. + if (Error Err = ImportTemplateInformation(D, ToFunction)) + return std::move(Err); + + if (auto *FromCXXMethod = dyn_cast<CXXMethodDecl>(D)) + if (Error Err = ImportOverriddenMethods(cast<CXXMethodDecl>(ToFunction), + FromCXXMethod)) + return std::move(Err); + if (D->doesThisDeclarationHaveABody()) { Error Err = ImportFunctionDeclBody(D, ToFunction); @@ -3604,21 +3983,16 @@ ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { ToFunction->setType(*TyOrErr); else return TyOrErr.takeError(); + if (Expected<TypeSourceInfo *> TSIOrErr = import(D->getTypeSourceInfo())) + ToFunction->setTypeSourceInfo(*TSIOrErr); + else + return TSIOrErr.takeError(); } // FIXME: Other bits to merge? - // If it is a template, import all related things. - if (Error Err = ImportTemplateInformation(D, ToFunction)) - return std::move(Err); - addDeclToContexts(D, ToFunction); - if (auto *FromCXXMethod = dyn_cast<CXXMethodDecl>(D)) - if (Error Err = ImportOverriddenMethods(cast<CXXMethodDecl>(ToFunction), - FromCXXMethod)) - return std::move(Err); - // Import the rest of the chain. I.e. import all subsequent declarations. for (++RedeclIt; RedeclIt != Redecls.end(); ++RedeclIt) { ExpectedDecl ToRedeclOrErr = import(*RedeclIt); @@ -3678,19 +4052,19 @@ ExpectedDecl ASTNodeImporter::VisitFieldDecl(FieldDecl *D) { // initializer of a FieldDecl might not had been instantiated in the // "To" context. However, the "From" context might instantiated that, // thus we have to merge that. + // Note: `hasInClassInitializer()` is not the same as non-null + // `getInClassInitializer()` value. if (Expr *FromInitializer = D->getInClassInitializer()) { - // We don't have yet the initializer set. - if (FoundField->hasInClassInitializer() && - !FoundField->getInClassInitializer()) { - if (ExpectedExpr ToInitializerOrErr = import(FromInitializer)) + if (ExpectedExpr ToInitializerOrErr = import(FromInitializer)) { + // Import of the FromInitializer may result in the setting of + // InClassInitializer. If not, set it here. + assert(FoundField->hasInClassInitializer() && + "Field should have an in-class initializer if it has an " + "expression for it."); + if (!FoundField->getInClassInitializer()) FoundField->setInClassInitializer(*ToInitializerOrErr); - else { - // We can't return error here, - // since we already mapped D as imported. - // FIXME: warning message? - consumeError(ToInitializerOrErr.takeError()); - return FoundField; - } + } else { + return ToInitializerOrErr.takeError(); } } return FoundField; @@ -3702,7 +4076,7 @@ ExpectedDecl ASTNodeImporter::VisitFieldDecl(FieldDecl *D) { Importer.ToDiag(FoundField->getLocation(), diag::note_odr_value_here) << FoundField->getType(); - return make_error<ImportError>(ImportError::NameConflict); + return make_error<ASTImportError>(ASTImportError::NameConflict); } } @@ -3711,7 +4085,6 @@ ExpectedDecl ASTNodeImporter::VisitFieldDecl(FieldDecl *D) { auto ToTInfo = importChecked(Err, D->getTypeSourceInfo()); auto ToBitWidth = importChecked(Err, D->getBitWidth()); auto ToInnerLocStart = importChecked(Err, D->getInnerLocStart()); - auto ToInitializer = importChecked(Err, D->getInClassInitializer()); if (Err) return std::move(Err); const Type *ToCapturedVLAType = nullptr; @@ -3726,14 +4099,32 @@ ExpectedDecl ASTNodeImporter::VisitFieldDecl(FieldDecl *D) { D->getInClassInitStyle())) return ToField; + // We need [[no_unqiue_address]] attributes to be added to FieldDecl, before + // we add fields in CXXRecordDecl::addedMember, otherwise record will be + // marked as having non-zero size. + Err = Importer.ImportAttrs(ToField, D); + if (Err) + return std::move(Err); ToField->setAccess(D->getAccess()); ToField->setLexicalDeclContext(LexicalDC); - if (ToInitializer) - ToField->setInClassInitializer(ToInitializer); ToField->setImplicit(D->isImplicit()); if (ToCapturedVLAType) ToField->setCapturedVLAType(cast<VariableArrayType>(ToCapturedVLAType)); LexicalDC->addDeclInternal(ToField); + // Import initializer only after the field was created, it may have recursive + // reference to the field. + auto ToInitializer = importChecked(Err, D->getInClassInitializer()); + if (Err) + return std::move(Err); + if (ToInitializer) { + auto *AlreadyImported = ToField->getInClassInitializer(); + if (AlreadyImported) + assert(ToInitializer == AlreadyImported && + "Duplicate import of in-class initializer."); + else + ToField->setInClassInitializer(ToInitializer); + } + return ToField; } @@ -3775,7 +4166,7 @@ ExpectedDecl ASTNodeImporter::VisitIndirectFieldDecl(IndirectFieldDecl *D) { Importer.ToDiag(FoundField->getLocation(), diag::note_odr_value_here) << FoundField->getType(); - return make_error<ImportError>(ImportError::NameConflict); + return make_error<ASTImportError>(ASTImportError::NameConflict); } } @@ -3815,22 +4206,34 @@ struct FriendCountAndPosition { unsigned int IndexOfDecl; }; -template <class T> -static FriendCountAndPosition getFriendCountAndPosition( - const FriendDecl *FD, - llvm::function_ref<T(const FriendDecl *)> GetCanTypeOrDecl) { +static bool IsEquivalentFriend(ASTImporter &Importer, FriendDecl *FD1, + FriendDecl *FD2) { + if ((!FD1->getFriendType()) != (!FD2->getFriendType())) + return false; + + if (const TypeSourceInfo *TSI = FD1->getFriendType()) + return Importer.IsStructurallyEquivalent( + TSI->getType(), FD2->getFriendType()->getType(), /*Complain=*/false); + + ASTImporter::NonEquivalentDeclSet NonEquivalentDecls; + StructuralEquivalenceContext Ctx( + FD1->getASTContext(), FD2->getASTContext(), NonEquivalentDecls, + StructuralEquivalenceKind::Default, + /* StrictTypeSpelling = */ false, /* Complain = */ false); + return Ctx.IsEquivalent(FD1, FD2); +} + +static FriendCountAndPosition getFriendCountAndPosition(ASTImporter &Importer, + FriendDecl *FD) { unsigned int FriendCount = 0; - llvm::Optional<unsigned int> FriendPosition; + std::optional<unsigned int> FriendPosition; const auto *RD = cast<CXXRecordDecl>(FD->getLexicalDeclContext()); - T TypeOrDecl = GetCanTypeOrDecl(FD); - - for (const FriendDecl *FoundFriend : RD->friends()) { + for (FriendDecl *FoundFriend : RD->friends()) { if (FoundFriend == FD) { FriendPosition = FriendCount; ++FriendCount; - } else if (!FoundFriend->getFriendDecl() == !FD->getFriendDecl() && - GetCanTypeOrDecl(FoundFriend) == TypeOrDecl) { + } else if (IsEquivalentFriend(Importer, FD, FoundFriend)) { ++FriendCount; } } @@ -3840,21 +4243,6 @@ static FriendCountAndPosition getFriendCountAndPosition( return {FriendCount, *FriendPosition}; } -static FriendCountAndPosition getFriendCountAndPosition(const FriendDecl *FD) { - if (FD->getFriendType()) - return getFriendCountAndPosition<QualType>(FD, [](const FriendDecl *F) { - if (TypeSourceInfo *TSI = F->getFriendType()) - return TSI->getType().getCanonicalType(); - llvm_unreachable("Wrong friend object type."); - }); - else - return getFriendCountAndPosition<Decl *>(FD, [](const FriendDecl *F) { - if (Decl *D = F->getFriendDecl()) - return D->getCanonicalDecl(); - llvm_unreachable("Wrong friend object type."); - }); -} - ExpectedDecl ASTNodeImporter::VisitFriendDecl(FriendDecl *D) { // Import the major distinguishing characteristics of a declaration. DeclContext *DC, *LexicalDC; @@ -3865,26 +4253,13 @@ ExpectedDecl ASTNodeImporter::VisitFriendDecl(FriendDecl *D) { // FriendDecl is not a NamedDecl so we cannot use lookup. // We try to maintain order and count of redundant friend declarations. const auto *RD = cast<CXXRecordDecl>(DC); - FriendDecl *ImportedFriend = RD->getFirstFriend(); SmallVector<FriendDecl *, 2> ImportedEquivalentFriends; - - while (ImportedFriend) { - bool Match = false; - if (D->getFriendDecl() && ImportedFriend->getFriendDecl()) { - Match = - IsStructuralMatch(D->getFriendDecl(), ImportedFriend->getFriendDecl(), - /*Complain=*/false); - } else if (D->getFriendType() && ImportedFriend->getFriendType()) { - Match = Importer.IsStructurallyEquivalent( - D->getFriendType()->getType(), - ImportedFriend->getFriendType()->getType(), /*Complain=*/false); - } - if (Match) + for (FriendDecl *ImportedFriend : RD->friends()) + if (IsEquivalentFriend(Importer, D, ImportedFriend)) ImportedEquivalentFriends.push_back(ImportedFriend); - ImportedFriend = ImportedFriend->getNextFriend(); - } - FriendCountAndPosition CountAndPosition = getFriendCountAndPosition(D); + FriendCountAndPosition CountAndPosition = + getFriendCountAndPosition(Importer, D); assert(ImportedEquivalentFriends.size() <= CountAndPosition.TotalCount && "Class with non-matching friends is imported, ODR check wrong?"); @@ -3966,7 +4341,7 @@ ExpectedDecl ASTNodeImporter::VisitObjCIvarDecl(ObjCIvarDecl *D) { Importer.ToDiag(FoundIvar->getLocation(), diag::note_odr_value_here) << FoundIvar->getType(); - return make_error<ImportError>(ImportError::NameConflict); + return make_error<ASTImportError>(ASTImportError::NameConflict); } } @@ -4134,6 +4509,17 @@ ExpectedDecl ASTNodeImporter::VisitVarDecl(VarDecl *D) { auto ToVTOrErr = import(D->getDescribedVarTemplate()); if (!ToVTOrErr) return ToVTOrErr.takeError(); + } else if (MemberSpecializationInfo *MSI = D->getMemberSpecializationInfo()) { + TemplateSpecializationKind SK = MSI->getTemplateSpecializationKind(); + VarDecl *FromInst = D->getInstantiatedFromStaticDataMember(); + if (Expected<VarDecl *> ToInstOrErr = import(FromInst)) + ToVar->setInstantiationOfStaticDataMember(*ToInstOrErr, SK); + else + return ToInstOrErr.takeError(); + if (ExpectedSLoc POIOrErr = import(MSI->getPointOfInstantiation())) + ToVar->getMemberSpecializationInfo()->setPointOfInstantiation(*POIOrErr); + else + return POIOrErr.takeError(); } if (Error Err = ImportInitializer(D, ToVar)) @@ -4178,6 +4564,8 @@ ExpectedDecl ASTNodeImporter::VisitImplicitParamDecl(ImplicitParamDecl *D) { Error ASTNodeImporter::ImportDefaultArgOfParmVarDecl( const ParmVarDecl *FromParam, ParmVarDecl *ToParam) { ToParam->setHasInheritedDefaultArg(FromParam->hasInheritedDefaultArg()); + ToParam->setExplicitObjectParameterLoc( + FromParam->getExplicitObjectParamThisLoc()); ToParam->setKNRPromoted(FromParam->isKNRPromoted()); if (FromParam->hasUninstantiatedDefaultArg()) { @@ -4197,6 +4585,17 @@ Error ASTNodeImporter::ImportDefaultArgOfParmVarDecl( return Error::success(); } +Expected<InheritedConstructor> +ASTNodeImporter::ImportInheritedConstructor(const InheritedConstructor &From) { + Error Err = Error::success(); + CXXConstructorDecl *ToBaseCtor = importChecked(Err, From.getConstructor()); + ConstructorUsingShadowDecl *ToShadow = + importChecked(Err, From.getShadowDecl()); + if (Err) + return std::move(Err); + return InheritedConstructor(ToShadow, ToBaseCtor); +} + ExpectedDecl ASTNodeImporter::VisitParmVarDecl(ParmVarDecl *D) { // Parameters are created in the translation unit's context, then moved // into the function declaration's context afterward. @@ -4263,7 +4662,7 @@ ExpectedDecl ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) { diag::note_odr_objc_method_here) << D->isInstanceMethod() << Name; - return make_error<ImportError>(ImportError::NameConflict); + return make_error<ASTImportError>(ASTImportError::NameConflict); } // Check the number of parameters. @@ -4275,7 +4674,7 @@ ExpectedDecl ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) { diag::note_odr_objc_method_here) << D->isInstanceMethod() << Name; - return make_error<ImportError>(ImportError::NameConflict); + return make_error<ASTImportError>(ASTImportError::NameConflict); } // Check parameter types. @@ -4291,7 +4690,7 @@ ExpectedDecl ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) { Importer.ToDiag((*FoundP)->getLocation(), diag::note_odr_value_here) << (*FoundP)->getType(); - return make_error<ImportError>(ImportError::NameConflict); + return make_error<ASTImportError>(ASTImportError::NameConflict); } } @@ -4304,7 +4703,7 @@ ExpectedDecl ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) { diag::note_odr_objc_method_here) << D->isInstanceMethod() << Name; - return make_error<ImportError>(ImportError::NameConflict); + return make_error<ASTImportError>(ASTImportError::NameConflict); } // FIXME: Any other bits we need to merge? @@ -4395,6 +4794,11 @@ ExpectedDecl ASTNodeImporter::VisitObjCTypeParamDecl(ObjCTypeParamDecl *D) { ToColonLoc, ToTypeSourceInfo)) return Result; + // Only import 'ObjCTypeParamType' after the decl is created. + auto ToTypeForDecl = importChecked(Err, D->getTypeForDecl()); + if (Err) + return std::move(Err); + Result->setTypeForDecl(ToTypeForDecl); Result->setLexicalDeclContext(LexicalDC); return Result; } @@ -4693,13 +5097,14 @@ ExpectedDecl ASTNodeImporter::VisitUsingEnumDecl(UsingEnumDecl *D) { Error Err = Error::success(); auto ToUsingLoc = importChecked(Err, D->getUsingLoc()); auto ToEnumLoc = importChecked(Err, D->getEnumLoc()); - auto ToEnumDecl = importChecked(Err, D->getEnumDecl()); + auto ToNameLoc = importChecked(Err, D->getLocation()); + auto *ToEnumType = importChecked(Err, D->getEnumType()); if (Err) return std::move(Err); UsingEnumDecl *ToUsingEnum; if (GetImportedOrCreateDecl(ToUsingEnum, D, Importer.getToContext(), DC, - ToUsingLoc, ToEnumLoc, Loc, ToEnumDecl)) + ToUsingLoc, ToEnumLoc, ToNameLoc, ToEnumType)) return ToUsingEnum; ToUsingEnum->setLexicalDeclContext(LexicalDC); @@ -4736,9 +5141,29 @@ ExpectedDecl ASTNodeImporter::VisitUsingShadowDecl(UsingShadowDecl *D) { return ToTargetOrErr.takeError(); UsingShadowDecl *ToShadow; - if (GetImportedOrCreateDecl(ToShadow, D, Importer.getToContext(), DC, Loc, - Name, *ToIntroducerOrErr, *ToTargetOrErr)) - return ToShadow; + if (auto *FromConstructorUsingShadow = + dyn_cast<ConstructorUsingShadowDecl>(D)) { + Error Err = Error::success(); + ConstructorUsingShadowDecl *Nominated = importChecked( + Err, FromConstructorUsingShadow->getNominatedBaseClassShadowDecl()); + if (Err) + return std::move(Err); + // The 'Target' parameter of ConstructorUsingShadowDecl constructor + // is really the "NominatedBaseClassShadowDecl" value if it exists + // (see code of ConstructorUsingShadowDecl::ConstructorUsingShadowDecl). + // We should pass the NominatedBaseClassShadowDecl to it (if non-null) to + // get the correct values. + if (GetImportedOrCreateDecl<ConstructorUsingShadowDecl>( + ToShadow, D, Importer.getToContext(), DC, Loc, + cast<UsingDecl>(*ToIntroducerOrErr), + Nominated ? Nominated : *ToTargetOrErr, + FromConstructorUsingShadow->constructsVirtualBase())) + return ToShadow; + } else { + if (GetImportedOrCreateDecl(ToShadow, D, Importer.getToContext(), DC, Loc, + Name, *ToIntroducerOrErr, *ToTargetOrErr)) + return ToShadow; + } ToShadow->setLexicalDeclContext(LexicalDC); ToShadow->setAccess(D->getAccess()); @@ -4798,6 +5223,35 @@ ExpectedDecl ASTNodeImporter::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) { return ToUsingDir; } +ExpectedDecl ASTNodeImporter::VisitUsingPackDecl(UsingPackDecl *D) { + DeclContext *DC, *LexicalDC; + DeclarationName Name; + SourceLocation Loc; + NamedDecl *ToD = nullptr; + if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) + return std::move(Err); + if (ToD) + return ToD; + + auto ToInstantiatedFromUsingOrErr = + Importer.Import(D->getInstantiatedFromUsingDecl()); + if (!ToInstantiatedFromUsingOrErr) + return ToInstantiatedFromUsingOrErr.takeError(); + SmallVector<NamedDecl *, 4> Expansions(D->expansions().size()); + if (Error Err = ImportArrayChecked(D->expansions(), Expansions.begin())) + return std::move(Err); + + UsingPackDecl *ToUsingPack; + if (GetImportedOrCreateDecl(ToUsingPack, D, Importer.getToContext(), DC, + cast<NamedDecl>(*ToInstantiatedFromUsingOrErr), + Expansions)) + return ToUsingPack; + + addDeclToContexts(D, ToUsingPack); + + return ToUsingPack; +} + ExpectedDecl ASTNodeImporter::VisitUnresolvedUsingValueDecl( UnresolvedUsingValueDecl *D) { DeclContext *DC, *LexicalDC; @@ -5182,7 +5636,7 @@ ASTNodeImporter::VisitObjCImplementationDecl(ObjCImplementationDecl *D) { Importer.FromDiag(D->getLocation(), diag::note_odr_objc_missing_superclass); - return make_error<ImportError>(ImportError::NameConflict); + return make_error<ASTImportError>(ASTImportError::NameConflict); } } @@ -5221,7 +5675,7 @@ ExpectedDecl ASTNodeImporter::VisitObjCPropertyDecl(ObjCPropertyDecl *D) { Importer.ToDiag(FoundProp->getLocation(), diag::note_odr_value_here) << FoundProp->getType(); - return make_error<ImportError>(ImportError::NameConflict); + return make_error<ASTImportError>(ASTImportError::NameConflict); } // FIXME: Check property attributes, getters, setters, etc.? @@ -5326,7 +5780,7 @@ ASTNodeImporter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) { << D->getPropertyDecl()->getDeclName() << (D->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic); - return make_error<ImportError>(ImportError::NameConflict); + return make_error<ASTImportError>(ASTImportError::NameConflict); } // For @synthesize, check that we have the same @@ -5341,7 +5795,7 @@ ASTNodeImporter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) { diag::note_odr_objc_synthesize_ivar_here) << D->getPropertyIvarDecl()->getDeclName(); - return make_error<ImportError>(ImportError::NameConflict); + return make_error<ASTImportError>(ASTImportError::NameConflict); } // Merge the existing implementation with the new implementation. @@ -5379,28 +5833,12 @@ ASTNodeImporter::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) { if (const TypeConstraint *TC = D->getTypeConstraint()) { Error Err = Error::success(); - auto ToNNS = importChecked(Err, TC->getNestedNameSpecifierLoc()); - auto ToName = importChecked(Err, TC->getConceptNameInfo().getName()); - auto ToNameLoc = importChecked(Err, TC->getConceptNameInfo().getLoc()); - auto ToFoundDecl = importChecked(Err, TC->getFoundDecl()); - auto ToNamedConcept = importChecked(Err, TC->getNamedConcept()); + auto ToConceptRef = importChecked(Err, TC->getConceptReference()); auto ToIDC = importChecked(Err, TC->getImmediatelyDeclaredConstraint()); if (Err) return std::move(Err); - TemplateArgumentListInfo ToTAInfo; - const auto *ASTTemplateArgs = TC->getTemplateArgsAsWritten(); - if (ASTTemplateArgs) - if (Error Err = ImportTemplateArgumentListInfo(*ASTTemplateArgs, - ToTAInfo)) - return std::move(Err); - - ToD->setTypeConstraint(ToNNS, DeclarationNameInfo(ToName, ToNameLoc), - ToFoundDecl, ToNamedConcept, - ASTTemplateArgs ? - ASTTemplateArgumentListInfo::Create(Importer.getToContext(), - ToTAInfo) : nullptr, - ToIDC); + ToD->setTypeConstraint(ToConceptRef, ToIDC); } if (D->hasDefaultArgument()) { @@ -5504,6 +5942,18 @@ ExpectedDecl ASTNodeImporter::VisitClassTemplateDecl(ClassTemplateDecl *D) { if (ToD) return ToD; + // Should check if a declaration is friend in a dependent context. + // Such templates are not linked together in a declaration chain. + // The ASTImporter strategy is to map existing forward declarations to + // imported ones only if strictly necessary, otherwise import these as new + // forward declarations. In case of the "dependent friend" declarations, new + // declarations are created, but not linked in a declaration chain. + auto IsDependentFriend = [](ClassTemplateDecl *TD) { + return TD->getFriendObjectKind() != Decl::FOK_None && + TD->getLexicalDeclContext()->isDependentContext(); + }; + bool DependentFriend = IsDependentFriend(D); + ClassTemplateDecl *FoundByLookup = nullptr; // We may already have a template of the same name; try to find and match it. @@ -5521,7 +5971,15 @@ ExpectedDecl ASTNodeImporter::VisitClassTemplateDecl(ClassTemplateDecl *D) { if (!hasSameVisibilityContextAndLinkage(FoundTemplate, D)) continue; - if (IsStructuralMatch(D, FoundTemplate)) { + // FIXME: sufficient conditon for 'IgnoreTemplateParmDepth'? + bool IgnoreTemplateParmDepth = + (FoundTemplate->getFriendObjectKind() != Decl::FOK_None) != + (D->getFriendObjectKind() != Decl::FOK_None); + if (IsStructuralMatch(D, FoundTemplate, /*Complain=*/true, + IgnoreTemplateParmDepth)) { + if (DependentFriend || IsDependentFriend(FoundTemplate)) + continue; + ClassTemplateDecl *TemplateWithDef = getTemplateDefinition(FoundTemplate); if (D->isThisDeclarationADefinition() && TemplateWithDef) @@ -5596,11 +6054,6 @@ ExpectedDecl ASTNodeImporter::VisitClassTemplateDecl(ClassTemplateDecl *D) { D2->setPreviousDecl(Recent); } - if (FromTemplated->isCompleteDefinition() && - !ToTemplated->isCompleteDefinition()) { - // FIXME: Import definition! - } - return D2; } @@ -5617,8 +6070,8 @@ ExpectedDecl ASTNodeImporter::VisitClassTemplateSpecializationDecl( // Import template arguments. SmallVector<TemplateArgument, 2> TemplateArgs; - if (Error Err = ImportTemplateArguments( - D->getTemplateArgs().data(), D->getTemplateArgs().size(), TemplateArgs)) + if (Error Err = + ImportTemplateArguments(D->getTemplateArgs().asArray(), TemplateArgs)) return std::move(Err); // Try to find an existing specialization with these template arguments and // template parameter list. @@ -5671,7 +6124,7 @@ ExpectedDecl ASTNodeImporter::VisitClassTemplateSpecializationDecl( } } else { // ODR violation. // FIXME HandleNameConflict - return make_error<ImportError>(ImportError::NameConflict); + return make_error<ASTImportError>(ASTImportError::NameConflict); } } @@ -5699,10 +6152,10 @@ ExpectedDecl ASTNodeImporter::VisitClassTemplateSpecializationDecl( CanonInjType = CanonInjType.getCanonicalType(); if (GetImportedOrCreateDecl<ClassTemplatePartialSpecializationDecl>( - D2, D, Importer.getToContext(), D->getTagKind(), DC, - *BeginLocOrErr, *IdLocOrErr, ToTPList, ClassTemplate, - llvm::makeArrayRef(TemplateArgs.data(), TemplateArgs.size()), - ToTAInfo, CanonInjType, + D2, D, Importer.getToContext(), D->getTagKind(), DC, *BeginLocOrErr, + *IdLocOrErr, ToTPList, ClassTemplate, + llvm::ArrayRef(TemplateArgs.data(), TemplateArgs.size()), ToTAInfo, + CanonInjType, cast_or_null<ClassTemplatePartialSpecializationDecl>(PrevDecl))) return D2; @@ -5713,6 +6166,11 @@ ExpectedDecl ASTNodeImporter::VisitClassTemplateSpecializationDecl( InsertPos)) // Add this partial specialization to the class template. ClassTemplate->AddPartialSpecialization(PartSpec2, InsertPos); + if (Expected<ClassTemplatePartialSpecializationDecl *> ToInstOrErr = + import(PartialSpec->getInstantiatedFromMember())) + PartSpec2->setInstantiatedFromMember(*ToInstOrErr); + else + return ToInstOrErr.takeError(); updateLookupTableForTemplateParameters(*ToTPList); } else { // Not a partial specialization. @@ -5776,6 +6234,30 @@ ExpectedDecl ASTNodeImporter::VisitClassTemplateSpecializationDecl( D2->setTemplateSpecializationKind(D->getTemplateSpecializationKind()); + if (auto P = D->getInstantiatedFrom()) { + if (auto *CTD = P.dyn_cast<ClassTemplateDecl *>()) { + if (auto CTDorErr = import(CTD)) + D2->setInstantiationOf(*CTDorErr); + } else { + auto *CTPSD = cast<ClassTemplatePartialSpecializationDecl *>(P); + auto CTPSDOrErr = import(CTPSD); + if (!CTPSDOrErr) + return CTPSDOrErr.takeError(); + const TemplateArgumentList &DArgs = D->getTemplateInstantiationArgs(); + SmallVector<TemplateArgument, 2> D2ArgsVec(DArgs.size()); + for (unsigned I = 0; I < DArgs.size(); ++I) { + const TemplateArgument &DArg = DArgs[I]; + if (auto ArgOrErr = import(DArg)) + D2ArgsVec[I] = *ArgOrErr; + else + return ArgOrErr.takeError(); + } + D2->setInstantiationOf( + *CTPSDOrErr, + TemplateArgumentList::CreateCopy(Importer.getToContext(), D2ArgsVec)); + } + } + if (D->isCompleteDefinition()) if (Error Err = ImportDefinition(D, D2)) return std::move(Err); @@ -5811,14 +6293,21 @@ ExpectedDecl ASTNodeImporter::VisitVarTemplateDecl(VarTemplateDecl *D) { D->getTemplatedDecl())) continue; if (IsStructuralMatch(D, FoundTemplate)) { - // The Decl in the "From" context has a definition, but in the - // "To" context we already have a definition. + // FIXME Check for ODR error if the two definitions have + // different initializers? VarTemplateDecl *FoundDef = getTemplateDefinition(FoundTemplate); - if (D->isThisDeclarationADefinition() && FoundDef) - // FIXME Check for ODR error if the two definitions have - // different initializers? - return Importer.MapImported(D, FoundDef); - + if (D->getDeclContext()->isRecord()) { + assert(FoundTemplate->getDeclContext()->isRecord() && + "Member variable template imported as non-member, " + "inconsistent imported AST?"); + if (FoundDef) + return Importer.MapImported(D, FoundDef); + if (!D->isThisDeclarationADefinition()) + return Importer.MapImported(D, FoundTemplate); + } else { + if (FoundDef && D->isThisDeclarationADefinition()) + return Importer.MapImported(D, FoundDef); + } FoundByLookup = FoundTemplate; break; } @@ -5879,11 +6368,6 @@ ExpectedDecl ASTNodeImporter::VisitVarTemplateDecl(VarTemplateDecl *D) { ToVarTD->setPreviousDecl(Recent); } - if (DTemplated->isThisDeclarationADefinition() && - !ToTemplated->isThisDeclarationADefinition()) { - // FIXME: Import definition! - } - return ToVarTD; } @@ -5920,8 +6404,8 @@ ExpectedDecl ASTNodeImporter::VisitVarTemplateSpecializationDecl( // Import template arguments. SmallVector<TemplateArgument, 2> TemplateArgs; - if (Error Err = ImportTemplateArguments( - D->getTemplateArgs().data(), D->getTemplateArgs().size(), TemplateArgs)) + if (Error Err = + ImportTemplateArguments(D->getTemplateArgs().asArray(), TemplateArgs)) return std::move(Err); // Try to find an existing specialization with these template arguments. @@ -5944,19 +6428,11 @@ ExpectedDecl ASTNodeImporter::VisitVarTemplateSpecializationDecl( } } } else { - // Import the type. - QualType T; - if (Error Err = importInto(T, D->getType())) - return std::move(Err); - - auto TInfoOrErr = import(D->getTypeSourceInfo()); - if (!TInfoOrErr) - return TInfoOrErr.takeError(); - TemplateArgumentListInfo ToTAInfo; - if (Error Err = ImportTemplateArgumentListInfo( - D->getTemplateArgsInfo(), ToTAInfo)) - return std::move(Err); + if (const ASTTemplateArgumentListInfo *Args = D->getTemplateArgsInfo()) { + if (Error Err = ImportTemplateArgumentListInfo(*Args, ToTAInfo)) + return std::move(Err); + } using PartVarSpecDecl = VarTemplatePartialSpecializationDecl; // Create a new specialization. @@ -5976,7 +6452,7 @@ ExpectedDecl ASTNodeImporter::VisitVarTemplateSpecializationDecl( PartVarSpecDecl *ToPartial; if (GetImportedOrCreateDecl(ToPartial, D, Importer.getToContext(), DC, *BeginLocOrErr, *IdLocOrErr, *ToTPListOrErr, - VarTemplate, T, *TInfoOrErr, + VarTemplate, QualType(), nullptr, D->getStorageClass(), TemplateArgs, ArgInfos)) return ToPartial; @@ -5997,11 +6473,21 @@ ExpectedDecl ASTNodeImporter::VisitVarTemplateSpecializationDecl( } else { // Full specialization if (GetImportedOrCreateDecl(D2, D, Importer.getToContext(), DC, *BeginLocOrErr, *IdLocOrErr, VarTemplate, - T, *TInfoOrErr, - D->getStorageClass(), TemplateArgs)) + QualType(), nullptr, D->getStorageClass(), + TemplateArgs)) return D2; } + QualType T; + if (Error Err = importInto(T, D->getType())) + return std::move(Err); + D2->setType(T); + + auto TInfoOrErr = import(D->getTypeSourceInfo()); + if (!TInfoOrErr) + return TInfoOrErr.takeError(); + D2->setTypeSourceInfo(*TInfoOrErr); + if (D->getPointOfInstantiation().isValid()) { if (ExpectedSLoc POIOrErr = import(D->getPointOfInstantiation())) D2->setPointOfInstantiation(*POIOrErr); @@ -6088,20 +6574,24 @@ ASTNodeImporter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) { if (Error Err = importInto(TemplatedFD, D->getTemplatedDecl())) return std::move(Err); - // Template parameters of the ClassTemplateDecl and FunctionTemplateDecl are - // shared, if the FunctionTemplateDecl is a deduction guide for the class. - // At import the ClassTemplateDecl object is always created first (FIXME: is - // this really true?) because the dependency, then the FunctionTemplateDecl. - // The DeclContext of the template parameters is changed when the - // FunctionTemplateDecl is created, but was set already when the class - // template was created. So here it is not the TU (default value) any more. - // FIXME: The DeclContext of the parameters is now set finally to the - // CXXDeductionGuideDecl object that was imported later. This may not be the - // same that is in the original AST, specially if there are multiple deduction - // guides. - DeclContext *OldParamDC = nullptr; - if (Params->size() > 0) - OldParamDC = Params->getParam(0)->getDeclContext(); + // At creation of the template the template parameters are "adopted" + // (DeclContext is changed). After this possible change the lookup table + // must be updated. + // At deduction guides the DeclContext of the template parameters may be + // different from what we would expect, it may be the class template, or a + // probably different CXXDeductionGuideDecl. This may come from the fact that + // the template parameter objects may be shared between deduction guides or + // the class template, and at creation of multiple FunctionTemplateDecl + // objects (for deduction guides) the same parameters are re-used. The + // "adoption" happens multiple times with different parent, even recursively + // for TemplateTemplateParmDecl. The same happens at import when the + // FunctionTemplateDecl objects are created, but in different order. + // In this way the DeclContext of these template parameters is not necessarily + // the same as in the "from" context. + SmallVector<DeclContext *, 2> OldParamDC; + OldParamDC.reserve(Params->size()); + llvm::transform(*Params, std::back_inserter(OldParamDC), + [](NamedDecl *ND) { return ND->getDeclContext(); }); FunctionTemplateDecl *ToFunc; if (GetImportedOrCreateDecl(ToFunc, D, Importer.getToContext(), DC, Loc, Name, @@ -6112,8 +6602,13 @@ ASTNodeImporter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) { ToFunc->setAccess(D->getAccess()); ToFunc->setLexicalDeclContext(LexicalDC); - LexicalDC->addDeclInternal(ToFunc); - updateLookupTableForTemplateParameters(*Params, OldParamDC); + addDeclToContexts(D, ToFunc); + + ASTImporterLookupTable *LT = Importer.SharedState->getLookupTable(); + if (LT && !OldParamDC.empty()) { + for (unsigned int I = 0; I < OldParamDC.size(); ++I) + LT->updateForced(Params->getParam(I), OldParamDC[I]); + } if (FoundByLookup) { auto *Recent = @@ -6139,13 +6634,13 @@ ASTNodeImporter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) { ExpectedStmt ASTNodeImporter::VisitStmt(Stmt *S) { Importer.FromDiag(S->getBeginLoc(), diag::err_unsupported_ast_node) << S->getStmtClassName(); - return make_error<ImportError>(ImportError::UnsupportedConstruct); + return make_error<ASTImportError>(ASTImportError::UnsupportedConstruct); } ExpectedStmt ASTNodeImporter::VisitGCCAsmStmt(GCCAsmStmt *S) { if (Importer.returnWithErrorInTest()) - return make_error<ImportError>(ImportError::UnsupportedConstruct); + return make_error<ASTImportError>(ASTImportError::UnsupportedConstruct); SmallVector<IdentifierInfo *, 4> Names; for (unsigned I = 0, E = S->getNumOutputs(); I != E; I++) { IdentifierInfo *ToII = Importer.Import(S->getOutputIdentifier(I)); @@ -6258,9 +6753,10 @@ ExpectedStmt ASTNodeImporter::VisitCompoundStmt(CompoundStmt *S) { if (!ToRBracLocOrErr) return ToRBracLocOrErr.takeError(); - return CompoundStmt::Create( - Importer.getToContext(), ToStmts, - *ToLBracLocOrErr, *ToRBracLocOrErr); + FPOptionsOverride FPO = + S->hasStoredFPFeatures() ? S->getStoredFPFeatures() : FPOptionsOverride(); + return CompoundStmt::Create(Importer.getToContext(), ToStmts, FPO, + *ToLBracLocOrErr, *ToRBracLocOrErr); } ExpectedStmt ASTNodeImporter::VisitCaseStmt(CaseStmt *S) { @@ -6339,7 +6835,7 @@ ExpectedStmt ASTNodeImporter::VisitIfStmt(IfStmt *S) { if (Err) return std::move(Err); - return IfStmt::Create(Importer.getToContext(), ToIfLoc, S->isConstexpr(), + return IfStmt::Create(Importer.getToContext(), ToIfLoc, S->getStatementKind(), ToInit, ToConditionVariable, ToCond, ToLParenLoc, ToRParenLoc, ToThen, ToElseLoc, ToElse); } @@ -6515,8 +7011,8 @@ ExpectedStmt ASTNodeImporter::VisitCXXTryStmt(CXXTryStmt *S) { return ToHandlerOrErr.takeError(); } - return CXXTryStmt::Create( - Importer.getToContext(), *ToTryLocOrErr,*ToTryBlockOrErr, ToHandlers); + return CXXTryStmt::Create(Importer.getToContext(), *ToTryLocOrErr, + cast<CompoundStmt>(*ToTryBlockOrErr), ToHandlers); } ExpectedStmt ASTNodeImporter::VisitCXXForRangeStmt(CXXForRangeStmt *S) { @@ -6652,11 +7148,12 @@ ExpectedStmt ASTNodeImporter::VisitObjCAutoreleasePoolStmt( ExpectedStmt ASTNodeImporter::VisitExpr(Expr *E) { Importer.FromDiag(E->getBeginLoc(), diag::err_unsupported_ast_node) << E->getStmtClassName(); - return make_error<ImportError>(ImportError::UnsupportedConstruct); + return make_error<ASTImportError>(ASTImportError::UnsupportedConstruct); } ExpectedStmt ASTNodeImporter::VisitSourceLocExpr(SourceLocExpr *E) { Error Err = Error::success(); + auto ToType = importChecked(Err, E->getType()); auto BLoc = importChecked(Err, E->getBeginLoc()); auto RParenLoc = importChecked(Err, E->getEndLoc()); if (Err) @@ -6666,8 +7163,8 @@ ExpectedStmt ASTNodeImporter::VisitSourceLocExpr(SourceLocExpr *E) { return ParentContextOrErr.takeError(); return new (Importer.getToContext()) - SourceLocExpr(Importer.getToContext(), E->getIdentKind(), BLoc, RParenLoc, - *ParentContextOrErr); + SourceLocExpr(Importer.getToContext(), E->getIdentKind(), ToType, BLoc, + RParenLoc, *ParentContextOrErr); } ExpectedStmt ASTNodeImporter::VisitVAArgExpr(VAArgExpr *E) { @@ -6710,6 +7207,39 @@ ExpectedStmt ASTNodeImporter::VisitChooseExpr(ChooseExpr *E) { ToRParenLoc, CondIsTrue); } +ExpectedStmt ASTNodeImporter::VisitConvertVectorExpr(ConvertVectorExpr *E) { + Error Err = Error::success(); + auto *ToSrcExpr = importChecked(Err, E->getSrcExpr()); + auto ToRParenLoc = importChecked(Err, E->getRParenLoc()); + auto ToBuiltinLoc = importChecked(Err, E->getBuiltinLoc()); + auto ToType = importChecked(Err, E->getType()); + auto *ToTSI = importChecked(Err, E->getTypeSourceInfo()); + if (Err) + return std::move(Err); + + return new (Importer.getToContext()) + ConvertVectorExpr(ToSrcExpr, ToTSI, ToType, E->getValueKind(), + E->getObjectKind(), ToBuiltinLoc, ToRParenLoc); +} + +ExpectedStmt ASTNodeImporter::VisitShuffleVectorExpr(ShuffleVectorExpr *E) { + Error Err = Error::success(); + auto ToRParenLoc = importChecked(Err, E->getRParenLoc()); + auto ToBeginLoc = importChecked(Err, E->getBeginLoc()); + auto ToType = importChecked(Err, E->getType()); + const unsigned NumSubExprs = E->getNumSubExprs(); + + llvm::SmallVector<Expr *, 8> ToSubExprs; + llvm::ArrayRef<Expr *> FromSubExprs(E->getSubExprs(), NumSubExprs); + ToSubExprs.resize(NumSubExprs); + + if ((Err = ImportContainerChecked(FromSubExprs, ToSubExprs))) + return std::move(Err); + + return new (Importer.getToContext()) ShuffleVectorExpr( + Importer.getToContext(), ToSubExprs, ToType, ToBeginLoc, ToRParenLoc); +} + ExpectedStmt ASTNodeImporter::VisitGNUNullExpr(GNUNullExpr *E) { ExpectedType TypeOrErr = import(E->getType()); if (!TypeOrErr) @@ -6726,7 +7256,14 @@ ExpectedStmt ASTNodeImporter::VisitGenericSelectionExpr(GenericSelectionExpr *E) { Error Err = Error::success(); auto ToGenericLoc = importChecked(Err, E->getGenericLoc()); - auto *ToControllingExpr = importChecked(Err, E->getControllingExpr()); + Expr *ToControllingExpr = nullptr; + TypeSourceInfo *ToControllingType = nullptr; + if (E->isExprPredicate()) + ToControllingExpr = importChecked(Err, E->getControllingExpr()); + else + ToControllingType = importChecked(Err, E->getControllingType()); + assert((ToControllingExpr || ToControllingType) && + "Either the controlling expr or type must be nonnull"); auto ToDefaultLoc = importChecked(Err, E->getDefaultLoc()); auto ToRParenLoc = importChecked(Err, E->getRParenLoc()); if (Err) @@ -6744,15 +7281,27 @@ ASTNodeImporter::VisitGenericSelectionExpr(GenericSelectionExpr *E) { const ASTContext &ToCtx = Importer.getToContext(); if (E->isResultDependent()) { + if (ToControllingExpr) { + return GenericSelectionExpr::Create( + ToCtx, ToGenericLoc, ToControllingExpr, llvm::ArrayRef(ToAssocTypes), + llvm::ArrayRef(ToAssocExprs), ToDefaultLoc, ToRParenLoc, + E->containsUnexpandedParameterPack()); + } return GenericSelectionExpr::Create( - ToCtx, ToGenericLoc, ToControllingExpr, - llvm::makeArrayRef(ToAssocTypes), llvm::makeArrayRef(ToAssocExprs), - ToDefaultLoc, ToRParenLoc, E->containsUnexpandedParameterPack()); + ToCtx, ToGenericLoc, ToControllingType, llvm::ArrayRef(ToAssocTypes), + llvm::ArrayRef(ToAssocExprs), ToDefaultLoc, ToRParenLoc, + E->containsUnexpandedParameterPack()); } + if (ToControllingExpr) { + return GenericSelectionExpr::Create( + ToCtx, ToGenericLoc, ToControllingExpr, llvm::ArrayRef(ToAssocTypes), + llvm::ArrayRef(ToAssocExprs), ToDefaultLoc, ToRParenLoc, + E->containsUnexpandedParameterPack(), E->getResultIndex()); + } return GenericSelectionExpr::Create( - ToCtx, ToGenericLoc, ToControllingExpr, llvm::makeArrayRef(ToAssocTypes), - llvm::makeArrayRef(ToAssocExprs), ToDefaultLoc, ToRParenLoc, + ToCtx, ToGenericLoc, ToControllingType, llvm::ArrayRef(ToAssocTypes), + llvm::ArrayRef(ToAssocExprs), ToDefaultLoc, ToRParenLoc, E->containsUnexpandedParameterPack(), E->getResultIndex()); } @@ -6766,7 +7315,8 @@ ExpectedStmt ASTNodeImporter::VisitPredefinedExpr(PredefinedExpr *E) { return std::move(Err); return PredefinedExpr::Create(Importer.getToContext(), ToBeginLoc, ToType, - E->getIdentKind(), ToFunctionName); + E->getIdentKind(), E->isTransparent(), + ToFunctionName); } ExpectedStmt ASTNodeImporter::VisitDeclRefExpr(DeclRefExpr *E) { @@ -6804,6 +7354,7 @@ ExpectedStmt ASTNodeImporter::VisitDeclRefExpr(DeclRefExpr *E) { E->getValueKind(), ToFoundD, ToResInfo, E->isNonOdrUse()); if (E->hadMultipleCandidates()) ToE->setHadMultipleCandidates(true); + ToE->setIsImmediateEscalating(E->isImmediateEscalating()); return ToE; } @@ -7047,10 +7598,17 @@ ExpectedStmt ASTNodeImporter::VisitUnaryOperator(UnaryOperator *E) { if (Err) return std::move(Err); - return UnaryOperator::Create( - Importer.getToContext(), ToSubExpr, E->getOpcode(), ToType, - E->getValueKind(), E->getObjectKind(), ToOperatorLoc, E->canOverflow(), - E->getFPOptionsOverride()); + auto *UO = UnaryOperator::CreateEmpty(Importer.getToContext(), + E->hasStoredFPFeatures()); + UO->setType(ToType); + UO->setSubExpr(ToSubExpr); + UO->setOpcode(E->getOpcode()); + UO->setOperatorLoc(ToOperatorLoc); + UO->setCanOverflow(E->canOverflow()); + if (E->hasStoredFPFeatures()) + UO->setStoredFPFeatures(E->getStoredFPFeatures()); + + return UO; } ExpectedStmt @@ -7094,7 +7652,7 @@ ExpectedStmt ASTNodeImporter::VisitBinaryOperator(BinaryOperator *E) { return BinaryOperator::Create( Importer.getToContext(), ToLHS, ToRHS, E->getOpcode(), ToType, E->getValueKind(), E->getObjectKind(), ToOperatorLoc, - E->getFPFeatures(Importer.getFromContext().getLangOpts())); + E->getFPFeatures()); } ExpectedStmt ASTNodeImporter::VisitConditionalOperator(ConditionalOperator *E) { @@ -7133,6 +7691,17 @@ ASTNodeImporter::VisitBinaryConditionalOperator(BinaryConditionalOperator *E) { E->getObjectKind()); } +ExpectedStmt ASTNodeImporter::VisitCXXRewrittenBinaryOperator( + CXXRewrittenBinaryOperator *E) { + Error Err = Error::success(); + auto ToSemanticForm = importChecked(Err, E->getSemanticForm()); + if (Err) + return std::move(Err); + + return new (Importer.getToContext()) + CXXRewrittenBinaryOperator(ToSemanticForm, E->isReversed()); +} + ExpectedStmt ASTNodeImporter::VisitArrayTypeTraitExpr(ArrayTypeTraitExpr *E) { Error Err = Error::success(); auto ToBeginLoc = importChecked(Err, E->getBeginLoc()); @@ -7205,7 +7774,7 @@ ASTNodeImporter::VisitCompoundAssignOperator(CompoundAssignOperator *E) { return CompoundAssignOperator::Create( Importer.getToContext(), ToLHS, ToRHS, E->getOpcode(), ToType, E->getValueKind(), E->getObjectKind(), ToOperatorLoc, - E->getFPFeatures(Importer.getFromContext().getLangOpts()), + E->getFPFeatures(), ToComputationLHSType, ToComputationResultType); } @@ -7293,9 +7862,21 @@ ExpectedStmt ASTNodeImporter::VisitExplicitCastExpr(ExplicitCastExpr *E) { *ToLParenLocOrErr, OCE->getBridgeKind(), E->getCastKind(), *ToBridgeKeywordLocOrErr, ToTypeInfoAsWritten, ToSubExpr); } + case Stmt::BuiltinBitCastExprClass: { + auto *BBC = cast<BuiltinBitCastExpr>(E); + ExpectedSLoc ToKWLocOrErr = import(BBC->getBeginLoc()); + if (!ToKWLocOrErr) + return ToKWLocOrErr.takeError(); + ExpectedSLoc ToRParenLocOrErr = import(BBC->getEndLoc()); + if (!ToRParenLocOrErr) + return ToRParenLocOrErr.takeError(); + return new (Importer.getToContext()) BuiltinBitCastExpr( + ToType, E->getValueKind(), E->getCastKind(), ToSubExpr, + ToTypeInfoAsWritten, *ToKWLocOrErr, *ToRParenLocOrErr); + } default: llvm_unreachable("Cast expression of unsupported type!"); - return make_error<ImportError>(ImportError::UnsupportedConstruct); + return make_error<ASTImportError>(ASTImportError::UnsupportedConstruct); } } @@ -7414,15 +7995,23 @@ ExpectedStmt ASTNodeImporter::VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) { // see VisitParmVarDecl). ParmVarDecl *ToParam = *ToParamOrErr; if (!ToParam->getDefaultArg()) { - Optional<ParmVarDecl *> FromParam = Importer.getImportedFromDecl(ToParam); + std::optional<ParmVarDecl *> FromParam = + Importer.getImportedFromDecl(ToParam); assert(FromParam && "ParmVarDecl was not imported?"); if (Error Err = ImportDefaultArgOfParmVarDecl(*FromParam, ToParam)) return std::move(Err); } - + Expr *RewrittenInit = nullptr; + if (E->hasRewrittenInit()) { + ExpectedExpr ExprOrErr = import(E->getRewrittenExpr()); + if (!ExprOrErr) + return ExprOrErr.takeError(); + RewrittenInit = ExprOrErr.get(); + } return CXXDefaultArgExpr::Create(Importer.getToContext(), *ToUsedLocOrErr, - *ToParamOrErr, *UsedContextOrErr); + *ToParamOrErr, RewrittenInit, + *UsedContextOrErr); } ExpectedStmt @@ -7540,16 +8129,14 @@ ExpectedStmt ASTNodeImporter::VisitSizeOfPackExpr(SizeOfPackExpr *E) { if (Err) return std::move(Err); - Optional<unsigned> Length; + std::optional<unsigned> Length; if (!E->isValueDependent()) Length = E->getPackLength(); SmallVector<TemplateArgument, 8> ToPartialArguments; if (E->isPartiallySubstituted()) { - if (Error Err = ImportTemplateArguments( - E->getPartialArguments().data(), - E->getPartialArguments().size(), - ToPartialArguments)) + if (Error Err = ImportTemplateArguments(E->getPartialArguments(), + ToPartialArguments)) return std::move(Err); } @@ -7615,12 +8202,14 @@ ExpectedStmt ASTNodeImporter::VisitCXXConstructExpr(CXXConstructExpr *E) { if (Error Err = ImportContainerChecked(E->arguments(), ToArgs)) return std::move(Err); - return CXXConstructExpr::Create( + CXXConstructExpr *ToE = CXXConstructExpr::Create( Importer.getToContext(), ToType, ToLocation, ToConstructor, E->isElidable(), ToArgs, E->hadMultipleCandidates(), E->isListInitialization(), E->isStdInitListInitialization(), E->requiresZeroInitialization(), E->getConstructionKind(), ToParenOrBraceRange); + ToE->setIsImmediateEscalating(E->isImmediateEscalating()); + return ToE; } ExpectedStmt ASTNodeImporter::VisitExprWithCleanups(ExprWithCleanups *E) { @@ -7663,8 +8252,8 @@ ExpectedStmt ASTNodeImporter::VisitCXXThisExpr(CXXThisExpr *E) { if (!ToLocationOrErr) return ToLocationOrErr.takeError(); - return new (Importer.getToContext()) CXXThisExpr( - *ToLocationOrErr, *ToTypeOrErr, E->isImplicit()); + return CXXThisExpr::Create(Importer.getToContext(), *ToLocationOrErr, + *ToTypeOrErr, E->isImplicit()); } ExpectedStmt ASTNodeImporter::VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E) { @@ -7676,8 +8265,8 @@ ExpectedStmt ASTNodeImporter::VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E) { if (!ToLocationOrErr) return ToLocationOrErr.takeError(); - return new (Importer.getToContext()) CXXBoolLiteralExpr( - E->getValue(), *ToTypeOrErr, *ToLocationOrErr); + return CXXBoolLiteralExpr::Create(Importer.getToContext(), E->getValue(), + *ToTypeOrErr, *ToLocationOrErr); } ExpectedStmt ASTNodeImporter::VisitMemberExpr(MemberExpr *E) { @@ -7839,7 +8428,7 @@ ExpectedStmt ASTNodeImporter::VisitCXXUnresolvedConstructExpr( return CXXUnresolvedConstructExpr::Create( Importer.getToContext(), ToType, ToTypeSourceInfo, ToLParenLoc, - llvm::makeArrayRef(ToArgs), ToRParenLoc); + llvm::ArrayRef(ToArgs), ToRParenLoc, E->isListInitialization()); } ExpectedStmt @@ -7881,10 +8470,13 @@ ASTNodeImporter::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E) { if (!ToTemplateKeywordLocOrErr) return ToTemplateKeywordLocOrErr.takeError(); + const bool KnownDependent = + (E->getDependence() & ExprDependence::TypeValue) == + ExprDependence::TypeValue; return UnresolvedLookupExpr::Create( Importer.getToContext(), *ToNamingClassOrErr, *ToQualifierLocOrErr, *ToTemplateKeywordLocOrErr, ToNameInfo, E->requiresADL(), &ToTAInfo, - ToDecls.begin(), ToDecls.end()); + ToDecls.begin(), ToDecls.end(), KnownDependent); } return UnresolvedLookupExpr::Create( @@ -8101,8 +8693,31 @@ ExpectedStmt ASTNodeImporter::VisitCXXDefaultInitExpr(CXXDefaultInitExpr *E) { if (!UsedContextOrErr) return UsedContextOrErr.takeError(); - return CXXDefaultInitExpr::Create( - Importer.getToContext(), *ToBeginLocOrErr, *ToFieldOrErr, *UsedContextOrErr); + FieldDecl *ToField = *ToFieldOrErr; + assert(ToField->hasInClassInitializer() && + "Field should have in-class initializer if there is a default init " + "expression that uses it."); + if (!ToField->getInClassInitializer()) { + // The in-class initializer may be not yet set in "To" AST even if the + // field is already there. This must be set here to make construction of + // CXXDefaultInitExpr work. + auto ToInClassInitializerOrErr = + import(E->getField()->getInClassInitializer()); + if (!ToInClassInitializerOrErr) + return ToInClassInitializerOrErr.takeError(); + ToField->setInClassInitializer(*ToInClassInitializerOrErr); + } + + Expr *RewrittenInit = nullptr; + if (E->hasRewrittenInit()) { + ExpectedExpr ExprOrErr = import(E->getRewrittenExpr()); + if (!ExprOrErr) + return ExprOrErr.takeError(); + RewrittenInit = ExprOrErr.get(); + } + + return CXXDefaultInitExpr::Create(Importer.getToContext(), *ToBeginLocOrErr, + ToField, *UsedContextOrErr, RewrittenInit); } ExpectedStmt ASTNodeImporter::VisitCXXNamedCastExpr(CXXNamedCastExpr *E) { @@ -8141,7 +8756,7 @@ ExpectedStmt ASTNodeImporter::VisitCXXNamedCastExpr(CXXNamedCastExpr *E) { ToOperatorLoc, ToRParenLoc, ToAngleBrackets); } else { llvm_unreachable("Unknown cast type"); - return make_error<ImportError>(); + return make_error<ASTImportError>(); } } @@ -8150,14 +8765,14 @@ ExpectedStmt ASTNodeImporter::VisitSubstNonTypeTemplateParmExpr( Error Err = Error::success(); auto ToType = importChecked(Err, E->getType()); auto ToExprLoc = importChecked(Err, E->getExprLoc()); - auto ToParameter = importChecked(Err, E->getParameter()); + auto ToAssociatedDecl = importChecked(Err, E->getAssociatedDecl()); auto ToReplacement = importChecked(Err, E->getReplacement()); if (Err) return std::move(Err); return new (Importer.getToContext()) SubstNonTypeTemplateParmExpr( - ToType, E->getValueKind(), ToExprLoc, ToParameter, - E->isReferenceParameter(), ToReplacement); + ToType, E->getValueKind(), ToExprLoc, ToReplacement, ToAssociatedDecl, + E->getIndex(), E->getPackIndex(), E->isReferenceParameter()); } ExpectedStmt ASTNodeImporter::VisitTypeTraitExpr(TypeTraitExpr *E) { @@ -8258,13 +8873,13 @@ ASTImporter::ASTImporter(ASTContext &ToContext, FileManager &ToFileManager, ASTImporter::~ASTImporter() = default; -Optional<unsigned> ASTImporter::getFieldIndex(Decl *F) { +std::optional<unsigned> ASTImporter::getFieldIndex(Decl *F) { assert(F && (isa<FieldDecl>(*F) || isa<IndirectFieldDecl>(*F)) && "Try to get field index for non-field."); auto *Owner = dyn_cast<RecordDecl>(F->getDeclContext()); if (!Owner) - return None; + return std::nullopt; unsigned Index = 0; for (const auto *D : Owner->decls()) { @@ -8277,7 +8892,7 @@ Optional<unsigned> ASTImporter::getFieldIndex(Decl *F) { llvm_unreachable("Field was not found in its parent context."); - return None; + return std::nullopt; } ASTImporter::FoundDeclsTy @@ -8336,10 +8951,10 @@ ASTImporter::Import(ExprWithCleanups::CleanupObject From) { // FIXME: Handle BlockDecl when we implement importing BlockExpr in // ASTNodeImporter. - return make_error<ImportError>(ImportError::UnsupportedConstruct); + return make_error<ASTImportError>(ASTImportError::UnsupportedConstruct); } -Expected<const Type *> ASTImporter::Import(const Type *FromT) { +ExpectedTypePtr ASTImporter::Import(const Type *FromT) { if (!FromT) return FromT; @@ -8349,7 +8964,7 @@ Expected<const Type *> ASTImporter::Import(const Type *FromT) { if (Pos != ImportedTypes.end()) return Pos->second; - // Import the type + // Import the type. ASTNodeImporter Importer(*this); ExpectedType ToTOrErr = Importer.Visit(FromT); if (!ToTOrErr) @@ -8365,7 +8980,7 @@ Expected<QualType> ASTImporter::Import(QualType FromT) { if (FromT.isNull()) return QualType{}; - Expected<const Type *> ToTyOrErr = Import(FromT.getTypePtr()); + ExpectedTypePtr ToTyOrErr = Import(FromT.getTypePtr()); if (!ToTyOrErr) return ToTyOrErr.takeError(); @@ -8388,67 +9003,301 @@ Expected<TypeSourceInfo *> ASTImporter::Import(TypeSourceInfo *FromTSI) { return ToContext.getTrivialTypeSourceInfo(*TOrErr, *BeginLocOrErr); } -Expected<Attr *> ASTImporter::Import(const Attr *FromAttr) { +namespace { +// To use this object, it should be created before the new attribute is created, +// and destructed after it is created. The construction already performs the +// import of the data. +template <typename T> struct AttrArgImporter { + AttrArgImporter(const AttrArgImporter<T> &) = delete; + AttrArgImporter(AttrArgImporter<T> &&) = default; + AttrArgImporter<T> &operator=(const AttrArgImporter<T> &) = delete; + AttrArgImporter<T> &operator=(AttrArgImporter<T> &&) = default; + + AttrArgImporter(ASTNodeImporter &I, Error &Err, const T &From) + : To(I.importChecked(Err, From)) {} + + const T &value() { return To; } + +private: + T To; +}; + +// To use this object, it should be created before the new attribute is created, +// and destructed after it is created. The construction already performs the +// import of the data. The array data is accessible in a pointer form, this form +// is used by the attribute classes. This object should be created once for the +// array data to be imported (the array size is not imported, just copied). +template <typename T> struct AttrArgArrayImporter { + AttrArgArrayImporter(const AttrArgArrayImporter<T> &) = delete; + AttrArgArrayImporter(AttrArgArrayImporter<T> &&) = default; + AttrArgArrayImporter<T> &operator=(const AttrArgArrayImporter<T> &) = delete; + AttrArgArrayImporter<T> &operator=(AttrArgArrayImporter<T> &&) = default; + + AttrArgArrayImporter(ASTNodeImporter &I, Error &Err, + const llvm::iterator_range<T *> &From, + unsigned ArraySize) { + if (Err) + return; + To.reserve(ArraySize); + Err = I.ImportContainerChecked(From, To); + } + + T *value() { return To.data(); } + +private: + llvm::SmallVector<T, 2> To; +}; + +class AttrImporter { + Error Err{Error::success()}; Attr *ToAttr = nullptr; - SourceRange ToRange; - if (Error Err = importInto(ToRange, FromAttr->getRange())) - return std::move(Err); + ASTImporter &Importer; + ASTNodeImporter NImporter; + +public: + AttrImporter(ASTImporter &I) : Importer(I), NImporter(I) {} + + // Useful for accessing the imported attribute. + template <typename T> T *castAttrAs() { return cast<T>(ToAttr); } + template <typename T> const T *castAttrAs() const { return cast<T>(ToAttr); } + + // Create an "importer" for an attribute parameter. + // Result of the 'value()' of that object is to be passed to the function + // '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 + // 'importAttr', then the size of the array as next argument. + template <typename T> + AttrArgArrayImporter<T> importArrayArg(const llvm::iterator_range<T *> &From, + unsigned ArraySize) { + return AttrArgArrayImporter<T>(NImporter, Err, From, ArraySize); + } + + // Create an attribute object with the specified arguments. + // The 'FromAttr' is the original (not imported) attribute, the 'ImportedArg' + // should be values that are passed to the 'Create' function of the attribute. + // (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> + 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 = + Importer.Import(FromAttr->getScopeName()); + SourceRange ToAttrRange = + NImporter.importChecked(Err, FromAttr->getRange()); + SourceLocation ToScopeLoc = + NImporter.importChecked(Err, FromAttr->getScopeLoc()); + + if (Err) + return; + + AttributeCommonInfo ToI(ToAttrName, ToScopeName, ToAttrRange, ToScopeLoc, + FromAttr->getParsedKind(), FromAttr->getForm()); + // The "SemanticSpelling" is not needed to be passed to the constructor. + // That value is recalculated from the SpellingListIndex if needed. + 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); + ToAttr->setAttrName(Importer.Import(FromAttr->getAttrName())); + } + + // 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; + } +}; +} // namespace + +Expected<Attr *> ASTImporter::Import(const Attr *FromAttr) { + 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::AlignValue: { + auto *From = cast<AlignValueAttr>(FromAttr); + AI.importAttr(From, AI.importArg(From->getAlignment()).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; } - 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); + + case attr::EnableIf: { + const auto *From = cast<EnableIfAttr>(FromAttr); + AI.importAttr(From, AI.importArg(From->getCond()).value(), + From->getMessage()); + break; + } + + case attr::AssertCapability: { + const auto *From = cast<AssertCapabilityAttr>(FromAttr); + AI.importAttr(From, + AI.importArrayArg(From->args(), From->args_size()).value(), + From->args_size()); + break; + } + case attr::AcquireCapability: { + const auto *From = cast<AcquireCapabilityAttr>(FromAttr); + AI.importAttr(From, + AI.importArrayArg(From->args(), From->args_size()).value(), + From->args_size()); + break; + } + case attr::TryAcquireCapability: { + const auto *From = cast<TryAcquireCapabilityAttr>(FromAttr); + 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); + AI.importAttr(From, + AI.importArrayArg(From->args(), From->args_size()).value(), + From->args_size()); + break; + } + case attr::RequiresCapability: { + const auto *From = cast<RequiresCapabilityAttr>(FromAttr); + AI.importAttr(From, + AI.importArrayArg(From->args(), From->args_size()).value(), + From->args_size()); + break; + } + case attr::GuardedBy: { + const auto *From = cast<GuardedByAttr>(FromAttr); + AI.importAttr(From, AI.importArg(From->getArg()).value()); + break; + } + case attr::PtGuardedBy: { + const auto *From = cast<PtGuardedByAttr>(FromAttr); + AI.importAttr(From, AI.importArg(From->getArg()).value()); + break; + } + case attr::AcquiredAfter: { + const auto *From = cast<AcquiredAfterAttr>(FromAttr); + AI.importAttr(From, + AI.importArrayArg(From->args(), From->args_size()).value(), + From->args_size()); + break; + } + case attr::AcquiredBefore: { + const auto *From = cast<AcquiredBeforeAttr>(FromAttr); + AI.importAttr(From, + AI.importArrayArg(From->args(), From->args_size()).value(), + From->args_size()); + break; + } + case attr::AssertExclusiveLock: { + const auto *From = cast<AssertExclusiveLockAttr>(FromAttr); + AI.importAttr(From, + AI.importArrayArg(From->args(), From->args_size()).value(), + From->args_size()); + break; + } + case attr::AssertSharedLock: { + const auto *From = cast<AssertSharedLockAttr>(FromAttr); + AI.importAttr(From, + AI.importArrayArg(From->args(), From->args_size()).value(), + From->args_size()); break; } - assert(ToAttr && "Attribute should be created."); - - return ToAttr; + case attr::ExclusiveTrylockFunction: { + const auto *From = cast<ExclusiveTrylockFunctionAttr>(FromAttr); + 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); + 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); + AI.importAttr(From, AI.importArg(From->getArg()).value()); + break; + } + case attr::LocksExcluded: { + const auto *From = cast<LocksExcludedAttr>(FromAttr); + AI.importAttr(From, + AI.importArrayArg(From->args(), From->args_size()).value(), + From->args_size()); + break; + } + case attr::CountedBy: { + AI.cloneAttr(FromAttr); + const auto *CBA = cast<CountedByAttr>(FromAttr); + Expected<SourceRange> SR = Import(CBA->getCountedByFieldLoc()).get(); + if (!SR) + return SR.takeError(); + AI.castAttrAs<CountedByAttr>()->setCountedByFieldLoc(SR.get()); + break; + } + + 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; + } + } + + return std::move(AI).getResult(); } Decl *ASTImporter::GetAlreadyImportedOrNull(const Decl *FromD) const { - auto Pos = ImportedDecls.find(FromD); - if (Pos != ImportedDecls.end()) - return Pos->second; - else - return nullptr; + return ImportedDecls.lookup(FromD); } TranslationUnitDecl *ASTImporter::GetFromTU(Decl *ToD) { @@ -8458,6 +9307,19 @@ TranslationUnitDecl *ASTImporter::GetFromTU(Decl *ToD) { return FromDPos->second->getTranslationUnitDecl(); } +Error ASTImporter::ImportAttrs(Decl *ToD, Decl *FromD) { + if (!FromD->hasAttrs() || ToD->hasAttrs()) + return Error::success(); + for (const Attr *FromAttr : FromD->getAttrs()) { + auto ToAttrOrErr = Import(FromAttr); + if (ToAttrOrErr) + ToD->addAttr(*ToAttrOrErr); + else + return ToAttrOrErr.takeError(); + } + return Error::success(); +} + Expected<Decl *> ASTImporter::Import(Decl *FromD) { if (!FromD) return nullptr; @@ -8470,7 +9332,7 @@ Expected<Decl *> ASTImporter::Import(Decl *FromD) { // Check whether there was a previous failed import. // If yes return the existing error. if (auto Error = getImportDeclErrorIfAny(FromD)) - return make_error<ImportError>(*Error); + return make_error<ASTImportError>(*Error); // Check whether we've already imported this declaration. Decl *ToD = GetAlreadyImportedOrNull(FromD); @@ -8478,7 +9340,7 @@ Expected<Decl *> ASTImporter::Import(Decl *FromD) { // Already imported (possibly from another TU) and with an error. if (auto Error = SharedState->getImportDeclErrorIfAny(ToD)) { setImportDeclError(FromD, *Error); - return make_error<ImportError>(*Error); + return make_error<ASTImportError>(*Error); } // If FromD has some updated flags after last import, apply it. @@ -8530,9 +9392,9 @@ Expected<Decl *> ASTImporter::Import(Decl *FromD) { // Error encountered for the first time. // After takeError the error is not usable any more in ToDOrErr. // Get a copy of the error object (any more simple solution for this?). - ImportError ErrOut; + ASTImportError ErrOut; handleAllErrors(ToDOrErr.takeError(), - [&ErrOut](const ImportError &E) { ErrOut = E; }); + [&ErrOut](const ASTImportError &E) { ErrOut = E; }); setImportDeclError(FromD, ErrOut); // Set the error for the mapped to Decl, which is in the "to" context. if (Pos != ImportedDecls.end()) @@ -8540,8 +9402,20 @@ Expected<Decl *> ASTImporter::Import(Decl *FromD) { // Set the error for all nodes which have been created before we // recognized the error. - for (const auto &Path : SavedImportPaths[FromD]) + for (const auto &Path : SavedImportPaths[FromD]) { + // The import path contains import-dependency nodes first. + // Save the node that was imported as dependency of the current node. + Decl *PrevFromDi = FromD; for (Decl *FromDi : Path) { + // Begin and end of the path equals 'FromD', skip it. + if (FromDi == FromD) + continue; + // We should not set import error on a node and all following nodes in + // the path if child import errors are ignored. + if (ChildErrorHandlingStrategy(FromDi).ignoreChildErrorOnParent( + PrevFromDi)) + break; + PrevFromDi = FromDi; setImportDeclError(FromDi, ErrOut); //FIXME Should we remove these Decls from ImportedDecls? // Set the error for the mapped to Decl, which is in the "to" context. @@ -8551,10 +9425,11 @@ Expected<Decl *> ASTImporter::Import(Decl *FromD) { // FIXME Should we remove these Decls from the LookupTable, // and from ImportedFromDecls? } + } SavedImportPaths.erase(FromD); // Do not return ToDOrErr, error was taken out of it. - return make_error<ImportError>(ErrOut); + return make_error<ASTImportError>(ErrOut); } ToD = *ToDOrErr; @@ -8566,7 +9441,7 @@ Expected<Decl *> ASTImporter::Import(Decl *FromD) { if (!ToD) { auto Err = getImportDeclErrorIfAny(FromD); assert(Err); - return make_error<ImportError>(*Err); + return make_error<ASTImportError>(*Err); } // We could import from the current TU without error. But previously we @@ -8574,20 +9449,12 @@ Expected<Decl *> ASTImporter::Import(Decl *FromD) { // ASTImporter object) and with an error. if (auto Error = SharedState->getImportDeclErrorIfAny(ToD)) { setImportDeclError(FromD, *Error); - return make_error<ImportError>(*Error); + return make_error<ASTImportError>(*Error); } - // Make sure that ImportImpl registered the imported decl. assert(ImportedDecls.count(FromD) != 0 && "Missing call to MapImported?"); - - if (FromD->hasAttrs()) - for (const Attr *FromAttr : FromD->getAttrs()) { - auto ToAttrOrErr = Import(FromAttr); - if (ToAttrOrErr) - ToD->addAttr(*ToAttrOrErr); - else - return ToAttrOrErr.takeError(); - } + if (auto Error = ImportAttrs(ToD, FromD)) + return std::move(Error); // Notify subclasses. Imported(FromD, ToD); @@ -8597,6 +9464,11 @@ Expected<Decl *> ASTImporter::Import(Decl *FromD) { return ToDOrErr; } +llvm::Expected<InheritedConstructor> +ASTImporter::Import(const InheritedConstructor &From) { + return ASTNodeImporter(*this).ImportInheritedConstructor(From); +} + Expected<DeclContext *> ASTImporter::ImportContext(DeclContext *FromDC) { if (!FromDC) return FromDC; @@ -8741,12 +9613,11 @@ ASTImporter::Import(NestedNameSpecifier *FromNNS) { case NestedNameSpecifier::TypeSpec: case NestedNameSpecifier::TypeSpecWithTemplate: - if (Expected<QualType> TyOrErr = - Import(QualType(FromNNS->getAsType(), 0u))) { + if (ExpectedTypePtr TyOrErr = Import(FromNNS->getAsType())) { bool TSTemplate = FromNNS->getKind() == NestedNameSpecifier::TypeSpecWithTemplate; return NestedNameSpecifier::Create(ToContext, Prefix, TSTemplate, - TyOrErr->getTypePtr()); + *TyOrErr); } else { return TyOrErr.takeError(); } @@ -8845,7 +9716,7 @@ Expected<TemplateName> ASTImporter::Import(TemplateName From) { switch (From.getKind()) { case TemplateName::Template: if (ExpectedDecl ToTemplateOrErr = Import(From.getAsTemplateDecl())) - return TemplateName(cast<TemplateDecl>(*ToTemplateOrErr)); + return TemplateName(cast<TemplateDecl>((*ToTemplateOrErr)->getCanonicalDecl())); else return ToTemplateOrErr.takeError(); @@ -8875,13 +9746,11 @@ Expected<TemplateName> ASTImporter::Import(TemplateName From) { auto QualifierOrErr = Import(QTN->getQualifier()); if (!QualifierOrErr) return QualifierOrErr.takeError(); - - if (ExpectedDecl ToTemplateOrErr = Import(From.getAsTemplateDecl())) - return ToContext.getQualifiedTemplateName( - *QualifierOrErr, QTN->hasTemplateKeyword(), - cast<TemplateDecl>(*ToTemplateOrErr)); - else - return ToTemplateOrErr.takeError(); + auto TNOrErr = Import(QTN->getUnderlyingTemplate()); + if (!TNOrErr) + return TNOrErr.takeError(); + return ToContext.getQualifiedTemplateName( + *QualifierOrErr, QTN->hasTemplateKeyword(), *TNOrErr); } case TemplateName::DependentTemplate: { @@ -8902,33 +9771,41 @@ Expected<TemplateName> ASTImporter::Import(TemplateName From) { case TemplateName::SubstTemplateTemplateParm: { SubstTemplateTemplateParmStorage *Subst = From.getAsSubstTemplateTemplateParm(); - ExpectedDecl ParamOrErr = Import(Subst->getParameter()); - if (!ParamOrErr) - return ParamOrErr.takeError(); - auto ReplacementOrErr = Import(Subst->getReplacement()); if (!ReplacementOrErr) return ReplacementOrErr.takeError(); + auto AssociatedDeclOrErr = Import(Subst->getAssociatedDecl()); + if (!AssociatedDeclOrErr) + return AssociatedDeclOrErr.takeError(); + return ToContext.getSubstTemplateTemplateParm( - cast<TemplateTemplateParmDecl>(*ParamOrErr), *ReplacementOrErr); + *ReplacementOrErr, *AssociatedDeclOrErr, Subst->getIndex(), + Subst->getPackIndex()); } case TemplateName::SubstTemplateTemplateParmPack: { - SubstTemplateTemplateParmPackStorage *SubstPack - = From.getAsSubstTemplateTemplateParmPack(); - ExpectedDecl ParamOrErr = Import(SubstPack->getParameterPack()); - if (!ParamOrErr) - return ParamOrErr.takeError(); - + SubstTemplateTemplateParmPackStorage *SubstPack = + From.getAsSubstTemplateTemplateParmPack(); ASTNodeImporter Importer(*this); auto ArgPackOrErr = Importer.ImportTemplateArgument(SubstPack->getArgumentPack()); if (!ArgPackOrErr) return ArgPackOrErr.takeError(); + auto AssociatedDeclOrErr = Import(SubstPack->getAssociatedDecl()); + if (!AssociatedDeclOrErr) + return AssociatedDeclOrErr.takeError(); + return ToContext.getSubstTemplateTemplateParmPack( - cast<TemplateTemplateParmDecl>(*ParamOrErr), *ArgPackOrErr); + *ArgPackOrErr, *AssociatedDeclOrErr, SubstPack->getIndex(), + SubstPack->getFinal()); + } + case TemplateName::UsingTemplate: { + auto UsingOrError = Import(From.getAsUsingShadowDecl()); + if (!UsingOrError) + return UsingOrError.takeError(); + return TemplateName(cast<UsingShadowDecl>(*UsingOrError)); } } @@ -8979,13 +9856,13 @@ Expected<FileID> ASTImporter::Import(FileID FromID, bool IsBuiltin) { ExpectedSLoc ToExLocS = Import(FromEx.getExpansionLocStart()); if (!ToExLocS) return ToExLocS.takeError(); - unsigned TokenLen = FromSM.getFileIDSize(FromID); + unsigned ExLength = FromSM.getFileIDSize(FromID); SourceLocation MLoc; if (FromEx.isMacroArgExpansion()) { - MLoc = ToSM.createMacroArgExpansionLoc(*ToSpLoc, *ToExLocS, TokenLen); + MLoc = ToSM.createMacroArgExpansionLoc(*ToSpLoc, *ToExLocS, ExLength); } else { if (ExpectedSLoc ToExLocE = Import(FromEx.getExpansionLocEnd())) - MLoc = ToSM.createExpansionLoc(*ToSpLoc, *ToExLocS, *ToExLocE, TokenLen, + MLoc = ToSM.createExpansionLoc(*ToSpLoc, *ToExLocS, *ToExLocE, ExLength, FromEx.isExpansionTokenRange()); else return ToExLocE.takeError(); @@ -9027,11 +9904,11 @@ Expected<FileID> ASTImporter::Import(FileID FromID, bool IsBuiltin) { if (ToID.isInvalid() || IsBuiltin) { // FIXME: We want to re-use the existing MemoryBuffer! - llvm::Optional<llvm::MemoryBufferRef> FromBuf = + std::optional<llvm::MemoryBufferRef> FromBuf = Cache->getBufferOrNone(FromContext.getDiagnostics(), FromSM.getFileManager(), SourceLocation{}); if (!FromBuf) - return llvm::make_error<ImportError>(ImportError::Unknown); + return llvm::make_error<ASTImportError>(ASTImportError::Unknown); std::unique_ptr<llvm::MemoryBuffer> ToBuf = llvm::MemoryBuffer::getMemBufferCopy(FromBuf->getBuffer(), @@ -9107,7 +9984,7 @@ Expected<CXXCtorInitializer *> ASTImporter::Import(CXXCtorInitializer *From) { *ToExprOrErr, *RParenLocOrErr); } else { // FIXME: assert? - return make_error<ImportError>(); + return make_error<ASTImportError>(); } } @@ -9381,16 +10258,14 @@ ASTNodeImporter::ImportAPValue(const APValue &FromValue) { } } else { FromElemTy = FromValue.getLValueBase().getTypeInfoType(); - QualType ImpTypeInfo = importChecked( - Err, - QualType(FromValue.getLValueBase().get<TypeInfoLValue>().getType(), - 0)); + const Type *ImpTypeInfo = importChecked( + Err, FromValue.getLValueBase().get<TypeInfoLValue>().getType()); QualType ImpType = importChecked(Err, FromValue.getLValueBase().getTypeInfoType()); if (Err) return std::move(Err); - Base = APValue::LValueBase::getTypeInfo( - TypeInfoLValue(ImpTypeInfo.getTypePtr()), ImpType); + Base = APValue::LValueBase::getTypeInfo(TypeInfoLValue(ImpTypeInfo), + ImpType); } } CharUnits Offset = FromValue.getLValueOffset(); @@ -9438,7 +10313,7 @@ Expected<DeclarationName> ASTImporter::HandleNameConflict(DeclarationName Name, unsigned NumDecls) { if (ODRHandling == ODRHandlingType::Conservative) // Report error at any name conflict. - return make_error<ImportError>(ImportError::NameConflict); + return make_error<ASTImportError>(ASTImportError::NameConflict); else // Allow to create the new Decl with the same name. return Name; @@ -9498,16 +10373,16 @@ Decl *ASTImporter::MapImported(Decl *From, Decl *To) { return To; } -llvm::Optional<ImportError> +std::optional<ASTImportError> ASTImporter::getImportDeclErrorIfAny(Decl *FromD) const { auto Pos = ImportDeclErrors.find(FromD); if (Pos != ImportDeclErrors.end()) return Pos->second; else - return Optional<ImportError>(); + return std::nullopt; } -void ASTImporter::setImportDeclError(Decl *From, ImportError Error) { +void ASTImporter::setImportDeclError(Decl *From, ASTImportError Error) { auto InsertRes = ImportDeclErrors.insert({From, Error}); (void)InsertRes; // Either we set the error for the first time, or we already had set one and |