blob: a549cf9f899ee12a2eae5158c4fc80a69732885b [file] [log] [blame]
//===- ASTImporter.cpp - Importing ASTs from other Contexts ---------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file defines the ASTImporter class which imports AST nodes from one
// context into another context.
//
//===----------------------------------------------------------------------===//
#include "clang/AST/ASTImporter.h"
#include "clang/AST/ASTImporterSharedState.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTDiagnostic.h"
#include "clang/AST/ASTStructuralEquivalence.h"
#include "clang/AST/Attr.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclAccessPair.h"
#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclFriend.h"
#include "clang/AST/DeclGroup.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/DeclVisitor.h"
#include "clang/AST/DeclarationName.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
#include "clang/AST/ExternalASTSource.h"
#include "clang/AST/LambdaCapture.h"
#include "clang/AST/NestedNameSpecifier.h"
#include "clang/AST/OperationKinds.h"
#include "clang/AST/Stmt.h"
#include "clang/AST/StmtCXX.h"
#include "clang/AST/StmtObjC.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/AST/TemplateBase.h"
#include "clang/AST/TemplateName.h"
#include "clang/AST/Type.h"
#include "clang/AST/TypeLoc.h"
#include "clang/AST/TypeVisitor.h"
#include "clang/AST/UnresolvedSet.h"
#include "clang/Basic/ExceptionSpecificationType.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/Specifiers.h"
#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/SmallVector.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MemoryBuffer.h"
#include <algorithm>
#include <cassert>
#include <cstddef>
#include <memory>
#include <type_traits>
#include <utility>
namespace clang {
using llvm::make_error;
using llvm::Error;
using llvm::Expected;
using ExpectedType = llvm::Expected<QualType>;
using ExpectedStmt = llvm::Expected<Stmt *>;
using ExpectedExpr = llvm::Expected<Expr *>;
using ExpectedDecl = llvm::Expected<Decl *>;
using ExpectedSLoc = llvm::Expected<SourceLocation>;
using ExpectedName = llvm::Expected<DeclarationName>;
std::string ImportError::toString() const {
// FIXME: Improve error texts.
switch (Error) {
case NameConflict:
return "NameConflict";
case UnsupportedConstruct:
return "UnsupportedConstruct";
case Unknown:
return "Unknown error";
}
llvm_unreachable("Invalid error code.");
return "Invalid error code.";
}
void ImportError::log(raw_ostream &OS) const {
OS << toString();
}
std::error_code ImportError::convertToErrorCode() const {
llvm_unreachable("Function not implemented.");
}
char ImportError::ID;
template <class T>
SmallVector<Decl *, 2>
getCanonicalForwardRedeclChain(Redeclarable<T>* D) {
SmallVector<Decl *, 2> Redecls;
for (auto *R : D->getFirstDecl()->redecls()) {
if (R != D->getFirstDecl())
Redecls.push_back(R);
}
Redecls.push_back(D->getFirstDecl());
std::reverse(Redecls.begin(), Redecls.end());
return Redecls;
}
SmallVector<Decl*, 2> getCanonicalForwardRedeclChain(Decl* D) {
if (auto *FD = dyn_cast<FunctionDecl>(D))
return getCanonicalForwardRedeclChain<FunctionDecl>(FD);
if (auto *VD = dyn_cast<VarDecl>(D))
return getCanonicalForwardRedeclChain<VarDecl>(VD);
if (auto *TD = dyn_cast<TagDecl>(D))
return getCanonicalForwardRedeclChain<TagDecl>(TD);
llvm_unreachable("Bad declaration kind");
}
void updateFlags(const Decl *From, Decl *To) {
// Check if some flags or attrs are new in 'From' and copy into 'To'.
// FIXME: Other flags or attrs?
if (From->isUsed(false) && !To->isUsed(false))
To->setIsUsed();
}
class ASTNodeImporter : public TypeVisitor<ASTNodeImporter, ExpectedType>,
public DeclVisitor<ASTNodeImporter, ExpectedDecl>,
public StmtVisitor<ASTNodeImporter, ExpectedStmt> {
ASTImporter &Importer;
// Use this instead of Importer.importInto .
template <typename ImportT>
LLVM_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) {
auto ToOrErr = Importer.Import(From);
if (ToOrErr)
To = cast_or_null<ImportT>(*ToOrErr);
return ToOrErr.takeError();
}
// 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 ToOrErr = Importer.Import(From);
if (!ToOrErr)
return ToOrErr.takeError();
return cast_or_null<T>(*ToOrErr);
}
template <typename T>
Expected<T *> import(const T *From) {
return import(const_cast<T *>(From));
}
// Call the import function of ASTImporter for type `T`.
template <typename T>
Expected<T> import(const T &From) {
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) {
if (!From)
return Optional<T>();
return import(*From);
}
template <class T>
Expected<std::tuple<T>>
importSeq(const T &From) {
Expected<T> ToOrErr = import(From);
if (!ToOrErr)
return ToOrErr.takeError();
return std::make_tuple<T>(std::move(*ToOrErr));
}
// Import multiple objects with a single function call.
// This should work for every type for which a variant of `import` exists.
// The arguments are processed from left to right and import is stopped on
// first error.
template <class THead, class... TTail>
Expected<std::tuple<THead, TTail...>>
importSeq(const THead &FromHead, const TTail &...FromTail) {
Expected<std::tuple<THead>> ToHeadOrErr = importSeq(FromHead);
if (!ToHeadOrErr)
return ToHeadOrErr.takeError();
Expected<std::tuple<TTail...>> ToTailOrErr = importSeq(FromTail...);
if (!ToTailOrErr)
return ToTailOrErr.takeError();
return std::tuple_cat(*ToHeadOrErr, *ToTailOrErr);
}
// Wrapper for an overload set.
template <typename ToDeclT> struct CallOverloadedCreateFun {
template <typename... Args>
auto operator()(Args &&... args)
-> decltype(ToDeclT::Create(std::forward<Args>(args)...)) {
return ToDeclT::Create(std::forward<Args>(args)...);
}
};
// Always use these functions to create a Decl during import. There are
// certain tasks which must be done after the Decl was created, e.g. we
// must immediately register that as an imported Decl. The parameter `ToD`
// will be set to the newly created Decl or if had been imported before
// 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) {
// 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.
CallOverloadedCreateFun<ToDeclT> OC;
return GetImportedOrCreateSpecialDecl(ToD, OC, FromD,
std::forward<Args>(args)...);
}
// Use this overload if a special Type is needed to be created. E.g if we
// want to create a `TypeAliasDecl` and assign that to a `TypedefNameDecl`
// then:
// TypedefNameDecl *ToTypedef;
// GetImportedOrCreateDecl<TypeAliasDecl>(ToTypedef, FromD, ...);
template <typename NewDeclT, typename ToDeclT, typename FromDeclT,
typename... Args>
LLVM_NODISCARD bool GetImportedOrCreateDecl(ToDeclT *&ToD, FromDeclT *FromD,
Args &&... args) {
CallOverloadedCreateFun<NewDeclT> OC;
return GetImportedOrCreateSpecialDecl(ToD, OC, FromD,
std::forward<Args>(args)...);
}
// Use this version if a special create function must be
// used, e.g. CXXRecordDecl::CreateLambda .
template <typename ToDeclT, typename CreateFunT, typename FromDeclT,
typename... Args>
LLVM_NODISCARD bool
GetImportedOrCreateSpecialDecl(ToDeclT *&ToD, CreateFunT CreateFun,
FromDeclT *FromD, Args &&... args) {
if (Importer.getImportDeclErrorIfAny(FromD)) {
ToD = nullptr;
return true; // Already imported but with error.
}
ToD = cast_or_null<ToDeclT>(Importer.GetAlreadyImportedOrNull(FromD));
if (ToD)
return true; // Already imported.
ToD = CreateFun(std::forward<Args>(args)...);
// Keep track of imported Decls.
Importer.RegisterImportedDecl(FromD, ToD);
InitializeImportedDecl(FromD, ToD);
return false; // A new Decl is created.
}
void InitializeImportedDecl(Decl *FromD, Decl *ToD) {
ToD->IdentifierNamespace = FromD->IdentifierNamespace;
if (FromD->hasAttrs())
for (const Attr *FromAttr : FromD->getAttrs()) {
// FIXME: Return of the error here is not possible until store of
// import errors is implemented.
auto ToAttrOrErr = import(FromAttr);
if (ToAttrOrErr)
ToD->addAttr(*ToAttrOrErr);
else
llvm::consumeError(ToAttrOrErr.takeError());
}
if (FromD->isUsed())
ToD->setIsUsed();
if (FromD->isImplicit())
ToD->setImplicit();
}
// Check if we have found an existing definition. Returns with that
// definition if yes, otherwise returns null.
Decl *FindAndMapDefinition(FunctionDecl *D, FunctionDecl *FoundFunction) {
const FunctionDecl *Definition = nullptr;
if (D->doesThisDeclarationHaveABody() &&
FoundFunction->hasBody(Definition))
return Importer.MapImported(D, const_cast<FunctionDecl *>(Definition));
return nullptr;
}
public:
explicit ASTNodeImporter(ASTImporter &Importer) : Importer(Importer) {}
using TypeVisitor<ASTNodeImporter, ExpectedType>::Visit;
using DeclVisitor<ASTNodeImporter, ExpectedDecl>::Visit;
using StmtVisitor<ASTNodeImporter, ExpectedStmt>::Visit;
// 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 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);
// Importing declarations
Error ImportDeclParts(
NamedDecl *D, DeclContext *&DC, DeclContext *&LexicalDC,
DeclarationName &Name, NamedDecl *&ToD, SourceLocation &Loc);
Error ImportDefinitionIfNeeded(Decl *FromD, Decl *ToD = nullptr);
Error ImportDeclarationNameLoc(
const DeclarationNameInfo &From, DeclarationNameInfo &To);
Error ImportDeclContext(DeclContext *FromDC, bool ForceImport = false);
Error ImportDeclContext(
Decl *From, DeclContext *&ToDC, DeclContext *&ToLexicalDC);
Error ImportImplicitMethods(const CXXRecordDecl *From, CXXRecordDecl *To);
Expected<CXXCastPath> ImportCastPath(CastExpr *E);
using Designator = DesignatedInitExpr::Designator;
/// What we should import from the definition.
enum ImportDefinitionKind {
/// Import the default subset of the definition, which might be
/// nothing (if minimal import is set) or might be everything (if minimal
/// import is not set).
IDK_Default,
/// Import everything.
IDK_Everything,
/// Import only the bare bones needed to establish a valid
/// DeclContext.
IDK_Basic
};
bool shouldForceImportDeclContext(ImportDefinitionKind IDK) {
return IDK == IDK_Everything ||
(IDK == IDK_Default && !Importer.isMinimalImport());
}
Error ImportInitializer(VarDecl *From, VarDecl *To);
Error ImportDefinition(
RecordDecl *From, RecordDecl *To,
ImportDefinitionKind Kind = IDK_Default);
Error ImportDefinition(
EnumDecl *From, EnumDecl *To,
ImportDefinitionKind Kind = IDK_Default);
Error ImportDefinition(
ObjCInterfaceDecl *From, ObjCInterfaceDecl *To,
ImportDefinitionKind Kind = IDK_Default);
Error ImportDefinition(
ObjCProtocolDecl *From, ObjCProtocolDecl *To,
ImportDefinitionKind Kind = IDK_Default);
Error ImportTemplateArguments(
const TemplateArgument *FromArgs, unsigned NumFromArgs,
SmallVectorImpl<TemplateArgument> &ToArgs);
Expected<TemplateArgument>
ImportTemplateArgument(const TemplateArgument &From);
template <typename InContainerTy>
Error ImportTemplateArgumentListInfo(
const InContainerTy &Container, TemplateArgumentListInfo &ToTAInfo);
template<typename InContainerTy>
Error ImportTemplateArgumentListInfo(
SourceLocation FromLAngleLoc, SourceLocation FromRAngleLoc,
const InContainerTy &Container, TemplateArgumentListInfo &Result);
using TemplateArgsTy = SmallVector<TemplateArgument, 8>;
using FunctionTemplateAndArgsTy =
std::tuple<FunctionTemplateDecl *, TemplateArgsTy>;
Expected<FunctionTemplateAndArgsTy>
ImportFunctionTemplateWithTemplateArgsFromSpecialization(
FunctionDecl *FromFD);
Error ImportTemplateParameterLists(const DeclaratorDecl *FromD,
DeclaratorDecl *ToD);
Error ImportTemplateInformation(FunctionDecl *FromFD, FunctionDecl *ToFD);
Error ImportFunctionDeclBody(FunctionDecl *FromFD, FunctionDecl *ToFD);
Error ImportDefaultArgOfParmVarDecl(const ParmVarDecl *FromParam,
ParmVarDecl *ToParam);
template <typename T>
bool hasSameVisibilityContext(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);
ExpectedDecl VisitDecl(Decl *D);
ExpectedDecl VisitImportDecl(ImportDecl *D);
ExpectedDecl VisitEmptyDecl(EmptyDecl *D);
ExpectedDecl VisitAccessSpecDecl(AccessSpecDecl *D);
ExpectedDecl VisitStaticAssertDecl(StaticAssertDecl *D);
ExpectedDecl VisitTranslationUnitDecl(TranslationUnitDecl *D);
ExpectedDecl VisitNamespaceDecl(NamespaceDecl *D);
ExpectedDecl VisitNamespaceAliasDecl(NamespaceAliasDecl *D);
ExpectedDecl VisitTypedefNameDecl(TypedefNameDecl *D, bool IsAlias);
ExpectedDecl VisitTypedefDecl(TypedefDecl *D);
ExpectedDecl VisitTypeAliasDecl(TypeAliasDecl *D);
ExpectedDecl VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D);
ExpectedDecl VisitLabelDecl(LabelDecl *D);
ExpectedDecl VisitEnumDecl(EnumDecl *D);
ExpectedDecl VisitRecordDecl(RecordDecl *D);
ExpectedDecl VisitEnumConstantDecl(EnumConstantDecl *D);
ExpectedDecl VisitFunctionDecl(FunctionDecl *D);
ExpectedDecl VisitCXXMethodDecl(CXXMethodDecl *D);
ExpectedDecl VisitCXXConstructorDecl(CXXConstructorDecl *D);
ExpectedDecl VisitCXXDestructorDecl(CXXDestructorDecl *D);
ExpectedDecl VisitCXXConversionDecl(CXXConversionDecl *D);
ExpectedDecl VisitFieldDecl(FieldDecl *D);
ExpectedDecl VisitIndirectFieldDecl(IndirectFieldDecl *D);
ExpectedDecl VisitFriendDecl(FriendDecl *D);
ExpectedDecl VisitObjCIvarDecl(ObjCIvarDecl *D);
ExpectedDecl VisitVarDecl(VarDecl *D);
ExpectedDecl VisitImplicitParamDecl(ImplicitParamDecl *D);
ExpectedDecl VisitParmVarDecl(ParmVarDecl *D);
ExpectedDecl VisitObjCMethodDecl(ObjCMethodDecl *D);
ExpectedDecl VisitObjCTypeParamDecl(ObjCTypeParamDecl *D);
ExpectedDecl VisitObjCCategoryDecl(ObjCCategoryDecl *D);
ExpectedDecl VisitObjCProtocolDecl(ObjCProtocolDecl *D);
ExpectedDecl VisitLinkageSpecDecl(LinkageSpecDecl *D);
ExpectedDecl VisitUsingDecl(UsingDecl *D);
ExpectedDecl VisitUsingShadowDecl(UsingShadowDecl *D);
ExpectedDecl VisitUsingDirectiveDecl(UsingDirectiveDecl *D);
ExpectedDecl VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D);
ExpectedDecl VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D);
Expected<ObjCTypeParamList *>
ImportObjCTypeParamList(ObjCTypeParamList *list);
ExpectedDecl VisitObjCInterfaceDecl(ObjCInterfaceDecl *D);
ExpectedDecl VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D);
ExpectedDecl VisitObjCImplementationDecl(ObjCImplementationDecl *D);
ExpectedDecl VisitObjCPropertyDecl(ObjCPropertyDecl *D);
ExpectedDecl VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D);
ExpectedDecl VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D);
ExpectedDecl VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D);
ExpectedDecl VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D);
ExpectedDecl VisitClassTemplateDecl(ClassTemplateDecl *D);
ExpectedDecl VisitClassTemplateSpecializationDecl(
ClassTemplateSpecializationDecl *D);
ExpectedDecl VisitVarTemplateDecl(VarTemplateDecl *D);
ExpectedDecl VisitVarTemplateSpecializationDecl(VarTemplateSpecializationDecl *D);
ExpectedDecl VisitFunctionTemplateDecl(FunctionTemplateDecl *D);
// Importing statements
ExpectedStmt VisitStmt(Stmt *S);
ExpectedStmt VisitGCCAsmStmt(GCCAsmStmt *S);
ExpectedStmt VisitDeclStmt(DeclStmt *S);
ExpectedStmt VisitNullStmt(NullStmt *S);
ExpectedStmt VisitCompoundStmt(CompoundStmt *S);
ExpectedStmt VisitCaseStmt(CaseStmt *S);
ExpectedStmt VisitDefaultStmt(DefaultStmt *S);
ExpectedStmt VisitLabelStmt(LabelStmt *S);
ExpectedStmt VisitAttributedStmt(AttributedStmt *S);
ExpectedStmt VisitIfStmt(IfStmt *S);
ExpectedStmt VisitSwitchStmt(SwitchStmt *S);
ExpectedStmt VisitWhileStmt(WhileStmt *S);
ExpectedStmt VisitDoStmt(DoStmt *S);
ExpectedStmt VisitForStmt(ForStmt *S);
ExpectedStmt VisitGotoStmt(GotoStmt *S);
ExpectedStmt VisitIndirectGotoStmt(IndirectGotoStmt *S);
ExpectedStmt VisitContinueStmt(ContinueStmt *S);
ExpectedStmt VisitBreakStmt(BreakStmt *S);
ExpectedStmt VisitReturnStmt(ReturnStmt *S);
// FIXME: MSAsmStmt
// FIXME: SEHExceptStmt
// FIXME: SEHFinallyStmt
// FIXME: SEHTryStmt
// FIXME: SEHLeaveStmt
// FIXME: CapturedStmt
ExpectedStmt VisitCXXCatchStmt(CXXCatchStmt *S);
ExpectedStmt VisitCXXTryStmt(CXXTryStmt *S);
ExpectedStmt VisitCXXForRangeStmt(CXXForRangeStmt *S);
// FIXME: MSDependentExistsStmt
ExpectedStmt VisitObjCForCollectionStmt(ObjCForCollectionStmt *S);
ExpectedStmt VisitObjCAtCatchStmt(ObjCAtCatchStmt *S);
ExpectedStmt VisitObjCAtFinallyStmt(ObjCAtFinallyStmt *S);
ExpectedStmt VisitObjCAtTryStmt(ObjCAtTryStmt *S);
ExpectedStmt VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *S);
ExpectedStmt VisitObjCAtThrowStmt(ObjCAtThrowStmt *S);
ExpectedStmt VisitObjCAutoreleasePoolStmt(ObjCAutoreleasePoolStmt *S);
// Importing expressions
ExpectedStmt VisitExpr(Expr *E);
ExpectedStmt VisitVAArgExpr(VAArgExpr *E);
ExpectedStmt VisitChooseExpr(ChooseExpr *E);
ExpectedStmt VisitGNUNullExpr(GNUNullExpr *E);
ExpectedStmt VisitPredefinedExpr(PredefinedExpr *E);
ExpectedStmt VisitDeclRefExpr(DeclRefExpr *E);
ExpectedStmt VisitImplicitValueInitExpr(ImplicitValueInitExpr *E);
ExpectedStmt VisitDesignatedInitExpr(DesignatedInitExpr *E);
ExpectedStmt VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *E);
ExpectedStmt VisitIntegerLiteral(IntegerLiteral *E);
ExpectedStmt VisitFloatingLiteral(FloatingLiteral *E);
ExpectedStmt VisitImaginaryLiteral(ImaginaryLiteral *E);
ExpectedStmt VisitCharacterLiteral(CharacterLiteral *E);
ExpectedStmt VisitStringLiteral(StringLiteral *E);
ExpectedStmt VisitCompoundLiteralExpr(CompoundLiteralExpr *E);
ExpectedStmt VisitAtomicExpr(AtomicExpr *E);
ExpectedStmt VisitAddrLabelExpr(AddrLabelExpr *E);
ExpectedStmt VisitConstantExpr(ConstantExpr *E);
ExpectedStmt VisitParenExpr(ParenExpr *E);
ExpectedStmt VisitParenListExpr(ParenListExpr *E);
ExpectedStmt VisitStmtExpr(StmtExpr *E);
ExpectedStmt VisitUnaryOperator(UnaryOperator *E);
ExpectedStmt VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E);
ExpectedStmt VisitBinaryOperator(BinaryOperator *E);
ExpectedStmt VisitConditionalOperator(ConditionalOperator *E);
ExpectedStmt VisitBinaryConditionalOperator(BinaryConditionalOperator *E);
ExpectedStmt VisitOpaqueValueExpr(OpaqueValueExpr *E);
ExpectedStmt VisitArrayTypeTraitExpr(ArrayTypeTraitExpr *E);
ExpectedStmt VisitExpressionTraitExpr(ExpressionTraitExpr *E);
ExpectedStmt VisitArraySubscriptExpr(ArraySubscriptExpr *E);
ExpectedStmt VisitCompoundAssignOperator(CompoundAssignOperator *E);
ExpectedStmt VisitImplicitCastExpr(ImplicitCastExpr *E);
ExpectedStmt VisitExplicitCastExpr(ExplicitCastExpr *E);
ExpectedStmt VisitOffsetOfExpr(OffsetOfExpr *OE);
ExpectedStmt VisitCXXThrowExpr(CXXThrowExpr *E);
ExpectedStmt VisitCXXNoexceptExpr(CXXNoexceptExpr *E);
ExpectedStmt VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E);
ExpectedStmt VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E);
ExpectedStmt VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E);
ExpectedStmt VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *E);
ExpectedStmt VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E);
ExpectedStmt VisitPackExpansionExpr(PackExpansionExpr *E);
ExpectedStmt VisitSizeOfPackExpr(SizeOfPackExpr *E);
ExpectedStmt VisitCXXNewExpr(CXXNewExpr *E);
ExpectedStmt VisitCXXDeleteExpr(CXXDeleteExpr *E);
ExpectedStmt VisitCXXConstructExpr(CXXConstructExpr *E);
ExpectedStmt VisitCXXMemberCallExpr(CXXMemberCallExpr *E);
ExpectedStmt VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E);
ExpectedStmt VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E);
ExpectedStmt VisitCXXUnresolvedConstructExpr(CXXUnresolvedConstructExpr *E);
ExpectedStmt VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E);
ExpectedStmt VisitUnresolvedMemberExpr(UnresolvedMemberExpr *E);
ExpectedStmt VisitExprWithCleanups(ExprWithCleanups *E);
ExpectedStmt VisitCXXThisExpr(CXXThisExpr *E);
ExpectedStmt VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E);
ExpectedStmt VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *E);
ExpectedStmt VisitMemberExpr(MemberExpr *E);
ExpectedStmt VisitCallExpr(CallExpr *E);
ExpectedStmt VisitLambdaExpr(LambdaExpr *LE);
ExpectedStmt VisitInitListExpr(InitListExpr *E);
ExpectedStmt VisitCXXStdInitializerListExpr(CXXStdInitializerListExpr *E);
ExpectedStmt VisitCXXInheritedCtorInitExpr(CXXInheritedCtorInitExpr *E);
ExpectedStmt VisitArrayInitLoopExpr(ArrayInitLoopExpr *E);
ExpectedStmt VisitArrayInitIndexExpr(ArrayInitIndexExpr *E);
ExpectedStmt VisitCXXDefaultInitExpr(CXXDefaultInitExpr *E);
ExpectedStmt VisitCXXNamedCastExpr(CXXNamedCastExpr *E);
ExpectedStmt VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *E);
ExpectedStmt VisitTypeTraitExpr(TypeTraitExpr *E);
ExpectedStmt VisitCXXTypeidExpr(CXXTypeidExpr *E);
template<typename IIter, typename OIter>
Error ImportArrayChecked(IIter Ibegin, IIter Iend, OIter Obegin) {
using ItemT = typename std::remove_reference<decltype(*Obegin)>::type;
for (; Ibegin != Iend; ++Ibegin, ++Obegin) {
Expected<ItemT> ToOrErr = import(*Ibegin);
if (!ToOrErr)
return ToOrErr.takeError();
*Obegin = *ToOrErr;
}
return Error::success();
}
// Import every item from a container structure into an output container.
// If error occurs, stops at first error and returns the error.
// The output container should have space for all needed elements (it is not
// expanded, new items are put into from the beginning).
template<typename InContainerTy, typename OutContainerTy>
Error ImportContainerChecked(
const InContainerTy &InContainer, OutContainerTy &OutContainer) {
return ImportArrayChecked(
InContainer.begin(), InContainer.end(), OutContainer.begin());
}
template<typename InContainerTy, typename OIter>
Error ImportArrayChecked(const InContainerTy &InContainer, OIter Obegin) {
return ImportArrayChecked(InContainer.begin(), InContainer.end(), Obegin);
}
Error ImportOverriddenMethods(CXXMethodDecl *ToMethod,
CXXMethodDecl *FromMethod);
Expected<FunctionDecl *> FindFunctionTemplateSpecialization(
FunctionDecl *FromFD);
};
template <typename InContainerTy>
Error ASTNodeImporter::ImportTemplateArgumentListInfo(
SourceLocation FromLAngleLoc, SourceLocation FromRAngleLoc,
const InContainerTy &Container, TemplateArgumentListInfo &Result) {
auto ToLAngleLocOrErr = import(FromLAngleLoc);
if (!ToLAngleLocOrErr)
return ToLAngleLocOrErr.takeError();
auto ToRAngleLocOrErr = import(FromRAngleLoc);
if (!ToRAngleLocOrErr)
return ToRAngleLocOrErr.takeError();
TemplateArgumentListInfo ToTAInfo(*ToLAngleLocOrErr, *ToRAngleLocOrErr);
if (auto Err = ImportTemplateArgumentListInfo(Container, ToTAInfo))
return Err;
Result = ToTAInfo;
return Error::success();
}
template <>
Error ASTNodeImporter::ImportTemplateArgumentListInfo<TemplateArgumentListInfo>(
const TemplateArgumentListInfo &From, TemplateArgumentListInfo &Result) {
return ImportTemplateArgumentListInfo(
From.getLAngleLoc(), From.getRAngleLoc(), From.arguments(), Result);
}
template <>
Error ASTNodeImporter::ImportTemplateArgumentListInfo<
ASTTemplateArgumentListInfo>(
const ASTTemplateArgumentListInfo &From,
TemplateArgumentListInfo &Result) {
return ImportTemplateArgumentListInfo(
From.LAngleLoc, From.RAngleLoc, From.arguments(), Result);
}
Expected<ASTNodeImporter::FunctionTemplateAndArgsTy>
ASTNodeImporter::ImportFunctionTemplateWithTemplateArgsFromSpecialization(
FunctionDecl *FromFD) {
assert(FromFD->getTemplatedKind() ==
FunctionDecl::TK_FunctionTemplateSpecialization);
FunctionTemplateAndArgsTy Result;
auto *FTSInfo = FromFD->getTemplateSpecializationInfo();
if (Error Err = importInto(std::get<0>(Result), FTSInfo->getTemplate()))
return std::move(Err);
// Import template arguments.
auto TemplArgs = FTSInfo->TemplateArguments->asArray();
if (Error Err = ImportTemplateArguments(TemplArgs.data(), TemplArgs.size(),
std::get<1>(Result)))
return std::move(Err);
return Result;
}
template <>
Expected<TemplateParameterList *>
ASTNodeImporter::import(TemplateParameterList *From) {
SmallVector<NamedDecl *, 4> To(From->size());
if (Error Err = ImportContainerChecked(*From, To))
return std::move(Err);
ExpectedExpr ToRequiresClause = import(From->getRequiresClause());
if (!ToRequiresClause)
return ToRequiresClause.takeError();
auto ToTemplateLocOrErr = import(From->getTemplateLoc());
if (!ToTemplateLocOrErr)
return ToTemplateLocOrErr.takeError();
auto ToLAngleLocOrErr = import(From->getLAngleLoc());
if (!ToLAngleLocOrErr)
return ToLAngleLocOrErr.takeError();
auto ToRAngleLocOrErr = import(From->getRAngleLoc());
if (!ToRAngleLocOrErr)
return ToRAngleLocOrErr.takeError();
return TemplateParameterList::Create(
Importer.getToContext(),
*ToTemplateLocOrErr,
*ToLAngleLocOrErr,
To,
*ToRAngleLocOrErr,
*ToRequiresClause);
}
template <>
Expected<TemplateArgument>
ASTNodeImporter::import(const TemplateArgument &From) {
switch (From.getKind()) {
case TemplateArgument::Null:
return TemplateArgument();
case TemplateArgument::Type: {
ExpectedType ToTypeOrErr = import(From.getAsType());
if (!ToTypeOrErr)
return ToTypeOrErr.takeError();
return TemplateArgument(*ToTypeOrErr);
}
case TemplateArgument::Integral: {
ExpectedType ToTypeOrErr = import(From.getIntegralType());
if (!ToTypeOrErr)
return ToTypeOrErr.takeError();
return TemplateArgument(From, *ToTypeOrErr);
}
case TemplateArgument::Declaration: {
Expected<ValueDecl *> ToOrErr = import(From.getAsDecl());
if (!ToOrErr)
return ToOrErr.takeError();
ExpectedType ToTypeOrErr = import(From.getParamTypeForDecl());
if (!ToTypeOrErr)
return ToTypeOrErr.takeError();
return TemplateArgument(*ToOrErr, *ToTypeOrErr);
}
case TemplateArgument::NullPtr: {
ExpectedType ToTypeOrErr = import(From.getNullPtrType());
if (!ToTypeOrErr)
return ToTypeOrErr.takeError();
return TemplateArgument(*ToTypeOrErr, /*isNullPtr*/true);
}
case TemplateArgument::Template: {
Expected<TemplateName> ToTemplateOrErr = import(From.getAsTemplate());
if (!ToTemplateOrErr)
return ToTemplateOrErr.takeError();
return TemplateArgument(*ToTemplateOrErr);
}
case TemplateArgument::TemplateExpansion: {
Expected<TemplateName> ToTemplateOrErr =
import(From.getAsTemplateOrTemplatePattern());
if (!ToTemplateOrErr)
return ToTemplateOrErr.takeError();
return TemplateArgument(
*ToTemplateOrErr, From.getNumTemplateExpansions());
}
case TemplateArgument::Expression:
if (ExpectedExpr ToExpr = import(From.getAsExpr()))
return TemplateArgument(*ToExpr);
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))
return std::move(Err);
return TemplateArgument(
llvm::makeArrayRef(ToPack).copy(Importer.getToContext()));
}
}
llvm_unreachable("Invalid template argument kind");
}
template <>
Expected<TemplateArgumentLoc>
ASTNodeImporter::import(const TemplateArgumentLoc &TALoc) {
Expected<TemplateArgument> ArgOrErr = import(TALoc.getArgument());
if (!ArgOrErr)
return ArgOrErr.takeError();
TemplateArgument Arg = *ArgOrErr;
TemplateArgumentLocInfo FromInfo = TALoc.getLocInfo();
TemplateArgumentLocInfo ToInfo;
if (Arg.getKind() == TemplateArgument::Expression) {
ExpectedExpr E = import(FromInfo.getAsExpr());
if (!E)
return E.takeError();
ToInfo = TemplateArgumentLocInfo(*E);
} else if (Arg.getKind() == TemplateArgument::Type) {
if (auto TSIOrErr = import(FromInfo.getAsTypeSourceInfo()))
ToInfo = TemplateArgumentLocInfo(*TSIOrErr);
else
return TSIOrErr.takeError();
} else {
auto ToTemplateQualifierLocOrErr =
import(FromInfo.getTemplateQualifierLoc());
if (!ToTemplateQualifierLocOrErr)
return ToTemplateQualifierLocOrErr.takeError();
auto ToTemplateNameLocOrErr = import(FromInfo.getTemplateNameLoc());
if (!ToTemplateNameLocOrErr)
return ToTemplateNameLocOrErr.takeError();
auto ToTemplateEllipsisLocOrErr =
import(FromInfo.getTemplateEllipsisLoc());
if (!ToTemplateEllipsisLocOrErr)
return ToTemplateEllipsisLocOrErr.takeError();
ToInfo = TemplateArgumentLocInfo(
*ToTemplateQualifierLocOrErr,
*ToTemplateNameLocOrErr,
*ToTemplateEllipsisLocOrErr);
}
return TemplateArgumentLoc(Arg, ToInfo);
}
template <>
Expected<DeclGroupRef> ASTNodeImporter::import(const DeclGroupRef &DG) {
if (DG.isNull())
return DeclGroupRef::Create(Importer.getToContext(), nullptr, 0);
size_t NumDecls = DG.end() - DG.begin();
SmallVector<Decl *, 1> ToDecls;
ToDecls.reserve(NumDecls);
for (Decl *FromD : DG) {
if (auto ToDOrErr = import(FromD))
ToDecls.push_back(*ToDOrErr);
else
return ToDOrErr.takeError();
}
return DeclGroupRef::Create(Importer.getToContext(),
ToDecls.begin(),
NumDecls);
}
template <>
Expected<ASTNodeImporter::Designator>
ASTNodeImporter::import(const Designator &D) {
if (D.isFieldDesignator()) {
IdentifierInfo *ToFieldName = Importer.Import(D.getFieldName());
ExpectedSLoc ToDotLocOrErr = import(D.getDotLoc());
if (!ToDotLocOrErr)
return ToDotLocOrErr.takeError();
ExpectedSLoc ToFieldLocOrErr = import(D.getFieldLoc());
if (!ToFieldLocOrErr)
return ToFieldLocOrErr.takeError();
return Designator(ToFieldName, *ToDotLocOrErr, *ToFieldLocOrErr);
}
ExpectedSLoc ToLBracketLocOrErr = import(D.getLBracketLoc());
if (!ToLBracketLocOrErr)
return ToLBracketLocOrErr.takeError();
ExpectedSLoc ToRBracketLocOrErr = import(D.getRBracketLoc());
if (!ToRBracketLocOrErr)
return ToRBracketLocOrErr.takeError();
if (D.isArrayDesignator())
return Designator(D.getFirstExprIndex(),
*ToLBracketLocOrErr, *ToRBracketLocOrErr);
ExpectedSLoc ToEllipsisLocOrErr = import(D.getEllipsisLoc());
if (!ToEllipsisLocOrErr)
return ToEllipsisLocOrErr.takeError();
assert(D.isArrayRangeDesignator());
return Designator(
D.getFirstExprIndex(), *ToLBracketLocOrErr, *ToEllipsisLocOrErr,
*ToRBracketLocOrErr);
}
template <>
Expected<LambdaCapture> ASTNodeImporter::import(const LambdaCapture &From) {
VarDecl *Var = nullptr;
if (From.capturesVariable()) {
if (auto VarOrErr = import(From.getCapturedVar()))
Var = *VarOrErr;
else
return VarOrErr.takeError();
}
auto LocationOrErr = import(From.getLocation());
if (!LocationOrErr)
return LocationOrErr.takeError();
SourceLocation EllipsisLoc;
if (From.isPackExpansion())
if (Error Err = importInto(EllipsisLoc, From.getEllipsisLoc()))
return std::move(Err);
return LambdaCapture(
*LocationOrErr, From.isImplicit(), From.getCaptureKind(), Var,
EllipsisLoc);
}
template <typename T>
bool ASTNodeImporter::hasSameVisibilityContext(T *Found, T *From) {
if (From->hasExternalFormalLinkage())
return Found->hasExternalFormalLinkage();
if (Importer.GetFromTU(Found) != From->getTranslationUnitDecl())
return false;
if (From->isInAnonymousNamespace())
return Found->isInAnonymousNamespace();
else
return !Found->isInAnonymousNamespace() &&
!Found->hasExternalFormalLinkage();
}
template <>
bool ASTNodeImporter::hasSameVisibilityContext(TypedefNameDecl *Found,
TypedefNameDecl *From) {
if (From->isInAnonymousNamespace() && Found->isInAnonymousNamespace())
return Importer.GetFromTU(Found) == From->getTranslationUnitDecl();
return From->isInAnonymousNamespace() == Found->isInAnonymousNamespace();
}
} // namespace clang
//----------------------------------------------------------------------------
// Import Types
//----------------------------------------------------------------------------
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);
}
ExpectedType ASTNodeImporter::VisitAtomicType(const AtomicType *T){
ExpectedType UnderlyingTypeOrErr = import(T->getValueType());
if (!UnderlyingTypeOrErr)
return UnderlyingTypeOrErr.takeError();
return Importer.getToContext().getAtomicType(*UnderlyingTypeOrErr);
}
ExpectedType ASTNodeImporter::VisitBuiltinType(const BuiltinType *T) {
switch (T->getKind()) {
#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
case BuiltinType::Id: \
return Importer.getToContext().SingletonId;
#include "clang/Basic/OpenCLImageTypes.def"
#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
case BuiltinType::Id: \
return Importer.getToContext().Id##Ty;
#include "clang/Basic/OpenCLExtensionTypes.def"
#define SVE_TYPE(Name, Id, SingletonId) \
case BuiltinType::Id: \
return Importer.getToContext().SingletonId;
#include "clang/Basic/AArch64SVEACLETypes.def"
#define SHARED_SINGLETON_TYPE(Expansion)
#define BUILTIN_TYPE(Id, SingletonId) \
case BuiltinType::Id: return Importer.getToContext().SingletonId;
#include "clang/AST/BuiltinTypes.def"
// FIXME: for Char16, Char32, and NullPtr, make sure that the "to"
// context supports C++.
// FIXME: for ObjCId, ObjCClass, and ObjCSel, make sure that the "to"
// context supports ObjC.
case BuiltinType::Char_U:
// The context we're importing from has an unsigned 'char'. If we're
// importing into a context with a signed 'char', translate to
// 'unsigned char' instead.
if (Importer.getToContext().getLangOpts().CharIsSigned)
return Importer.getToContext().UnsignedCharTy;
return Importer.getToContext().CharTy;
case BuiltinType::Char_S:
// The context we're importing from has an unsigned 'char'. If we're
// importing into a context with a signed 'char', translate to
// 'unsigned char' instead.
if (!Importer.getToContext().getLangOpts().CharIsSigned)
return Importer.getToContext().SignedCharTy;
return Importer.getToContext().CharTy;
case BuiltinType::WChar_S:
case BuiltinType::WChar_U:
// FIXME: If not in C++, shall we translate to the C equivalent of
// wchar_t?
return Importer.getToContext().WCharTy;
}
llvm_unreachable("Invalid BuiltinType Kind!");
}
ExpectedType ASTNodeImporter::VisitDecayedType(const DecayedType *T) {
ExpectedType ToOriginalTypeOrErr = import(T->getOriginalType());
if (!ToOriginalTypeOrErr)
return ToOriginalTypeOrErr.takeError();
return Importer.getToContext().getDecayedType(*ToOriginalTypeOrErr);
}
ExpectedType ASTNodeImporter::VisitComplexType(const ComplexType *T) {
ExpectedType ToElementTypeOrErr = import(T->getElementType());
if (!ToElementTypeOrErr)
return ToElementTypeOrErr.takeError();
return Importer.getToContext().getComplexType(*ToElementTypeOrErr);
}
ExpectedType ASTNodeImporter::VisitPointerType(const PointerType *T) {
ExpectedType ToPointeeTypeOrErr = import(T->getPointeeType());
if (!ToPointeeTypeOrErr)
return ToPointeeTypeOrErr.takeError();
return Importer.getToContext().getPointerType(*ToPointeeTypeOrErr);
}
ExpectedType ASTNodeImporter::VisitBlockPointerType(const BlockPointerType *T) {
// FIXME: Check for blocks support in "to" context.
ExpectedType ToPointeeTypeOrErr = import(T->getPointeeType());
if (!ToPointeeTypeOrErr)
return ToPointeeTypeOrErr.takeError();
return Importer.getToContext().getBlockPointerType(*ToPointeeTypeOrErr);
}
ExpectedType
ASTNodeImporter::VisitLValueReferenceType(const LValueReferenceType *T) {
// FIXME: Check for C++ support in "to" context.
ExpectedType ToPointeeTypeOrErr = import(T->getPointeeTypeAsWritten());
if (!ToPointeeTypeOrErr)
return ToPointeeTypeOrErr.takeError();
return Importer.getToContext().getLValueReferenceType(*ToPointeeTypeOrErr);
}
ExpectedType
ASTNodeImporter::VisitRValueReferenceType(const RValueReferenceType *T) {
// FIXME: Check for C++0x support in "to" context.
ExpectedType ToPointeeTypeOrErr = import(T->getPointeeTypeAsWritten());
if (!ToPointeeTypeOrErr)
return ToPointeeTypeOrErr.takeError();
return Importer.getToContext().getRValueReferenceType(*ToPointeeTypeOrErr);
}
ExpectedType
ASTNodeImporter::VisitMemberPointerType(const MemberPointerType *T) {
// FIXME: Check for C++ support in "to" context.
ExpectedType ToPointeeTypeOrErr = import(T->getPointeeType());
if (!ToPointeeTypeOrErr)
return ToPointeeTypeOrErr.takeError();
ExpectedType ClassTypeOrErr = import(QualType(T->getClass(), 0));
if (!ClassTypeOrErr)
return ClassTypeOrErr.takeError();
return Importer.getToContext().getMemberPointerType(
*ToPointeeTypeOrErr, (*ClassTypeOrErr).getTypePtr());
}
ExpectedType
ASTNodeImporter::VisitConstantArrayType(const ConstantArrayType *T) {
QualType ToElementType;
const Expr *ToSizeExpr;
if (auto Imp = importSeq(T->getElementType(), T->getSizeExpr()))
std::tie(ToElementType, ToSizeExpr) = *Imp;
else
return Imp.takeError();
return Importer.getToContext().getConstantArrayType(
ToElementType, T->getSize(), ToSizeExpr, T->getSizeModifier(),
T->getIndexTypeCVRQualifiers());
}
ExpectedType
ASTNodeImporter::VisitIncompleteArrayType(const IncompleteArrayType *T) {
ExpectedType ToElementTypeOrErr = import(T->getElementType());
if (!ToElementTypeOrErr)
return ToElementTypeOrErr.takeError();
return Importer.getToContext().getIncompleteArrayType(*ToElementTypeOrErr,
T->getSizeModifier(),
T->getIndexTypeCVRQualifiers());
}
ExpectedType
ASTNodeImporter::VisitVariableArrayType(const VariableArrayType *T) {
QualType ToElementType;
Expr *ToSizeExpr;
SourceRange ToBracketsRange;
if (auto Imp = importSeq(
T->getElementType(), T->getSizeExpr(), T->getBracketsRange()))
std::tie(ToElementType, ToSizeExpr, ToBracketsRange) = *Imp;
else
return Imp.takeError();
return Importer.getToContext().getVariableArrayType(
ToElementType, ToSizeExpr, T->getSizeModifier(),
T->getIndexTypeCVRQualifiers(), ToBracketsRange);
}
ExpectedType ASTNodeImporter::VisitDependentSizedArrayType(
const DependentSizedArrayType *T) {
QualType ToElementType;
Expr *ToSizeExpr;
SourceRange ToBracketsRange;
if (auto Imp = importSeq(
T->getElementType(), T->getSizeExpr(), T->getBracketsRange()))
std::tie(ToElementType, ToSizeExpr, ToBracketsRange) = *Imp;
else
return Imp.takeError();
// SizeExpr may be null if size is not specified directly.
// For example, 'int a[]'.
return Importer.getToContext().getDependentSizedArrayType(
ToElementType, ToSizeExpr, T->getSizeModifier(),
T->getIndexTypeCVRQualifiers(), ToBracketsRange);
}
ExpectedType ASTNodeImporter::VisitVectorType(const VectorType *T) {
ExpectedType ToElementTypeOrErr = import(T->getElementType());
if (!ToElementTypeOrErr)
return ToElementTypeOrErr.takeError();
return Importer.getToContext().getVectorType(*ToElementTypeOrErr,
T->getNumElements(),
T->getVectorKind());
}
ExpectedType ASTNodeImporter::VisitExtVectorType(const ExtVectorType *T) {
ExpectedType ToElementTypeOrErr = import(T->getElementType());
if (!ToElementTypeOrErr)
return ToElementTypeOrErr.takeError();
return Importer.getToContext().getExtVectorType(*ToElementTypeOrErr,
T->getNumElements());
}
ExpectedType
ASTNodeImporter::VisitFunctionNoProtoType(const FunctionNoProtoType *T) {
// FIXME: What happens if we're importing a function without a prototype
// into C++? Should we make it variadic?
ExpectedType ToReturnTypeOrErr = import(T->getReturnType());
if (!ToReturnTypeOrErr)
return ToReturnTypeOrErr.takeError();
return Importer.getToContext().getFunctionNoProtoType(*ToReturnTypeOrErr,
T->getExtInfo());
}
ExpectedType
ASTNodeImporter::VisitFunctionProtoType(const FunctionProtoType *T) {
ExpectedType ToReturnTypeOrErr = import(T->getReturnType());
if (!ToReturnTypeOrErr)
return ToReturnTypeOrErr.takeError();
// Import argument types
SmallVector<QualType, 4> ArgTypes;
for (const auto &A : T->param_types()) {
ExpectedType TyOrErr = import(A);
if (!TyOrErr)
return TyOrErr.takeError();
ArgTypes.push_back(*TyOrErr);
}
// Import exception types
SmallVector<QualType, 4> ExceptionTypes;
for (const auto &E : T->exceptions()) {
ExpectedType TyOrErr = import(E);
if (!TyOrErr)
return TyOrErr.takeError();
ExceptionTypes.push_back(*TyOrErr);
}
FunctionProtoType::ExtProtoInfo FromEPI = T->getExtProtoInfo();
FunctionProtoType::ExtProtoInfo ToEPI;
auto Imp = importSeq(
FromEPI.ExceptionSpec.NoexceptExpr,
FromEPI.ExceptionSpec.SourceDecl,
FromEPI.ExceptionSpec.SourceTemplate);
if (!Imp)
return Imp.takeError();
ToEPI.ExtInfo = FromEPI.ExtInfo;
ToEPI.Variadic = FromEPI.Variadic;
ToEPI.HasTrailingReturn = FromEPI.HasTrailingReturn;
ToEPI.TypeQuals = FromEPI.TypeQuals;
ToEPI.RefQualifier = FromEPI.RefQualifier;
ToEPI.ExceptionSpec.Type = FromEPI.ExceptionSpec.Type;
ToEPI.ExceptionSpec.Exceptions = ExceptionTypes;
std::tie(
ToEPI.ExceptionSpec.NoexceptExpr,
ToEPI.ExceptionSpec.SourceDecl,
ToEPI.ExceptionSpec.SourceTemplate) = *Imp;
return Importer.getToContext().getFunctionType(
*ToReturnTypeOrErr, ArgTypes, ToEPI);
}
ExpectedType ASTNodeImporter::VisitUnresolvedUsingType(
const UnresolvedUsingType *T) {
UnresolvedUsingTypenameDecl *ToD;
Decl *ToPrevD;
if (auto Imp = importSeq(T->getDecl(), T->getDecl()->getPreviousDecl()))
std::tie(ToD, ToPrevD) = *Imp;
else
return Imp.takeError();
return Importer.getToContext().getTypeDeclType(
ToD, cast_or_null<TypeDecl>(ToPrevD));
}
ExpectedType ASTNodeImporter::VisitParenType(const ParenType *T) {
ExpectedType ToInnerTypeOrErr = import(T->getInnerType());
if (!ToInnerTypeOrErr)
return ToInnerTypeOrErr.takeError();
return Importer.getToContext().getParenType(*ToInnerTypeOrErr);
}
ExpectedType ASTNodeImporter::VisitTypedefType(const TypedefType *T) {
Expected<TypedefNameDecl *> ToDeclOrErr = import(T->getDecl());
if (!ToDeclOrErr)
return ToDeclOrErr.takeError();
return Importer.getToContext().getTypeDeclType(*ToDeclOrErr);
}
ExpectedType ASTNodeImporter::VisitTypeOfExprType(const TypeOfExprType *T) {
ExpectedExpr ToExprOrErr = import(T->getUnderlyingExpr());
if (!ToExprOrErr)
return ToExprOrErr.takeError();
return Importer.getToContext().getTypeOfExprType(*ToExprOrErr);
}
ExpectedType ASTNodeImporter::VisitTypeOfType(const TypeOfType *T) {
ExpectedType ToUnderlyingTypeOrErr = import(T->getUnderlyingType());
if (!ToUnderlyingTypeOrErr)
return ToUnderlyingTypeOrErr.takeError();
return Importer.getToContext().getTypeOfType(*ToUnderlyingTypeOrErr);
}
ExpectedType ASTNodeImporter::VisitDecltypeType(const DecltypeType *T) {
// FIXME: Make sure that the "to" context supports C++0x!
ExpectedExpr ToExprOrErr = import(T->getUnderlyingExpr());
if (!ToExprOrErr)
return ToExprOrErr.takeError();
ExpectedType ToUnderlyingTypeOrErr = import(T->getUnderlyingType());
if (!ToUnderlyingTypeOrErr)
return ToUnderlyingTypeOrErr.takeError();
return Importer.getToContext().getDecltypeType(
*ToExprOrErr, *ToUnderlyingTypeOrErr);
}
ExpectedType
ASTNodeImporter::VisitUnaryTransformType(const UnaryTransformType *T) {
ExpectedType ToBaseTypeOrErr = import(T->getBaseType());
if (!ToBaseTypeOrErr)
return ToBaseTypeOrErr.takeError();
ExpectedType ToUnderlyingTypeOrErr = import(T->getUnderlyingType());
if (!ToUnderlyingTypeOrErr)
return ToUnderlyingTypeOrErr.takeError();
return Importer.getToContext().getUnaryTransformType(
*ToBaseTypeOrErr, *ToUnderlyingTypeOrErr, T->getUTTKind());
}
ExpectedType ASTNodeImporter::VisitAutoType(const AutoType *T) {
// FIXME: Make sure that the "to" context supports C++11!
ExpectedType ToDeducedTypeOrErr = import(T->getDeducedType());
if (!ToDeducedTypeOrErr)
return ToDeducedTypeOrErr.takeError();
return Importer.getToContext().getAutoType(*ToDeducedTypeOrErr,
T->getKeyword(),
/*IsDependent*/false);
}
ExpectedType ASTNodeImporter::VisitInjectedClassNameType(
const InjectedClassNameType *T) {
Expected<CXXRecordDecl *> ToDeclOrErr = import(T->getDecl());
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);
}
ExpectedType ASTNodeImporter::VisitRecordType(const RecordType *T) {
Expected<RecordDecl *> ToDeclOrErr = import(T->getDecl());
if (!ToDeclOrErr)
return ToDeclOrErr.takeError();
return Importer.getToContext().getTagDeclType(*ToDeclOrErr);
}
ExpectedType ASTNodeImporter::VisitEnumType(const EnumType *T) {
Expected<EnumDecl *> ToDeclOrErr = import(T->getDecl());
if (!ToDeclOrErr)
return ToDeclOrErr.takeError();
return Importer.getToContext().getTagDeclType(*ToDeclOrErr);
}
ExpectedType ASTNodeImporter::VisitAttributedType(const AttributedType *T) {
ExpectedType ToModifiedTypeOrErr = import(T->getModifiedType());
if (!ToModifiedTypeOrErr)
return ToModifiedTypeOrErr.takeError();
ExpectedType ToEquivalentTypeOrErr = import(T->getEquivalentType());
if (!ToEquivalentTypeOrErr)
return ToEquivalentTypeOrErr.takeError();
return Importer.getToContext().getAttributedType(T->getAttrKind(),
*ToModifiedTypeOrErr, *ToEquivalentTypeOrErr);
}
ExpectedType ASTNodeImporter::VisitTemplateTypeParmType(
const TemplateTypeParmType *T) {
Expected<TemplateTypeParmDecl *> ToDeclOrErr = import(T->getDecl());
if (!ToDeclOrErr)
return ToDeclOrErr.takeError();
return Importer.getToContext().getTemplateTypeParmType(
T->getDepth(), T->getIndex(), T->isParameterPack(), *ToDeclOrErr);
}
ExpectedType ASTNodeImporter::VisitSubstTemplateTypeParmType(
const SubstTemplateTypeParmType *T) {
ExpectedType ReplacedOrErr = import(QualType(T->getReplacedParameter(), 0));
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());
}
ExpectedType ASTNodeImporter::VisitTemplateSpecializationType(
const TemplateSpecializationType *T) {
auto ToTemplateOrErr = import(T->getTemplateName());
if (!ToTemplateOrErr)
return ToTemplateOrErr.takeError();
SmallVector<TemplateArgument, 2> ToTemplateArgs;
if (Error Err = ImportTemplateArguments(
T->getArgs(), T->getNumArgs(), ToTemplateArgs))
return std::move(Err);
QualType ToCanonType;
if (!QualType(T, 0).isCanonical()) {
QualType FromCanonType
= Importer.getFromContext().getCanonicalType(QualType(T, 0));
if (ExpectedType TyOrErr = import(FromCanonType))
ToCanonType = *TyOrErr;
else
return TyOrErr.takeError();
}
return Importer.getToContext().getTemplateSpecializationType(*ToTemplateOrErr,
ToTemplateArgs,
ToCanonType);
}
ExpectedType ASTNodeImporter::VisitElaboratedType(const ElaboratedType *T) {
// Note: the qualifier in an ElaboratedType is optional.
auto ToQualifierOrErr = import(T->getQualifier());
if (!ToQualifierOrErr)
return ToQualifierOrErr.takeError();
ExpectedType ToNamedTypeOrErr = import(T->getNamedType());
if (!ToNamedTypeOrErr)
return ToNamedTypeOrErr.takeError();
Expected<TagDecl *> ToOwnedTagDeclOrErr = import(T->getOwnedTagDecl());
if (!ToOwnedTagDeclOrErr)
return ToOwnedTagDeclOrErr.takeError();
return Importer.getToContext().getElaboratedType(T->getKeyword(),
*ToQualifierOrErr,
*ToNamedTypeOrErr,
*ToOwnedTagDeclOrErr);
}
ExpectedType
ASTNodeImporter::VisitPackExpansionType(const PackExpansionType *T) {
ExpectedType ToPatternOrErr = import(T->getPattern());
if (!ToPatternOrErr)
return ToPatternOrErr.takeError();
return Importer.getToContext().getPackExpansionType(*ToPatternOrErr,
T->getNumExpansions());
}
ExpectedType ASTNodeImporter::VisitDependentTemplateSpecializationType(
const DependentTemplateSpecializationType *T) {
auto ToQualifierOrErr = import(T->getQualifier());
if (!ToQualifierOrErr)
return ToQualifierOrErr.takeError();
IdentifierInfo *ToName = Importer.Import(T->getIdentifier());
SmallVector<TemplateArgument, 2> ToPack;
ToPack.reserve(T->getNumArgs());
if (Error Err = ImportTemplateArguments(
T->getArgs(), T->getNumArgs(), ToPack))
return std::move(Err);
return Importer.getToContext().getDependentTemplateSpecializationType(
T->getKeyword(), *ToQualifierOrErr, ToName, ToPack);
}
ExpectedType
ASTNodeImporter::VisitDependentNameType(const DependentNameType *T) {
auto ToQualifierOrErr = import(T->getQualifier());
if (!ToQualifierOrErr)
return ToQualifierOrErr.takeError();
IdentifierInfo *Name = Importer.Import(T->getIdentifier());
QualType Canon;
if (T != T->getCanonicalTypeInternal().getTypePtr()) {
if (ExpectedType TyOrErr = import(T->getCanonicalTypeInternal()))
Canon = (*TyOrErr).getCanonicalType();
else
return TyOrErr.takeError();
}
return Importer.getToContext().getDependentNameType(T->getKeyword(),
*ToQualifierOrErr,
Name, Canon);
}
ExpectedType
ASTNodeImporter::VisitObjCInterfaceType(const ObjCInterfaceType *T) {
Expected<ObjCInterfaceDecl *> ToDeclOrErr = import(T->getDecl());
if (!ToDeclOrErr)
return ToDeclOrErr.takeError();
return Importer.getToContext().getObjCInterfaceType(*ToDeclOrErr);
}
ExpectedType ASTNodeImporter::VisitObjCObjectType(const ObjCObjectType *T) {
ExpectedType ToBaseTypeOrErr = import(T->getBaseType());
if (!ToBaseTypeOrErr)
return ToBaseTypeOrErr.takeError();
SmallVector<QualType, 4> TypeArgs;
for (auto TypeArg : T->getTypeArgsAsWritten()) {
if (ExpectedType TyOrErr = import(TypeArg))
TypeArgs.push_back(*TyOrErr);
else
return TyOrErr.takeError();
}
SmallVector<ObjCProtocolDecl *, 4> Protocols;
for (auto *P : T->quals()) {
if (Expected<ObjCProtocolDecl *> ProtocolOrErr = import(P))
Protocols.push_back(*ProtocolOrErr);
else
return ProtocolOrErr.takeError();
}
return Importer.getToContext().getObjCObjectType(*ToBaseTypeOrErr, TypeArgs,
Protocols,
T->isKindOfTypeAsWritten());
}
ExpectedType
ASTNodeImporter::VisitObjCObjectPointerType(const ObjCObjectPointerType *T) {
ExpectedType ToPointeeTypeOrErr = import(T->getPointeeType());
if (!ToPointeeTypeOrErr)
return ToPointeeTypeOrErr.takeError();
return Importer.getToContext().getObjCObjectPointerType(*ToPointeeTypeOrErr);
}
//----------------------------------------------------------------------------
// Import Declarations
//----------------------------------------------------------------------------
Error ASTNodeImporter::ImportDeclParts(
NamedDecl *D, DeclContext *&DC, DeclContext *&LexicalDC,
DeclarationName &Name, NamedDecl *&ToD, SourceLocation &Loc) {
// Check if RecordDecl is in FunctionDecl parameters to avoid infinite loop.
// example: int struct_in_proto(struct data_t{int a;int b;} *d);
DeclContext *OrigDC = D->getDeclContext();
FunctionDecl *FunDecl;
if (isa<RecordDecl>(D) && (FunDecl = dyn_cast<FunctionDecl>(OrigDC)) &&
FunDecl->hasBody()) {
auto getLeafPointeeType = [](const Type *T) {
while (T->isPointerType() || T->isArrayType()) {
T = T->getPointeeOrArrayElementType();
}
return T;
};
for (const ParmVarDecl *P : FunDecl->parameters()) {
const Type *LeafT =
getLeafPointeeType(P->getType().getCanonicalType().getTypePtr());
auto *RT = dyn_cast<RecordType>(LeafT);
if (RT && RT->getDecl() == D) {
Importer.FromDiag(D->getLocation(), diag::err_unsupported_ast_node)
<< D->getDeclKindName();
return make_error<ImportError>(ImportError::UnsupportedConstruct);
}
}
}
// Import the context of this declaration.
if (Error Err = ImportDeclContext(D, DC, LexicalDC))
return Err;
// Import the name of this declaration.
if (Error Err = importInto(Name, D->getDeclName()))
return Err;
// Import the location of this declaration.
if (Error Err = importInto(Loc, D->getLocation()))
return Err;
ToD = cast_or_null<NamedDecl>(Importer.GetAlreadyImportedOrNull(D));
if (ToD)
if (Error Err = ASTNodeImporter(*this).ImportDefinitionIfNeeded(D, ToD))
return Err;
return Error::success();
}
Error ASTNodeImporter::ImportDefinitionIfNeeded(Decl *FromD, Decl *ToD) {
if (!FromD)
return Error::success();
if (!ToD)
if (Error Err = importInto(ToD, FromD))
return Err;
if (RecordDecl *FromRecord = dyn_cast<RecordDecl>(FromD)) {
if (RecordDecl *ToRecord = cast<RecordDecl>(ToD)) {
if (FromRecord->getDefinition() && FromRecord->isCompleteDefinition() &&
!ToRecord->getDefinition()) {
if (Error Err = ImportDefinition(FromRecord, ToRecord))
return Err;
}
}
return Error::success();
}
if (EnumDecl *FromEnum = dyn_cast<EnumDecl>(FromD)) {
if (EnumDecl *ToEnum = cast<EnumDecl>(ToD)) {
if (FromEnum->getDefinition() && !ToEnum->getDefinition()) {
if (Error Err = ImportDefinition(FromEnum, ToEnum))
return Err;
}
}
return Error::success();
}
return Error::success();
}
Error
ASTNodeImporter::ImportDeclarationNameLoc(
const DeclarationNameInfo &From, DeclarationNameInfo& To) {
// NOTE: To.Name and To.Loc are already imported.
// We only have to import To.LocInfo.
switch (To.getName().getNameKind()) {
case DeclarationName::Identifier:
case DeclarationName::ObjCZeroArgSelector:
case DeclarationName::ObjCOneArgSelector:
case DeclarationName::ObjCMultiArgSelector:
case DeclarationName::CXXUsingDirective:
case DeclarationName::CXXDeductionGuideName:
return Error::success();
case DeclarationName::CXXOperatorName: {
if (auto ToRangeOrErr = import(From.getCXXOperatorNameRange()))
To.setCXXOperatorNameRange(*ToRangeOrErr);
else
return ToRangeOrErr.takeError();
return Error::success();
}
case DeclarationName::CXXLiteralOperatorName: {
if (ExpectedSLoc LocOrErr = import(From.getCXXLiteralOperatorNameLoc()))
To.setCXXLiteralOperatorNameLoc(*LocOrErr);
else
return LocOrErr.takeError();
return Error::success();
}
case DeclarationName::CXXConstructorName:
case DeclarationName::CXXDestructorName:
case DeclarationName::CXXConversionFunctionName: {
if (auto ToTInfoOrErr = import(From.getNamedTypeInfo()))
To.setNamedTypeInfo(*ToTInfoOrErr);
else
return ToTInfoOrErr.takeError();
return Error::success();
}
}
llvm_unreachable("Unknown name kind.");
}
Error
ASTNodeImporter::ImportDeclContext(DeclContext *FromDC, bool ForceImport) {
if (Importer.isMinimalImport() && !ForceImport) {
auto ToDCOrErr = Importer.ImportContext(FromDC);
return ToDCOrErr.takeError();
}
// We use strict error handling in case of records and enums, but not
// with e.g. namespaces.
//
// FIXME Clients of the ASTImporter should be able to choose an
// appropriate error handling strategy for their needs. For instance,
// they may not want to mark an entire namespace as erroneous merely
// 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);
Error ChildErrors = Error::success();
for (auto *From : FromDC->decls()) {
ExpectedDecl ImportedOrErr = import(From);
if (!ImportedOrErr) {
if (AccumulateChildErrors)
ChildErrors =
joinErrors(std::move(ChildErrors), ImportedOrErr.takeError());
else
consumeError(ImportedOrErr.takeError());
}
}
// We reorder declarations in RecordDecls because they may have another order
// in the "to" context than they have in the "from" context. This may happen
// e.g when we import a class like this:
// struct declToImport {
// int a = c + b;
// int b = 1;
// int c = 2;
// };
// 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.
//
// Keeping field order is vital because it determines structure layout.
//
// Here and below, we cannot call field_begin() method and its callers on
// ToDC if it has an external storage. Calling field_begin() will
// automatically load all the fields by calling
// LoadFieldsFromExternalStorage(). LoadFieldsFromExternalStorage() would
// call ASTImporter::Import(). This is because the ExternalASTSource
// 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) {
consumeError(std::move(ChildErrors));
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)) {
assert(D && "DC contains a null decl");
Decl *ToD = Importer.GetAlreadyImportedOrNull(D);
// Remove only the decls which we successfully imported.
if (ToD) {
assert(ToDC == ToD->getLexicalDeclContext() && ToDC->containsDecl(ToD));
// Remove the decl from its wrong place in the linked list.
ToDC->removeDecl(ToD);
// Add the decl to the end of the linked list.
// This time it will be at the proper place because the enclosing for
// loop iterates in the original (good) order of the decls.
ToDC->addDeclInternal(ToD);
}
}
}
return ChildErrors;
}
Error ASTNodeImporter::ImportDeclContext(
Decl *FromD, DeclContext *&ToDC, DeclContext *&ToLexicalDC) {
auto ToDCOrErr = Importer.ImportContext(FromD->getDeclContext());
if (!ToDCOrErr)
return ToDCOrErr.takeError();
ToDC = *ToDCOrErr;
if (FromD->getDeclContext() != FromD->getLexicalDeclContext()) {
auto ToLexicalDCOrErr = Importer.ImportContext(
FromD->getLexicalDeclContext());
if (!ToLexicalDCOrErr)
return ToLexicalDCOrErr.takeError();
ToLexicalDC = *ToLexicalDCOrErr;
} else
ToLexicalDC = ToDC;
return Error::success();
}
Error ASTNodeImporter::ImportImplicitMethods(
const CXXRecordDecl *From, CXXRecordDecl *To) {
assert(From->isCompleteDefinition() && To->getDefinition() == To &&
"Import implicit methods to or from non-definition");
for (CXXMethodDecl *FromM : From->methods())
if (FromM->isImplicit()) {
Expected<CXXMethodDecl *> ToMOrErr = import(FromM);
if (!ToMOrErr)
return ToMOrErr.takeError();
}
return Error::success();
}
static Error setTypedefNameForAnonDecl(TagDecl *From, TagDecl *To,
ASTImporter &Importer) {
if (TypedefNameDecl *FromTypedef = From->getTypedefNameForAnonDecl()) {
if (ExpectedDecl ToTypedefOrErr = Importer.Import(FromTypedef))
To->setTypedefNameForAnonDecl(cast<TypedefNameDecl>(*ToTypedefOrErr));
else
return ToTypedefOrErr.takeError();
}
return Error::success();
}
Error ASTNodeImporter::ImportDefinition(
RecordDecl *From, RecordDecl *To, ImportDefinitionKind Kind) {
auto DefinitionCompleter = [To]() {
// There are cases in LLDB when we first import a class without its
// members. The class will have DefinitionData, but no members. Then,
// importDefinition is called from LLDB, which tries to get the members, so
// when we get here, the class already has the DefinitionData set, so we
// must unset the CompleteDefinition here to be able to complete again the
// definition.
To->setCompleteDefinition(false);
To->completeDefinition();
};
if (To->getDefinition() || To->isBeingDefined()) {
if (Kind == IDK_Everything ||
// In case of lambdas, the class already has a definition ptr set, but
// the contained decls are not imported yet. Also, isBeingDefined was
// set in CXXRecordDecl::CreateLambda. We must import the contained
// decls here and finish the definition.
(To->isLambda() && shouldForceImportDeclContext(Kind))) {
Error Result = ImportDeclContext(From, /*ForceImport=*/true);
// Finish the definition of the lambda, set isBeingDefined to false.
if (To->isLambda())
DefinitionCompleter();
return Result;
}
return Error::success();
}
To->startDefinition();
// 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.
auto DefinitionCompleterScopeExit =
llvm::make_scope_exit(DefinitionCompleter);
if (Error Err = setTypedefNameForAnonDecl(From, To, Importer))
return Err;
// Add base classes.
auto *ToCXX = dyn_cast<CXXRecordDecl>(To);
auto *FromCXX = dyn_cast<CXXRecordDecl>(From);
if (ToCXX && FromCXX && ToCXX->dataPtr() && FromCXX->dataPtr()) {
struct CXXRecordDecl::DefinitionData &ToData = ToCXX->data();
struct CXXRecordDecl::DefinitionData &FromData = FromCXX->data();
#define FIELD(Name, Width, Merge) \
ToData.Name = FromData.Name;
#include "clang/AST/CXXRecordDeclDefinitionBits.def"
// Copy over the data stored in RecordDeclBits
ToCXX->setArgPassingRestrictions(FromCXX->getArgPassingRestrictions());
SmallVector<CXXBaseSpecifier *, 4> Bases;
for (const auto &Base1 : FromCXX->bases()) {
ExpectedType TyOrErr = import(Base1.getType());
if (!TyOrErr)
return TyOrErr.takeError();
SourceLocation EllipsisLoc;
if (Base1.isPackExpansion()) {
if (ExpectedSLoc LocOrErr = import(Base1.getEllipsisLoc()))
EllipsisLoc = *LocOrErr;
else
return LocOrErr.takeError();
}
// Ensure that we have a definition for the base.
if (Error Err =
ImportDefinitionIfNeeded(Base1.getType()->getAsCXXRecordDecl()))
return Err;
auto RangeOrErr = import(Base1.getSourceRange());
if (!RangeOrErr)
return RangeOrErr.takeError();
auto TSIOrErr = import(Base1.getTypeSourceInfo());
if (!TSIOrErr)
return TSIOrErr.takeError();
Bases.push_back(
new (Importer.getToContext()) CXXBaseSpecifier(
*RangeOrErr,
Base1.isVirtual(),
Base1.isBaseOfClass(),
Base1.getAccessSpecifierAsWritten(),
*TSIOrErr,
EllipsisLoc));
}
if (!Bases.empty())
ToCXX->setBases(Bases.data(), Bases.size());
}
if (shouldForceImportDeclContext(Kind))
if (Error Err = ImportDeclContext(From, /*ForceImport=*/true))
return Err;
return Error::success();
}
Error ASTNodeImporter::ImportInitializer(VarDecl *From, VarDecl *To) {
if (To->getAnyInitializer())
return Error::success();
Expr *FromInit = From->getInit();
if (!FromInit)
return Error::success();
ExpectedExpr ToInitOrErr = import(FromInit);
if (!ToInitOrErr)
return ToInitOrErr.takeError();
To->setInit(*ToInitOrErr);
if (From->isInitKnownICE()) {
EvaluatedStmt *Eval = To->ensureEvaluatedStmt();
Eval->CheckedICE = true;
Eval->IsICE = From->isInitICE();
}
// FIXME: Other bits to merge?
return Error::success();
}
Error ASTNodeImporter::ImportDefinition(
EnumDecl *From, EnumDecl *To, ImportDefinitionKind Kind) {
if (To->getDefinition() || To->isBeingDefined()) {
if (Kind == IDK_Everything)
return ImportDeclContext(From, /*ForceImport=*/true);
return Error::success();
}
To->startDefinition();
if (Error Err = setTypedefNameForAnonDecl(From, To, Importer))
return Err;
ExpectedType ToTypeOrErr =
import(Importer.getFromContext().getTypeDeclType(From));
if (!ToTypeOrErr)
return ToTypeOrErr.takeError();
ExpectedType ToPromotionTypeOrErr = import(From->getPromotionType());
if (!ToPromotionTypeOrErr)
return ToPromotionTypeOrErr.takeError();
if (shouldForceImportDeclContext(Kind))
if (Error Err = ImportDeclContext(From, /*ForceImport=*/true))
return Err;
// FIXME: we might need to merge the number of positive or negative bits
// if the enumerator lists don't match.
To->completeDefinition(*ToTypeOrErr, *ToPromotionTypeOrErr,
From->getNumPositiveBits(),
From->getNumNegativeBits());
return Error::success();
}
Error ASTNodeImporter::ImportTemplateArguments(
const TemplateArgument *FromArgs, unsigned NumFromArgs,
SmallVectorImpl<TemplateArgument> &ToArgs) {
for (unsigned I = 0; I != NumFromArgs; ++I) {
if (auto ToOrErr = import(FromArgs[I]))
ToArgs.push_back(*ToOrErr);
else
return ToOrErr.takeError();
}
return Error::success();
}
// FIXME: Do not forget to remove this and use only 'import'.
Expected<TemplateArgument>
ASTNodeImporter::ImportTemplateArgument(const TemplateArgument &From) {
return import(From);
}
template <typename InContainerTy>
Error ASTNodeImporter::ImportTemplateArgumentListInfo(
const InContainerTy &Container, TemplateArgumentListInfo &ToTAInfo) {
for (const auto &FromLoc : Container) {
if (auto ToLocOrErr = import(FromLoc))
ToTAInfo.addArgument(*ToLocOrErr);
else
return ToLocOrErr.takeError();
}
return Error::success();
}
static StructuralEquivalenceKind
getStructuralEquivalenceKind(const ASTImporter &Importer) {
return Importer.isMinimalImport() ? StructuralEquivalenceKind::Minimal
: 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) {
// 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);
if (ToOrigin) {
auto *ToOriginRecord = dyn_cast<RecordDecl>(ToOrigin);
if (ToOriginRecord)
ToRecord = ToOriginRecord;
}
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));
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);
}
ExpectedDecl ASTNodeImporter::VisitImportDecl(ImportDecl *D) {
Importer.FromDiag(D->getLocation(), diag::err_unsupported_ast_node)
<< D->getDeclKindName();
return make_error<ImportError>(ImportError::UnsupportedConstruct);
}
ExpectedDecl ASTNodeImporter::VisitEmptyDecl(EmptyDecl *D) {
// Import the context of this declaration.
DeclContext *DC, *LexicalDC;
if (Error Err = ImportDeclContext(D, DC, LexicalDC))
return std::move(Err);
// Import the location of this declaration.
ExpectedSLoc LocOrErr = import(D->getLocation());
if (!LocOrErr)
return LocOrErr.takeError();
EmptyDecl *ToD;
if (GetImportedOrCreateDecl(ToD, D, Importer.getToContext(), DC, *LocOrErr))
return ToD;
ToD->setLexicalDeclContext(LexicalDC);
LexicalDC->addDeclInternal(ToD);
return ToD;
}
ExpectedDecl ASTNodeImporter::VisitTranslationUnitDecl(TranslationUnitDecl *D) {
TranslationUnitDecl *ToD =
Importer.getToContext().getTranslationUnitDecl();
Importer.MapImported(D, ToD);
return ToD;
}
ExpectedDecl ASTNodeImporter::VisitAccessSpecDecl(AccessSpecDecl *D) {
ExpectedSLoc LocOrErr = import(D->getLocation());
if (!LocOrErr)
return LocOrErr.takeError();
auto ColonLocOrErr = import(D->getColonLoc());
if (!ColonLocOrErr)
return ColonLocOrErr.takeError();
// Import the context of this declaration.
auto DCOrErr = Importer.ImportContext(D->getDeclContext());
if (!DCOrErr)
return DCOrErr.takeError();
DeclContext *DC = *DCOrErr;
AccessSpecDecl *ToD;
if (GetImportedOrCreateDecl(ToD, D, Importer.getToContext(), D->getAccess(),
DC, *LocOrErr, *ColonLocOrErr))
return ToD;
// Lexical DeclContext and Semantic DeclContext
// is always the same for the accessSpec.
ToD->setLexicalDeclContext(DC);
DC->addDeclInternal(ToD);
return ToD;
}
ExpectedDecl ASTNodeImporter::VisitStaticAssertDecl(StaticAssertDecl *D) {
auto DCOrErr = Importer.ImportContext(D->getDeclContext());
if (!DCOrErr)
return DCOrErr.takeError();
DeclContext *DC = *DCOrErr;
DeclContext *LexicalDC = DC;
SourceLocation ToLocation, ToRParenLoc;
Expr *ToAssertExpr;
StringLiteral *ToMessage;
if (auto Imp = importSeq(
D->getLocation(), D->getAssertExpr(), D->getMessage(), D->getRParenLoc()))
std::tie(ToLocation, ToAssertExpr, ToMessage, ToRParenLoc) = *Imp;
else
return Imp.takeError();
StaticAssertDecl *ToD;
if (GetImportedOrCreateDecl(
ToD, D, Importer.getToContext(), DC, ToLocation, ToAssertExpr, ToMessage,
ToRParenLoc, D->isFailed()))
return ToD;
ToD->setLexicalDeclContext(LexicalDC);
LexicalDC->addDeclInternal(ToD);
return ToD;
}
ExpectedDecl ASTNodeImporter::VisitNamespaceDecl(NamespaceDecl *D) {
// Import the major distinguishing characteristics of this namespace.
DeclContext *DC, *LexicalDC;
DeclarationName Name;
SourceLocation Loc;
NamedDecl *ToD;
if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
return std::move(Err);
if (ToD)
return ToD;
NamespaceDecl *MergeWithNamespace = nullptr;
if (!Name) {
// This is an anonymous namespace. Adopt an existing anonymous
// namespace if we can.
// FIXME: Not testable.
if (auto *TU = dyn_cast<TranslationUnitDecl>(DC))
MergeWithNamespace = TU->getAnonymousNamespace();
else
MergeWithNamespace = cast<NamespaceDecl>(DC)->getAnonymousNamespace();
} else {
SmallVector<NamedDecl *, 4> ConflictingDecls;
auto FoundDecls = Importer.findDeclsInToCtx(DC, Name);
for (auto *FoundDecl : FoundDecls) {
if (!FoundDecl->isInIdentifierNamespace(Decl::IDNS_Namespace))
continue;
if (auto *FoundNS = dyn_cast<NamespaceDecl>(FoundDecl)) {
MergeWithNamespace = FoundNS;
ConflictingDecls.clear();
break;
}
ConflictingDecls.push_back(FoundDecl);
}
if (!ConflictingDecls.empty()) {
ExpectedName NameOrErr = Importer.HandleNameConflict(
Name, DC, Decl::IDNS_Namespace, ConflictingDecls.data(),
ConflictingDecls.size());
if (NameOrErr)
Name = NameOrErr.get();
else
return NameOrErr.takeError();
}
}
ExpectedSLoc BeginLocOrErr = import(D->getBeginLoc());
if (!BeginLocOrErr)
return BeginLocOrErr.takeError();
// 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))
return ToNamespace;
ToNamespace->setLexicalDeclContext(LexicalDC);
LexicalDC->addDeclInternal(ToNamespace);
// If this is an anonymous namespace, register it as the anonymous
// namespace within its context.
if (!Name) {
if (auto *TU = dyn_cast<TranslationUnitDecl>(DC))
TU->setAnonymousNamespace(ToNamespace);
else
cast<NamespaceDecl>(DC)->setAnonymousNamespace(ToNamespace);
}
}
Importer.MapImported(D, ToNamespace);
if (Error Err = ImportDeclContext(D))
return std::move(Err);
return ToNamespace;
}
ExpectedDecl ASTNodeImporter::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) {
// Import the major distinguishing characteristics of this namespace.
DeclContext *DC, *LexicalDC;
DeclarationName Name;
SourceLocation Loc;
NamedDecl *LookupD;
if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, LookupD, Loc))
return std::move(Err);
if (LookupD)
return LookupD;
// NOTE: No conflict resolution is done for namespace aliases now.
SourceLocation ToNamespaceLoc, ToAliasLoc, ToTargetNameLoc;
NestedNameSpecifierLoc ToQualifierLoc;
NamespaceDecl *ToNamespace;
if (auto Imp = importSeq(
D->getNamespaceLoc(), D->getAliasLoc(), D->getQualifierLoc(),
D->getTargetNameLoc(), D->getNamespace()))
std::tie(
ToNamespaceLoc, ToAliasLoc, ToQualifierLoc, ToTargetNameLoc,
ToNamespace) = *Imp;
else
return Imp.takeError();
IdentifierInfo *ToIdentifier = Importer.Import(D->getIdentifier());
NamespaceAliasDecl *ToD;
if (GetImportedOrCreateDecl(
ToD, D, Importer.getToContext(), DC, ToNamespaceLoc, ToAliasLoc,
ToIdentifier, ToQualifierLoc, ToTargetNameLoc, ToNamespace))
return ToD;
ToD->setLexicalDeclContext(LexicalDC);
LexicalDC->addDeclInternal(ToD);
return ToD;
}
ExpectedDecl
ASTNodeImporter::VisitTypedefNameDecl(TypedefNameDecl *D, bool IsAlias) {
// Import the major distinguishing characteristics of this typedef.
DeclContext *DC, *LexicalDC;
DeclarationName Name;
SourceLocation Loc;
NamedDecl *ToD;
if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
return std::move(Err);
if (ToD)
return ToD;
// If this typedef is not in block scope, determine whether we've
// seen a typedef with the same name (that we can merge with) or any
// other entity by that name (which name lookup could conflict with).
// Note: Repeated typedefs are not valid in C99:
// 'typedef int T; typedef int T;' is invalid
// We do not care about this now.
if (!DC->isFunctionOrMethod()) {
SmallVector<NamedDecl *, 4> ConflictingDecls;
unsigned IDNS = Decl::IDNS_Ordinary;
auto FoundDecls = Importer.findDeclsInToCtx(DC, Name);
for (auto *FoundDecl : FoundDecls) {
if (!FoundDecl->isInIdentifierNamespace(IDNS))
continue;
if (auto *FoundTypedef = dyn_cast<TypedefNameDecl>(FoundDecl)) {
if (!hasSameVisibilityContext(FoundTypedef, D))
continue;
QualType FromUT = D->getUnderlyingType();
QualType FoundUT = FoundTypedef->getUnderlyingType();
if (Importer.IsStructurallyEquivalent(FromUT, FoundUT)) {
// 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())
return Importer.MapImported(D, FoundTypedef);
// FIXME Handle redecl chain. When you do that make consistent changes
// in ASTImporterLookupTable too.
} else {
ConflictingDecls.push_back(FoundDecl);
}
}
}
if (!ConflictingDecls.empty()) {
ExpectedName NameOrErr = Importer.HandleNameConflict(
Name, DC, IDNS, ConflictingDecls.data(), ConflictingDecls.size());
if (NameOrErr)
Name = NameOrErr.get();
else
return NameOrErr.takeError();
}
}
QualType ToUnderlyingType;
TypeSourceInfo *ToTypeSourceInfo;
SourceLocation ToBeginLoc;
if (auto Imp = importSeq(
D->getUnderlyingType(), D->getTypeSourceInfo(), D->getBeginLoc()))
std::tie(ToUnderlyingType, ToTypeSourceInfo, ToBeginLoc) = *Imp;
else
return Imp.takeError();
// Create the new typedef node.
// FIXME: ToUnderlyingType is not used.
TypedefNameDecl *ToTypedef;
if (IsAlias) {
if (GetImportedOrCreateDecl<TypeAliasDecl>(
ToTypedef, D, Importer.getToContext(), DC, ToBeginLoc, Loc,
Name.getAsIdentifierInfo(), ToTypeSourceInfo))
return ToTypedef;
} else if (GetImportedOrCreateDecl<TypedefDecl>(
ToTypedef, D, Importer.getToContext(), DC, ToBeginLoc, Loc,
Name.getAsIdentifierInfo(), ToTypeSourceInfo))
return ToTypedef;
ToTypedef->setAccess(D->getAccess());
ToTypedef->setLexicalDeclContext(LexicalDC);
// Templated declarations should not appear in DeclContext.
TypeAliasDecl *FromAlias = IsAlias ? cast<TypeAliasDecl>(D) : nullptr;
if (!FromAlias || !FromAlias->getDescribedAliasTemplate())
LexicalDC->addDeclInternal(ToTypedef);
return ToTypedef;
}
ExpectedDecl ASTNodeImporter::VisitTypedefDecl(TypedefDecl *D) {
return VisitTypedefNameDecl(D, /*IsAlias=*/false);
}
ExpectedDecl ASTNodeImporter::VisitTypeAliasDecl(TypeAliasDecl *D) {
return VisitTypedefNameDecl(D, /*IsAlias=*/true);
}
ExpectedDecl
ASTNodeImporter::VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D) {
// Import the major distinguishing characteristics of this typedef.
DeclContext *DC, *LexicalDC;
DeclarationName Name;
SourceLocation Loc;
NamedDecl *FoundD;
if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, FoundD, Loc))
return std::move(Err);
if (FoundD)
return FoundD;
// If this typedef is not in block scope, determine whether we've
// seen a typedef with the same name (that we can merge with) or any
// other entity by that name (which name lookup could conflict with).
if (!DC->isFunctionOrMethod()) {
SmallVector<NamedDecl *, 4> ConflictingDecls;
unsigned IDNS = Decl::IDNS_Ordinary;
auto FoundDecls = Importer.findDeclsInToCtx(DC, Name);
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 (!ConflictingDecls.empty()) {
ExpectedName NameOrErr = Importer.HandleNameConflict(
Name, DC, IDNS, ConflictingDecls.data(), ConflictingDecls.size());
if (NameOrErr)
Name = NameOrErr.get();
else
return NameOrErr.takeError();
}
}
TemplateParameterList *ToTemplateParameters;
TypeAliasDecl *ToTemplatedDecl;
if (auto Imp = importSeq(D->getTemplateParameters(), D->getTemplatedDecl()))
std::tie(ToTemplateParameters, ToTemplatedDecl) = *Imp;
else
return Imp.takeError();
TypeAliasTemplateDecl *ToAlias;
if (GetImportedOrCreateDecl(ToAlias, D, Importer.getToContext(), DC, Loc,
Name, ToTemplateParameters, ToTemplatedDecl))
return ToAlias;
ToTemplatedDecl->setDescribedAliasTemplate(ToAlias);
ToAlias->setAccess(D->getAccess());
ToAlias->setLexicalDeclContext(LexicalDC);
LexicalDC->addDeclInternal(ToAlias);
return ToAlias;
}
ExpectedDecl ASTNodeImporter::VisitLabelDecl(LabelDecl *D) {
// Import the major distinguishing characteristics of this label.
DeclContext *DC, *LexicalDC;
DeclarationName Name;
SourceLocation Loc;
NamedDecl *ToD;
if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
return std::move(Err);
if (ToD)
return ToD;
assert(LexicalDC->isFunctionOrMethod());
LabelDecl *ToLabel;
if (D->isGnuLocal()) {
ExpectedSLoc BeginLocOrErr = import(D->getBeginLoc());
if (!BeginLocOrErr)
return BeginLocOrErr.takeError();
if (GetImportedOrCreateDecl(ToLabel, D, Importer.getToContext(), DC, Loc,
Name.getAsIdentifierInfo(), *BeginLocOrErr))
return ToLabel;
} else {
if (GetImportedOrCreateDecl(ToLabel, D, Importer.getToContext(), DC, Loc,
Name.getAsIdentifierInfo()))
return ToLabel;
}
Expected<LabelStmt *> ToStmtOrErr = import(D->getStmt());
if (!ToStmtOrErr)
return ToStmtOrErr.takeError();
ToLabel->setStmt(*ToStmtOrErr);
ToLabel->setLexicalDeclContext(LexicalDC);
LexicalDC->addDeclInternal(ToLabel);
return ToLabel;
}
ExpectedDecl ASTNodeImporter::VisitEnumDecl(EnumDecl *D) {
// Import the major distinguishing characteristics of this enum.
DeclContext *DC, *LexicalDC;
DeclarationName Name;
SourceLocation Loc;
NamedDecl *ToD;
if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
return std::move(Err);
if (ToD)
return ToD;
// Figure out what enum name we're looking for.
unsigned IDNS = Decl::IDNS_Tag;
DeclarationName SearchName = Name;
if (!SearchName && D->getTypedefNameForAnonDecl()) {
if (Error Err = importInto(
SearchName, D->getTypedefNameForAnonDecl()->getDeclName()))
return std::move(Err);
IDNS = Decl::IDNS_Ordinary;
} else if (Importer.getToContext().getLangOpts().CPlusPlus)
IDNS |= Decl::IDNS_Ordinary;
// We may already have an enum of the same name; try to find and match it.
if (!DC->isFunctionOrMethod() && SearchName) {
SmallVector<NamedDecl *, 4> ConflictingDecls;
auto FoundDecls =
Importer.findDeclsInToCtx(DC, SearchName);
for (auto *FoundDecl : FoundDecls) {
if (!FoundDecl->isInIdentifierNamespace(IDNS))
continue;
if (auto *Typedef = dyn_cast<TypedefNameDecl>(FoundDecl)) {
if (const auto *Tag = Typedef->getUnderlyingType()->getAs<TagType>())
FoundDecl = Tag->getDecl();
}
if (auto *FoundEnum = dyn_cast<EnumDecl>(FoundDecl)) {
if (!hasSameVisibilityContext(FoundEnum, D))
continue;
if (IsStructuralMatch(D, FoundEnum))
return Importer.MapImported(D, FoundEnum);
ConflictingDecls.push_back(FoundDecl);
}
}
if (!ConflictingDecls.empty()) {
ExpectedName NameOrErr = Importer.HandleNameConflict(
SearchName, DC, IDNS, ConflictingDecls.data(),
ConflictingDecls.size());
if (NameOrErr)
Name = NameOrErr.get();
else
return NameOrErr.takeError();
}
}
SourceLocation ToBeginLoc;
NestedNameSpecifierLoc ToQualifierLoc;
QualType ToIntegerType;
if (auto Imp = importSeq(
D->getBeginLoc(), D->getQualifierLoc(), D->getIntegerType()))
std::tie(ToBeginLoc, ToQualifierLoc, ToIntegerType) = *Imp;
else
return Imp.takeError();
// Create the enum declaration.
EnumDecl *D2;
if (GetImportedOrCreateDecl(
D2, D, Importer.getToContext(), DC, ToBeginLoc,
Loc, Name.getAsIdentifierInfo(), nullptr, D->isScoped(),
D->isScopedUsingClassTag(), D->isFixed()))
return D2;
D2->setQualifierInfo(ToQualifierLoc);
D2->setIntegerType(ToIntegerType);
D2->setAccess(D->getAccess());
D2->setLexicalDeclContext(LexicalDC);
LexicalDC->addDeclInternal(D2);
// Import the definition
if (D->isCompleteDefinition())
if (Error Err = ImportDefinition(D, D2))
return std::move(Err);
return D2;
}
ExpectedDecl ASTNodeImporter::VisitRecordDecl(RecordDecl *D) {
bool IsFriendTemplate = false;
if (auto *DCXX = dyn_cast<CXXRecordDecl>(D)) {
IsFriendTemplate =
DCXX->getDescribedClassTemplate() &&
DCXX->getDescribedClassTemplate()->getFriendObjectKind() !=
Decl::FOK_None;
}
// Import the major distinguishing characteristics of this record.
DeclContext *DC = nullptr, *LexicalDC = nullptr;
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;
// Figure out what structure name we're looking for.
unsigned IDNS = Decl::IDNS_Tag;
DeclarationName SearchName = Name;
if (!SearchName && D->getTypedefNameForAnonDecl()) {
if (Error Err = importInto(
SearchName, D->getTypedefNameForAnonDecl()->getDeclName()))
return std::move(Err);
IDNS = Decl::IDNS_Ordinary;
} else if (Importer.getToContext().getLangOpts().CPlusPlus)
IDNS |= Decl::IDNS_Ordinary | Decl::IDNS_TagFriend;
// We may already have a record of the same name; try to find and match it.
RecordDecl *PrevDecl = nullptr;
if (!DC->isFunctionOrMethod() && !D->isLambda()) {
SmallVector<NamedDecl *, 4> ConflictingDecls;
auto FoundDecls =
Importer.findDeclsInToCtx(DC, SearchName);
if (!FoundDecls.empty()) {
// We're going to have to compare D against potentially conflicting Decls,
// so complete it.
if (D->hasExternalLexicalStorage() && !D->isCompleteDefinition())
D->getASTContext().getExternalSource()->CompleteType(D);
}
for (auto *FoundDecl : FoundDecls) {
if (!FoundDecl->isInIdentifierNamespace(IDNS))
continue;
Decl *Found = FoundDecl;
if (auto *Typedef = dyn_cast<TypedefNameDecl>(Found)) {
if (const auto *Tag = Typedef->getUnderlyingType()->getAs<TagType>())
Found = Tag->getDecl();
}
if (auto *FoundRecord = dyn_cast<RecordDecl>(Found)) {
// Do not emit false positive diagnostic in case of unnamed
// struct/union and in case of anonymous structs. Would be false
// because there may be several anonymous/unnamed structs in a class.
// E.g. these are both valid:
// struct A { // unnamed structs
// struct { struct A *next; } entry0;
// struct { struct A *next; } entry1;
// };
// struct X { struct { int a; }; struct { int b; }; }; // anon structs
if (!SearchName)
if (!IsStructuralMatch(D, FoundRecord, false))
continue;
if (!hasSameVisibilityContext(FoundRecord, D))
continue;