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.
|
||||
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.
|
||||
bool FromDefault, ToDefault;
|
||||
|
||||
|
@ -469,7 +473,8 @@ class TemplateDiff {
|
|||
: Kind(Invalid), NextNode(0), ChildNode(0), ParentNode(ParentNode),
|
||||
FromType(), ToType(), FromExpr(0), ToExpr(0), FromTD(0), ToTD(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.
|
||||
|
@ -526,9 +531,12 @@ class TemplateDiff {
|
|||
}
|
||||
|
||||
/// 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].ToValueDecl = ToValueDecl;
|
||||
FlatTree[CurrentNode].FromAddressOf = FromAddressOf;
|
||||
FlatTree[CurrentNode].ToAddressOf = ToAddressOf;
|
||||
}
|
||||
|
||||
/// SetSame - Sets the same flag of the current node.
|
||||
|
@ -620,9 +628,12 @@ class TemplateDiff {
|
|||
}
|
||||
|
||||
/// 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;
|
||||
ToValueDecl = FlatTree[ReadNode].ToValueDecl;
|
||||
FromAddressOf = FlatTree[ReadNode].FromAddressOf;
|
||||
ToAddressOf = FlatTree[ReadNode].ToAddressOf;
|
||||
}
|
||||
|
||||
/// NodeIsSame - Returns true the arguments are the same.
|
||||
|
@ -942,7 +953,14 @@ class TemplateDiff {
|
|||
FromValueDecl = GetValueDecl(FromIter, FromExpr);
|
||||
if (!HasToValueDecl && 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 &&
|
||||
FromValueDecl->getCanonicalDecl() ==
|
||||
ToValueDecl->getCanonicalDecl());
|
||||
|
@ -1080,7 +1098,7 @@ class TemplateDiff {
|
|||
return ArgExpr->EvaluateKnownConstInt(Context);
|
||||
}
|
||||
|
||||
/// GetValueDecl - Retrieves the template integer argument, including
|
||||
/// GetValueDecl - Retrieves the template Decl argument, including
|
||||
/// default expression argument.
|
||||
ValueDecl *GetValueDecl(const TSTiterator &Iter, Expr *ArgExpr) {
|
||||
// Default, value-depenedent expressions require fetching
|
||||
|
@ -1095,7 +1113,12 @@ class TemplateDiff {
|
|||
default:
|
||||
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
|
||||
|
@ -1228,9 +1251,10 @@ class TemplateDiff {
|
|||
}
|
||||
case DiffTree::Declaration: {
|
||||
ValueDecl *FromValueDecl, *ToValueDecl;
|
||||
Tree.GetNode(FromValueDecl, ToValueDecl);
|
||||
PrintValueDecl(FromValueDecl, ToValueDecl, Tree.FromDefault(),
|
||||
Tree.ToDefault(), Tree.NodeIsSame());
|
||||
bool FromAddressOf, ToAddressOf;
|
||||
Tree.GetNode(FromValueDecl, ToValueDecl, FromAddressOf, ToAddressOf);
|
||||
PrintValueDecl(FromValueDecl, ToValueDecl, FromAddressOf, ToAddressOf,
|
||||
Tree.FromDefault(), Tree.ToDefault(), Tree.NodeIsSame());
|
||||
return;
|
||||
}
|
||||
case DiffTree::Template: {
|
||||
|
@ -1478,7 +1502,8 @@ class TemplateDiff {
|
|||
/// PrintDecl - Handles printing of Decl arguments, highlighting
|
||||
/// argument differences.
|
||||
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) &&
|
||||
"Only one Decl argument may be NULL");
|
||||
|
||||
|
@ -1487,15 +1512,21 @@ class TemplateDiff {
|
|||
} else if (!PrintTree) {
|
||||
OS << (FromDefault ? "(default) " : "");
|
||||
Bold();
|
||||
if (FromAddressOf)
|
||||
OS << "&";
|
||||
OS << (FromValueDecl ? FromValueDecl->getName() : "(no argument)");
|
||||
Unbold();
|
||||
} else {
|
||||
OS << (FromDefault ? "[(default) " : "[");
|
||||
Bold();
|
||||
if (FromAddressOf)
|
||||
OS << "&";
|
||||
OS << (FromValueDecl ? FromValueDecl->getName() : "(no argument)");
|
||||
Unbold();
|
||||
OS << " != " << (ToDefault ? "(default) " : "");
|
||||
Bold();
|
||||
if (ToAddressOf)
|
||||
OS << "&";
|
||||
OS << (ToValueDecl ? ToValueDecl->getName() : "(no argument)");
|
||||
Unbold();
|
||||
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-NOELIDE-NOTREE: {{[0-9]*}} errors generated.
|
||||
// CHECK-ELIDE-TREE: {{[0-9]*}} errors generated.
|
||||
|
|
Loading…
Reference in New Issue