Fix crash on invalid in template type diffing.

This is a fix for PR15895, where Clang will crash when trying to print a
template diff and the template uses an address of operator.  This resulted
from expecting a DeclRefExpr when the Expr could have also been
UnaryOperator->DeclRefExpr.

llvm-svn: 181365
This commit is contained in:
Richard Trieu 2013-05-07 21:36:24 +00:00
parent 1fd4365f91
commit 091872c5df
2 changed files with 68 additions and 10 deletions

View File

@ -459,6 +459,10 @@ class TemplateDiff {
/// FromValueDecl, ToValueDecl - Whether the argument is a decl. /// FromValueDecl, ToValueDecl - Whether the argument is a decl.
ValueDecl *FromValueDecl, *ToValueDecl; ValueDecl *FromValueDecl, *ToValueDecl;
/// FromAddressOf, ToAddressOf - Whether the ValueDecl needs an address of
/// operator before it.
bool FromAddressOf, ToAddressOf;
/// FromDefault, ToDefault - Whether the argument is a default argument. /// FromDefault, ToDefault - Whether the argument is a default argument.
bool FromDefault, ToDefault; bool FromDefault, ToDefault;
@ -469,7 +473,8 @@ class TemplateDiff {
: Kind(Invalid), NextNode(0), ChildNode(0), ParentNode(ParentNode), : Kind(Invalid), NextNode(0), ChildNode(0), ParentNode(ParentNode),
FromType(), ToType(), FromExpr(0), ToExpr(0), FromTD(0), ToTD(0), FromType(), ToType(), FromExpr(0), ToExpr(0), FromTD(0), ToTD(0),
IsValidFromInt(false), IsValidToInt(false), FromValueDecl(0), IsValidFromInt(false), IsValidToInt(false), FromValueDecl(0),
ToValueDecl(0), FromDefault(false), ToDefault(false), Same(false) { } ToValueDecl(0), FromAddressOf(false), ToAddressOf(false),
FromDefault(false), ToDefault(false), Same(false) { }
}; };
/// FlatTree - A flattened tree used to store the DiffNodes. /// FlatTree - A flattened tree used to store the DiffNodes.
@ -526,9 +531,12 @@ class TemplateDiff {
} }
/// SetNode - Set FromValueDecl and ToValueDecl of the current node. /// SetNode - Set FromValueDecl and ToValueDecl of the current node.
void SetNode(ValueDecl *FromValueDecl, ValueDecl *ToValueDecl) { void SetNode(ValueDecl *FromValueDecl, ValueDecl *ToValueDecl,
bool FromAddressOf, bool ToAddressOf) {
FlatTree[CurrentNode].FromValueDecl = FromValueDecl; FlatTree[CurrentNode].FromValueDecl = FromValueDecl;
FlatTree[CurrentNode].ToValueDecl = ToValueDecl; FlatTree[CurrentNode].ToValueDecl = ToValueDecl;
FlatTree[CurrentNode].FromAddressOf = FromAddressOf;
FlatTree[CurrentNode].ToAddressOf = ToAddressOf;
} }
/// SetSame - Sets the same flag of the current node. /// SetSame - Sets the same flag of the current node.
@ -620,9 +628,12 @@ class TemplateDiff {
} }
/// GetNode - Gets the FromValueDecl and ToValueDecl. /// GetNode - Gets the FromValueDecl and ToValueDecl.
void GetNode(ValueDecl *&FromValueDecl, ValueDecl *&ToValueDecl) { void GetNode(ValueDecl *&FromValueDecl, ValueDecl *&ToValueDecl,
bool &FromAddressOf, bool &ToAddressOf) {
FromValueDecl = FlatTree[ReadNode].FromValueDecl; FromValueDecl = FlatTree[ReadNode].FromValueDecl;
ToValueDecl = FlatTree[ReadNode].ToValueDecl; ToValueDecl = FlatTree[ReadNode].ToValueDecl;
FromAddressOf = FlatTree[ReadNode].FromAddressOf;
ToAddressOf = FlatTree[ReadNode].ToAddressOf;
} }
/// NodeIsSame - Returns true the arguments are the same. /// NodeIsSame - Returns true the arguments are the same.
@ -942,7 +953,14 @@ class TemplateDiff {
FromValueDecl = GetValueDecl(FromIter, FromExpr); FromValueDecl = GetValueDecl(FromIter, FromExpr);
if (!HasToValueDecl && ToExpr) if (!HasToValueDecl && ToExpr)
ToValueDecl = GetValueDecl(ToIter, ToExpr); ToValueDecl = GetValueDecl(ToIter, ToExpr);
Tree.SetNode(FromValueDecl, ToValueDecl); QualType ArgumentType = DefaultNTTPD->getType();
bool FromAddressOf = FromValueDecl &&
!ArgumentType->isReferenceType() &&
!FromValueDecl->getType()->isArrayType();
bool ToAddressOf = ToValueDecl &&
!ArgumentType->isReferenceType() &&
!ToValueDecl->getType()->isArrayType();
Tree.SetNode(FromValueDecl, ToValueDecl, FromAddressOf, ToAddressOf);
Tree.SetSame(FromValueDecl && ToValueDecl && Tree.SetSame(FromValueDecl && ToValueDecl &&
FromValueDecl->getCanonicalDecl() == FromValueDecl->getCanonicalDecl() ==
ToValueDecl->getCanonicalDecl()); ToValueDecl->getCanonicalDecl());
@ -1080,7 +1098,7 @@ class TemplateDiff {
return ArgExpr->EvaluateKnownConstInt(Context); return ArgExpr->EvaluateKnownConstInt(Context);
} }
/// GetValueDecl - Retrieves the template integer argument, including /// GetValueDecl - Retrieves the template Decl argument, including
/// default expression argument. /// default expression argument.
ValueDecl *GetValueDecl(const TSTiterator &Iter, Expr *ArgExpr) { ValueDecl *GetValueDecl(const TSTiterator &Iter, Expr *ArgExpr) {
// Default, value-depenedent expressions require fetching // Default, value-depenedent expressions require fetching
@ -1095,7 +1113,12 @@ class TemplateDiff {
default: default:
assert(0 && "Unexpected template argument kind"); assert(0 && "Unexpected template argument kind");
} }
return cast<DeclRefExpr>(ArgExpr)->getDecl(); DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(ArgExpr);
if (!DRE) {
DRE = cast<DeclRefExpr>(cast<UnaryOperator>(ArgExpr)->getSubExpr());
}
return DRE->getDecl();
} }
/// GetTemplateDecl - Retrieves the template template arguments, including /// GetTemplateDecl - Retrieves the template template arguments, including
@ -1228,9 +1251,10 @@ class TemplateDiff {
} }
case DiffTree::Declaration: { case DiffTree::Declaration: {
ValueDecl *FromValueDecl, *ToValueDecl; ValueDecl *FromValueDecl, *ToValueDecl;
Tree.GetNode(FromValueDecl, ToValueDecl); bool FromAddressOf, ToAddressOf;
PrintValueDecl(FromValueDecl, ToValueDecl, Tree.FromDefault(), Tree.GetNode(FromValueDecl, ToValueDecl, FromAddressOf, ToAddressOf);
Tree.ToDefault(), Tree.NodeIsSame()); PrintValueDecl(FromValueDecl, ToValueDecl, FromAddressOf, ToAddressOf,
Tree.FromDefault(), Tree.ToDefault(), Tree.NodeIsSame());
return; return;
} }
case DiffTree::Template: { case DiffTree::Template: {
@ -1478,7 +1502,8 @@ class TemplateDiff {
/// PrintDecl - Handles printing of Decl arguments, highlighting /// PrintDecl - Handles printing of Decl arguments, highlighting
/// argument differences. /// argument differences.
void PrintValueDecl(ValueDecl *FromValueDecl, ValueDecl *ToValueDecl, void PrintValueDecl(ValueDecl *FromValueDecl, ValueDecl *ToValueDecl,
bool FromDefault, bool ToDefault, bool Same) { bool FromAddressOf, bool ToAddressOf, bool FromDefault,
bool ToDefault, bool Same) {
assert((FromValueDecl || ToValueDecl) && assert((FromValueDecl || ToValueDecl) &&
"Only one Decl argument may be NULL"); "Only one Decl argument may be NULL");
@ -1487,15 +1512,21 @@ class TemplateDiff {
} else if (!PrintTree) { } else if (!PrintTree) {
OS << (FromDefault ? "(default) " : ""); OS << (FromDefault ? "(default) " : "");
Bold(); Bold();
if (FromAddressOf)
OS << "&";
OS << (FromValueDecl ? FromValueDecl->getName() : "(no argument)"); OS << (FromValueDecl ? FromValueDecl->getName() : "(no argument)");
Unbold(); Unbold();
} else { } else {
OS << (FromDefault ? "[(default) " : "["); OS << (FromDefault ? "[(default) " : "[");
Bold(); Bold();
if (FromAddressOf)
OS << "&";
OS << (FromValueDecl ? FromValueDecl->getName() : "(no argument)"); OS << (FromValueDecl ? FromValueDecl->getName() : "(no argument)");
Unbold(); Unbold();
OS << " != " << (ToDefault ? "(default) " : ""); OS << " != " << (ToDefault ? "(default) " : "");
Bold(); Bold();
if (ToAddressOf)
OS << "&";
OS << (ToValueDecl ? ToValueDecl->getName() : "(no argument)"); OS << (ToValueDecl ? ToValueDecl->getName() : "(no argument)");
Unbold(); Unbold();
OS << ']'; OS << ']';

View File

@ -1002,6 +1002,33 @@ namespace VariadicDefault {
} }
} }
namespace PointerArguments {
template <int *p> class T {};
template <int* ...> class U {};
int a, b, c;
int z[5];
void test() {
T<&a> ta;
T<z> tz;
T<&b> tb(ta);
// CHECK-ELIDE-NOTREE: no matching constructor for initialization of 'T<&b>'
// CHECK-ELIDE-NOTREE: candidate constructor (the implicit copy constructor) not viable: no known conversion from 'T<&a>' to 'const T<&b>' for 1st argument
T<&c> tc(tz);
// CHECK-ELIDE-NOTREE: no matching constructor for initialization of 'T<&c>'
// CHECK-ELIDE-NOTREE: candidate constructor (the implicit copy constructor) not viable: no known conversion from 'T<z>' to 'const T<&c>' for 1st argument
U<&a, &a> uaa;
U<&b> ub(uaa);
// CHECK-ELIDE-NOTREE: no matching constructor for initialization of 'U<&b>'
// CHECK-ELIDE-NOTREE: candidate constructor (the implicit copy constructor) not viable: no known conversion from 'U<&a, &a>' to 'const U<&b, (no argument)>' for 1st argument
U<&b, &b, &b> ubbb(uaa);
// CHECK-ELIDE-NOTREE: no matching constructor for initialization of 'U<&b, &b, &b>'
// CHECK-ELIDE-NOTREE: candidate constructor (the implicit copy constructor) not viable: no known conversion from 'U<&a, &a, (no argument)>' to 'const U<&b, &b, &b>' for 1st argument
}
}
// CHECK-ELIDE-NOTREE: {{[0-9]*}} errors generated. // CHECK-ELIDE-NOTREE: {{[0-9]*}} errors generated.
// CHECK-NOELIDE-NOTREE: {{[0-9]*}} errors generated. // CHECK-NOELIDE-NOTREE: {{[0-9]*}} errors generated.
// CHECK-ELIDE-TREE: {{[0-9]*}} errors generated. // CHECK-ELIDE-TREE: {{[0-9]*}} errors generated.