]> granicus.if.org Git - clang/commitdiff
Fix for PR21758
authorRichard Trieu <rtrieu@google.com>
Sat, 20 Dec 2014 02:42:08 +0000 (02:42 +0000)
committerRichard Trieu <rtrieu@google.com>
Sat, 20 Dec 2014 02:42:08 +0000 (02:42 +0000)
When a non-type template argument expression needs a conversion to change it
into the argument type, preserve that information by remaking the
TemplateArgument with an expression that has those conversions.  Also a small
fix to template type diffing to handle the extra conversions in some cases.

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

lib/AST/ASTDiagnostic.cpp
lib/Sema/SemaTemplate.cpp
test/Misc/diag-template-diffing.cpp

index 3212359db183bb2f1423110c1041e2345e1e1b6d..ed823f5537a8123213f0cf8ff19bfaf940a1340a 100644 (file)
@@ -1655,11 +1655,14 @@ class TemplateDiff {
     }
     Unbold();
   }
-  
+
   /// HasExtraInfo - Returns true if E is not an integer literal or the
   /// negation of an integer literal
   bool HasExtraInfo(Expr *E) {
     if (!E) return false;
+
+    E = E->IgnoreImpCasts();
+
     if (isa<IntegerLiteral>(E)) return false;
 
     if (UnaryOperator *UO = dyn_cast<UnaryOperator>(E))
index 67c36a5fb5e94d73fa1856253ae23ee6d71c33f4..209964922684e88b4afa921e689bff8a4fa4e787 100644 (file)
@@ -3433,6 +3433,13 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param,
       if (Res.isInvalid())
         return true;
 
+      // If the resulting expression is new, then use it in place of the
+      // old expression in the template argument.
+      if (Res.get() != Arg.getArgument().getAsExpr()) {
+        TemplateArgument TA(Res.get());
+        Arg = TemplateArgumentLoc(TA, Res.get());
+      }
+
       Converted.push_back(Result);
       break;
     }
index bdd6d62fdda2447e643c9306a1303329157c7c85..9f4806f64c90e3db048ef05dd162ca7a4f1cba3b 100644 (file)
@@ -1247,6 +1247,20 @@ template <class T> using A7 = A<(T::num)>;
 // CHECK-ELIDE-NOTREE: type alias template redefinition with different types ('A<(T::num), (default) 0>' vs 'A<T::num, 1>')
 }
 
+namespace TemplateArgumentImplicitConversion {
+template <int X> struct condition {};
+
+struct is_const {
+    constexpr operator int() const { return 10; }
+};
+
+using T = condition<(is_const())>;
+void foo(const T &t) {
+  T &t2 = t;
+}
+// CHECK-ELIDE-NOTREE: binding of reference to type 'condition<[...]>' to a value of type 'const condition<[...]>' drops qualifiers
+}
+
 // CHECK-ELIDE-NOTREE: {{[0-9]*}} errors generated.
 // CHECK-NOELIDE-NOTREE: {{[0-9]*}} errors generated.
 // CHECK-ELIDE-TREE: {{[0-9]*}} errors generated.