[PATCH] D117603: [clang] Don't typo-fix an expression in a SFINAE context

2022-02-03 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone added a comment.

In D117603#3292657 , @var-const wrote:

> @Quuxplusone Now that it's landed, do we still need `__workaround_52970` in 
> libc++? (see 
> https://github.com/llvm/llvm-project/blob/167b623a6af26802af47f455aaa3806faaa9da9e/libcxx/include/__concepts/class_or_enum.h#L28-L30)

It's landed in Clang 14, but libc++14 still needs to support Clang 13 for 
another whole release (six months? a year?), so, no, we can't remove that 
workaround //yet//.
But you're correct that that's the reason I was kinda hurrying to get it fixed 
already before the release/14.x branch — it'll mean libc++ gets to remove the 
workaround 6 (12?) months earlier than otherwise.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D117603

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D117603: [clang] Don't typo-fix an expression in a SFINAE context

2022-02-02 Thread Konstantin Varlamov via Phabricator via cfe-commits
var-const added a comment.

@Quuxplusone Now that it's landed, do we still need `__workaround_52970` in 
libc++? (see 
https://github.com/llvm/llvm-project/blob/167b623a6af26802af47f455aaa3806faaa9da9e/libcxx/include/__concepts/class_or_enum.h#L28-L30)


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D117603

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D117603: [clang] Don't typo-fix an expression in a SFINAE context

2022-02-01 Thread Arthur O'Dwyer via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rGc0185ffaec3c: [clang] Dont typo-fix an expression in a 
SFINAE context. (authored by arthur.j.odwyer).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D117603

Files:
  clang/lib/Sema/Sema.cpp
  clang/lib/Sema/SemaExprMember.cpp
  clang/test/SemaTemplate/pr52970.cpp

Index: clang/test/SemaTemplate/pr52970.cpp
===
--- /dev/null
+++ clang/test/SemaTemplate/pr52970.cpp
@@ -0,0 +1,63 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++14 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++17 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++20 -verify=cxx20 %s
+// expected-no-diagnostics
+
+struct Incomplete;
+template  struct Holder { T t; };
+
+namespace DotFollowingFunctionName {
+struct Good {
+  struct Nested {
+int b;
+  } a;
+};
+
+struct Bad {
+  Holder a();
+};
+
+template 
+constexpr auto f(T t) -> decltype((t.a.b, true)) { return true; }
+constexpr bool f(...) { return false; }
+
+static_assert(DotFollowingFunctionName::f(Good{}), "");
+static_assert(!DotFollowingFunctionName::f(Bad{}), "");
+
+#if __cplusplus >= 202002L
+template 
+concept C = requires(T t) { t.a.b; };
+  // cxx20-note@-1 {{because 't.a.b' would be invalid: reference to non-static member function must be called}}
+
+static_assert(C);
+static_assert(!C);
+static_assert(C); // cxx20-error {{static_assert failed}}
+  // cxx20-note@-1 {{because 'DotFollowingFunctionName::Bad' does not satisfy 'C'}}
+#endif
+} // namespace DotFollowingFunctionName
+
+namespace DotFollowingPointer {
+struct Good {
+  int begin();
+};
+using Bad = Holder *;
+
+template 
+constexpr auto f(T t) -> decltype((t.begin(), true)) { return true; }
+constexpr bool f(...) { return false; }
+
+static_assert(DotFollowingPointer::f(Good{}), "");
+static_assert(!DotFollowingPointer::f(Bad{}), "");
+
+#if __cplusplus >= 202002L
+template 
+concept C = requires(T t) { t.begin(); };
+  // cxx20-note@-1 {{because 't.begin()' would be invalid: member reference type 'Holder *' is a pointer}}
+
+static_assert(C);
+static_assert(!C);
+static_assert(C); // cxx20-error {{static_assert failed}}
+  // cxx20-note@-1 {{because 'DotFollowingPointer::Bad' (aka 'Holder *') does not satisfy 'C'}}
+#endif
+} // namespace DotFollowingPointer
Index: clang/lib/Sema/SemaExprMember.cpp
===
--- clang/lib/Sema/SemaExprMember.cpp
+++ clang/lib/Sema/SemaExprMember.cpp
@@ -1645,6 +1645,9 @@
   << BaseType << int(IsArrow) << BaseExpr.get()->getSourceRange()
   << FixItHint::CreateReplacement(OpLoc, "->");
 
+  if (S.isSFINAEContext())
+return ExprError();
+
   // Recurse as an -> access.
   IsArrow = true;
   return LookupMemberExpr(S, R, BaseExpr, IsArrow, OpLoc, SS,
Index: clang/lib/Sema/Sema.cpp
===
--- clang/lib/Sema/Sema.cpp
+++ clang/lib/Sema/Sema.cpp
@@ -2556,32 +2556,36 @@
 bool (*IsPlausibleResult)(QualType)) {
   SourceLocation Loc = E.get()->getExprLoc();
   SourceRange Range = E.get()->getSourceRange();
-
-  QualType ZeroArgCallTy;
   UnresolvedSet<4> Overloads;
-  if (tryExprAsCall(*E.get(), ZeroArgCallTy, Overloads) &&
-  !ZeroArgCallTy.isNull() &&
-  (!IsPlausibleResult || IsPlausibleResult(ZeroArgCallTy))) {
-// At this point, we know E is potentially callable with 0
-// arguments and that it returns something of a reasonable type,
-// so we can emit a fixit and carry on pretending that E was
-// actually a CallExpr.
-SourceLocation ParenInsertionLoc = getLocForEndOfToken(Range.getEnd());
-bool IsMV = IsCPUDispatchCPUSpecificMultiVersion(E.get());
-Diag(Loc, PD) << /*zero-arg*/ 1 << IsMV << Range
-  << (IsCallableWithAppend(E.get())
-  ? FixItHint::CreateInsertion(ParenInsertionLoc, "()")
-  : FixItHint());
-if (!IsMV)
-  notePlausibleOverloads(*this, Loc, Overloads, IsPlausibleResult);
-
-// FIXME: Try this before emitting the fixit, and suppress diagnostics
-// while doing so.
-E = BuildCallExpr(nullptr, E.get(), Range.getEnd(), None,
-  Range.getEnd().getLocWithOffset(1));
-return true;
-  }
 
+  // If this is a SFINAE context, don't try anything that might trigger ADL
+  // prematurely.
+  if (!isSFINAEContext()) {
+QualType ZeroArgCallTy;
+if (tryExprAsCall(*E.get(), ZeroArgCallTy, Overloads) &&
+!ZeroArgCallTy.isNull() &&
+(!IsPlausibleResult || IsPlausibleResult(ZeroArgCallTy))) {
+  // At this point, we know E is potentially callable with 0
+  // arguments 

[PATCH] D117603: [clang] Don't typo-fix an expression in a SFINAE context

2022-01-30 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone updated this revision to Diff 404381.
Quuxplusone added a comment.

Poke CI (clang-format failed).


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

https://reviews.llvm.org/D117603

Files:
  clang/lib/Sema/Sema.cpp
  clang/lib/Sema/SemaExprMember.cpp
  clang/test/SemaTemplate/pr52970.cpp

Index: clang/test/SemaTemplate/pr52970.cpp
===
--- /dev/null
+++ clang/test/SemaTemplate/pr52970.cpp
@@ -0,0 +1,63 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++14 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++17 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++20 -verify=cxx20 %s
+// expected-no-diagnostics
+
+struct Incomplete;
+template  struct Holder { T t; };
+
+namespace DotFollowingFunctionName {
+struct Good {
+  struct Nested {
+int b;
+  } a;
+};
+
+struct Bad {
+  Holder a();
+};
+
+template 
+constexpr auto f(T t) -> decltype((t.a.b, true)) { return true; }
+constexpr bool f(...) { return false; }
+
+static_assert(DotFollowingFunctionName::f(Good{}), "");
+static_assert(!DotFollowingFunctionName::f(Bad{}), "");
+
+#if __cplusplus >= 202002L
+template 
+concept C = requires(T t) { t.a.b; };
+  // cxx20-note@-1 {{because 't.a.b' would be invalid: reference to non-static member function must be called}}
+
+static_assert(C);
+static_assert(!C);
+static_assert(C); // cxx20-error {{static_assert failed}}
+  // cxx20-note@-1 {{because 'DotFollowingFunctionName::Bad' does not satisfy 'C'}}
+#endif
+} // namespace DotFollowingFunctionName
+
+namespace DotFollowingPointer {
+struct Good {
+  int begin();
+};
+using Bad = Holder *;
+
+template 
+constexpr auto f(T t) -> decltype((t.begin(), true)) { return true; }
+constexpr bool f(...) { return false; }
+
+static_assert(DotFollowingPointer::f(Good{}), "");
+static_assert(!DotFollowingPointer::f(Bad{}), "");
+
+#if __cplusplus >= 202002L
+template 
+concept C = requires(T t) { t.begin(); };
+  // cxx20-note@-1 {{because 't.begin()' would be invalid: member reference type 'Holder *' is a pointer}}
+
+static_assert(C);
+static_assert(!C);
+static_assert(C); // cxx20-error {{static_assert failed}}
+  // cxx20-note@-1 {{because 'DotFollowingPointer::Bad' (aka 'Holder *') does not satisfy 'C'}}
+#endif
+} // namespace DotFollowingPointer
Index: clang/lib/Sema/SemaExprMember.cpp
===
--- clang/lib/Sema/SemaExprMember.cpp
+++ clang/lib/Sema/SemaExprMember.cpp
@@ -1645,6 +1645,9 @@
   << BaseType << int(IsArrow) << BaseExpr.get()->getSourceRange()
   << FixItHint::CreateReplacement(OpLoc, "->");
 
+  if (S.isSFINAEContext())
+return ExprError();
+
   // Recurse as an -> access.
   IsArrow = true;
   return LookupMemberExpr(S, R, BaseExpr, IsArrow, OpLoc, SS,
Index: clang/lib/Sema/Sema.cpp
===
--- clang/lib/Sema/Sema.cpp
+++ clang/lib/Sema/Sema.cpp
@@ -2556,32 +2556,36 @@
 bool (*IsPlausibleResult)(QualType)) {
   SourceLocation Loc = E.get()->getExprLoc();
   SourceRange Range = E.get()->getSourceRange();
-
-  QualType ZeroArgCallTy;
   UnresolvedSet<4> Overloads;
-  if (tryExprAsCall(*E.get(), ZeroArgCallTy, Overloads) &&
-  !ZeroArgCallTy.isNull() &&
-  (!IsPlausibleResult || IsPlausibleResult(ZeroArgCallTy))) {
-// At this point, we know E is potentially callable with 0
-// arguments and that it returns something of a reasonable type,
-// so we can emit a fixit and carry on pretending that E was
-// actually a CallExpr.
-SourceLocation ParenInsertionLoc = getLocForEndOfToken(Range.getEnd());
-bool IsMV = IsCPUDispatchCPUSpecificMultiVersion(E.get());
-Diag(Loc, PD) << /*zero-arg*/ 1 << IsMV << Range
-  << (IsCallableWithAppend(E.get())
-  ? FixItHint::CreateInsertion(ParenInsertionLoc, "()")
-  : FixItHint());
-if (!IsMV)
-  notePlausibleOverloads(*this, Loc, Overloads, IsPlausibleResult);
-
-// FIXME: Try this before emitting the fixit, and suppress diagnostics
-// while doing so.
-E = BuildCallExpr(nullptr, E.get(), Range.getEnd(), None,
-  Range.getEnd().getLocWithOffset(1));
-return true;
-  }
 
+  // If this is a SFINAE context, don't try anything that might trigger ADL
+  // prematurely.
+  if (!isSFINAEContext()) {
+QualType ZeroArgCallTy;
+if (tryExprAsCall(*E.get(), ZeroArgCallTy, Overloads) &&
+!ZeroArgCallTy.isNull() &&
+(!IsPlausibleResult || IsPlausibleResult(ZeroArgCallTy))) {
+  // At this point, we know E is potentially callable with 0
+  // arguments and that it returns something of a reasonable type,
+  // so we can emit a fixit and carry on pretending that E was
+  // actually a CallExpr.
+  SourceLocation 

[PATCH] D117603: [clang] Don't typo-fix an expression in a SFINAE context

2022-01-29 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone updated this revision to Diff 404343.
Quuxplusone added a comment.

Move the regression test to clang/test/SemaTemplate/, alongside the one for 
D118552 . Also, make it test the error 
message wording.


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

https://reviews.llvm.org/D117603

Files:
  clang/lib/Sema/Sema.cpp
  clang/lib/Sema/SemaExprMember.cpp
  clang/test/SemaTemplate/pr52970.cpp

Index: clang/test/SemaTemplate/pr52970.cpp
===
--- /dev/null
+++ clang/test/SemaTemplate/pr52970.cpp
@@ -0,0 +1,63 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++14 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++17 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++20 -verify=cxx20 %s
+// expected-no-diagnostics
+
+struct Incomplete;
+template  struct Holder { T t; };
+
+namespace DotFollowingFunctionName {
+struct Good {
+  struct Nested {
+int b;
+  } a;
+};
+
+struct Bad {
+  Holder a();
+};
+
+template 
+constexpr auto f(T t) -> decltype((t.a.b, true)) { return true; }
+constexpr bool f(...) { return false; }
+
+static_assert(DotFollowingFunctionName::f(Good{}), "");
+static_assert(!DotFollowingFunctionName::f(Bad{}), "");
+
+#if __cplusplus >= 202002L
+template 
+concept C = requires(T t) { t.a.b; };
+  // cxx20-note@-1 {{because 't.a.b' would be invalid: reference to non-static member function must be called}}
+
+static_assert(C);
+static_assert(!C);
+static_assert(C); // cxx20-error {{static_assert failed}}
+  // cxx20-note@-1 {{because 'DotFollowingFunctionName::Bad' does not satisfy 'C'}}
+#endif
+} // namespace DotFollowingFunctionName
+
+namespace DotFollowingPointer {
+struct Good {
+  int begin();
+};
+using Bad = Holder *;
+
+template 
+constexpr auto f(T t) -> decltype((t.begin(), true)) { return true; }
+constexpr bool f(...) { return false; }
+
+static_assert(DotFollowingPointer::f(Good{}), "");
+static_assert(!DotFollowingPointer::f(Bad{}), "");
+
+#if __cplusplus >= 202002L
+template 
+concept C = requires(T t) { t.begin(); };
+  // cxx20-note@-1 {{because 't.begin()' would be invalid: member reference type 'Holder *' is a pointer}}
+
+static_assert(C);
+static_assert(!C);
+static_assert(C); // cxx20-error {{static_assert failed}}
+  // cxx20-note@-1 {{because 'DotFollowingPointer::Bad' (aka 'Holder *') does not satisfy 'C'}}
+#endif
+} // namespace DotFollowingPointer
Index: clang/lib/Sema/SemaExprMember.cpp
===
--- clang/lib/Sema/SemaExprMember.cpp
+++ clang/lib/Sema/SemaExprMember.cpp
@@ -1645,6 +1645,9 @@
   << BaseType << int(IsArrow) << BaseExpr.get()->getSourceRange()
   << FixItHint::CreateReplacement(OpLoc, "->");
 
+  if (S.isSFINAEContext())
+return ExprError();
+
   // Recurse as an -> access.
   IsArrow = true;
   return LookupMemberExpr(S, R, BaseExpr, IsArrow, OpLoc, SS,
Index: clang/lib/Sema/Sema.cpp
===
--- clang/lib/Sema/Sema.cpp
+++ clang/lib/Sema/Sema.cpp
@@ -2556,32 +2556,35 @@
 bool (*IsPlausibleResult)(QualType)) {
   SourceLocation Loc = E.get()->getExprLoc();
   SourceRange Range = E.get()->getSourceRange();
-
-  QualType ZeroArgCallTy;
   UnresolvedSet<4> Overloads;
-  if (tryExprAsCall(*E.get(), ZeroArgCallTy, Overloads) &&
-  !ZeroArgCallTy.isNull() &&
-  (!IsPlausibleResult || IsPlausibleResult(ZeroArgCallTy))) {
-// At this point, we know E is potentially callable with 0
-// arguments and that it returns something of a reasonable type,
-// so we can emit a fixit and carry on pretending that E was
-// actually a CallExpr.
-SourceLocation ParenInsertionLoc = getLocForEndOfToken(Range.getEnd());
-bool IsMV = IsCPUDispatchCPUSpecificMultiVersion(E.get());
-Diag(Loc, PD) << /*zero-arg*/ 1 << IsMV << Range
-  << (IsCallableWithAppend(E.get())
-  ? FixItHint::CreateInsertion(ParenInsertionLoc, "()")
-  : FixItHint());
-if (!IsMV)
-  notePlausibleOverloads(*this, Loc, Overloads, IsPlausibleResult);
-
-// FIXME: Try this before emitting the fixit, and suppress diagnostics
-// while doing so.
-E = BuildCallExpr(nullptr, E.get(), Range.getEnd(), None,
-  Range.getEnd().getLocWithOffset(1));
-return true;
-  }
 
+  // If this is a SFINAE context, don't try anything that might trigger ADL
+  // prematurely.
+  if (!isSFINAEContext()) {
+QualType ZeroArgCallTy;
+if (tryExprAsCall(*E.get(), ZeroArgCallTy, Overloads) &&
+!ZeroArgCallTy.isNull() &&
+(!IsPlausibleResult || IsPlausibleResult(ZeroArgCallTy))) {
+  // At this point, we know E is potentially callable with 0
+  // arguments and that it returns something of a 

[PATCH] D117603: [clang] Don't typo-fix an expression in a SFINAE context

2022-01-29 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone updated this revision to Diff 404341.
Quuxplusone added a comment.

It seems like we need `tryToRecoverWithCall` to always identify a diagnostic 
explaining the problem, so just short-circuit-returning `ExprError()` with no 
diagnostic is not acceptable. Let's try this version instead.
(This is also now based on top of D118552 .)


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

https://reviews.llvm.org/D117603

Files:
  clang/lib/Sema/Sema.cpp
  clang/lib/Sema/SemaExprMember.cpp
  clang/test/SemaCXX/PR52970.cpp

Index: clang/test/SemaCXX/PR52970.cpp
===
--- /dev/null
+++ clang/test/SemaCXX/PR52970.cpp
@@ -0,0 +1,57 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++14 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++17 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++20 -verify %s
+// expected-no-diagnostics
+
+struct Incomplete;
+template  struct Holder { T t; };
+
+namespace DotFollowingFunctionName {
+struct Good {
+  struct Nested {
+int b;
+  } a;
+};
+
+struct Bad {
+  Holder a();
+};
+
+template 
+constexpr auto f(T t) -> decltype((t.a.b, true)) { return true; }
+constexpr bool f(...) { return false; }
+
+static_assert(DotFollowingFunctionName::f(Good{}), "");
+static_assert(!DotFollowingFunctionName::f(Bad{}), "");
+
+#if __cplusplus >= 202002L
+template 
+concept C = requires(T t) { t.a.b; };
+
+static_assert(C);
+static_assert(!C);
+#endif
+} // namespace DotFollowingFunctionName
+
+namespace DotFollowingPointer {
+struct Good {
+  int begin();
+};
+using Bad = Holder *;
+
+template 
+constexpr auto f(T t) -> decltype((t.begin(), true)) { return true; }
+constexpr bool f(...) { return false; }
+
+static_assert(DotFollowingPointer::f(Good{}), "");
+static_assert(!DotFollowingPointer::f(Bad{}), "");
+
+#if __cplusplus >= 202002L
+template 
+concept C = requires(T t) { t.begin(); };
+
+static_assert(C);
+static_assert(!C);
+#endif
+} // namespace DotFollowingPointer
Index: clang/lib/Sema/SemaExprMember.cpp
===
--- clang/lib/Sema/SemaExprMember.cpp
+++ clang/lib/Sema/SemaExprMember.cpp
@@ -1645,6 +1645,9 @@
   << BaseType << int(IsArrow) << BaseExpr.get()->getSourceRange()
   << FixItHint::CreateReplacement(OpLoc, "->");
 
+  if (S.isSFINAEContext())
+return ExprError();
+
   // Recurse as an -> access.
   IsArrow = true;
   return LookupMemberExpr(S, R, BaseExpr, IsArrow, OpLoc, SS,
Index: clang/lib/Sema/Sema.cpp
===
--- clang/lib/Sema/Sema.cpp
+++ clang/lib/Sema/Sema.cpp
@@ -2556,32 +2556,35 @@
 bool (*IsPlausibleResult)(QualType)) {
   SourceLocation Loc = E.get()->getExprLoc();
   SourceRange Range = E.get()->getSourceRange();
-
-  QualType ZeroArgCallTy;
   UnresolvedSet<4> Overloads;
-  if (tryExprAsCall(*E.get(), ZeroArgCallTy, Overloads) &&
-  !ZeroArgCallTy.isNull() &&
-  (!IsPlausibleResult || IsPlausibleResult(ZeroArgCallTy))) {
-// At this point, we know E is potentially callable with 0
-// arguments and that it returns something of a reasonable type,
-// so we can emit a fixit and carry on pretending that E was
-// actually a CallExpr.
-SourceLocation ParenInsertionLoc = getLocForEndOfToken(Range.getEnd());
-bool IsMV = IsCPUDispatchCPUSpecificMultiVersion(E.get());
-Diag(Loc, PD) << /*zero-arg*/ 1 << IsMV << Range
-  << (IsCallableWithAppend(E.get())
-  ? FixItHint::CreateInsertion(ParenInsertionLoc, "()")
-  : FixItHint());
-if (!IsMV)
-  notePlausibleOverloads(*this, Loc, Overloads, IsPlausibleResult);
-
-// FIXME: Try this before emitting the fixit, and suppress diagnostics
-// while doing so.
-E = BuildCallExpr(nullptr, E.get(), Range.getEnd(), None,
-  Range.getEnd().getLocWithOffset(1));
-return true;
-  }
 
+  // If this is a SFINAE context, don't try anything that might trigger ADL
+  // prematurely.
+  if (!isSFINAEContext()) {
+QualType ZeroArgCallTy;
+if (tryExprAsCall(*E.get(), ZeroArgCallTy, Overloads) &&
+!ZeroArgCallTy.isNull() &&
+(!IsPlausibleResult || IsPlausibleResult(ZeroArgCallTy))) {
+  // At this point, we know E is potentially callable with 0
+  // arguments and that it returns something of a reasonable type,
+  // so we can emit a fixit and carry on pretending that E was
+  // actually a CallExpr.
+  SourceLocation ParenInsertionLoc = getLocForEndOfToken(Range.getEnd());
+  bool IsMV = IsCPUDispatchCPUSpecificMultiVersion(E.get());
+  Diag(Loc, PD) << /*zero-arg*/ 1 << IsMV << Range
+<< (IsCallableWithAppend(E.get())
+? 

[PATCH] D117603: [clang] Don't typo-fix an expression in a SFINAE context

2022-01-27 Thread Chuanqi Xu via Phabricator via cfe-commits
ChuanqiXu added a comment.

The problem looks similar with what we met in: 
https://github.com/llvm/llvm-project/issues/52909#issuecomment-1021631943
Maybe both of the problem could be solved at the same time.

> Anyone see how this patch might have caused a placeholder type to survive 
> into mangling, on Windows specifically?

I didn't have a Windows and I would leave the office for some time so I 
couldn't see it for a time.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D117603

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D117603: [clang] Don't typo-fix an expression in a SFINAE context

2022-01-27 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone reopened this revision.
Quuxplusone added a comment.
This revision is now accepted and ready to land.

I'm not sure if this caused
https://lab.llvm.org/buildbot/#/builders/60/builds/6350
https://lab.llvm.org/buildbot/#/builders/119/builds/7433
but I'm acting as if it did.

Anyone see how this patch might have caused a placeholder type to survive into 
mangling, //on Windows specifically?//

  Assertion failed: !E->hasPlaceholderType() && "unexpected placeholder", file 
C:\buildbot\as-builder-2\x-aarch64\llvm-project\clang\lib\Sema\SemaType.cpp, 
line 9031
  PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ 
and include the crash backtrace, preprocessed source, and associated run script.
  Stack dump:
  0.Program arguments: 
c:\\buildbot\\as-builder-2\\x-aarch64\\build\\bin\\clang++.exe -cc1 -triple 
aarch64-unknown-linux-gnu -emit-obj -mrelax-all --mrelax-relocations 
-disable-free -clear-ast-before-backend -main-file-name deduct_F.pass.cpp 
-mrelocation-model static -mframe-pointer=non-leaf -fmath-errno 
-ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 
-target-cpu generic -target-feature +neon -target-feature +v8a -target-abi 
aapcs -fallow-half-arguments-and-returns -mllvm 
-treat-scalable-fixed-error-as-warning -debugger-tuning=gdb -v 
-fcoverage-compilation-dir=C:\\buildbot\\as-builder-2\\x-aarch64\\build\\runtimes\\runtimes-bins\\libcxx\\test\\std\\utilities\\function.objects\\func.wrap\\func.wrap.func\\func.wrap.func.con
 -nostdinc++ -resource-dir 
c:\\buildbot\\as-builder-2\\x-aarch64\\build\\lib\\clang\\14.0.0 -I 
C:/buildbot/as-builder-2/x-aarch64/build/include\\aarch64-unknown-linux-gnu\\c++\\v1
 -I C:/buildbot/as-builder-2/x-aarch64/build/include/c++/v1 -I 
C:/buildbot/as-builder-2/x-aarch64/build/runtimes/runtimes-bins/libcxx\\include\\c++build
 -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -D __STDC_CONSTANT_MACROS -I 
C:/buildbot/as-builder-2/x-aarch64/llvm-project/libcxx\\test/support -D 
_LIBCPP_DISABLE_AVAILABILITY -D _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER -D 
_LIBCPP_HAS_THREAD_API_PTHREAD -D _LIBCPP_ABI_VERSION=1 -isysroot 
C:/buildbot/.aarch64-ubuntu -internal-isystem 
c:\\buildbot\\as-builder-2\\x-aarch64\\build\\lib\\clang\\14.0.0\\include 
-internal-isystem C:/buildbot/.aarch64-ubuntu/usr/local/include 
-internal-isystem 
C:/buildbot/.aarch64-ubuntu/usr/lib/gcc/aarch64-linux-gnu/5.4.0/../../../../aarch64-linux-gnu/include
 -internal-externc-isystem 
C:/buildbot/.aarch64-ubuntu/usr/include/aarch64-linux-gnu 
-internal-externc-isystem C:/buildbot/.aarch64-ubuntu/include 
-internal-externc-isystem C:/buildbot/.aarch64-ubuntu/usr/include -Werror -Wall 
-Wextra -Wshadow -Wundef -Wno-unused-command-line-argument -Wno-attributes 
-Wno-pessimizing-move -Wno-c++11-extensions -Wno-user-defined-literals 
-Wno-noexcept-type -Wno-atomic-alignment -Wsign-compare -Wunused-variable 
-Wunused-parameter -Wunreachable-code -Wno-unused-local-typedef 
-Werror=thread-safety -Wuser-defined-warnings -Wno-macro-redefined 
-Wno-macro-redefined -std=c++2b -fdeprecated-macro 
-fdebug-compilation-dir=C:\\buildbot\\as-builder-2\\x-aarch64\\build\\runtimes\\runtimes-bins\\libcxx\\test\\std\\utilities\\function.objects\\func.wrap\\func.wrap.func\\func.wrap.func.con
 -ferror-limit 19 -fcoroutines-ts -fno-signed-char -fgnuc-version=4.2.1 
-fcxx-exceptions -fexceptions -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o 
C:\\Users\\buildbot\\AppData\\Local\\Temp\\lit-tmp-ex1gsg43\\deduct_F-0ed146.o 
-x c++ 
C:\\buildbot\\as-builder-2\\x-aarch64\\llvm-project\\libcxx\\test\\std\\utilities\\function.objects\\func.wrap\\func.wrap.func\\func.wrap.func.con\\deduct_F.pass.cpp
  1.
C:\buildbot\as-builder-2\x-aarch64\llvm-project\libcxx\test\std\utilities\function.objects\func.wrap\func.wrap.func\func.wrap.func.con\deduct_F.pass.cpp:136:37:
 current parser token ')'
   #0 0x7ff65e92b105 
(c:\buildbot\as-builder-2\x-aarch64\build\bin\clang++.exe+0xfdb105)
   #1 0x7fffb07cd167 (C:\Windows\SYSTEM32\ucrtbase.DLL+0x6d167)
   #2 0x7fffb07cdff1 (C:\Windows\SYSTEM32\ucrtbase.DLL+0x6dff1)
  [...]


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D117603

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D117603: [clang] Don't typo-fix an expression in a SFINAE context

2022-01-27 Thread Arthur O'Dwyer via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rG9be5f4d5afd9: [clang] Dont typo-fix an expression in a 
SFINAE context. (authored by arthur.j.odwyer).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D117603

Files:
  clang/lib/Sema/Sema.cpp
  clang/lib/Sema/SemaExprMember.cpp
  clang/test/SemaCXX/PR52970.cpp


Index: clang/test/SemaCXX/PR52970.cpp
===
--- /dev/null
+++ clang/test/SemaCXX/PR52970.cpp
@@ -0,0 +1,57 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++14 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++17 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++20 -verify %s
+// expected-no-diagnostics
+
+struct Incomplete;
+template  struct Holder { T t; };
+
+namespace DotFollowingFunctionName {
+struct Good {
+  struct Nested {
+int b;
+  } a;
+};
+
+struct Bad {
+  Holder a();
+};
+
+template 
+constexpr auto f(T t) -> decltype((t.a.b, true)) { return true; }
+constexpr bool f(...) { return false; }
+
+static_assert(DotFollowingFunctionName::f(Good{}), "");
+static_assert(!DotFollowingFunctionName::f(Bad{}), "");
+
+#if __cplusplus >= 202002L
+template 
+concept C = requires(T t) { t.a.b; };
+
+static_assert(C);
+static_assert(!C);
+#endif
+} // namespace DotFollowingFunctionName
+
+namespace DotFollowingPointer {
+struct Good {
+  int begin();
+};
+using Bad = Holder *;
+
+template 
+constexpr auto f(T t) -> decltype((t.begin(), true)) { return true; }
+constexpr bool f(...) { return false; }
+
+static_assert(DotFollowingPointer::f(Good{}), "");
+static_assert(!DotFollowingPointer::f(Bad{}), "");
+
+#if __cplusplus >= 202002L
+template 
+concept C = requires(T t) { t.begin(); };
+
+static_assert(C);
+static_assert(!C);
+#endif
+} // namespace DotFollowingPointer
Index: clang/lib/Sema/SemaExprMember.cpp
===
--- clang/lib/Sema/SemaExprMember.cpp
+++ clang/lib/Sema/SemaExprMember.cpp
@@ -1645,6 +1645,9 @@
   << BaseType << int(IsArrow) << BaseExpr.get()->getSourceRange()
   << FixItHint::CreateReplacement(OpLoc, "->");
 
+  if (S.isSFINAEContext())
+return ExprError();
+
   // Recurse as an -> access.
   IsArrow = true;
   return LookupMemberExpr(S, R, BaseExpr, IsArrow, OpLoc, SS,
Index: clang/lib/Sema/Sema.cpp
===
--- clang/lib/Sema/Sema.cpp
+++ clang/lib/Sema/Sema.cpp
@@ -2554,6 +2554,11 @@
 bool Sema::tryToRecoverWithCall(ExprResult , const PartialDiagnostic ,
 bool ForceComplain,
 bool (*IsPlausibleResult)(QualType)) {
+  if (isSFINAEContext()) {
+// If this is a SFINAE context, don't try anything that might trigger ADL
+// prematurely.
+return false;
+  }
   SourceLocation Loc = E.get()->getExprLoc();
   SourceRange Range = E.get()->getSourceRange();
 


Index: clang/test/SemaCXX/PR52970.cpp
===
--- /dev/null
+++ clang/test/SemaCXX/PR52970.cpp
@@ -0,0 +1,57 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++14 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++17 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++20 -verify %s
+// expected-no-diagnostics
+
+struct Incomplete;
+template  struct Holder { T t; };
+
+namespace DotFollowingFunctionName {
+struct Good {
+  struct Nested {
+int b;
+  } a;
+};
+
+struct Bad {
+  Holder a();
+};
+
+template 
+constexpr auto f(T t) -> decltype((t.a.b, true)) { return true; }
+constexpr bool f(...) { return false; }
+
+static_assert(DotFollowingFunctionName::f(Good{}), "");
+static_assert(!DotFollowingFunctionName::f(Bad{}), "");
+
+#if __cplusplus >= 202002L
+template 
+concept C = requires(T t) { t.a.b; };
+
+static_assert(C);
+static_assert(!C);
+#endif
+} // namespace DotFollowingFunctionName
+
+namespace DotFollowingPointer {
+struct Good {
+  int begin();
+};
+using Bad = Holder *;
+
+template 
+constexpr auto f(T t) -> decltype((t.begin(), true)) { return true; }
+constexpr bool f(...) { return false; }
+
+static_assert(DotFollowingPointer::f(Good{}), "");
+static_assert(!DotFollowingPointer::f(Bad{}), "");
+
+#if __cplusplus >= 202002L
+template 
+concept C = requires(T t) { t.begin(); };
+
+static_assert(C);
+static_assert(!C);
+#endif
+} // namespace DotFollowingPointer
Index: clang/lib/Sema/SemaExprMember.cpp
===
--- clang/lib/Sema/SemaExprMember.cpp
+++ clang/lib/Sema/SemaExprMember.cpp
@@ -1645,6 +1645,9 @@
   << BaseType << int(IsArrow) << BaseExpr.get()->getSourceRange()
   << FixItHint::CreateReplacement(OpLoc, "->");
 
+  if (S.isSFINAEContext())

[PATCH] D117603: [clang] Don't typo-fix an expression in a SFINAE context

2022-01-25 Thread Nathan Sidwell via Phabricator via cfe-commits
urnathan accepted this revision.
urnathan added a comment.
This revision is now accepted and ready to land.

go for it


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D117603

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D117603: [clang] Don't typo-fix an expression in a SFINAE context

2022-01-25 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone added reviewers: ChuanqiXu, urnathan, hokein, dblaikie.
Quuxplusone added a comment.

Add some more reviewers who've touched SemaCXX recently. Ping! If no objections 
are forthcoming, I'd like to land this on Friday morning.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D117603

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D117603: [clang] Don't typo-fix an expression in a SFINAE context

2022-01-20 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone updated this revision to Diff 401652.
Quuxplusone added a comment.

Clang-formatted.

@mizvekov or @rsmith: ping?
I'd like to get this in before Feb 1, which is the release/14.x branch date 
AFAIK; because it affects workarounds in libc++ and thus makes a difference 
whether we will be able to remove the workarounds in version 16 or version 17.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D117603

Files:
  clang/lib/Sema/Sema.cpp
  clang/lib/Sema/SemaExprMember.cpp
  clang/test/SemaCXX/PR52970.cpp


Index: clang/test/SemaCXX/PR52970.cpp
===
--- /dev/null
+++ clang/test/SemaCXX/PR52970.cpp
@@ -0,0 +1,57 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++14 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++17 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++20 -verify %s
+// expected-no-diagnostics
+
+struct Incomplete;
+template  struct Holder { T t; };
+
+namespace DotFollowingFunctionName {
+struct Good {
+  struct Nested {
+int b;
+  } a;
+};
+
+struct Bad {
+  Holder a();
+};
+
+template 
+constexpr auto f(T t) -> decltype((t.a.b, true)) { return true; }
+constexpr bool f(...) { return false; }
+
+static_assert(DotFollowingFunctionName::f(Good{}), "");
+static_assert(!DotFollowingFunctionName::f(Bad{}), "");
+
+#if __cplusplus >= 202002L
+template 
+concept C = requires(T t) { t.a.b; };
+
+static_assert(C);
+static_assert(!C);
+#endif
+} // namespace DotFollowingFunctionName
+
+namespace DotFollowingPointer {
+struct Good {
+  int begin();
+};
+using Bad = Holder *;
+
+template 
+constexpr auto f(T t) -> decltype((t.begin(), true)) { return true; }
+constexpr bool f(...) { return false; }
+
+static_assert(DotFollowingPointer::f(Good{}), "");
+static_assert(!DotFollowingPointer::f(Bad{}), "");
+
+#if __cplusplus >= 202002L
+template 
+concept C = requires(T t) { t.begin(); };
+
+static_assert(C);
+static_assert(!C);
+#endif
+} // namespace DotFollowingPointer
Index: clang/lib/Sema/SemaExprMember.cpp
===
--- clang/lib/Sema/SemaExprMember.cpp
+++ clang/lib/Sema/SemaExprMember.cpp
@@ -1645,6 +1645,9 @@
   << BaseType << int(IsArrow) << BaseExpr.get()->getSourceRange()
   << FixItHint::CreateReplacement(OpLoc, "->");
 
+  if (S.isSFINAEContext())
+return ExprError();
+
   // Recurse as an -> access.
   IsArrow = true;
   return LookupMemberExpr(S, R, BaseExpr, IsArrow, OpLoc, SS,
Index: clang/lib/Sema/Sema.cpp
===
--- clang/lib/Sema/Sema.cpp
+++ clang/lib/Sema/Sema.cpp
@@ -2552,6 +2552,11 @@
 bool Sema::tryToRecoverWithCall(ExprResult , const PartialDiagnostic ,
 bool ForceComplain,
 bool (*IsPlausibleResult)(QualType)) {
+  if (isSFINAEContext()) {
+// If this is a SFINAE context, don't try anything that might trigger ADL
+// prematurely.
+return false;
+  }
   SourceLocation Loc = E.get()->getExprLoc();
   SourceRange Range = E.get()->getSourceRange();
 


Index: clang/test/SemaCXX/PR52970.cpp
===
--- /dev/null
+++ clang/test/SemaCXX/PR52970.cpp
@@ -0,0 +1,57 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++14 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++17 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++20 -verify %s
+// expected-no-diagnostics
+
+struct Incomplete;
+template  struct Holder { T t; };
+
+namespace DotFollowingFunctionName {
+struct Good {
+  struct Nested {
+int b;
+  } a;
+};
+
+struct Bad {
+  Holder a();
+};
+
+template 
+constexpr auto f(T t) -> decltype((t.a.b, true)) { return true; }
+constexpr bool f(...) { return false; }
+
+static_assert(DotFollowingFunctionName::f(Good{}), "");
+static_assert(!DotFollowingFunctionName::f(Bad{}), "");
+
+#if __cplusplus >= 202002L
+template 
+concept C = requires(T t) { t.a.b; };
+
+static_assert(C);
+static_assert(!C);
+#endif
+} // namespace DotFollowingFunctionName
+
+namespace DotFollowingPointer {
+struct Good {
+  int begin();
+};
+using Bad = Holder *;
+
+template 
+constexpr auto f(T t) -> decltype((t.begin(), true)) { return true; }
+constexpr bool f(...) { return false; }
+
+static_assert(DotFollowingPointer::f(Good{}), "");
+static_assert(!DotFollowingPointer::f(Bad{}), "");
+
+#if __cplusplus >= 202002L
+template 
+concept C = requires(T t) { t.begin(); };
+
+static_assert(C);
+static_assert(!C);
+#endif
+} // namespace DotFollowingPointer
Index: clang/lib/Sema/SemaExprMember.cpp
===
--- clang/lib/Sema/SemaExprMember.cpp
+++ clang/lib/Sema/SemaExprMember.cpp
@@ -1645,6 +1645,9 @@
  

[PATCH] D117603: [clang] Don't typo-fix an expression in a SFINAE context

2022-01-18 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone created this revision.
Quuxplusone added reviewers: ldionne, rsmith, leonardchan, mizvekov.
Quuxplusone added a project: clang.
Quuxplusone requested review of this revision.
Herald added a subscriber: cfe-commits.

If this is a SFINAE context, then continuing to look up names (in particular, 
to treat a non-function as a function, and then do ADL) might too-eagerly 
complete a type that it's not safe to complete right now. We should just say 
"okay, that's a substitution failure" and not do any more work than absolutely 
required.

Fixes https://github.com/llvm/llvm-project/issues/52970

  


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D117603

Files:
  clang/lib/Sema/Sema.cpp
  clang/lib/Sema/SemaExprMember.cpp
  clang/test/SemaCXX/PR52970.cpp


Index: clang/test/SemaCXX/PR52970.cpp
===
--- /dev/null
+++ clang/test/SemaCXX/PR52970.cpp
@@ -0,0 +1,59 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++14 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++17 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++20 -verify %s
+// expected-no-diagnostics
+
+struct Incomplete;
+template struct Holder { T t; };
+
+namespace DotFollowingFunctionName {
+  struct Good {
+struct Nested {
+  int b;
+} a;
+  };
+
+  struct Bad {
+Holder a();
+  };
+
+  template
+  constexpr auto f(T t) -> decltype((t.a.b, true))
+{ return true; }
+  constexpr bool f(...) { return false; }
+
+  static_assert(DotFollowingFunctionName::f(Good{}), "");
+  static_assert(!DotFollowingFunctionName::f(Bad{}), "");
+
+#if __cplusplus >= 202002L
+  template
+  concept C = requires (T t) { t.a.b; };
+
+  static_assert(C);
+  static_assert(!C);
+#endif
+}
+
+namespace DotFollowingPointer {
+  struct Good {
+int begin();
+  };
+  using Bad = Holder*;
+
+  template
+  constexpr auto f(T t) -> decltype((t.begin(), true))
+{ return true; }
+  constexpr bool f(...) { return false; }
+
+  static_assert(DotFollowingPointer::f(Good{}), "");
+  static_assert(!DotFollowingPointer::f(Bad{}), "");
+
+#if __cplusplus >= 202002L
+  template
+  concept C = requires (T t) { t.begin(); };
+
+  static_assert(C);
+  static_assert(!C);
+#endif
+}
Index: clang/lib/Sema/SemaExprMember.cpp
===
--- clang/lib/Sema/SemaExprMember.cpp
+++ clang/lib/Sema/SemaExprMember.cpp
@@ -1645,6 +1645,9 @@
   << BaseType << int(IsArrow) << BaseExpr.get()->getSourceRange()
   << FixItHint::CreateReplacement(OpLoc, "->");
 
+  if (S.isSFINAEContext())
+return ExprError();
+
   // Recurse as an -> access.
   IsArrow = true;
   return LookupMemberExpr(S, R, BaseExpr, IsArrow, OpLoc, SS,
Index: clang/lib/Sema/Sema.cpp
===
--- clang/lib/Sema/Sema.cpp
+++ clang/lib/Sema/Sema.cpp
@@ -2552,6 +2552,10 @@
 bool Sema::tryToRecoverWithCall(ExprResult , const PartialDiagnostic ,
 bool ForceComplain,
 bool (*IsPlausibleResult)(QualType)) {
+  if (isSFINAEContext()) {
+// If this is a SFINAE context, don't try anything that might trigger ADL 
prematurely.
+return false;
+  }
   SourceLocation Loc = E.get()->getExprLoc();
   SourceRange Range = E.get()->getSourceRange();
 


Index: clang/test/SemaCXX/PR52970.cpp
===
--- /dev/null
+++ clang/test/SemaCXX/PR52970.cpp
@@ -0,0 +1,59 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++14 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++17 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++20 -verify %s
+// expected-no-diagnostics
+
+struct Incomplete;
+template struct Holder { T t; };
+
+namespace DotFollowingFunctionName {
+  struct Good {
+struct Nested {
+  int b;
+} a;
+  };
+
+  struct Bad {
+Holder a();
+  };
+
+  template
+  constexpr auto f(T t) -> decltype((t.a.b, true))
+{ return true; }
+  constexpr bool f(...) { return false; }
+
+  static_assert(DotFollowingFunctionName::f(Good{}), "");
+  static_assert(!DotFollowingFunctionName::f(Bad{}), "");
+
+#if __cplusplus >= 202002L
+  template
+  concept C = requires (T t) { t.a.b; };
+
+  static_assert(C);
+  static_assert(!C);
+#endif
+}
+
+namespace DotFollowingPointer {
+  struct Good {
+int begin();
+  };
+  using Bad = Holder*;
+
+  template
+  constexpr auto f(T t) -> decltype((t.begin(), true))
+{ return true; }
+  constexpr bool f(...) { return false; }
+
+  static_assert(DotFollowingPointer::f(Good{}), "");
+  static_assert(!DotFollowingPointer::f(Bad{}), "");
+
+#if __cplusplus >= 202002L
+  template
+  concept C = requires (T t) { t.begin(); };
+
+  static_assert(C);
+  static_assert(!C);
+#endif
+}
Index: