EricWF updated this revision to Diff 181829.
EricWF marked an inline comment as done.
EricWF added a comment.

Address inline comments.


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

https://reviews.llvm.org/D56731

Files:
  include/clang/Basic/DiagnosticGroups.td
  include/clang/Basic/DiagnosticSemaKinds.td
  lib/Sema/SemaInit.cpp
  test/SemaCXX/cxx1z-class-template-argument-deduction.cpp

Index: test/SemaCXX/cxx1z-class-template-argument-deduction.cpp
===================================================================
--- test/SemaCXX/cxx1z-class-template-argument-deduction.cpp
+++ test/SemaCXX/cxx1z-class-template-argument-deduction.cpp
@@ -409,6 +409,61 @@
 
 }
 
+#pragma clang diagnostic push
+#pragma clang diagnostic warning "-Wimplicit-ctad"
+namespace test_implicit_ctad_warning {
+
+template <class T>
+struct Tag {};
+
+template <class T>
+struct NoExplicit {
+  NoExplicit(T) {}
+  NoExplicit(T, int) {}
+};
+
+// expected-warning@+1 {{using class template argument deduction for 'NoExplicit' that has no user-defined deduction guides}}
+NoExplicit ne(42);
+
+template <class U>
+struct HasExplicit {
+  HasExplicit(U) {}
+  HasExplicit(U, int) {}
+};
+template <class U> HasExplicit(U, int) -> HasExplicit<Tag<U>>;
+
+HasExplicit he(42);
+
+// Motivating examples from (taken from Stephan Lavavej's 2018 Cppcon talk)
+template<class T, class U>
+struct AmateurPair {
+    T first; U second;
+    explicit AmateurPair(const T& t, const U& u) {}
+};
+// expected-warning@+1 {{using class template argument deduction for 'AmateurPair' that has no user-defined deduction guides}}
+AmateurPair p1(42, "hello world"); // deduces to Pair<int, char[12]>
+
+template<class T, class U>
+struct AmateurPair2 {
+    T first; U second;
+    explicit AmateurPair2(T t, U u)  {}
+};
+// expected-warning@+1 {{using class template argument deduction for 'AmateurPair2' that has no user-defined deduction guides}}
+AmateurPair2 p2(42, "hello world"); // deduces to Pair2<int, const char*>
+
+template <class T, class U>
+struct ProPair {
+  T first; U second;
+    explicit ProPair(T const& t, U  const& u)  {}
+};
+template<class T1, class T2>
+ProPair(T1, T2) -> ProPair<T1, T2>;
+ProPair p3(42, "hello world"); // deduces to ProPair<int, const char*>
+static_assert(__is_same(decltype(p3), ProPair<int, const char*>));
+
+}
+#pragma clang diagnostic pop
+
 #else
 
 // expected-no-diagnostics
Index: lib/Sema/SemaInit.cpp
===================================================================
--- lib/Sema/SemaInit.cpp
+++ lib/Sema/SemaInit.cpp
@@ -9264,9 +9264,15 @@
   OverloadCandidateSet Candidates(Kind.getLocation(),
                                   OverloadCandidateSet::CSK_Normal);
   OverloadCandidateSet::iterator Best;
+
+  // Record if at least one user-defined deduction guide was considered
+  bool HasUserDefinedDeductionGuideCandidate = false;
+
   auto tryToResolveOverload =
       [&](bool OnlyListConstructors) -> OverloadingResult {
     Candidates.clear(OverloadCandidateSet::CSK_Normal);
+    HasUserDefinedDeductionGuideCandidate = false;
+
     for (auto I = Guides.begin(), E = Guides.end(); I != E; ++I) {
       NamedDecl *D = (*I)->getUnderlyingDecl();
       if (D->isInvalidDecl())
@@ -9278,6 +9284,9 @@
       if (!GD)
         continue;
 
+      if (!GD->isImplicit())
+        HasUserDefinedDeductionGuideCandidate = true;
+
       // C++ [over.match.ctor]p1: (non-list copy-initialization from non-class)
       //   For copy-initialization, the candidate functions are all the
       //   converting constructors (12.3.1) of that class.
@@ -9430,5 +9439,15 @@
   Diag(TSInfo->getTypeLoc().getBeginLoc(),
        diag::warn_cxx14_compat_class_template_argument_deduction)
       << TSInfo->getTypeLoc().getSourceRange() << 1 << DeducedType;
+
+
+  // -Wimplicit-ctad: Warn if CTAD was used on a type that does not have any
+  // user-defined deduction guides.
+  if (!HasUserDefinedDeductionGuideCandidate) {
+    Diag(TSInfo->getTypeLoc().getBeginLoc(),
+         diag::warn_class_template_argument_deduction_no_user_defined_guides)
+        << TemplateName;
+  }
+
   return DeducedType;
 }
Index: include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- include/clang/Basic/DiagnosticSemaKinds.td
+++ include/clang/Basic/DiagnosticSemaKinds.td
@@ -2125,6 +2125,9 @@
   "class template argument deduction is incompatible with C++ standards "
   "before C++17%select{|; for compatibility, use explicit type name %1}0">,
   InGroup<CXXPre17Compat>, DefaultIgnore;
+def warn_class_template_argument_deduction_no_user_defined_guides : Warning<
+  "using class template argument deduction for %0 that has no user-defined deduction guides" >,
+  InGroup<ImplicitCTADUsage>, DefaultIgnore;
 
 // C++14 deduced return types
 def err_auto_fn_deduction_failure : Error<
Index: include/clang/Basic/DiagnosticGroups.td
===================================================================
--- include/clang/Basic/DiagnosticGroups.td
+++ include/clang/Basic/DiagnosticGroups.td
@@ -1050,3 +1050,5 @@
 
 // A group for cross translation unit static analysis related warnings.
 def CrossTU : DiagGroup<"ctu">;
+
+def ImplicitCTADUsage : DiagGroup<"implicit-ctad">;
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to