[PATCH] D14326: ASTImporter rebased onto master

Kareem Khazem via cfe-commits cfe-commits at lists.llvm.org
Fri Sep 23 12:13:03 PDT 2016


Hello,

https://reviews.llvm.org/D14326

has been accepted but hasn't seen any activity for a couple of months.
Are there any plans to merge it?

There is now a small conflict with master, which I have resolved in
the patch below. There is currently one test failing, which I am
working to fix now.

The patch to make D14326 rebase cleanly onto master is this:

------------ 8>< ------ snip ----------------

--- a/lib/AST/ASTImporter.cpp
+++ b/lib/AST/ASTImporter.cpp
@@ -2309,16 +2309,9 @@ bool ASTNodeImporter::ImportDefinition(EnumDecl
*From, EnumDecl *To,

 TemplateParameterList *ASTNodeImporter::ImportTemplateParameterList(
                                                 TemplateParameterList
*Params) {
-  SmallVector<NamedDecl *, 4> ToParams;
-  ToParams.reserve(Params->size());
-  for (TemplateParameterList::iterator P = Params->begin(),
-                                    PEnd = Params->end();
-       P != PEnd; ++P) {
-    Decl *To = Importer.Import(*P);
-    if (!To)
-      return nullptr;
-    ToParams.push_back(cast<NamedDecl>(To));
-  }
+  SmallVector<NamedDecl *, 4> ToParams(Params->size());
+  if (ImportContainerChecked(*Params, ToParams))
+    return nullptr;

   Expr *ToRequiresClause;
   if (Expr *const R = Params->getRequiresClause()) {


------------ 8>< ------ snip ----------------


Thus, the full patch is as follows:


------------ 8>< ------ snip ----------------

--- a/include/clang/AST/ASTImporter.h
+++ b/include/clang/AST/ASTImporter.h
@@ -24,6 +24,7 @@
 namespace clang {
   class ASTContext;
   class CXXCtorInitializer;
+  class CXXBaseSpecifier;
   class Decl;
   class DeclContext;
   class DiagnosticsEngine;
@@ -39,7 +40,9 @@ namespace clang {
   class ASTImporter {
   public:
     typedef llvm::DenseSet<std::pair<Decl *, Decl *> > NonEquivalentDeclSet;
-
+    typedef llvm::DenseMap<const CXXBaseSpecifier *, CXXBaseSpecifier *>
+    ImportedCXXBaseSpecifierMap;
+
   private:
     /// \brief The contexts we're importing to and from.
     ASTContext &ToContext, &FromContext;
@@ -68,7 +71,12 @@ namespace clang {
     /// \brief Mapping from the already-imported FileIDs in the "from" source
     /// manager to the corresponding FileIDs in the "to" source manager.
     llvm::DenseMap<FileID, FileID> ImportedFileIDs;
-
+
+    /// \brief Mapping from the already-imported CXXBasesSpecifier in
+    ///  the "from" source manager to the corresponding CXXBasesSpecifier
+    ///  in the "to" source manager.
+    ImportedCXXBaseSpecifierMap ImportedCXXBaseSpecifiers;
+
     /// \brief Imported, anonymous tag declarations that are missing their
     /// corresponding typedefs.
     SmallVector<TagDecl *, 4> AnonTagsWithPendingTypedefs;
@@ -212,8 +220,13 @@ namespace clang {
     /// \returns the equivalent initializer in the "to" context.
     CXXCtorInitializer *Import(CXXCtorInitializer *FromInit);

+    /// \brief Import the given CXXBaseSpecifier from the "from" context into
+    /// the "to" context.
+    ///
+    /// \returns the equivalent CXXBaseSpecifier in the source manager of the
+    /// "to" context.
+    CXXBaseSpecifier *Import(const CXXBaseSpecifier *FromSpec);

-
     /// \brief Import the definition of the given declaration, including all of
     /// the declarations it contains.
     ///
diff --git a/include/clang/AST/DeclFriend.h b/include/clang/AST/DeclFriend.h
index 5b2e2d9..48ccb7c 100644
--- a/include/clang/AST/DeclFriend.h
+++ b/include/clang/AST/DeclFriend.h
@@ -166,6 +166,7 @@ public:

   friend class ASTDeclReader;
   friend class ASTDeclWriter;
+  friend class ASTNodeImporter;
   friend TrailingObjects;
 };

diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp
index 7c0a87d..d15a5c5 100644
--- a/lib/AST/ASTImporter.cpp
+++ b/lib/AST/ASTImporter.cpp
@@ -40,6 +40,7 @@ namespace clang {
     // Importing types
     QualType VisitType(const Type *T);
     QualType VisitBuiltinType(const BuiltinType *T);
+    QualType VisitDecayedType(const DecayedType *T);
     QualType VisitComplexType(const ComplexType *T);
     QualType VisitPointerType(const PointerType *T);
     QualType VisitBlockPointerType(const BlockPointerType *T);
@@ -88,6 +89,8 @@ namespace clang {
                                   DeclarationNameInfo& To);
     void ImportDeclContext(DeclContext *FromDC, bool ForceImport = false);

+    bool ImportCastPath(CastExpr *E, CXXCastPath &Path);
+
     typedef DesignatedInitExpr::Designator Designator;
     Designator ImportDesignator(const Designator &D);

@@ -123,6 +126,8 @@ namespace clang {
     TemplateParameterList *ImportTemplateParameterList(

TemplateParameterList *Params);
     TemplateArgument ImportTemplateArgument(const TemplateArgument &From);
+    TemplateArgumentLoc ImportTemplateArgumentLoc(
+        const TemplateArgumentLoc &TALoc, bool &Error);
     bool ImportTemplateArguments(const TemplateArgument *FromArgs,
                                  unsigned NumFromArgs,
                                SmallVectorImpl<TemplateArgument> &ToArgs);
@@ -136,6 +141,7 @@ namespace clang {
     bool IsStructuralMatch(VarTemplateDecl *From, VarTemplateDecl *To);
     Decl *VisitDecl(Decl *D);
     Decl *VisitAccessSpecDecl(AccessSpecDecl *D);
+    Decl *VisitStaticAssertDecl(StaticAssertDecl *D);
     Decl *VisitTranslationUnitDecl(TranslationUnitDecl *D);
     Decl *VisitNamespaceDecl(NamespaceDecl *D);
     Decl *VisitTypedefNameDecl(TypedefNameDecl *D, bool IsAlias);
@@ -152,6 +158,7 @@ namespace clang {
     Decl *VisitCXXConversionDecl(CXXConversionDecl *D);
     Decl *VisitFieldDecl(FieldDecl *D);
     Decl *VisitIndirectFieldDecl(IndirectFieldDecl *D);
+    Decl *VisitFriendDecl(FriendDecl *D);
     Decl *VisitObjCIvarDecl(ObjCIvarDecl *D);
     Decl *VisitVarDecl(VarDecl *D);
     Decl *VisitImplicitParamDecl(ImplicitParamDecl *D);
@@ -242,11 +249,25 @@ namespace clang {
     Expr *VisitConditionalOperator(ConditionalOperator *E);
     Expr *VisitBinaryConditionalOperator(BinaryConditionalOperator *E);
     Expr *VisitOpaqueValueExpr(OpaqueValueExpr *E);
+    Expr *VisitArrayTypeTraitExpr(ArrayTypeTraitExpr *E);
+    Expr *VisitExpressionTraitExpr(ExpressionTraitExpr *E);
+    Expr *VisitArraySubscriptExpr(ArraySubscriptExpr *E);
     Expr *VisitCompoundAssignOperator(CompoundAssignOperator *E);
     Expr *VisitImplicitCastExpr(ImplicitCastExpr *E);
-    Expr *VisitCStyleCastExpr(CStyleCastExpr *E);
+    Expr *VisitExplicitCastExpr(ExplicitCastExpr *E);
+    Expr *VisitOffsetOfExpr(OffsetOfExpr *OE);
+    Expr *VisitCXXThrowExpr(CXXThrowExpr *E);
+    Expr *VisitCXXNoexceptExpr(CXXNoexceptExpr *E);
+    Expr *VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E);
+    Expr *VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E);
+    Expr *VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E);
+    Expr *VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *CE);
+    Expr *VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E);
+    Expr *VisitCXXNewExpr(CXXNewExpr *CE);
+    Expr *VisitCXXDeleteExpr(CXXDeleteExpr *E);
     Expr *VisitCXXConstructExpr(CXXConstructExpr *E);
     Expr *VisitCXXMemberCallExpr(CXXMemberCallExpr *E);
+    Expr *VisitExprWithCleanups(ExprWithCleanups *EWC);
     Expr *VisitCXXThisExpr(CXXThisExpr *E);
     Expr *VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E);
     Expr *VisitMemberExpr(MemberExpr *E);
@@ -272,13 +293,26 @@ namespace clang {
       bool Failed = false;
       std::transform(Ibegin, Iend, Obegin,
                      [&ImporterRef, &Failed](ItemT *From) -> ItemT * {
-                       ItemT *To = ImporterRef.Import(From);
+                       ItemT *To = cast_or_null<ItemT>(
+                             ImporterRef.Import(From));
                        if (!To && From)
                          Failed = true;
                        return To;
                      });
       return Failed;
     }
+
+    template<typename InContainerTy, typename OutContainerTy>
+    bool ImportContainerChecked(const InContainerTy &InContainer,
+                                OutContainerTy &OutContainer) {
+      return ImportArrayChecked(InContainer.begin(), InContainer.end(),
+                                OutContainer.begin());
+    }
+
+    template<typename InContainerTy, typename OIter>
+    bool ImportArrayChecked(const InContainerTy &InContainer, OIter Obegin) {
+      return ImportArrayChecked(InContainer.begin(),
InContainer.end(), Obegin);
+    }
   };
 }

@@ -1611,6 +1645,14 @@ QualType
ASTNodeImporter::VisitBuiltinType(const BuiltinType *T) {
   llvm_unreachable("Invalid BuiltinType Kind!");
 }

+QualType ASTNodeImporter::VisitDecayedType(const DecayedType *T) {
+  QualType OrigT = Importer.Import(T->getOriginalType());
+  if (OrigT.isNull())
+    return QualType();
+
+  return Importer.getToContext().getDecayedType(OrigT);
+}
+
 QualType ASTNodeImporter::VisitComplexType(const ComplexType *T) {
   QualType ToElementType = Importer.Import(T->getElementType());
   if (ToElementType.isNull())
@@ -2267,18 +2309,10 @@ bool
ASTNodeImporter::ImportDefinition(EnumDecl *From, EnumDecl *To,

 TemplateParameterList *ASTNodeImporter::ImportTemplateParameterList(
                                                 TemplateParameterList
*Params) {
-  SmallVector<NamedDecl *, 4> ToParams;
-  ToParams.reserve(Params->size());
-  for (TemplateParameterList::iterator P = Params->begin(),
-                                    PEnd = Params->end();
-       P != PEnd; ++P) {
-    Decl *To = Importer.Import(*P);
-    if (!To)
-      return nullptr;
+  SmallVector<NamedDecl *, 4> ToParams(Params->size());
+  if (ImportContainerChecked(*Params, ToParams))
+    return nullptr;

-    ToParams.push_back(cast<NamedDecl>(To));
-  }
-
   Expr *ToRequiresClause;
   if (Expr *const R = Params->getRequiresClause()) {
     ToRequiresClause = Importer.Import(R);
@@ -2367,6 +2401,31 @@ ASTNodeImporter::ImportTemplateArgument(const
TemplateArgument &From) {
   llvm_unreachable("Invalid template argument kind");
 }

+TemplateArgumentLoc ASTNodeImporter::ImportTemplateArgumentLoc(
+    const TemplateArgumentLoc &TALoc, bool &Error) {
+  Error = false;
+  TemplateArgument Arg = ImportTemplateArgument(TALoc.getArgument());
+  TemplateArgumentLocInfo FromInfo = TALoc.getLocInfo();
+  TemplateArgumentLocInfo ToInfo;
+  if (Arg.getKind() == TemplateArgument::Expression) {
+    Expr *E = Importer.Import(FromInfo.getAsExpr());
+    ToInfo = TemplateArgumentLocInfo(E);
+    if (!E)
+      Error = true;
+  } else if (Arg.getKind() == TemplateArgument::Type) {
+    if (TypeSourceInfo *TSI = Importer.Import(FromInfo.getAsTypeSourceInfo()))
+      ToInfo = TemplateArgumentLocInfo(TSI);
+    else
+      Error = true;
+  } else {
+    ToInfo = TemplateArgumentLocInfo(
+          Importer.Import(FromInfo.getTemplateQualifierLoc()),
+          Importer.Import(FromInfo.getTemplateNameLoc()),
+          Importer.Import(FromInfo.getTemplateEllipsisLoc()));
+  }
+  return TemplateArgumentLoc(Arg, ToInfo);
+}
+
 bool ASTNodeImporter::ImportTemplateArguments(const TemplateArgument *FromArgs,
                                               unsigned NumFromArgs,
                               SmallVectorImpl<TemplateArgument> &ToArgs) {
@@ -2481,6 +2540,35 @@ Decl
*ASTNodeImporter::VisitAccessSpecDecl(AccessSpecDecl *D) {
   return accessSpecDecl;
 }

+Decl *ASTNodeImporter::VisitStaticAssertDecl(StaticAssertDecl *D) {
+  DeclContext *DC = Importer.ImportContext(D->getDeclContext());
+  if (!DC)
+    return nullptr;
+
+  DeclContext *LexicalDC = DC;
+
+  // Import the location of this declaration.
+  SourceLocation Loc = Importer.Import(D->getLocation());
+
+  Expr *AssertExpr = Importer.Import(D->getAssertExpr());
+  if (!AssertExpr)
+    return nullptr;
+
+  StringLiteral *FromMsg = D->getMessage();
+  StringLiteral *ToMsg = cast_or_null<StringLiteral>(Importer.Import(FromMsg));
+  if (!ToMsg && FromMsg)
+    return nullptr;
+
+  StaticAssertDecl *ToD = StaticAssertDecl::Create(
+        Importer.getToContext(), DC, Loc, AssertExpr, ToMsg,
+        Importer.Import(D->getRParenLoc()), D->isFailed());
+
+  ToD->setLexicalDeclContext(LexicalDC);
+  LexicalDC->addDeclInternal(ToD);
+  Importer.Imported(D, ToD);
+  return ToD;
+}
+
 Decl *ASTNodeImporter::VisitNamespaceDecl(NamespaceDecl *D) {
   // Import the major distinguishing characteristics of this namespace.
   DeclContext *DC, *LexicalDC;
@@ -3330,6 +3418,70 @@ Decl
*ASTNodeImporter::VisitIndirectFieldDecl(IndirectFieldDecl *D) {
   return ToIndirectField;
 }

+Decl *ASTNodeImporter::VisitFriendDecl(FriendDecl *D) {
+  // Import the major distinguishing characteristics of a declaration.
+  DeclContext *DC = Importer.ImportContext(D->getDeclContext());
+  DeclContext *LexicalDC = D->getDeclContext() == D->getLexicalDeclContext()
+      ? DC : Importer.ImportContext(D->getLexicalDeclContext());
+  if (!DC || !LexicalDC)
+    return nullptr;
+
+  // Determine whether we've already imported this decl.
+  // FriendDecl is not a NamedDecl so we cannot use localUncachedLookup.
+  CXXRecordDecl *RD = cast<CXXRecordDecl>(DC);
+  FriendDecl *ImportedFriend = RD->getFirstFriend();
+  StructuralEquivalenceContext Context(
+      Importer.getFromContext(), Importer.getToContext(),
+      Importer.getNonEquivalentDecls(), false, false);
+
+  while (ImportedFriend) {
+    if (D->getFriendDecl() && ImportedFriend->getFriendDecl()) {
+      if (Context.IsStructurallyEquivalent(D->getFriendDecl(),
+                                           ImportedFriend->getFriendDecl()))
+        return Importer.Imported(D, ImportedFriend);
+
+    } else if (D->getFriendType() && ImportedFriend->getFriendType()) {
+      if (Importer.IsStructurallyEquivalent(
+            D->getFriendType()->getType(),
+            ImportedFriend->getFriendType()->getType(), true))
+        return Importer.Imported(D, ImportedFriend);
+    }
+    ImportedFriend = ImportedFriend->getNextFriend();
+  }
+
+  // Not found. Create it.
+  FriendDecl::FriendUnion ToFU;
+  if (NamedDecl *FriendD = D->getFriendDecl())
+    ToFU = cast_or_null<NamedDecl>(Importer.Import(FriendD));
+  else
+    ToFU = Importer.Import(D->getFriendType());
+  if (!ToFU)
+    return nullptr;
+
+  SmallVector<TemplateParameterList *, 1> ToTPLists(D->NumTPLists);
+  TemplateParameterList **FromTPLists =
+      D->getTrailingObjects<TemplateParameterList *>();
+  for (unsigned I = 0; I < D->NumTPLists; I++) {
+    TemplateParameterList *List = ImportTemplateParameterList(FromTPLists[I]);
+    if (!List)
+      return nullptr;
+    ToTPLists[I] = List;
+  }
+
+  FriendDecl *FrD = FriendDecl::Create(Importer.getToContext(), DC,
+                                       Importer.Import(D->getLocation()),
+                                       ToFU,
Importer.Import(D->getFriendLoc()),
+                                       ToTPLists);
+
+  Importer.Imported(D, FrD);
+  RD->pushFriendDecl(FrD);
+
+  FrD->setAccess(D->getAccess());
+  FrD->setLexicalDeclContext(LexicalDC);
+  LexicalDC->addDeclInternal(FrD);
+  return FrD;
+}
+
 Decl *ASTNodeImporter::VisitObjCIvarDecl(ObjCIvarDecl *D) {
   // Import the major distinguishing characteristics of an ivar.
   DeclContext *DC, *LexicalDC;
@@ -4886,11 +5038,10 @@ Stmt *ASTNodeImporter::VisitGCCAsmStmt(GCCAsmStmt *S) {
   }

   SmallVector<Expr *, 4> Exprs(S->getNumOutputs() + S->getNumInputs());
-  if (ImportArrayChecked(S->begin_outputs(), S->end_outputs(), Exprs.begin()))
+  if (ImportContainerChecked(S->outputs(), Exprs))
     return nullptr;

-  if (ImportArrayChecked(S->begin_inputs(), S->end_inputs(),
-                         Exprs.begin() + S->getNumOutputs()))
+  if (ImportArrayChecked(S->inputs(), Exprs.begin() + S->getNumOutputs()))
     return nullptr;

   StringLiteral *AsmStr = cast_or_null<StringLiteral>(
@@ -4933,8 +5084,8 @@ Stmt *ASTNodeImporter::VisitNullStmt(NullStmt *S) {

 Stmt *ASTNodeImporter::VisitCompoundStmt(CompoundStmt *S) {
   llvm::SmallVector<Stmt *, 8> ToStmts(S->size());
-
-  if (ImportArrayChecked(S->body_begin(), S->body_end(), ToStmts.begin()))
+
+  if (ImportContainerChecked(S->body(), ToStmts))
     return nullptr;

   SourceLocation ToLBraceLoc = Importer.Import(S->getLBracLoc());
@@ -5388,7 +5539,7 @@ Expr *ASTNodeImporter::VisitGNUNullExpr(GNUNullExpr *E) {
     return nullptr;

   return new (Importer.getToContext()) GNUNullExpr(
-        T, Importer.Import(E->getExprLoc()));
+        T, Importer.Import(E->getLocStart()));
 }

 Expr *ASTNodeImporter::VisitPredefinedExpr(PredefinedExpr *E) {
@@ -5402,7 +5553,7 @@ Expr
*ASTNodeImporter::VisitPredefinedExpr(PredefinedExpr *E) {
     return nullptr;

   return new (Importer.getToContext()) PredefinedExpr(
-        Importer.Import(E->getExprLoc()), T, E->getIdentType(), SL);
+        Importer.Import(E->getLocStart()), T, E->getIdentType(), SL);
 }

 Expr *ASTNodeImporter::VisitDeclRefExpr(DeclRefExpr *E) {
@@ -5421,6 +5572,23 @@ Expr *ASTNodeImporter::VisitDeclRefExpr(DeclRefExpr *E) {
   if (T.isNull())
     return nullptr;

+
+  TemplateArgumentListInfo ToTAInfo;
+  TemplateArgumentListInfo *ResInfo = nullptr;
+  if (E->hasExplicitTemplateArgs()) {
+    const TemplateArgumentLoc *FromArgArray = E->getTemplateArgs();
+    for (unsigned i = 0, e = E->getNumTemplateArgs(); i < e; i++) {
+      const TemplateArgumentLoc &FromLoc = FromArgArray[i];
+      bool Error = false;
+      TemplateArgumentLoc ToTALoc = ImportTemplateArgumentLoc(FromLoc, Error);
+      if (Error)
+        return nullptr;
+      else
+        ToTAInfo.addArgument(ToTALoc);
+    }
+    ResInfo = &ToTAInfo;
+  }
+
   DeclRefExpr *DRE = DeclRefExpr::Create(Importer.getToContext(),
                                          Importer.Import(E->getQualifierLoc()),
                                    Importer.Import(E->getTemplateKeywordLoc()),
@@ -5429,7 +5597,7 @@ Expr *ASTNodeImporter::VisitDeclRefExpr(DeclRefExpr *E) {
                                          Importer.Import(E->getLocation()),
                                          T, E->getValueKind(),
                                          FoundD,
-                                         /*FIXME:TemplateArgs=*/nullptr);
+                                         /*TemplateArgs=*/ResInfo);
   if (E->hadMultipleCandidates())
     DRE->setHadMultipleCandidates(true);
   return DRE;
@@ -5438,7 +5606,7 @@ Expr *ASTNodeImporter::VisitDeclRefExpr(DeclRefExpr *E) {
 Expr *ASTNodeImporter::VisitImplicitValueInitExpr(ImplicitValueInitExpr *E) {
   QualType T = Importer.Import(E->getType());
   if (T.isNull())
-    return NULL;
+    return nullptr;

   return new (Importer.getToContext()) ImplicitValueInitExpr(T);
 }
@@ -5607,8 +5775,7 @@ Expr *ASTNodeImporter::VisitParenExpr(ParenExpr *E) {

 Expr *ASTNodeImporter::VisitParenListExpr(ParenListExpr *E) {
   SmallVector<Expr *, 4> Exprs(E->getNumExprs());
-  if (ImportArrayChecked(
-        E->getExprs(), E->getExprs() + E->getNumExprs(), Exprs.begin()))
+  if (ImportContainerChecked(E->exprs(), Exprs))
     return nullptr;

   return new (Importer.getToContext()) ParenListExpr(
@@ -5746,6 +5913,38 @@ Expr *ASTNodeImporter::VisitBinaryConditionalOperator(
         T, E->getValueKind(), E->getObjectKind());
 }

+Expr *ASTNodeImporter::VisitArrayTypeTraitExpr(ArrayTypeTraitExpr *E) {
+  QualType T = Importer.Import(E->getType());
+  if (T.isNull())
+    return nullptr;
+
+  TypeSourceInfo *ToQueried = Importer.Import(E->getQueriedTypeSourceInfo());
+  if (!ToQueried)
+    return nullptr;
+
+  Expr *Dim = Importer.Import(E->getDimensionExpression());
+  if (!Dim && E->getDimensionExpression())
+    return nullptr;
+
+  return new (Importer.getToContext()) ArrayTypeTraitExpr(
+        Importer.Import(E->getLocStart()), E->getTrait(), ToQueried,
+        E->getValue(), Dim, Importer.Import(E->getLocEnd()), T);
+}
+
+Expr *ASTNodeImporter::VisitExpressionTraitExpr(ExpressionTraitExpr *E) {
+  QualType T = Importer.Import(E->getType());
+  if (T.isNull())
+    return nullptr;
+
+  Expr *ToQueried = Importer.Import(E->getQueriedExpression());
+  if (!ToQueried)
+    return nullptr;
+
+  return new (Importer.getToContext()) ExpressionTraitExpr(
+        Importer.Import(E->getLocStart()), E->getTrait(), ToQueried,
+        E->getValue(), Importer.Import(E->getLocEnd()), T);
+}
+
 Expr *ASTNodeImporter::VisitOpaqueValueExpr(OpaqueValueExpr *E) {
   QualType T = Importer.Import(E->getType());
   if (T.isNull())
@@ -5756,10 +5955,28 @@ Expr
*ASTNodeImporter::VisitOpaqueValueExpr(OpaqueValueExpr *E) {
     return nullptr;

   return new (Importer.getToContext()) OpaqueValueExpr(
-        Importer.Import(E->getExprLoc()), T, E->getValueKind(),
+        Importer.Import(E->getLocation()), T, E->getValueKind(),
         E->getObjectKind(), SourceExpr);
 }

+Expr *ASTNodeImporter::VisitArraySubscriptExpr(ArraySubscriptExpr *E) {
+  QualType T = Importer.Import(E->getType());
+  if (T.isNull())
+    return nullptr;
+
+  Expr *ToLHS = Importer.Import(E->getLHS());
+  if (!ToLHS)
+    return nullptr;
+
+  Expr *ToRHS = Importer.Import(E->getRHS());
+  if (!ToRHS)
+    return nullptr;
+
+  return new (Importer.getToContext()) ArraySubscriptExpr(
+        ToLHS, ToRHS, T, E->getValueKind(), E->getObjectKind(),
+        Importer.Import(E->getRBracketLoc()));
+}
+
 Expr *ASTNodeImporter::VisitCompoundAssignOperator(CompoundAssignOperator *E) {
   QualType T = Importer.Import(E->getType());
   if (T.isNull())
@@ -5790,11 +6007,14 @@ Expr
*ASTNodeImporter::VisitCompoundAssignOperator(CompoundAssignOperator
*E) {
                                                E->isFPContractable());
 }

-static bool ImportCastPath(CastExpr *E, CXXCastPath &Path) {
-  if (E->path_empty()) return false;
-
-  // TODO: import cast paths
-  return true;
+bool ASTNodeImporter::ImportCastPath(CastExpr *CE, CXXCastPath &Path) {
+  for (auto I = CE->path_begin(), E = CE->path_end(); I != E; ++I) {
+    if (CXXBaseSpecifier *Spec = Importer.Import(*I))
+      Path.push_back(Spec);
+    else
+      return true;
+  }
+  return false;
 }

 Expr *ASTNodeImporter::VisitImplicitCastExpr(ImplicitCastExpr *E) {
@@ -5814,7 +6034,7 @@ Expr
*ASTNodeImporter::VisitImplicitCastExpr(ImplicitCastExpr *E) {
                                   SubExpr, &BasePath, E->getValueKind());
 }

-Expr *ASTNodeImporter::VisitCStyleCastExpr(CStyleCastExpr *E) {
+Expr *ASTNodeImporter::VisitExplicitCastExpr(ExplicitCastExpr *E) {
   QualType T = Importer.Import(E->getType());
   if (T.isNull())
     return nullptr;
@@ -5831,11 +6051,320 @@ Expr
*ASTNodeImporter::VisitCStyleCastExpr(CStyleCastExpr *E) {
   if (ImportCastPath(E, BasePath))
     return nullptr;

-  return CStyleCastExpr::Create(Importer.getToContext(), T,
-                                E->getValueKind(), E->getCastKind(),
-                                SubExpr, &BasePath, TInfo,
-                                Importer.Import(E->getLParenLoc()),
-                                Importer.Import(E->getRParenLoc()));
+  switch (E->getStmtClass()) {
+  case Stmt::CStyleCastExprClass: {
+    CStyleCastExpr *CCE = cast<CStyleCastExpr>(E);
+    return CStyleCastExpr::Create(Importer.getToContext(), T,
+                                  E->getValueKind(), E->getCastKind(),
+                                  SubExpr, &BasePath, TInfo,
+                                  Importer.Import(CCE->getLParenLoc()),
+                                  Importer.Import(CCE->getRParenLoc()));
+  }
+
+  case Stmt::CXXFunctionalCastExprClass: {
+    CXXFunctionalCastExpr *FCE = cast<CXXFunctionalCastExpr>(E);
+    return CXXFunctionalCastExpr::Create(Importer.getToContext(), T,
+                                         E->getValueKind(), TInfo,
+                                         E->getCastKind(), SubExpr, &BasePath,
+                                         Importer.Import(FCE->getLParenLoc()),
+                                         Importer.Import(FCE->getRParenLoc()));
+  }
+
+  case Stmt::ObjCBridgedCastExprClass: {
+      ObjCBridgedCastExpr *OCE = cast<ObjCBridgedCastExpr>(E);
+      return new (Importer.getToContext()) ObjCBridgedCastExpr(
+            Importer.Import(OCE->getLParenLoc()), OCE->getBridgeKind(),
+            E->getCastKind(), Importer.Import(OCE->getBridgeKeywordLoc()),
+            TInfo, SubExpr);
+  }
+  default:
+    break; // just fall through
+  }
+
+  CXXNamedCastExpr *Named = cast<CXXNamedCastExpr>(E);
+  SourceLocation ExprLoc = Importer.Import(Named->getOperatorLoc()),
+      RParenLoc = Importer.Import(Named->getRParenLoc());
+  SourceRange Brackets = Importer.Import(Named->getAngleBrackets());
+
+  switch (E->getStmtClass()) {
+  case Stmt::CXXStaticCastExprClass:
+    return CXXStaticCastExpr::Create(Importer.getToContext(), T,
+                                     E->getValueKind(), E->getCastKind(),
+                                     SubExpr, &BasePath, TInfo,
+                                     ExprLoc, RParenLoc, Brackets);
+
+  case Stmt::CXXDynamicCastExprClass:
+    return CXXDynamicCastExpr::Create(Importer.getToContext(), T,
+                                      E->getValueKind(), E->getCastKind(),
+                                      SubExpr, &BasePath, TInfo,
+                                      ExprLoc, RParenLoc, Brackets);
+
+  case Stmt::CXXReinterpretCastExprClass:
+    return CXXReinterpretCastExpr::Create(Importer.getToContext(), T,
+                                          E->getValueKind(), E->getCastKind(),
+                                          SubExpr, &BasePath, TInfo,
+                                          ExprLoc, RParenLoc, Brackets);
+
+  case Stmt::CXXConstCastExprClass:
+    return CXXConstCastExpr::Create(Importer.getToContext(), T,
+                                    E->getValueKind(), SubExpr, TInfo, ExprLoc,
+                                    RParenLoc, Brackets);
+  default:
+    llvm_unreachable("Cast expression of unsupported type!");
+    return nullptr;
+  }
+}
+
+Expr *ASTNodeImporter::VisitOffsetOfExpr(OffsetOfExpr *OE) {
+  QualType T = Importer.Import(OE->getType());
+  if (T.isNull())
+    return nullptr;
+
+  SmallVector<OffsetOfNode, 4> Nodes;
+  for (int I = 0, E = OE->getNumComponents(); I < E; ++I) {
+    const OffsetOfNode &Node = OE->getComponent(I);
+
+    switch (Node.getKind()) {
+    case OffsetOfNode::Array:
+      Nodes.push_back(OffsetOfNode(Importer.Import(Node.getLocStart()),
+                                   Node.getArrayExprIndex(),
+                                   Importer.Import(Node.getLocEnd())));
+      break;
+
+    case OffsetOfNode::Base: {
+      CXXBaseSpecifier *BS = Importer.Import(Node.getBase());
+      if (!BS && Node.getBase())
+        return nullptr;
+      Nodes.push_back(OffsetOfNode(BS));
+      break;
+    }
+    case OffsetOfNode::Field: {
+      FieldDecl *FD =
cast_or_null<FieldDecl>(Importer.Import(Node.getField()));
+      if (!FD)
+        return nullptr;
+      Nodes.push_back(OffsetOfNode(Importer.Import(Node.getLocStart()), FD,
+                                   Importer.Import(Node.getLocEnd())));
+      break;
+    }
+    case OffsetOfNode::Identifier: {
+      IdentifierInfo *ToII = Importer.Import(Node.getFieldName());
+      if (!ToII)
+        return nullptr;
+      Nodes.push_back(OffsetOfNode(Importer.Import(Node.getLocStart()), ToII,
+                                   Importer.Import(Node.getLocEnd())));
+      break;
+    }
+    }
+  }
+
+  SmallVector<Expr *, 4> Exprs(OE->getNumExpressions());
+  for (int I = 0, E = OE->getNumExpressions(); I < E; ++I) {
+    Expr *ToIndexExpr = Importer.Import(OE->getIndexExpr(I));
+    if (!ToIndexExpr)
+      return nullptr;
+    Exprs[I] = ToIndexExpr;
+  }
+
+  TypeSourceInfo *TInfo = Importer.Import(OE->getTypeSourceInfo());
+  if (!TInfo && OE->getTypeSourceInfo())
+    return nullptr;
+
+  return OffsetOfExpr::Create(Importer.getToContext(), T,
+                              Importer.Import(OE->getOperatorLoc()),
+                              TInfo, Nodes, Exprs,
+                              Importer.Import(OE->getRParenLoc()));
+}
+
+Expr *ASTNodeImporter::VisitCXXNoexceptExpr(CXXNoexceptExpr *E) {
+  QualType T = Importer.Import(E->getType());
+  if (T.isNull())
+    return nullptr;
+
+  Expr *Operand = Importer.Import(E->getOperand());
+  if (!Operand)
+    return nullptr;
+
+  CanThrowResult CanThrow;
+  if (E->isValueDependent())
+    CanThrow = CT_Dependent;
+  else
+    CanThrow = E->getValue() ? CT_Can : CT_Cannot;
+
+  return new (Importer.getToContext()) CXXNoexceptExpr(
+        T, Operand, CanThrow,
+        Importer.Import(E->getLocStart()), Importer.Import(E->getLocEnd()));
+}
+
+Expr *ASTNodeImporter::VisitCXXThrowExpr(CXXThrowExpr *E) {
+  QualType T = Importer.Import(E->getType());
+  if (T.isNull())
+    return nullptr;
+
+  Expr *SubExpr = Importer.Import(E->getSubExpr());
+  if (!SubExpr && E->getSubExpr())
+    return nullptr;
+
+  return new (Importer.getToContext()) CXXThrowExpr(
+        SubExpr, T, Importer.Import(E->getThrowLoc()),
+        E->isThrownVariableInScope());
+}
+
+Expr *ASTNodeImporter::VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) {
+  ParmVarDecl *Param = cast_or_null<ParmVarDecl>(
+        Importer.Import(E->getParam()));
+  if (!Param)
+    return nullptr;
+
+  return CXXDefaultArgExpr::Create(
+        Importer.getToContext(), Importer.Import(E->getUsedLocation()), Param);
+}
+
+Expr *ASTNodeImporter::VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E) {
+  QualType T = Importer.Import(E->getType());
+  if (T.isNull())
+    return nullptr;
+
+  TypeSourceInfo *TypeInfo = Importer.Import(E->getTypeSourceInfo());
+  if (!TypeInfo)
+    return nullptr;
+
+  return new (Importer.getToContext()) CXXScalarValueInitExpr(
+        T, TypeInfo, Importer.Import(E->getRParenLoc()));
+}
+
+Expr *ASTNodeImporter::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) {
+  Expr *SubExpr = Importer.Import(E->getSubExpr());
+  if (!SubExpr)
+    return nullptr;
+
+  auto *Dtor = cast_or_null<CXXDestructorDecl>(
+        Importer.Import(const_cast<CXXDestructorDecl *>(
+                          E->getTemporary()->getDestructor())));
+  if (!Dtor)
+    return nullptr;
+
+  ASTContext &ToCtx = Importer.getToContext();
+  CXXTemporary *Temp = CXXTemporary::Create(ToCtx, Dtor);
+  return CXXBindTemporaryExpr::Create(ToCtx, Temp, SubExpr);
+}
+
+Expr *ASTNodeImporter::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr
*CE) {
+  QualType T = Importer.Import(CE->getType());
+  if (T.isNull())
+    return nullptr;
+
+  SmallVector<Expr *, 8> Args(CE->getNumArgs());
+  if (ImportContainerChecked(CE->arguments(), Args))
+    return nullptr;
+
+  auto *Ctor = cast_or_null<CXXConstructorDecl>(
+        Importer.Import(CE->getConstructor()));
+  if (!Ctor)
+    return nullptr;
+
+  return CXXTemporaryObjectExpr::Create(
+        Importer.getToContext(), T,
+        Importer.Import(CE->getLocStart()),
+        Ctor,
+        CE->isElidable(),
+        Args,
+        CE->hadMultipleCandidates(),
+        CE->isListInitialization(),
+        CE->isStdInitListInitialization(),
+        CE->requiresZeroInitialization(),
+        CE->getConstructionKind(),
+        Importer.Import(CE->getParenOrBraceRange()));
+}
+
+Expr *
+ASTNodeImporter::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E) {
+  QualType T = Importer.Import(E->getType());
+  if (T.isNull())
+    return nullptr;
+
+  Expr *TempE = Importer.Import(E->GetTemporaryExpr());
+  if (!TempE)
+    return nullptr;
+
+  ValueDecl *ExtendedBy = cast_or_null<ValueDecl>(
+        Importer.Import(const_cast<ValueDecl *>(E->getExtendingDecl())));
+  if (!ExtendedBy && E->getExtendingDecl())
+    return nullptr;
+
+  auto *ToMTE =  new (Importer.getToContext()) MaterializeTemporaryExpr(
+        T, TempE, E->isBoundToLvalueReference());
+
+  // FIXME: Should ManglingNumber get numbers associated with 'to' context?
+  ToMTE->setExtendingDecl(ExtendedBy, E->getManglingNumber());
+  return ToMTE;
+}
+
+
+Expr *ASTNodeImporter::VisitCXXNewExpr(CXXNewExpr *CE) {
+  QualType T = Importer.Import(CE->getType());
+  if (T.isNull())
+    return nullptr;
+
+  SmallVector<Expr *, 4> PlacementArgs(CE->getNumPlacementArgs());
+  if (ImportContainerChecked(CE->placement_arguments(), PlacementArgs))
+    return nullptr;
+
+  FunctionDecl *OperatorNewDecl = cast_or_null<FunctionDecl>(
+        Importer.Import(CE->getOperatorNew()));
+  if (!OperatorNewDecl && CE->getOperatorNew())
+    return nullptr;
+
+  FunctionDecl *OperatorDeleteDecl = cast_or_null<FunctionDecl>(
+        Importer.Import(CE->getOperatorDelete()));
+  if (!OperatorDeleteDecl && CE->getOperatorDelete())
+    return nullptr;
+
+  Expr *ToInit = Importer.Import(CE->getInitializer());
+  if (!ToInit && CE->getInitializer())
+    return nullptr;
+
+  TypeSourceInfo *TInfo = Importer.Import(CE->getAllocatedTypeSourceInfo());
+  if (!TInfo)
+    return nullptr;
+
+  Expr *ToArrSize = Importer.Import(CE->getArraySize());
+  if (!ToArrSize && CE->getArraySize())
+    return nullptr;
+
+  return new (Importer.getToContext()) CXXNewExpr(
+        Importer.getToContext(),
+        CE->isGlobalNew(),
+        OperatorNewDecl, OperatorDeleteDecl,
+        CE->doesUsualArrayDeleteWantSize(),
+        PlacementArgs,
+        Importer.Import(CE->getTypeIdParens()),
+        ToArrSize, CE->getInitializationStyle(), ToInit, T, TInfo,
+        Importer.Import(CE->getSourceRange()),
+        Importer.Import(CE->getDirectInitRange()));
+}
+
+Expr *ASTNodeImporter::VisitCXXDeleteExpr(CXXDeleteExpr *E) {
+  QualType T = Importer.Import(E->getType());
+  if (T.isNull())
+    return nullptr;
+
+  FunctionDecl *OperatorDeleteDecl = cast_or_null<FunctionDecl>(
+        Importer.Import(E->getOperatorDelete()));
+  if (!OperatorDeleteDecl && E->getOperatorDelete())
+    return nullptr;
+
+  Expr *ToArg = Importer.Import(E->getArgument());
+  if (!ToArg && E->getArgument())
+    return nullptr;
+
+  return new (Importer.getToContext()) CXXDeleteExpr(
+        T, E->isGlobalDelete(),
+        E->isArrayForm(),
+        E->isArrayFormAsWritten(),
+        E->doesUsualArrayDeleteWantSize(),
+        OperatorDeleteDecl,
+        ToArg,
+        Importer.Import(E->getLocStart()));
 }

 Expr *ASTNodeImporter::VisitCXXConstructExpr(CXXConstructExpr *E) {
@@ -5849,8 +6378,7 @@ Expr
*ASTNodeImporter::VisitCXXConstructExpr(CXXConstructExpr *E) {
     return nullptr;

   SmallVector<Expr *, 6> ToArgs(E->getNumArgs());
-  if (ImportArrayChecked(E->getArgs(), E->getArgs() + E->getNumArgs(),
-                         ToArgs.begin()))
+  if (ImportContainerChecked(E->arguments(), ToArgs))
     return nullptr;

   return CXXConstructExpr::Create(Importer.getToContext(), T,
@@ -5864,6 +6392,24 @@ Expr
*ASTNodeImporter::VisitCXXConstructExpr(CXXConstructExpr *E) {
                                   Importer.Import(E->getParenOrBraceRange()));
 }

+Expr *ASTNodeImporter::VisitExprWithCleanups(ExprWithCleanups *EWC) {
+  Expr *SubExpr = Importer.Import(EWC->getSubExpr());
+  if (!SubExpr && EWC->getSubExpr())
+    return nullptr;
+
+  SmallVector<ExprWithCleanups::CleanupObject, 8> Objs(EWC->getNumObjects());
+  for (unsigned I = 0, E = EWC->getNumObjects(); I < E; I++)
+    if (ExprWithCleanups::CleanupObject Obj =
+        cast_or_null<BlockDecl>(Importer.Import(EWC->getObject(I))))
+      Objs[I] = Obj;
+    else
+      return nullptr;
+
+  return ExprWithCleanups::Create(Importer.getToContext(),
+                                  SubExpr, EWC->cleanupsHaveSideEffects(),
+                                  Objs);
+}
+
 Expr *ASTNodeImporter::VisitCXXMemberCallExpr(CXXMemberCallExpr *E) {
   QualType T = Importer.Import(E->getType());
   if (T.isNull())
@@ -5874,8 +6420,7 @@ Expr
*ASTNodeImporter::VisitCXXMemberCallExpr(CXXMemberCallExpr *E) {
     return nullptr;

   SmallVector<Expr *, 4> ToArgs(E->getNumArgs());
-
-  if (ImportArrayChecked(E->arg_begin(), E->arg_end(), ToArgs.begin()))
+  if (ImportContainerChecked(E->arguments(), ToArgs))
     return nullptr;

   return new (Importer.getToContext()) CXXMemberCallExpr(
@@ -5976,8 +6521,7 @@ Expr
*ASTNodeImporter::VisitInitListExpr(InitListExpr *ILE) {
     return nullptr;

   llvm::SmallVector<Expr *, 4> Exprs(ILE->getNumInits());
-  if (ImportArrayChecked(
-        ILE->getInits(), ILE->getInits() + ILE->getNumInits(), Exprs.begin()))
+  if (ImportContainerChecked(ILE->inits(), Exprs))
     return nullptr;

   ASTContext &ToCtx = Importer.getToContext();
@@ -6530,6 +7074,21 @@ CXXCtorInitializer
*ASTImporter::Import(CXXCtorInitializer *From) {
 }


+CXXBaseSpecifier *ASTImporter::Import(const CXXBaseSpecifier *BaseSpec) {
+  auto Pos = ImportedCXXBaseSpecifiers.find(BaseSpec);
+  if (Pos != ImportedCXXBaseSpecifiers.end())
+    return Pos->second;
+
+  CXXBaseSpecifier *Imported = new (ToContext) CXXBaseSpecifier(
+        Import(BaseSpec->getSourceRange()),
+        BaseSpec->isVirtual(), BaseSpec->isBaseOfClass(),
+        BaseSpec->getAccessSpecifierAsWritten(),
+        Import(BaseSpec->getTypeSourceInfo()),
+        Import(BaseSpec->getEllipsisLoc()));
+  ImportedCXXBaseSpecifiers[BaseSpec] = Imported;
+  return Imported;
+}
+
 void ASTImporter::ImportDefinition(Decl *From) {
   Decl *To = Import(From);
   if (!To)
diff --git a/test/ASTMerge/Inputs/class3.cpp b/test/ASTMerge/Inputs/class3.cpp
new file mode 100644
index 0000000..428acc3
--- /dev/null
+++ b/test/ASTMerge/Inputs/class3.cpp
@@ -0,0 +1,26 @@
+class C1 {
+public:
+  C1();
+  ~C1();
+  C1 *method_1() {
+    return this;
+  }
+  C1 method_2() {
+    return C1();
+  }
+  void method_3() {
+    const C1 &ref = C1();
+  }
+};
+
+class C11 : public C1 {
+};
+
+class C2 {
+private:
+  int x;
+  friend class C3;
+public:
+  static_assert(sizeof(x) == sizeof(int), "Error");
+  typedef class C2::C2 InjType;
+};
diff --git a/test/ASTMerge/Inputs/exprs3.cpp b/test/ASTMerge/Inputs/exprs3.cpp
new file mode 100644
index 0000000..33c54f8
--- /dev/null
+++ b/test/ASTMerge/Inputs/exprs3.cpp
@@ -0,0 +1,131 @@
+// Integer literals
+const char Ch1 = 'a';
+const signed char Ch2 = 'b';
+const unsigned char Ch3 = 'c';
+
+const wchar_t Ch4 = L'd';
+const signed wchar_t Ch5 = L'e';
+const unsigned wchar_t Ch6 = L'f';
+
+const short C1 = 12;
+const unsigned short C2 = 13;
+
+const int C3 = 12;
+const unsigned int C4 = 13;
+
+const long C5 = 22;
+const unsigned long C6 = 23;
+
+const long long C7 = 66;
+const unsigned long long C8 = 67;
+
+
+// String literals
+const char str1[] = "ABCD";
+const char str2[] = "ABCD" "0123";
+
+const wchar_t wstr1[] = L"DEF";
+const wchar_t wstr2[] = L"DEF" L"123";
+
+
+// Boolean literals
+const bool bval1 = true;
+const bool bval2 = false;
+
+// Floating Literals
+const float F1 = 12.2F;
+const double F2 = 1E4;
+const long double F3 = 1.2E-3L;
+
+
+// nullptr literal
+const void *vptr = nullptr;
+
+
+int glb_1[4] = { 10, 20, 30, 40 };
+
+struct S1 {
+  int a;
+  int b[3];
+};
+
+struct S2 {
+  int c;
+  S1 d;
+};
+
+S2 glb_2 = { 22, .d.a = 44, .d.b[0] = 55, .d.b[1] = 66 };
+
+void testNewThrowDelete() {
+  throw;
+  char *p = new char[10];
+  delete[] p;
+}
+
+int testArrayElement(int *x, int n) {
+  return x[n];
+}
+
+int testTernaryOp(int c, int x, int y) {
+  return c ? x : y;
+}
+
+S1 &testConstCast(const S1 &x) {
+  return const_cast<S1&>(x);
+}
+
+S1 &testStaticCast(S1 &x) {
+  return static_cast<S1&>(x);
+}
+
+S1 &testReinterpretCast(S1 &x) {
+  return reinterpret_cast<S1&>(x);
+}
+
+S1 &testDynamicCast(S1 &x) {
+  return dynamic_cast<S1&>(x);
+}
+
+int testScalarInit(int x) {
+  return int(x);
+}
+
+struct S {
+  float f;
+  double d;
+};
+struct T {
+  int i;
+  struct S s[10];
+};
+
+void testOffsetOf() {
+  (void)__builtin_offsetof(struct T, s[2].d);
+}
+
+
+unsigned char asmFunc(unsigned char a, unsigned char b) {
+  unsigned int la = a;
+  unsigned int lb = b;
+  unsigned int bigres;
+  unsigned char res;
+  __asm__ ("0:\n1:\n" : [bigres] "=la"(bigres) : [la] "0"(la), [lb] "c"(lb) :
+                        "edx", "cc");
+  res = bigres;
+  return res;
+}
+
+int testDefaultArg(int a = 2*2) {
+  return a;
+}
+
+template <typename T> // T has TemplateTypeParmType
+void testTemplateTypeParmType(int i);
+
+void useTemplateType() {
+  testTemplateTypeParmType<char>(4);
+}
+
+const bool ExpressionTrait = __is_lvalue_expr(1);
+const unsigned ArrayRank = __array_rank(int[10][20]);
+const unsigned ArrayExtent = __array_extent(int[10][20], 1);
diff --git a/test/ASTMerge/class2.cpp b/test/ASTMerge/class2.cpp
new file mode 100644
index 0000000..6021403
--- /dev/null
+++ b/test/ASTMerge/class2.cpp
@@ -0,0 +1,9 @@
+// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++1z -emit-pch
-o %t.1.ast %S/Inputs/class3.cpp
+// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++1z -ast-merge
%t.1.ast -fsyntax-only -verify %s
+// expected-no-diagnostics
+
+class C3 {
+  int method_1(C2 *x) {
+    return x->x;
+  }
+};
diff --git a/test/ASTMerge/exprs.cpp b/test/ASTMerge/exprs.cpp
new file mode 100644
index 0000000..ba1f18b
--- /dev/null
+++ b/test/ASTMerge/exprs.cpp
@@ -0,0 +1,45 @@
+// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++1z
-fcxx-exceptions -emit-pch -o %t.1.ast %S/Inputs/exprs3.cpp
+// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++1z
-fcxx-exceptions -ast-merge %t.1.ast -fsyntax-only -verify %s
+// expected-no-diagnostics
+
+static_assert(Ch1 == 'a');
+static_assert(Ch2 == 'b');
+static_assert(Ch3 == 'c');
+
+static_assert(Ch4 == L'd');
+static_assert(Ch5 == L'e');
+static_assert(Ch6 == L'f');
+
+static_assert(C1 == 12);
+static_assert(C2 == 13);
+
+static_assert(C3 == 12);
+static_assert(C4 == 13);
+
+static_assert(C5 == 22L);
+static_assert(C6 == 23L);
+
+static_assert(C7 == 66LL);
+static_assert(C8 == 67ULL);
+
+static_assert(bval1 == true);
+static_assert(bval2 == false);
+
+static_assert(ExpressionTrait == false);
+
+static_assert(ArrayRank == 2);
+static_assert(ArrayExtent == 20);
+
+void testImport(int *x, const S1 &cs1, S1 &s1) {
+  testNewThrowDelete();
+  testArrayElement(nullptr, 12);
+  testTernaryOp(0, 1, 2);
+  testConstCast(cs1);
+  testStaticCast(s1);
+  testReinterpretCast(s1);
+  testDynamicCast(s1);
+  testScalarInit(42);
+  testOffsetOf();
+  testDefaultArg(12);
+  useTemplateType();
+}
diff --git a/unittests/AST/ASTImporterTest.cpp
b/unittests/AST/ASTImporterTest.cpp
index 3cc38fb..39d6afe 100644
--- a/unittests/AST/ASTImporterTest.cpp
+++ b/unittests/AST/ASTImporterTest.cpp
@@ -456,5 +456,24 @@ TEST(ImportExpr, ImportInitListExpr) {
 }


+const internal::VariadicDynCastAllOfMatcher<Expr, VAArgExpr> vaArgExpr;
+
+TEST(ImportExpr, ImportVAArgExpr) {
+  MatchVerifier<Decl> Verifier;
+  EXPECT_TRUE(
+        testImport(
+          "void declToImport(__builtin_va_list list, ...) {"
+          "  (void)__builtin_va_arg(list, int); }",
+          Lang_CXX, "", Lang_CXX, Verifier,
+          functionDecl(
+            hasBody(
+              compoundStmt(
+                has(
+                  cStyleCastExpr(
+                    hasSourceExpression(
+                      vaArgExpr()))))))));
+}
+
+
 } // end namespace ast_matchers
 } // end namespace clang

------------ 8>< ------ snip ----------------

cheers

-- 
Kareem


More information about the cfe-commits mailing list