From: Richard Trieu Date: Wed, 3 Apr 2013 02:11:36 +0000 (+0000) Subject: Fix a crasher in Template Diffing. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=625785d370f6c0d8262090b8a2abe3799f72d58d;p=clang 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 --- 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(FromExpr); - FromValueDecl = cast(DRE->getDecl()); - } - if (!HasToValueDecl && ToExpr) { - DeclRefExpr *DRE = cast(ToExpr); - ToValueDecl = cast(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(ArgExpr)->getDecl(); + default: + assert(0 && "Unexpected template argument kind"); + } + return cast(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 struct Trait { + enum { V = 40 }; + typedef int Ty; + static int I; + }; + int other; + + template ::V > struct A {}; + template ::Ty > struct B {}; + template ::I > struct C {}; + + void test() { + + A a1; + A a2; + A a3; + a1 = a2; + // CHECK-ELIDE-NOTREE: no viable overloaded '=' + // CHECK-ELIDE-NOTREE: no known conversion from 'A' to 'A' + 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' to 'A' + + B b1; + B b2; + B b3; + b1 = b2; + // CHECK-ELIDE-NOTREE: no viable overloaded '=' + // CHECK-ELIDE-NOTREE: no known conversion from 'B::Ty>' to 'B' + b3 = b1; + // CHECK-ELIDE-NOTREE: no viable overloaded '=' + // CHECK-ELIDE-NOTREE: no known conversion from 'B<[...], (default) Trait::Ty>' to 'B<[...], char>' + b2 = b3; + // CHECK-ELIDE-NOTREE: no viable overloaded '=' + // CHECK-ELIDE-NOTREE: no known conversion from 'B' to 'B' + + C c1; + C c2; + C c3; + c1 = c2; + // CHECK-ELIDE-NOTREE: no viable overloaded '=' + // CHECK-ELIDE-NOTREE: no known conversion from 'C' to 'C' + 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' to 'C' + } +} + // CHECK-ELIDE-NOTREE: {{[0-9]*}} errors generated. // CHECK-NOELIDE-NOTREE: {{[0-9]*}} errors generated. // CHECK-ELIDE-TREE: {{[0-9]*}} errors generated.