From 3fe1e09a6e285a4792224969b582ada1bd6747f8 Mon Sep 17 00:00:00 2001 From: Nikola Smiljanic Date: Tue, 1 Jul 2014 04:17:53 +0000 Subject: [PATCH] PR15677 - Crash in template diffing. Check that expression is evaluatable before evaluating it. llvm-svn: 212090 --- clang/lib/AST/ASTDiagnostic.cpp | 46 +++++++++++++++++++------------ clang/test/Misc/diag-template-diffing.cpp | 37 +++++++++++++++++++++++++ 2 files changed, 66 insertions(+), 17 deletions(-) diff --git a/clang/lib/AST/ASTDiagnostic.cpp b/clang/lib/AST/ASTDiagnostic.cpp index 6919ee2..2ee26fb 100644 --- a/clang/lib/AST/ASTDiagnostic.cpp +++ b/clang/lib/AST/ASTDiagnostic.cpp @@ -959,25 +959,27 @@ class TemplateDiff { ToIter.isEnd() && ToExpr); if (DefaultNTTPD->getType()->isIntegralOrEnumerationType()) { if (FromExpr) - FromInt = GetInt(FromIter, FromExpr); + HasFromInt = GetInt(FromIter, FromExpr, FromInt); if (ToExpr) - ToInt = GetInt(ToIter, ToExpr); - Tree.SetNode(FromInt, ToInt, FromExpr, ToExpr); + HasToInt = GetInt(ToIter, ToExpr, ToInt); + } + if (HasFromInt && HasToInt) { + Tree.SetNode(FromInt, ToInt, HasFromInt, HasToInt); Tree.SetSame(IsSameConvertedInt(ParamWidth, FromInt, ToInt)); Tree.SetKind(DiffTree::Integer); + } else if (HasFromInt || HasToInt) { + Tree.SetNode(FromInt, ToInt, HasFromInt, HasToInt); + Tree.SetSame(false); + Tree.SetKind(DiffTree::Integer); } else { Tree.SetSame(IsEqualExpr(Context, ParamWidth, FromExpr, ToExpr)); Tree.SetKind(DiffTree::Expression); } } else if (HasFromInt || HasToInt) { - if (!HasFromInt && FromExpr) { - FromInt = GetInt(FromIter, FromExpr); - HasFromInt = true; - } - if (!HasToInt && ToExpr) { - ToInt = GetInt(ToIter, ToExpr); - HasToInt = true; - } + if (!HasFromInt && FromExpr) + HasFromInt = GetInt(FromIter, FromExpr, FromInt); + if (!HasToInt && ToExpr) + HasToInt = GetInt(ToIter, ToExpr, ToInt); Tree.SetNode(FromInt, ToInt, HasFromInt, HasToInt); Tree.SetSame(IsSameConvertedInt(ParamWidth, FromInt, ToInt)); Tree.SetDefault(FromIter.isEnd() && HasFromInt, @@ -1121,20 +1123,28 @@ class TemplateDiff { /// GetInt - Retrieves the template integer argument, including evaluating /// default arguments. - llvm::APInt GetInt(const TSTiterator &Iter, Expr *ArgExpr) { + bool GetInt(const TSTiterator &Iter, Expr *ArgExpr, llvm::APInt &Int) { // Default, value-depenedent expressions require fetching - // from the desugared TemplateArgument - if (Iter.isEnd() && ArgExpr->isValueDependent()) + // from the desugared TemplateArgument, otherwise expression needs to + // be evaluatable. + if (Iter.isEnd() && ArgExpr->isValueDependent()) { switch (Iter.getDesugar().getKind()) { case TemplateArgument::Integral: - return Iter.getDesugar().getAsIntegral(); + Int = Iter.getDesugar().getAsIntegral(); + return true; case TemplateArgument::Expression: ArgExpr = Iter.getDesugar().getAsExpr(); - return ArgExpr->EvaluateKnownConstInt(Context); + Int = ArgExpr->EvaluateKnownConstInt(Context); + return true; default: llvm_unreachable("Unexpected template argument kind"); } - return ArgExpr->EvaluateKnownConstInt(Context); + } else if (ArgExpr->isEvaluatable(Context)) { + Int = ArgExpr->EvaluateKnownConstInt(Context); + return true; + } + + return false; } /// GetValueDecl - Retrieves the template Decl argument, including @@ -1517,6 +1527,8 @@ class TemplateDiff { Bold(); } OS << Val.toString(10); + } else if (E) { + PrintExpr(E); } else { OS << "(no argument)"; } diff --git a/clang/test/Misc/diag-template-diffing.cpp b/clang/test/Misc/diag-template-diffing.cpp index 4680707..c43ed26 100644 --- a/clang/test/Misc/diag-template-diffing.cpp +++ b/clang/test/Misc/diag-template-diffing.cpp @@ -1068,6 +1068,43 @@ void foo() { } } +namespace PR15677 { +template +struct A{}; + +template +using B = A; + +template +using B = A; +// CHECK-ELIDE-NOTREE: type alias template redefinition with different types ('A' vs 'A') + +template +struct C{}; + +template +using D = C; + +template +using D = C; +// CHECK-ELIDE-NOTREE: type alias template redefinition with different types ('C' vs 'C') + +template +using E = C; + +template +using E = C<42>; +// CHECK-ELIDE-NOTREE: type alias template redefinition with different types ('C<42>' vs 'C') + +template +using F = C; + +template +using F = C<21 + 21>; +// CHECK-ELIDE-NOTREE: type alias template redefinition with different types ('C<21 + 21 aka 42>' vs 'C') +} +} + // CHECK-ELIDE-NOTREE: {{[0-9]*}} errors generated. // CHECK-NOELIDE-NOTREE: {{[0-9]*}} errors generated. // CHECK-ELIDE-TREE: {{[0-9]*}} errors generated. -- 2.7.4