forked from OSchip/llvm-project
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:
parent
1fd4365f91
commit
091872c5df
|
@ -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 << ']';
|
||||||
|
|
|
@ -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.
|
||||||
|
|
Loading…
Reference in New Issue