]> granicus.if.org Git - clang/commitdiff
Fix for Bug 33471: Preventing operator auto from resolving to a template operator.
authorErich Keane <erich.keane@intel.com>
Tue, 20 Jun 2017 17:38:07 +0000 (17:38 +0000)
committerErich Keane <erich.keane@intel.com>
Tue, 20 Jun 2017 17:38:07 +0000 (17:38 +0000)
As the bug report says,
struct A
{

  template<typename T> operator T();

};

void foo()
{

  A().operator auto();

}

causes: "undeduced type in IR-generation
UNREACHABLE executed at llvm/tools/clang/lib/CodeGen/CodeGenFunction.cpp:208!"

The problem is that in this case, "T" is being deduced as "auto",
which I believe is incorrect.

The 'operator auto' implementation in Clang is standards compliant, however
there is a defect report against core (1670).

Differential Revision: https://reviews.llvm.org/D34370

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@305812 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaLookup.cpp
test/SemaCXX/cxx1y-deduced-return-type.cpp

index 1fb25f4e0e7c93bf3e236ff04111a29047a68f3e..9f657a446c02a43a4ffc4024b197dfbc5516ff5c 100644 (file)
@@ -862,6 +862,16 @@ static bool LookupDirect(Sema &S, LookupResult &R, const DeclContext *DC) {
   if (!Record->isCompleteDefinition())
     return Found;
 
+  // For conversion operators, 'operator auto' should only match
+  // 'operator auto'.  Since 'auto' is not a type, it shouldn't be considered
+  // as a candidate for template substitution.
+  auto *ContainedDeducedType =
+      R.getLookupName().getCXXNameType()->getContainedDeducedType();
+  if (R.getLookupName().getNameKind() ==
+          DeclarationName::CXXConversionFunctionName &&
+      ContainedDeducedType && ContainedDeducedType->isUndeducedType())
+    return Found;
+
   for (CXXRecordDecl::conversion_iterator U = Record->conversion_begin(),
          UEnd = Record->conversion_end(); U != UEnd; ++U) {
     FunctionTemplateDecl *ConvTemplate = dyn_cast<FunctionTemplateDecl>(*U);
index bfe0ab9dcdbc2624e4f63a8c1b0594b4ee87ebc3..13ff751acae4d3349a8ad48379577ac822b0432c 100644 (file)
@@ -55,6 +55,25 @@ auto b(bool k) {
   return "goodbye";
 }
 
+// Allow 'operator auto' to call only the explicit operator auto.
+struct BothOps {
+  template <typename T> operator T();
+  template <typename T> operator T *();
+  operator auto() { return 0; }
+  operator auto *() { return this; }
+};
+struct JustTemplateOp {
+  template <typename T> operator T();
+  template <typename T> operator T *();
+};
+
+auto c() {
+  BothOps().operator auto(); // ok
+  BothOps().operator auto *(); // ok
+  JustTemplateOp().operator auto(); // expected-error {{no member named 'operator auto' in 'JustTemplateOp'}}
+  JustTemplateOp().operator auto *(); // expected-error {{no member named 'operator auto *' in 'JustTemplateOp'}}
+}
+
 auto *ptr_1() {
   return 100; // expected-error {{cannot deduce return type 'auto *' from returned value of type 'int'}}
 }