r266292 - [ASTImporter] Implement some expression-related AST node import.

Artem Dergachev via cfe-commits cfe-commits at lists.llvm.org
Thu Apr 14 04:51:29 PDT 2016


Author: dergachev
Date: Thu Apr 14 06:51:27 2016
New Revision: 266292

URL: http://llvm.org/viewvc/llvm-project?rev=266292&view=rev
Log:
[ASTImporter] Implement some expression-related AST node import.

Introduce ASTImporter unit test framework.

Fix a memory leak introduced in cf8ccff5: an array is allocated
in ImportArray and never freed.

Support new node kinds:

- GCCAsmStmt

- AddrLabelExpr
- AtomicExpr
- CompoundLiteralExpr
- CXXBoolLiteralExpr
- CXXNullPtrLiteralExpr
- CXXThisExpr
- DesignatedInitExpr
- GNUNullExpr
- ImplicitValueInitExpr
- InitListExpr
- OpaqueValueExpr
- PredefinedExpr
- ParenListExpr
- StmtExpr
- VAArgExpr

- BinaryConditionalOperator
- ConditionalOperator

- FloatingLiteral
- StringLiteral

- InjectedClassNameType
- TemplateTypeParmType

- LabelDecl

Patch by Aleksei Sidorin!

Differential Revision: http://reviews.llvm.org/D14286

Added:
    cfe/trunk/unittests/AST/ASTImporterTest.cpp
Modified:
    cfe/trunk/include/clang/AST/Type.h
    cfe/trunk/lib/AST/ASTImporter.cpp
    cfe/trunk/unittests/AST/CMakeLists.txt

Modified: cfe/trunk/include/clang/AST/Type.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Type.h?rev=266292&r1=266291&r2=266292&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Type.h (original)
+++ cfe/trunk/include/clang/AST/Type.h Thu Apr 14 06:51:27 2016
@@ -4278,6 +4278,8 @@ class InjectedClassNameType : public Typ
   friend class ASTReader; // FIXME: ASTContext::getInjectedClassNameType is not
                           // currently suitable for AST reading, too much
                           // interdependencies.
+  friend class ASTNodeImporter;
+
   InjectedClassNameType(CXXRecordDecl *D, QualType TST)
     : Type(InjectedClassName, QualType(), /*Dependent=*/true,
            /*InstantiationDependent=*/true,

Modified: cfe/trunk/lib/AST/ASTImporter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTImporter.cpp?rev=266292&r1=266291&r2=266292&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTImporter.cpp (original)
+++ cfe/trunk/lib/AST/ASTImporter.cpp Thu Apr 14 06:51:27 2016
@@ -29,7 +29,7 @@ namespace clang {
                           public DeclVisitor<ASTNodeImporter, Decl *>,
                           public StmtVisitor<ASTNodeImporter, Stmt *> {
     ASTImporter &Importer;
-    
+
   public:
     explicit ASTNodeImporter(ASTImporter &Importer) : Importer(Importer) { }
     
@@ -64,11 +64,12 @@ namespace clang {
     QualType VisitDecltypeType(const DecltypeType *T);
     QualType VisitUnaryTransformType(const UnaryTransformType *T);
     QualType VisitAutoType(const AutoType *T);
+    QualType VisitInjectedClassNameType(const InjectedClassNameType *T);
     // FIXME: DependentDecltypeType
     QualType VisitRecordType(const RecordType *T);
     QualType VisitEnumType(const EnumType *T);
     QualType VisitAttributedType(const AttributedType *T);
-    // FIXME: TemplateTypeParmType
+    QualType VisitTemplateTypeParmType(const TemplateTypeParmType *T);
     // FIXME: SubstTemplateTypeParmType
     QualType VisitTemplateSpecializationType(const TemplateSpecializationType *T);
     QualType VisitElaboratedType(const ElaboratedType *T);
@@ -86,6 +87,10 @@ namespace clang {
     void ImportDeclarationNameLoc(const DeclarationNameInfo &From,
                                   DeclarationNameInfo& To);
     void ImportDeclContext(DeclContext *FromDC, bool ForceImport = false);
+
+    typedef DesignatedInitExpr::Designator Designator;
+    Designator ImportDesignator(const Designator &D);
+
                         
     /// \brief What we should import from the definition.
     enum ImportDefinitionKind { 
@@ -136,6 +141,7 @@ namespace clang {
     Decl *VisitTypedefNameDecl(TypedefNameDecl *D, bool IsAlias);
     Decl *VisitTypedefDecl(TypedefDecl *D);
     Decl *VisitTypeAliasDecl(TypeAliasDecl *D);
+    Decl *VisitLabelDecl(LabelDecl *D);
     Decl *VisitEnumDecl(EnumDecl *D);
     Decl *VisitRecordDecl(RecordDecl *D);
     Decl *VisitEnumConstantDecl(EnumConstantDecl *D);
@@ -175,6 +181,7 @@ namespace clang {
     DeclGroupRef ImportDeclGroup(DeclGroupRef DG);
 
     Stmt *VisitStmt(Stmt *S);
+    Stmt *VisitGCCAsmStmt(GCCAsmStmt *S);
     Stmt *VisitDeclStmt(DeclStmt *S);
     Stmt *VisitNullStmt(NullStmt *S);
     Stmt *VisitCompoundStmt(CompoundStmt *S);
@@ -192,7 +199,6 @@ namespace clang {
     Stmt *VisitContinueStmt(ContinueStmt *S);
     Stmt *VisitBreakStmt(BreakStmt *S);
     Stmt *VisitReturnStmt(ReturnStmt *S);
-    // FIXME: GCCAsmStmt
     // FIXME: MSAsmStmt
     // FIXME: SEHExceptStmt
     // FIXME: SEHFinallyStmt
@@ -213,13 +219,29 @@ namespace clang {
 
     // Importing expressions
     Expr *VisitExpr(Expr *E);
+    Expr *VisitVAArgExpr(VAArgExpr *E);
+    Expr *VisitGNUNullExpr(GNUNullExpr *E);
+    Expr *VisitPredefinedExpr(PredefinedExpr *E);
     Expr *VisitDeclRefExpr(DeclRefExpr *E);
+    Expr *VisitImplicitValueInitExpr(ImplicitValueInitExpr *ILE);
+    Expr *VisitDesignatedInitExpr(DesignatedInitExpr *E);
+    Expr *VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *E);
     Expr *VisitIntegerLiteral(IntegerLiteral *E);
+    Expr *VisitFloatingLiteral(FloatingLiteral *E);
     Expr *VisitCharacterLiteral(CharacterLiteral *E);
+    Expr *VisitStringLiteral(StringLiteral *E);
+    Expr *VisitCompoundLiteralExpr(CompoundLiteralExpr *E);
+    Expr *VisitAtomicExpr(AtomicExpr *E);
+    Expr *VisitAddrLabelExpr(AddrLabelExpr *E);
     Expr *VisitParenExpr(ParenExpr *E);
+    Expr *VisitParenListExpr(ParenListExpr *E);
+    Expr *VisitStmtExpr(StmtExpr *E);
     Expr *VisitUnaryOperator(UnaryOperator *E);
     Expr *VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E);
     Expr *VisitBinaryOperator(BinaryOperator *E);
+    Expr *VisitConditionalOperator(ConditionalOperator *E);
+    Expr *VisitBinaryConditionalOperator(BinaryConditionalOperator *E);
+    Expr *VisitOpaqueValueExpr(OpaqueValueExpr *E);
     Expr *VisitCompoundAssignOperator(CompoundAssignOperator *E);
     Expr *VisitImplicitCastExpr(ImplicitCastExpr *E);
     Expr *VisitCStyleCastExpr(CStyleCastExpr *E);
@@ -230,32 +252,34 @@ namespace clang {
     Expr *VisitMemberExpr(MemberExpr *E);
     Expr *VisitCallExpr(CallExpr *E);
     Expr *VisitInitListExpr(InitListExpr *E);
-                            
-    template <typename T, typename Iter> bool ImportArray(Iter B, Iter E, llvm::ArrayRef<T*> &ToArray) {
-      size_t NumElements = E - B;
-      SmallVector<T *, 1> ImportedElements(NumElements);
-      ASTImporter &_Importer = Importer;
-      
+
+    template<typename IIter, typename OIter>
+    void ImportArray(IIter Ibegin, IIter Iend, OIter Obegin) {
+      typedef typename std::remove_reference<decltype(*Obegin)>::type ItemT;
+      ASTImporter &ImporterRef = Importer;
+      std::transform(Ibegin, Iend, Obegin,
+                     [&ImporterRef](ItemT From) -> ItemT {
+                       return ImporterRef.Import(From);
+                     });
+    }
+
+    template<typename IIter, typename OIter>
+    bool ImportArrayChecked(IIter Ibegin, IIter Iend, OIter Obegin) {
+      typedef typename std::remove_reference<decltype(**Obegin)>::type ItemT;
+      ASTImporter &ImporterRef = Importer;
       bool Failed = false;
-      std::transform(B, E, ImportedElements.begin(),
-                     [&_Importer, &Failed](T *Element) -> T* {
-                       T *ToElement = _Importer.Import(Element);
-                       if (Element && !ToElement)
+      std::transform(Ibegin, Iend, Obegin,
+                     [&ImporterRef, &Failed](ItemT *From) -> ItemT * {
+                       ItemT *To = ImporterRef.Import(From);
+                       if (!To && From)
                          Failed = true;
-                       return ToElement;
+                       return To;
                      });
-      
-      if (Failed)
-        return false;
-      
-      T **CopiedElements = new (Importer.getToContext()) T*[NumElements];
-      std::copy(ImportedElements.begin(), ImportedElements.end(), &CopiedElements[0]);
-      ToArray = llvm::ArrayRef<T*>(CopiedElements, NumElements);
-      
-      return true;
+      return Failed;
     }
   };
 }
+
 using namespace clang;
 
 //----------------------------------------------------------------------------
@@ -1791,6 +1815,28 @@ QualType ASTNodeImporter::VisitAutoType(
                                              /*IsDependent*/false);
 }
 
+QualType ASTNodeImporter::VisitInjectedClassNameType(
+    const InjectedClassNameType *T) {
+  CXXRecordDecl *D = cast_or_null<CXXRecordDecl>(Importer.Import(T->getDecl()));
+  if (!D)
+    return QualType();
+
+  QualType InjType = Importer.Import(T->getInjectedSpecializationType());
+  if (InjType.isNull())
+    return QualType();
+
+  // 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(D, InjType), 0);
+}
+
 QualType ASTNodeImporter::VisitRecordType(const RecordType *T) {
   RecordDecl *ToDecl
     = dyn_cast_or_null<RecordDecl>(Importer.Import(T->getDecl()));
@@ -1830,6 +1876,18 @@ QualType ASTNodeImporter::VisitAttribute
     ToModifiedType, ToEquivalentType);
 }
 
+
+QualType ASTNodeImporter::VisitTemplateTypeParmType(
+    const TemplateTypeParmType *T) {
+  TemplateTypeParmDecl *ParmDecl =
+      cast_or_null<TemplateTypeParmDecl>(Importer.Import(T->getDecl()));
+  if (!ParmDecl && T->getDecl())
+    return QualType();
+
+  return Importer.getToContext().getTemplateTypeParmType(
+        T->getDepth(), T->getIndex(), T->isParameterPack(), ParmDecl);
+}
+
 QualType ASTNodeImporter::VisitTemplateSpecializationType(
                                        const TemplateSpecializationType *T) {
   TemplateName ToTemplate = Importer.Import(T->getTemplateName());
@@ -2525,6 +2583,39 @@ Decl *ASTNodeImporter::VisitTypeAliasDec
   return VisitTypedefNameDecl(D, /*IsAlias=*/true);
 }
 
+Decl *ASTNodeImporter::VisitLabelDecl(LabelDecl *D) {
+  // Import the major distinguishing characteristics of this label.
+  DeclContext *DC, *LexicalDC;
+  DeclarationName Name;
+  SourceLocation Loc;
+  NamedDecl *ToD;
+  if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
+    return nullptr;
+  if (ToD)
+    return ToD;
+
+  assert(LexicalDC->isFunctionOrMethod());
+
+  LabelDecl *ToLabel = D->isGnuLocal()
+      ? LabelDecl::Create(Importer.getToContext(),
+                          DC, Importer.Import(D->getLocation()),
+                          Name.getAsIdentifierInfo(),
+                          Importer.Import(D->getLocStart()))
+      : LabelDecl::Create(Importer.getToContext(),
+                          DC, Importer.Import(D->getLocation()),
+                          Name.getAsIdentifierInfo());
+  Importer.Imported(D, ToLabel);
+
+  LabelStmt *Label = cast_or_null<LabelStmt>(Importer.Import(D->getStmt()));
+  if (!Label)
+    return nullptr;
+
+  ToLabel->setStmt(Label);
+  ToLabel->setLexicalDeclContext(LexicalDC);
+  LexicalDC->addDeclInternal(ToLabel);
+  return ToLabel;
+}
+
 Decl *ASTNodeImporter::VisitEnumDecl(EnumDecl *D) {
   // Import the major distinguishing characteristics of this enum.
   DeclContext *DC, *LexicalDC;
@@ -4328,16 +4419,16 @@ Decl *ASTNodeImporter::VisitClassTemplat
   CXXRecordDecl *DTemplated = D->getTemplatedDecl();
   
   // Create the declaration that is being templated.
-  SourceLocation StartLoc = Importer.Import(DTemplated->getLocStart());
-  SourceLocation IdLoc = Importer.Import(DTemplated->getLocation());
-  CXXRecordDecl *D2Templated = CXXRecordDecl::Create(Importer.getToContext(),
-                                                     DTemplated->getTagKind(),
-                                                     DC, StartLoc, IdLoc,
-                                                   Name.getAsIdentifierInfo());
-  D2Templated->setAccess(DTemplated->getAccess());
-  D2Templated->setQualifierInfo(Importer.Import(DTemplated->getQualifierLoc()));
-  D2Templated->setLexicalDeclContext(LexicalDC);
-  
+  // Create the declaration that is being templated.
+  CXXRecordDecl *D2Templated = cast_or_null<CXXRecordDecl>(
+        Importer.Import(DTemplated));
+  if (!D2Templated)
+    return nullptr;
+
+  // Resolve possible cyclic import.
+  if (Decl *AlreadyImported = Importer.GetAlreadyImportedOrNull(D))
+    return AlreadyImported;
+
   // Create the class template declaration itself.
   TemplateParameterList *TemplateParams
     = ImportTemplateParameterList(D->getTemplateParameters());
@@ -4681,7 +4772,78 @@ DeclGroupRef ASTNodeImporter::ImportDecl
      << S->getStmtClassName();
    return nullptr;
  }
- 
+
+
+Stmt *ASTNodeImporter::VisitGCCAsmStmt(GCCAsmStmt *S) {
+  SmallVector<IdentifierInfo *, 4> Names;
+  for (unsigned I = 0, E = S->getNumOutputs(); I != E; I++) {
+    IdentifierInfo *ToII = Importer.Import(S->getOutputIdentifier(I));
+    if (!ToII)
+      return nullptr;
+    Names.push_back(ToII);
+  }
+  for (unsigned I = 0, E = S->getNumInputs(); I != E; I++) {
+    IdentifierInfo *ToII = Importer.Import(S->getInputIdentifier(I));
+    if (!ToII)
+      return nullptr;
+    Names.push_back(ToII);
+  }
+
+  SmallVector<StringLiteral *, 4> Clobbers;
+  for (unsigned I = 0, E = S->getNumClobbers(); I != E; I++) {
+    StringLiteral *Clobber = cast_or_null<StringLiteral>(
+          Importer.Import(S->getClobberStringLiteral(I)));
+    if (!Clobber)
+      return nullptr;
+    Clobbers.push_back(Clobber);
+  }
+
+  SmallVector<StringLiteral *, 4> Constraints;
+  for (unsigned I = 0, E = S->getNumOutputs(); I != E; I++) {
+    StringLiteral *Output = cast_or_null<StringLiteral>(
+          Importer.Import(S->getOutputConstraintLiteral(I)));
+    if (!Output)
+      return nullptr;
+    Constraints.push_back(Output);
+  }
+
+  for (unsigned I = 0, E = S->getNumInputs(); I != E; I++) {
+    StringLiteral *Input = cast_or_null<StringLiteral>(
+          Importer.Import(S->getInputConstraintLiteral(I)));
+    if (!Input)
+      return nullptr;
+    Constraints.push_back(Input);
+  }
+
+  SmallVector<Expr *, 4> Exprs(S->getNumOutputs() + S->getNumInputs());
+  if (ImportArrayChecked(S->begin_outputs(), S->end_outputs(), Exprs.begin()))
+    return nullptr;
+
+  if (ImportArrayChecked(S->begin_inputs(), S->end_inputs(),
+                         Exprs.begin() + S->getNumOutputs()))
+    return nullptr;
+
+  StringLiteral *AsmStr = cast_or_null<StringLiteral>(
+        Importer.Import(S->getAsmString()));
+  if (!AsmStr)
+    return nullptr;
+
+  return new (Importer.getToContext()) GCCAsmStmt(
+        Importer.getToContext(),
+        Importer.Import(S->getAsmLoc()),
+        S->isSimple(),
+        S->isVolatile(),
+        S->getNumOutputs(),
+        S->getNumInputs(),
+        Names.data(),
+        Constraints.data(),
+        Exprs.data(),
+        AsmStr,
+        S->getNumClobbers(),
+        Clobbers.data(),
+        Importer.Import(S->getRParenLoc()));
+}
+
 Stmt *ASTNodeImporter::VisitDeclStmt(DeclStmt *S) {
   DeclGroupRef ToDG = ImportDeclGroup(S->getDeclGroup());
   for (Decl *ToD : ToDG) {
@@ -4700,9 +4862,9 @@ Stmt *ASTNodeImporter::VisitNullStmt(Nul
 }
 
 Stmt *ASTNodeImporter::VisitCompoundStmt(CompoundStmt *S) {
-  llvm::ArrayRef<Stmt *> ToStmts;
+  llvm::SmallVector<Stmt *, 8> ToStmts(S->size());
     
-  if (!ImportArray(S->body_begin(), S->body_end(), ToStmts))
+  if (ImportArrayChecked(S->body_begin(), S->body_end(), ToStmts.begin()))
     return nullptr;
 
   SourceLocation ToLBraceLoc = Importer.Import(S->getLBracLoc());
@@ -5123,6 +5285,48 @@ Expr *ASTNodeImporter::VisitExpr(Expr *E
   return nullptr;
 }
 
+Expr *ASTNodeImporter::VisitVAArgExpr(VAArgExpr *E) {
+  QualType T = Importer.Import(E->getType());
+  if (T.isNull())
+    return nullptr;
+
+  Expr *SubExpr = Importer.Import(E->getSubExpr());
+  if (!SubExpr && E->getSubExpr())
+    return nullptr;
+
+  TypeSourceInfo *TInfo = Importer.Import(E->getWrittenTypeInfo());
+  if (!TInfo)
+    return nullptr;
+
+  return new (Importer.getToContext()) VAArgExpr(
+        Importer.Import(E->getBuiltinLoc()), SubExpr, TInfo,
+        Importer.Import(E->getRParenLoc()), T, E->isMicrosoftABI());
+}
+
+
+Expr *ASTNodeImporter::VisitGNUNullExpr(GNUNullExpr *E) {
+  QualType T = Importer.Import(E->getType());
+  if (T.isNull())
+    return nullptr;
+
+  return new (Importer.getToContext()) GNUNullExpr(
+        T, Importer.Import(E->getExprLoc()));
+}
+
+Expr *ASTNodeImporter::VisitPredefinedExpr(PredefinedExpr *E) {
+  QualType T = Importer.Import(E->getType());
+  if (T.isNull())
+    return nullptr;
+
+  StringLiteral *SL = cast_or_null<StringLiteral>(
+        Importer.Import(E->getFunctionName()));
+  if (!SL && E->getFunctionName())
+    return nullptr;
+
+  return new (Importer.getToContext()) PredefinedExpr(
+        Importer.Import(E->getExprLoc()), T, E->getIdentType(), SL);
+}
+
 Expr *ASTNodeImporter::VisitDeclRefExpr(DeclRefExpr *E) {
   ValueDecl *ToD = cast_or_null<ValueDecl>(Importer.Import(E->getDecl()));
   if (!ToD)
@@ -5153,6 +5357,76 @@ Expr *ASTNodeImporter::VisitDeclRefExpr(
   return DRE;
 }
 
+Expr *ASTNodeImporter::VisitImplicitValueInitExpr(ImplicitValueInitExpr *E) {
+  QualType T = Importer.Import(E->getType());
+  if (T.isNull())
+    return NULL;
+
+  return new (Importer.getToContext()) ImplicitValueInitExpr(T);
+}
+
+ASTNodeImporter::Designator
+ASTNodeImporter::ImportDesignator(const Designator &D) {
+  if (D.isFieldDesignator()) {
+    IdentifierInfo *ToFieldName = Importer.Import(D.getFieldName());
+    // Caller checks for import error
+    return Designator(ToFieldName, Importer.Import(D.getDotLoc()),
+                      Importer.Import(D.getFieldLoc()));
+  }
+  if (D.isArrayDesignator())
+    return Designator(D.getFirstExprIndex(),
+                      Importer.Import(D.getLBracketLoc()),
+                      Importer.Import(D.getRBracketLoc()));
+
+  assert(D.isArrayRangeDesignator());
+  return Designator(D.getFirstExprIndex(),
+                    Importer.Import(D.getLBracketLoc()),
+                    Importer.Import(D.getEllipsisLoc()),
+                    Importer.Import(D.getRBracketLoc()));
+}
+
+
+Expr *ASTNodeImporter::VisitDesignatedInitExpr(DesignatedInitExpr *DIE) {
+  Expr *Init = cast_or_null<Expr>(Importer.Import(DIE->getInit()));
+  if (!Init)
+    return nullptr;
+
+  SmallVector<Expr *, 4> IndexExprs(DIE->getNumSubExprs() - 1);
+  // List elements from the second, the first is Init itself
+  for (unsigned I = 1, E = DIE->getNumSubExprs(); I < E; I++) {
+    if (Expr *Arg = cast_or_null<Expr>(Importer.Import(DIE->getSubExpr(I))))
+      IndexExprs[I - 1] = Arg;
+    else
+      return nullptr;
+  }
+
+  SmallVector<Designator, 4> Designators(DIE->size());
+  std::transform(DIE->designators_begin(), DIE->designators_end(),
+                 Designators.begin(),
+    [this](const Designator &D) -> Designator {
+      return ImportDesignator(D);
+    });
+
+  for (auto I = DIE->designators_begin(), E = DIE->designators_end(); I != E;
+       ++I)
+    if (I->isFieldDesignator() && !I->getFieldName())
+      return nullptr;
+
+  return DesignatedInitExpr::Create(
+        Importer.getToContext(), Designators.data(), Designators.size(),
+        IndexExprs, Importer.Import(DIE->getEqualOrColonLoc()),
+        DIE->usesGNUSyntax(), Init);
+}
+
+Expr *ASTNodeImporter::VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *E) {
+  QualType T = Importer.Import(E->getType());
+  if (T.isNull())
+    return nullptr;
+
+  return new (Importer.getToContext())
+      CXXNullPtrLiteralExpr(T, Importer.Import(E->getLocation()));
+}
+
 Expr *ASTNodeImporter::VisitIntegerLiteral(IntegerLiteral *E) {
   QualType T = Importer.Import(E->getType());
   if (T.isNull())
@@ -5163,6 +5437,16 @@ Expr *ASTNodeImporter::VisitIntegerLiter
                                 Importer.Import(E->getLocation()));
 }
 
+Expr *ASTNodeImporter::VisitFloatingLiteral(FloatingLiteral *E) {
+  QualType T = Importer.Import(E->getType());
+  if (T.isNull())
+    return nullptr;
+
+  return FloatingLiteral::Create(Importer.getToContext(),
+                                E->getValue(), E->isExact(), T,
+                                Importer.Import(E->getLocation()));
+}
+
 Expr *ASTNodeImporter::VisitCharacterLiteral(CharacterLiteral *E) {
   QualType T = Importer.Import(E->getType());
   if (T.isNull())
@@ -5173,6 +5457,67 @@ Expr *ASTNodeImporter::VisitCharacterLit
                                           Importer.Import(E->getLocation()));
 }
 
+Expr *ASTNodeImporter::VisitStringLiteral(StringLiteral *E) {
+  QualType T = Importer.Import(E->getType());
+  if (T.isNull())
+    return nullptr;
+
+  SmallVector<SourceLocation, 4> Locations(E->getNumConcatenated());
+  ImportArray(E->tokloc_begin(), E->tokloc_end(), Locations.begin());
+
+  return StringLiteral::Create(Importer.getToContext(), E->getBytes(),
+                               E->getKind(), E->isPascal(), T,
+                               Locations.data(), Locations.size());
+}
+
+Expr *ASTNodeImporter::VisitCompoundLiteralExpr(CompoundLiteralExpr *E) {
+  QualType T = Importer.Import(E->getType());
+  if (T.isNull())
+    return nullptr;
+
+  TypeSourceInfo *TInfo = Importer.Import(E->getTypeSourceInfo());
+  if (!TInfo)
+    return nullptr;
+
+  Expr *Init = Importer.Import(E->getInitializer());
+  if (!Init)
+    return nullptr;
+
+  return new (Importer.getToContext()) CompoundLiteralExpr(
+        Importer.Import(E->getLParenLoc()), TInfo, T, E->getValueKind(),
+        Init, E->isFileScope());
+}
+
+Expr *ASTNodeImporter::VisitAtomicExpr(AtomicExpr *E) {
+  QualType T = Importer.Import(E->getType());
+  if (T.isNull())
+    return nullptr;
+
+  SmallVector<Expr *, 6> Exprs(E->getNumSubExprs());
+  if (ImportArrayChecked(
+        E->getSubExprs(), E->getSubExprs() + E->getNumSubExprs(),
+        Exprs.begin()))
+    return nullptr;
+
+  return new (Importer.getToContext()) AtomicExpr(
+        Importer.Import(E->getBuiltinLoc()), Exprs, T, E->getOp(),
+        Importer.Import(E->getRParenLoc()));
+}
+
+Expr *ASTNodeImporter::VisitAddrLabelExpr(AddrLabelExpr *E) {
+  QualType T = Importer.Import(E->getType());
+  if (T.isNull())
+    return nullptr;
+
+  LabelDecl *ToLabel = cast_or_null<LabelDecl>(Importer.Import(E->getLabel()));
+  if (!ToLabel)
+    return nullptr;
+
+  return new (Importer.getToContext()) AddrLabelExpr(
+        Importer.Import(E->getAmpAmpLoc()), Importer.Import(E->getLabelLoc()),
+        ToLabel, T);
+}
+
 Expr *ASTNodeImporter::VisitParenExpr(ParenExpr *E) {
   Expr *SubExpr = Importer.Import(E->getSubExpr());
   if (!SubExpr)
@@ -5184,6 +5529,31 @@ Expr *ASTNodeImporter::VisitParenExpr(Pa
                                             SubExpr);
 }
 
+Expr *ASTNodeImporter::VisitParenListExpr(ParenListExpr *E) {
+  SmallVector<Expr *, 4> Exprs(E->getNumExprs());
+  if (ImportArrayChecked(
+        E->getExprs(), E->getExprs() + E->getNumExprs(), Exprs.begin()))
+    return nullptr;
+
+  return new (Importer.getToContext()) ParenListExpr(
+        Importer.getToContext(), Importer.Import(E->getLParenLoc()),
+        Exprs, Importer.Import(E->getLParenLoc()));
+}
+
+Expr *ASTNodeImporter::VisitStmtExpr(StmtExpr *E) {
+  QualType T = Importer.Import(E->getType());
+  if (T.isNull())
+    return nullptr;
+
+  CompoundStmt *ToSubStmt = cast_or_null<CompoundStmt>(
+        Importer.Import(E->getSubStmt()));
+  if (!ToSubStmt && E->getSubStmt())
+    return nullptr;
+
+  return new (Importer.getToContext()) StmtExpr(ToSubStmt, T,
+        Importer.Import(E->getLParenLoc()), Importer.Import(E->getRParenLoc()));
+}
+
 Expr *ASTNodeImporter::VisitUnaryOperator(UnaryOperator *E) {
   QualType T = Importer.Import(E->getType());
   if (T.isNull())
@@ -5244,6 +5614,76 @@ Expr *ASTNodeImporter::VisitBinaryOperat
                                                       E->isFPContractable());
 }
 
+Expr *ASTNodeImporter::VisitConditionalOperator(ConditionalOperator *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;
+
+  Expr *ToCond = Importer.Import(E->getCond());
+  if (!ToCond)
+    return nullptr;
+
+  return new (Importer.getToContext()) ConditionalOperator(
+        ToCond, Importer.Import(E->getQuestionLoc()),
+        ToLHS, Importer.Import(E->getColonLoc()),
+        ToRHS, T, E->getValueKind(), E->getObjectKind());
+}
+
+Expr *ASTNodeImporter::VisitBinaryConditionalOperator(
+    BinaryConditionalOperator *E) {
+  QualType T = Importer.Import(E->getType());
+  if (T.isNull())
+    return nullptr;
+
+  Expr *Common = Importer.Import(E->getCommon());
+  if (!Common)
+    return nullptr;
+
+  Expr *Cond = Importer.Import(E->getCond());
+  if (!Cond)
+    return nullptr;
+
+  OpaqueValueExpr *OpaqueValue = cast_or_null<OpaqueValueExpr>(
+        Importer.Import(E->getOpaqueValue()));
+  if (!OpaqueValue)
+    return nullptr;
+
+  Expr *TrueExpr = Importer.Import(E->getTrueExpr());
+  if (!TrueExpr)
+    return nullptr;
+
+  Expr *FalseExpr = Importer.Import(E->getFalseExpr());
+  if (!FalseExpr)
+    return nullptr;
+
+  return new (Importer.getToContext()) BinaryConditionalOperator(
+        Common, OpaqueValue, Cond, TrueExpr, FalseExpr,
+        Importer.Import(E->getQuestionLoc()), Importer.Import(E->getColonLoc()),
+        T, E->getValueKind(), E->getObjectKind());
+}
+
+Expr *ASTNodeImporter::VisitOpaqueValueExpr(OpaqueValueExpr *E) {
+  QualType T = Importer.Import(E->getType());
+  if (T.isNull())
+    return nullptr;
+
+  Expr *SourceExpr = Importer.Import(E->getSourceExpr());
+  if (!SourceExpr && E->getSourceExpr())
+    return nullptr;
+
+  return new (Importer.getToContext()) OpaqueValueExpr(
+        Importer.Import(E->getExprLoc()), T, E->getValueKind(),
+        E->getObjectKind(), SourceExpr);
+}
+
 Expr *ASTNodeImporter::VisitCompoundAssignOperator(CompoundAssignOperator *E) {
   QualType T = Importer.Import(E->getType());
   if (T.isNull())
@@ -5332,9 +5772,9 @@ Expr *ASTNodeImporter::VisitCXXConstruct
   if (!ToCCD && E->getConstructor())
     return nullptr;
 
-  ArrayRef<Expr *> ToArgs;
-  
-  if (!ImportArray(E->arg_begin(), E->arg_end(), ToArgs))
+  SmallVector<Expr *, 6> ToArgs(E->getNumArgs());
+  if (ImportArrayChecked(E->getArgs(), E->getArgs() + E->getNumArgs(),
+                         ToArgs.begin()))
     return nullptr;
 
   return CXXConstructExpr::Create(Importer.getToContext(), T,
@@ -5357,14 +5797,14 @@ Expr *ASTNodeImporter::VisitCXXMemberCal
   if (!ToFn)
     return nullptr;
   
-  ArrayRef<Expr *> ToArgs;
+  SmallVector<Expr *, 4> ToArgs(E->getNumArgs());
   
-  if (!ImportArray(E->arg_begin(), E->arg_end(), ToArgs))
+  if (ImportArrayChecked(E->arg_begin(), E->arg_end(), ToArgs.begin()))
     return nullptr;
 
-  return new (Importer.getToContext()) CXXMemberCallExpr(Importer.getToContext(), ToFn,
-                                                         ToArgs, T, E->getValueKind(),
-                                                         Importer.Import(E->getRParenLoc()));
+  return new (Importer.getToContext()) CXXMemberCallExpr(
+        Importer.getToContext(), ToFn, ToArgs, T, E->getValueKind(),
+        Importer.Import(E->getRParenLoc()));
 }
 
 Expr *ASTNodeImporter::VisitCXXThisExpr(CXXThisExpr *E) {
@@ -5454,26 +5894,49 @@ Expr *ASTNodeImporter::VisitCallExpr(Cal
              Importer.Import(E->getRParenLoc()));
 }
 
-Expr *ASTNodeImporter::VisitInitListExpr(InitListExpr *E) {
-  QualType T = Importer.Import(E->getType());
+Expr *ASTNodeImporter::VisitInitListExpr(InitListExpr *ILE) {
+  QualType T = Importer.Import(ILE->getType());
   if (T.isNull())
     return nullptr;
-    
-  ArrayRef<Expr *> ToInits;
 
-  if (!ImportArray(E->inits().begin(), E->inits().end(), ToInits))
+  llvm::SmallVector<Expr *, 4> Exprs(ILE->getNumInits());
+  if (ImportArrayChecked(
+        ILE->getInits(), ILE->getInits() + ILE->getNumInits(), Exprs.begin()))
     return nullptr;
-    
-  InitListExpr *ToE = new (Importer.getToContext())
-    InitListExpr(Importer.getToContext(),
-                 Importer.Import(E->getLBraceLoc()),
-                 ToInits,
-                 Importer.Import(E->getRBraceLoc()));
-  
-  if (ToE)
-    ToE->setType(T);
 
-  return ToE;
+  ASTContext &ToCtx = Importer.getToContext();
+  InitListExpr *To = new (ToCtx) InitListExpr(
+        ToCtx, Importer.Import(ILE->getLBraceLoc()),
+        Exprs, Importer.Import(ILE->getLBraceLoc()));
+  To->setType(T);
+
+  if (ILE->hasArrayFiller()) {
+    Expr *Filler = Importer.Import(ILE->getArrayFiller());
+    if (!Filler)
+      return nullptr;
+    To->setArrayFiller(Filler);
+  }
+
+  if (FieldDecl *FromFD = ILE->getInitializedFieldInUnion()) {
+    FieldDecl *ToFD = cast_or_null<FieldDecl>(Importer.Import(FromFD));
+    if (!ToFD)
+      return nullptr;
+    To->setInitializedFieldInUnion(ToFD);
+  }
+
+  if (InitListExpr *SyntForm = ILE->getSyntacticForm()) {
+    InitListExpr *ToSyntForm = cast_or_null<InitListExpr>(
+          Importer.Import(SyntForm));
+    if (!ToSyntForm)
+      return nullptr;
+    To->setSyntacticForm(ToSyntForm);
+  }
+
+  To->sawArrayRangeDesignator(ILE->hadArrayRangeDesignator());
+  To->setValueDependent(ILE->isValueDependent());
+  To->setInstantiationDependent(ILE->isInstantiationDependent());
+
+  return To;
 }
 
 ASTImporter::ASTImporter(ASTContext &ToContext, FileManager &ToFileManager,

Added: cfe/trunk/unittests/AST/ASTImporterTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/AST/ASTImporterTest.cpp?rev=266292&view=auto
==============================================================================
--- cfe/trunk/unittests/AST/ASTImporterTest.cpp (added)
+++ cfe/trunk/unittests/AST/ASTImporterTest.cpp Thu Apr 14 06:51:27 2016
@@ -0,0 +1,470 @@
+//===- unittest/AST/ASTImporterTest.cpp - AST node import test ------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Tests for the correct import of AST nodes from one AST context to another.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/ASTImporter.h"
+#include "MatchVerifier.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Tooling/Tooling.h"
+#include "gtest/gtest.h"
+
+namespace clang {
+namespace ast_matchers {
+
+using clang::tooling::newFrontendActionFactory;
+using clang::tooling::runToolOnCodeWithArgs;
+using clang::tooling::FrontendActionFactory;
+
+typedef std::vector<std::string> StringVector;
+
+void getLangArgs(Language Lang, StringVector &Args) {
+  switch (Lang) {
+  case Lang_C:
+    Args.insert(Args.end(), { "-x", "c", "-std=c99" });
+    break;
+  case Lang_C89:
+    Args.insert(Args.end(), { "-x", "c", "-std=c89" });
+    break;
+  case Lang_CXX:
+    Args.push_back("-std=c++98");
+    break;
+  case Lang_CXX11:
+    Args.push_back("-std=c++11");
+    break;
+  case Lang_OpenCL:
+  case Lang_OBJCXX:
+    break;
+  }
+}
+
+template<typename NodeType, typename MatcherType>
+testing::AssertionResult
+testImport(const std::string &FromCode, Language FromLang,
+           const std::string &ToCode, Language ToLang,
+           MatchVerifier<NodeType> &Verifier,
+           const MatcherType &AMatcher) {
+  StringVector FromArgs, ToArgs;
+  getLangArgs(FromLang, FromArgs);
+  getLangArgs(ToLang, ToArgs);
+
+  const char *const InputFileName = "input.cc";
+  const char *const OutputFileName = "output.cc";
+
+  std::unique_ptr<ASTUnit>
+      FromAST = tooling::buildASTFromCodeWithArgs(
+        FromCode, FromArgs, InputFileName),
+      ToAST = tooling::buildASTFromCodeWithArgs(ToCode, ToArgs, OutputFileName);
+
+  ASTContext &FromCtx = FromAST->getASTContext(),
+      &ToCtx = ToAST->getASTContext();
+
+  // Add input.cc to virtual file system so importer can 'find' it
+  // while importing SourceLocations.
+  vfs::OverlayFileSystem *OFS = static_cast<vfs::OverlayFileSystem *>(
+        ToCtx.getSourceManager().getFileManager().getVirtualFileSystem().get());
+  vfs::InMemoryFileSystem *MFS = static_cast<vfs::InMemoryFileSystem *>(
+        OFS->overlays_begin()->get());
+  MFS->addFile(InputFileName, 0,
+               llvm::MemoryBuffer::getMemBuffer(FromCode.c_str()));
+
+  ASTImporter Importer(ToCtx, ToAST->getFileManager(),
+                       FromCtx, FromAST->getFileManager(), false);
+
+  IdentifierInfo *ImportedII = &FromCtx.Idents.get("declToImport");
+  assert(ImportedII && "Declaration with 'declToImport' name"
+                       "should be specified in test!");
+  DeclarationName ImportDeclName(ImportedII);
+  SmallVector<NamedDecl *, 4> FoundDecls;
+  FromCtx.getTranslationUnitDecl()->localUncachedLookup(
+        ImportDeclName, FoundDecls);
+
+  if (FoundDecls.size() != 1)
+    return testing::AssertionFailure() << "Multiple declarations were found!";
+
+  auto Imported = Importer.Import(*FoundDecls.begin());
+  if (!Imported)
+    return testing::AssertionFailure() << "Import failed, nullptr returned!";
+
+  // This should dump source locations and assert if some source locations
+  // were not imported
+  SmallString<1024> ImportChecker;
+  llvm::raw_svector_ostream ToNothing(ImportChecker);
+  ToCtx.getTranslationUnitDecl()->print(ToNothing);
+
+  return Verifier.match(Imported, AMatcher);
+}
+
+TEST(ImportExpr, ImportStringLiteral) {
+  MatchVerifier<Decl> Verifier;
+  EXPECT_TRUE(testImport("void declToImport() { \"foo\"; }",
+                         Lang_CXX, "", Lang_CXX, Verifier,
+                         functionDecl(
+                           hasBody(
+                             compoundStmt(
+                               has(
+                                 stringLiteral(
+                                   hasType(
+                                     asString("const char [4]")))))))));
+  EXPECT_TRUE(testImport("void declToImport() { L\"foo\"; }",
+                         Lang_CXX, "", Lang_CXX, Verifier,
+                         functionDecl(
+                           hasBody(
+                             compoundStmt(
+                               has(
+                                 stringLiteral(
+                                   hasType(
+                                     asString("const wchar_t [4]")))))))));
+  EXPECT_TRUE(testImport("void declToImport() { \"foo\" \"bar\"; }",
+                         Lang_CXX, "", Lang_CXX, Verifier,
+                         functionDecl(
+                           hasBody(
+                             compoundStmt(
+                               has(
+                                 stringLiteral(
+                                   hasType(
+                                     asString("const char [7]")))))))));
+}
+
+TEST(ImportExpr, ImportGNUNullExpr) {
+  MatchVerifier<Decl> Verifier;
+  EXPECT_TRUE(testImport("void declToImport() { __null; }",
+                         Lang_CXX, "", Lang_CXX, Verifier,
+                         functionDecl(
+                           hasBody(
+                             compoundStmt(
+                               has(
+                                 gnuNullExpr(
+                                   hasType(isInteger()))))))));
+}
+
+TEST(ImportExpr, ImportCXXNullPtrLiteralExpr) {
+  MatchVerifier<Decl> Verifier;
+  EXPECT_TRUE(testImport("void declToImport() { nullptr; }",
+                         Lang_CXX11, "", Lang_CXX11, Verifier,
+                         functionDecl(
+                           hasBody(
+                             compoundStmt(
+                               has(
+                                 cxxNullPtrLiteralExpr()))))));
+}
+
+
+TEST(ImportExpr, ImportFloatinglLiteralExpr) {
+  MatchVerifier<Decl> Verifier;
+  EXPECT_TRUE(testImport("void declToImport() { 1.0; }",
+                         Lang_CXX, "", Lang_CXX, Verifier,
+                         functionDecl(
+                           hasBody(
+                             compoundStmt(
+                               has(
+                                 floatLiteral(
+                                   equals(1.0),
+                                   hasType(asString("double")))))))));
+  EXPECT_TRUE(testImport("void declToImport() { 1.0e-5f; }",
+                         Lang_CXX, "", Lang_CXX, Verifier,
+                         functionDecl(
+                           hasBody(
+                             compoundStmt(
+                               has(
+                                 floatLiteral(
+                                   equals(1.0e-5f),
+                                   hasType(asString("float")))))))));
+}
+
+TEST(ImportExpr, ImportCompoundLiteralExpr) {
+  MatchVerifier<Decl> Verifier;
+  EXPECT_TRUE(
+        testImport(
+          "void declToImport() {"
+          "  struct s { int x; long y; unsigned z; }; "
+          "  (struct s){ 42, 0L, 1U }; }",
+          Lang_CXX, "", Lang_CXX, Verifier,
+          functionDecl(
+            hasBody(
+              compoundStmt(
+                has(
+                  compoundLiteralExpr(
+                    hasType(asString("struct s")),
+                    has(initListExpr(
+                      hasType(asString("struct s")),
+                      has(integerLiteral(
+                            equals(42), hasType(asString("int")))),
+                      has(integerLiteral(
+                            equals(0), hasType(asString("long")))),
+                      has(integerLiteral(
+                            equals(1),
+                            hasType(asString("unsigned int"))))
+                      )))))))));
+}
+
+TEST(ImportExpr, ImportCXXThisExpr) {
+  MatchVerifier<Decl> Verifier;
+  EXPECT_TRUE(
+        testImport("class declToImport { void f() { this; } };",
+                   Lang_CXX, "", Lang_CXX, Verifier,
+                   cxxRecordDecl(
+                     hasMethod(
+                       hasBody(
+                         compoundStmt(
+                           has(
+                             cxxThisExpr(
+                               hasType(
+                                 asString("class declToImport *"))))))))));
+}
+
+TEST(ImportExpr, ImportAtomicExpr) {
+  MatchVerifier<Decl> Verifier;
+  EXPECT_TRUE(
+        testImport(
+          "void declToImport() { int *ptr; __atomic_load_n(ptr, 1); }",
+          Lang_CXX, "", Lang_CXX, Verifier,
+          functionDecl(
+            hasBody(
+              compoundStmt(
+                has(
+                  atomicExpr(
+                    has(declRefExpr(
+                          hasDeclaration(varDecl(hasName("ptr"))),
+                          hasType(asString("int *")))),
+                    has(integerLiteral(equals(1), hasType(asString("int"))))
+                    )))))));
+}
+
+TEST(ImportExpr, ImportLabelDeclAndAddrLabelExpr) {
+  MatchVerifier<Decl> Verifier;
+  EXPECT_TRUE(
+        testImport(
+          "void declToImport() { loop: goto loop; &&loop; }",
+          Lang_CXX, "", Lang_CXX, Verifier,
+          functionDecl(
+            hasBody(
+              compoundStmt(
+                has(labelStmt(hasDeclaration(labelDecl(hasName("loop"))))),
+                has(addrLabelExpr(hasDeclaration(labelDecl(hasName("loop")))))
+                )))));
+}
+
+AST_MATCHER_P(TemplateDecl, hasTemplateDecl,
+              internal::Matcher<NamedDecl>, InnerMatcher) {
+  const NamedDecl *Template = Node.getTemplatedDecl();
+  return Template && InnerMatcher.matches(*Template, Finder, Builder);
+}
+
+TEST(ImportExpr, ImportParenListExpr) {
+  MatchVerifier<Decl> Verifier;
+  EXPECT_TRUE(
+        testImport(
+          "template<typename T> class dummy { void f() { dummy X(*this); } };"
+          "typedef dummy<int> declToImport;"
+          "template class dummy<int>;",
+          Lang_CXX, "", Lang_CXX, Verifier,
+          typedefDecl(
+            hasType(
+              templateSpecializationType(
+                hasDeclaration(
+                  classTemplateDecl(
+                    hasTemplateDecl(
+                      cxxRecordDecl(
+                        hasMethod(
+                        allOf(
+                          hasName("f"),
+                          hasBody(
+                            compoundStmt(
+                              has(
+                                declStmt(
+                                  hasSingleDecl(
+                                    varDecl(
+                                      hasInitializer(
+                                        parenListExpr(
+                                          has(
+                                            unaryOperator(
+                                              hasOperatorName("*"),
+                                              hasUnaryOperand(cxxThisExpr())
+                                              )))))))))))))))))))));
+}
+
+TEST(ImportExpr, ImportStmtExpr) {
+  MatchVerifier<Decl> Verifier;
+  // NOTE: has() ignores implicit casts, using hasDescendant() to match it
+  EXPECT_TRUE(
+        testImport(
+          "void declToImport() { int b; int a = b ?: 1; int C = ({int X=4; X;}); }",
+          Lang_CXX, "", Lang_CXX, Verifier,
+          functionDecl(
+            hasBody(
+              compoundStmt(
+                has(
+                  declStmt(
+                    hasSingleDecl(
+                      varDecl(
+                        hasName("C"),
+                        hasType(asString("int")),
+                        hasInitializer(
+                          stmtExpr(
+                            hasAnySubstatement(
+                              declStmt(
+                                hasSingleDecl(
+                                  varDecl(
+                                    hasName("X"),
+                                    hasType(asString("int")),
+                                    hasInitializer(
+                                      integerLiteral(equals(4))))))),
+                            hasDescendant(
+                              implicitCastExpr()
+                              ))))))))))));
+}
+
+TEST(ImportExpr, ImportConditionalOperator) {
+  MatchVerifier<Decl> Verifier;
+  EXPECT_TRUE(
+        testImport(
+          "void declToImport() { true ? 1 : -5; }",
+          Lang_CXX, "", Lang_CXX, Verifier,
+          functionDecl(
+            hasBody(
+              compoundStmt(
+                has(
+                  conditionalOperator(
+                    hasCondition(cxxBoolLiteral(equals(true))),
+                    hasTrueExpression(integerLiteral(equals(1))),
+                    hasFalseExpression(
+                      unaryOperator(hasUnaryOperand(integerLiteral(equals(5))))
+                      ))))))));
+}
+
+TEST(ImportExpr, ImportBinaryConditionalOperator) {
+  MatchVerifier<Decl> Verifier;
+  EXPECT_TRUE(
+        testImport(
+          "void declToImport() { 1 ?: -5; }",
+          Lang_CXX, "", Lang_CXX, Verifier,
+          functionDecl(
+            hasBody(
+              compoundStmt(
+                has(
+                  binaryConditionalOperator(
+                    hasCondition(
+                      implicitCastExpr(
+                        hasSourceExpression(
+                          opaqueValueExpr(
+                            hasSourceExpression(integerLiteral(equals(1))))),
+                        hasType(booleanType()))),
+                    hasTrueExpression(
+                      opaqueValueExpr(hasSourceExpression(
+                                        integerLiteral(equals(1))))),
+                    hasFalseExpression(
+                      unaryOperator(hasOperatorName("-"),
+                                    hasUnaryOperand(integerLiteral(equals(5)))))
+                      )))))));
+}
+
+TEST(ImportExpr, ImportDesignatedInitExpr) {
+  MatchVerifier<Decl> Verifier;
+  EXPECT_TRUE(testImport("void declToImport() {"
+                         "  struct point { double x; double y; };"
+                         "  struct point ptarray[10] = "
+                                "{ [2].y = 1.0, [2].x = 2.0, [0].x = 1.0 }; }",
+                         Lang_C, "", Lang_C, Verifier,
+                         functionDecl(
+                           hasBody(
+                             compoundStmt(
+                               has(
+                                 declStmt(
+                                   hasSingleDecl(
+                                     varDecl(
+                                       hasInitializer(
+                                         initListExpr(
+                                           hasSyntacticForm(
+                                             initListExpr(
+                                               has(
+                                                 designatedInitExpr(
+                                                   designatorCountIs(2),
+                                                   has(floatLiteral(
+                                                         equals(1.0))),
+                                                   has(integerLiteral(
+                                                         equals(2))))),
+                                               has(
+                                                 designatedInitExpr(
+                                                   designatorCountIs(2),
+                                                   has(floatLiteral(
+                                                         equals(2.0))),
+                                                   has(integerLiteral(
+                                                         equals(2))))),
+                                               has(
+                                                 designatedInitExpr(
+                                                   designatorCountIs(2),
+                                                   has(floatLiteral(
+                                                         equals(1.0))),
+                                                   has(integerLiteral(
+                                                         equals(0)))))
+                                               )))))))))))));
+}
+
+
+TEST(ImportExpr, ImportPredefinedExpr) {
+  MatchVerifier<Decl> Verifier;
+  // __func__ expands as StringLiteral("declToImport")
+  EXPECT_TRUE(testImport("void declToImport() { __func__; }",
+                         Lang_CXX, "", Lang_CXX, Verifier,
+                         functionDecl(
+                           hasBody(
+                             compoundStmt(
+                               has(
+                                 predefinedExpr(
+                                   hasType(
+                                     asString("const char [13]")),
+                                   has(
+                                     stringLiteral(
+                                       hasType(
+                                         asString("const char [13]")))))))))));
+}
+
+TEST(ImportExpr, ImportInitListExpr) {
+  MatchVerifier<Decl> Verifier;
+  EXPECT_TRUE(
+        testImport(
+          "void declToImport() {"
+          "  struct point { double x; double y; };"
+          "  point ptarray[10] = { [2].y = 1.0, [2].x = 2.0,"
+          "                        [0].x = 1.0 }; }",
+          Lang_CXX, "", Lang_CXX, Verifier,
+          functionDecl(
+            hasBody(
+              compoundStmt(
+                has(
+                  declStmt(
+                    hasSingleDecl(
+                      varDecl(
+                        hasInitializer(
+                          initListExpr(
+                            has(
+                              cxxConstructExpr(
+                                requiresZeroInitialization())),
+                            has(
+                              initListExpr(
+                                hasType(asString("struct point")),
+                                has(floatLiteral(equals(1.0))),
+                                has(implicitValueInitExpr(
+                                      hasType(asString("double")))))),
+                            has(
+                              initListExpr(
+                                hasType(asString("struct point")),
+                                has(floatLiteral(equals(2.0))),
+                                has(floatLiteral(equals(1.0)))))
+                              )))))))))));
+}
+
+
+} // end namespace ast_matchers
+} // end namespace clang

Modified: cfe/trunk/unittests/AST/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/AST/CMakeLists.txt?rev=266292&r1=266291&r2=266292&view=diff
==============================================================================
--- cfe/trunk/unittests/AST/CMakeLists.txt (original)
+++ cfe/trunk/unittests/AST/CMakeLists.txt Thu Apr 14 06:51:27 2016
@@ -4,6 +4,7 @@ set(LLVM_LINK_COMPONENTS
 
 add_clang_unittest(ASTTests
   ASTContextParentMapTest.cpp
+  ASTImporterTest.cpp
   ASTTypeTraitsTest.cpp
   ASTVectorTest.cpp
   CommentLexer.cpp




More information about the cfe-commits mailing list