aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Trieu <rtrieu@google.com>2013-04-03 02:11:36 +0000
committerRichard Trieu <rtrieu@google.com>2013-04-03 02:11:36 +0000
commit625785d370f6c0d8262090b8a2abe3799f72d58d (patch)
tree2a4c561a0ce7e36199b2295da7c96f0e711c9871
parent54c63523ec002146328b69bdb912f64144b1f077 (diff)
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! git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@178609 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/AST/ASTDiagnostic.cpp98
-rw-r--r--test/Misc/diag-template-diffing.cpp55
2 files changed, 102 insertions, 51 deletions
diff --git a/lib/AST/ASTDiagnostic.cpp b/lib/AST/ASTDiagnostic.cpp
index b9c57ab2e9..419152de04 100644
--- a/lib/AST/ASTDiagnostic.cpp
+++ b/lib/AST/ASTDiagnostic.cpp
@@ -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,
diff --git a/test/Misc/diag-template-diffing.cpp b/test/Misc/diag-template-diffing.cpp
index 823bad2798..fd331139a8 100644
--- a/test/Misc/diag-template-diffing.cpp
+++ b/test/Misc/diag-template-diffing.cpp
@@ -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.