EricWF updated this revision to Diff 177716.
EricWF added a comment.

More tests.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D55534/new/

https://reviews.llvm.org/D55534

Files:
  include/clang/AST/Expr.h
  include/clang/AST/ExprCXX.h
  include/clang/AST/Stmt.h
  include/clang/ASTMatchers/ASTMatchers.h
  include/clang/Sema/Overload.h
  include/clang/Sema/Sema.h
  lib/AST/ASTDumper.cpp
  lib/AST/ASTImporter.cpp
  lib/AST/Expr.cpp
  lib/Sema/SemaExpr.cpp
  lib/Sema/SemaOverload.cpp
  lib/Serialization/ASTReaderStmt.cpp
  lib/Serialization/ASTWriterStmt.cpp
  test/AST/ast-dump-expr.cpp
  unittests/ASTMatchers/ASTMatchersNodeTest.cpp

Index: unittests/ASTMatchers/ASTMatchersNodeTest.cpp
===================================================================
--- unittests/ASTMatchers/ASTMatchersNodeTest.cpp
+++ unittests/ASTMatchers/ASTMatchersNodeTest.cpp
@@ -199,6 +199,40 @@
                                    "-fno-delayed-template-parsing"));
 }
 
+TEST(Matcher, ADLCall) {
+  StatementMatcher ADLMatch = callExpr(usesADL());
+  StatementMatcher ADLMatchOper = cxxOperatorCallExpr(usesADL());
+  auto NS_Str = R"cpp(
+  namespace NS {
+    struct X {};
+    void f(X);
+    void operator+(X, X);
+  }
+  struct MyX {};
+  void f(...);
+  void operator+(MyX, MyX);
+)cpp";
+
+  auto MkStr = [&](std::string Body) -> std::string {
+    std::string S = NS_Str;
+    S += "void test_fn() { " + Body + " }";
+    return S;
+  };
+
+  EXPECT_TRUE(matches(MkStr("NS::X x; f(x);"), ADLMatch));
+  EXPECT_TRUE(notMatches(MkStr("NS::X x; NS::f(x);"), ADLMatch));
+  EXPECT_TRUE(notMatches(MkStr("MyX x; f(x);"), ADLMatch));
+  EXPECT_TRUE(notMatches(MkStr("NS::X x; using NS::f; f(x);"), ADLMatch));
+
+  // Operator call expressions
+  EXPECT_TRUE(matches(MkStr("NS::X x; x + x;"), ADLMatch));
+  EXPECT_TRUE(matches(MkStr("NS::X x; x + x;"), ADLMatchOper));
+  EXPECT_TRUE(notMatches(MkStr("MyX x; x + x;"), ADLMatch));
+  EXPECT_TRUE(notMatches(MkStr("MyX x; x + x;"), ADLMatchOper));
+  EXPECT_TRUE(matches(MkStr("NS::X x; operator+(x, x);"), ADLMatch));
+  EXPECT_TRUE(notMatches(MkStr("NS::X x; NS::operator+(x, x);"), ADLMatch));
+}
+
 TEST(Matcher, Call) {
   // FIXME: Do we want to overload Call() to directly take
   // Matcher<Decl>, too?
Index: test/AST/ast-dump-expr.cpp
===================================================================
--- /dev/null
+++ test/AST/ast-dump-expr.cpp
@@ -0,0 +1,44 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -Wno-unused-value -std=c++14 -ast-dump %s \
+// RUN:    | FileCheck -strict-whitespace %s
+
+namespace NS {
+struct X {};
+void f(X);
+void y(...);
+} // namespace NS
+
+// CHECK-LABEL: FunctionDecl 0x{{[^ ]*}} {{.*}}ADLCall 'void ()'
+void ADLCall() {
+  NS::X x;
+  // CHECK: CallExpr 0x{{[^ ]*}} <line:[[@LINE+1]]:{{[^>]+}}> 'void' adl{{$}}
+  f(x);
+  // CHECK: CallExpr 0x{{[^ ]*}} <line:[[@LINE+1]]:{{[^>]+}}> 'void' adl{{$}}
+  y(x);
+}
+
+// CHECK-LABEL: FunctionDecl 0x{{[^ ]*}} {{.*}}NonADLCall 'void ()'
+void NonADLCall() {
+  NS::X x;
+  // CHECK: CallExpr 0x{{[^ ]*}} <line:[[@LINE+1]]:{{[^>]+}}> 'void'{{$}}
+  NS::f(x);
+}
+
+// CHECK-LABEL: FunctionDecl 0x{{[^ ]*}} {{.*}}NonADLCall2 'void ()'
+void NonADLCall2() {
+  NS::X x;
+  using NS::f;
+  // CHECK: CallExpr 0x{{[^ ]*}} <line:[[@LINE+1]]:{{[^>]+}}> 'void'{{$}}
+  f(x);
+  // CHECK: CallExpr 0x{{[^ ]*}} <line:[[@LINE+1]]:{{[^>]+}}> 'void' adl{{$}}
+  y(x);
+}
+
+namespace test_adl_call_three {
+using namespace NS;
+// CHECK-LABEL: FunctionDecl 0x{{[^ ]*}} {{.*}}NonADLCall3 'void ()'
+void NonADLCall3() {
+  X x;
+  // CHECK: CallExpr 0x{{[^ ]*}} <line:[[@LINE+1]]:{{[^>]+}}> 'void'{{$}}
+  f(x);
+}
+} // namespace test_adl_call_three
Index: lib/Serialization/ASTWriterStmt.cpp
===================================================================
--- lib/Serialization/ASTWriterStmt.cpp
+++ lib/Serialization/ASTWriterStmt.cpp
@@ -651,6 +651,7 @@
   for (CallExpr::arg_iterator Arg = E->arg_begin(), ArgEnd = E->arg_end();
        Arg != ArgEnd; ++Arg)
     Record.AddStmt(*Arg);
+  Record.push_back(E->usesADL());
   Code = serialization::EXPR_CALL;
 }
 
Index: lib/Serialization/ASTReaderStmt.cpp
===================================================================
--- lib/Serialization/ASTReaderStmt.cpp
+++ lib/Serialization/ASTReaderStmt.cpp
@@ -737,6 +737,7 @@
   E->setCallee(Record.readSubExpr());
   for (unsigned I = 0; I != NumArgs; ++I)
     E->setArg(I, Record.readSubExpr());
+  E->setUsesADL(Record.readInt());
 }
 
 void ASTStmtReader::VisitCXXMemberCallExpr(CXXMemberCallExpr *E) {
Index: lib/Sema/SemaOverload.cpp
===================================================================
--- lib/Sema/SemaOverload.cpp
+++ lib/Sema/SemaOverload.cpp
@@ -5946,15 +5946,13 @@
 /// \param PartialOverloading true if we are performing "partial" overloading
 /// based on an incomplete set of function arguments. This feature is used by
 /// code completion.
-void
-Sema::AddOverloadCandidate(FunctionDecl *Function,
-                           DeclAccessPair FoundDecl,
-                           ArrayRef<Expr *> Args,
-                           OverloadCandidateSet &CandidateSet,
-                           bool SuppressUserConversions,
-                           bool PartialOverloading,
-                           bool AllowExplicit,
-                           ConversionSequenceList EarlyConversions) {
+void Sema::AddOverloadCandidate(FunctionDecl *Function,
+                                DeclAccessPair FoundDecl, ArrayRef<Expr *> Args,
+                                OverloadCandidateSet &CandidateSet,
+                                bool SuppressUserConversions,
+                                bool PartialOverloading, bool AllowExplicit,
+                                bool IsADLCandidate,
+                                ConversionSequenceList EarlyConversions) {
   const FunctionProtoType *Proto
     = dyn_cast<FunctionProtoType>(Function->getType()->getAs<FunctionType>());
   assert(Proto && "Functions without a prototype cannot be overloaded");
@@ -6013,6 +6011,7 @@
   Candidate.Function = Function;
   Candidate.Viable = true;
   Candidate.IsSurrogate = false;
+  Candidate.IsADLCandidate = IsADLCandidate;
   Candidate.IgnoreObjectArgument = false;
   Candidate.ExplicitCallArguments = Args.size();
 
@@ -6715,14 +6714,11 @@
 /// Add a C++ function template specialization as a candidate
 /// in the candidate set, using template argument deduction to produce
 /// an appropriate function template specialization.
-void
-Sema::AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate,
-                                   DeclAccessPair FoundDecl,
-                                 TemplateArgumentListInfo *ExplicitTemplateArgs,
-                                   ArrayRef<Expr *> Args,
-                                   OverloadCandidateSet& CandidateSet,
-                                   bool SuppressUserConversions,
-                                   bool PartialOverloading) {
+void Sema::AddTemplateOverloadCandidate(
+    FunctionTemplateDecl *FunctionTemplate, DeclAccessPair FoundDecl,
+    TemplateArgumentListInfo *ExplicitTemplateArgs, ArrayRef<Expr *> Args,
+    OverloadCandidateSet &CandidateSet, bool SuppressUserConversions,
+    bool PartialOverloading, bool IsADLCandidate) {
   if (!CandidateSet.isNewCandidate(FunctionTemplate))
     return;
 
@@ -6751,6 +6747,7 @@
     Candidate.Function = FunctionTemplate->getTemplatedDecl();
     Candidate.Viable = false;
     Candidate.IsSurrogate = false;
+    Candidate.IsADLCandidate = IsADLCandidate;
     // Ignore the object argument if there is one, since we don't have an object
     // type.
     Candidate.IgnoreObjectArgument =
@@ -6772,7 +6769,7 @@
   assert(Specialization && "Missing function template specialization?");
   AddOverloadCandidate(Specialization, FoundDecl, Args, CandidateSet,
                        SuppressUserConversions, PartialOverloading,
-                       /*AllowExplicit*/false, Conversions);
+                       /*AllowExplicit*/ false, IsADLCandidate, Conversions);
 }
 
 /// Check that implicit conversion sequences can be formed for each argument
@@ -8935,16 +8932,19 @@
   // set.
   for (ADLResult::iterator I = Fns.begin(), E = Fns.end(); I != E; ++I) {
     DeclAccessPair FoundDecl = DeclAccessPair::make(*I, AS_none);
+
     if (FunctionDecl *FD = dyn_cast<FunctionDecl>(*I)) {
       if (ExplicitTemplateArgs)
         continue;
 
       AddOverloadCandidate(FD, FoundDecl, Args, CandidateSet, false,
-                           PartialOverloading);
+                           PartialOverloading, /*AllowExplicit=*/false,
+                           /*IsADLCandidate=*/true);
     } else
-      AddTemplateOverloadCandidate(cast<FunctionTemplateDecl>(*I),
-                                   FoundDecl, ExplicitTemplateArgs,
-                                   Args, CandidateSet, PartialOverloading);
+      AddTemplateOverloadCandidate(cast<FunctionTemplateDecl>(*I), FoundDecl,
+                                   ExplicitTemplateArgs, Args, CandidateSet,
+                                   /*SuppressUserConversions=*/false,
+                                   PartialOverloading, /*IsADLCandidate=*/true);
   }
 }
 
@@ -12021,7 +12021,8 @@
       return ExprError();
     Fn = SemaRef.FixOverloadedFunctionReference(Fn, (*Best)->FoundDecl, FDecl);
     return SemaRef.BuildResolvedCallExpr(Fn, FDecl, LParenLoc, Args, RParenLoc,
-                                         ExecConfig);
+                                         ExecConfig, /*IsExecConfig=*/false,
+                                         (*Best)->IsADLCandidate);
   }
 
   case OR_No_Viable_Function: {
@@ -12073,7 +12074,8 @@
     FunctionDecl *FDecl = (*Best)->Function;
     Fn = SemaRef.FixOverloadedFunctionReference(Fn, (*Best)->FoundDecl, FDecl);
     return SemaRef.BuildResolvedCallExpr(Fn, FDecl, LParenLoc, Args, RParenLoc,
-                                         ExecConfig);
+                                         ExecConfig, /*IsExecConfig=*/false,
+                                         (*Best)->IsADLCandidate);
   }
   }
 
@@ -12262,9 +12264,9 @@
       ResultTy = ResultTy.getNonLValueExprType(Context);
 
       Args[0] = Input;
-      CallExpr *TheCall =
-        new (Context) CXXOperatorCallExpr(Context, Op, FnExpr.get(), ArgsArray,
-                                          ResultTy, VK, OpLoc, FPOptions());
+      CallExpr *TheCall = new (Context)
+          CXXOperatorCallExpr(Context, Op, FnExpr.get(), ArgsArray, ResultTy,
+                              VK, OpLoc, FPOptions(), Best->IsADLCandidate);
 
       if (CheckCallReturnType(FnDecl->getReturnType(), OpLoc, TheCall, FnDecl))
         return ExprError();
@@ -12494,10 +12496,9 @@
         ExprValueKind VK = Expr::getValueKindForType(ResultTy);
         ResultTy = ResultTy.getNonLValueExprType(Context);
 
-        CXXOperatorCallExpr *TheCall =
-          new (Context) CXXOperatorCallExpr(Context, Op, FnExpr.get(),
-                                            Args, ResultTy, VK, OpLoc,
-                                            FPFeatures);
+        CXXOperatorCallExpr *TheCall = new (Context)
+            CXXOperatorCallExpr(Context, Op, FnExpr.get(), Args, ResultTy, VK,
+                                OpLoc, FPFeatures, Best->IsADLCandidate);
 
         if (CheckCallReturnType(FnDecl->getReturnType(), OpLoc, TheCall,
                                 FnDecl))
Index: lib/Sema/SemaExpr.cpp
===================================================================
--- lib/Sema/SemaExpr.cpp
+++ lib/Sema/SemaExpr.cpp
@@ -5585,12 +5585,11 @@
 /// block-pointer type.
 ///
 /// \param NDecl the declaration being called, if available
-ExprResult
-Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
-                            SourceLocation LParenLoc,
-                            ArrayRef<Expr *> Args,
-                            SourceLocation RParenLoc,
-                            Expr *Config, bool IsExecConfig) {
+ExprResult Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
+                                       SourceLocation LParenLoc,
+                                       ArrayRef<Expr *> Args,
+                                       SourceLocation RParenLoc, Expr *Config,
+                                       bool IsExecConfig, bool UsesADL) {
   FunctionDecl *FDecl = dyn_cast_or_null<FunctionDecl>(NDecl);
   unsigned BuiltinID = (FDecl ? FDecl->getBuiltinID() : 0);
 
@@ -5670,13 +5669,13 @@
   unsigned NumParams = Proto ? Proto->getNumParams() : 0;
 
   CallExpr *TheCall;
-  if (Config)
+  if (Config) {
     TheCall = new (Context)
         CUDAKernelCallExpr(Context, Fn, cast<CallExpr>(Config), Args, ResultTy,
                            VK_RValue, RParenLoc, NumParams);
-  else
-    TheCall = new (Context)
-        CallExpr(Context, Fn, Args, ResultTy, VK_RValue, RParenLoc, NumParams);
+  } else
+    TheCall = new (Context) CallExpr(Context, Fn, Args, ResultTy, VK_RValue,
+                                     RParenLoc, NumParams, UsesADL);
 
   if (!getLangOpts().CPlusPlus) {
     // C cannot always handle TypoExpr nodes in builtin calls and direct
Index: lib/AST/Expr.cpp
===================================================================
--- lib/AST/Expr.cpp
+++ lib/AST/Expr.cpp
@@ -1223,11 +1223,13 @@
 CallExpr::CallExpr(const ASTContext &C, StmtClass SC, Expr *fn,
                    ArrayRef<Expr *> preargs, ArrayRef<Expr *> args, QualType t,
                    ExprValueKind VK, SourceLocation rparenloc,
-                   unsigned MinNumArgs)
+                   unsigned MinNumArgs, bool UsesADL)
     : Expr(SC, t, VK, OK_Ordinary, fn->isTypeDependent(),
            fn->isValueDependent(), fn->isInstantiationDependent(),
            fn->containsUnexpandedParameterPack()),
       RParenLoc(rparenloc) {
+  CallExprBits.UsesADL = UsesADL;
+
   NumArgs = std::max<unsigned>(args.size(), MinNumArgs);
   unsigned NumPreArgs = preargs.size();
   CallExprBits.NumPreArgs = NumPreArgs;
@@ -1249,19 +1251,20 @@
 
 CallExpr::CallExpr(const ASTContext &C, StmtClass SC, Expr *fn,
                    ArrayRef<Expr *> args, QualType t, ExprValueKind VK,
-                   SourceLocation rparenloc, unsigned MinNumArgs)
+                   SourceLocation rparenloc, unsigned MinNumArgs, bool UsesADL)
     : CallExpr(C, SC, fn, ArrayRef<Expr *>(), args, t, VK, rparenloc,
-               MinNumArgs) {}
+               MinNumArgs, UsesADL) {}
 
 CallExpr::CallExpr(const ASTContext &C, Expr *fn, ArrayRef<Expr *> args,
                    QualType t, ExprValueKind VK, SourceLocation rparenloc,
-                   unsigned MinNumArgs)
-    : CallExpr(C, CallExprClass, fn, ArrayRef<Expr *>(), args, t, VK,
-               rparenloc, MinNumArgs) {}
+                   unsigned MinNumArgs, bool UsesADL)
+    : CallExpr(C, CallExprClass, fn, ArrayRef<Expr *>(), args, t, VK, rparenloc,
+               MinNumArgs, UsesADL) {}
 
 CallExpr::CallExpr(const ASTContext &C, StmtClass SC, unsigned NumPreArgs,
                    unsigned NumArgs, EmptyShell Empty)
     : Expr(SC, Empty), NumArgs(NumArgs) {
+  CallExprBits.UsesADL = false;
   CallExprBits.NumPreArgs = NumPreArgs;
   SubExprs = new (C) Stmt *[NumArgs + PREARGS_START + NumPreArgs];
 }
Index: lib/AST/ASTImporter.cpp
===================================================================
--- lib/AST/ASTImporter.cpp
+++ lib/AST/ASTImporter.cpp
@@ -7380,7 +7380,7 @@
   if (const auto *OCE = dyn_cast<CXXOperatorCallExpr>(E)) {
     return new (Importer.getToContext()) CXXOperatorCallExpr(
         Importer.getToContext(), OCE->getOperator(), ToCallee, ToArgs, ToType,
-        OCE->getValueKind(), ToRParenLoc, OCE->getFPFeatures());
+        OCE->getValueKind(), ToRParenLoc, OCE->getFPFeatures(), OCE->usesADL());
   }
 
   return new (Importer.getToContext()) CallExpr(
Index: lib/AST/ASTDumper.cpp
===================================================================
--- lib/AST/ASTDumper.cpp
+++ lib/AST/ASTDumper.cpp
@@ -382,6 +382,7 @@
     void VisitOMPExecutableDirective(const OMPExecutableDirective *Node);
 
     // Exprs
+    void VisitCallExpr(const CallExpr *Node);
     void VisitCastExpr(const CastExpr *Node);
     void VisitImplicitCastExpr(const ImplicitCastExpr *Node);
     void VisitDeclRefExpr(const DeclRefExpr *Node);
@@ -1876,6 +1877,11 @@
   OS << ')';
 }
 
+void ASTDumper::VisitCallExpr(const CallExpr *Node) {
+  if (Node->usesADL())
+    OS << " adl";
+}
+
 void ASTDumper::VisitCastExpr(const CastExpr *Node) {
   OS << " <";
   {
Index: include/clang/Sema/Sema.h
===================================================================
--- include/clang/Sema/Sema.h
+++ include/clang/Sema/Sema.h
@@ -2749,13 +2749,13 @@
   typedef llvm::SmallSetVector<DeclContext   *, 16> AssociatedNamespaceSet;
   typedef llvm::SmallSetVector<CXXRecordDecl *, 16> AssociatedClassSet;
 
-  void AddOverloadCandidate(FunctionDecl *Function,
-                            DeclAccessPair FoundDecl,
+  void AddOverloadCandidate(FunctionDecl *Function, DeclAccessPair FoundDecl,
                             ArrayRef<Expr *> Args,
                             OverloadCandidateSet &CandidateSet,
                             bool SuppressUserConversions = false,
                             bool PartialOverloading = false,
                             bool AllowExplicit = false,
+                            bool IsADLCandidate = false,
                             ConversionSequenceList EarlyConversions = None);
   void AddFunctionCandidates(const UnresolvedSetImpl &Functions,
                       ArrayRef<Expr *> Args,
@@ -2789,13 +2789,11 @@
                                   OverloadCandidateSet& CandidateSet,
                                   bool SuppressUserConversions = false,
                                   bool PartialOverloading = false);
-  void AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate,
-                                    DeclAccessPair FoundDecl,
-                                 TemplateArgumentListInfo *ExplicitTemplateArgs,
-                                    ArrayRef<Expr *> Args,
-                                    OverloadCandidateSet& CandidateSet,
-                                    bool SuppressUserConversions = false,
-                                    bool PartialOverloading = false);
+  void AddTemplateOverloadCandidate(
+      FunctionTemplateDecl *FunctionTemplate, DeclAccessPair FoundDecl,
+      TemplateArgumentListInfo *ExplicitTemplateArgs, ArrayRef<Expr *> Args,
+      OverloadCandidateSet &CandidateSet, bool SuppressUserConversions = false,
+      bool PartialOverloading = false, bool IsADLCandidate = false);
   bool CheckNonDependentConversions(FunctionTemplateDecl *FunctionTemplate,
                                     ArrayRef<QualType> ParamTypes,
                                     ArrayRef<Expr *> Args,
@@ -4387,12 +4385,11 @@
                            MultiExprArg ArgExprs, SourceLocation RParenLoc,
                            Expr *ExecConfig = nullptr,
                            bool IsExecConfig = false);
-  ExprResult BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
-                                   SourceLocation LParenLoc,
-                                   ArrayRef<Expr *> Arg,
-                                   SourceLocation RParenLoc,
-                                   Expr *Config = nullptr,
-                                   bool IsExecConfig = false);
+  ExprResult
+  BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, SourceLocation LParenLoc,
+                        ArrayRef<Expr *> Arg, SourceLocation RParenLoc,
+                        Expr *Config = nullptr, bool IsExecConfig = false,
+                        bool UsesADL = false);
 
   ExprResult ActOnCUDAExecConfigExpr(Scope *S, SourceLocation LLLLoc,
                                      MultiExprArg ExecConfig,
Index: include/clang/Sema/Overload.h
===================================================================
--- include/clang/Sema/Overload.h
+++ include/clang/Sema/Overload.h
@@ -771,6 +771,9 @@
     /// object argument.
     bool IgnoreObjectArgument;
 
+    /// True if the candidate was found using ADL.
+    bool IsADLCandidate;
+
     /// FailureKind - The reason why this candidate is not viable.
     /// Actually an OverloadFailureKind.
     unsigned char FailureKind;
@@ -823,6 +826,11 @@
         return Function->getNumParams();
       return ExplicitCallArguments;
     }
+
+  private:
+    // Only the OverloadCandidate set is allowed to construct OverloadCandidates.
+    friend class OverloadCandidateSet;
+    OverloadCandidate() = default;
   };
 
   /// OverloadCandidateSet - A set of overload candidates, used in C++
@@ -945,6 +953,7 @@
 
       Candidates.push_back(OverloadCandidate());
       OverloadCandidate &C = Candidates.back();
+      C.IsADLCandidate = false;
       C.Conversions = Conversions.empty()
                           ? allocateConversionSequences(NumConversions)
                           : Conversions;
Index: include/clang/ASTMatchers/ASTMatchers.h
===================================================================
--- include/clang/ASTMatchers/ASTMatchers.h
+++ include/clang/ASTMatchers/ASTMatchers.h
@@ -1257,6 +1257,26 @@
 /// \endcode
 extern const internal::VariadicDynCastAllOfMatcher<Stmt, CallExpr> callExpr;
 
+/// Matches call expressions which were resolved using ADL.
+///
+/// Example matches y(x) but not y(42) or NS::y(x).
+/// \code
+///   namespace NS {
+///     struct X {};
+///     void y(X);
+///   } // namespace NS
+///
+///   void y(...);
+///
+///   void test() {
+///     NS::X x;
+///     y(x); // Matches
+///     NS::y(x); // Doesn't match
+///     y(42); // Doesn't match.
+///   }
+/// \endcode
+AST_MATCHER(CallExpr, usesADL) { return Node.usesADL(); }
+
 /// Matches lambda expressions.
 ///
 /// Example matches [&](){return 5;}
Index: include/clang/AST/Stmt.h
===================================================================
--- include/clang/AST/Stmt.h
+++ include/clang/AST/Stmt.h
@@ -430,6 +430,9 @@
     unsigned : NumExprBits;
 
     unsigned NumPreArgs : 1;
+
+    /// True if the callee of the call expression was found using ADL.
+    unsigned UsesADL : 1;
   };
 
   class MemberExprBitfields {
Index: include/clang/AST/ExprCXX.h
===================================================================
--- include/clang/AST/ExprCXX.h
+++ include/clang/AST/ExprCXX.h
@@ -90,10 +90,12 @@
   friend class ASTStmtReader;
   friend class ASTStmtWriter;
 
-  CXXOperatorCallExpr(ASTContext& C, OverloadedOperatorKind Op, Expr *fn,
-                      ArrayRef<Expr*> args, QualType t, ExprValueKind VK,
-                      SourceLocation operatorloc, FPOptions FPFeatures)
-      : CallExpr(C, CXXOperatorCallExprClass, fn, args, t, VK, operatorloc),
+  CXXOperatorCallExpr(ASTContext &C, OverloadedOperatorKind Op, Expr *fn,
+                      ArrayRef<Expr *> args, QualType t, ExprValueKind VK,
+                      SourceLocation operatorloc, FPOptions FPFeatures,
+                      bool UsesADL = false)
+      : CallExpr(C, CXXOperatorCallExprClass, fn, args, t, VK, operatorloc,
+                 /*MinNumArgs=*/0, UsesADL),
         Operator(Op), FPFeatures(FPFeatures) {
     Range = getSourceRangeImpl();
   }
@@ -168,7 +170,8 @@
   CXXMemberCallExpr(ASTContext &C, Expr *fn, ArrayRef<Expr *> args, QualType t,
                     ExprValueKind VK, SourceLocation RP,
                     unsigned MinNumArgs = 0)
-      : CallExpr(C, CXXMemberCallExprClass, fn, args, t, VK, RP, MinNumArgs) {}
+      : CallExpr(C, CXXMemberCallExprClass, fn, args, t, VK, RP, MinNumArgs,
+                 /*UsesADL=*/false) {}
 
   CXXMemberCallExpr(ASTContext &C, unsigned NumArgs, EmptyShell Empty)
       : CallExpr(C, CXXMemberCallExprClass, /*NumPreArgs=*/0, NumArgs, Empty) {}
@@ -212,7 +215,7 @@
                      ArrayRef<Expr *> args, QualType t, ExprValueKind VK,
                      SourceLocation RP, unsigned MinNumArgs = 0)
       : CallExpr(C, CUDAKernelCallExprClass, fn, Config, args, t, VK, RP,
-                 MinNumArgs) {}
+                 MinNumArgs, /*UsesADL=*/false) {}
 
   CUDAKernelCallExpr(ASTContext &C, unsigned NumArgs, EmptyShell Empty)
       : CallExpr(C, CUDAKernelCallExprClass, /*NumPreArgs=*/END_PREARG, NumArgs,
@@ -487,16 +490,17 @@
   friend class ASTStmtReader;
   friend class ASTStmtWriter;
 
-  UserDefinedLiteral(const ASTContext &C, Expr *Fn, ArrayRef<Expr*> Args,
+  UserDefinedLiteral(const ASTContext &C, Expr *Fn, ArrayRef<Expr *> Args,
                      QualType T, ExprValueKind VK, SourceLocation LitEndLoc,
                      SourceLocation SuffixLoc)
-      : CallExpr(C, UserDefinedLiteralClass, Fn, Args, T, VK, LitEndLoc),
+      : CallExpr(C, UserDefinedLiteralClass, Fn, Args, T, VK, LitEndLoc,
+                 /*MinNumArgs=*/0, /*UsesADL=*/false),
         UDSuffixLoc(SuffixLoc) {}
 
   explicit UserDefinedLiteral(const ASTContext &C, unsigned NumArgs,
                               EmptyShell Empty)
-      : CallExpr(C, UserDefinedLiteralClass, /*NumPreArgs=*/0, NumArgs,
-                 Empty) {}
+      : CallExpr(C, UserDefinedLiteralClass, /*NumPreArgs=*/0, NumArgs, Empty) {
+  }
 
   /// The kind of literal operator which is invoked.
   enum LiteralOperatorKind {
Index: include/clang/AST/Expr.h
===================================================================
--- include/clang/AST/Expr.h
+++ include/clang/AST/Expr.h
@@ -2416,10 +2416,11 @@
   // These versions of the constructor are for derived classes.
   CallExpr(const ASTContext &C, StmtClass SC, Expr *fn,
            ArrayRef<Expr *> preargs, ArrayRef<Expr *> args, QualType t,
-           ExprValueKind VK, SourceLocation rparenloc, unsigned MinNumArgs = 0);
+           ExprValueKind VK, SourceLocation rparenloc, unsigned MinNumArgs = 0,
+           bool UsesADL = false);
   CallExpr(const ASTContext &C, StmtClass SC, Expr *fn, ArrayRef<Expr *> args,
            QualType t, ExprValueKind VK, SourceLocation rparenloc,
-           unsigned MinNumArgs = 0);
+           unsigned MinNumArgs = 0, bool UsesADL = false);
   CallExpr(const ASTContext &C, StmtClass SC, unsigned NumPreArgs,
            unsigned NumArgs, EmptyShell Empty);
 
@@ -2443,7 +2444,8 @@
   /// arguments. The actual number of arguments will be the greater of
   /// args.size() and MinNumArgs.
   CallExpr(const ASTContext &C, Expr *fn, ArrayRef<Expr *> args, QualType t,
-           ExprValueKind VK, SourceLocation rparenloc, unsigned MinNumArgs = 0);
+           ExprValueKind VK, SourceLocation rparenloc, unsigned MinNumArgs = 0,
+           bool UsesADL = false);
 
   /// Build an empty call expression.
   CallExpr(const ASTContext &C, unsigned NumArgs, EmptyShell Empty);
@@ -2452,6 +2454,9 @@
   Expr *getCallee() { return cast<Expr>(SubExprs[FN]); }
   void setCallee(Expr *F) { SubExprs[FN] = F; }
 
+  bool usesADL() const { return CallExprBits.UsesADL; }
+  void setUsesADL(bool V = true) { CallExprBits.UsesADL = V; }
+
   Decl *getCalleeDecl();
   const Decl *getCalleeDecl() const {
     return const_cast<CallExpr*>(this)->getCalleeDecl();
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to