diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2018-07-22 05:21:47 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2018-07-22 05:21:47 +0000 |
commit | cc4ad95c303daf27ba3a1815eb81b2c832383ba2 (patch) | |
tree | c740130471721ea30c00d8b05108a5685c3ff619 | |
parent | b8b21d2fcac48ef26d3af325cc4d6cf4bddb78f7 (diff) | |
download | bcm5719-llvm-cc4ad95c303daf27ba3a1815eb81b2c832383ba2.tar.gz bcm5719-llvm-cc4ad95c303daf27ba3a1815eb81b2c832383ba2.zip |
PR38257: don't perform ADL when instantiating a unary & operator that turns out
to be forming a pointer-to-member.
llvm-svn: 337653
-rw-r--r-- | clang/include/clang/Sema/Sema.h | 1 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Sema/TreeTransform.h | 8 | ||||
-rw-r--r-- | clang/test/SemaTemplate/argument-dependent-lookup.cpp | 45 |
4 files changed, 52 insertions, 4 deletions
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 0aa1fc42c6a..ab934223b8f 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -4262,6 +4262,7 @@ public: ExprResult ActOnUnaryOp(Scope *S, SourceLocation OpLoc, tok::TokenKind Op, Expr *Input); + bool isQualifiedMemberAccess(Expr *E); QualType CheckAddressOfOperand(ExprResult &Operand, SourceLocation OpLoc); ExprResult CreateUnaryExprOrTypeTraitExpr(TypeSourceInfo *TInfo, diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index e350517946e..fc70c882c22 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -12809,7 +12809,7 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc, /// Determine whether the given expression is a qualified member /// access expression, of a form that could be turned into a pointer to member /// with the address-of operator. -static bool isQualifiedMemberAccess(Expr *E) { +bool Sema::isQualifiedMemberAccess(Expr *E) { if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) { if (!DRE->getQualifier()) return false; diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 5ed92aea32c..19567397112 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -12658,9 +12658,11 @@ TreeTransform<Derived>::RebuildCXXOperatorCallExpr(OverloadedOperatorKind Op, // -> is never a builtin operation. return SemaRef.BuildOverloadedArrowExpr(nullptr, First, OpLoc); } else if (Second == nullptr || isPostIncDec) { - if (!First->getType()->isOverloadableType()) { - // The argument is not of overloadable type, so try to create a - // built-in unary operation. + if (!First->getType()->isOverloadableType() || + (Op == OO_Amp && getSema().isQualifiedMemberAccess(First))) { + // The argument is not of overloadable type, or this is an expression + // of the form &Class::member, so try to create a built-in unary + // operation. UnaryOperatorKind Opc = UnaryOperator::getOverloadedOpcode(Op, isPostIncDec); diff --git a/clang/test/SemaTemplate/argument-dependent-lookup.cpp b/clang/test/SemaTemplate/argument-dependent-lookup.cpp new file mode 100644 index 00000000000..d1603d56b96 --- /dev/null +++ b/clang/test/SemaTemplate/argument-dependent-lookup.cpp @@ -0,0 +1,45 @@ +// RUN: %clang_cc1 -verify %s +// RUN: %clang_cc1 -verify %s -DHAVE_UNQUALIFIED_LOOKUP_RESULTS +// expected-no-diagnostics + +namespace address_of { +#ifdef HAVE_UNQUALIFIED_LOOKUP_RESULTS + struct Q {}; + void operator&(Q); +#endif + + template<typename T> struct A { + static constexpr auto x = &T::value; + }; + + template<typename T> struct B { + constexpr int operator&() { return 123; } + }; + + template<typename T> struct C { + static_assert(sizeof(T) == 123, ""); + }; + + struct X1 { + static B<X1> value; + }; + struct X2 : B<X2> { + enum E { value }; + friend constexpr int operator&(E) { return 123; } + }; + + struct Y1 { + C<int> *value; + }; + struct Y2 { + C<int> value(); + }; + + // ok, uses ADL to find operator&: + static_assert(A<X1>::x == 123, ""); + static_assert(A<X2>::x == 123, ""); + + // ok, does not use ADL so does not instantiate C<T>: + static_assert(A<Y1>::x == &Y1::value, ""); + static_assert(A<Y2>::x == &Y2::value, ""); +} |