aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/clang/lib/AST/ASTImporter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/clang/lib/AST/ASTImporter.cpp')
-rw-r--r--contrib/llvm-project/clang/lib/AST/ASTImporter.cpp2269
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