]> granicus.if.org Git - clang/commitdiff
Fix a crasher in Template Diffing.
authorRichard Trieu <rtrieu@google.com>
Wed, 3 Apr 2013 02:11:36 +0000 (02:11 +0000)
committerRichard Trieu <rtrieu@google.com>
Wed, 3 Apr 2013 02:11:36 +0000 (02:11 +0000)
Value depenedent expressions for default arguments cannot be evaluated.
Instead, use the desugared template type to get an argument expression that
can be used.  This is needed for both integer and declaration arguements.

Also, move this common code into a separate function.

Patch by Olivier Goffart!

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

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

index b9c57ab2e9b43d057c8265c80fce1be9a7ef1311..419152de041b300023ef7b343b32ba124915af32 100644 (file)
@@ -913,47 +913,11 @@ class TemplateDiff {
                           ToIter.isEnd() && ToExpr);
           if ((FromExpr && FromExpr->getType()->isIntegerType()) ||
               (ToExpr && ToExpr->getType()->isIntegerType())) {
-            HasFromInt = FromExpr;
-            HasToInt = ToExpr;
-            if (FromExpr) {
-              // Getting the integer value from the expression.
-              // Default, value-depenedent expressions require fetching
-              // from the desugared TemplateArgument
-              if (FromIter.isEnd() && FromExpr->isValueDependent())
-                switch (FromIter.getDesugar().getKind()) {
-                  case TemplateArgument::Integral:
-                    FromInt = FromIter.getDesugar().getAsIntegral();
-                    break;
-                  case TemplateArgument::Expression:
-                    FromExpr = FromIter.getDesugar().getAsExpr();
-                    FromInt = FromExpr->EvaluateKnownConstInt(Context);
-                    break;
-                  default:
-                    assert(0 && "Unexpected template argument kind");
-                }
-              else
-                FromInt = FromExpr->EvaluateKnownConstInt(Context);
-            }
-            if (ToExpr) {
-              // Getting the integer value from the expression.
-              // Default, value-depenedent expressions require fetching
-              // from the desugared TemplateArgument
-              if (ToIter.isEnd() && ToExpr->isValueDependent())
-                switch (ToIter.getDesugar().getKind()) {
-                  case TemplateArgument::Integral:
-                    ToInt = ToIter.getDesugar().getAsIntegral();
-                    break;
-                  case TemplateArgument::Expression:
-                    ToExpr = ToIter.getDesugar().getAsExpr();
-                    ToInt = ToExpr->EvaluateKnownConstInt(Context);
-                    break;
-                  default:
-                    assert(0 && "Unexpected template argument kind");
-                }
-              else
-                ToInt = ToExpr->EvaluateKnownConstInt(Context);
-            }
-            Tree.SetNode(FromInt, ToInt, HasFromInt, HasToInt);
+            if (FromExpr)
+              FromInt = GetInt(FromIter, FromExpr);
+            if (ToExpr)
+              ToInt = GetInt(ToIter, ToExpr);
+            Tree.SetNode(FromInt, ToInt, FromExpr, ToExpr);
             Tree.SetSame(IsSameConvertedInt(ParamWidth, FromInt, ToInt));
             Tree.SetKind(DiffTree::Integer);
           } else {
@@ -962,11 +926,11 @@ class TemplateDiff {
           }
         } else if (HasFromInt || HasToInt) {
           if (!HasFromInt && FromExpr) {
-            FromInt = FromExpr->EvaluateKnownConstInt(Context);
+            FromInt = GetInt(FromIter, FromExpr);
             HasFromInt = true;
           }
           if (!HasToInt && ToExpr) {
-            ToInt = ToExpr->EvaluateKnownConstInt(Context);
+            ToInt = GetInt(ToIter, ToExpr);
             HasToInt = true;
           }
           Tree.SetNode(FromInt, ToInt, HasFromInt, HasToInt);
@@ -975,14 +939,10 @@ class TemplateDiff {
                           ToIter.isEnd() && HasToInt);
           Tree.SetKind(DiffTree::Integer);
         } else {
-          if (!HasFromValueDecl && FromExpr) {
-            DeclRefExpr *DRE = cast<DeclRefExpr>(FromExpr);
-            FromValueDecl = cast<ValueDecl>(DRE->getDecl());
-          }
-          if (!HasToValueDecl && ToExpr) {
-            DeclRefExpr *DRE = cast<DeclRefExpr>(ToExpr);
-            ToValueDecl = cast<ValueDecl>(DRE->getDecl());
-          }
+          if (!HasFromValueDecl && FromExpr)
+            FromValueDecl = GetValueDecl(FromIter, FromExpr);
+          if (!HasToValueDecl && ToExpr)
+            ToValueDecl = GetValueDecl(ToIter, ToExpr);
           Tree.SetNode(FromValueDecl, ToValueDecl);
           Tree.SetSame(FromValueDecl->getCanonicalDecl() ==
                        ToValueDecl->getCanonicalDecl());
@@ -1101,6 +1061,42 @@ class TemplateDiff {
         ArgExpr = SNTTPE->getReplacement();
   }
 
+  /// GetInt - Retrieves the template integer argument, including evaluating
+  /// default arguments.
+  llvm::APInt GetInt(const TSTiterator &Iter, Expr *ArgExpr) {
+    // Default, value-depenedent expressions require fetching
+    // from the desugared TemplateArgument
+    if (Iter.isEnd() && ArgExpr->isValueDependent())
+      switch (Iter.getDesugar().getKind()) {
+        case TemplateArgument::Integral:
+          return Iter.getDesugar().getAsIntegral();
+        case TemplateArgument::Expression:
+          ArgExpr = Iter.getDesugar().getAsExpr();
+          return ArgExpr->EvaluateKnownConstInt(Context);
+        default:
+          assert(0 && "Unexpected template argument kind");
+      }
+    return ArgExpr->EvaluateKnownConstInt(Context);
+  }
+
+  /// GetValueDecl - Retrieves the template integer argument, including
+  /// default expression argument.
+  ValueDecl *GetValueDecl(const TSTiterator &Iter, Expr *ArgExpr) {
+    // Default, value-depenedent expressions require fetching
+    // from the desugared TemplateArgument
+    if (Iter.isEnd() && ArgExpr->isValueDependent())
+      switch (Iter.getDesugar().getKind()) {
+        case TemplateArgument::Declaration:
+          return Iter.getDesugar().getAsDecl();
+        case TemplateArgument::Expression:
+          ArgExpr = Iter.getDesugar().getAsExpr();
+          return cast<DeclRefExpr>(ArgExpr)->getDecl();
+        default:
+          assert(0 && "Unexpected template argument kind");
+      }
+    return cast<DeclRefExpr>(ArgExpr)->getDecl();
+  }
+
   /// GetTemplateDecl - Retrieves the template template arguments, including
   /// default arguments.
   void GetTemplateDecl(const TSTiterator &Iter,
index 823bad2798ccdf75c938ff5690ac40e486be6045..fd331139a82ff2c58d453621c73dde53ef05b543 100644 (file)
@@ -903,6 +903,61 @@ namespace ValueDecl {
   }
 }
 
+namespace DependentDefault {
+  template <typename> struct Trait {
+    enum { V = 40 };
+    typedef int Ty;
+    static int I;
+  };
+  int other;
+
+  template <typename T, int = Trait<T>::V > struct A {};
+  template <typename T, typename = Trait<T>::Ty > struct B {};
+  template <typename T, int& = Trait<T>::I > struct C {};
+
+  void test() {
+
+    A<int> a1;
+    A<char> a2;
+    A<int, 10> a3;
+    a1 = a2;
+    // CHECK-ELIDE-NOTREE: no viable overloaded '='
+    // CHECK-ELIDE-NOTREE: no known conversion from 'A<char, [...]>' to 'A<int, [...]>'
+    a3 = a1;
+    // CHECK-ELIDE-NOTREE: no viable overloaded '='
+    // CHECK-ELIDE-NOTREE: no known conversion from 'A<[...], (default) 40>' to 'A<[...], 10>'
+    a2 = a3;
+    // CHECK-ELIDE-NOTREE: no viable overloaded '='
+    // CHECK-ELIDE-NOTREE: no known conversion from 'A<int, 10>' to 'A<char, 40>'
+
+    B<int> b1;
+    B<char> b2;
+    B<int, char> b3;
+    b1 = b2;
+    // CHECK-ELIDE-NOTREE: no viable overloaded '='
+    // CHECK-ELIDE-NOTREE: no known conversion from 'B<char, (default) Trait<T>::Ty>' to 'B<int, int>'
+    b3 = b1;
+    // CHECK-ELIDE-NOTREE: no viable overloaded '='
+    // CHECK-ELIDE-NOTREE: no known conversion from 'B<[...], (default) Trait<T>::Ty>' to 'B<[...], char>'
+    b2 = b3;
+    // CHECK-ELIDE-NOTREE: no viable overloaded '='
+    // CHECK-ELIDE-NOTREE: no known conversion from 'B<int, char>' to 'B<char, int>'
+
+    C<int> c1;
+    C<char> c2;
+    C<int, other> c3;
+    c1 = c2;
+    // CHECK-ELIDE-NOTREE: no viable overloaded '='
+    // CHECK-ELIDE-NOTREE: no known conversion from 'C<char, (default) I>' to 'C<int, I>'
+    c3 = c1;
+    // CHECK-ELIDE-NOTREE: no viable overloaded '='
+    // CHECK-ELIDE-NOTREE: no known conversion from 'C<[...], (default) I>' to 'C<[...], other>'
+    c2 = c3;
+    // CHECK-ELIDE-NOTREE: no viable overloaded '='
+    // CHECK-ELIDE-NOTREE: no known conversion from 'C<int, other>' to 'C<char, I>'
+  }
+}
+
 // CHECK-ELIDE-NOTREE: {{[0-9]*}} errors generated.
 // CHECK-NOELIDE-NOTREE: {{[0-9]*}} errors generated.
 // CHECK-ELIDE-TREE: {{[0-9]*}} errors generated.