return false;
}
-bool Sema::AttachTypeConstraint(AutoTypeLoc TL, NonTypeTemplateParmDecl *NTTP,
+bool Sema::AttachTypeConstraint(AutoTypeLoc TL,
+ NonTypeTemplateParmDecl *NewConstrainedParm,
+ NonTypeTemplateParmDecl *OrigConstrainedParm,
SourceLocation EllipsisLoc) {
- if (NTTP->getType() != TL.getType() ||
+ if (NewConstrainedParm->getType() != TL.getType() ||
TL.getAutoKeyword() != AutoTypeKeyword::Auto) {
- Diag(NTTP->getTypeSourceInfo()->getTypeLoc().getBeginLoc(),
+ Diag(NewConstrainedParm->getTypeSourceInfo()->getTypeLoc().getBeginLoc(),
diag::err_unsupported_placeholder_constraint)
- << NTTP->getTypeSourceInfo()->getTypeLoc().getSourceRange();
+ << NewConstrainedParm->getTypeSourceInfo()
+ ->getTypeLoc()
+ .getSourceRange();
return true;
}
// FIXME: Concepts: This should be the type of the placeholder, but this is
// unclear in the wording right now.
DeclRefExpr *Ref =
- BuildDeclRefExpr(NTTP, NTTP->getType(), VK_PRValue, NTTP->getLocation());
+ BuildDeclRefExpr(OrigConstrainedParm, OrigConstrainedParm->getType(),
+ VK_PRValue, OrigConstrainedParm->getLocation());
if (!Ref)
return true;
ExprResult ImmediatelyDeclaredConstraint = formImmediatelyDeclaredConstraint(
*this, TL.getNestedNameSpecifierLoc(), TL.getConceptNameInfo(),
TL.getNamedConcept(), TL.getLAngleLoc(), TL.getRAngleLoc(),
- BuildDecltypeType(Ref), NTTP->getLocation(),
+ BuildDecltypeType(Ref), OrigConstrainedParm->getLocation(),
[&](TemplateArgumentListInfo &ConstraintArgs) {
for (unsigned I = 0, C = TL.getNumArgs(); I != C; ++I)
ConstraintArgs.addArgument(TL.getArgLoc(I));
},
EllipsisLoc);
if (ImmediatelyDeclaredConstraint.isInvalid() ||
- !ImmediatelyDeclaredConstraint.isUsable())
+ !ImmediatelyDeclaredConstraint.isUsable())
return true;
- NTTP->setPlaceholderTypeConstraint(ImmediatelyDeclaredConstraint.get());
+ NewConstrainedParm->setPlaceholderTypeConstraint(
+ ImmediatelyDeclaredConstraint.get());
return false;
}
if (AutoTypeLoc TL = TInfo->getTypeLoc().getContainedAutoTypeLoc())
if (TL.isConstrained())
- if (AttachTypeConstraint(TL, Param, D.getEllipsisLoc()))
+ if (AttachTypeConstraint(TL, Param, Param, D.getEllipsisLoc()))
Invalid = true;
if (Invalid)
return b;
}
} // namespace GH48182
+
+namespace GH61777 {
+template<class T> concept C = sizeof(T) == 4; // #61777_C
+template<class T, class U> concept C2 = sizeof(T) == sizeof(U); //#61777_C2
+
+template<class T>
+struct Parent {
+ template<class, C auto> struct TakesUnary { static const int i = 0 ; }; // #UNARY
+ template<class, C2<T> auto> struct TakesBinary { static const int i = 0 ; }; //#BINARY
+};
+
+static_assert(Parent<void>::TakesUnary<int, 0>::i == 0);
+// expected-error@+3{{constraints not satisfied for class template 'TakesUnary'}}
+// expected-note@#UNARY{{because 'decltype(0ULL)' (aka 'unsigned long long') does not satisfy 'C'}}
+// expected-note@#61777_C{{because 'sizeof(unsigned long long) == 4' (8 == 4) evaluated to false}}
+static_assert(Parent<void>::TakesUnary<int, 0uLL>::i == 0);
+
+static_assert(Parent<int>::TakesBinary<int, 0>::i == 0);
+// expected-error@+3{{constraints not satisfied for class template 'TakesBinary'}}
+// expected-note@#BINARY{{because 'C2<decltype(0ULL), int>' evaluated to false}}
+// expected-note@#61777_C2{{because 'sizeof(unsigned long long) == sizeof(int)' (8 == 4) evaluated to false}}
+static_assert(Parent<int>::TakesBinary<int, 0ULL>::i == 0);
+}
+