r178609 - Fix a crasher in Template Diffing.

Richard Trieu rtrieu at google.com
Tue Apr 2 19:11:36 PDT 2013


Author: rtrieu
Date: Tue Apr  2 21:11:36 2013
New Revision: 178609

URL: http://llvm.org/viewvc/llvm-project?rev=178609&view=rev
Log:
Fix a crasher in Template Diffing.

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!

Modified:
    cfe/trunk/lib/AST/ASTDiagnostic.cpp
    cfe/trunk/test/Misc/diag-template-diffing.cpp

Modified: cfe/trunk/lib/AST/ASTDiagnostic.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTDiagnostic.cpp?rev=178609&r1=178608&r2=178609&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTDiagnostic.cpp (original)
+++ cfe/trunk/lib/AST/ASTDiagnostic.cpp Tue Apr  2 21:11:36 2013
@@ -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,

Modified: cfe/trunk/test/Misc/diag-template-diffing.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Misc/diag-template-diffing.cpp?rev=178609&r1=178608&r2=178609&view=diff
==============================================================================
--- cfe/trunk/test/Misc/diag-template-diffing.cpp (original)
+++ cfe/trunk/test/Misc/diag-template-diffing.cpp Tue Apr  2 21:11:36 2013
@@ -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.





More information about the cfe-commits mailing list