EricWF created this revision.
EricWF added reviewers: rsmith, james.dennett, gromer.

Some style guides want to allow using CTAD only on types that "opt-in"; i.e. on 
types that are designed to support it and not just types that *happen* to work 
with it.

This patch implements the `-Wimplicit-ctad` warning, which is off by default, 
which warns when CTAD is used on a type that does not define any deduction 
guides.


Repository:
  rC Clang

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,35 @@
 
 }
 
+#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 {{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);
+
+
+}
+#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 a user-declared deduction guide was considered
+  bool HasUserDeclaredDeductionGuideCandidate = false;
+
   auto tryToResolveOverload =
       [&](bool OnlyListConstructors) -> OverloadingResult {
     Candidates.clear(OverloadCandidateSet::CSK_Normal);
+    HasUserDeclaredDeductionGuideCandidate = false;
+
     for (auto I = Guides.begin(), E = Guides.end(); I != E; ++I) {
       NamedDecl *D = (*I)->getUnderlyingDecl();
       if (D->isInvalidDecl())
@@ -9278,6 +9284,8 @@
       if (!GD)
         continue;
 
+      HasUserDeclaredDeductionGuideCandidate |= !GD->isImplicit();
+
       // 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 +9438,14 @@
   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
+  if (!HasUserDeclaredDeductionGuideCandidate) {
+    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<
+  "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