Updated to Clang 3.5a.

Change-Id: I8127eb568f674c2e72635b639a3295381fe8af82
diff --git a/unittests/AST/ASTContextParentMapTest.cpp b/unittests/AST/ASTContextParentMapTest.cpp
index c1910a8..0dcb175 100644
--- a/unittests/AST/ASTContextParentMapTest.cpp
+++ b/unittests/AST/ASTContextParentMapTest.cpp
@@ -12,11 +12,11 @@
 //===----------------------------------------------------------------------===//
 
 #include "clang/AST/ASTContext.h"
+#include "MatchVerifier.h"
 #include "clang/ASTMatchers/ASTMatchFinder.h"
 #include "clang/ASTMatchers/ASTMatchers.h"
 #include "clang/Tooling/Tooling.h"
 #include "gtest/gtest.h"
-#include "MatchVerifier.h"
 
 namespace clang {
 namespace ast_matchers {
diff --git a/unittests/AST/ASTTypeTraitsTest.cpp b/unittests/AST/ASTTypeTraitsTest.cpp
index dd73b52..0e73f76 100644
--- a/unittests/AST/ASTTypeTraitsTest.cpp
+++ b/unittests/AST/ASTTypeTraitsTest.cpp
@@ -9,8 +9,8 @@
 
 
 #include "clang/AST/ASTTypeTraits.h"
-#include "gtest/gtest.h"
 #include "MatchVerifier.h"
+#include "gtest/gtest.h"
 
 using namespace clang::ast_matchers;
 
@@ -34,6 +34,19 @@
   EXPECT_TRUE(DNT<Decl>().isSame(DNT<Decl>()));
 }
 
+TEST(ASTNodeKind, BaseDistances) {
+  unsigned Distance = 1;
+  EXPECT_TRUE(DNT<Expr>().isBaseOf(DNT<Expr>(), &Distance));
+  EXPECT_EQ(0u, Distance);
+
+  EXPECT_TRUE(DNT<Stmt>().isBaseOf(DNT<IfStmt>(), &Distance));
+  EXPECT_EQ(1u, Distance);
+
+  Distance = 3;
+  EXPECT_TRUE(DNT<DeclaratorDecl>().isBaseOf(DNT<ParmVarDecl>(), &Distance));
+  EXPECT_EQ(2u, Distance);
+}
+
 TEST(ASTNodeKind, SameBase) {
   EXPECT_TRUE(DNT<Expr>().isBaseOf(DNT<CallExpr>()));
   EXPECT_TRUE(DNT<Expr>().isBaseOf(DNT<BinaryOperator>()));
diff --git a/unittests/AST/CMakeLists.txt b/unittests/AST/CMakeLists.txt
index 70f86d3..9a55626 100644
--- a/unittests/AST/CMakeLists.txt
+++ b/unittests/AST/CMakeLists.txt
@@ -1,3 +1,7 @@
+set(LLVM_LINK_COMPONENTS
+  Support
+  )
+
 add_clang_unittest(ASTTests
   ASTContextParentMapTest.cpp
   ASTTypeTraitsTest.cpp
@@ -6,10 +10,16 @@
   CommentParser.cpp
   DeclPrinterTest.cpp
   DeclTest.cpp
+  EvaluateAsRValueTest.cpp
+  ExternalASTSourceTest.cpp
   SourceLocationTest.cpp
   StmtPrinterTest.cpp
   )
 
 target_link_libraries(ASTTests
-  clangAST clangASTMatchers clangTooling
+  clangAST
+  clangASTMatchers
+  clangBasic
+  clangFrontend
+  clangTooling
   )
diff --git a/unittests/AST/CommentParser.cpp b/unittests/AST/CommentParser.cpp
index f75c636..c72aef1 100644
--- a/unittests/AST/CommentParser.cpp
+++ b/unittests/AST/CommentParser.cpp
@@ -1420,6 +1420,26 @@
   }
 }
 
+TEST_F(CommentParserTest, Deprecated) {
+  const char *Sources[] = {
+    "/** @deprecated*/",
+    "/// @deprecated\n"
+  };
+
+  for (size_t i = 0, e = array_lengthof(Sources); i != e; i++) {
+    FullComment *FC = parseString(Sources[i]);
+    ASSERT_TRUE(HasChildCount(FC, 2));
+
+    ASSERT_TRUE(HasParagraphCommentAt(FC, 0, " "));
+    {
+      BlockCommandComment *BCC;
+      ParagraphComment *PC;
+      ASSERT_TRUE(HasBlockCommandAt(FC, Traits, 1, BCC, "deprecated", PC));
+      ASSERT_TRUE(HasChildCount(PC, 0));
+    }
+  }
+}
+
 } // unnamed namespace
 
 } // end namespace comments
diff --git a/unittests/AST/DeclPrinterTest.cpp b/unittests/AST/DeclPrinterTest.cpp
index 44fa742..5340756 100644
--- a/unittests/AST/DeclPrinterTest.cpp
+++ b/unittests/AST/DeclPrinterTest.cpp
@@ -74,10 +74,12 @@
   PrintMatch Printer;
   MatchFinder Finder;
   Finder.addMatcher(NodeMatch, &Printer);
-  OwningPtr<FrontendActionFactory> Factory(newFrontendActionFactory(&Finder));
+  std::unique_ptr<FrontendActionFactory> Factory(
+      newFrontendActionFactory(&Finder));
 
   if (!runToolOnCodeWithArgs(Factory->create(), Code, Args, FileName))
-    return testing::AssertionFailure() << "Parsing error in \"" << Code << "\"";
+    return testing::AssertionFailure()
+      << "Parsing error in \"" << Code.str() << "\"";
 
   if (Printer.getNumFoundDecls() == 0)
     return testing::AssertionFailure()
@@ -90,8 +92,8 @@
 
   if (Printer.getPrinted() != ExpectedPrinted)
     return ::testing::AssertionFailure()
-      << "Expected \"" << ExpectedPrinted << "\", "
-         "got \"" << Printer.getPrinted() << "\"";
+      << "Expected \"" << ExpectedPrinted.str() << "\", "
+         "got \"" << Printer.getPrinted().str() << "\"";
 
   return ::testing::AssertionSuccess();
 }
@@ -142,6 +144,19 @@
                             "input.cc");
 }
 
+::testing::AssertionResult PrintedDeclCXX11nonMSCMatches(
+                                  StringRef Code,
+                                  const DeclarationMatcher &NodeMatch,
+                                  StringRef ExpectedPrinted) {
+  std::vector<std::string> Args(1, "-std=c++11");
+  Args.push_back("-fno-delayed-template-parsing");
+  return PrintedDeclMatches(Code,
+                            Args,
+                            NodeMatch,
+                            ExpectedPrinted,
+                            "input.cc");
+}
+
 ::testing::AssertionResult PrintedDeclObjCMatches(
                                   StringRef Code,
                                   const DeclarationMatcher &NodeMatch,
@@ -156,6 +171,40 @@
 
 } // unnamed namespace
 
+TEST(DeclPrinter, TestTypedef1) {
+  ASSERT_TRUE(PrintedDeclCXX98Matches(
+    "typedef int A;",
+    "A",
+    "typedef int A"));
+    // Should be: with semicolon
+}
+
+TEST(DeclPrinter, TestTypedef2) {
+  ASSERT_TRUE(PrintedDeclCXX98Matches(
+    "typedef const char *A;",
+    "A",
+    "typedef const char *A"));
+    // Should be: with semicolon
+}
+
+TEST(DeclPrinter, TestTypedef3) {
+  ASSERT_TRUE(PrintedDeclCXX98Matches(
+    "template <typename Y> class X {};"
+    "typedef X<int> A;",
+    "A",
+    "typedef X<int> A"));
+    // Should be: with semicolon
+}
+
+TEST(DeclPrinter, TestTypedef4) {
+  ASSERT_TRUE(PrintedDeclCXX98Matches(
+    "namespace X { class Y {}; }"
+    "typedef X::Y A;",
+    "A",
+    "typedef X::Y A"));
+    // Should be: with semicolon
+}
+
 TEST(DeclPrinter, TestNamespace1) {
   ASSERT_TRUE(PrintedDeclCXX98Matches(
     "namespace A { int B; }",
@@ -340,8 +389,8 @@
   ASSERT_TRUE(PrintedDeclCXX11Matches(
     "constexpr int A(int a);",
     "A",
-    "int A(int a)"));
-    // WRONG; Should be: "constexpr int A(int a);"
+    "constexpr int A(int a)"));
+    // Should be: with semicolon
 }
 
 TEST(DeclPrinter, TestFunctionDecl8) {
@@ -370,11 +419,11 @@
 
 TEST(DeclPrinter, TestFunctionDecl11) {
   ASSERT_TRUE(PrintedDeclCXX98Matches(
-    "typedef long size_t;"
+    "typedef long ssize_t;"
     "typedef int *pInt;"
-    "void A(int a, pInt b, size_t c);",
+    "void A(int a, pInt b, ssize_t c);",
     "A",
-    "void A(int a, pInt b, size_t c)"));
+    "void A(int a, pInt b, ssize_t c)"));
     // Should be: with semicolon
 }
 
@@ -466,8 +515,7 @@
     "  constexpr A();"
     "};",
     constructorDecl(ofClass(hasName("A"))).bind("id"),
-    "A()"));
-    // WRONG; Should be: "constexpr A();"
+    "constexpr A()"));
 }
 
 TEST(DeclPrinter, TestCXXConstructorDecl8) {
@@ -498,18 +546,16 @@
     "A<T...>(const A<T...> &a)"));
 }
 
-#if !defined(_MSC_VER)
 TEST(DeclPrinter, TestCXXConstructorDecl11) {
-  ASSERT_TRUE(PrintedDeclCXX11Matches(
+  ASSERT_TRUE(PrintedDeclCXX11nonMSCMatches(
     "template<typename... T>"
     "struct A : public T... {"
     "  A(T&&... ts) : T(ts)... {}"
     "};",
     constructorDecl(ofClass(hasName("A"))).bind("id"),
-    "A<T...>(T &&ts...) : T(ts)"));
+    "A<T...>(T &&ts...) : T(ts)..."));
     // WRONG; Should be: "A(T&&... ts) : T(ts)..."
 }
-#endif
 
 TEST(DeclPrinter, TestCXXDestructorDecl1) {
   ASSERT_TRUE(PrintedDeclCXX98Matches(
@@ -517,8 +563,7 @@
     "  ~A();"
     "};",
     destructorDecl(ofClass(hasName("A"))).bind("id"),
-    "void ~A()"));
-    // WRONG; Should be: "~A();"
+    "~A()"));
 }
 
 TEST(DeclPrinter, TestCXXDestructorDecl2) {
@@ -527,8 +572,7 @@
     "  virtual ~A();"
     "};",
     destructorDecl(ofClass(hasName("A"))).bind("id"),
-    "virtual void ~A()"));
-    // WRONG; Should be: "virtual ~A();"
+    "virtual ~A()"));
 }
 
 TEST(DeclPrinter, TestCXXConversionDecl1) {
@@ -537,8 +581,7 @@
     "  operator int();"
     "};",
     methodDecl(ofClass(hasName("A"))).bind("id"),
-    "int operator int()"));
-    // WRONG; Should be: "operator int();"
+    "operator int()"));
 }
 
 TEST(DeclPrinter, TestCXXConversionDecl2) {
@@ -547,8 +590,7 @@
     "  operator bool();"
     "};",
     methodDecl(ofClass(hasName("A"))).bind("id"),
-    "bool operator _Bool()"));
-    // WRONG; Should be: "operator bool();"
+    "operator bool()"));
 }
 
 TEST(DeclPrinter, TestCXXConversionDecl3) {
@@ -558,8 +600,7 @@
     "  operator Z();"
     "};",
     methodDecl(ofClass(hasName("A"))).bind("id"),
-    "Z operator struct Z()"));
-    // WRONG; Should be: "operator Z();"
+    "operator Z()"));
 }
 
 TEST(DeclPrinter, TestCXXMethodDecl_AllocationFunction1) {
@@ -756,8 +797,8 @@
     "  void A(int a) &;"
     "};",
     "A",
-    "void A(int a)"));
-    // WRONG; Should be: "void A(int a) &;"
+    "void A(int a) &"));
+    // Should be: with semicolon
 }
 
 TEST(DeclPrinter, TestCXXMethodDecl_RefQualifier2) {
@@ -766,8 +807,8 @@
     "  void A(int a) &&;"
     "};",
     "A",
-    "void A(int a)"));
-    // WRONG; Should be: "void A(int a) &&;"
+    "void A(int a) &&"));
+    // Should be: with semicolon
 }
 
 TEST(DeclPrinter, TestFunctionDecl_ExceptionSpecification1) {
diff --git a/unittests/AST/DeclTest.cpp b/unittests/AST/DeclTest.cpp
index c845da2..87aeef4 100644
--- a/unittests/AST/DeclTest.cpp
+++ b/unittests/AST/DeclTest.cpp
@@ -20,7 +20,7 @@
 
 TEST(Decl, CleansUpAPValues) {
   MatchFinder Finder;
-  llvm::OwningPtr<FrontendActionFactory> Factory(
+  std::unique_ptr<FrontendActionFactory> Factory(
       newFrontendActionFactory(&Finder));
 
   // This is a regression test for a memory leak in APValues for structs that
diff --git a/unittests/AST/EvaluateAsRValueTest.cpp b/unittests/AST/EvaluateAsRValueTest.cpp
new file mode 100644
index 0000000..9120c93
--- /dev/null
+++ b/unittests/AST/EvaluateAsRValueTest.cpp
@@ -0,0 +1,112 @@
+//===- unittests/AST/EvaluateAsRValueTest.cpp -----------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// \file
+// \brief Unit tests for evaluation of constant initializers.
+//
+//===----------------------------------------------------------------------===//
+
+#include <map>
+#include <string>
+
+#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/Tooling/Tooling.h"
+#include "gtest/gtest.h"
+
+#include "clang/AST/ASTConsumer.h"
+
+using namespace clang::tooling;
+
+namespace {
+// For each variable name encountered, whether its initializer was a
+// constant.
+typedef std::map<std::string, bool> VarInfoMap;
+
+/// \brief Records information on variable initializers to a map.
+class EvaluateConstantInitializersVisitor
+    : public clang::RecursiveASTVisitor<EvaluateConstantInitializersVisitor> {
+ public:
+  explicit EvaluateConstantInitializersVisitor(VarInfoMap &VarInfo)
+      : VarInfo(VarInfo) {}
+
+  /// \brief Checks that isConstantInitializer and EvaluateAsRValue agree
+  /// and don't crash.
+  ///
+  /// For each VarDecl with an initializer this also records in VarInfo
+  /// whether the initializer could be evaluated as a constant.
+  bool VisitVarDecl(const clang::VarDecl *VD) {
+    if (const clang::Expr *Init = VD->getInit()) {
+      clang::Expr::EvalResult Result;
+      bool WasEvaluated = Init->EvaluateAsRValue(Result, VD->getASTContext());
+      VarInfo[VD->getNameAsString()] = WasEvaluated;
+      EXPECT_EQ(WasEvaluated, Init->isConstantInitializer(VD->getASTContext(),
+                                                          false /*ForRef*/));
+    }
+    return true;
+  }
+
+ private:
+  VarInfoMap &VarInfo;
+};
+
+class EvaluateConstantInitializersAction : public clang::ASTFrontendAction {
+ public:
+  clang::ASTConsumer *CreateASTConsumer(clang::CompilerInstance &Compiler,
+                                        llvm::StringRef FilePath) override {
+    return new Consumer;
+  }
+
+ private:
+  class Consumer : public clang::ASTConsumer {
+   public:
+    ~Consumer() override {}
+
+    void HandleTranslationUnit(clang::ASTContext &Ctx) override {
+      VarInfoMap VarInfo;
+      EvaluateConstantInitializersVisitor Evaluator(VarInfo);
+      Evaluator.TraverseDecl(Ctx.getTranslationUnitDecl());
+      EXPECT_EQ(2u, VarInfo.size());
+      EXPECT_FALSE(VarInfo["Dependent"]);
+      EXPECT_TRUE(VarInfo["Constant"]);
+      EXPECT_EQ(2u, VarInfo.size());
+    }
+  };
+};
+}
+
+TEST(EvaluateAsRValue, FailsGracefullyForUnknownTypes) {
+  // This is a regression test; the AST library used to trigger assertion
+  // failures because it assumed that the type of initializers was always
+  // known (which is true only after template instantiation).
+  std::string ModesToTest[] = {"-std=c++03", "-std=c++11", "-std=c++1y"};
+  for (std::string const &Mode : ModesToTest) {
+    std::vector<std::string> Args(1, Mode);
+    Args.push_back("-fno-delayed-template-parsing");
+    ASSERT_TRUE(runToolOnCodeWithArgs(
+      new EvaluateConstantInitializersAction(),
+      "template <typename T>"
+      "struct vector {"
+      "  explicit vector(int size);"
+      "};"
+      "template <typename R>"
+      "struct S {"
+      "  vector<R> intervals() const {"
+      "    vector<R> Dependent(2);"
+      "    return Dependent;"
+      "  }"
+      "};"
+      "void doSomething() {"
+      "  int Constant = 2 + 2;"
+      "  (void) Constant;"
+      "}",
+      Args));
+  }
+}
diff --git a/unittests/AST/ExternalASTSourceTest.cpp b/unittests/AST/ExternalASTSourceTest.cpp
new file mode 100644
index 0000000..5cc2def
--- /dev/null
+++ b/unittests/AST/ExternalASTSourceTest.cpp
@@ -0,0 +1,83 @@
+//===- unittest/AST/ExternalASTSourceTest.cpp -----------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains tests for Clang's ExternalASTSource.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/ExternalASTSource.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/CompilerInvocation.h"
+#include "clang/Frontend/FrontendActions.h"
+#include "gtest/gtest.h"
+
+using namespace clang;
+using namespace llvm;
+
+
+class TestFrontendAction : public ASTFrontendAction {
+public:
+  TestFrontendAction(ExternalASTSource *Source) : Source(Source) {}
+
+private:
+  virtual void ExecuteAction() {
+    getCompilerInstance().getASTContext().setExternalSource(Source);
+    getCompilerInstance().getASTContext().getTranslationUnitDecl()
+        ->setHasExternalVisibleStorage();
+    return ASTFrontendAction::ExecuteAction();
+  }
+
+  virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
+                                         StringRef InFile) {
+    return new ASTConsumer;
+  }
+
+  IntrusiveRefCntPtr<ExternalASTSource> Source;
+};
+
+bool testExternalASTSource(ExternalASTSource *Source,
+                           StringRef FileContents) {
+  CompilerInstance Compiler;
+  Compiler.createDiagnostics();
+
+  CompilerInvocation *Invocation = new CompilerInvocation;
+  Invocation->getPreprocessorOpts().addRemappedFile(
+    "test.cc", MemoryBuffer::getMemBuffer(FileContents));
+  const char *Args[] = { "test.cc" };
+  CompilerInvocation::CreateFromArgs(*Invocation, Args,
+                                     Args + array_lengthof(Args),
+                                     Compiler.getDiagnostics());
+  Compiler.setInvocation(Invocation);
+
+  TestFrontendAction Action(Source);
+  return Compiler.ExecuteAction(Action);
+}
+
+
+// Ensure that a failed name lookup into an external source only occurs once.
+TEST(ExternalASTSourceTest, FailedLookupOccursOnce) {
+  struct TestSource : ExternalASTSource {
+    TestSource(unsigned &Calls) : Calls(Calls) {}
+
+    bool FindExternalVisibleDeclsByName(const DeclContext*,
+                                        DeclarationName Name) {
+      if (Name.getAsString() == "j")
+        ++Calls;
+      return false;
+    }
+
+    unsigned &Calls;
+  };
+
+  unsigned Calls = 0;
+  ASSERT_TRUE(testExternalASTSource(new TestSource(Calls), "int j, k = j;"));
+  EXPECT_EQ(1u, Calls);
+}
diff --git a/unittests/AST/MatchVerifier.h b/unittests/AST/MatchVerifier.h
index 5a29cde..0265f4a 100644
--- a/unittests/AST/MatchVerifier.h
+++ b/unittests/AST/MatchVerifier.h
@@ -79,7 +79,7 @@
     std::vector<std::string>& Args, Language L) {
   MatchFinder Finder;
   Finder.addMatcher(AMatcher.bind(""), this);
-  OwningPtr<tooling::FrontendActionFactory> Factory(
+  std::unique_ptr<tooling::FrontendActionFactory> Factory(
       tooling::newFrontendActionFactory(&Finder));
 
   StringRef FileName;
diff --git a/unittests/AST/SourceLocationTest.cpp b/unittests/AST/SourceLocationTest.cpp
index 29156bc..6e94442 100644
--- a/unittests/AST/SourceLocationTest.cpp
+++ b/unittests/AST/SourceLocationTest.cpp
@@ -17,11 +17,11 @@
 //===----------------------------------------------------------------------===//
 
 #include "clang/AST/ASTContext.h"
+#include "MatchVerifier.h"
 #include "clang/ASTMatchers/ASTMatchFinder.h"
 #include "clang/ASTMatchers/ASTMatchers.h"
 #include "clang/Tooling/Tooling.h"
 #include "gtest/gtest.h"
-#include "MatchVerifier.h"
 
 namespace clang {
 namespace ast_matchers {
@@ -211,6 +211,16 @@
       functionalCastExpr(), Lang_CXX11));
 }
 
+TEST(CXXConstructExpr, SourceRange) {
+  RangeVerifier<CXXConstructExpr> Verifier;
+  Verifier.expectRange(3, 14, 3, 19);
+  EXPECT_TRUE(Verifier.match(
+      "struct A { A(int, int); };\n"
+      "void f(A a);\n"
+      "void g() { f({0, 0}); }",
+      constructExpr(), Lang_CXX11));
+}
+
 TEST(CXXTemporaryObjectExpr, SourceRange) {
   RangeVerifier<CXXTemporaryObjectExpr> Verifier;
   Verifier.expectRange(2, 6, 2, 12);
diff --git a/unittests/AST/StmtPrinterTest.cpp b/unittests/AST/StmtPrinterTest.cpp
index 473ee13..d726517 100644
--- a/unittests/AST/StmtPrinterTest.cpp
+++ b/unittests/AST/StmtPrinterTest.cpp
@@ -64,19 +64,20 @@
   }
 };
 
-::testing::AssertionResult PrintedStmtMatches(
-                                        StringRef Code,
-                                        const std::vector<std::string> &Args,
-                                        const DeclarationMatcher &NodeMatch,
-                                        StringRef ExpectedPrinted) {
+template <typename T>
+::testing::AssertionResult
+PrintedStmtMatches(StringRef Code, const std::vector<std::string> &Args,
+                   const T &NodeMatch, StringRef ExpectedPrinted) {
 
   PrintMatch Printer;
   MatchFinder Finder;
   Finder.addMatcher(NodeMatch, &Printer);
-  OwningPtr<FrontendActionFactory> Factory(newFrontendActionFactory(&Finder));
+  std::unique_ptr<FrontendActionFactory> Factory(
+      newFrontendActionFactory(&Finder));
 
   if (!runToolOnCodeWithArgs(Factory->create(), Code, Args))
-    return testing::AssertionFailure() << "Parsing error in \"" << Code << "\"";
+    return testing::AssertionFailure()
+      << "Parsing error in \"" << Code.str() << "\"";
 
   if (Printer.getNumFoundStmts() == 0)
     return testing::AssertionFailure()
@@ -89,12 +90,21 @@
 
   if (Printer.getPrinted() != ExpectedPrinted)
     return ::testing::AssertionFailure()
-      << "Expected \"" << ExpectedPrinted << "\", "
-         "got \"" << Printer.getPrinted() << "\"";
+      << "Expected \"" << ExpectedPrinted.str() << "\", "
+         "got \"" << Printer.getPrinted().str() << "\"";
 
   return ::testing::AssertionSuccess();
 }
 
+::testing::AssertionResult
+PrintedStmtCXX98Matches(StringRef Code, const StatementMatcher &NodeMatch,
+                        StringRef ExpectedPrinted) {
+  std::vector<std::string> Args;
+  Args.push_back("-std=c++98");
+  Args.push_back("-Wno-unused-value");
+  return PrintedStmtMatches(Code, Args, NodeMatch, ExpectedPrinted);
+}
+
 ::testing::AssertionResult PrintedStmtCXX98Matches(
                                               StringRef Code,
                                               StringRef ContainingFunction,
@@ -109,6 +119,15 @@
                             ExpectedPrinted);
 }
 
+::testing::AssertionResult
+PrintedStmtCXX11Matches(StringRef Code, const StatementMatcher &NodeMatch,
+                        StringRef ExpectedPrinted) {
+  std::vector<std::string> Args;
+  Args.push_back("-std=c++11");
+  Args.push_back("-Wno-unused-value");
+  return PrintedStmtMatches(Code, Args, NodeMatch, ExpectedPrinted);
+}
+
 ::testing::AssertionResult PrintedStmtMSMatches(
                                               StringRef Code,
                                               StringRef ContainingFunction,
@@ -163,3 +182,32 @@
     "1.F , -1.F , 1. , -1. , 1.L , -1.L"));
     // Should be: with semicolon
 }
+
+TEST(StmtPrinter, TestCXXConversionDeclImplicit) {
+  ASSERT_TRUE(PrintedStmtCXX98Matches(
+    "struct A {"
+      "operator void *();"
+      "A operator&(A);"
+    "};"
+    "void bar(void *);"
+    "void foo(A a, A b) {"
+    "  bar(a & b);"
+    "}",
+    memberCallExpr(anything()).bind("id"),
+    "a & b"));
+}
+
+TEST(StmtPrinter, TestCXXConversionDeclExplicit) {
+  ASSERT_TRUE(PrintedStmtCXX11Matches(
+    "struct A {"
+      "operator void *();"
+      "A operator&(A);"
+    "};"
+    "void bar(void *);"
+    "void foo(A a, A b) {"
+    "  auto x = (a & b).operator void *();"
+    "}",
+    memberCallExpr(anything()).bind("id"),
+    "(a & b)"));
+    // WRONG; Should be: (a & b).operator void *()
+}