forked from OSchip/llvm-project
The type of a reference to a non-type template parameter pack should
not be a pack expansion type. Using a pack expansion type for a pack declaration makes sense, but general expressions should never have pack expansion types. If we have a pack `T *...V`, then the type of `V` is the type `T *`, which contains an unexpanded pack, and is a pointer type. This allows us to better diagnose issues where a template is invalid due to some non-dependent portion of a dependent type of a non-type template parameter pack.
This commit is contained in:
parent
9dda41e433
commit
c36b03e325
|
@ -944,6 +944,12 @@ public:
|
|||
/// from non-class types (in C++) or all types (in C).
|
||||
QualType getNonLValueExprType(const ASTContext &Context) const;
|
||||
|
||||
/// Remove an outer pack expansion type (if any) from this type. Used as part
|
||||
/// of converting the type of a declaration to the type of an expression that
|
||||
/// references that expression. It's meaningless for an expression to have a
|
||||
/// pack expansion type.
|
||||
QualType getNonPackExpansionType() const;
|
||||
|
||||
/// Return the specified type with any "sugar" removed from
|
||||
/// the type. This takes off typedefs, typeof's etc. If the outer level of
|
||||
/// the type is already concrete, it returns it unmodified. This is similar
|
||||
|
|
|
@ -4724,7 +4724,7 @@ TemplateArgument ASTContext::getInjectedTemplateArg(NamedDecl *Param) {
|
|||
} else if (auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(Param)) {
|
||||
Expr *E = new (*this) DeclRefExpr(
|
||||
*this, NTTP, /*enclosing*/ false,
|
||||
NTTP->getType().getNonLValueExprType(*this),
|
||||
NTTP->getType().getNonPackExpansionType().getNonLValueExprType(*this),
|
||||
Expr::getValueKindForType(NTTP->getType()), NTTP->getLocation());
|
||||
|
||||
if (NTTP->isParameterPack())
|
||||
|
|
|
@ -3049,6 +3049,13 @@ StringRef BuiltinType::getName(const PrintingPolicy &Policy) const {
|
|||
llvm_unreachable("Invalid builtin type.");
|
||||
}
|
||||
|
||||
QualType QualType::getNonPackExpansionType() const {
|
||||
// We never wrap type sugar around a PackExpansionType.
|
||||
if (auto *PET = dyn_cast<PackExpansionType>(getTypePtr()))
|
||||
return PET->getPattern();
|
||||
return *this;
|
||||
}
|
||||
|
||||
QualType QualType::getNonLValueExprType(const ASTContext &Context) const {
|
||||
if (const auto *RefType = getTypePtr()->getAs<ReferenceType>())
|
||||
return RefType->getPointeeType();
|
||||
|
|
|
@ -3151,6 +3151,11 @@ ExprResult Sema::BuildDeclarationNameExpr(
|
|||
return ExprError();
|
||||
ExprValueKind valueKind = VK_RValue;
|
||||
|
||||
// In 'T ...V;', the type of the declaration 'V' is 'T...', but the type of
|
||||
// a reference to 'V' is simply (unexpanded) 'T'. The type, like the value,
|
||||
// is expanded by some outer '...' in the context of the use.
|
||||
type = type.getNonPackExpansionType();
|
||||
|
||||
switch (D->getKind()) {
|
||||
// Ignore all the non-ValueDecl kinds.
|
||||
#define ABSTRACT_DECL(kind)
|
||||
|
|
|
@ -5042,7 +5042,7 @@ void TestNonADLCall3() {
|
|||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: },
|
||||
// CHECK-NEXT: "type": {
|
||||
// CHECK-NEXT: "qualType": "Ts..."
|
||||
// CHECK-NEXT: "qualType": "Ts"
|
||||
// CHECK-NEXT: },
|
||||
// CHECK-NEXT: "valueCategory": "lvalue",
|
||||
// CHECK-NEXT: "referencedDecl": {
|
||||
|
@ -6622,7 +6622,7 @@ void TestNonADLCall3() {
|
|||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: },
|
||||
// CHECK-NEXT: "type": {
|
||||
// CHECK-NEXT: "qualType": "Ts..."
|
||||
// CHECK-NEXT: "qualType": "Ts"
|
||||
// CHECK-NEXT: },
|
||||
// CHECK-NEXT: "valueCategory": "lvalue",
|
||||
// CHECK-NEXT: "referencedDecl": {
|
||||
|
@ -7603,7 +7603,7 @@ void TestNonADLCall3() {
|
|||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: },
|
||||
// CHECK-NEXT: "type": {
|
||||
// CHECK-NEXT: "qualType": "Ts..."
|
||||
// CHECK-NEXT: "qualType": "Ts"
|
||||
// CHECK-NEXT: },
|
||||
// CHECK-NEXT: "valueCategory": "lvalue",
|
||||
// CHECK-NEXT: "referencedDecl": {
|
||||
|
@ -7656,7 +7656,7 @@ void TestNonADLCall3() {
|
|||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: },
|
||||
// CHECK-NEXT: "type": {
|
||||
// CHECK-NEXT: "qualType": "Ts..."
|
||||
// CHECK-NEXT: "qualType": "Ts"
|
||||
// CHECK-NEXT: },
|
||||
// CHECK-NEXT: "valueCategory": "lvalue",
|
||||
// CHECK-NEXT: "referencedDecl": {
|
||||
|
@ -7707,7 +7707,7 @@ void TestNonADLCall3() {
|
|||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: },
|
||||
// CHECK-NEXT: "type": {
|
||||
// CHECK-NEXT: "qualType": "Ts..."
|
||||
// CHECK-NEXT: "qualType": "Ts"
|
||||
// CHECK-NEXT: },
|
||||
// CHECK-NEXT: "valueCategory": "lvalue",
|
||||
// CHECK-NEXT: "referencedDecl": {
|
||||
|
|
|
@ -327,7 +327,7 @@ void PrimaryExpressions(Ts... a) {
|
|||
// CHECK-NEXT: CompoundStmt
|
||||
// CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <col:4> col:4 implicit 'Ts...'
|
||||
// CHECK-NEXT: ParenListExpr 0x{{[^ ]*}} <col:4> 'NULL TYPE'
|
||||
// CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:4> 'Ts...' lvalue ParmVar 0x{{[^ ]*}} 'a' 'Ts...'
|
||||
// CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:4> 'Ts' lvalue ParmVar 0x{{[^ ]*}} 'a' 'Ts...'
|
||||
// CHECK-NEXT: CompoundStmt 0x{{[^ ]*}} <col:9, col:10>
|
||||
|
||||
[=]{};
|
||||
|
@ -440,7 +440,7 @@ void PrimaryExpressions(Ts... a) {
|
|||
// CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <col:4> col:4 implicit 'Ts...'
|
||||
// CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <col:10> col:10 implicit 'int':'int'
|
||||
// CHECK-NEXT: ParenListExpr 0x{{[^ ]*}} <col:4> 'NULL TYPE'
|
||||
// CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:4> 'Ts...' lvalue ParmVar 0x{{[^ ]*}} 'a' 'Ts...'
|
||||
// CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:4> 'Ts' lvalue ParmVar 0x{{[^ ]*}} 'a' 'Ts...'
|
||||
// CHECK-NEXT: IntegerLiteral 0x{{[^ ]*}} <col:14> 'int' 12
|
||||
// CHECK-NEXT: CompoundStmt 0x{{[^ ]*}} <col:17, col:18>
|
||||
|
||||
|
@ -514,17 +514,17 @@ void PrimaryExpressions(Ts... a) {
|
|||
|
||||
(a + ...);
|
||||
// CHECK: CXXFoldExpr 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:11> '<dependent type>'
|
||||
// CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:4> 'Ts...' lvalue ParmVar 0x{{[^ ]*}} 'a' 'Ts...'
|
||||
// CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:4> 'Ts' lvalue ParmVar 0x{{[^ ]*}} 'a' 'Ts...'
|
||||
// CHECK-NEXT: <<<NULL>>>
|
||||
|
||||
(... + a);
|
||||
// CHECK: CXXFoldExpr 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:11> '<dependent type>'
|
||||
// CHECK-NEXT: <<<NULL>>>
|
||||
// CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:10> 'Ts...' lvalue ParmVar 0x{{[^ ]*}} 'a' 'Ts...'
|
||||
// CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:10> 'Ts' lvalue ParmVar 0x{{[^ ]*}} 'a' 'Ts...'
|
||||
|
||||
(a + ... + b);
|
||||
// CHECK: CXXFoldExpr 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:15> '<dependent type>'
|
||||
// CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:4> 'Ts...' lvalue ParmVar 0x{{[^ ]*}} 'a' 'Ts...'
|
||||
// CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:4> 'Ts' lvalue ParmVar 0x{{[^ ]*}} 'a' 'Ts...'
|
||||
// CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:14> 'int' lvalue Var 0x{{[^ ]*}} 'b' 'int'
|
||||
}
|
||||
|
||||
|
|
|
@ -3,9 +3,10 @@
|
|||
// CHECK: PackExpansionExpr
|
||||
// CHECK-SAME: '<dependent type>'
|
||||
// CHECK-NEXT: DeclRefExpr
|
||||
// CHECK-SAME: 'T...'
|
||||
// CHECK-SAME: 'T'
|
||||
// CHECK-SAME: ParmVar
|
||||
// CHECK-SAME: 'a'
|
||||
// CHECK-SAME: 'T...'
|
||||
|
||||
void expr() {
|
||||
f();
|
||||
|
|
|
@ -506,3 +506,11 @@ namespace complete_array_from_incomplete {
|
|||
extern const char *const kStrs[3] = {};
|
||||
Derived<T, kStrs> d;
|
||||
}
|
||||
|
||||
namespace type_of_pack {
|
||||
template<typename ...T> struct A { // expected-warning 0-1{{extension}}
|
||||
template<T *...V> void f() {
|
||||
g(V.f() ...); // expected-error {{base type 'T *' is not a structure or union}}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue